目标
• 学习使用不同的低通滤波器对图像进行模糊
• 使用自定义的滤波器对图像进行卷积(2D 卷积)
结构化元素
- 在前面的例子中我们使用 Numpy 构建了结构化元素,它是正方形的。但有时我们需要构建一个椭圆形/圆形的核。为了实现这种要求,提供了 OpenCV函数 cv2.getStructuringElement()。你只需要告诉他你需要的核的形状和大小。
图像卷积
- 与以为信号一样,我们也可以对 2D 图像实施低通滤波(LPF),高通滤波(HPF)等。LPF 帮助我们去除噪音,模糊图像。HPF 帮助我们找到图像的边缘
- OpenCV 提供的函数 cv.filter2D() 可以让我们对一幅图像进行卷积操
作。下面我们将对一幅图像使用平均滤波器
dst = cv.filter2D(src,ddepth,kernel)
- ddepth:输入图像的数据类型(深度).如果您使用-1,结果(目标)图像将具有与输入(源)图像相同的深度。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('./Pytorch.png')
kernel = np.ones((5,5),np.float_)/25
dst = cv2.filter2D(img,-1,kernel)
plt.subplot(121)
plt.imshow(img)
plt.title('Original')
plt.axis('off')
plt.subplot(122)
plt.imshow(dst)
plt.title('Averaging')
plt.axis('off')
plt.show()
图像模糊(图像平滑)
使用低通滤波器可以达到图像模糊的目的。这对与去除噪音很有帮助。其
实就是去除图像中的高频成分(比如:噪音,边界)。所以边界也会被模糊
点。(当然,也有一些模糊技术不会模糊掉边界)。OpenCV 提供了四种模糊技术。
平均
可以使用函数 cv2.blur() 和 cv2.boxFilter() 来完这个任务。blur 函数执行平均的核卷积图像操作
注意:如果你不想使用归一化卷积框,你应该使用 cv2.boxFilter(),这时要传入参数 normalize=False.
img = cv2.imread('./Pytorch.png')
kernel = np.ones((5,5),np.float_)/25
blur = cv2.blur(img,(5,5))
plt.subplot(121)
plt.imshow(img)
plt.title('Original')
plt.axis('off')
plt.subplot(122)
plt.imshow(blur)
plt.title('Blurred')
plt.axis('off')
plt.show()
- OpenCV中的函数cv2.boxFilter()是一种一般化的形式,而cv2.blur()是一种特殊化的形式。两者之间根本的区别主要是前者可以以非归一化形式调用,并且输出图像深度可以控制(cv2.blur()输出图像的深度与源图像保持一致)。假如变量ddepth的值设为-1,目标图像的深度将于源图像保持一致。
高斯模糊
- 现在把卷积核换成高斯核(简单来说,方框不变,将原来每个方框的值是
相等的,现在里面的值是符合高斯分布的,方框中心的值最大,其余方框根据距离中心元素的距离递减,构成一个高斯小山包。原来的求平均数现在变成求加权平均数,全就是方框里的值)。 - 实现的函数是
cv2.GaussianBlur()
我们需要指定高斯核的宽和高(必须是奇数)。以及高斯函数沿 X,Y 方向的标准差。如果我们只指定了 X 方向的的标准差,Y 方向也会取相同值。如果两个标准差都是 0,那么函数会根据核函数的大小自己计算。高斯滤波可以有效的从图像中去除高斯噪音。 - 也可以使用函数
cv2.getGaussianKernel()
自己构建一个高斯核。
cv2.GaussianBlur( SRC,ksize,sigmaX )
- ksize –高斯核大小。 ksize.width 并且 ksize.height 可以有所不同,但它们都必须是
正数
和奇数
。或者,它们可以为零,是指根据窗口大小ksize(sizeX,sizeY))来计算高斯函数标准差。 - sigmaX – X方向上的高斯核标准偏差。
中值模糊
- 顾名思义就是用与卷积框对应像素的
中值
来替代中心像素的值。这个滤波
器经常用来去除椒盐噪声
。前面的滤波器都是用计算得到的一个新值来取代中心像素的值,而中值滤波是用中心像素周围(也可以使他本身)的值来取代他。他能有效的去除噪声。卷积核的大小也应该是一个奇数
。
在这个例子中,我们给原始图像加上 50% 的噪声然后再使用中值模糊。
dst=cv2.medianBlur(src,ksize)
双边滤波
- 函数
cv2.bilateralFilter()
能在保持边界清晰的情况下有效的去除噪音
。但是这种操作与其他滤波器相比会比较慢
。我们已经知道高斯滤波器是求中心点邻近区域像素的高斯加权平均值
。这种高斯滤波器只考虑像素之间的空间关系
,而不会考虑像素值之间的关系(像素的相似度)。所以这种方法不会考虑一个像素是否位于边界。因此边界也会别模糊掉,而这正不是我们想要。双边滤波在同时使用空间高斯权重
和灰度值相似性高斯权重
。空间高斯函数确保只有邻近区域的像素对中心点有影响,灰度值相似性高斯函数确保只有与中心像素灰度值相近
的才会被用来做模糊运算。所以这种方法会确保边界不会被模糊掉,因为边界处的灰度值变化比较大
#9 邻域直径,两个 75 分别是空间高斯函数标准差,灰度值相似性高斯函数标准差
blur = cv2.bilateralFilter(img,9,75,75)