⚠️这个系列是自己瞎翻的,文法很丑,主要靠意会,跳着跳着捡重要的部分翻,翻错了不负责,就这样哈。
⚠️基于3.4.3,Smoothing Images,附原文。
目标
学会:
- 使用各种低通滤波器模糊图像
- 将定制过滤器应用于图像(2D卷积)
2D卷积(图像过滤)
和一维信号一样,图像也可以使用各种低通滤波器(LPF),高通滤波器(HPF)等进行滤波。LPF有助于消除噪声,模糊图像等等。HPF滤波器有助于找到图片(中形象)的边缘。
OpenCV 提供了方法,cv.filter2D() 来把图像和内核做卷积。好像示例一样,我们会尝试对图像进行滤波。一个 5x5 平均内核看起来如下:
具体操作是像这样的:保持这个内核在一个像素点上,把这个内核覆盖到的所有的25个像素加在一起,计算出他们的平均值,并且用这个平均值替换掉中心点的像素值。它为图像中的每个像素点重复这个操作。尝试这段代码,查看结果:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('opencv_logo.png')
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 提供了provides 主要有四种模糊技术。
1、平均
这种模糊是通过把图像与标准化的盒式滤波器做卷积达成的。它简单的获取所有在内核区域之下的所有像素点的平均值来替代中心元素(的值)。这是由方法 cv.blur() 或者 cv.boxFilter() 来完成的。 查看文档,了解关于内核的更多细节。我们需要指定内核的宽度和高度,一个 3x3 标准化的盒式滤波器看起来应该是下面这样的:
提示
如果你不想使用标准化的盒式滤波器,用 cv.boxFilter() 。对该方法传入一个参数 normalize=False 。
查看以下使用 5x5 大小内核的简单示例:
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、高斯模糊
在这种模糊中,使用高斯内核代替盒式滤波器。它通过方法 cv.GaussianBlur() 来完成。我们需要指定内核的宽度和高度,它们必须为正奇数。我们还需要分别的指定 X 和 Y 方向的标准差, sigmaX 和 sigmaY 。如果只有 sigmaX 被指定了,sigmaY 就被当做是和 sigmaX 一样。如果他俩都被指定为0,它们会按照内核大小来计算。高斯模糊在除去图像中的高斯噪声是非常有效的。
如果你想要的话,你可以通过 cv.getGaussianKernel() 方法创建高斯内核。
之前的代码可以被修改为高斯模糊:
blur = cv.GaussianBlur(img,(5,5),0)
结果:
3、中值模糊
这种模糊里,函数 cv.medianBlur() 取所有内核区域之下的所有像素的中值来替代中心元素。这对图像中的椒盐噪声非常有效。有趣的事情是,在上面那些滤波器里,中心元素的值都是重新算出来的,也就是说这里有可能是会算出一个图像中从未出现过的新数值。但中值模糊,中心元素总是会被某个图像中的像素值替代。它降低了噪音的影响,它的内核应该是一个正的奇数。
在这个示例中,我添加了 50% 的噪音到我们的原图上,然后应用了中值模糊,看看这结果:
median = cv.medianBlur(img,5)
结果:
4、双边滤波器
cv.bilateralFilter() 这个方法在消除噪声的同事保持边缘清晰的时候非常有效。但这个操作比起其他的滤波器来更慢。我们已经看到高斯滤波器采用像素周围的邻域并找到其高斯加权平均值。这个高斯滤波器仅仅是一个针对区域的方法,就是说,周围的像素点在过滤的时候都被考虑进去了。它没有考虑这些像素点是否有相同的亮度,没有考虑这个像素点是否是一个边缘。因此它把边缘也给模糊了,这不是我们想要的结果。
双边滤波器也在区域中采用高斯滤波器的方案,但还引入了一个计算像素(强度)差的函数。区域中的高斯函数确保仅(过滤器)考虑附近的像素用于模糊,而这个计算像素强度差的高斯函数,确保只有那些与中心像素相似的强度的像素参与于模糊。因此它保留了边缘,因为边缘处的像素将具有较大的强度变化。
以下示例显示双边滤波器的使用(想知道参数的细节,请查看文档)。
blur = cv.bilateralFilter(img,9,75,75)
结果:
看,表面上的纹路消失了,但边缘依然被保留。
额外资源
- 关于双边滤波器的细节
- 译者附:大家还可以了解下高斯噪声和椒盐噪声的区别