OpenCV(二十四):图像滤波
滤波概述
在数字图像处理中,滤波(Filtering) 是最基本也是最常用的操作之一。滤波的核心思想是利用邻域像素的信息,对目标像素的灰度值或颜色进行加权平均或非线性变换,从而达到 去噪、平滑、增强或提取特征 的目的。
在 OpenCV 中,滤波功能非常完善,提供了线性滤波(如均值滤波、高斯滤波)、非线性滤波(如中值滤波、双边滤波)以及基于卷积核的自定义滤波接口。
滤波的基本原理
假设输入图像为 I(x,y),滤波器或卷积核(Kernel)为 K(i,j),则线性滤波可表示为:

其中:
- I′(x,y):滤波后的输出像素;
- K(i,j):卷积核的权重;
- (2k+1)×(2k+1):核的尺寸。
根据卷积核权值分布的不同,滤波可分为平滑滤波和锐化滤波:
- 平滑滤波:抑制噪声与细节变化,使图像变得更“平滑”;
- 锐化滤波:增强边缘与细节,使图像更清晰。
卷积核
概念
在图像处理中,卷积核(Kernel) 是一个用于提取图像局部特征的矩阵。
它定义了如何将输入图像中每个像素与其邻域像素组合,从而生成新的输出图像。
数学上,卷积(Convolution)操作可表示为:

其中:
- I(x,y):输入图像;
- K(i,j):卷积核(权重矩阵);
- G(x,y):输出图像;
- k:卷积核的半径(若核大小为 3×3,则 k=1)。
卷积的本质是:
通过局部加权求和的方式,让图像在空间域上发生平滑、锐化、边缘增强、检测等变化。
分类
在 OpenCV 中,卷积核主要分为以下几类:
| 分类 | 核心作用 | 常见类型 | 示例函数 |
|---|---|---|---|
| 平滑滤波核 | 去噪与模糊图像 | 均值核、高斯核 | cv2.blur, cv2.GaussianBlur |
| 锐化核 | 增强边缘与细节 | Laplacian、锐化核 | cv2.filter2D, cv2.Laplacian |
| 边缘检测核 | 提取梯度与轮廓 | Sobel、Prewitt、Canny | cv2.Sobel, cv2.Canny |
| 特殊效果核 | 模拟浮雕、边缘光照等 | Emboss、Outline | 自定义卷积核 |
OpenCV 中的卷积函数
| 函数名 | 功能 | 示例 |
|---|---|---|
cv2.filter2D() | 通用卷积操作 | 自定义核 |
cv2.blur() | 均值滤波 | 平滑 |
cv2.GaussianBlur() | 高斯滤波 | 去噪 |
cv2.medianBlur() | 中值滤波(非线性) | 去椒盐噪声 |
cv2.bilateralFilter() | 双边滤波 | 平滑且保边 |
cv2.Sobel() | 一阶导边缘检测 | 边缘检测 |
cv2.Laplacian() | 二阶导锐化 | 边缘增强 |
平滑滤波(去噪滤波)
1. 均值滤波(Mean Filter)
原理:用邻域像素的平均值替代中心像素。该方法简单高效,但对边缘保留能力较差。
公式:

OpenCV 实现:
cv::blur(src, dst, cv::Size(5, 5));
特点:
- 计算速度快;
- 容易模糊边缘;
- 适合去除高斯噪声。
2. 高斯滤波(Gaussian Filter)
原理: 使用高斯分布作为权重函数,对邻域像素加权平均。距离中心越近的像素权重越大。
高斯核定义:

OpenCV 实现:
cv::GaussianBlur(src, dst, cv::Size(5, 5), 1.5);
参数说明:
Size(5,5):核大小;sigmaX、sigmaY:高斯分布的标准差。
特点:
- 平滑性优于均值滤波;
- 对噪声的抑制更有效;
- 能保持一定的边缘特征。
3. 中值滤波(Median Filter)
原理: 用邻域像素的中值替代中心像素值,属于非线性滤波。
OpenCV 实现:
cv::medianBlur(src, dst, 5);
特点:
- 对椒盐噪声效果非常好;
- 边缘保留能力强;
- 运算速度略慢于均值滤波。
4. 双边滤波(Bilateral Filter)
原理: 同时考虑空间距离与像素相似性两个因素。即使在平滑噪声的同时,也能很好地保留边缘。
加权公式:

其中:
- Gs:空间高斯权重;
- Gr:像素值相似度权重。
OpenCV 实现:
cv::bilateralFilter(src, dst, 9, 75, 75);
参数含义:
9:邻域直径;75:颜色与空间的高斯标准差。
特点:
- 边缘保留能力最强;
- 去噪效果好;
- 计算复杂度高。
5. 非局部均值滤波(Non-Local Means)
原理: 通过在更大范围内寻找相似块进行加权平均,保留纹理和细节。
OpenCV 实现:
cv::fastNlMeansDenoising(src, dst, 10, 7, 21);
特点:
- 能有效保留纹理;
- 适合自然图像;
- 计算量大。
锐化滤波(边缘增强)
锐化滤波的目的是增强图像的边缘,使轮廓更加清晰。常用方法包括 拉普拉斯滤波、Sobel 滤波 和 自定义卷积核锐化。
1. 拉普拉斯滤波(Laplacian Filter)
原理: 计算像素的二阶导数,检测灰度突变区域。
公式:

OpenCV 实现:
cv::Laplacian(src, dst, CV_16S, 3);
cv::convertScaleAbs(dst, dst);
特点:
- 对噪声敏感;
- 常与高斯滤波配合使用(如 LoG 算法)。
2. Sobel 滤波(Sobel Filter)
原理: 一阶导数算子,用于检测边缘方向。
Sobel 核:

OpenCV 实现:
cv::Sobel(src, grad_x, CV_16S, 1, 0);
cv::Sobel(src, grad_y, CV_16S, 0, 1);
cv::convertScaleAbs(grad_x, grad_x);
cv::convertScaleAbs(grad_y, grad_y);
cv::addWeighted(grad_x, 0.5, grad_y, 0.5, 0, dst);
特点:
- 对边缘方向敏感;
- 可结合梯度幅值计算实现边缘检测。
3. 自定义卷积锐化
可以通过自定义卷积核实现更灵活的锐化效果。例如经典锐化核:

OpenCV 实现:
cv::Mat kernel = (cv::Mat_<float>(3,3) << 0,-1,0,-1,5,-1,0,-1,0);
cv::filter2D(src, dst, -1, kernel);
特点:
- 可灵活调整锐化强度;
- 可与平滑滤波结合使用。
自定义滤波与卷积
OpenCV 提供了 filter2D() 通用接口,可自定义任意卷积核,实现各种滤波器。
示例:
cv::Mat kernel = (cv::Mat_<float>(3,3) << 1,1,1,1,1,1,1,1,1);
kernel = kernel / 9.0;
cv::filter2D(src, dst, -1, kernel);
说明:
- 第三个参数
-1表示输出图像深度与输入相同; - 可通过改变核系数实现不同效果。
示例:
import cv2
import numpy as np# 读取原图(灰度)
src = cv2.imread('test.jpg', cv2.IMREAD_GRAYSCALE)# ----------------------------
# 1. 自定义均值滤波核
# ----------------------------
mean_kernel = np.ones((5, 5), np.float32) / 25
dst_mean = cv2.filter2D(src, -1, mean_kernel)# ----------------------------
# 2. 自定义锐化滤波核
# ----------------------------
sharpen_kernel = np.array([[0, -1, 0],[-1, 5, -1],[0, -1, 0]], np.float32)
dst_sharp = cv2.filter2D(src, -1, sharpen_kernel)# ----------------------------
# 3. 自定义边缘检测核(Sobel X方向)
# ----------------------------
sobelx_kernel = np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]], np.float32)
dst_sobelx = cv2.filter2D(src, -1, sobelx_kernel)# ----------------------------
# 4. 自定义拉普拉斯核(边缘增强)
# ----------------------------
laplacian_kernel = np.array([[0, 1, 0],[1, -4, 1],[0, 1, 0]], np.float32)
dst_lap = cv2.filter2D(src, -1, laplacian_kernel)# ----------------------------
# 5. 自定义浮雕滤波核
# ----------------------------
emboss_kernel = np.array([[-2, -1, 0],[-1, 1, 1],[0, 1, 2]], np.float32)
dst_emboss = cv2.filter2D(src, -1, emboss_kernel)
dst_emboss = cv2.normalize(dst_emboss, None, 0, 255, cv2.NORM_MINMAX)# ----------------------------
# 显示结果
# ----------------------------
cv2.imshow("Original", src)
cv2.imshow("Mean Blur", dst_mean)
cv2.imshow("Sharpen", dst_sharp)
cv2.imshow("Sobel X", dst_sobelx)
cv2.imshow("Laplacian", dst_lap)
cv2.imshow("Emboss", dst_emboss)cv2.waitKey(0)
cv2.destroyAllWindows()
总结
| 滤波类型 | 是否线性 | 主要优点 | 主要缺点 | 典型场景 |
|---|---|---|---|---|
| 均值滤波 | 线性 | 简单高效 | 模糊边缘 | 基础平滑 |
| 高斯滤波 | 线性 | 去噪效果好 | 边缘损失 | 图像预处理 |
| 中值滤波 | 非线性 | 去椒盐噪声 | 运算慢 | 工业视觉 |
| 双边滤波 | 非线性 | 保边去噪 | 计算复杂 | 美颜、HDR |
| 非局部均值 | 非线性 | 保留纹理 | 速度慢 | 高质量去噪 |
| Sobel/拉普拉斯 | 线性 | 边缘增强 | 对噪声敏感 | 边缘检测 |
