opencv函数源码之腐蚀

形态学处理最基本的操作是腐蚀和膨胀,所以研究一下opencv的这两个基本操作,路径:D:\OpenCV\opencv\sources\modules\imgproc\src\morph.cpp中,由于腐蚀和膨胀的基本程序流程一样,在这里着重看一下cv::erode()函数

void cv::erode( InputArray src, OutputArray dst, InputArray kernel,
                Point anchor, int iterations,
                int borderType, const Scalar& borderValue )
{
    //调用opencv的函数morphOp并设置参数为MORPH_ERODE
    morphOp( MORPH_ERODE, src, dst, kernel, anchor, iterations, borderType, borderValue ); //见补充一
}
//===================补充一=================//
static void morphOp( int op, InputArray _src, OutputArray _dst,
                     InputArray _kernel,
                     Point anchor, int iterations,
                     int borderType, const Scalar& borderValue )
{
    Mat kernel = _kernel.getMat(); //转化为Mat类型的结构元(核)
    Size ksize = kernel.data ? kernel.size() : Size(3,3); //获取结构元的大小(默认3X3)
    anchor = normalizeAnchor(anchor, ksize); //归一化结构元内核

    CV_Assert( anchor.inside(Rect(0, 0, ksize.width, ksize.height)) );

#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
    if( IPPMorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue) )
        return;
#endif

    Mat src = _src.getMat();

    _dst.create( src.size(), src.type() );
    Mat dst = _dst.getMat();

    if( iterations == 0 || kernel.rows*kernel.cols == 1 )
    {
        src.copyTo(dst);
        return;
    }

    if( !kernel.data )
    {   
        //当结构元没有数据时,生成矩形的结构元,大小为3X3,中点为(1,1)
        kernel = getStructuringElement(MORPH_RECT, Size(1+iterations*2,1+iterations*2));
        anchor = Point(iterations, iterations);
        iterations = 1;
    }
    else if( iterations > 1 && countNonZero(kernel) == kernel.rows*kernel.cols )
    {
        anchor = Point(anchor.x*iterations, anchor.y*iterations);
        kernel = getStructuringElement(MORPH_RECT,
                                       Size(ksize.width + (iterations-1)*(ksize.width-1),
                                            ksize.height + (iterations-1)*(ksize.height-1)),
                                       anchor);
        iterations = 1;
    }

    int nStripes = 1;
#if defined HAVE_TEGRA_OPTIMIZATION
    if (src.data != dst.data && iterations == 1 &&  //NOTE: threads are not used for inplace processing
        (borderType & BORDER_ISOLATED) == 0 && //TODO: check border types
        src.rows >= 64 ) //NOTE: just heuristics
        nStripes = 4;
#endif

    parallel_for_(Range(0, nStripes),
                  MorphologyRunner(src, dst, nStripes, iterations, op, kernel, anchor, borderType, borderType, borderValue)); //见补充二,Range(0, nStripes)运算符重载如下:

    //Ptr<FilterEngine> f = createMorphologyFilter(op, src.type(),
    //                                             kernel, anchor, borderType, borderType, borderValue );

    //f->apply( src, dst );
    //for( int i = 1; i < iterations; i++ )
    //    f->apply( dst, dst );
}
//======================见补充二======================//
class MorphologyRunner : public ParallelLoopBody
{
public:
    //构造函数
    MorphologyRunner(Mat _src, Mat _dst, int _nStripes, int _iterations,
                     int _op, Mat _kernel, Point _anchor,
                     int _rowBorderType, int _columnBorderType, const Scalar& _borderValue) :
        borderValue(_borderValue)
    {
        src = _src;
        dst = _dst;

        nStripes = _nStripes;
        iterations = _iterations;

        op = _op;
        kernel = _kernel;
        anchor = _anchor;
        rowBorderType = _rowBorderType;
        columnBorderType = _columnBorderType;
    }
    
    void operator () ( const Range& range ) const
    {
        int row0 = min(cvRound(range.start * src.rows / nStripes), src.rows);
        int row1 = min(cvRound(range.end * src.rows / nStripes), src.rows);

        /*if(0)
            printf("Size = (%d, %d), range[%d,%d), row0 = %d, row1 = %d\n",
                   src.rows, src.cols, range.start, range.end, row0, row1);*/

        Mat srcStripe = src.rowRange(row0, row1);
        Mat dstStripe = dst.rowRange(row0, row1);

        Ptr<FilterEngine> f = createMorphologyFilter(op, src.type(), kernel, anchor,
                                                     rowBorderType, columnBorderType, borderValue );  //调用滤波器引擎

        f->apply( srcStripe, dstStripe );
        for( int i = 1; i < iterations; i++ )
            f->apply( dstStripe, dstStripe );
    }

private:
    Mat src;
    Mat dst;
    int nStripes;
    int iterations;

    int op;
    Mat kernel;
    Point anchor;
    int rowBorderType;
    int columnBorderType;
    Scalar borderValue;
};


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值