OpenCV入门学习-图像处理(二)

环境:

  • win11 x64
  • OpenCV 4.9.0
  • VS 2022 (v143)
  • C++ (ISO C++ 14 标准)

线性滤波器

涵盖以下内容:

  • 使用OpenCV的cv::filter2D()函数创建自定义线性滤波器
  • 理解图像处理中核(Kernel)的概念及相关运算(Correlation)
  • 实现归一化盒式滤波器(Normalized Box Filter)并观察不同核尺寸的效果

理论基础

相关运算与核

在图像处理中,相关运算(Correlation)是核与图像局部区域进行加权求和的操作。核是一个固定大小的数值矩阵,其中心通常定义为锚点(Anchor Point)。

核的工作流程如下:

  1. 将核的锚点对准图像中的目标像素
  2. 核系数与对应像素值相乘后求和
  3. 将结果写入输出图像的锚点位置
  4. 遍历所有像素完成计算

数学表达式为:
\[ H(x, y) = \sum_{i=0}^{M_i-1} \sum_{j=0}^{M_j-1} I(x + i - a_i, y + j - a_j) K(i, j) \nonumber \]

归一化盒式滤波器

以尺寸为3×3的归一化盒式滤波器为例,核矩阵为:
\[ K = \frac{1}{9} \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix} \nonumber \]
其作用是计算局部像素的平均值,实现图像模糊效果。


代码实现

以下代码展示了如何使用cv::filter2D()实现不同尺寸的归一化盒式滤波器:

#include "opencv2/imgproc.hpp"  
#include "opencv2/imgcodecs.hpp"  
#include "opencv2/highgui.hpp"  

int main(int argc, char** argv) {  
    // 加载图像  
    cv::Mat src = cv::imread(cv::samples::findFile(argc >=2 ? argv[1] : "lena.jpg"));  
    if (src.empty()) {  
        printf("Error opening image\n");  
        return EXIT_FAILURE;  
    }  

    // 初始化参数  
    cv::Mat dst, kernel;  
    cv::Point anchor(-1, -1);  
    double delta = 0;  
    int ddepth = -1;  
    const char* window_name = "filter2D Demo";  

    // 循环应用不同尺寸的核  
    int ind = 0;  
    while (true) {  
        // 核尺寸在[3, 11]范围内按奇数递增  
        int kernel_size = 3 + 2 * (ind % 5);  
        kernel = cv::Mat::ones(kernel_size, kernel_size, CV_32F) / (float)(kernel_size * kernel_size);  

        // 应用滤波器  
        cv::filter2D(src, dst, ddepth, kernel, anchor, delta, cv::BORDER_DEFAULT);  
        cv::imshow(window_name, dst);  

        // 按ESC退出  
        char c = (char)cv::waitKey(500);  
        if (c == 27) break;  

        ind++;  
    }  
    return EXIT_SUCCESS;  
}  

滤波器应用

使用cv::filter2D进行滤波操作:

  • src:输入图像
  • dst:输出图像
  • ddepth:输出图像深度(-1表示与输入一致)
  • kernel:自定义核
  • anchor:核锚点位置(默认中心)
  • delta:输出像素值的额外偏移量


参考资料

[1] OpenCV 官方文档

-------------本文结束 感谢您的阅读-------------