关于opencv中的CvChain 结构

   今天本来想写一个图像椭圆拟合的,使用到opencv库。主要想借助opencv里的cvFindContours函数先得到图像中的所有轮廓,接着对每一个contours->h_next 进行下面的同样操作。contours这个变量是CvSeq 类型的,是opencv中一个基础的动态库。我原本打算将contours这个序列转化得到该轮廓各点所在的位置,即将contours 装换成CvPoint 类型的变量,得到轮廓所有的点之后好进一步对它们进行椭圆的拟合。拟合的函数是通过一个cvFitEllipse2(CvArr* points) 这个函数来的。当我直接将contours(CvSeq)作为参数时,编译器当然不给通过,毕竟接受的参数类型不一致。
   但是想到opencv里面有一个cvDrawContours 的函数,它的作用就是画轮廓图的。那么,它在画的时候,势必要获得轮廓像素所在的位置,因此,就查找opencv源代码,该函数在一个\src\cvcore\cxdrawing.cpp的文件中实现。实现如下:

.......

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::Point pt = ((CvChain*)contour)->origin; //!!!!!!!!这里就是将contours转换为points的
        cv::Point 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;
            }

……..

上面标注的CvChain 结构在opencv的帮助文档中并没有找得到,好吧,在代码中继续追踪它的定义所在,CvChain 的结构定义如下:

typedef struct CvChain
{

CV_SEQUENCE_FIELDS()   /*这一部分的定义和CvSeq 结构的定义相同*/
CvPoint  origin;          /*!!!!此处的origin 变量就是轮廓开始的点*/

}
CvChain;

因此从功能上来说,CvChain 结构不如说是CvSeq ”派生“来的(但是C中没有面向对象的概念),但此处的定义与继承或派生相似,姑且可以这么看吧。

  当然,origin变量记录的只是一条轮廓的开始位置,并不包含全部的轮廓像素的位置信息!要想获取得到全部位置,还得另想办法。能想到的办法就是利用种子生长相似的原理,使用8-邻域对头像素追宗,但似乎花费稍微高了点。

你可能感兴趣的:(opencv,CvChain,contour,拟合)