打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
我的OpenCV学习笔记(20):提取元素的轮廓及形状描述子

先看提取轮廓的代码:

  1. Mat image = imread("D:/picture/images/binaryGroup.bmp",0);  
  2. if(!image.data)  
  3.     return -1;  
  4. imshow("源图像",image);  
  5.   
  6. //获取轮廓  
  7. std::vector<std::vector<Point>> contours;  
  8. //获取轮廓:  
  9. findContours(image,         //图像  
  10.     contours,               //轮廓点  
  11.                     //包含图像拓扑结构的信息(可选参数,这里没有选)  
  12.     CV_RETR_EXTERNAL,           //获取轮廓的方法(这里获取外围轮廓)  
  13.     CV_CHAIN_APPROX_NONE);      //轮廓近似的方法(这里不近似,获取全部轮廓)  
  14. //打印轮廓信息  
  15. std::cout<<"共有外围轮廓:"<<contours.size()<<"条"<<std::endl;  
  16. std::vector<std::vector<Point>>::const_iterator itContours = contours.begin();  
  17. for(;itContours != contours.end();++itContours)  
  18. {  
  19.     std::cout<<"每个轮廓的长度: "<<itContours->size()<<std::endl;  
  20. }  

注意到轮廓的存储格式为std::vector<std::vector<Point>>,他说明整个轮廓是若干条轮廓按一定顺序组成的,而每个轮廓中的点也是有顺序的。

画出轮廓就比较简单了:

  1. //画出轮廓  
  2. Mat result(image.size(),CV_8U,Scalar(255));  
  3. //画出轮廓,参数为:画板,轮廓,轮廓指示(这里画出所有轮廓),颜色,线粗  
  4. drawContours(result,contours,-1,Scalar(0),2);  
  5. imshow("提取外围轮廓",result);  

还要注意提取轮廓的方法还有很多种,比如CV_RETR_LIST代表所有轮廓

  1. findContours(image,         //图像  
  2.     contours,               //轮廓点  
  3.                     //包含图像拓扑结构的信息(可选参数,这里没有选)  
  4.     CV_RETR_LIST,           //获取轮廓的方法(这里获取所有轮廓)  
  5.     CV_CHAIN_APPROX_NONE);      //轮廓近似的方法(这里不近似,获取全部轮廓  
  6. //画出轮廓  
  7. drawContours(result,contours,-1,Scalar(0),2);  
  8. imshow("提取所有轮廓",result);  

通常,这样提取的轮廓包含一些我们不希望的轮廓(比如一些小洞),或者假如我们知道我们感兴趣的物体轮廓的大概范围时,我们就可以用下面的办法缩小目标范围:

  1. //除去太长或者太短的轮廓  
  2. int cmin = 100;  
  3. int cmax = 1000;  
  4. std::vector<std::vector<Point>>::const_iterator itc = contours.begin();  
  5. while(itc != contours.end())  
  6. {  
  7.     if(itc->size() < cmin || itc->size() > cmax)  
  8.         itc = contours.erase(itc);  
  9.     else  
  10.         ++itc;  
  11. }  
  12.   
  13. //把结果画在源图像上:  
  14. Mat original = imread("D:/picture/images/group.jpg");  
  15. if(!original.data)  
  16.     return -1;  
  17. drawContours(original,contours,-1,Scalar(255,255,255),2);  
  18. imshow("动物的轮廓",original);  
  19.   
  20. //将轮廓重绘于白板上  
  21. result.setTo(Scalar(255));  
  22. drawContours(result,contours,-1,Scalar(0),1);  


怎么提取轮廓的特征呢?OpenCV提供了很多函数,我们展示其中的几个:

  1. //轮廓的形状描述子  
  2. //外接矩形  
  3. Rect r0 = boundingRect(Mat(contours[0]));  
  4. rectangle(result,r0,Scalar(0),2);  
  5.   
  6. //最小外接圆  
  7. float radius;  
  8. Point2f center;  
  9. minEnclosingCircle(Mat(contours[1]),center,radius);  
  10. circle(result,Point(center),static_cast<int>(radius),Scalar(0),2);  
  11.   
  12. //多边形估计  
  13. std::vector<Point> poly;  
  14. //参数为:输入图像的2维点集,输出结果,估计精度,是否闭合  
  15. approxPolyDP(Mat(contours[2]),poly,5,true);  
  16. std::cout<<"多边形大小:"<<poly.size()<<std::endl;  
  17. //画出结果  
  18. std::vector<Point>::const_iterator itp = poly.begin();  
  19. while(itp != poly.end()-1)  
  20. {  
  21.     line(result,*itp,*(itp+1),Scalar(0),2);  
  22.     ++itp;  
  23. }  
  24. //将第一个点和最后一点连起来  
  25. line(result,*(poly.begin()),*(poly.end()-1),Scalar(128),2);  
  26.   
  27.   
  28. //计算凸包  
  29. std::vector<Point> hull;  
  30. convexHull(Mat(contours[3]),hull);  
  31. std::vector<cv::Point>::const_iterator it= hull.begin();  
  32. while(it != (hull.end()-1))  
  33. {  
  34.     line(result,*it,*(it+1),Scalar(0),2);  
  35.     ++it;  
  36. }  
  37. line(result,*(hull.begin()),*(hull.end()-1),Scalar(0),2);  
  38.   
  39.   
  40. //计算矩信息  
  41. itc = contours.begin();  
  42. while(itc != contours.end())  
  43. {  
  44.     //计算所有的距  
  45.     Moments mom = moments(Mat(*itc++));  
  46.     //计算并画出质心  
  47.     circle(result,Point(mom.m10/mom.m00,mom.m01/mom.m00),2,Scalar(2),2);  
  48. }  
  49. imshow("形状描述子",result);  

我们再次看到,轮廓的确是有顺序的。值得注意的是矩信息:OpenCV提供了一个结构体Moments,它的元素就是计算好的矩信息,里面存放了常用的距。

其实,OpenCV还提供了许多其他的形状描述子,比如函数cv::minAreaRect计算了最小外界倾斜的矩形。函数cv::contourArea估计轮廓区域的面积(里面的像素数)。函数cv::pointPolygonTest计算一个点是否在轮廓内,cv::matchShapes测量了2两个轮廓的相似程度等等。这里就不一一介绍了。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
OpenCV—轮廓操作一站式详解:查找/筛选/绘制/形状描述与重心标注(C 版)
OpenCV系列之轮廓入门 | 二十一
OpenCV
使用 Python 和 OpenCV 构建 SET 求解器
OpenCV入门指南
OpenCV3入门教程(一)基础知识
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服