findContours轮廓提取函数与drawContours轮廓绘制函数的使用

来源:互联网 发布:金刚2005知乎 编辑:程序博客网 时间:2024/06/04 19:43

OpenCV中函数findContours()用于中对象的轮廓,有两种形式:

第一种:

void findContours( InputOutputArray image, OutputArrayOfArrays contours,
                              int mode, int method, Point offset=Point());

第二种:

void findContours( InputOutputArray image, OutputArrayOfArrays contours,
                              OutputArray hierarchy, int mode,

                              int method, Point offset=Point());

注意:findContours()函数会改变图像

下面解释各个参数的作用:

第一个参数:image,单通道图像矩阵,可以使灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像;

第二个参数:contours,定义为“vector<vector<Point>> contours”,是一个向量,并且是一个双重向量,向量内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓。有多少轮廓,向量contours就有多少元素。

第三个参数:hierarchy,定义为“vector<Vec4i> hierarchy”,先来看一下Vec4i的定义:typedef Vec<int,4> Vec4i;

                     Vec4i是Vec<int, 4>的别名,定义了一个“向量内每一个元素包含了4个int型变量”的向量。所以从定义上看,hierarchy也是一个向量,向量内每个元素保存了一个包含4个int整型的数组。向量hierarchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。

                      hierarchy向量内每一个元素的4个int型变量----hierarchy[i][0]-hierarchy[i][3],分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓或内嵌轮廓的话,则相应位置被设置为默认值-1。

第四个参数:int型的mode,定义轮廓的检索模式:

                     取值一:CV_RETR_EXTERNAL     只检测最外围轮廓,包含在外围轮廓内的内围轮廓将被忽略;

                     取值二:CV_RETR_LIST               检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等 级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1。

                     取值三:CV_RETR_CCOMP          检测所有的轮廓,但所有的轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层。

                     取值四:CV_RETR_TREE              检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。

第五个参数:int型的method,定义轮廓的近似方法:

                     取值一:CV_CHAIN_APPROX_NONE     保存物体边界上所有连续的轮廓点到contours向量内

                     取值二:CV_CHAIN_APPROX_SIMPLE  仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入向量内,拐点与拐点之间直线段上的信息点不予保留

                     取值三和四:CV_CHAIN_APPROX——TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain近似算法

第六个参数:Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值。


代码如下:

  1. #include "highgui.h"  
  2. #include "imgproc/imgproc.hpp"  
  3.   
  4. int main()  
  5. {  
  6.     cv::Mat image = cv::imread("D:/Development/OpenCV/images/binaryGroup.bmp" , 0) ;  
  7.     std::vector<std::vector<cv::Point>> contours ;  
  8.     //获取轮廓不包括轮廓内的轮廓  
  9.     cv::findContours(image , contours ,   
  10.         CV_RETR_EXTERNAL , CV_CHAIN_APPROX_NONE) ;  
  11.     cv::Mat result(image.size() , CV_8U , cv::Scalar(255)) ;  
  12.     cv::drawContours(result , contours ,  
  13.         -1 , cv::Scalar(0) , 2) ;  
  14.     cv::imshow("resultImage" , result) ;  
  15.       
  16.     //获取所有轮廓包括轮廓内的轮廓  
  17.     std::vector<std::vector<cv::Point>> allContours ;  
  18.     cv::Mat allContoursResult(image.size() , CV_8U , cv::Scalar(255)) ;  
  19.     cv::findContours(image , allContours ,  
  20.         CV_RETR_LIST , CV_CHAIN_APPROX_NONE) ;  
  21.     cv::drawContours(allContoursResult , allContours ,-1 ,  
  22.         cv::Scalar(0) , 2) ;  
  23.     cv::imshow("allContours" , allContoursResult) ;  
  24.   
  25.     //获取轮廓的等级  
  26.     std::vector<cv::Vec4i> hierarchy ;  
  27.     cv::findContours(image , contours , hierarchy , CV_RETR_TREE ,  
  28.         CV_CHAIN_APPROX_NONE) ;  
  29.   
  30.     cv::waitKey(0) ;  
  31.     return 0 ;  

1、获取包围对象的垂直矩阵

[cpp] view plain copy
  1. cv::Rect r0= cv::boundingRect(cv::Mat(contours[0]));  
  2. cv::rectangle(result,r0,cv::Scalar(0),2);  

2、获取包围对象的最小圆

[cpp] view plain copy
  1. cv::Rect r0= cv::boundingRect(cv::Mat(contours[0]));  
  2. cv::rectangle(result,r0,cv::Scalar(0),2);  

3、获取包围对象的多边形

[cpp] view plain copy
  1. // testing the approximate polygon  
  2. std::vector<cv::Point> poly;  
  3. cv::approxPolyDP(cv::Mat(contours[2]),poly,  
  4. 5, // accuracy of the approximation  
  5. true); // yes it is a closed shape  

4、获得包围对象的凸包

[cpp] view plain copy
  1. // testing the convex hull  
  2. std::vector<cv::Point> hull;  
  3. cv::convexHull(cv::Mat(contours[3]),hull);  

5、获取各个对象的质心

[cpp] view plain copy
  1. itc= contours.begin();  
  2. while (itc!=contours.end()) {  
  3. // compute all moments  
  4. cv::Moments mom= cv::moments(cv::Mat(*itc++));  
  5. // draw mass center  
  6. cv::circle(result,  
  7. // position of mass center converted to integer  
  8. cv::Point(mom.m10/mom.m00,mom.m01/mom.m00),  
  9. 2,cv::Scalar(0),2); // draw black dot  
  10. }  


void drawContours//绘制轮廓,用于绘制找到的图像轮廓
(
     InputOutputArray image,//要绘制轮廓的图像
     InputArrayOfArrays contours,//所有输入的轮廓,每个轮廓被保存成一个point向量
     int contourIdx,//指定要绘制轮廓的编号,如果是负数,则绘制所有的轮廓
     const Scalar& color,//绘制轮廓所用的颜色
     int thickness = 1, //绘制轮廓的线的粗细,如果是负数,则轮廓内部被填充
     int lineType = 8, /绘制轮廓的线的连通性
     InputArray hierarchy = noArray(),//关于层级的可选参数,只有绘制部分轮廓时才会用到
     int maxLevel = INT_MAX,//绘制轮廓的最高级别,这个参数只有hierarchy有效的时候才有效
                                          //maxLevel=0,绘制与输入轮廓属于同一等级的所有轮廓即输入轮廓和与其相邻的轮廓
                                          //maxLevel=1, 绘制与输入轮廓同一等级的所有轮廓与其子节点。
                                          //maxLevel=2,绘制与输入轮廓同一等级的所有轮廓与其子节点以及子节点的子节点
     Point offset = Point()
)

阅读全文
0 0
原创粉丝点击