opencv计算摄影学之图像去噪

1.原理

  • 在图像平滑小节介绍了很多算法,如高斯模糊、中值模糊等,它们在一定程度上可以很好地去除少量的噪声。在这些技术中,我们在像素周围取一个小的邻域,并做了一些操作,如高斯加权平均、值的中值等来替换中心元素。简而言之,像素的噪声去除是其邻近区域的局部。
  • 噪声有一个性质。我们认为噪声是平均值为一的随机变量。考虑一个带噪声的像素点, p = p 0 + n p = p_0 + n ,其中 p 0 p_0 为像素的真实值, n n 为这个像素的噪声。我们可以从不同图片中选取大量的相同像素(N)然后计算平均值。理想情况下我们会得到 p = p 0 p = p_0 。因为噪声的平均值为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()

在这里插入图片描述
以上是放大后的局部图像。

发布了154 篇原创文章 · 获赞 45 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_36622009/article/details/104786091