在黑色背景上画一个半径为200白色的圆,理论上其周长应该为2π*200≈1267 。检测该图像的轮廓,计算轮廓的长度;然后分别使用1/90,1/66,1/11,1/10,1/2,1,3作为精度参数,使用cvApproxPoly()逼近,计算轮廓长度。
#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)
/*cvApproxPoly()的精度*/
double parameter[] = { 1.0/90, 1.0/66, 1.0/11, 1.0/10, 1.0/2, 1.0, 3.0 };
//*****************************************************
//主函数
//*****************************************************
int main()
{
/*用cvCreateMat函数建立一个CvMat格式、500行*500列、单通道8位unsigned型的矩阵mat,返回一个指向CvMat结构体的指针*/
CvMat* mat = cvCreateMat( 500, 500, CV_8UC1 );
cvZero(mat);
/*使用画圆函数,在mat矩阵上画一个圆心在点(250,250),半径为200,颜色为白色的一个圆*/
cvCircle( mat, cvPoint(250,250), 200, cvScalarAll(255), 2, 8 );
/*阈值化,转换为二值图像*/
IplImage* img = (IplImage*)mat;
cvThreshold( img, img, 100, 255, CV_THRESH_BINARY );
/*将矩阵强制转换并输出*/
cvNamedWindow( "homework_8-5", CV_WINDOW_AUTOSIZE );
cvShowImage( "homework_8-5", img );
/*画出轮廓*/
CvMemStorage* storage1 = cvCreateMemStorage(0);
CvSeq* contours = NULL;
/*在img_edge中找出轮廓存储于storage中,轮廓序列首地址为first_contour,返回值为检测到的轮廓数值number_of_contours*/
IplImage* img_contour = cvCreateImage( cvGetSize(img), 8, 3 );
cvZero( img_contour );
cvNamedWindow( "img_contour", CV_WINDOW_AUTOSIZE );
int num_c = cvFindContours( img, storage1, &contours, sizeof(CvContour), CV_RETR_LIST );
printf( "Total Contours Detected: %d\n", num_c );
int n = 0;
for (CvSeq* c=contours; c!=NULL; c=c->h_next)
{
/*在img_contour图像上以红色画出轮廓,以蓝色画出孔*/
cvDrawContours( img_contour, c, CVX_RED, CVX_BLUE, 1, 2, 8 );
cvShowImage( "img_contour", img_contour );
/*打印出轮廓序数,以及该轮廓所含有的数据个数*/
printf( "Contour #%d: ", n );
printf( "elements: %d\n", c->total );
/*计算并打印周长*/
double len = cvContourPerimeter(c);
printf( "perimeter: %f\n\n", len );
n++;
}
/*计算多边形逼近时的轮廓点数并打印*/
CvMemStorage* storage2 = cvCreateMemStorage(0);
for (int i = 0; i<7; i++)
{
contours = cvApproxPoly( contours, sizeof(CvContour), storage2, CV_POLY_APPROX_DP, parameter[i], 0 );
printf( "Approximately Poly Contours: %d, Parameter: %f\n", contours->total, parameter[i] );
}
/*释放内存,销毁窗口*/
cvWaitKey(0);
cvReleaseMat( &mat );
cvReleaseImage( &img_contour );
cvDestroyWindow( "homework_8-5" );
return 0;
}