使用 OpenCV 自定义线性滤波器教程
目标
在本教程中,您将学习如何使用 OpenCV 函数创建您自己的线性过滤器,并理解其背后的数学原理。
理论
相关性与卷积
从非常一般的意义上讲,相关性是图像的每个部分与运算符(内核)之间的操作。在图像处理中,我们通常使用卷积或相关运算来提取特征或进行平滑处理。
什么是内核?
内核本质上是一个固定大小的数值系数数组,以及该数组中的锚点。该锚点通常位于中心,决定了计算时相对于当前像素的位置。
与内核的关联是如何工作的?
假设您想知道图像中特定位置的结果值。相关性的值按以下方式计算:
- 将内核锚点放在确定像素的顶部,内核的其余部分覆盖图像中相应的局部像素。
- 将核系数乘以相应的图像像素值,然后对结果求和。
- 将结果放置在输入图像中的定位点位置。
- 通过扫描整个图像的内核来对所有像素重复该过程。
以方程式的形式表示上述过程,我们将得到: $$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)$$
幸运的是,OpenCV 为您提供了函数 filter2D,因此您不必编写所有这些底层操作。
程序功能概述
本示例程序将演示以下功能:
- 加载图像:读取本地图片文件。
- 执行规范化的框筛选器:例如,对于大小为 $size = 3$ 的内核,内核为全 1 矩阵除以元素个数。
- 动态调整内核大小:程序将使用大小为 3、5、7、9 和 11 的内核依次执行过滤器操作。
- 实时显示:过滤器输出将在窗口中每 500 毫秒更新一次。
C++ 代码实现
以下是完整的 C++ 代码示例。请确保您的开发环境已正确配置 OpenCV。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// 声明变量
Mat src, dst;
int anchor = -1;
double delta = 0;
int ddepth = -1;
int kernel_size;
* window_name = ;
* imageName = (argc >= ) ? argv[] : ;
src = (imageName, IMREAD_COLOR);
(src.())
{
();
();
EXIT_FAILURE;
}
anchor = ;
delta = ;
ddepth = ;
ind = ;
()
{
kernel_size = + * (ind % );
Mat kernel = Mat::(kernel_size, kernel_size, CV_32F) / ()(kernel_size * kernel_size);
(src, dst, ddepth, kernel, (anchor, anchor), delta, BORDER_DEFAULT);
(window_name, dst);
c = ();
(c == )
{
;
}
ind++;
}
EXIT_SUCCESS;
}


