3.4. 平滑图像

3.4.1. 目标

学会:
-使用各种低通滤波器模糊图像-对图像应用自定义滤波器(二维卷积)

3.4.2. 二维卷积(图像滤波)

对于一维信号,图像也可以用各种低通滤波器(LPF)、高通滤波器(HPF)等进行滤波。LPF有助于去除噪声或模糊图像。HPF过滤器有助于在图像中找到边缘。

OpenCV提供了一个函数, cv2.过滤器2D() ,用图像卷积内核。作为一个例子,我们将尝试对图像进行平均滤波。5x5平均滤波器内核定义如下:

\[开始{aligned}K=frac{1}{25}begin{bmatrix}1&1&1&1&1'1&1&1&1&1&1'1&1&1&1&1&1&1'1&1&1'1&1&1&1&1{bmatrix}end{aligned}\]

使用上述内核进行过滤的结果如下:对于每个像素,5x5窗口以该像素为中心,将该窗口内的所有像素相加,然后将结果除以25。这相当于计算窗口内像素值的平均值。对图像中的所有像素执行此操作,以生成输出滤波图像。请尝试此代码并检查结果:

>>> import cv2
>>> import numpy as np
>>> from matplotlib import pyplot as plt
>>>
>>> # img = cv2.imread('opencv_logo.png')
>>>
>>> img = cv2.imread('/cvdata/opencv_logo.jpg')
>>>
>>> kernel = np.ones((5,5),np.float32)/25
>>> dst = cv2.filter2D(img,-1,kernel)
>>>
>>> plt.subplot(121),plt.imshow(img),plt.title('Original')
>>> plt.xticks([]), plt.yticks([])
>>> plt.subplot(122),plt.imshow(dst),plt.title('Averaging')
>>> plt.xticks([]), plt.yticks([])
>>> plt.show()
../_images/sec04-filtering_1_0.png

结果:

3.4.3. 图像模糊(图像平滑)

图像模糊是通过卷积图像与低通滤波核来实现的。它对消除噪音很有用。它实际上会从图像中移除高频内容(例如:噪声、边缘),从而在应用此is filter时导致边缘模糊。(嗯,有些模糊技术不会模糊边缘)。OpenCV主要提供四种模糊技术。

一。平均值

这是通过卷积图像与一个规范化的盒子过滤器。它只需要取内核区域下所有像素的平均值,并用该平均值替换中心元素。这是由函数完成的 cv2.模糊()cv2.boxFilter() . 查看文档以了解有关内核的更多详细信息。我们应该指定内核的宽度和高度。一个3x3规格化的盒式过滤器如下所示:

\[开始{aligned}K=frac{1}{9}begin{bmatrix}1&1&1\1&1&1\1&1&1&1end{bmatrix}end{aligned}\]

注意

如果不想使用规范化的框过滤器,请使用 cv2.boxFilter() 通过辩论 normalize=False 到函数。

使用5x5大小的内核查看下面的示例演示:

>>> import cv2
>>> import numpy as np
>>> from matplotlib import pyplot as plt
>>>
>>> # img = cv2.imread('opencv_logo.png')
>>>
>>> img = cv2.imread('/cvdata/opencv_logo.jpg')
>>>
>>> blur = cv2.blur(img,(5,5))
>>>
>>> plt.subplot(121),plt.imshow(img),plt.title('Original')
>>> plt.xticks([]), plt.yticks([])
>>> plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
>>> plt.xticks([]), plt.yticks([])
>>> plt.show()
../_images/sec04-filtering_3_0.png

结果:

2。高斯滤波

在这种方法中,使用高斯核代替由等滤波器系数组成的盒滤波器。它完成了功能, 高斯蓝() . 我们应该指定内核的宽度和高度,它应该是正数和奇数。我们还应该分别指定X和Y方向的标准偏差sigmaX和sigmaY。如果只指定了sigmaX,则sigmaX等于sigmaX。如果两者都是零,则从内核大小计算它们。高斯滤波在去除图像中的高斯噪声方面是非常有效的。

如果你愿意,你可以用这个函数创建一个高斯核, cv2.getGaussianKernel() .

上面的代码可以修改为高斯模糊:

>>> blur = cv2.GaussianBlur(img,(5,5),0)
>>> plt.subplot(121),plt.imshow(img),plt.title('Original')
>>> plt.xticks([]), plt.yticks([])
>>> plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
>>> plt.xticks([]), plt.yticks([])
>>> plt.show()
../_images/sec04-filtering_6_0.png

结果:

三。中值滤波

这里,函数 中音模糊() 计算内核窗口下所有像素的中值,并用该中值替换中心像素。这是非常有效的去除盐和胡椒噪音。值得注意的一点是,在高斯和box滤波器中,中心元素的滤波值可以是原始图像中可能不存在的值。然而,在中值滤波中情况并非如此,因为中心元素总是被图像中的某个像素值所代替。这有效地降低了噪音。内核大小必须是正奇数整数。

在这个演示中,我们将50%的噪声添加到原始图像中,并使用中值滤波器。检查结果:

>>> blur = cv2.medianBlur(img,5)
>>>
>>>
>>> plt.subplot(121),plt.imshow(img),plt.title('Original')
>>> plt.xticks([]), plt.yticks([])
>>> plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
>>> plt.xticks([]), plt.yticks([])
>>> plt.show()
../_images/sec04-filtering_10_0.png

结果:

四。双边滤波

正如我们所注意到的,我们前面介绍的过滤器倾向于模糊边缘。双边滤波器不是这样的, cv2.双边滤波器() ,它是为定义的,并且在保留边缘的情况下非常有效地去除噪声。但与其他过滤器相比,操作速度较慢。我们已经看到,高斯滤波器取像素周围的a邻域,并求出其高斯加权平均值。这种高斯滤波器是一个单独的空间函数,也就是说,在滤波时要考虑附近的像素。它不考虑像素是否具有几乎相同的强度值,也不考虑像素是否位于边上。其结果是高斯滤波器倾向于模糊边缘,这是不可取的。

双边滤波器在空间域中也使用高斯滤波器,但它也使用一个以上(乘法)高斯滤波器分量,该分量是像素强度差的函数。空间的高斯函数确保只考虑像素是“空间邻域”进行滤波,而应用在强度域中的高斯分量(强度差的高斯函数)确保仅包括那些强度与中心像素类似的像素(“强度邻域”)来计算模糊的强度值。因此,该方法保留边缘,因为对于位于边缘附近的像素,放置在边缘另一侧的相邻像素(因此与中心像素相比显示出较大的强度变化)将不包括在模糊中。

下面的示例演示了双边过滤的使用(有关参数的详细信息,请参阅OpenCV文档)。

>>> blur = cv2.bilateralFilter(img,9,75,75)
>>> plt.subplot(121),plt.imshow(img),plt.title('Original')
>>> plt.xticks([]), plt.yticks([])
>>> plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
>>> plt.xticks([]), plt.yticks([])
>>> plt.show()
../_images/sec04-filtering_13_0.png

结果:

请注意,表面上的纹理已消失,但边缘仍保留。

3.4.4. 额外资源

  1. 有关的详细信息 bilateral filtering can be found at

3.4.5. 练习

取一幅图像,加入高斯噪声和椒盐噪声,当你改变噪声水平时,比较通过box、高斯、中值和双边滤波器对这两幅噪声图像的模糊效果。