OpenCV笔记(三)——线性滤波
对像素(i, j)做线性滤波的方法:
1. 做一个3X3的矩阵,分别赋予(i, j)和它的4邻域和D邻域相应的权值。
2. 计算。
示例代码如下:
1 void Sharpen(const Mat& myImage,Mat& Result) 2 { 3 CV_Assert(myImage.depth() == CV_8U); // accept only uchar images 4 5 const int nChannels = myImage.channels(); 6 Result.create(myImage.size(),myImage.type()); 7 8 for(int j = 1 ; j < myImage.rows-1; ++j) 9 { 10 const uchar* previous = myImage.ptr<uchar>(j - 1); 11 const uchar* current = myImage.ptr<uchar>(j ); 12 const uchar* next = myImage.ptr<uchar>(j + 1); 13 14 uchar* output = Result.ptr<uchar>(j); 15 16 for(int i= nChannels;i < nChannels*(myImage.cols-1); ++i) 17 { 18 *output++ = saturate_cast<uchar>(5*current[i] 19 -current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]); 20 } 21 } 22 23 Result.row(0).setTo(Scalar(0)); 24 Result.row(Result.rows-1).setTo(Scalar(0)); 25 Result.col(0).setTo(Scalar(0)); 26 Result.col(Result.cols-1).setTo(Scalar(0)); 27 }
第10行、11行、12行分别使用指针指向上一行、当前行、下一行。
第18行就是对当前像素进行滤波操作。滤波的矩阵为(0, -1, 0,
-1, 5, -1,
0, -1, 0)
函数当中使用ptr<uchar>方法,返回指向某行的指针,用来遍历当前行的每个字节,而非像素。
另外,第18行中使用了saturate_cast<uchar>这个模板函数,它重新包装了C++当中的类型转换,当左边的值的范围不足以接收右边的值的范围的时候,这个转换并非简单地截断位数,而是选择最接近的合法值。
第23行,row(0)和col(0)分别返回第0行和第0列的所有元素构成的Mat。
setTo(Scalar(0))方法调用,将调用它的Mat所有元素设为Scalar(0)。
OpenCV实现了线性滤波的方法:filter2D。
1 Mat kern = (Mat_<char>(3,3) << 0, -1, 0, 2 -1, 5, -1, 3 0, -1, 0); 4 t = (double)getTickCount(); 5 filter2D(I, K, I.depth(), kern ); /* 其中I是输入的Mat,K是输出的Mat*/
filter2D的声明为
C++: void filter2D(InputArray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor=Point(-1,-1), double delta=0, intborderType=BORDER_DEFAULT )
前面四个参数都很清楚了。
第五个参数anchor是中心点在kernel矩阵中的相对位置。可能有点抽象,看下面这个式子,就清楚anchor了:
第六个参数delta,是在将结果保存至dst之前,加上一个常数。
第七个参数borderType,暂时没看是什么。