多轮廓提取

【目标】提取图像中的目标轮廓

【寻找轮廓】

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();

原文地址:https://www.cnblogs.com/xixixing/p/6040627.html