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 实现:

cpp 复制代码
cv::blur(src, dst, cv::Size(5, 5));

特点:

  • 计算速度快;
  • 容易模糊边缘;
  • 适合去除高斯噪声。

2. 高斯滤波(Gaussian Filter)

原理: 使用高斯分布作为权重函数,对邻域像素加权平均。距离中心越近的像素权重越大。

高斯核定义:

OpenCV 实现:

cpp 复制代码
cv::GaussianBlur(src, dst, cv::Size(5, 5), 1.5);

参数说明:

  • Size(5,5):核大小;
  • sigmaXsigmaY:高斯分布的标准差。

特点:

  • 平滑性优于均值滤波;
  • 对噪声的抑制更有效;
  • 能保持一定的边缘特征。

3. 中值滤波(Median Filter)

原理: 用邻域像素的中值替代中心像素值,属于非线性滤波。

OpenCV 实现:

cpp 复制代码
cv::medianBlur(src, dst, 5);

特点:

  • 对椒盐噪声效果非常好;
  • 边缘保留能力强;
  • 运算速度略慢于均值滤波。

4. 双边滤波(Bilateral Filter)

原理: 同时考虑空间距离与像素相似性两个因素。即使在平滑噪声的同时,也能很好地保留边缘。

加权公式:

其中:

  • Gs:空间高斯权重;
  • Gr:像素值相似度权重。

OpenCV 实现:

cpp 复制代码
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 实现:

cpp 复制代码
cv::Laplacian(src, dst, CV_16S, 3);
cv::convertScaleAbs(dst, dst);

特点:

  • 对噪声敏感;
  • 常与高斯滤波配合使用(如 LoG 算法)。

2. Sobel 滤波(Sobel Filter)

原理: 一阶导数算子,用于检测边缘方向。

Sobel 核:

OpenCV 实现:

cpp 复制代码
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 实现:

cpp 复制代码
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() 通用接口,可自定义任意卷积核,实现各种滤波器。

示例:

cpp 复制代码
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 表示输出图像深度与输入相同;
  • 可通过改变核系数实现不同效果。

示例:

python 复制代码
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/拉普拉斯 线性 边缘增强 对噪声敏感 边缘检测
相关推荐
Learn Beyond Limits1 小时前
Data Mining Tasks|数据挖掘任务
人工智能·python·神经网络·算法·机器学习·ai·数据挖掘
lisw051 小时前
计算生物学的学科体系!
大数据·人工智能·机器学习
cxr8282 小时前
深度解析顶级 Doc Agent System Prompt 的架构与实践
网络·人工智能·架构·prompt·ai智能体·ai赋能·上下文工程
TGITCIC2 小时前
User Prompt 与 System Prompt:大模型沟通的“双引擎”机制深度拆解
人工智能·大模型·prompt·提示词·ai大模型·大模型ai·上下文工程
leiming62 小时前
ResNetLayer 类
人工智能·神经网络·计算机视觉
麦麦大数据2 小时前
F045 vue+flask棉花病虫害CNN识别+AI问答知识neo4j 图谱可视化系统深度学习神经网络
人工智能·深度学习·神经网络·cnn·可视化·智能问答·病虫害识别
IT_陈寒2 小时前
Java 17实战:我从老旧Spring项目迁移中总结的7个关键避坑点
前端·人工智能·后端
渡我白衣3 小时前
字符串的陷阱与艺术——std::string全解析
网络·c++·人工智能·自然语言处理·智能路由器·信息与通信·caffe
Allen200003 小时前
Hello-Agents task2 大语言模型基础
人工智能·语言模型·自然语言处理