int cvFindContours(CvArr* image, CvMemStorage* storage, CvSeq** first_contour, int header_size=sizeof(CvContour), int mode=CV_RETR_LIST, int method=CV_CHAIN_APPROX_SIMPLE, CvPoint offset=cvPoint(0,0));
第六个参数用来表示轮廓边缘的近似方法的,常用值如下所示:
CV_CHAIN_CODE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
CV_CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。
第七个参数表示偏移量,比如你要从图像的(100, 0)开始进行轮廓检测,那么就传入(100, 0)。
使用cvFindContours函数能检测出图像的轮廓,将轮廓绘制出来则需要另一函数——cvDrawContours来配合了。下面介绍cvDrawContours函数。
1.2 cvDrawContoursvoid cvDrawContours(CvArr *img, CvSeq* contour, CvScalar external_color, CvScalar hole_color, int max_level, int thickness=1, int line_type=8, CvPoint offset=cvPoint(0,0));第一个参数表示输入图像,函数将在这张图像上绘制轮廓。
//图像的轮廓检测上 //By MoreWindows (http://blog.csdn.net/MoreWindows) #include <opencv2/opencv.hpp> using namespace std; #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") int main( int argc, char** argv ) { const char *pstrWindowsSrcTitle = "原图(http://blog.csdn.net/MoreWindows)"; const char *pstrWindowsOutLineTitle = "轮廓图(http://blog.csdn.net/MoreWindows)"; const int IMAGE_WIDTH = 400; const int IMAGE_HEIGHT = 200; // 创建图像 IplImage *pSrcImage = cvCreateImage(cvSize(IMAGE_WIDTH, IMAGE_HEIGHT), IPL_DEPTH_8U, 3); // 填充成白色 cvRectangle(pSrcImage, cvPoint(0, 0), cvPoint(pSrcImage->width, pSrcImage->height), CV_RGB(255, 255, 255), CV_FILLED); // 画圆 CvPoint ptCircleCenter = cvPoint(IMAGE_WIDTH / 4, IMAGE_HEIGHT / 2); int nRadius = 80; cvCircle(pSrcImage, ptCircleCenter, nRadius, CV_RGB(255, 255, 0), CV_FILLED); ptCircleCenter = cvPoint(IMAGE_WIDTH / 4, IMAGE_HEIGHT / 2); nRadius = 30; cvCircle(pSrcImage, ptCircleCenter, nRadius, CV_RGB(255, 255, 255), CV_FILLED); // 画矩形 CvPoint ptLeftTop = cvPoint(IMAGE_WIDTH / 2 + 20, 20); CvPoint ptRightBottom = cvPoint(IMAGE_WIDTH - 20, IMAGE_HEIGHT - 20); cvRectangle(pSrcImage, ptLeftTop, ptRightBottom, CV_RGB(0, 255, 255), CV_FILLED); ptLeftTop = cvPoint(IMAGE_WIDTH / 2 + 60, 40); ptRightBottom = cvPoint(IMAGE_WIDTH - 60, IMAGE_HEIGHT - 40); cvRectangle(pSrcImage, ptLeftTop, ptRightBottom, CV_RGB(255, 255, 255), CV_FILLED); // 显示原图 cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE); cvShowImage(pstrWindowsSrcTitle, pSrcImage); // 转为灰度图 IplImage *pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1); cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY); // 转为二值图 IplImage *pBinaryImage = cvCreateImage(cvGetSize(pGrayImage), IPL_DEPTH_8U, 1); cvThreshold(pGrayImage, pBinaryImage, 250, 255, CV_THRESH_BINARY); // 检索轮廓并返回检测到的轮廓的个数 CvMemStorage *pcvMStorage = cvCreateMemStorage(); CvSeq *pcvSeq = NULL; cvFindContours(pBinaryImage, pcvMStorage, &pcvSeq, sizeof(CvContour), CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0)); // 画轮廓图 IplImage *pOutlineImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3); int nLevels = 5; // 填充成白色 cvRectangle(pOutlineImage, cvPoint(0, 0), cvPoint(pOutlineImage->width, pOutlineImage->height), CV_RGB(255, 255, 255), CV_FILLED); cvDrawContours(pOutlineImage, pcvSeq, CV_RGB(255,0,0), CV_RGB(0,255,0), nLevels, 2); // 显示轮廓图 cvNamedWindow(pstrWindowsOutLineTitle, CV_WINDOW_AUTOSIZE); cvShowImage(pstrWindowsOutLineTitle, pOutlineImage); cvWaitKey(0); cvReleaseMemStorage(&pcvMStorage); cvDestroyWindow(pstrWindowsSrcTitle); cvDestroyWindow(pstrWindowsOutLineTitle); cvReleaseImage(&pSrcImage); cvReleaseImage(&pGrayImage); cvReleaseImage(&pBinaryImage); cvReleaseImage(&pOutlineImage); return 0; }
运行结果如下图所示:
由图可以看出,轮廓线已经按层次交替的绘制成功了,读者可以修改程序中的cvDrawContours中的nLevels参数,看看图形会有什么变化。
上一篇《【OpenCV入门指南】第五篇轮廓检测上》介绍了cvFindContours函数和cvDrawContours函数,并作了一个简单的使用示范。本篇将展示一个实例,让大家对轮廓检测有个更加深入的认识。
代码如下:
程序运行结果如下所示:
可以明显看出,由于图像的二值化处理只是根据图像中单个像素的值来决定,因此这种最简单轮廓检测所产生的结果和人眼观测的实际感觉肯定是有比较大的区别的。
轮廓检测另外还有一个重要的函数cvApproxPoly,它的函数原型如下所示
CVAPI(CvSeq*) cvApproxPoly( const void* src_seq, int header_size, CvMemStorage* storage, int method, double parameter, int parameter2 CV_DEFAULT(0));
由于篇幅问题,对于cvApproxPoly函数就不细讲了,有兴趣的读者可以参考下面这一篇博客:http://blog.csdn.net/bruce_zeng/article/details/
《OpenCV入门指南》系列文章地址:http://blog.csdn.net/morewindows/article/category/863841
转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/8253137
欢迎关注微博:http://weibo.com/MoreWindows