3-4 图像平滑—OpenCV-Python教程翻译

目标

  • 使用多种低通滤波器(low pass filters)模糊图像
  • 学会使用自定义滤波器(2维卷积)

2D卷积(图像滤波)

和一维信号相似,图像可以使用多种低通滤波器(LPF)或者高通滤波器(HPF)等进行滤波处理。LPF可以除去噪声,模糊图像等,HPF则可以找到图像中的边缘。

OpenCV提供了一个函数cv2.filter2D()实现图像和一个卷积核进行卷积运算。下面我们将对一副图像进行均值滤波。其中,5×5阶的均值滤波卷积核如下所示:

 具体操作如下:对每一个像素进行卷积操作,每一个像素都是周围25个像素值的均值。下面的代码将展示进行均值滤波的结果:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('image\\lena.bmp')
kernel = np.ones((5,5),np.float32)/25
dst = cv.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()

 结果如图所示:经过平均滤波后左边的图像变得模糊

 图像模糊(图像平滑)

图像模糊是通过对一副图像使用低通滤波器进行卷积处理实现的,这样的操作有助于去除噪声。通常,从图像中去除了高频部分(比如噪音或者边缘等)。因此,通过这个操作边缘会变得模糊。(当然,也有技术可以实现不模糊边缘)。OpenCV主要提供了4中模糊技术。

1、平均滤波

这一步是使用一个归一化块滤波器对图像进行卷积处理。这里只是简单的计算卷积核对应区域的像素值的平均值,用于取代中心像素值,可以使用函数cv2.blur()或者cv2.boxFilter()。关于卷积核更详细的内容可以去查看帮助手册。我们使用这些函数的时候只需要指定卷积核的宽度和高度。一个3×3的卷积核如下所示,

 注意:如果你不想使用一个归一化块过滤器,可以使用函数cv2.boxFilter(),将参数normalize=False传递给函数即可。

下面的代码演示了使用一个5×5的卷积核对图像进行处理。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('opencv-logo-white.png')
blur = cv.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()

结果如下,可以看出右边的图像字母边缘的毛刺都被除去了,但是图像边缘也变得模糊了。

2、高斯滤波

在这里,使用高斯卷积核代替方框卷积核,可以使用函数cv2.GaussianBlur( src, ksize, sigmax[, dst[, sigmaY[, borderType]]] )。我们需要指定卷积核的宽和高,宽和高必须是正值和奇数。同样我们可以指定在X和Y方向的标准差和方差。如果只指定sigmaX,那么sigmaY会和sigmaX一样。如果两个都指定为0,将通过卷积核尺寸计算他们。高斯滤波可以有效地去除图像中的高斯噪音。

在OpenCV中,可以使用函数cv2.getGaussianKernel()创建自己定义的高斯卷积核。

上面的代码可以修改进行滤波处理的代码为高斯滤波

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

 

3、中值滤波

中值滤波就是让临近的像素按照大小排列,取排序像素集中位于中间位置的值作为中值滤波后的像素值。中值滤波可以很好的去除图像中的椒盐噪声。值得注意的一点,在上面滤波处理中,中间位置的像素值都是被重新计算的,可能是图像中的一个值也可能是新的值。但是对于中值滤波,中间位置的像素值始终是图像中的一些像素值,因此这样可以降低噪音的影响。其中,卷积核和尺寸必须是一个正的奇数。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('image\\lenaNoise.png',cv.IMREAD_GRAYSCALE)
kernel = np.ones((5,5),np.float32)/25
median = cv.medianBlur(img,5)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(median),plt.title('median')
plt.xticks([]), plt.yticks([])
plt.show()

结果如下所示,可以看到原始图像中的椒盐噪音都被除去了。

 4、双边滤波

函数cv2.bilaterlFilter()可以高效地去除图像中的噪声,同时保持边缘的形状。但是相对于其他的滤波处理,双边滤波的速度要慢很多。我们已经了解了高斯滤波是计算周围像素的高斯加权平均值,因此,高斯滤波只是空间的函数,在滤波处理的时候只考虑周围像素值,并不会在意像素值是否具有相同的强度,或者是否是边缘像素。因此,高斯滤波对边缘进行滤波处理,获得了我们并不想要的结果。

双边滤波也在空间内进行高斯滤波,但是会多进行一次高斯滤波,这次高斯滤波会考虑像素梯度。空间的高斯函数会考虑周围区域的像素进行滤波处理,强度梯度的高斯函数会考虑与中间位置像素有相同强度的像素进行滤波处理。这样在滤波处理的时候就能保留边缘,因为在边缘区域的像素值会急剧变化。

下面的代码展示如何使用双边滤波(详细的参数信息请查看帮助文档)

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

结果如图所示,可以看到微小的细节被过滤,但是边缘被很好的保留下来。

 参考文献

Details about the bilateral filtering

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值