上面计算图像导数的方法存在缺陷:在该方法中,滤波器的尺度需要随着图像分辨率的变化而变化(?)。为了在图像噪声方面更稳健,以及在任意尺度上计算导数,我们可以使用高斯导数滤波器:
\[
I_x = I * G_{\sigma x} 和 I_y = I*G_{\sigma y}
\]
其中,\(G_{\sigma x}\) 和\(G_{\sigma y}\)表示\(G_\sigma\) 在 \(x\) 和 \(y\) 方向上的导数,\(G_\sigma\) 表示标准差为 \(\sigma\) 的高斯函数。以下给出使用样例:
结果演示:
在对图像进行处理时,去噪也是很重要的一环。图像去噪是在去除图像噪声的同时,尽可能地保留图像细节和结构地处理技术,以下给出使用ROF去噪模型地Demo:
from PIL import Image import matplotlib.pyplot as plt import numpy as np from scipy.ndimage import filters def de_noise(img, U_init, tolerance=0.1, tau=0.125, tv_weight=100): U = U_init Px = Py = img error = 1 while error > tolerance: Uold = U # 变量U梯度的x分量 gradUx = np.roll(U, -1, axis=1)-U # 变量U梯度的y分量 gradUy = np.roll(U, -1, axis=0)-U # 更新对偶变量 PxNew = Px + (tau/tv_weight)*gradUx PyNew = Py + (tau/tv_weight)*gradUy NormNew = np.maximum(1, np.sqrt(PxNew**2+PyNew**2)) # 更新x,y分量 Px = PxNew / NormNew Py = PyNew / NormNew # 更新原始变量 RxPx = np.roll(Px, 1, axis=1) # 将x分量向x轴正方向平移 RyPy = np.roll(Py, 1, axis=0) # 将y分量向y轴正方向平移 DivP = (Px - RxPx) + (Py - RyPy) # 对偶域散度 U = img + tv_weight * DivP error = np.linalg.norm(U - Uold)/np.sqrt(img.shape[0] * img.shape[1]) return U, img-U if __name__ == '__main__': im = np.zeros((500, 500)) im[100:400,100:400] = 128 im[200:300, 200:300] = 255 im = im + 30 * np.random.standard_normal((500, 500)) U, T = de_noise(im, im) G = filters.gaussian_filter(im, 10) plt.figure() plt.gray() plt.subplot(221).set_title("Original image") plt.axis('off') plt.imshow(im) plt.subplot(222).set_title("Gauss blurred image") plt.axis('off') plt.imshow(G) plt.subplot(223).set_title("ROF") plt.axis('off') plt.imshow(U) plt.savefig('tmp.jpg') plt.show()结果演示
ROF去噪后的图像保留了边缘和图像的结构信息,同时模糊了“噪声”。
np.roll()函数可以循环滚动元素,np.linalg.norm()用于衡量两个数组间的差异。
之后有空将补充图像去噪
参考书籍
Python计算机视觉