OpenCV中文网站

 找回密码
 立即注册
搜索
热搜: 安装 配置
查看: 7160|回复: 0

关于轮廓的遍历,有谁能解释下cvDrawContours函数及相关的数

[复制链接]
发表于 2013-8-7 09:35:39 | 显示全部楼层 |阅读模式
下面代码1能够覆盖所有轮廓,但是代码2当出现多个环套接在一起(类似箭靶子的样子)时,就不能把内部的轮廓遍历到
代码1,原版opencv的cvDrawContours函数:
CV_IMPL void
cvDrawContours( void* _img, CvSeq* contour,
                CvScalar _externalColor, CvScalar _holeColor,
                int  maxLevel, int thickness,
                int line_type, CvPoint _offset )
{
    CvSeq *contour0 = contour, *h_next = 0;
    CvTreeNodeIterator iterator;
    cv::vector<cv:olyEdge> edges;
    cv::vector<cv:oint> pts;
    cv::Scalar externalColor = _externalColor, holeColor = _holeColor;
    cv::Mat img = cv::cvarrToMat(_img);
    cv:oint offset = _offset;
    double ext_buf[4], hole_buf[4];

    if( line_type == CV_AA && img.depth() != CV_8U )
        line_type = 8;

    if( !contour )
        return;

    CV_Assert( thickness <= 255 );

    scalarToRawData( externalColor, ext_buf, img.type(), 0 );
    scalarToRawData( holeColor, hole_buf, img.type(), 0 );

    maxLevel = MAX(maxLevel, INT_MIN+2);
    maxLevel = MIN(maxLevel, INT_MAX-1);
   
    if( maxLevel < 0 )
    {
        h_next = contour->h_next;
        contour->h_next = 0;
        maxLevel = -maxLevel+1;
    }

    cvInitTreeNodeIterator( &iterator, contour, maxLevel );
    while( (contour = (CvSeq*)cvNextTreeNode( &iterator )) != 0 )
    {
        CvSeqReader reader;
        int i, count = contour->total;
        int elem_type = CV_MAT_TYPE(contour->flags);
        void* clr = (contour->flags & CV_SEQ_FLAG_HOLE) == 0 ? ext_buf : hole_buf;

        cvStartReadSeq( contour, &reader, 0 );
        if( thickness < 0 )
            pts.resize(0);

        if( CV_IS_SEQ_CHAIN_CONTOUR( contour ))
        {
            cv:oint pt = ((CvChain*)contour)->origin;
            cv:oint prev_pt = pt;
            char prev_code = reader.ptr ? reader.ptr[0] : '\0';

            prev_pt += offset;

            for( i = 0; i < count; i++ )
            {
                char code;
                CV_READ_SEQ_ELEM( code, reader );

                assert( (code & ~7) == 0 );

                if( code != prev_code )
                {
                    prev_code = code;
                    if( thickness >= 0 )
                        cv::ThickLine( img, prev_pt, pt, clr, thickness, line_type, 2, 0 );
                    else
                        pts.push_back(pt);
                    prev_pt = pt;
                }
            
                pt.x += CodeDeltas[(int)code][0];
                pt.y += CodeDeltas[(int)code][1];
            }

            if( thickness >= 0 )
                cv::ThickLine( img, prev_pt,
                    cv:oint(((CvChain*)contour)->origin) + offset,
                    clr, thickness, line_type, 2, 0 );
            else
                cv::CollectPolyEdges(img, &pts[0], (int)pts.size(),
                                     edges, ext_buf, line_type, 0, offset);
        }
        else if( CV_IS_SEQ_POLYLINE( contour ))
        {
            CV_Assert( elem_type == CV_32SC2 );
            cv:oint pt1, pt2;
            int shift = 0;
            
            count -= !CV_IS_SEQ_CLOSED(contour);
            CV_READ_SEQ_ELEM( pt1, reader );
            pt1 += offset;
            if( thickness < 0 )
                pts.push_back(pt1);

            for( i = 0; i < count; i++ )
            {
                CV_READ_SEQ_ELEM( pt2, reader );
                pt2 += offset;
                if( thickness >= 0 )
                    cv::ThickLine( img, pt1, pt2, clr, thickness, line_type, 2, shift );
                else
                    pts.push_back(pt2);
                pt1 = pt2;
            }
            if( thickness < 0 )
                cv::CollectPolyEdges( img, &pts[0], (int)pts.size(),
                                      edges, ext_buf, line_type, 0, cv:oint() );
        }
    }

    if( thickness < 0 )
        cv::FillEdgeCollection( img, edges, ext_buf );

    if( h_next && contour0 )
        contour0->h_next = h_next;
}
代码2,简化的遍历代码:
                ////////////////////////////////////////////////////////////////////////////////////////////
                CvTreeNodeIterator iterator;  
                int iOneTourLength=0;
                CvSeq *contour = contours;
                cvInitTreeNodeIterator(&iterator,contour,3);  
                //把所有轮廓的点收集起来  
                CvSeq* allpointsSeq = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour),  
                sizeof(CvPoint), storage);  
                while( 0 != (contour = (CvSeq*)cvNextTreeNode(&iterator)) ){   
                        //找到一个轮廓就可以用for循环提取里面的点了  
                        //这里遍历CvSeq里面的元素的方法很怪异  
                        iOneTourLength = contour->total;  
                        //给点数组分配空间,记得释放  
                        CvPoint *points = (CvPoint *)malloc(sizeof(CvPoint) * iOneTourLength);   
                        //printf(&quot;seqlength:%d\n&quot;,seqlength);  
                        CvSeqReader reader;  
                        CvPoint pt = cvPoint(0,0);
                        cvStartReadSeq(contour,&reader);  
                        //开始提取  
                        for(int i = 0 ;i < iOneTourLength; i++){  
                                CV_READ_SEQ_ELEM(pt,reader);  
                                points = pt;  
                                cvSeqPush(allpointsSeq,&pt);  
                        }   
                        //把这个轮廓点找出后,就可以用这些点画个封闭线  
                        cvPolyLine(frmIn1, &points, &iOneTourLength, 1, 1, CV_RGB(0,255,0),2 , 8, 0);  
                }  
                ////////////////////////////////////////////////////////////////////////////////////////////
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|OpenCV中文网站

GMT+8, 2024-4-19 03:14 , Processed in 0.009881 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表