OpenCV | 二值图像分析的技巧都在这里

  • 2020 年 2 月 21 日
  • 筆記

轮廓属性

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

  • 轮廓面积
  • 轮廓周长
  • 轮廓几何矩
  • 轮廓的最小外接矩形
  • 轮廓的最大外接矩形
  • 轮廓的最小外接圆
  • 轮廓的最小外接三角形
  • 轮廓拟合(支持拟合直线、椭圆、圆)
  • 轮廓的凸包
  • 轮廓层次信息提取
  • 多边形逼近
  • 计算欧拉数

函数介绍

OpenCV中提供大量轮廓分析函数,通过这些函数我们可以方便快捷的得到轮廓的各种有用属性信息、高效完成各种二值图像分析需求,下面是我总结的一些常用的函数列表与说明。

OpenCV中轮廓发现函数如下:

void cv::findContours(  InputArray      image,  OutputArrayOfArrays contours,  OutputArray hierarchy,  int   mode,  int   method,  Point       offset = Point()  )  

参数解释如下:

image: 输入图像、八位单通道的,背景为黑色 contours: 得到的轮廓图像 hierarchy: 层次图像,根据需要提取轮廓层次信息 mode: 决定提取到层次信息内容,是多层还是单层 method: 每个轮廓的编码信息 offset: 表示轮廓偏移,默认为0

轮廓分析相关的常用函数

// 计算轮廓面积  double cv::contourArea(  InputArray contour,  bool oriented = false  )  // 计算轮廓周长  double cv::arcLength(  InputArray      curve,  bool        closed  )  // 计算几何矩与中心距  Moments cv::moments(  InputArray      array,  bool        binaryImage = false  )  // 计算最小外接矩形  RotatedRect cv::minAreaRect(  InputArray      points  )  // 计算最大外接矩形  Rect cv::boundingRect(  InputArray      array  )  // 计算最小外接圆/拟合圆  void cv::minEnclosingCircle(  InputArray      points,  Point2f &        center,  float &    radius  )  // 计算最小外接三角形/拟合三角形  double cv::minEnclosingTriangle(  InputArray      points,  OutputArray   triangle  )  // 拟合直线  void cv::fitLine(  InputArray      points,  OutputArray   line,  int   distType,  double    param,  double    reps,  double    aeps  )  // 拟合椭圆  RotatedRect cv::fitEllipse(  InputArray      points  )  // 计算凸包  void cv::convexHull(  InputArray      points,  OutputArray   hull,  bool        clockwise = false,  bool        returnPoints = true  )  // 多边形逼近-逼近真实形状  void cv::approxPolyDP(  InputArray      curve,  OutputArray   approxCurve,  double    epsilon,  bool        closed  )

灵活使用上述轮廓属性信息,可以实现对二值图像的几何形状判别、测量、面积过滤、获取每个对象的几何属性包括面积、周长、编码点、形状、层次/位置信息、欧拉数、中心位置、倾斜角度。

综合运用代码演示

2020年 以前我分享过一些综合使用的例子,列表如下(都看过你就赢了):

二值图像分析案例精选

OpenCV二值图像案例分析精选 | 第二期

OpenCV轮廓层次分析实现欧拉数计算

OpenCV寻找复杂背景下物体的轮廓

如何识别出轮廓准确的长和宽

OpenCV中几何形状识别与测量

OpenCV中BLOB特征提取与几何形状分类

OpenCV直线拟合检测

OpenCV中实现曲线与圆拟合

这里再分享一个硬币计数的例子!

原图如下:

代码如下:

// 加载图像  Mat img = imread("D:/CoinsB.png");  imshow("Original Image", img);    // 阈值化操作  Mat gray, binary;  cvtColor(img, gray, COLOR_BGR2GRAY);  float t = threshold(gray, binary, 0, 255, THRESH_BINARY|THRESH_OTSU);  imshow("binary", binary);  imwrite("D:/binary1.png", binary);    // 形态学操作  Mat se = getStructuringElement(MORPH_RECT, Size(3, 3));  morphologyEx(binary, binary, MORPH_OPEN, se, Point(-1, -1));    // 轮廓发现  vector<Vec4i> hireachy;  vector<vector<Point>> contours;  bitwise_not(binary, binary);  findContours(binary, contours, hireachy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());  Mat result = img.clone();  Point2f center;  float radius;    // 轮廓分析  for (size_t t = 0; t < contours.size(); t++) {      double area = contourArea(contours[t]);      if (area < 1000) {          continue;      }      RotatedRect rrt = fitEllipse(contours[t]);      radius = min(rrt.size.width, rrt.size.height)/2.0;      circle(result, rrt.center, radius, Scalar(0, 0, 255), 4, 8, 0);      Moments mm = moments(contours[t]);      double cx = mm.m10 / mm.m00;      double cy = mm.m01 / mm.m00;      circle(result, Point(cx, cy), 2, Scalar(255, 0, 0), 2, 8, 0);  }    // 显示结果  imshow("result", result);  imwrite("D:/drawing.png", result);  waitKey(0);

最终效果如下:

2020年少写废话,觉得不是废话就点赞,做好自己该做的事情就是对自己最好的交待!