Bootstrap

【计算机视觉】图像滤波

1. 图像滤波定义

图像滤波是一种非常重要的图像处理技术,图像平滑、边缘检测、边缘增强、去除噪声都属于图像滤波,图像滤波是一种基于邻域的算法。
通过图像滤波,可以实现图像平滑、边缘检测;图像平滑也叫图像模糊,用以去除图像中的噪声、伪影等,它是图像处理和计算机视觉的常见步骤。

函数模糊类型特点使用场景
cv.blur均值模糊简单快速,所有像素权重相等基础平滑和降噪
cv.GaussianBlur高斯模糊中心权重高,模糊效果更自然,边缘细节保留较好图像处理前降噪、边缘检测
cv.medianBlur中值模糊抗噪能力强,尤其适合去除椒盐噪声去噪或细节保护的平滑处理

2. 均值滤波

均值滤波是一种简单的图像平滑方法,输出图像的每一个像素值都为其领域内的所有原始图像像素值的平均值。卷积核越大,滤波后的图像越模糊。
cv.blur 是 OpenCV 中的一种用于图像模糊处理的函数。它通过均值滤波(平均模糊)来平滑图像,减少噪声和细节。以下是其具体功能和用法详解。

1. 函数定义
cv.blur(src, ksize, dst=None, anchor=(-1, -1), borderType=cv.BORDER_DEFAULT) -> dst

2. 参数详解
  1. src

    • 输入图像,通常为单通道(灰度)或多通道(彩色)的矩阵。
    • 类型:numpy.ndarray
  2. ksize

    • 滤波核的大小,表示为 (width, height)
    • 是一个元组,例如 (5, 5) 表示一个 5x5 的矩形核。
    • 核越大,模糊效果越明显。
  3. dst(可选)

    • 输出图像,通常与输入图像大小和类型相同。如果未指定,会返回一个新的图像。
  4. anchor(可选)

    • 滤波核的锚点,表示滤波核的参考点(默认值为 (-1, -1),即使用核的中心作为锚点)。
  5. borderType(可选)

    • 边界扩充模式,决定如何处理图像边界。常见选项:
      • cv.BORDER_CONSTANT:使用常量填充边界。
      • cv.BORDER_REFLECT:边界像素反射。
      • cv.BORDER_REFLECT_101:类似反射,但不重复边界像素。
      • cv.BORDER_REPLICATE:复制边界像素。
      • cv.BORDER_WRAP:边界像素从另一侧复制。

3. 核心原理

cv.blur 是一种基于卷积的滤波方法。

  • 每个像素的值是由滤波核覆盖范围内的所有像素值的平均值计算得出的。
  • 公式:
    g ( x , y ) = 1 k w ⋅ k h ∑ u = 0 k w − 1 ∑ v = 0 k h − 1 f ( x + u , y + v ) g(x, y) = \frac{1}{k_w \cdot k_h} \sum_{u=0}^{k_w-1} \sum_{v=0}^{k_h-1} f(x+u, y+v) g(x,y)=kwkh1u=0kw1v=0kh1f(x+u,y+v)
    • ( g(x, y) ):输出图像的像素值。
    • ( f(x, y) ):输入图像的像素值。
    • ( k_w ),( k_h ):滤波核的宽和高。

3. 高斯滤波

高斯滤波是图像平滑或去噪的常用方法,高斯滤波的卷积核由高斯函数生成。
cv.GaussianBlur 是 OpenCV 中实现高斯模糊(Gaussian Blur)的函数,用于对图像进行平滑处理。相比普通均值模糊 (cv.blur),高斯模糊采用高斯权重分布,能更自然地减少图像噪声和细节,同时保留更多边缘信息。

1. 函数定义
cv.GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=0, borderType=cv.BORDER_DEFAULT) -> dst
2. 参数详解
  1. src

    • 输入图像,可以是单通道(灰度)或多通道(彩色)的图像。
    • 类型:numpy.ndarray
  2. ksize

    • 高斯核大小,表示为 (width, height),必须是奇数(如 (3, 3)(5, 5))。
    • 如果指定核大小为 (0, 0),会根据 sigmaXsigmaY 自动计算适当的核大小。
  3. sigmaX

    • X 方向上的高斯核标准差。
    • 标准差越大,模糊效果越明显。如果设置为 0,会根据核大小自动计算。
  4. dst(可选)

    • 输出图像,与输入图像类型和大小相同。如果未指定,会返回一个新图像。
  5. sigmaY(可选)

    • Y 方向上的高斯核标准差。如果设置为 0,默认与 sigmaX 相同。
  6. borderType(可选)

    • 边界扩展方式,决定如何处理图像边界。常见选项:
      • cv.BORDER_CONSTANT:用常量值填充边界。
      • cv.BORDER_REFLECT:边界像素反射。
      • cv.BORDER_REPLICATE:复制边界像素。
      • 等等。
3. 核心原理

高斯模糊通过高斯函数定义的权重对图像进行卷积。高斯函数的数学公式为:

G ( x , y ) = 1 2 π σ 2 exp ⁡ ( − x 2 + y 2 2 σ 2 ) G(x, y) = \frac{1}{2\pi \sigma^2} \exp\left(-\frac{x^2 + y^2}{2\sigma^2}\right) G(x,y)=2πσ21exp(2σ2x2+y2)

  • 核心思想是距离中心点越远的像素权重越小,中心点的权重最大。
  • 核的形状和标准差 σ 决定模糊效果的强弱和范围。

4. 中值滤波

中值滤波是将每个像素值用领域内所有像素值的中间值替代,不同于均值滤波和高斯滤波,中值滤波属于非线性滤波。
cv.medianBlur 是 OpenCV 中的一种中值模糊(Median Blur)处理函数,主要用于去噪声,尤其对椒盐噪声有很好的抑制效果。相比于均值模糊(cv.blur)和高斯模糊(cv.GaussianBlur),它更适合在保留边缘的同时去除噪声。
以下是 cv.medianBlur 的详解:

1. 函数定义
cv.medianBlur(src, ksize) -> dst
2. 参数详解
  1. src

    • 输入图像,可以是单通道(灰度)或多通道(彩色)的图像。
    • 类型:numpy.ndarray
  2. ksize

    • 滤波核大小,必须是正奇数(如 3, 5, 7)。
    • 核越大,模糊效果越强,但计算量也越大。
  3. 返回值 dst

    • 输出图像,与输入图像大小和类型相同。
    • 输出图像是中值模糊后的图像。
3. 核心原理

中值模糊是基于局部窗口(滤波核)的中值计算。具体步骤如下:

  1. 选择窗口: 在目标像素周围,定义一个大小为 ksize × ksize 的窗口。
  2. 排序: 对窗口内的所有像素值进行排序。
  3. 取中值: 用排序后的中间值替换窗口中心像素的值。

5. 双边滤波

双边滤波可以在去除噪声的同时,较好的保留图像的边缘;其卷积核综合考虑了像素间的空间距离和像素值的相似度。

1. 函数定义
cv.bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=cv.BORDER_DEFAULT) -> dst
2. 参数详解
  1. src

    • 输入图像,可以是单通道(灰度)或多通道(彩色)的图像。
    • 类型:numpy.ndarray
  2. d

    • 滤波的像素邻域直径(kernel size),指定用于滤波计算的区域范围。
    • 若设置为负值,则根据 sigmaSpace 自动计算合适的值。
  3. sigmaColor

    • 颜色空间的标准差,用于控制颜色相似性。
    • 值越大,颜色差异较大的像素也会参与模糊;值越小,仅对相近颜色的像素进行模糊。
  4. sigmaSpace

    • 坐标空间的标准差,用于控制像素间的距离权重。
    • 值越大,较远的像素也会影响当前像素;值越小,仅影响邻近像素。
  5. dst(可选)

    • 输出图像,与输入图像大小和类型相同。如果未指定,会返回一个新图像。
  6. borderType(可选)

    • 边界处理方式,决定如何处理图像边界。常见选项:
      • cv.BORDER_CONSTANT:用常量值填充边界。
      • cv.BORDER_REFLECT:边界像素反射。
      • cv.BORDER_REPLICATE:复制边界像素。
      • 等等。

3. 核心原理

双边滤波是一种非线性滤波,结合了空间和颜色的双重信息对像素值进行加权平均。其核心公式如下:

I f i l t e r e d ( p ) = 1 W p ∑ q ∈ Ω G s ( ∣ ∣ p − q ∣ ∣ ) ⋅ G r ( ∣ ∣ I ( p ) − I ( q ) ∣ ∣ ) ⋅ I ( q ) I_{filtered}(p) = \frac{1}{W_p} \sum_{q \in \Omega} G_s(||p - q||) \cdot G_r(||I(p) - I(q)||) \cdot I(q) Ifiltered(p)=Wp1qΩGs(∣∣pq∣∣)Gr(∣∣I(p)I(q)∣∣)I(q)

  • ( p ) 和 ( q ):分别表示当前像素和邻域内像素。
  • ( \Omega ):滤波核的邻域范围。
  • ( G_s(||p - q||) ):空间权重,由坐标距离 ( ||p - q|| ) 决定。
  • ( G_r(||I§ - I(q)||) ):颜色权重,由像素值差异 ( ||I§ - I(q)|| ) 决定。
  • ( W_p ):归一化系数,确保权重和为 1。

6. 自定义滤波

允许用户自己定义卷积核进行滤波。
cv.filter2D 是 OpenCV 中一个通用的二维卷积函数,允许用户对图像应用自定义的卷积核(滤波器)。它提供了一种灵活的方式实现各种滤波操作,例如锐化、边缘检测、模糊、浮雕效果等。

1. 函数定义
cv.filter2D(src, ddepth, kernel, dst=None, anchor=(-1, -1), delta=0, borderType=cv.BORDER_DEFAULT) -> dst
2. 参数详解
  1. src

    • 输入图像,可以是灰度图像或彩色图像。
    • 类型:numpy.ndarray
  2. ddepth

    • 输出图像的深度(像素值类型),可以是以下选项之一:
      • cv.CV_8U:8 位无符号整数(标准图像)。
      • cv.CV_16U:16 位无符号整数。
      • cv.CV_16S:16 位有符号整数。
      • cv.CV_32F:32 位浮点数。
      • cv.CV_64F:64 位浮点数。
    • 若设为 -1,则输出图像的深度与输入图像相同。
  3. kernel

    • 卷积核(滤波器),通常是一个二维矩阵,定义滤波操作的权重。
    • 类型:numpy.ndarray(例如,np.array([[...], [...], [...]]))。
    • 核的大小必须是奇数(如 (3 \times 3)、(5 \times 5))。
  4. dst(可选)

    • 输出图像,与输入图像大小相同。
  5. anchor(可选)

    • 卷积核的锚点位置,表示核的哪个位置与输入图像像素对齐。默认值为 (-1, -1),表示核的中心点是锚点。
    • 例如,若核大小为 (3 \times 3),默认锚点为 (1, 1)
  6. delta(可选)

    • 可选的偏移量,应用于卷积结果的每个像素。默认值为 0
  7. borderType(可选)

    • 边界像素填充方式,决定如何处理图像边界。常见选项包括:
      • cv.BORDER_CONSTANT:填充常数值。
      • cv.BORDER_REFLECT:边界像素反射。
      • cv.BORDER_REPLICATE:复制边界像素。
      • 等等。
3. 核心原理

cv.filter2D 的工作原理是二维卷积。对于每个像素位置 ( (x, y) ),函数将卷积核与图像的对应区域进行逐点相乘并求和。其公式为:

d s t ( x , y ) = ∑ i = 0 m − 1 ∑ j = 0 n − 1 k e r n e l ( i , j ) ⋅ s r c ( x + i − a , y + j − b ) + delta dst(x, y) = \sum_{i=0}^{m-1} \sum_{j=0}^{n-1} kernel(i, j) \cdot src(x+i-a, y+j-b) + \text{delta} dst(x,y)=i=0m1j=0n1kernel(i,j)src(x+ia,y+jb)+delta

  • ( m, n ):卷积核的宽度和高度。
  • ( (a, b) ):锚点的位置。
  • ( \text{delta} ):偏移量,默认为 0
基本用法
import cv2 as cv
import numpy as np

# 加载图像
img = cv.imread('example.jpg', cv.IMREAD_GRAYSCALE)

# 定义卷积核(例如:简单均值模糊核)
kernel = np.ones((5, 5), np.float32) / 25

# 应用卷积
filtered_img = cv.filter2D(img, ddepth=-1, kernel=kernel)

# 显示原图和卷积结果
cv.imshow('Original', img)
cv.imshow('Filtered', filtered_img)
cv.waitKey(0)
cv.destroyAllWindows()
使用自定义卷积核
# 锐化核
sharpen_kernel = np.array([[ 0, -1,  0],
                           [-1,  5, -1],
                           [ 0, -1,  0]], np.float32)

# 应用锐化卷积
sharpened_img = cv.filter2D(img, ddepth=-1, kernel=sharpen_kernel)
cv.imshow('Sharpened', sharpened_img)

# 边缘检测核
edge_kernel = np.array([[-1, -1, -1],
                        [-1,  8, -1],
                        [-1, -1, -1]], np.float32)

# 应用边缘检测卷积
edges_img = cv.filter2D(img, ddepth=-1, kernel=edge_kernel)
cv.imshow('Edges', edges_img)

cv.waitKey(0)
cv.destroyAllWindows()
5. 常用卷积核
功能卷积核(Kernel)
均值模糊 ( 1 9 [ 1 1 1 1 1 1 1 1 1 ] (\frac{1}{9}\begin{bmatrix}1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1\end{bmatrix} (91 111111111
高斯模糊 ( [ 1 2 1 2 4 2 1 2 1 ] / 16 ) (\begin{bmatrix}1 & 2 & 1 \\ 2 & 4 & 2 \\ 1 & 2 & 1\end{bmatrix} / 16) ( 121242121 /16)
锐化 ( [ 0 − 1 0 − 1 5 − 1 0 − 1 0 ] (\begin{bmatrix}0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1 & 0\end{bmatrix} ( 010151010 )
水平边缘检测 ( [ − 1 − 1 − 1 0 0 0 1 1 1 ] (\begin{bmatrix}-1 & -1 & -1 \\ 0 & 0 & 0 \\ 1 & 1 & 1\end{bmatrix} ( 101101101 )
垂直边缘检测 ( [ − 1 0 1 − 1 0 1 − 1 0 1 ] (\begin{bmatrix}-1 & 0 & 1 \\ -1 & 0 & 1 \\ -1 & 0 & 1\end{bmatrix} ( 111000111 )
拉普拉斯边缘检测 ( [ − 1 − 1 − 1 − 1 8 − 1 − 1 − 1 − 1 ] (\begin{bmatrix}-1 & -1 & -1 \\ -1 & 8 & -1 \\ -1 & -1 & -1\end{bmatrix} ( 111181111 )
浮雕效果 ( [ − 2 − 1 0 − 1 1 1 0 1 2 ] (\begin{bmatrix}-2 & -1 & 0 \\ -1 & 1 & 1 \\ 0 & 1 & 2\end{bmatrix} ( 210111012 )
;