八、OpenCV中的常见滤波方式
文章目录
- 一、滤波的分类
- 1.线性滤波
- 2. 非线性滤波
- 二、示例代码
一、滤波的分类
1.线性滤波
均值滤波(cv::blur)
作用:用邻域内像素的均值来代替中心像素,平滑图像,去除噪声。缺点是模糊明显,边缘不清晰。
函数原型:
void cv::blur(InputArray src, OutputArray dst, Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT);
参数:
- src: 输入图像。
- dst: 输出图像。
- ksize: 滤波核大小,如 Size(3,3)。
- anchor: 锚点(默认中心)。
- borderType: 边界处理方式。
示例:
cv::Mat img = cv::imread("lena.jpg");
cv::Mat result;
cv::blur(img, result, cv::Size(5,5));
高斯滤波(cv::GaussianBlur)
作用:高斯加权平均,邻域内越靠近中心的像素权重越大,常用于图像去噪。优点是保留更多边缘信息,效果比均值滤波更自然。
函数原型:
void cv::GaussianBlur(InputArray src, OutputArray dst, Size ksize,double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT);
参数:
- ksize: 高斯核大小(必须为奇数)。
- sigmaX: X方向标准差。
sigmaY: Y方向标准差(默认 0,即与 sigmaX 相同)。
示例:
cv::GaussianBlur(src, dst, cv::Size(5, 5), 1.5);
方框滤波(cv::boxFilter)
作用:类似均值滤波,但可以选择是否进行归一化。
函数原型:
void cv::boxFilter(InputArray src, OutputArray dst, int ddepth, Size ksize,Point anchor = Point(-1,-1), bool normalize = true, int borderType = BORDER_DEFAULT);
区别:
- normalize = true → 等价于均值滤波。
- normalize = false → 卷积核全为 1,不做均值,输出像素值可能变大。
示例:
cv::boxFilter(img, result, -1, cv::Size(5,5), cv::Point(-1,-1), true);
2. 非线性滤波
中值滤波(cv::medianBlur)
作用:用邻域内像素的中值替代中心像素,特别适合去除椒盐噪声。
函数原型:
void cv::medianBlur(InputArray src, OutputArray dst, int ksize);
参数:
- ksize: 滤波核大小(必须为奇数,如 3、5、7)。
示例:
cv::medianBlur(src, dst, 5);
双边滤波(cv::bilateralFilter)
作用:同时考虑空间距离和像素差异,既能平滑噪声,又能保持边缘。
函数原型:
void cv::bilateralFilter(InputArray src, OutputArray dst, int d,double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT);
参数:
- d: 邻域直径(像素数,推荐 5~15)。
- sigmaColor: 颜色空间标准差(越大越模糊)。
- sigmaSpace: 坐标空间标准差(越大越模糊)。
示例:
cv::bilateralFilter(img, result, 9, 75, 75);
自定义滤波(cv::filter2D)
作用:用自定义的卷积核对图像进行滤波(如锐化、边缘检测)。
函数原型:
void cv::filter2D(InputArray src, OutputArray dst, int ddepth,InputArray kernel, Point anchor = Point(-1,-1), double delta = 0,int borderType = BORDER_DEFAULT);
示例:
cv::Mat kernel = (cv::Mat_<float>(3,3) <<-1, -1, -1,-1, 8, -1,-1, -1, -1);
cv::filter2D(src, dst, -1, kernel);
二、示例代码
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;// 辅助函数:在图像上添加标题
Mat addTitle(const Mat& img, const string& title) {Mat dst;img.copyTo(dst);putText(dst, title, Point(10, 30), FONT_HERSHEY_SIMPLEX,1.0, Scalar(0, 0, 255), 2); // 红色文字return dst;
}int main() {// 读取图像Mat src = imread("opencv_demo.png");if (src.empty()) {cout << "无法读取图片!" << endl;return -1;}// 调整大小,保证拼接时统一尺寸Mat src_resized;resize(src, src_resized, Size(300, 300));// 各种滤波结果Mat blurImg, gaussianImg, medianImg, bilateralImg, sharpenImg;// 均值滤波blur(src_resized, blurImg, Size(5, 5));// 高斯滤波GaussianBlur(src_resized, gaussianImg, Size(5, 5), 1.5);// 中值滤波medianBlur(src_resized, medianImg, 5);// 双边滤波bilateralFilter(src_resized, bilateralImg, 9, 75, 75);// 锐化滤波 (自定义卷积核)Mat kernel = (Mat_<float>(3, 3) <<0, -1, 0,-1, 5, -1,0, -1, 0);filter2D(src_resized, sharpenImg, -1, kernel);// 加标题Mat img1 = addTitle(src_resized, "Original");Mat img2 = addTitle(blurImg, "Mean Blur");Mat img3 = addTitle(gaussianImg, "Gaussian Blur");Mat img4 = addTitle(medianImg, "Median Blur");Mat img5 = addTitle(bilateralImg, "Bilateral Filter");Mat img6 = addTitle(sharpenImg, "Sharpen");// 第一行 (原图 + 均值 + 高斯)Mat topRow;hconcat(vector<Mat>{img1, img2, img3}, topRow);// 第二行 (中值 + 双边 + 锐化)Mat bottomRow;hconcat(vector<Mat>{img4, img5, img6}, bottomRow);// 拼成 2x3 大图Mat finalShow;vconcat(topRow, bottomRow, finalShow);imshow("滤波对比", finalShow);waitKey(0);return 0;
}
输出结果如下: