阿牧路泽

哪有那么多坚强,无非是死扛罢了
  博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

23、【opencv入门】轮廓查找与绘制(1)

Posted on 2018-09-18 10:27  阿牧路泽  阅读(552)  评论(0)    收藏  举报

一、简介

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 }