0
点赞
收藏
分享

微信扫一扫

OpenCV学习(26)

图像处理(1):

线性滤波(2):线性滤波相关OpenCV源码剖析

一,OpenCV 中boxFilter函数源码解析;二,FilterEngine类解析:OpenCV图像滤波核心引擎;

三,OpenCV中blur函数源码剖析;

一,OpenCV 中boxFilter函数源码解析

   我们可以在OpenCV的安装路径的\sources\modules\imgproc\src下的smooth.cpp源文件的第711行找到boxFilter函数的源代码。(但是源代码只限于曾经版本的opencv,最新版只有封装好的函数)。

原码如下:

//-----------------------------------【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图像滤波功能的核心引擎,我们有必要详细剖析看其源代码。

二,FilterEngine类解析:OpenCV图像滤波核心引擎

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

   这个类可以把几乎是所有的滤波操作施加到图像上。它包含了所有必要的中间缓存器。有很多和滤波相关的create系函数的返回值直接就是Ptr。比如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);
 
   //如果滤波器可分离,则返回true
boolisSeparable() 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;
};

三,OpenCV中blur函数源码剖析

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

   一起来看一下OpenCV中blur函数定义的真面目:

//-----------------------------------【blur()函数中文注释版源代码】----------------------------
//     代码作用:进行blur均值滤波操作的函数
//     说明:以下代码为来自于计算机开源视觉库OpenCV的官方源代码
//     OpenCV源代码版本:2.4.8
//     源码路径:…\opencv\sources\modules\imgproc\src\smooth.cpp
//     源文件中如下代码的起始行数:738行
//     中文注释by浅墨
//--------------------------------------------------------------------------------------------------------
 
void cv::blur(InputArray src, OutputArray dst,
          Size ksize, Point anchor, int borderType )
{
//调用boxFilter函数进行处理
   boxFilter( src, dst, -1, ksize, anchor, true, borderType );
}

可以看到在blur函数内部就是调用了一个boxFilter函数,且第六个参数为true,即我们上文所说的normalize=true,即均值滤波是均一化后的方框滤波。

举报

相关推荐

0 条评论