一个轮廓一般对应一系列的点,即图像中的一条曲线。
OpenCV中一般用序列来储存轮廓信息。
序列中的每个元素是曲线中的一个点的位置。
FindContours
在二值图像中寻找轮廓
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) );
输入的 8-比特、单通道图像. 非零元素被当成 1, 0 象素值保留为 0 - 从而图像被看成二值的。为了从灰度图像中得到这样的二值图像,可以使用 cvThreshold, cvAdaptiveThreshold 或 cvCanny. 本函数改变输入图像内容。
storage
得到的轮廓的存储容器
first_contour
输出参数:包含第一个输出轮廓的指针
header_size
如果 method=CV_CHAIN_CODE,则序列头的大小 >=sizeof(CvChain),否则 >=sizeof(CvContour) .
mode
- CV_RETR_EXTERNAL - 只提取最外层的轮廓
- CV_RETR_LIST - 提取所有轮廓,并且放置在 list 中
- CV_RETR_CCOMP - 提取所有轮廓,并且将其组织为两层的 hierarchy: 顶层为连通域的外围边界,次层为洞的内层边界。
- CV_RETR_TREE - 提取所有轮廓,并且重构嵌套轮廓的全部 hierarchy
- CV_CHAIN_CODE - Freeman 链码的输出轮廓. 其它方法输出多边形(定点序列).
- CV_CHAIN_APPROX_NONE - 将所有点由链码形式翻译(转化)为点序列形式
- CV_CHAIN_APPROX_SIMPLE - 压缩水平、垂直和对角分割,即函数只保留末端的象素点;
- CV_CHAIN_APPROX_TC89_L1,
- CV_CHAIN_APPROX_TC89_KCOS - 应用 Teh-Chin 链逼近算法. CV_LINK_RUNS - 通过连接为 1 的水平碎片使用完全不同的轮廓提取算法。仅有 CV_RETR_LIST 提取模式可以在本方法中应用.
每一个轮廓点的偏移量. 当轮廓是从图像 ROI 中提取出来的时候,使用偏移量有用,因为可以从整个图像上下文来对轮廓做分析.
函数 cvFindContours 从二值图像中提取轮廓,并且返回提取轮廓的数目。指针 first_contour 的内容由函数填写。它包含第一个最外层轮廓的指针,如果指针为 NULL,则没有检测到轮廓(比如图像是全黑的)。其它轮廓可以从 first_contour 利用 h_next 和 v_next 链接访问到。 在 cvDrawContours 的样例显示如何使用轮廓来进行连通域的检测。轮廓也可以用来做形状分析和对象识别 - 见CVPR2001 教程中的 squares 样例。该教程可以在 SourceForge 网站上找到。
实现:
/*
轮廓检测
*/
#include "highgui.h"
#include "cv.h"
#include "cxcore.h"
void doContour(IplImage* img)
{
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contour = 0;
int mode = CV_RETR_CCOMP;
IplImage* con = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
cvCvtColor(img, con, CV_GRAY2BGR);
//查找contour
cvFindContours(img,storage,&contour,sizeof(CvContour), mode, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
//将轮廓画出
cvDrawContours(con, contour, CV_RGB(0,255,0), CV_RGB(0,0,255), 2, 2, 8, cvPoint(0,0));
cvNamedWindow("contour", 1);
cvShowImage("contour", con);
cvWaitKey(0);
cvReleaseMemStorage(&storage);
}
结果: