zoukankan      html  css  js  c++  java
  • 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
    ", 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++;  
            }  
    
            cvShowImage("img_contour", img_8uc3);  
            //显示目前已绘制的轮廓图像  
    
            printf("Finished all contours. Hit ESC to finish
    ");  
    
            while (cvWaitKey() != 27);  
    
            cvReleaseImage(&img_edge);  
            cvReleaseImage(&img_8uc3);  
        }  
        cvDestroyWindow("img_contour");  
        cvReleaseImage(&img_8uc1);  
        return 0;  
    }  

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

  • 相关阅读:
    电机调速作业
    迟到的大作业模块分析
    PLC梯形图设计
    电机随笔
    好难
    电机随笔(三)
    电机随笔(二)
    电机随笔 (一)
    机电传动控制直流调速作业
    机电传动控制大作业第一阶段
  • 原文地址:https://www.cnblogs.com/betterwgo/p/6561445.html
Copyright © 2011-2022 走看看