\qquad 图像模糊也称图像平滑处理,它主要处理图像中与周围差异较大的点,将其像素值调整为与周围点像素值近似的值,其目的主要是消除图像噪声和边缘。线性的平滑滤波可以有效地消除噪声,但同时将使图像中的细节产生模糊,清晰度下降,低通滤波效应明显。非线性平滑滤波可以在消除图像孤立噪声的同时,较好地保持图像的细节信息。
\qquad 均值滤波是指以当前点为中心点,用其周围N × \times ×N个点的像素值的平均值来代替当前这个点的像素值。用于计算平均值的N × \times ×N个点称为邻域,用于滤波计算的卷积大小与邻域相同。举个例子,一个大小为 3 × 3 3\times3 3×3的邻域如下图
则卷积核为:
1 3 × 3 [ 1 1 1 1 1 1 1 1 1 ] \frac{1}{3\times3} \quad \left[ \begin{matrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \\ \end{matrix} \right] 3×31⎣⎡111111111⎦⎤
则中心点的均值滤波值=(125+132+124+67+251+123+113+142+102)÷9=120,120比251 更接近周围的值,所以用120替换251。
OpenCV 的 cv2.blur()函数用于实现均值滤波,其基本格式如下:
dst=cv2.blur(src,ksize [,anchor [,borderType]])
其参数说明如下:
参数 | 说明 |
---|---|
dst | 为滤波结果图像 |
src | 为原图像 |
ksize | 为卷积核大小,表示为(width,height), width 和 height 通常设置为相同值,且为正数和奇数 |
anchor | 为锚点,默认值为(-1,-1),表示锚点位于卷积核中心 |
borderType | 为边界值处理方式 |
import cv2
img = cv2.imread('lena2.jpg')
cv2.imshow('img', img)
img2 = cv2.blur(img, (5, 5)) # 可调整卷积核大小查看不同效果
cv2.imshow('imgBlur', img2)
cv2.waitKey(0)
高斯滤波与均值滤波略有不同,它按像素点与中心点的不同距离,赋予像素点不同的权重值,越靠近中心点权重值越大,越远离中心点权重值越小;然后根据权重值计算邻域内所有像素点的和,将和作为中心点的像素值。
常用的高斯卷积核有以下两种:
1 16 [ 1 2 1 2 4 2 1 2 1 ] \frac{1}{16} \quad \left[ \begin{matrix} 1 & 2 & 1 \\ 2 & 4 & 2\\ 1 & 2 & 1 \\ \end{matrix} \right] 161⎣⎡121242121⎦⎤
1 273 [ 1 4 7 4 1 4 16 26 16 4 7 26 41 26 7 4 16 26 16 4 1 4 7 4 1 ] \frac{1}{273} \quad \left[ \begin{matrix} 1 & 4 & 7&4&1 \\ 4 & 16 & 26&16&4\\ 7 & 26 & 41&26&7 \\ 4 & 16 & 26&16&4\\ 1 & 4 & 7&4&1 \\ \end{matrix} \right] 2731⎣⎢⎢⎢⎢⎡1474141626164726412674162616414741⎦⎥⎥⎥⎥⎤
这两种高斯卷积核是如何得来的呢?其实是通过高斯函数计算出来的,公式如下:
G ( x , y ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 G(x,y) = \frac{1}{2\pi\sigma^2} \quad e^- \frac{x^2+y^2}{2\sigma^2} \quad G(x,y)=2πσ21e−2σ2x2+y2
以3 × 3的高斯卷积核为例,以模板的中心位置为坐标原点进行取样。模板在各个位置的坐标,如下所示(x轴水平向右,y轴竖直向上)。
这样,将各个位置的坐标带入到高斯函数G中,得到的每个值按照位置排列,就得到了高斯卷积核。
这样输出的高斯卷积核有两种形式:
① 小数类型:直接计算得到的值,没有经过任何处理。
② 整数类型:将得到的值进行归一化处理,即将坐上叫的值归一化为1,其他每个系数都除以左上角的系数,然后取整。在使用整数模板时,则需要在模板的前面加一个系数,该系数为模板系数之和的倒数。(上面的就是整数类型)
例如:生成高斯卷积核为3 × 3,σ = 0.8的模板
小数模板:
整数模板:
再经过四舍五入和添加系数得到最终结果:
1 16 [ 1 2 1 2 4 2 1 2 1 ] \frac{1}{16} \quad \left[ \begin{matrix} 1 & 2 & 1 \\ 2 & 4 & 2\\ 1 & 2 & 1 \\ \end{matrix} \right] 161⎣⎡121242121⎦⎤
OpenCV 的 cv2.GaussianBlur()函数用于实现高斯滤波,其基本格式如下:
dst=cv2.GaussianBlur(src,ksize,SigmaX [,sigmaY [,borderType]])
参数说明如下:
参数 | 说明 |
---|---|
sigmaX | 为水平方向上的权重值 |
sigmaY | 为垂直方向上的权重值 |
其他参数 | 含义和 cv2.blur)函数中的一致 |
如果 sigmaY 为0,则令其等于 sigmaX;如果sigmaX 和 sigmaY 均为0,则按下面的公式计算其值,其中 ksize 为(width,height)。
sigmaX = 0.3×((width-1)×0.5-1)+0.8
sigmar = 0.3×((height-1)×0.5-1)+0.8
import cv2
img = cv2.imread('lena2.jpg')
cv2.imshow('img', img)
img2 = cv2.GaussianBlur(img, (51, 51), 0, 0) # 可调整卷积核大小查看不同效果
cv2.imshow('imgBlur', img2)
cv2.waitKey(0)
方框滤波以均值滤波为基础,可选择是否对滤波结果进行归一化。如果选择进行归一化,则滤波结果为邻域内点的像素值之和的平均值,否则滤波结果为像素值之和。
OpencV 的cv2.boxFilter()函数用于实现方框滤波,其基本格式如下。
dst=cv2.boxFilter(snc,ddepth,ksize[,anchor[,normalize[,bordertype]]])
其参数说明如下:
参数 | 说明 |
---|---|
ddepth | 为目标图像的深度,一般使用-1 表示与原图像的深度一致 |
normalize | 为 True(默认值)时执行归一化操作,为 False 时不执行归一化操作 |
其他参数含义 | 和 cv2.blur()函数中的一致 |
import cv2
img = cv2.imread('lena2.jpg')
cv2.imshow('img', img)
img2 = cv2.boxFilter(img, -1, (7, 7), normalize=True) # 可调整卷积核大小查看不同效果
cv2.imshow('imgBlur', img2)
cv2.waitKey(0)
中值滤波将邻域内的所有像素值排序,取中间值作为邻域中心点的像素值。其设计思想是使拥有不同像素点的值看起来更接近它的邻域值,因为噪声的出现,使该点像素比周围的像素亮(暗)许多,中值滤波是给出滤波用的模板,对模板中的像素值由小到大排列,最终待处理像素的灰度取这个模板中的灰度的中值。在一定条件下,中值滤波可以克服线性滤波器所带来的图像细节模糊,而且对滤除脉冲干扰及颗粒噪声最为有效。但是对一些细节多,特别是点、线、尖顶细节多的图像则不宜采用中值滤波的方法。
中值滤波的步骤
(1)模板在图中漫游,模板中心与图中某个像素位置重合。
(2)读取模板中各个对应像素值。
(3)将这些像素值从小到大排成一列。
(4)找出这些值里排在中间的一个。
(5)将这个中间值赋给当前对应模板中心位置的像素。
OpenCV 的 cv2.medianBilur()函数用于实现中值滤波,其基本格式如下。
dst=cv2.medianBlur(src,ksize)
其中,ksize 表示卷积核大小,必须是大于 1 的奇数。
import cv2
img = cv2.imread('lena2.jpg')
cv2.imshow('img', img)
img2 = cv2.medianBlur(img, 5) # 可调整卷积核大小查看不同效果
cv2.imshow('imgBlur', img2)
cv2.waitKey(0)
双边滤波在计算像素值的同时会考虑距离和色差信息,从而可在消除噪声的同时保护边缘信息。在执行双边滤波操作时,如果像素点与当前点色差较小,则赋予其较大的权重值,否则赋予其较小的权重值。
OpenCV 的 cv2.bilateralFflter()函数用于实现双边滤波,其基本格式如下:
dst=cv2.bilateralFilter(snc,d,sigmacolor,sigmaSpace[,borderType])
其参数说明如下:
参数 | 说明 |
---|---|
d | 表示以当前点为中心的邻域的直径,一般为 5 |
sigmaColor | 为双边滤波选择的色差范围 |
sigmaSpace | 为空间坐标中的 sigma值,值越大表示越多的像素点参与滤波计算。当d>0时,忽略 sigmaSpace,由d决定邻域大小;否则d 由 sigmaSpace 计算得出,与 sigmaSpace 成比例 |
import numpy as np
import cv2
img = cv2.imread('lena2.jpg')
cv2.imshow('img', img)
img2 = cv2.bilateralFilter(img, 50, 50, 50) # 可调整参数查看不同效果
cv2.imshow('imgBlur', img2)
cv2.waitKey(0)
均值滤波、高斯滤波、方框滤波、中值滤波和双边滤波等可以通过参数柬碩定卷积核,2D 卷积可使用自定义的卷积核来执行滤波操作。
OpenCV的 cv2.filter2D()函数用于实现 2D 卷积,其基本格式如下:
dst=cv2.filter2D(src,ddepth,kennel[,anchor[,delta[,bondenType]]])
其参数说明如下:
参数 | 说明 |
---|---|
ddepth | 表示目标图像 dst 的深度,一般使用-1 表示与原图像 SrC一致 |
kernel | 为单通道卷积核(一维数组)) |
anchor | 为图像处理的锚点 |
delta | 为修正值,未省略时,将加上该值作为最终的滤波结果 |
borderType | 为边界值处理方式 |
import numpy as np
import cv2
img = cv2.imread('lena2.jpg')
k1 = np.array([[3, 3, 3, 3, 3],
[3, 9, 9, 9, 3],
[3, 11, 12, 13, 3],
[3, 8, 8, 8, 3],
[3, 3, 3, 3, 3], ])/25 # 自定义卷积核1
k2 = np.ones((5, 5), np.float32)/25 # 自定义卷积核2
img2 = cv2.filter2D(img, -1, k1)
cv2.imshow('imgK1', img2)
img2 = cv2.filter2D(img, -1, k2)
cv2.imshow('imgK2', img2)
cv2.waitKey(0)