opencv findcontour drawContour函数以及延伸函数的分析
2017-03-05 22:04
696 查看
void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())
参数说明
输入图像image必须为一个2值单通道图像,常见为Mat类型。
contours参数为检测的轮廓数组,每一个轮廓用一个point类型的vector表示,该数组一般是一个装有向量的向量容器,定义为Vector<Vector<Point>>contour;
hiararchy参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。一般本项可忽略。
mode表示轮廓的检索模式
CV_RETR_EXTERNAL表示只检测外轮廓
CV_RETR_LIST检测的轮廓不建立等级关系
CV_RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
CV_RETR_TREE建立一个等级树结构的轮廓。具体参考contours.c这个demo。一般选择该项,指检测全部轮廓。
method为轮廓的近似办法
CV_CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
CV_CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息。NONE和SIMPLE两项皆可以。
CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
offset表示代表轮廓点的偏移量,可以设置为任意值。对ROI图像中找出的轮廓,并要在整个图像中进行分析时,这个参数还是很有用的。
findContours后会对输入的2值图像改变,所以如果不想改变该2值图像,需创建新mat来存放,findContours后的轮廓信息contours可能过于复杂不平滑,可以用approxPolyDP函数对该多边形曲线做适当近似
contourArea函数可以得到当前轮廓包含区域的大小,方便轮廓的筛选。
findContours经常与drawContours配合使用,用来将轮廓绘制出来。
void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )其中第一个参数image表示目标图像,Mat类型。第二个参数contours表示输入的轮廓组,每一组轮廓由点vector构成。第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓。第四个参数color为轮廓的颜色。第五个参数thickness为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部。第六个参数lineType为线型,第七个参数为轮廓结构信息,第八个参数为maxLevel。得到了复杂轮廓往往不适合特征的检测,这里再介绍一个点集凸包络的提取函数convexHull,输入参数就可以是contours组中的一个轮廓,返回外凸包络的点集。注意:主动轮廓模型cvsnakeimage函数在opencv3里面已删除。与此功能类似的有convexHull函数,即平滑轮廓。示例代码:#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <cvaux.h>
#include <iostream>
using namespace std;
int main()
{
IplImage *src = cvLoadImage("f:\\images\\test2.bmp",CV_LOAD_IMAGE_GRAYSCALE);
IplImage *dst = cvCreateImage(cvGetSize(src),8,3);cvZero(dst);
CvMemStorage *storage = cvCreateMemStorage();
CvSeq *contour = NULL , *hull = NULL;
CvContourScanner scanner = cvStartFindContours(src,storage);
while((contour = cvFindNextContour(scanner)) != NULL){
cvDrawContours(dst,contour,CV_RGB(255,0,0),CV_RGB(0,255,0),0);
cout<<cvCheckContourConvexity(contour)<<endl;
hull = cvConvexHull2(contour,0,CV_CLOCKWISE,0);
CvPoint pt0 = **(CvPoint**)cvGetSeqElem(hull,hull->total - 1);
for(int i = 0;i<hull->total;++i){
CvPoint pt1 = **(CvPoint**)cvGetSeqElem(hull,i);
cvLine(dst,pt0,pt1,CV_RGB(0,0,255));
pt0 = pt1;
}
CvSeq *defect = cvConvexityDefects(contour,hull);
for(int i = 0;i<defect->total;++i){
CvConvexityDefect df = *(CvConvexityDefect*)cvGetSeqElem(defect,i);
cvCircle(dst,*df.start,2,CV_RGB(255,255,0),-1);
cvCircle(dst,*df.end,2,CV_RGB(255,255,0),-1);
cvCircle(dst,*df.depth_point,2,CV_RGB(0,255,255),-1);
}
cvShowImage("dst",dst);
cvWaitKey();
}
cvEndFindContours(&scanner);
}
还可以得到轮廓的外包络矩形,使用函数boundingRect,如果想得到旋转的外包络矩形,使用函数minAreaRect,返回值为RotatedRect;也可以得到轮廓的外包络圆,对应的函数为minEnclosingCircle;想得到轮廓的外包络椭圆,对应的函数为fitEllipse,返回值也是RotatedRect,可以用ellipse函数画出对应的椭圆。
如果想根据多边形的轮廓信息得到多边形的多阶矩,可以使用类moments,这个类可以得到多边形和光栅形状的3阶以内的所有矩,类内有变量m00,m10,m01,m20,m11,m02,m30,m21,m12,m03,比如多边形的质心为
x = m10 / m00,y = m01 / m00。
如果想获得一点与多边形封闭轮廓的信息,可以调用pointPolygonTest函数,这个函数返回值为该点距离轮廓最近边界的距离,为正值为在轮廓内部,负值为在轮廓外部,0表示在边界上。
相关文章推荐
- 部分C库函数重写以及反汇编分析之memcpy()
- 部分C库函数重写以及反汇编分析之memmov()
- C++ 函数反汇编跟踪以及栈结构分析
- 【OpenCV】CvCreateImage函数说明以及颜色空间量化之间转换
- OpenCV自带库寻找四边形求余弦值函数分析
- 数据库学习:oracle的递归写法,分析函数写法,以及teradata的取一定数量记录的写法
- Opencv中计算梯度、梯度幅值以及梯度方向的相关函数
- HEVC/H.265整个程序调用流程分析以及函数复杂度分析 .
- OpenCV:Mat元素访问方法、性能、代码复杂度以及安全性分析
- 部分C库函数重写以及反汇编分析之memset()
- OpenCV中寻找轮廓函数cvFindContours的使用说明以及序列cvSeq的用法说明
- HEVC/H.265整个程序调用流程分析以及函数复杂度分析
- oracle 分析函数以及实例解析
- PHP数组排序函数合集 以及它们之间的联系分析
- 部分C库函数重写以及反汇编分析之 toupper()
- 关于动态存储分配函数的调用,在已经过排序的数组中查找及删除内容的操作,余数的分析,删除字符数组中的空格,对链表的逆置,在源字符串中查找子字符串的个数,函数指针以及函数的调用,循环赋值带来的问题以及插入
- matlab中zeros 和 ones 这两个函数的用法以及size的用法,princomp,pcacov,pcares,barttest四大分析函数用法
- php的POSIX 函数以及进程测试的深入分析
- HEVC/H.265整个程序调用流程分析以及函数复杂度分析
- nginx configure location 流程以及重要函数分析