一、简介
1、轮廓的相关概念
1)什么是轮廓
轮廓可以简单认为成将连续的点(连着边界)连在一起的曲线,具有相同的颜色或者灰度,提取轮廓就是提取这些具有相同颜色或者灰度的曲线,或者说是连通域,轮廓在形状分析和物体的检测和识别中非常有用。
2)注意事项:
①为了更加准确,要使用二值化图像。在寻找轮廓之前,要进行阈值化处理 或者 Canny 边界检测
②查找轮廓的函数会修改原始图像。如果你在找到轮廓之后还想使用原始图像的话,你应该将原始图像存储到其他变量中(clone(), copyTo())
③在OpenCV 中,查找轮廓就像在黑色背景中找白色物体。你应该记住,要找的物体应该是白色而背景应该是黑色。
3)常用函数:
findContours()-----查找轮廓
drawContours()-----绘制轮廓
2、查找轮廓
1 CV_EXPORTS_W void findContours(InputArray image, OutputArrayofArrays contours, OutputArray hierarchy,
int mode, int method, Point offset=Point());
image: 输入图像, Mat类型8位单通道图像(一般为二值图)
contours: 检测到的轮廓, 每个轮廓存储为一个点向量, 即Point类型的vector表示
hierarchy: 可选的输出向量, 包含图像的拓扑信息。其作为轮廓数量的表示, 包含了许多元素, 每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0]~hierarchy[i][3], 分别表示后一轮廓、前一轮廓、父轮廓、内嵌轮廓的索引编号, 如果没有对应项, 设置为负数
mode: 轮廓检索模式, 取值如下:
CV_RETR_EXTERNAL=0-----表示只检测最外层轮廓 CV_RETR_LIST=1------提取所有轮廓并放置在list中, 轮廓不建立等级关系 CV_RETR_CCOMP=2------提取所有轮廓并组织为双层结构 CV_RETR_TREE=3------提取所有轮廓并重新建立网状轮廓结构
method: 轮廓的近似方法, 取值如下:
1 CV_CHAIN_APPROX_NONE ---连续存储所有的轮廓点,任何两个相邻的点都是水平、垂直或者相邻的。也就是说max(abs(x1-x2), abs(y2-y1)) == 1 2 CV_CHAIN_APPROX_SIMPLE --- 压缩存储,对于水平、垂直或者斜向的线段,比如一个四边形,只会存储四个顶点 3 CV_CHAIN_APPROX_TC89_L1/CV_CHAIN_APPROX_TC89_KCOS
offset: 每个轮廓的可选偏移量, 默认值Point()
3、绘制轮廓
1 CV_EXPORTS_W 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: 所有的输入轮廓, 每个轮廓存储为一个点向量
contourIdx: 轮廓绘制指示变量(索引), 若为负值, 则表示绘制所有轮廓
color: 绘制轮廓的颜色
thickness: 轮廓线条的粗细, 默认值1, 如果为负值, 则绘制轮廓内部, 可选宏 CV_FILLED
lineType: 线条类型, 默认值8
hierarcy: 可选的层次结构信息, 默认值noArray()
maxLevel: 表示用于绘制轮廓的最大等级, 默认值INT_MAX
offset: 可选的轮廓偏移参数, 默认值Point()
【示例】
1 //轮廓查找 轮廓绘制 2 #include"opencv2/opencv.hpp" 3 #include<iostream> 4 5 using namespace std; 6 using namespace cv; 7 8 int main() 9 { 10 Mat srcImg = imread("2.png"); 11 Mat tempImg = srcImg.clone(); 12 //Mat draw(srcImg.rows, srcImg.cols, CV_8UC3); 13 cvtColor(srcImg, srcImg, CV_BGR2GRAY); //转为灰度图 14 threshold(srcImg, srcImg,100, 255, CV_THRESH_BINARY);//图像二值化,value>threshold(即100)?255:0 15 imshow("srcImg", srcImg); //轮廓查找前 16 17 vector<vector<Point>> contours; 18 vector<Vec4i> hierarchy; 19 //findContours(srcImg, contours, hierarchy,RETR_EXTERNAL, CHAIN_APPROX_SIMPLE ); //查找外轮廓,压缩存储轮廓点 20 findContours(srcImg, contours, hierarchy,RETR_LIST, CHAIN_APPROX_SIMPLE ); //查找所有轮廓 21 //findContours(srcImg, contours, hierarchy,CV_RETR_CCOMP, CHAIN_APPROX_SIMPLE ); //查找所有轮廓 22 //findContours(srcImg, contours, hierarchy,RETR_TREE, CHAIN_APPROX_NONE ); //查找所有轮廓,存储所有轮廓点 23 imshow("cont", srcImg); //轮廓查找后 24 drawContours(tempImg, contours,-1, Scalar(0, 255, 0),2); //绘制轮廓:-1代表绘制所有轮廓 25 cout<<"num="<<contours.size()<<endl; //输出轮廓个数 26 imshow("contours", tempImg); 27 28 waitKey(0); 29 return 0; 30 }