OpenCV制作自己的线性滤镜
目标
在本教程中,您将学习如何:
- 使用OpenCV函数cv :: filter2D创建自己的线性过滤器。
理论
- 注意
- 下面的解释属于Bradski和Kaehler 的“ 学习OpenCV ”一书。
关联
在非常一般的意义上,相关性是图像的每个部分和运算符(内核)之间的操作。
什么是内核?
内核本质上是固定大小的数字系列数组,以及该阵列中的一个锚点,通常位于中心。
与内核的关联如何工作?
假设您想知道图像中特定位置的结果值。相关值的计算方式如下:
- 将内核锚放置在确定的像素的顶部,其余核心覆盖图像中的相应局部像素。
- 将内核系数乘以相应的图像像素值并对结果求和。
- 将结果放置在输入图像中锚点的位置。
- 通过在整个图像上扫描内核来重复所有像素的过程。
以方程式的形式表达上述程序,我们将具有:
幸运的是,OpenCV为您提供了函数cv :: filter2D,因此您不必对所有这些操作进行编码。
Code
- 这个程序是做什么的?
- 加载图像
- 执行标准化的盒式过滤器。例如,对于的内核,内核将是:size=3,
该程序将使用大小为3,5,7,9和11的内核执行过滤操作。
- 过滤器输出(每个内核)将在500毫秒内显示
2. 教程代码如下所示。您也可以从这里下载
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int main ( int argc, char** argv )
{
Mat src, dst;
Mat kernel;
Point anchor;
double delta;
int ddepth;
int kernel_size;
const char* window_name = "filter2D Demo";
String imageName("../data/lena.jpg"); // by default
if (argc > 1)
{
imageName = argv[1];
}
src = imread( imageName, IMREAD_COLOR ); // Load an image
if( src.empty() )
{ return -1; }
anchor = Point( -1, -1 );
delta = 0;
ddepth = -1;
int ind = 0;
for(;;)
{
char c = (char)waitKey(500);
if( c == 27 )
{ break; }
kernel_size = 3 + 2*( ind%5 );
kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size);
filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT );
imshow( window_name, dst );
ind++;
}
return 0;
}
Explanation
说明
- 加载图像
String imageName("../data/lena.jpg"); // by default
if (argc > 1)
{
imageName = argv[1];
}
src = imread( imageName, IMREAD_COLOR ); // Load an image
if( src.empty() )
{ return -1; }
- 初始化线性滤波器的参数
anchor = Point(-1,-1);
delta = 0;
ddepth = -1;
- 执行无限循环更新内核大小,并将我们的线性滤波器应用于输入图像。我们来详细分析一下:
- 首先我们定义我们的过滤器将要使用的内核。这里是:
kernel_size = 3 + 2*( ind%5 );
kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size);
第一行是将kernel_size更新为在范围内的奇数值:[3,11]。第二行实际上通过将其值设置为1′s 填充矩阵并通过将其除以元素数量进行规范化来构建内核。
- 设置内核后,我们可以使用函数cv :: filter2D来生成过滤器:
参数表示:
- src:源图像
- dst:目的地图像
- ddepth:深度dst。负值(如−1)表示深度与源相同。
- 内核:要通过图像扫描的内核
- anchor:锚点相对于其内核的位置。位置点(-1,-1)表示默认的中心。
- delta:在关联期间要添加到每个像素的值。默认情况下为0
- BORDER_DEFAULT:我们默认设置此值(以下教程中有更多详细信息)
- 我们的方案将实行一个而循环,每500毫秒我们的过滤器的内核大小的范围进行更新显示。
结果
- 在编译上面的代码之后,可以执行它作为参数作为图像的路径。结果应该是一个窗口,显示由归一化过滤器模糊的图像。每个0.5秒的内核大小应该改变,从下面的一系列快照可以看出: