滤波器的种类有很多, 在新版本的OpenCV中,提供了如下五种常用的图像平滑处理操作方法,且他们分别被封装在单独的函数中,使用起来非常方便:
· 方框滤波——boxblur函数
· 均值滤波——blur函数
· 高斯滤波——GaussianBlur函数
· 中值滤波——medianBlur函数
· 双边滤波——bilateralFilter函数
本文主要以blur展开解析:
CV_EXPORTS_W void blur( InputArray src, OutputArray dst,
Size ksize, Point anchor=Point(-1,-1),
int
· 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
· 第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
· 第三个参数,Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
· 第四个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
· 第五个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT
borderType参数解析如下:
/*
Various border types, image boundaries aredenoted with '|'
* BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh
* BORDER_REFLECT: fedcba|abcdefgh|hgfedcb
* BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba
* BORDER_WRAP: cdefgh|abcdefgh|abcdefg
* BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i'
*/
根据borderInterpolate可知其只支持上面五种边缘插值方法,上面的插值按照右边的字符串很形象的表示了。
在OpenCV滤波算法中,有两个非常重要的基本工具函数,copyMakeBorder和borderInterpolate
void copyMakeBorder( const Mat& src,Mat& dst,int top, int bottom, int left, int right,
int borderType, const Scalar& value=Scalar() );
源码在utils.cpp中
功能
扩充src的边缘,将图像变大,然后以各种外插方式自动填充图像边界,这个函数实际上调用了函数cv::borderInterpolate,这个函数最重要的功能就是为了处理边界,比如均值滤波或者中值滤波中,使用copyMakeBorder将原图稍微放大,然后我们就可以处理边界的情况了
// borderInterpolate源码在 filter.cpp里面
BORDER_REPLICATE:复制法,也就是复制最边缘像素。边缘扩大的像素个数根据你的模板大小
BORDER_REFLECT : 对称法,也就是以最边缘像素的边为轴,即该边缘像素会复制一遍
BORDER_REFLECT_101对称法,也就是以最边缘像素为轴,对称,该边缘像素不会复制一遍
BORDER_CONSTANT:常量法:边界填充特点常量,默认为0(没有发现可以修改该值,望补充,MAtlib的可以修改)
BORDER_WRAP:镜像对称复制,但是 blur(Mat(M), tempM, cv::Size(3, 3), Point(-1, -1), BORDER_WRAP);提示错误
根据错误提示你会发现问题来到FilterEngine 类解析——OpenCV图像滤波核心引擎
FilterEngine类是OpenCV关于图像滤波的主力军类,OpenCV图像滤波功能的核心引擎。各种滤波函数比如blur, GaussianBlur,到头来其实是就是在函数末尾处定义了一个Ptr
这个类可以把几乎是所有的滤波操作施加到图像上。它包含了所有必要的中间缓存器。有很多和滤波相关的create系函数的返回值直接就是Ptr
源码解析BORDER_WRAP在blur(Mat(M), tempM, cv::Size(3, 3), Point(-1, -1), BORDER_WRAP)里面使用错误:
http://www.opencv.org.cn/opencvdoc/2.3.2/html/modules/imgproc/doc/filtering.html?highlight=filterengine#filterengine
void init(const Ptr& _filter2D,
const Ptr& _rowFilter,
const Ptr& _columnFilter,
int srcType, int dstType, int bufType,
int _rowBorderType = BORDER_REPLICATE, int _columnBorderType = -1,
const Scalar& _borderValue = Scalar());
发现init函数出现如下代码:
if (_columnBorderType < 0)
_columnBorderType = _rowBorderType;
rowBorderType = _rowBorderType;
columnBorderType = _columnBorderType;
CV_Assert(columnBorderType != BORDER_WRAP);
Blur()源码在opencv目录下面
E:\opencv\sources\modules\imgproc\src
filter.cpp
smooth.cpp
最后送各种模板边缘插值测试程序一枚:#include "stdafx.h"
#include
#include
#include
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector vecortImg(9);
CvMat* M = cvCreateMat(3, 3, CV_64FC1);
double num =-1;
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
cvmSet(M, i, j, ++num);
cout << num <<" ";
vecortImg.at(i*3+j) = num;//因为滤波的不同导致的不同呀…………
}
cout << endl;
}
//! various border interpolation methods
/*
Various border types, image boundaries are denoted with '|'
* BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh
* BORDER_REFLECT: fedcba|abcdefgh|hgfedcb
* BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba
* BORDER_WRAP: cdefgh|abcdefgh|abcdefg
* BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i'
*/
cout <<"平滑后"< markdata1;
int row = hh.rows ;
int col = hh.cols;
double* pMatdata = (double*)hh.data;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++){
cout << *(pMatdata + i * 3 + j)<<" ";
markdata1.push_back(*(pMatdata + i*3+j));
}
cout << endl;
}
cvReleaseMat(&M);
system("PAUSE");
return 0;
}