【opencv】轮廓相关

IplImage* contours_rect;

IplImage* contours;

CvMemStorage* countours_storage=NULL;

    if(contours_rect==NULL)

    {

        contours_rect=cvCreateImage(cvSize(video_width,video_height),IPL_DEPTH_8U,1);

    }

    if(contours==NULL)

    {

        contours=cvCreateImage(cvSize(video_width,video_height),IPL_DEPTH_8U,1);

    }else{

        memcpy(contours->imageData,fgedge->imageData,fgedge->height*fgedge->width);

    }

    if(countours_storage==NULL)

    {

        countours_storage=cvCreateMemStorage(0);

    }else{

        cvClearMemStorage(countours_storage);

    }

    CvSeq* firstContour=NULL;

    int contours_num=cvFindContours(contours,countours_storage,&firstContour);  //查找所有轮廓

    cvZero(contours); //图像置为全黑

    CvSeq* contourlonger=NULL;  //虽然赋值为NULL 但是实际上不是的

    CvSeq* temp=NULL;

    int n_contours=0;

    for(;firstContour->h_next!=NULL;firstContour=firstContour->h_next)

    {

        double contours_length=cvContourPerimeter(firstContour);  //获取每个轮廓的长度信息

        double contours_area=cvContourArea(firstContour);         //获取每个轮廓的面积值

        //cout<<contours_length<<endl;

        if(contours_length>9&&contours_length<300&&contours_area>5/*&&contours_length/contours_area<4*/)  //根据长度面积信息挑选符合条件的序列重组

        {    

            if(n_contours==0)

            {

                temp=cvCloneSeq(firstContour);  //直接等于会使原来的序列被破坏

                contourlonger=temp;

            }else{

                temp->h_next=cvCloneSeq(firstContour);

                temp=temp->h_next;

            }

            n_contours++;

        }



    }

    

    if(contourlonger)

    {

        cvDrawContours(contours,contourlonger,cvScalarAll(255),cvScalarAll(255),1);//第5个参数-1表示采用填充的方式

    }

    cvShowImage("Contours",contours);





    //获取边界框

    memcpy(contours_rect->imageData,contours->imageData,fgedge->height*fgedge->width);

    if(contourlonger!=NULL)

    {

    for(;contourlonger->h_next!=NULL;contourlonger=contourlonger->h_next)

    {

        //得到不一定平行于图片的最小面积矩形框

        CvBox2D contours_box=cvMinAreaRect2(contourlonger);

        CvPoint2D32f point4[4];

        cvBoxPoints(contours_box,point4); //得到contours_box四个角的坐标

        CvPoint pt[4];

        for(int i=0;i<4;i++)

            pt[i]=cvPoint((int)point4[i].x,point4[i].y);

        CvPoint* ppt=pt;

        int count=4;

        cvPolyLine(contours_rect,&ppt,&count,1,1,cvScalarAll(127),1);

        //下面得到的是平行于图片的矩形框

        //CvRect contours_boundary=cvBoundingRect(contourlonger); //这样得到的矩形坐标和长宽都是0 不知道为什么

        //cvRectangle(contourlonger,cvPoint(contours_boundary.x,contours_boundary.y),cvPoint(contours_boundary.x+contours_boundary.width,contours_boundary.y+contours_boundary.height),cvScalarAll(255));

    }

    }

    cvShowImage("Contours_boundary",contours_rect);

我已经通过其他方法提取了轮廓 用OPENCV的函数查找更完整的轮廓 并且根据轮廓的长度和面积信息将轮廓序列做一个选择性处理 最后画出外接矩形框。

 

在对轮廓做选择性处理的时候 发现虽然新建CvSeq* 赋值为了NULL 但实际上不是的 它本身有一个地址值 因此 不能通过(指针!=NULL )来初始化第一个序列 因此引入了n_contours。 CvCloneSeq函数也仅仅是复制当前的序列,它的前驱和后继是没有被复制过来的,需要每一次都使用复制函数。

first  3    5    2    9    1    7    8    2        设序列长度   //若只要大于5的

     ---》---》---》--》-》--》--》---》

temp:clone(5)-->clone(9)--->clone(7)-->clone(8)-->NULL

               ↑

         contours :指向新建的头指针

你可能感兴趣的:(opencv)