【OpenCV入门教程之八】线性邻域滤波专场:方框滤波、均值滤波与

C++: void GaussianBlur(InputArray src,OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT )

嗯,第一部分的理论介绍大概就是这些了,我们接着进入第二部分,OpenCV的源码剖析。

二、深入——OpenCV源码剖析

上一篇文章中我们已经和当前最新版的OpenCV的源码亲密接触过。 在这一部分中,浅墨将带领大家领略OpenCV的开源魅力,对OpenCV中本篇文章里讲解到线性滤波函数——boxFilter,blur和GaussianBlur函数以及周边的涉及到的源码进行适当的剖析。

这样,我们就可以对 OpenCV有一个更加深刻的理解,成为一个高端大气的OpenCV使用者。

<1>OpenCV中boxFilter函数源码解析

我们可以在OpenCV的安装路径的\sources\modules\imgproc\src下的smooth.cpp源文件的第711行找到boxFilter函数的源代码。对应于浅墨将OpenCV 2.4.8安装在D:\Program Files\opencv的路径下,那么,smooth.cpp文件就在D:\ProgramFiles\opencv\sources\modules\imgproc\src路径下。

//———————————–【boxFilter()函数中文注释版源代码】—————————-//代码作用:进行box Filter滤波操作的函数//说明:以下代码为来自于计算机开源视觉库OpenCV的官方源代码//OpenCV源代码版本:2.4.8//源码路径:…\opencv\sources\modules\imgproc\src\smooth.cpp//源文件中如下代码的起始行数:711行//中文注释by浅墨//——————————————————————————————————–void cv::boxFilter( InputArray _src,OutputArray _dst, int ddepth,Size ksize, Point anchor,bool normalize, int borderType){ Mat src = _src.getMat();//拷贝源图的形参Mat数据到临时变量,用于稍后的操作int sdepth =src.depth(), cn = src.channels();//定义int型临时变量,代表源图深度的sdepth,源图通道的引用cn //处理ddepth小于零的情况 if( ddepth < 0 )ddepth = sdepth; _dst.create( src.size(), CV_MAKETYPE(ddepth, cn) );//初始化目标图Mat dst =_dst.getMat();//拷贝目标图的形参Mat数据到临时变量,用于稍后的操作 //处理 borderType不为 BORDER_CONSTANT 且normalize为真的情况 if( borderType != BORDER_CONSTANT && normalize ) {if( src.rows == 1 )ksize.height = 1;if( src.cols == 1 )ksize.width = 1;} //若之前有过HAVE_TEGRA_OPTIMIZATION优化选项的定义,则执行宏体中的tegra优化版函数并返回#ifdef HAVE_TEGRA_OPTIMIZATION if ( tegra::box(src, dst, ksize, anchor, normalize, borderType) )return;#endif//调用FilterEngine滤波引擎,正式开始滤波操作 Ptr<FilterEngine> f = createBoxFilter( src.type(), dst.type(),ksize, anchor,normalize, borderType ); f->apply( src, dst );}

其中的Ptr是用来动态分配的对象的智能指针模板类。可以发现,函数的内部代码思路是很清晰的,先拷贝源图的形参Mat数据到临时变量,定义一些临时变量,在处理ddepth小于零的情况,接着处理 borderType不为 BORDER_CONSTANT 且normalize为真的情况,最终调用FilterEngine滤波引擎创建一个BoxFilter,正式开始滤波操作。

这里的FilterEngine是OpenCV图像滤波功能的核心引擎,我们有必要详细剖析看其源代码。

<2>FilterEngine类解析——OpenCV图像滤波核心引擎

FilterEngine类是OpenCV关于图像滤波的主力军类,OpenCV图像滤波功能的核心引擎。各种滤波函数比如blur, GaussianBlur,到头来其实是就是在函数末尾处定义了一个Ptr<FilterEngine>类型的f,然后f->apply( src, dst )了一下而已。

这个类可以把几乎是所有的滤波操作施加到图像上。它包含了所有必要的中间缓存器。有很多和滤波相关的create系函数的返回值直接就是Ptr<FilterEngine>。比如cv::createSeparableLinearFilter(),

cv::createLinearFilter(),cv::createGaussianFilter(), cv::createDerivFilter(),

cv::createBoxFilter() 和cv::createMorphologyFilter().,这里给出其中一个函数的原型吧:

Ptr<FilterEngine>createLinearFilter(int srcType, int dstType, InputArray kernel, Point_anchor=Point(-1,-1), double delta=0, int rowBorderType=BORDER_DEFAULT, intcolumnBorderType=-1, const Scalar& borderValue=Scalar() )

上面我们提到过了,其中的Ptr是用来动态分配的对象的智能指针模板类,而上面的尖括号里面的模板参数就是FilterEngine。

使用FilterEngine类可以分块处理大量的图像,构建复杂的管线,其中就包含一些进行滤波阶段。如果我们需要使用预先定义好的的滤波操作,cv::filter2D(), cv::erode(),以及cv::dilate(),可以选择,他们不依赖于FilterEngine,自立自强,在自己函数体内部就实现了FilterEngine提供的功能。不像其他的诸如我们今天讲的blur系列函数,依赖于FilterEngine引擎。

我们看下其类声明经过浅墨详细注释的源码:

//———————————–【FilterEngine类中文注释版源代码】—————————-//代码作用:FilterEngine类,OpenCV图像滤波功能的核心引擎//说明:以下代码为来自于计算机开源视觉库OpenCV的官方源代码//OpenCV源代码版本:2.4.8//源码路径:…\opencv\sources\modules\imgproc\include\opencv2\imgproc\imgproc.hpp//源文件中如下代码的起始行数:222行//中文注释by浅墨//——————————————————————————————————– class CV_EXPORTS FilterEngine{public: //默认构造函数 FilterEngine(); //完整的构造函数。 _filter2D 、_rowFilter 和 _columnFilter之一,必须为非空 FilterEngine(const Ptr<BaseFilter>& _filter2D,constPtr<BaseRowFilter>& _rowFilter,constPtr<BaseColumnFilter>& _columnFilter,int srcType, int dstType, intbufType,int_rowBorderType=BORDER_REPLICATE,int _columnBorderType=-1,const Scalar&_borderValue=Scalar()); //默认析构函数 virtual ~FilterEngine(); //重新初始化引擎。释放之前滤波器申请的内存。 void init(const Ptr<BaseFilter>& _filter2D,constPtr<BaseRowFilter>& _rowFilter,constPtr<BaseColumnFilter>& _columnFilter,int srcType, int dstType, intbufType,int_rowBorderType=BORDER_REPLICATE, int _columnBorderType=-1,const Scalar&_borderValue=Scalar()); //开始对指定了ROI区域和尺寸的图片进行滤波操作 virtual int start(Size wholeSize, Rect roi, int maxBufRows=-1);//开始对指定了ROI区域的图片进行滤波操作 virtual int start(const Mat& src, const Rect&srcRoi=Rect(0,0,-1,-1),bool isolated=false, intmaxBufRows=-1); //处理图像的下一个srcCount行(函数的第三个参数) virtual int proceed(const uchar* src, int srcStep, int srcCount,uchar* dst, intdstStep); //对图像指定的ROI区域进行滤波操作,若srcRoi=(0,0,-1,-1),则对整个图像进行滤波操作 virtual void apply( const Mat& src, Mat& dst,const Rect&srcRoi=Rect(0,0,-1,-1),Point dstOfs=Point(0,0),bool isolated=false);//如果滤波器可分离,则返回trueboolisSeparable() const { return (const BaseFilter*)filter2D == 0; }//返回输入和输出行数 int remainingInputRows() const;intremainingOutputRows() const;//一些成员参数定义 int srcType, dstType, bufType; Size ksize; Point anchor; int maxWidth; Size wholeSize; Rect roi; int dx1, dx2; int rowBorderType, columnBorderType; vector<int> borderTab; int borderElemSize; vector<uchar> ringBuf; vector<uchar> srcRow; vector<uchar> constBorderValue; vector<uchar> constBorderRow; int bufStep, startY, startY0, endY, rowCount, dstY; vector<uchar*> rows;Ptr<BaseFilter> filter2D; Ptr<BaseRowFilter> rowFilter; Ptr<BaseColumnFilter> columnFilter;};

<3>OpenCV中size类型剖析

size类型我们也讲一下,,通过转到定义,我们可以在……\opencv\sources\modules\core\include\opencv2\core\core.hpp路径下,对应于浅墨的OpenCV安装路径,就是在

D:\ProgramFiles\opencv\sources\modules\core\include\opencv2\core\core.hpp下,找到其原型声明:

typedef Size_<int> Size2i;typedef Size2i Size;

Size_ 是个模板类,在这里Size_<int>表示其类体内部的模板所代表的类型为int。

那这两句的意思,就是首先给已知的数据类型Size_<int>起个新名字,叫Size2i。

然后又给已知的数据类型Size2i起个新名字,叫Size。

所以,连起来就是,Size_<int>、Size2i、Size这三个类型名等价。

爱情不是避难所,想进去避难的话,是会被赶出来的。

【OpenCV入门教程之八】线性邻域滤波专场:方框滤波、均值滤波与

相关文章:

你感兴趣的文章:

标签云: