opencv学习笔记(二)寻找轮廓

  opencv中使用findContours函数来查找轮廓,这个函数的原型为:

  1. void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierar-
  2. chy, int mode, int method, Point offset=Point())
  3.  
  4. /*
  5. 参数说明:
  6.  
  7. image:输入图像image必须为一个2值单通道图像;
  8.  
  9. contours:为检测的轮廓数组,每一个轮廓用一个point类型的vector表示,vector<Point>,则轮廓的集合可表示为vector<vector<Point>>;
  10.  
  11. hiararchy:参数和轮廓个数相同,每个轮廓contours[i]对应hierarchy元素hierarchy[i][0]—hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数;
  12.  
  13. mode:轮廓的检索模式
  14.  
  15. a.CV_RETR_EXTERNAL:表示只检测外轮廓
  16.  
  17. b.CV_RETR_LIST:检测的轮廓不建立登记关系
  18.  
  19. c.CV_RETR_CCOMP:建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
  20.  
  21. d.CV_RETR_TREE:建立一个等级树结构的轮廓。
  22.  
  23. method:轮廓的近似方法
  24.  
  25. a.CV_CHAIN_APPROX_NONE:存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2)),abs(y2-y1))==1
  26.  
  27. b.CV_CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
  28.   c.CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法offset表示代表轮廓点的偏移量,可以设置为任意值。对ROI图像中找出的轮廓,并要在整个图像中进行分析时,这个参数还是很有用的。
  29. */

  findContours后会对输入的2值图像改变,所以如果不想改变该2值图像,需创建新mat来存放,findContours后的轮廓信息contours可能过于复杂不平滑,可以用approxPolyDP函数对该多边形曲线做适当近似;contourArea函数可以得到当前轮廓包含区域的大小,方便轮廓的筛选。

  findContours函数经常与drawcontours配合使用,用来将轮廓绘制出来,函数原型为:

  1. void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=, int lineType=, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )
  2.  
  3. /*
  4. 参数说明:
  5.  
  6. image:目标图像
  7.  
  8. contours:输入的轮廓组,每一组轮廓由点vector构成
  9.  
  10. contourIdx:指明画第几个轮廓,如果该参数为负值,则画全部轮廓
  11.  
  12. color:轮廓的颜色
  13.  
  14. thickness:轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内容
  15.  
  16. lineType:为线型
  17.  
  18. hierarchy:如果你想画出图像的一部分轮廓,那么你就需要它
  19.  
  20. maxLevel:用于画轮廓的最大成,如果为0,只是画出指定轮廓,如果为1,画出第一层的所有轮廓,如果为2,画出第一和第二层的所有轮廓,依次类推,这个参数只有在有层次关系的时候被使用
  21.  
  22. offset:每个轮廓点的偏移量
  23.  
  24. */

  得到了复杂轮廓往往不适合特征的检测,这里再介绍一个点集凸包络的提取函数convexHull,输入参数就可以是contours组中的一个轮廓,返回外凸包络的点集。

  还可以得到轮廓的外包络矩形,使用boundingRect,函数原型为:

  1. Rect boundingRect(InputArray points)
  2.  
  3. //  points:二维点集
  4. //  返回:包围轮廓的2D矩形的模板类Rect
  5. //功能:对指定的点集进行包含,使得形成一个最合适的正向矩形框把当前指定的点集都框住

  如果想得到旋转的外包络矩形,使用函数minAreaRect 函数原型:

  1. RotatedRect minAreaRect(InputArray points)
  2. //points:输入的2维向量点,其类型为:std::vector<> or Mat
  3. ////函数功能:为一个指定的点集计算并返回的最小边界矩形(可能旋转)
    4 //返回值类型:RotatedRect

  也可以得到轮廓的外包络圆,对应的函数为minEnclosingCircle;想得到轮廓的外包络椭圆,对应的函数为fitEllipse,返回值也是RotatedRect类型,可以用ellipse函数画出对应的椭圆;

  如果想根据多边形的轮廓信息得到多边形的多阶矩,可以使用类moments;

  如果想获得一点与多边形封闭轮廓信息,可以调用pointPolygonTest函数,这个函数返回值为该点距离轮廓最近边界的距离,为正值为在轮廓内部,负值为在轮廓外部,0表示在边界上。

Example

  1. #include "opencv2/highgui/highgui.hpp"
  2. #include "opencv2/imgproc/imgproc.hpp"
  3. #include <iostream>
  4. using namespace cv;
  5. using namespace std;
  6. int main()
  7. {
  8.  
  9. const char* inputImage = "rice.jpg";//输入图像名称
  10. Mat img;
  11. img = imread(inputImage, );
  12. //判断图像存在与否
  13. if (img.empty())
  14. {
  15. cout << "Could not read input image file: " << inputImage << endl;
  16. return -;
  17. }
  18.  
  19. namedWindow("Img", );
  20. imshow("Img", img);
  21. //二值化,为提取轮廓做准备
  22. threshold(img, img, , , CV_THRESH_OTSU + CV_THRESH_BINARY);
  23. namedWindow("thr_img", );
  24. imshow("thr_img", img);
  25. //创建轮廓集合
  26. vector<vector<Point> > contours;
  27. //创建层级hierarchy
  28. vector<Vec4i>hierarchy;
  29. Mat dst = Mat::zeros(img.rows, img.cols, CV_8UC3);
  30. findContours(img, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
  31. if (!contours.empty() && !hierarchy.empty())
  32. {
  33. int idx = ;
  34. for (; idx >= ; idx = hierarchy[idx][])//hierarchy[idx][0]表示当前轮廓序号idx的下一个轮廓
  35. {
  36. Scalar color((rand() & ), (rand() & ), (rand() & ));
  37. drawContours(dst, contours, idx, color, , , hierarchy);
  38. }
  39. }
  40. namedWindow("Connected Components", );
  41. imshow("Connected Components", dst);
  42. waitKey();
  43. return ;
  44. }

opencv学习笔记(二)寻找轮廓的更多相关文章

  1. 【opencv学习笔记二】opencv3.4.0组件结构说明

    在学习opencv使用之前我们先来看一下opencv有哪些组件结构.至于OpenCV组件结构的研究方法, 我们不妨管中窥豹,通过opencv安装路径下include目录里面头文件的分类存放,来一窥Op ...

  2. OpenCV学习笔记二:OpenCV模块一览

    注:本系列博客基于OpenCV 2.9.0.0 一,一览图: 二,模块: /* 基础库 */ 1,opencv_core(链接) ,opencv最基础的库.包含exception,point,rect ...

  3. OpenCV学习笔记二十:opencv_ts模块

    一,简介: OpenCV测试库,用于单元测试.

  4. OpenCV学习笔记(二) - 写入视频、jpg格式

    写入视频: import sys, os import cv2 imgDir = '/Users/xxx/salient/' videoName = 'vname' fps = 30 #帧频 outp ...

  5. opencv学习笔记二

    1,读取照片(imread()) 2,处理照片(cvtcolor()) 3,命名窗口(namewindow()) 4,显示照片(imshow()) 5,保存照片(imwrite()) #include ...

  6. OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓

    本节代码使用的opencv-python 4.0.1,numpy 1.15.4 + mkl 使用图片为 Mjolnir_Round_Car_Magnet_300x300.jpg 代码如下: impor ...

  7. OpenCV 学习笔记03 boundingRect、minAreaRect、minEnclosingCircle、boxPoints、int0、circle、rectangle函数的用法

    函数中的代码是部分代码,详细代码在最后 1 cv2.boundingRect 作用:矩形边框(boundingRect),用于计算图像一系列点的外部矩形边界. cv2.boundingRect(arr ...

  8. OpenCV 学习笔记03 findContours函数

    opencv-python   4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ...

  9. OpenCV 学习笔记 02 使用opencv处理图像

    1 不同色彩空间的转换 opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度.BRG.HSV(Hue-Saturation-Value) 灰度 - 灰度色彩空间是通过去除彩 ...

随机推荐

  1. 用requests库实现登录遇到的问题

    想登录zhihu,然后总是得到403 foribidden的错误,各种谷歌百度,得到结论说是输入错误或者是url错误,用fldder发现的确是url错了,post的地址是错误的 ==. 开始以为是#s ...

  2. 安卓系统源码编译系列(六)——单独编译内置浏览器WebView教程

    原文                   http://blog.csdn.net/zhaoxy_thu/article/details/18883015                 本文主要对从 ...

  3. SCU 4424(求子集排列数)

    A - A Time Limit:0MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice ...

  4. NSThread - (void)start vs java Thread implements Runnable

    This method spawns the new thread and invokes the receiver’s main method on the new thread. If you i ...

  5. truncate的用法

    truncate是文件处理中的截断函数,今天是有个需求改动了json中的某个值,然后用改动后的值去覆盖之前的数据,这个方法有很多,比如边读边写,然后使用os模块替换,这个适合用于在程序和文件都在同一个 ...

  6. mysql join详解

    下面是例子分析 表A记录如下: aID aNum 1 a20050111 2 a20050112 3 a20050113 4 a20050114 5 a20050115 表B记录如下: bID bNa ...

  7. TCP,IP,HTTP,SOCKET区别和联系

    物理层-- 数据链路层-- 传输层--                       TCP协议 会话层-- 我 们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如 果没有应用层,便 ...

  8. Excel加密的Sheet如何hack

    Excel的加密sheet如何hack: 思路:在VBA中添加穷举法模块函数并运行 源代码: Sub PasswordBreaker() 'Breaks worksheet password prot ...

  9. 淘宝(阿里百川)手机客户端开发日记第九篇 Looper详解

    public final class Looper: 官方的API: Class used to run a message loop for a thread. Threads by default ...

  10. Unbuntu 下编译安装 PHP 必要库的安装

    2010/08/22 LINUX, PHP 2 COMMENTS 编译环境 sudo apt-get install build-essential xml sudo apt-get install ...