1)CV_Assert():若括号中的表达式值为false,则返回一个错误信息。
函数原型是:#define CV_Assert( expr ) if((expr)) ; else cv::error
( cv::Exception(CV_StsAssert, #expr, "", __FILE__, __LINE__) )
2)cvContourPerimeter:函数作用于一个轮廓并返回其长度。事实上,
这个函数是一个调用通用函数cvArcLength的宏。
double cvArcLength(const void *curve,CvSlice slice =CV_WHOLE_SEQ,
int is_closed=-1);
curve:第一个参数是轮廓,其形式可以是点的序列(CvContour *或CvSeq *)
或任一n*2的点的数组。
slice:表面是否将轮廓视为闭合的一个布尔类型(例如,是否将轮廓的
最后一个点视为和第一个点有连接)。
slice可以让我们只选择曲线(curve)上的点的部分集合。
#define cvContourPerimeter(contour)
cvArcLength(contour,CV_WHOLE_SEQ,1)
代码:
#include
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
int main()
{
cvNamedWindow("ff",1);
string file_full_name = "D:\\VC98\\C++项目\\opencv\\cvContourPerimeter\\cvContourPerimeter\\a4.png";
IplImage * image_source = cvLoadImage(file_full_name.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
CV_Assert(image_source);//若括号中的表达式值为false,则返回一个错误信息。
IplImage * image_binary = cvCloneImage(image_source);
cvZero(image_binary);
//在二值化图像的过程中,阀值很关键,将决定黑白化的效果。
cvThreshold(image_source, image_binary, 205, 255, CV_THRESH_BINARY);//二值化
cvShowImage("ff",image_binary);
CvMemStorage *storage = cvCreateMemStorage();
CvSeq* first_contour=NULL;
int contour_num;
contour_num = cvFindContours(image_binary, storage, &first_contour, sizeof(CvContour), CV_RETR_LIST);//轮廓获取
cout << "轮廓数为:" << contour_num << endl;
double contour_length;
//for (CvSeq * c = first_contour; c != NULL; c = c->h_next)
//{
// contour_length = cvContourPerimeter(c);
// cout << "周长" << contour_length << endl;
//}
contour_length = cvContourPerimeter(first_contour);//计算轮廓长度
cout << "周长为:";
cout<< contour_length << endl;
double perimeter = 126.7;//轮廓精度
double parameters[4] = { 126.7 / 90, 126.7 / 66, 126.7 / 11, 126.7 / 10 };
CvMemStorage* storage_approx = cvCreateMemStorage();
IplImage *image_approx = cvCloneImage(image_binary);
cvZero(image_approx);
CvSeq *seq_approx=NULL;
string window_name = "Approx窗口";
for (int i = 0; i < 4; ++i)
{ //分别用4中精度来进行多边形逼近轮廓,是一个轮廓
seq_approx = cvApproxPoly(first_contour, sizeof(CvContour), storage_approx, CV_POLY_APPROX_DP, parameters[i], 0);
contour_length = cvContourPerimeter(seq_approx);//每一次都计算出逼近轮廓的长度,也是一个轮廓
cout << i<
window_name = window_name + "1";//区别4个窗口
cvDrawContours(image_approx, seq_approx, cvScalar(255), cvScalar(125), 0);//画出轮廓
cvShowImage(window_name.c_str(), image_approx);
if(i==0)
cvSaveImage("result.jpg",image_approx);
if(i==1)
cvSaveImage("result1.jpg",image_approx);
if(i==2)
cvSaveImage("result2.jpg",image_approx);
if(i==3)
cvSaveImage("result3.jpg",image_approx);
}
cvWaitKey(0);
cvReleaseImage(&image_source);
cvReleaseImage(&image_binary);
cvReleaseImage(&image_approx);
cvDestroyAllWindows();
return 0;
}
结果:输入一个椭圆图:
一下图的精度参数分别对应: 126.7 / 90,126.7 / 66, 126.7 / 11, 126.7 / 10
图1
图2,
图3
图4,
椭圆内部的折线就是多边形逼近轮廓的过程。不难发现,parameters精度参数值越小,
精度要求越大,多边形逼近越接近实际轮廓。