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)```