OpenCV教程 之 寻找物体的轮廓与凸包:findContours、convexHull函数(C++)
2017-11-18 23:12
573 查看
凸包(Convex Hull)是一个计算几何中常见的概念,简单来说,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有点,理解物体形状轮廓的一种比较有用的方法便是计算一个物体的凸包,然后计算其凸缺陷。很多复杂物体的性能能被这种缺陷表示出来
举个栗子
举个栗子:
使用下图作为原图像
效果如下:
这里有更完整的代码介绍:
https://github.com/LiangjunFeng/Implement-OpenCV
一、寻找轮廓:findContours()函数
一个轮廓一般对应着一系列的点,也就是图像中的一条曲线,在OpenCV中,可以用findContours()函数从二值图像中查找轮廓,我们先来看一下这个函数的函数原型void findContours(InputOutArray image,OutputArrayOfArrays contours,outputArray hierarchy,int method,Point offset = Point()) @第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类对象即可,且需为8位单通道图像 @第二个参数,OutputArrayOfArrays类型的contours,检测到的轮廓、函数调用后的运算结果存在这里。每一个轮廓存储为一个点向量,即用point类型的vector表示 @第三个参数,outputArray类型的hierarchy,可选的输出量,包含图像的拓扑信息 @第四个参数,int类型的mode,轮廓检索模式,取值有RETR_EXTERNAL、RETR_LIST、RETR_CCOMP、RETR_TREE @第五个参数,int类型的method,为轮廓的近似办法,取值有CHAIN_APPROX_NONE、CHAIN_APPROX_SIMPLE、CHAIN_APPROX_TC89_L1、CHAIN_APPROX_TC89_KCOS @第六个参数,Point类型的offset,每个轮廓点的可选偏移量,有默认值Point()
举个栗子
vector<vector<Point>> contours; findContours(image,countours,CV_RETR_EXTERNAL,CV_CHAIN_APROX_NONE)
二、绘制轮廓:drawContours()函数
findContours经常与drawContours配合使用,在使用findContours()函数检测到图像的轮廓以后,便可以用drawContours()函数将检测到的轮廓绘制出来,该函数的函数原型如下: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()) @第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类对象即可 @第二个参数,OutputArrayOfArrays类型的contours,所有的输入轮廓。每一个轮廓存储为一个点向量,即用point类型的vector表示 @第三个参数,int类型的contourIdx,轮廓绘制的指示变量。如果其为负值,则绘制所有轮廓 @第四个参数,constScalar&类型的color,轮廓的颜色 @第五个参数,int thickness,轮廓线条的粗细,有默认值1 @第六个参数,int类型的lineType,线条的类型,有默认值8 @第七个参数,InputArray类型的hierarchy,可选的层次结构信息,有默认值noArray() @第八个参数,int类型的maxLevel,表示用于绘制轮廓的最大等级,有默认值INT_MAX @第九个参数,Point类型的offset,可选的轮廓偏移参数,默认为Point()
举个栗子:
使用下图作为原图像
//在白色图像上绘制黑色轮廓 Mat result(image.size(),CV_8U,CV::Scalar(255)); drawContours(result,contours,-1,Scalar(0),3);
二、convexHull函数
首先来介绍一下OpenCV中的这个凸包检测函数void convexHull(InputArray points,OutputArray hull,bool clockwise = false,bool returnPoints = true) @第一个参数,InputArray类型的Points,输入的二维点集,可以填Mat类型或者std::vector @第二个参数,OutputArray类型的Hull,输出参数,函数调用后找到的凸包 @第三个参数,bool类型的clockwise,操作方向标识符。当此标志符为真时,输出的凸包为顺时针方向,否则就为逆时针方向。并且是假定坐标系的x轴指向右,y轴指向上方 @第四个参数,bool类型的returnPoints,操作符标识,默认为true。当标识符为真时,函数返回各个凸包的各个点。否则,它返回凸包各点的指数。当输出数组是std::vector时,此标志被忽略
三、应用举例
结合上面介绍的三个函数,我们来尝试一个完整的使用案例//- 4000 ------------------------------------【head file\namesapce declaration】------------------------------ // statement: declare head file and namespace //----------------------------------------------------------------------------------------------------- #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> using namespace cv; using namespace std; typedef vector<Point> vec; //-------------------------------------【public Variables】--------------------------------------------- // statement: declare global variables //----------------------------------------------------------------------------------------------------- Mat g_srcImage,g_grayImage; int g_nThresh = 50; int g_maxThresh = 255; RNG g_rng(12345); Mat srcImage_copy; Mat g_thresholdImage_ouput; vector<vec> g_vContours; vector<Vec4i> g_vHierarchy; //-------------------------------------【public function】--------------------------------------------- // statement: declare global function //----------------------------------------------------------------------------------------------------- static void on_ThreshChange(int,void*); //--------------------------------------【main()function】---------------------------------------------- // statement: our code run from here //----------------------------------------------------------------------------------------------------- int main(int argc,char *argv[]){ g_srcImage = imread("/Users/zhuxiaoxiansheng/Desktop/xiaoxin.jpg",1 ); cvtColor(g_srcImage,g_grayImage,COLOR_BGR2GRAY); blur(g_grayImage,g_grayImage,Size(3,3)); namedWindow("srcIamge"); imshow("srcImage",g_srcImage); waitKey(); namedWindow("show"); createTrackbar("ThresholdValue:","show",&g_nThresh,g_maxThresh,on_ThreshChange); on_ThreshChange(0,0); waitKey(); return(0); } //----------------------------------【thresh_callback() function】-------------------------------------- // statement: Thresh's help function //----------------------------------------------------------------------------------------------------- static void on_ThreshChange(int,void*){ threshold(g_grayImage,g_thresholdImage_ouput,g_nThresh,255,THRESH_BINARY); findContours(g_thresholdImage_ouput,g_vContours,g_vHierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point(0,0)); vector<vec> hull(g_vContours.size()); for(unsigned int i =0;i < g_vContours.size();i++) convexHull(Mat(g_vContours[i]),hull[i],false); Mat drawing = Mat::zeros(g_thresholdImage_ouput.size(),CV_8UC3); for(unsigned int i = 0;i<g_vContours.size();i++){ Scalar color = Scalar(g_rng.uniform(0,255),g_rng.uniform(0,255),g_rng.uniform(0,255)); drawContours(drawing,g_vContours,i,color,1,8,vector<Vec4i>(),0,Point()); drawContours(drawing,hull,i,color,1,8,vector<Vec4i>(),0,Point()); } imshow("show",drawing); }
效果如下:
这里有更完整的代码介绍:
https://github.com/LiangjunFeng/Implement-OpenCV
相关文章推荐
- OpenCV在图像中寻找轮廓和计算图像中物体的凸包
- 【OpenCV笔记 15-1】OpenCV寻找物体的凸包convexHull
- OpenCV之imgproc 模块. 图像处理(5)在图像中寻找轮廓 计算物体的凸包 创建包围轮廓的矩形和圆形边界框 为轮廓创建可倾斜的边界框和椭圆 轮廓矩 多边形测试
- opencv学习(四十)之寻找图像轮廓findContours()
- 基于opencv,设置findcontours参数减提取中间轮廓
- OpenCV示例学习笔记(1)-contours2.cpp-通过findContours 函数实现轮廓提取
- opencv3检测凸包convexHull函数-使用方法一-滚动条
- OpenCV通过cvFindContours与cvDrawCountours函数查找轮廓
- opencv cvFindContours 查找轮廓 cvDrawCountours 用法及例子
- opencv3检测凸包convexHull函数-使用方式二
- opencv查找轮廓---cvFindContours && cvDrawCountours 用法及例子
- 提取轮廓在OpenCV里有一个函数 cvFindContours
- opencv3检测凸包convexHull函数-使用方式二-滚动条
- Opencv findContours轮廓检测返回轮廓数过多时程序崩溃问题解决
- opencv查找轮廓---cvFindContours && cvDrawCountours 用法及例子
- opencv开发笔记(十三):寻找和绘制物体的凸包
- opencv之查找轮廓---cvFindContours && cvDrawCountours 用法及例子
- 提取轮廓函数 cvFindContours ---OpenCV
- Opencv通过cvFindContours找到的轮廓图时暗时亮
- OpenCV示例学习笔记(1)-contours2.cpp-通过findContours 函数实现轮廓提取