图片解析:
原图:
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;
}
效果: