美文网首页
OpenCV-Python教程:56.图像去噪

OpenCV-Python教程:56.图像去噪

作者: xxxss | 来源:发表于2017-06-30 11:52 被阅读5806次

    理论

    在早先的章节里,我们看到很多图像平滑技术如高斯模糊,Median模糊等,它们在移除数量小的噪音时在某种程度上比较好用。在这些技术里,我们取像素周围的一小部分邻居,做一些类似于高斯平均权重,中值等替换掉中间的元素。简单说,移除一个像素的噪音是基于本地邻居的。

    噪音有一个属性,噪音一般被认为是具有零平均值的随机变量。假设一个像素噪音,p = p0 + n, 其中p0是像素的真实值,n是那个像素的噪音。你可以从不同图像取大量的同一个像素(N)并计算他们的平均值,理想情况下,你应该得到p=p0,因为均值是0.

    你可以自己通过一个简单例子验证一下。保持一个静止的摄像机对准一个位置多呆几秒,这会给你很多帧,或者是对一个场景的很多图像。然后写一些代码来找到视频里所有帧的平均值。比较最终的结果和第一帧。你可以看到噪点被去掉了。不幸的是这个简单的方法对于摄像机和场景的运动来说就不健壮了。而且经常你也只有一个噪音图像可用。

    所以思路很简单,我们需要一套类似的图像来平均去掉噪点,假设图像上一个小窗口(比如5x5的窗口)。很有可能在图像里的某处还有一个相同的块。有时候是在它附近的邻居。用这样类似的块来做他们的平均会怎么样呢?对于这个特定的窗口,看下面的例子:

    图像里蓝色的块看上去一样,绿色块看上去也类似,所以我们取一个像素,取它周围的一个小窗口,找到图像里和它类似的窗口,平均所有的窗口,然后用结果来替换掉这个像素。这哥方法就是非局部均值去噪。它要比其他我们之前介绍过的模糊技术要花更多时间。但是结果要更好。

    对于彩色图像,图像先要转换成CIELAB颜色空间然后再分成L去噪和AB部分。

    OpenCV里的图像去噪

    OpenCV提供了这个技术的四个变形:

    1.cv2.fastNlMeansDenoising() - 对于一个灰度图像的

    2.cv2.fastNlMeansDenoisingColored() - 对于彩色图像的

    3.cv2.fastNlMeansDenoisingMulti() - 对于短时间内拍摄的一序列图像的(灰度图像)

    4.cv2.fastNlMeansDenoisingColoredMulti() - 和上面一眼个,不过是彩色图像。

    通用参数如下:

    ·h: 决定过滤器强度的参数。更高的h值能够更好去噪,但是会去掉更多图像细节(10就ok)

    ·hForColorComponents: 和h一样,不过只是针对彩色图像的(一般和h一样)

    ·templateWindowSize:应该是奇数(推荐7)

    ·searchWindowSize:应该是奇数(推荐21)

    我们会演示几个例子。

    1.cv2.fastNlMeansDenoisingColored()

    上面说过这事去除彩色图像噪点的(噪点应该是符合高斯分布的)

    import numpy as np
    import cv2
    from matplotlib import pyplot as plt

    img = cv2.imread('die.png')

    dst = cv2.fastNlMeansDenoisingColored(img,None,10,10,7,21)

    plt.subplot(121),plt.imshow(img)
    plt.subplot(122),plt.imshow(dst)
    plt.show()

    下面是一个放大的结果。我的输入图像是一个σ=25的高斯噪点

    2. cv2.fastNlMeansDenoisingMulti()

    现在我们把方法应用到视频上,第一个参数是带噪点的帧的列表。第二个参数imgToDenoiseIndex 指定我们需要降哪一帧的噪,应该写输入列表里的帧的索引。第三个参数temporalWindowSize指定多少个周围的帧用来去噪。应该是奇数。这种情况下,temporalWindowSize数量的帧被用来去噪,其中中间帧是要去噪的。比如你传入了5帧的列表作为输入,imgToDenoiseIndex = 2, temporalWindowSize = 3.那么帧1,帧2, 帧3倍用来给帧2去噪,看下面的例子:

    import numpy as np
    import cv2
    from matplotlib import pyplot as plt

    cap = cv2.VideoCapture('vtest.avi')

    # create a list of first 5 frames
    img = [cap.read()[1] for i in xrange(5)]

    # convert all to grayscale
    gray = [cv2.cvtColor(i, cv2.COLOR_BGR2GRAY) for i in img]

    # convert all to float64
    gray = [np.float64(i) for i in gray]

    # create a noise of variance 25
    noise = np.random.randn(*gray[1].shape)*10

    # Add this noise to images
    noisy = [i+noise for i in gray]

    # Convert back to uint8
    noisy = [np.uint8(np.clip(i,0,255)) for i in noisy]

    # Denoise 3rd frame considering all the 5 frames
    dst = cv2.fastNlMeansDenoisingMulti(noisy, 2, 5, None, 4, 7, 35)

    plt.subplot(131),plt.imshow(gray[2],'gray')
    plt.subplot(132),plt.imshow(noisy[2],'gray')
    plt.subplot(133),plt.imshow(dst,'gray')
    plt.show()

    它会花掉很多时间计算,上面的结果里,第一张图是原始帧,第二张图是噪点图,第三章是去噪的。

    相关文章

      网友评论

          本文标题:OpenCV-Python教程:56.图像去噪

          本文链接:https://www.haomeiwen.com/subject/ussssttx.html