1 均值滤波
均值滤波器是一种基本的线性滤波器,常用于图像处理中的平滑操作。在 OpenCV 中,可以使用cv2.blur()
函数或cv2.boxFilter()
函数进行均值滤波操作。
均值滤波器的原理是将每个像素的灰度值替换为其周围像素灰度值的平均值。其核心思想是去除图像中的高频噪声,同时保留图像中的低频信息。
在进行均值滤波操作时,需要定义一个滤波模板(也称为卷积核),通常是一个矩形区域,其大小由模板的宽度和高度决定。在模板中的每一个像素,都会与该像素周围的像素进行加权平均,从而得到新的像素值。
可以使用cv2.blur()
函数或cv2.boxFilter()
函数。cv2.blur()
函数的基本语法如下:
dst = cv2.blur(src, ksize)
其中:
src
:输入图像,可以为灰度图像或彩色图像。ksize
:滤波模板大小,必须为正奇数。当ksize
为(5,5)时,表示使用5x5大小的矩形滤波器。
import cv2
img = cv2.imread('test.png')
blur = cv2.blur(img, (5,5))
cv2.imshow('original', img)
cv2.imshow('blurred', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
2 中值滤波
中值滤波与均值滤波非常相似,只是中值滤波赋给中间核心元素的数值是周边数值的中位数而非平均数。该方法的函数基本语法是:
dst = cv2.medianBlur(src, ksize)
3 高斯滤波
3.1 基本原理
高斯滤波(Gaussian Blur)是一种常见的图像滤波方法,它可以对图像进行平滑处理,减少噪声和细节,常用于预处理和特征提取等领域。其核心思想是使用高斯分布来模糊图像,使得图像中的高频噪声被滤除,从而达到平滑图像的效果。
高斯分布是一种常见的概率分布,它具有以下的概率密度函数:
G ( x , y ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 G(x,y) = \frac{1}{2\pi\sigma^2} e^{-\frac{x^2+y^2}{2\sigma^2}} G(x,y)=2πσ21e−2σ2x2+y2
其中, ( x , y ) (x, y) (x,y) 是高斯分布的二维坐标, σ \sigma σ 是高斯分布的标准差。高斯分布的形状是一个钟形曲线,具有对称性,随着距离坐标中心点越远,其值逐渐变小。在高斯滤波的卷积核中,离中心越近,权重越高。
在高斯滤波中,我们使用一个大小为 k × k k \times k k×k 的二维卷积核来进行滤波,该卷积核的值由高斯分布产生。具体而言,对于图像中的每个像素 ( i , j ) (i, j) (i,j),我们将高斯滤波器与该像素的邻域 N i , j N_{i,j} Ni,j 进行卷积运算,得到新的像素值 I ′ ( i , j ) I'(i, j) I′(i,j):
I ′ ( i , j ) = 1 k 2 ∑ u = − k / 2 k / 2 ∑ v = − k / 2 k / 2 G ( u , v ) ⋅ I ( i + u , j + v ) I'(i, j) = \frac{1}{k^2} \sum_{u=-k/2}^{k/2}\sum_{v=-k/2}^{k/2} G(u, v) \cdot I(i+u, j+v) I′(i,j)=k21u=−k/2∑k/2v=−k/2∑k/2G(u,v)⋅I(i+u,j+v)
其中, G ( u , v ) G(u, v) G(u,v) 表示高斯滤波器在 ( u , v ) (u, v) (u,v) 处的值, I ( i + u , j + v ) I(i+u, j+v) I(i+u,j+v) 表示输入图像在 ( i + u , j + v ) (i+u, j+v) (i+u,j+v) 处的像素值。
注意,这里我们对卷积核中每个元素乘上了 1 / k 2 1/k^2 1/k2 的缩放因子,这是为了避免滤波后图像的亮度变化。
3.2 对应函数
在OpenCV中,可以使用 cv2.GaussianBlur()
函数来进行高斯滤波。该函数的参数包括输入图像、卷积核大小、高斯分布的标准差等,函数的语法如下:
cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]]) → dst
其中,参数含义如下:
src
:输入图像。ksize
:滤波器的大小。该参数必须为正的奇数。 如果指定了宽度和高度,则它们应该分别指定为ksize.width
和ksize.height
。如果将该参数设置为零,OpenCV 会自动计算滤波器大小。sigmaX
:高斯分布在 x x x 方向的标准差。如果该值为零,OpenCV 会根据ksize
来计算标准差。dst
:输出图像。如果未提供,则函数会创建一个与src
具有相同尺寸和类型的输出图像。sigmaY
:高斯分布在 y y y 方向的标准差。如果将该值设置为零,那么函数会将其设置为sigmaX
的值,即沿着 x x x 和 y y y 方向使用相同的标准差。borderType
:边界模式。默认值为cv2.BORDER_DEFAULT
。个人不建议修改。
示例代码如下:
import cv2
img = cv2.imread("test.png") # 读取原图
dst1 = cv2.GaussianBlur(img, (5, 5), 0, 0) # 使用大小为5*5的滤波核进行高斯滤波
dst2 = cv2.GaussianBlur(img, (9, 9), 0, 0) # 使用大小为9*9的滤波核进行高斯滤波
dst3 = cv2.GaussianBlur(img, (15, 15), 0, 0) # 使用大小为15*15的滤波核进行高斯滤波
cv2.imshow("img", img)
cv2.imshow("5", dst1)
cv2.imshow("9", dst2)
cv2.imshow("15", dst3)
cv2.waitKey()
cv2.destroyAllWindows()
随着滤波核的变大,图像逐渐模糊。高斯滤波器在图形处理中可以产生较好的毛玻璃效果。
4 双边滤波器
双边滤波器(Bilateral Filter)是一种非线性滤波器,它可以保留图像边缘信息的同时进行平滑处理,常用于去除图像中的噪声。
双边滤波器在空间域和灰度值域均使用了高斯滤波器,但是在进行灰度值域的滤波时,它使用了不同于高斯分布的加权函数。双边滤波器的加权函数有两个参数:一个是空间域的标准差,用于控制像素之间距离的影响;另一个是灰度值域的标准差,用于控制像素之间灰度值差异的影响。这样就可以保留图像中的边缘信息,同时去除噪声。
使用 cv2.bilateralFilter()
函数来应用双边滤波器。函数的语法如下:
cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]]) → dst
其中:
src
:输入图像。d
:滤波器的直径。该参数应该是正的奇数。sigmaColor
:颜色空间的标准差,用于控制灰度值域的影响。sigmaSpace
:空间域的标准差,用于控制像素之间距离的影响。dst
:输出图像。如果未提供,则函数会创建一个与src
具有相同尺寸和类型的输出图像。borderType
:边界模式。默认值为cv2.BORDER_DEFAULT
。
下面对比一下高斯滤波器和双边滤波器:
import cv2
img = cv2.imread("test.png") # 读取原图
dst1 = cv2.GaussianBlur(img, (15, 15), 0, 0) # 使用大小为15*15的滤波核进行高斯滤波
# 双边滤波,选取范围直径为15,颜色差为120
dst2 = cv2.bilateralFilter(img, 15, 120, 100)
cv2.imshow("img", img)
cv2.imshow("Gauss", dst1) # 显示高斯滤波效果
cv2.imshow("bilateral", dst2) # 显示双边滤波效果
cv2.waitKey()
cv2.destroyAllWindows()
可以看出双边滤波器在部分区域并没有进行模糊处理。