cvFindContours函数

 

cvFindContours函数:
int cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour,
int header_size=sizeof(CvContour), int mode=CV_RETR_LIST,
int method=CV_CHAIN_APPROX_SIMPLE, CvPoint offset=cvPoint(0,0) );
image:
  8比特单通道的源二值图像。非零像素作为1处理,0像素保存不变。从一个灰度图像得到二值图像的函数有:cvThreshold,cvAdaptiveThreshold和cvCanny。
storage:返回轮廓的容器。
first_contour:
  输出参数,用于存储指向第一个外接轮廓。
header_size:
  header序列的尺寸.如果选择method = CV_CHAIN_CODE, 则header_size >= sizeof(CvChain);其他,则 header_size >= sizeof(CvContour)。
mode:
  CV_RETR_EXTERNAL:只检索最外面的轮廓;
  CV_RETR_LIST:检索所有的轮廓,并将其放入list中;
  CV_RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
  CV_RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次。

   蓝色表示v_next,绿色表示h_next
method:
  边缘近似方法(除了CV_RETR_RUNS使用内置的近似,其他模式均使用此设定的近似算法)。可取值如下:
  CV_CHAIN_CODE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
  CV_CHAIN_APPROX_NONE:将所有的连码点,转换成点。
  CV_CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。
  CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS:使用the flavors of Teh-Chin chain近似算法的一种。
  CV_LINK_RUNS:通过连接水平段的1,使用完全不同的边缘提取算法。使用CV_RETR_LIST检索模式能使用此方法。
offset:
  偏移量,用于移动所有轮廓点。当轮廓是从图像的ROI提取的,并且需要在整个图像中分析时,这个参数将很有用。

我的一个不知道从哪里抄来的栗子:

#include "stdafx.h"

#include "cv.h"
#include "highgui.h"

#define CVX_RED CV_RGB(0xff, 0x00, 0x00)  
#define CVX_GREEN CV_RGB(0x00, 0xff, 0x00)  
#define CVX_BLUE CV_RGB(0x00, 0x00, 0xff)

using namespace cv;

int main()  
{  
    IplImage* img_8uc1 = NULL;  
    cvNamedWindow("img_contour", CV_WINDOW_AUTOSIZE);  

    if (img_8uc1 = cvLoadImage("cv38.jpg", 0))          
    {  
        IplImage* img_edge = cvCreateImage(cvGetSize(img_8uc1), 8, 1);  
        IplImage* img_8uc3 = cvCreateImage(cvGetSize(img_8uc1), 8, 3);  

        cvThreshold(img_8uc1, img_edge, 128, 255, CV_THRESH_BINARY);  
        //对灰度图img_8uc1 像进行阈值操作得到二值图像 img_edge  

        CvMemStorage* storage = cvCreateMemStorage();  
        //创建一个内存储存器 默认为 64K  

        CvSeq* first_contour = NULL;  
        //创建一个动态序列指针,用其指向第一个存储轮廓单元地址  

        int NC = cvFindContours(      
            //cvFindContours从二值图像中检索轮廓,并返回检测到的轮廓的个数  
            img_edge,         
            storage,                //存储轮廓元素的储存容器  
            &first_contour,         //指向第一个输出轮廓  
            sizeof (CvContour),       
            CV_RETR_LIST            //提取所有轮廓,并且放置在 list 中  
            );  

        printf("Total Contours Detected: %d\n", NC);  

        cvCvtColor(img_8uc1, img_8uc3, CV_GRAY2BGR);  
        //色彩空间转换,将img_8uc1 转换为BGR空间,img_8uc3 为转换后结果  

        int n = 0;  
        //用于下面轮廓的记数  
        for (CvSeq* c=first_contour; c!=NULL; c = c->h_next)  
        {   //从第一个轮廓开始遍历,直到所有轮廓都遍历结束  

            CvRect rect = cvBoundingRect(c,1); 

            if (rect.height > 0 && rect.width > 0 )
            {
                if ( (double)rect.height / (double)rect.width > 5 || (double)rect.height / (double)rect.width < 0.2 )
                {
                    continue ;
                }
            }

            if ( cvContourArea(c) < 20 )
            {
                continue ;
            }

            cvDrawContours(  
                img_8uc3,   //用于绘制轮廓的图像  
                c,          //指向目前轮廓所在地址空间  
                CVX_RED,    //外层轮廓颜色  
                CVX_BLUE,   //内层轮廓颜色  
                0,          //等级为0,绘制单独的轮廓  
                1,          //轮廓线条粗细  
                8           //线段类型为(8邻接)连接线  
                );  

            printf("Contour #%d\n", n);  
            //输出第 n 个轮廓  

            n++;  
        }  

        cvShowImage("img_contour", img_8uc3);  
        //显示目前已绘制的轮廓图像  

        printf("Finished all contours. Hit ESC to finish\n");  

        while (cvWaitKey() != 27);  

        cvReleaseImage(&img_edge);  
        cvReleaseImage(&img_8uc3);  
    }  
    cvDestroyWindow("img_contour");  
    cvReleaseImage(&img_8uc1);  
    return 0;  
}  

  代码注释还算仔细,我就不想多写了。

posted @ 2016-10-24 22:11  yeren2046  阅读(2433)  评论(0编辑  收藏  举报