现在的位置: 首页 > 综合 > 正文

opencv 图像轮廓

2013年08月29日 ⁄ 综合 ⁄ 共 2426字 ⁄ 字号 评论关闭

图片解析:

原图:

code:

#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <opencv\cxcore.h>
#include <stdlib.h>
#include <stdio.h>
 
int main(int argc, char* argv[]){

#if 1
 
    int i, j;
 

    CvMemStorage* storage = cvCreateMemStorage(0);
	//以单通道方式加载图像
    IplImage* img = cvLoadImage("C:\\Users\\zxl\\Desktop\\0.png",CV_LOAD_IMAGE_GRAYSCALE);
	//常见一个等大小的3通道图像 (作为备份)
    IplImage* imgColor = cvCreateImage(cvGetSize(img),8,3);
	//用来显示轮廓的
	IplImage* contoursImage = cvCreateImage(cvSize(img->width,img->height),8,1);

    CvSeq* contours = 0 , *contoursTemp=0;
    cvZero(contoursImage);

    //对图像进行二值化
    cvThreshold(img,img,100,255,CV_THRESH_BINARY);
 
    //img的备份
    cvCvtColor(img,imgColor,CV_GRAY2BGR);
 

    // 提取图像img的轮廓信息函数 contours指向第一个轮廓 将轮廓存放在CvMemStorage类型的变量storage里面
	//&contours =>表示指针 指向能够提取的第一个轮廓  
	//CV_RETR_CCOMP =>表示轮廓的排列方式 有4种
	//-------------------------------------
	//CV_RETR_EXTERNAL 只返回最外面的轮廓
	//first=c0
	//CV_RETR_CCOMP 把外轮廓用双向链表的方式存放,有顺序 <从里到外><从右到左>
	//frist=c01001 <-> c01000 <-> c010 <-> c000 <-> c0
	//                              |        |      |
	//                            h0100    h0000    h01 <-> h00
	//CV_RETR_LIST 所有的轮廓(无分内外轮廓)通过1个链表的方式存储,<从里到外><从右到左>
	//first=c01001 <-> c01000 <-> h0100 <-> h0000 <-> c010 <-> c000 <-> h01 <-> h00 <-> c0
	//
	//
	//CV_RETR_TREE 按照树形结构存储,
	//first = c0
	//		  |
	//   h00 <->  h01
 	//	  |        |
	//  c000      c010
	//    |        |
	//  h0000   c01000 <-> c01001
	//-------------------------------------
	//CV_CHAIN_APPROX_NONE=> 轮廓显示是坐标的形式还是点的形式
	//提取轮廓后源图像会发生变化 所以需要用到开始生命的备份机制

	/*
	//备份机制检查原图 
	cvNamedWindow( "1");
    cvShowImage( "1", img );
	*/

    int total = cvFindContours( img, storage, &contours, sizeof(CvContour),
                    CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(0,0) );

	/*
	//备份机制检查提取后
	cvNamedWindow( "2");
    cvShowImage( "2", img );
	cvWaitKey(0);
	*/


	//提取指针所指的地方
    contoursTemp = contours ;

    int count=0;
 
    //对轮廓进行循环
	//h_next 表示水平的方向上轮廓链接
	//v_next 表示垂直方向上的轮廓链接
    for(;contoursTemp!=0 ; contoursTemp=contoursTemp->h_next){ //通过这个循环访问每一个轮廓
            //提取外轮廓 上的所以坐标点
            for( i=0; i<contoursTemp->total; i++) {  //通过这个循环 得到坐标
                    CvPoint * pt = (CvPoint*)cvGetSeqElem(contoursTemp, i); // 读出第i个点。
                    //轮廓窗口让其显示为白色
					cvSetReal2D(contoursImage , pt->y , pt->x , 255.0);
                    //在原窗口让其显示为红色
					cvSet2D(imgColor,pt->y,pt->x,cvScalar(0,0,255,0));
            }
            count++;

            //提取内轮廓上的所以坐标点
            CvSeq* InterCon = contoursTemp->v_next;

            for(;InterCon!=0;InterCon=InterCon->h_next){
                    for(i=0;i<InterCon->total;i++) {
                            CvPoint * pt = (CvPoint*)cvGetSeqElem(InterCon, i); // 读出第i个点。
 
                            cvSetReal2D(contoursImage , pt->y , pt->x , 255.0);
                            cvSet2D(imgColor,pt->y,pt->x,cvScalar(0,255,0,0));
                    }
            }
    }
 
    cvNamedWindow( "image", 1 );
    cvShowImage( "image", imgColor );

    cvNamedWindow( "contours");
    cvShowImage("contours",contoursImage);
 
    cvWaitKey(0);
 

    cvReleaseMemStorage( &storage );
    cvReleaseImage( &img );
    cvReleaseImage(&contoursImage);
	cvReleaseImage(&imgColor);
 

#endif


	return 0;
}

 

效果:

抱歉!评论已关闭.