图像去噪 OpenCV-Python v4.7.0

目标

在本章中

理论

在前面的章节中,我们已经看到了许多图像平滑技术,如高斯模糊(Gaussian Blurring)、中值模糊(Median Blurring)等,它们在一定程度上可以很好地去除少量噪声。在这些技术中,我们选取像素周围的一个小邻域,然后进行一些操作,如高斯加权平均、数值中值等来替换中心元素。简而言之,像素的噪点去除是在其邻域内进行的。

噪声有一个特性。噪音通常被认为是一个均值为零的随机变量。考虑一个噪声像素, p = p 0 + n p=p_0+n p=p0+n
其中 p0 是像素的真实值,n 是该像素的噪声。您可以从不同的图像中提取大量相同的像素(例如 N),然后计算它们的平均值。理想情况下,您应该得到 p=p0,因为噪声的平均值为零。

您可以通过一个简单的设置来验证这一点。将一个静态摄像头对准某个位置几秒钟。这样就可以获得大量的帧,或者同一场景的大量图像。然后编写一段代码,找出视频中所有帧的平均值(这对你来说应该太简单了)。比较最终结果和第一帧图像。您可以看到噪点的减少。遗憾的是,这种简单的方法对摄像机和场景运动的影响不大。此外,通常情况下只有一张噪点图像可用。

因此,我们需要一组相似的图像来平均噪点。在图像中考虑一个小窗口(比如 5x5 窗口)。在图像的其他地方也有可能出现相同的斑块。有时就在它周围的一个小范围内。把这些相似的斑块放在一起,找出它们的平均值如何?对于该特定窗口来说,这样就可以了。请看下面的示例图像:

在这里插入图片描述
图片中的蓝色斑块看起来很相似。绿色斑块看起来相似。因此,我们取一个像素点,在其周围开一个小窗口,搜索图像中的相似窗口,求出所有窗口的平均值,然后用得到的结果替换像素点。这种方法就是非局部均值去噪。与我们之前看到的模糊技术相比,它需要更多时间,但效果非常好。更多详细信息和在线演示,请参见附加资源中的第一个链接。

对于彩色图像,先将图像转换为 CIELAB 色彩空间,然后分别对 L 和 AB 部分进行去噪。

OpenCV 中的图像去噪

OpenCV 提供了该技术的四种变体。

  1. cv.fastNlMeansDenoising() - 适用于单个灰度图像
  2. cv.fastNlMeansDenoisingColored() - 处理彩色图像。
  3. cv.fastNlMeansDenoisingMulti() - 处理短时间内捕获的图像序列(灰度图像)
  4. cv.fastNlMeansDenoisingColoredMulti()- 与上述方法相同,但用于彩色图像。

常用参数有

  • h:决定滤波强度的参数。h 值越大,去除噪点的效果越好,但也会去除图像的细节。(10也可以)
  • hForColorComponents:与 h 相同,但只适用于彩色图像。(通常与 h 相同)
  • templateWindowSize:应为奇数(建议为 7)
  • searchWindowSize : 应该是奇数。
    有关这些参数的详细信息,请访问附加资源中的第一个链接。

我们将在此演示 2 和 3。其余部分留给您。

1. cv.fastNlMeansDenoisingColored()

如上所述,它用于去除彩色图像中的噪声。(噪声预计是高斯噪声)。请看下面的示例:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('die.png')
dst = cv.fastNlMeansDenoisingColored(img,None,10,10,7,21)
plt.subplot(121),plt.imshow(img)
plt.subplot(122),plt.imshow(dst)
plt.show()

以下是放大后的结果。我的输入图像具有 σ=25 的高斯噪声。请看结果:
在这里插入图片描述

2. cv.fastNlMeansDenoisingMulti()

现在我们将对视频应用相同的方法。第一个参数是imgToDenoiseIndex。第二个参数 imgToDenoiseIndex 指定我们需要去噪的帧,为此我们要传递输入列表中帧的索引。第三个参数是 temporalWindowSize,指定用于去噪的附近帧数。它应该是奇数。在这种情况下,将使用总的 temporalWindowSize 帧数,其中中心帧就是要去噪的帧。例如,您输入了一个包含 5 幅图像的列表。让 imgToDenoiseIndex = 2 和 temporalWindowSize = 3。那么帧-1、帧-2 和帧-3 将用于对帧-2 进行去噪处理。让我们来看一个例子。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
cap = cv.VideoCapture('vtest.avi')
# 创建前 5 帧的列表
img = [cap.read()[1] for i in range(5)] # 将所有图像转换为灰度图像。
# 将所有画面转换为灰度
gray = [cv.cvtColor(i, cv.COLOR_BGR2GRAY) for i in img] # 将所有图像转换为 float64 格式。
# 将所有图像转换为 float64
gray = [np.float64(i) for i in gray] # 创建方差为 25 的噪声。
# 创建方差为 25 的噪声
noise = np.random.randn(*gray[1].shape)*10
# 将此噪声添加到图像中
noisy = [i+noise for i in gray] # 转换回 uint8 文件格式。
# 转换回 uint8
noisy = [np.uint8(np.clip(i,0,255)) for i in noisy] # 对第三帧图像进行去噪处理。
# 考虑到所有 5 幅图像,对第 3 幅图像进行去噪处理
dst = cv.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()

下图是我们得到的结果的放大版:
在这里插入图片描述
这需要大量的计算时间。结果中,第一幅图像为原始图像,第二幅为噪声图像,第三幅为去噪图像。

其他资源

  1. http://www.ipol.im/pub/art/2011/bcm_nlm/ (提供详细信息和在线演示等。强烈建议访问。我们的测试图像就是从这个链接生成的)
  2. coursera 的在线课程(第一张图片取自此处)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值