Skip to content

use_noparm

复制本地路径 | 在线编辑

原始文件为 .py 代码,本文是转换后的 Markdown 文件。

```.py
'''
使用一种非参数的方法,其实就是类似 NLM 去噪的方法,去找最近似的块
参考文章:https://zhuanlan.zhihu.com/p/68430344
'''
import os
import cv2
import numpy as np

template_patch: 以要处理的像素为中心的 patch

sample_image: 整个已知的图像

weights: 权重矩阵,用于计算 SSD

相当于遍历像素,看看哪个模块和 template_patch 最相似,但需要考虑 template_patch 有些像素是未知的

def find_matches(template_patch, sample_image, weights):
winsize = template_patch.shape[0]

# 计算 SSD
min_ssd = np.inf
min_i, min_j = 0, 0
for i in range(sample_image.shape[0] - winsize):
    for j in range(sample_image.shape[1] - winsize):
        now_ssd = np.sum(weights * (template_patch - sample_image[i:i+winsize, j:j+winsize])**2)
        if now_ssd < min_ssd:
            min_ssd = now_ssd
            min_i, min_j = i, j

# 返回中心点
return min_i + winsize//2, min_j + winsize//2

texture = cv2.imread('./data/texture.png', -1)
texture = texture[200:200+40, 200:200+40]
texture = cv2.cvtColor(texture, cv2.COLOR_BGR2GRAY)

os.makedirs('./result/use_noparm', exist_ok=True)
cv2.imwrite('./result/use_noparm/texture.png', texture)

nowimg = np.copy(texture)

winradius = 5

初始化一个块的权重矩阵,初始用二维高斯 kernel

之后遍历的时候,会把未知像素的权重设为 0

weights = cv2.getGaussianKernel(2*winradius+1, 0)
weights = np.dot(weights, weights.T)
weights = weights / np.sum(weights)

开始合成纹理,每次向外拓展一层

for layer in range(101):
print(f'layer {layer}')

rows, cols = nowimg.shape[0:2]
result = np.zeros((rows+2, cols+2), np.uint8)
result[1:rows+1, 1:cols+1] = nowimg

mask = np.zeros((rows+2, cols+2), bool)
mask[0, :] = mask[:, 0] = mask[:, -1] = mask[-1, :] = True

for i in range(0, rows+2):
    for j in range(0, cols+2):
        if mask[i, j]:
            # 以 i, j 为中心,patch 的半径为 winradius
            now_patch = np.zeros((2*winradius+1, 2*winradius+1), np.uint8)
            # 对应的权重矩阵,初始化是用二维高斯核
            now_weights = np.copy(weights)

            for x in range(-winradius, winradius+1):
                for y in range(-winradius, winradius+1):
                    if i+x < 1 or i+x > rows or j+y < 1 or j+y > cols:
                        now_patch[x+winradius, y+winradius] = 0
                        now_weights[x+winradius, y+winradius] = 0
                    else:
                        now_patch[x+winradius, y+winradius] = result[i+x, j+y]

            min_i, min_j = find_matches(now_patch, texture, now_weights)
            result[i, j] = texture[min_i, min_j]

nowimg = np.copy(result)
if layer % 10 == 0:
    cv2.imwrite(f'./result/use_noparm/result_{layer}.png', nowimg)```

Comments