文章目录
- 1.原理
- 2.去除彩色图像噪声
- 3.去除视频(短序列)噪声
1.原理
- 在图像平滑小节介绍了很多算法,如高斯模糊、中值模糊等,它们在一定程度上可以很好地去除少量的噪声。在这些技术中,我们在像素周围取一个小的邻域,并做了一些操作,如高斯加权平均、值的中值等来替换中心元素。简而言之,像素的噪声去除是其邻近区域的局部。
- 噪声有一个性质。我们认为噪声是平均值为一的随机变量。考虑一个带噪声的像素点,,其中 为像素的真实值, 为这个像素的噪声。我们可以从不同图片中选取大量的相同像素(N)然后计算平均值。理想情况下我们会得到。因为噪声的平均值为0。
- 我们需要一组相似的图片,通过取平均值的方法可以去除噪音。下图中的蓝色窗口看起来是相似的。绿色窗口看起来也是相似的。所以我们可以 选取包含目标像素的一个小窗口,然后在图像中搜索相似的窗口,最后求取所有窗口的平均值,并用这个值取代目标像素的值。 这种方法就是非局部平均值去噪。与我们以前学习的平滑技术相比这种算法要消耗更多的时间,但是结果很好。
- 对于彩色图像,要先转换到CIELAB 颜色空间,然后对L 和AB 成分分别去噪。
- OpenCV 提供了这种技术的四个变本:
- cv2.fastNlMeansDenoising() #使用对象为灰度图。
- cv2.fastNlMeansDenoisingColored() #使用对象为彩色图。
- cv2.fastNlMeansDenoisingMulti() #适用于短时间的图像序列(灰度图像)
- cv2.fastNlMeansDenoisingColoredMulti() #适用于短时间的图像序列(彩色图像)
这些函数的共同参数有:
- h : 决定过滤器强度。h 值高可以很好的去除噪声,但也会把图像的细节抹去。(取10 的效果不错)
- hForColorComponents : 与h 相同,但使用于彩色图像。(与h 相同)
- templateWindowSize : 奇数。(推荐值为7)
- searchWindowSize : 奇数。(推荐值为21)
2.去除彩色图像噪声
输入图像中含有方差为25 的噪声。
def denoise_color(self):
img = cv2.cvtColor(self.img, code=cv2.COLOR_BGR2RGB)
dst = cv2.fastNlMeansDenoisingColored(img, None, 10, 10, 7, 21)
plt.subplot(121), plt.imshow(img)
plt.subplot(122), plt.imshow(dst)
plt.show()
3.去除视频(短序列)噪声
def denoise_video(self):
cap = cv2.VideoCapture('../images/vtest.avi')
img = [cap.read()[1] for i in range(5)]# 创建一个前5帧的list
gray = [cv2.cvtColor(i, cv2.COLOR_BGR2GRAY) for i in img]# 全部转为灰度图
gray = [np.float64(i) for i in gray]# 全部转为float64类型
noise = np.random.randn(*gray[1].shape) * 10#创建一个方差为25的噪声
noisy = [i + noise for i in gray]#向所有图像添加噪声
noisy = [np.uint8(np.clip(i, 0, 255)) for i in noisy]#转为uint8类型
# 根据这5帧图像,对第三帧去噪
dst = cv2.fastNlMeansDenoisingMulti(noisy, 2, 5, None, 4, 7, 35)
titles = ['3rd frame', '3rd frame+noise','3rd denoise']
imgs = [gray[2], noisy[2],dst]
for i in range(3):
plt.subplot(1, 3, i + 1), plt.imshow(imgs[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
以上是放大后的局部图像。