/*
我本人感觉例程有误,下面是修改后的英文(如:max_level)和例程,
运行时按住除ESC 键以外任意一个按键,可观察到轮廓从下往上的顺序
依次画出。外部轮廓为红色,内部轮廓为蓝色。
效果图:
我本人感觉例程有误,下面是修改后的英文(如:max_level)和例程,
运行时按住除ESC 键以外任意一个按键,可观察到轮廓从下往上的顺序
依次画出。外部轮廓为红色,内部轮廓为蓝色。
*/
/**
In this example, we find contours on an input image and then proceed to draw them
one by one. This is a good example to play with yourself and see what effects result from
changing either the contour finding mode (CV_RETR_LIST in the code) or the max_level
that is used to draw the contours (0 in the code). If you set max_level to a larger number,
notice that the example code steps through the contours returned by cvFindContours()
by means of h_next. Thus, for some topologies (CV_RETR_TREE, CV_RETR_CCOMP, etc.), you
may see the same contour more than once as you step through. See Example 8-3.
Example 8-3. Finding and drawing contours on an input image
*/
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "stdio.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)
int main()
{
IplImage* img_8uc1 = NULL;
cvNamedWindow("img_contour", CV_WINDOW_AUTOSIZE);
if (img_8uc1 = cvLoadImage("lena.jpg", 0))
//CV_LOAD_IMAGE_GRAYSCALE == 0 加载lena.jpg 灰度图
{
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)
{ //从第一个轮廓开始遍历,直到所有轮廓都遍历结束
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("%d elements:\n", c->total);
//输出构成目前轮廓点的个数
for (int i=0; i<c->total; i++)
{
CvPoint* p = CV_GET_SEQ_ELEM(CvPoint, c, i);
//查找轮廓序列中索引所指定的点,并返回指向该点的指针
printf(" (%d, %d)\n", p->x, p->y);
//输出该点坐标
}
if (cvWaitKey() == 27)
//按下ESC 键退出循环
break;
n++;
}
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;
}