Image Processing in OpenCV (2)

4 Smoothing Images

4.1 目标

学习:

  • 使用各种低通滤波器(low pass filters)模糊(Blur)图像
  • 对图像使用自定义滤波器(2D convolutin)

4.2 2D卷积(图像滤波)(Image Filtering)

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

OpenCV提供了一个函数cv2.filter2D(),用于将内核与图像进行卷积。例如,我们将尝试对图像使用平均滤波器。 5x5平均滤波器内核可以定义如下:

\[ K = \frac{1}{25} \left[ \begin{matrix} 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 \end{matrix} \tag{3} \right]\]

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

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

%matplotlib inline 

img = cv2.imread("opencv_logo.png")

kernel = np.ones((5, 5), np.float32)/25
dst = cv2.filter2D(img, -1, kernel)

plt.rcParams['figure.figsize'] = (9, 6)
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()

4.3 图像模糊(图像平滑)Image Blurring(Image Smoothing)

通过将图像与低通滤波器内核卷积来实现图像模糊。它有助于消除噪音。它实际上从图像中去除了高频内容(例如:噪声,边缘),导致边缘在应用滤波器时模糊。 (嗯,有模糊技术不会模糊边缘)。 OpenCV主要提供四种模糊技术。

4.3.1 平均(Averaging)

这是通过将图像与标准化的箱式滤波器进行卷积来完成的。它采用内核区域下所有像素的平均值,并用这个平均值替换中心元素。这是由函数cv2.blur()或cv2.boxFilter()完成的。查看文档以获取有关内核的更多详细信息。我们应该指定内核的宽度和高度。 3x3标准化的箱式滤波器看起来像这样:

\[ K = \frac{1}{9} \left[ \begin{matrix} 1 & 1 &1 \\ 1 & 1 &1 \\ 1 & 1 &1 \end{matrix} \right] \]

注意:
如果你不想使用标准箱式滤波器,使用cv.bowFilter()时将参数normalize=False传递给函数。

检查下面的5x5内核的例子演示:

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

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

blur = cv2.blur(img, (5, 5))

plt.rcParams['figure.figsize'] = (9, 6)
plt.subplot(121), plt.imshow(img), plt.title("Original")
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(dst), plt.title("Blurred")
plt.xticks([]), plt.yticks([])

plt.show()

4.3.2 高斯滤波(Gaussian Filtering)

在该方法中,使用高斯核代替由相等滤波器系数组成的箱式滤波器。它是通过函数cv2.GaussianBlur()完成的。我们应该指定内核的宽度和高度,它们应该是正数和奇数。我们还应该分别指定X和Y方向的标准差,sigmaX和sigmaY。如果仅指定了sigmaX,则sigmaY等于sigmaX。如果两者都为零,则根据内核大小计算它们。高斯滤波在从图像中去除高斯噪声方面非常有效。

如果需要,可以使用函数cv2.getGaussianKernel()创建高斯内核。

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

blur = cv2.GaussianBlur(img, (5, 5), 0)

4.3.3 中值滤波(Median Filtering)

这里,函数cv2.medianBlur()计算内核窗口下所有像素的中值,并用该中值替换中心像素。这在去除椒盐噪音(salt-and-pepper noise)方面非常有效。值得注意的一件事是,在高斯和箱式滤波器中,中心元素的滤波值可以是原始图像中可能不存在的值。然而,在中值滤波中不是这种情况,因为中心元素总是被图像中的某个像素值替换。这有效地降低了噪音。内核大小必须是正奇数。

在此演示中,我们在原始图像中添加了50%的噪点并使用中值滤波器。检查结果:

median = cv2.medianBlur(img, 5)

4.3.4 双边滤波(Bilateral Filtering)

正如我们所指出的,我们之前介绍的滤镜往往会模糊边界。双边滤波器cv2.bilateralFilter()不会这样,并且在保留边界时非常有效地去除噪声。但与其滤波器相比,操作速度较慢。我们已经看到高斯滤波器采用像素周围的邻域并找到其高斯加权平均值。该高斯滤波器仅是空间的函数,即在滤波时考虑附近的像素。它不考虑像素是否具有几乎相同的强度值,并且不考虑像素是否位于边缘上。产生的效果是高斯滤波器趋于模糊边缘,这不是所希望的。

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

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

blur = cv2.bilateralFilter(img, 9, 75, 75)

注意表面的纹理(texture)已经模糊掉了,但是边界仍然保留。

4.4 附加资源

双边滤波

猜你喜欢

转载自www.cnblogs.com/shaocf/p/9418421.html