opencv——轮廓发现与轮廓分析

Posted 唯有自己强大

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv——轮廓发现与轮廓分析相关的知识,希望对你有一定的参考价值。

引言

二值图像分析最常见的一个主要方式就是轮廓发现轮廓分析,其中轮廓发现的目的是为轮廓分析做准备,经过轮廓分析我们可以得到轮廓各种有用的属性信息。

这里顺带提下边缘检测,和轮廓提取的区别:

边缘检测主要是通过一些手段检测数字图像中明暗变化剧烈(即梯度变化比较大)像素点,偏向于图像中像素点的变化。如canny边缘检测,结果通常保存在和源图片一样尺寸和类型的边缘图中。 
轮廓检测指检测图像中的对象边界,更偏向于关注上层语义对象。如OpenCV中的findContours()函数, 它会得到每一个轮廓并以点向量方式存储,除此也得到一个图像的拓扑信息,即一个轮廓的后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓的索引编号。 


一,轮廓的发现与绘制


 在OpenCV里面利用findContours()函数和drawContours()函数实现这一功能。

  • findContours()函数
void findContours(
InputArray          image,
OutputArrayOfArrays contours,
OutputArray         hierarchy,
int                 mode,
int                 method,
Point               offset = Point()
                  )

参数一: image,输入图像、八位单通道的,背景为黑色的二值图像。(一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像)

参数二:contours,输出轮廓图像。是一个向量,向量的每个元素都是一个轮廓。因此,这个向量的每个元素仍是一个向量。即:

           vector<vector<Point> > contours;

参数三:hierarchy,输出各个轮廓的继承关系。hierarchy也是一个向量,长度和contours相等,每个元素和contours的元素对应。hierarchy的每个元素是一个包含四个整型数的向量。即:

           vector<Vec4i> hierarchy;

参数四:mode,检测轮廓的方法。有四种方法:

  1. RETR_EXTERNAL:只检测外轮廓。忽略轮廓内部的洞。
  2. RETR_LIST:检测所有轮廓,但不建立继承(包含)关系。
  3. RETR_TREE:检测所有轮廓,并且建立所有的继承(包含)关系。
  4. RETR_CCOMP:检测所有轮廓,但是仅仅建立两层包含关系。

参数五:method,每个轮廓的编码信息。也有四种(常用前两种)

  1. CHAIN_APPROX_NONE:把轮廓上所有的点存储。
  2. CHAIN_APPROX_SIMPLE:只存储轮廓上的拐点。
  3. CHAIN_APPROX_TC89_L1,CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

参数六: Point,偏移量。默认为0

注意该函数将白色区域当作前景物体。所以findContours()函数是黑色背景下找白色轮廓。(重要!!!)

  • drawContours()函数
drawContours(
      InputOutputArray  binImg, // 输出图像
      OutputArrayOfArrays  contours,//  全部发现的轮廓对象
      Int contourIdx// 轮廓索引号,-1表示绘制所有轮廓
      const Scalar & color,// 绘制时候颜色
      int  thickness,// 绘制线宽,-1表示填充轮廓内部
      int  lineType,// 线的类型LINE_8
      InputArray hierarchy,// 拓扑结构图
      int maxlevel,// 最大层数, 0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓
      Point offset = Point()// 轮廓位移,可选

二,轮廓分析


 在得到图像的轮廓以后,我们就可以进行轮廓分析。经过轮廓分析我们可以得到轮廓各种有用的属性信息、常见的如下: 

  • 计算轮廓面积 : 

contourArea(contour, oriented = False)  //计算轮廓的面积

参数说明:contour为输入的单个轮廓值;oriented:轮廓方向,默认值false。
如果为true,该函数返回一个带符号的面积,其正负取决于轮廓的方向(顺时针还是逆时针)。
如果是默认值false,则面积以绝对值的形式返回.
根据这个特性可以根据面积的符号来确定轮廓的位置。
  • 计算轮廓周长:arcLength()

arcLength(contour, closed)   //  计算轮廓的周长
参数说明:contour为输入的单个轮廓值,closed表示轮廓是否封闭(true为封闭,false为不封闭)
  • 计算几何矩与中心距: moments()

  Moments m = moments(contours[t]); //获取轮廓的距
//计算轮廓质心
    double cx = m.m10 / m.m00;
    double cy = m.m01 / m.m00;
  • 轮廓的外接矩形

轮廓的外接矩形有两种,如下图,绿色的叫外接矩形boundingRect(),表示不考虑旋转并且能包含整个轮廓的矩形。蓝色的叫最小外接矩形minAreaRect(),考虑了旋转

1️⃣外接矩形boundingRect()

Rect  rect = boundingRect(Mat(contours[i]));//获取轮廓外接正矩形
rectangle(src, rect, (0, 0, 255), 2, 8, 0);

2️⃣最小外接矩形minAreaRect()

RotatedRect rect = minAreaRect(contours[i]);//获取轮廓最小外接矩形
Point2f P[4];
rect.points(P);//获取四顶点坐标
for (int j = 0; j <= 3; j++)
{
    line(src, P[j], P[(j + 1) % 4], Scalar(0,0,255), 1);//依次连线
}
  • 最小外接圆/拟合圆:minEnclosingCircle()

void minEnclosingCircle(InputArray points, Point2f& center, float& radius);
points,输入的二维点集,可以是 vector 或 Mat 类型。
center,圆的输出圆心。
radius,圆的输出半径。
 
例如:
    findContours(bin_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
    //寻找包裹轮廓的最小圆
    vector<Point2f>centers(contours.size());//圆心个数
    vector<float>radius(contours.size());//半径个数
    for (int i = 0; i < contours.size(); i++) 
{
//寻找并绘制最小圆 minEnclosingCircle(contours[i], centers[i], radius[i]); circle(src, centers[i], radius[i], scalar(0,0,255), 2); }
  • 拟合椭圆:fitEllipse()
RotatedRect fitEllipse(InputArray points);
//唯一一个参数是输入的二维点集,可以是 vector 或 Mat 类型。

例如:
//寻找并绘制最小椭圆 rota_rect[i]
= fitEllipse(contours[i]); ellipse(dst, rota_rect[i], scalar(0,0,255), 2);
  • 轮廓的凸包:convexHull()

convexHull (   InputArray  points,         /输入的二维点集,Mat类型数据即可
               OutputArray     hull,       //输出参数,用于输出找到的凸包
               bool   clockwise = false,   //操作方向,当标识符为真时,输出凸包为顺时针方向,否则为逆时针方向。
               bool  returnPoints = true   //操作标识符,默认值为true,此时返回各凸包的各个点,否则返回凸包各点的指数
            )
  • 多边形逼近-逼近真实形状:approxPolyDP()

void approxPolyDP(        InputArray curve,        //输入曲线,一般是由图像的轮廓点组成的点集
                          OutputArray approxCurve, //表示输出的多边形点集
                          double epsilon,          //主要表示输出的精度,就是另个轮廓点之间最大距离数
                          bool closed              //表示输出的多边形是否封闭
                  )

 

以上是关于opencv——轮廓发现与轮廓分析的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV中几何形状识别与测量

OpenCV中几何形状识别与测量

OpenCV中几何形状识别与测量

youcans 的 OpenCV 例程200篇195.绘制图像轮廓(cv.drawContours)

youcans 的 OpenCV 例程200篇195.绘制图像轮廓(cv.drawContours)

高级特征提取