【目标】提取图像中的目标轮廓
【寻找轮廓】
findContours(InputOutputArray二值图, 点类型的contours, int mode, int method, Point offset=Point());
或
findContours(InputOutputArray二值图, 点类型的contours, OutputArray hierarchy, int mode, int method, Point offset=Point());
【注意】InputOutputArray类型的image都会被改变。此函数会改变输入的2值图像,所以一般先Mat src1=src.clone(),对src1处理。
contours——vector<vector<Point> > contours; 轮廓边界点的集合。
hierarchy——vector<Vec4i> hierarchy; 每个轮廓contours[i]对应4个hierarchy元素:hierarchy[i][0]~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。若没对应项,对应的hierarchy[i]值设为负。
mode——轮廓检索模式
轮廓检索模式 |
|
CV_RETR_EXTERNAL |
只检测最外层轮廓,对所有轮廓设置hierarchy[i][2]=hierarchy[i][3]=-1 |
CV_RETR_LIST |
检测所有轮廓,且放在list中,轮廓间无等级关系,即只有一层 |
CV_RETR_CCOMP |
检测所有轮廓,且组织为双层结构,即两层的 hierarchy。顶层为连通域外围边界、次层为内层边界 |
CV_RETR_TREE |
检测所有轮廓,并且重构嵌套轮廓的全部 hierarchy |
method——轮廓的近似方法
method |
|
CV_CHAIN_APPROX_NONE |
获取每个轮廓的每个像素,相邻像素点位置差≤1,即max(abs(x1-x2),abs(y1-y2))==1 |
CV_CHAIN_APPROX_SIMPLE |
只保留水平、竖直、对角线方向终点坐标,压缩元素,如矩形轮廓只需4点表示 |
CV_CHAIN_APPROX_TC89_L1 CV_CHAIN_APPROX_TC89_KCOS |
使用The-Chinl链逼近算法中的一个 |
offset——表示代表轮廓点的偏移量,可以设置为任意值。对ROI图像中找出的轮廓,并要在整个图像中进行分析时,这个参数还是很有用的。
【绘制轮廓】
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——输入输出图像,会被改变
contours——vector<vector<Point> > contours 注意> >间有空格
contourIdx——指定哪一个轮廓,若为负,则绘制所有轮廓
color ——Scalar&类型的color,轮廓颜色
thickness——轮廓线条粗细,若为负值(CV_FILLED),则填充整个轮廓。
lineType——线型,默认8连通线型。还有4连通线型,CV_AA(抗锯齿线型)
hierarchy——可选的层次结构信息
maxLevel——用于绘制轮廓的最大层,只有在有层次关系的时候被使用。若为0,只画指定轮廓,为1,画第一层所有轮廓,为2,画第一、二层的所有轮廓,以此类推。
offset——可选的轮廓偏移参数,offset(dx,dy)。
【所有轮廓】
//载入灰度图 Mat src=imread("C:/Users/Jv/Desktop/contour.png", 0); //二值化 src=src>100; namedWindow("原始图",0); imshow("原始图",src); vector<vector<Point> > contours; //搜索全部轮廓,获取每个轮廓的每个像素 findContours( src,contours,CV_RETR_LIST/CCOMP/TREE, CV_CHAIN_APPROX_NONE ); //显示轮廓线个数 printf("num=%d",contours.size()); //新建单通道黑色画布,CV_8UC1中的C1指单通道,默认单通道 Mat dst(src.size(),CV_8U,Scalar(0)); //绘制所有轮廓线,白色线条,线宽2 drawContours( dst, contours, -1, Scalar(255),2 ); namedWindow( "Components", 1 ); imshow( "Components", dst ); waitKey();
【最外层轮廓】
findContours( src,contours,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE ); drawContours( dst, contours,-1, Scalar(255) );
【所有轮廓的外围边界】
vector<Vec4i> hierarchy; findContours( src,contours,hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE ); drawContours( dst, contours,-1, Scalar(255),1,8,hierarchy,1 );
//三通道黑色画布 Mat dst(src.size(),CV_8UC3,Scalar(0,0,0)); //绘制所有轮廓外围边界,红色色线条,线宽2 drawContours( dst, contours,-1, Scalar(0,0,255),2,8,hierarchy,1 ); //在原彩色图上绘制所有轮廓外围边界,红色色线条,线宽2 Mat src1=src.clone();//防止src被更改,注意Mat src=imread("contour.png") drawContours( src1, contours,-1, Scalar(0,0,255),2,8,hierarchy,1 );
【绘制指定轮廓】分别对应0,1,2,3……
//载入三通道图 Mat src=imread("C:/Users/Jv/Desktop/contour.png"),gray; cvtColor(src,gray,CV_RGB2GRAY); //二值化 Mat binary=gray>100; namedWindow("原始图",0);imshow("原始图",binary); vector<vector<Point> > contours; vector<Vec4i> hierarchy; //搜索全部轮廓,获取每个轮廓的每个像素 findContours( binary,contours,hierarchy,CV_RETR_TREE, CV_CHAIN_APPROX_NONE ); //显示轮廓个数 printf("num=%d",contours.size()); //在原彩色图上绘制所有轮廓外围边界,红色色线条,线宽2 Mat src1=src.clone();//防止src被更改,注意Mat src=imread("C:/Users/Jv/Desktop/contour.png") drawContours( src1, contours,0, Scalar(0,0,255),2,8,hierarchy,0 );//0只画指定轮廓 namedWindow( "Components", 1 );imshow( "Components", src1 ); waitKey();