八、OpenCV中的常见滤波方式

文章目录

一、滤波的分类

1.线性滤波

均值滤波(cv::blur)

作用:用邻域内像素的均值来代替中心像素,平滑图像,去除噪声。缺点是模糊明显,边缘不清晰。

函数原型:

cpp 复制代码
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: 边界处理方式。

示例:

cpp 复制代码
cv::Mat img = cv::imread("lena.jpg");
cv::Mat result;
cv::blur(img, result, cv::Size(5,5));

高斯滤波(cv::GaussianBlur)

作用:高斯加权平均,邻域内越靠近中心的像素权重越大,常用于图像去噪。优点是保留更多边缘信息,效果比均值滤波更自然。

函数原型:

cpp 复制代码
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 相同)。

示例:

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

方框滤波(cv::boxFilter)

作用:类似均值滤波,但可以选择是否进行归一化。

函数原型:

cpp 复制代码
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,不做均值,输出像素值可能变大。

示例:

cpp 复制代码
cv::boxFilter(img, result, -1, cv::Size(5,5), cv::Point(-1,-1), true);

2. 非线性滤波

中值滤波(cv::medianBlur)

作用:用邻域内像素的中值替代中心像素,特别适合去除椒盐噪声。

函数原型:

cpp 复制代码
void cv::medianBlur(InputArray src, OutputArray dst, int ksize);

参数:

  • ksize: 滤波核大小(必须为奇数,如 3、5、7)。

示例:

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

双边滤波(cv::bilateralFilter)

作用:同时考虑空间距离和像素差异,既能平滑噪声,又能保持边缘。

函数原型:

cpp 复制代码
void cv::bilateralFilter(InputArray src, OutputArray dst, int d,
                         double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT);

参数:

  • d: 邻域直径(像素数,推荐 5~15)。
  • sigmaColor: 颜色空间标准差(越大越模糊)。
  • sigmaSpace: 坐标空间标准差(越大越模糊)。

示例:

cpp 复制代码
cv::bilateralFilter(img, result, 9, 75, 75);

自定义滤波(cv::filter2D)

作用:用自定义的卷积核对图像进行滤波(如锐化、边缘检测)。

函数原型:

cpp 复制代码
void cv::filter2D(InputArray src, OutputArray dst, int ddepth,
                  InputArray kernel, Point anchor = Point(-1,-1), double delta = 0,
                  int borderType = BORDER_DEFAULT);

示例:

cpp 复制代码
cv::Mat kernel = (cv::Mat_<float>(3,3) <<
                 -1, -1, -1,
                 -1,  8, -1,
                 -1, -1, -1);
cv::filter2D(src, dst, -1, kernel);

二、示例代码

cpp 复制代码
#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;
}

输出结果如下:

相关推荐
月疯7 小时前
OPENCV摄像头读取视频
人工智能·opencv·音视频
山烛9 小时前
OpenCV:人脸检测,Haar 级联分类器原理
人工智能·opencv·计算机视觉·人脸检测·harr级联分类器
Monkey的自我迭代13 小时前
背景建模(基于视频,超炫)项目实战!
opencv·计算机视觉·音视频
小码编匠14 小时前
开箱即用!集成 YOLO+OpenCV+OCR 的 WebAI 平台(支持RTSP/RTMP视频流识别与自训练)
spring boot·后端·opencv
山烛14 小时前
OpenCV:人脸识别实战,3 种算法(LBPH/EigenFaces/FisherFaces)代码详解
opencv·算法·计算机视觉·人脸识别·lbph·eigenfaces·fisherfaces
Data_IT_Farmer15 小时前
阿里云服务器ECS上安装anaconda(jupyter)和OpenCV教程
opencv·jupyter·anaconda·ecs·云服务器
dlraba80216 小时前
OpenCV 实战:轻松实现摄像头人脸识别与微笑检测
人工智能·opencv·计算机视觉
RIDDLE!17 小时前
Visual Studio使用C++配置OpenCV环境,同时添加模板以4.12为例
c++·opencv·visual studio
dlraba80218 小时前
dlib 实战:人脸检测、关键点定位与疲劳检测的全流程实现
图像处理·opencv·计算机视觉