函数cvFindContours从二值图像中检索轮廓,并返回检测到的轮廓的个数。first_contour的值由函数填充返回,它的值将为第一个外轮廓的指针,当没有轮廓被检测到时为NULL。其它轮廓可以使用h_next和v_next连接,从first_contour到达。
int cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour,
intheader_size=sizeof(CvContour), int mode=CV_RETR_LIST,
intmethod=CV_CHAIN_APPROX_SIMPLE, CvPoint offset=cvPoint(0,0) );
image
8比特单通道的源二值图像。非零像素作为1处理,0像素保存不变。从一个灰度图像得到二值图像的函数有:cvThreshold,cvAdaptiveThreshold和cvCanny。
storage
返回轮廓的容器。
first_contour
输出参数,用于存储指向第一个外接轮廓。
header_size
header序列的尺寸.如果选择method = CV_CHAIN_CODE, 则header_size >= sizeof(CvChain);其他,则
header_size >= sizeof(CvContour)。
mode
检索模式,可取值如下:
CV_RETR_EXTERNAL:只检索最外面的轮廓;
CV_RETR_LIST:检索所有的轮廓,并将其放入list中;
CV_RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
CV_RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次。
method
边缘近似方法(除了CV_RETR_RUNS使用内置的近似,其他模式均使用此设定的近似算法)。可取值如下:
CV_CHAIN_CODE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
CV_CHAIN_APPROX_NONE:将所有的连码点,转换成点。
CV_CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。
CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS:使用the flavors of Teh-Chin chain近似算法
的一种。
CV_LINK_RUNS:通过连接水平段的1,使用完全不同的边缘提取算法。使用CV_RETR_LIST检索模式能使用此方法。
offset
偏移量,用于移动所有轮廓点。当轮廓是从图像的ROI提取的,并且需要在整个图像中分析时,这个参数将很有用。
讨论部分cvDrawContours中的案例显示了任何使用轮廓检测连通区域。轮廓可以用于形状分析和目标识别——可以参考文件夹OpenCV sample中的squares.c。
最近做连通域分析
最初想自己写,发现好多东西居然不知道怎么做,比如说怎么找内轮廓等
于是改用cvBlobslib,发现他的架构还是不错的,不过很不爽的,让我发现了几处内存泄露,然后实际得到的轮廓似乎也比真正的轮廓少一圈,此外就是这个命名一塌糊涂,费了我好一段时间才大体搞明白,还是决定放弃
最后没办法,只好用cvFindContours来代替了
cvFindContours(
CvArr* image,
CvMemStorage* storage,
CvSeq** first_contour,
int header_size CV_DEFAULT(sizeof(CvContour)),
int mode CV_DEFAULT(CV_RETR_LIST),
int method CV_DEFAULT(CV_CHAIN_APPROX_SIMPLE),
CvPoint offset CV_DEFAULT(cvPoint(0,0)));
有几个参数意思比较明显,这里就不再多说了
重点解释一下mode ,method这两处
mode 有下面四个
#define CV_RETR_EXTERNAL 0
#define CV_RETR_LIST 1
#define CV_RETR_CCOMP 2
#define CV_RETR_TREE 3
其中External 和觉得就是找外轮廓(如果一个物体内部有空洞的话,很自然的有内轮廓)然后用contour->h_next遍历就行了
CV_RETR_LIST这种形式是不管外轮廓还是内轮廓通通以list的形式存储,这时我们可以用cvContourArea来求轮廓的面积,如果是外轮廓的话,面积应该是负的,反之,面积应该是正的,遍历时也用contour->h_next就行了
CCOMP就是找轮廓的连通域,没有空洞的话,就是只有外轮廓了,有空洞的话,也有内轮廓(他与下面的CV_RETR_TREE 不同的是,CCOMP只包含一层嵌套,也即一个外轮廓只包含一个内轮廓,而CV_RETR_TREE会包含好多层)
用contour->h_next遍历的是外轮廓,在每一个外轮廓里,求一次contour->v_next得到他所包含的内轮廓即可
CV_RETR_TREE 是以树的形式来表示,把内轮廓作为包含他的外轮廓的child,
用contour->h_next遍历的是外轮廓,在每一个外轮廓里,遍历contour->v_next得到他所包含的内轮廓
method
#define CV_CHAIN_CODE 0
#define CV_CHAIN_APPROX_NONE 1
#define CV_CHAIN_APPROX_SIMPLE 2
#define CV_CHAIN_APPROX_TC89_L1 3
#define CV_CHAIN_APPROX_TC89_KCOS 4
#define CV_LINK_RUNS 5
好象主要是轮廓所包含点的存储形式,我就知道
CV_CHINA_CODE和CV_CHIAN_APPROX_SIMPLE两种
一般我们只要用CV_CHIAN_APPROX_SIMPLE就可以了,在这种格式下,貌似轮廓就是以点集的形式来表示。
然后再说一下cvDrawContours
cvDrawContours( CvArr *img, CvSeq* contour,
CvScalar external_color, CvScalar hole_color,
int max_level, int thickness CV_DEFAULT(1),
int line_type CV_DEFAULT(8),
CvPoint offset CV_DEFAULT(cvPoint(0,0)));
其他参数比较好理解
主要说一下max_level
我感觉这个max_level主要还是和轮廓之间的嵌套相关
1 r
0 e e e
-1 i1 i1 i1 i1
-2 i2 i2 i2 i2
-3 i3 i3
最顶层的是root,包含所有的外轮廓,level是1
然后是外轮廓 level是0
然后是外轮廓包含的内轮廓 level是-1
然后是外轮廓包含的内轮廓包含的轮廓 level是-2
。
。
。
cvDrawContours绘制的是(maxlevel)以上的
所有如果maxlevel是1,则一次画完所有的外轮廓
如果maxlevel是0,则只画当前轮廓的外轮廓
如果maxlevel是-1,则绘制当前轮廓的外轮廓及他的下一层子轮廓
依次类推
Comments from the Wiki
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)
)
¶
Finds the contours in a binary image.
Parameters: |
|
The function retrieves contours from the binary image using the algorithm Suzuki85 . The contours are a useful tool for shape analysis and object detection and recognition.
first_contour is filled by the function. It will contain a pointer to the first outermost contour or NULL if no contours are detected (if the image is completely black). Other contours may be reached from first_contourusing the h_next and v_next links. The sample in the DrawContours discussion shows how to use contours for connected component detection. Contours can be also used for shape analysis and object recognition - see squares.c
Note: the source image