opencv findContours家族全集

本文介绍OpenCV中的轮廓检测函数findContours及其应用,包括轮廓绘制、近似、面积计算等操作,以及如何通过轮廓进行外包络线检测。

说明: 最近看图像处理,觉得这个函数很有用,而且作用很强大,帮深挖了一些,并进行了资料汇总。

(1)函数原型:

void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierar-
chy, int mode, int method, Point offset=Point())

findContours后会对输入的2值图像改变,所以如果不想改变该2值图像,需创建新mat来存放,

参数说明 :
1)image:必须为一个2值单通道图像 

2)contours:检测的轮廓数组,每一个轮廓用一个point类型的vector表示;可定义为:vector<vector<Point>> contours;

3)hiararchy:参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。

示例:// //hierarchy[idx][0] 返回同等级层次结构的下一个轮廓索引//遍历整个hierarchy
// for( ; idx >= 0; idx = heirarchy[idx][0] )  
// {  
//
// }  

4)mode表示轮廓的检索模式
CV_RETR_EXTERNAL表示只检测外轮廓
CV_RETR_LIST检测的轮廓不建立等级关系
CV_RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
CV_RETR_TREE建立一个等级树结构的轮廓。

示例:一个很好的例子做这个功能测试。如果有空研究,可以试一下下图,用画图板画一个即可。


5)method为轮廓的近似办法
CV_CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
CV_CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

6)offset表示代表轮廓点的偏移量,可以设置为任意值。对ROI图像中找出的轮廓,并要在整个图像中进行分析时,这个参数还是很有用的。

说明:这个功能还没试过。

(2)drawContours

findContours经常与drawContours配合使用,用来将轮廓绘制出来。其中第一个参数image表示目标图像,第二个参数contours表示输入的轮廓组,每一组轮廓由点vector构成,第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓,第四个参数color为轮廓的颜色,第五个参数thickness为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部,第六个参数lineType为线型,第七个参数为轮廓结构信息,第八个参数为maxLevel 


(3)approxPolyDP

findContours后的轮廓信息contours可能过于复杂不平滑,可以用approxPolyDP函数对该多边形曲线做适当近似; 


(4)contourArea
contourArea函数可以得到当前轮廓包含区域的大小,方便轮廓的筛选 。

示例:遍历方法:

for (int i = 0; i < contoursCopy.size(); i++)  
{  //下面是判断点是否是曲线的包围之中代码,并输出包围在第几个曲线中
if (pointPolygonTest(contoursCopy[i],pointMouse,false)==1)
{
cout<<pointMouse<<"in"<<endl;
cout<<"第几个:"<<i<<endl;
//break;
}
else
{
cout<<pointMouse<<"out"<<endl;
}


(5)轮廓的外包络线,方便做检测

1)点集凸包络的提取函数convexHull,输入参数就可以是contours组中的一个轮廓,返回外凸包络的点集
2)外包络矩形,使用函数boundingRect;

3)旋转的外包络矩形,使用函数minAreaRect,返回值为RotatedRect;

4)外包络圆,对应的函数为minEnclosingCircle;

5)外包络椭圆,对应的函数为fitEllipse,返回值也是RotatedRect,可以用ellipse函数画出对应的椭圆; 


如果想根据多边形的轮廓信息得到多边形的多阶矩,可以使用类moments,这个类可以得到多边形和光栅形状的3阶以内的所有矩,类内有变量m00,m10,m01,m20,m11,m02,m30,m21,m12,m03,比如多边形的质心为 x = m10 / m00,y = m01 / m00。
如果想获得一点与多边形封闭轮廓的信息,可以调用pointPolygonTest函数,这个函数返回值为该点距离轮廓最近边界的距离,为正值为在轮廓内部,负值为在轮廓外部,0表示在边界上。
例子:对二值图像画矩形框

findContours(binary_image,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE); 

for (int i = 0;i<contours.size();i++)
{
    Rect r = boundingRect(contours[i]);
    r.x = r.x -1;
    r.y = r.y -1;
    r.width = r.width+2;
    r.height =r.height+2;
    if(r.width>8 || r.height>8)
        rectangle(resize_image, r, Scalar(0,0,255), 1);
    imshow("real_time",resize_image);
    waitKey(0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值