专栏首页李蔚蓬的专栏计算机视觉 OpenCV Android | 基本特征检测 之 轮廓分析

计算机视觉 OpenCV Android | 基本特征检测 之 轮廓分析

(0)轮廓分析概述及作用

  • 通过将Canny边缘提取或者二值化结果作为输入图像来实现轮廓发现与绘制, 可是这些并不是我们想要的最终结果, 我们一般根据获取到的轮廓求出它们的外接矩形或者最小外接矩形, 并计算外接矩形横纵比例、轮廓面积、周长等数据然后使用这些数据实现特定几何形状轮廓查找与过滤 后续的处理与分析剔除不正确的区域保留候选对象
(1)边界框
  • 最常见的获取轮廓的外接矩形边界框, 获取每个轮廓的边界框, 通过可以得到与各个轮廓相对应的高度与宽度, 并能通过它计算出轮廓的纵横比

通过轮廓点集合得到轮廓边界框的API如下:

boundingRect(MatOfPoint points)

其中,points轮廓所有点的集合对象注意其数据类型。

调用该API会返回一个Rect对象实例,它是OpenCV关于矩形的数据结构, 从中可以得到外界矩形(边界框)的宽高, 然后就可以计算出轮廓的横纵比了。

这种情况下得到的边界框不一定满足条件,有时候我们还需要获取轮廓的最小边界框

(2)最小边界框

与上面边界框不同的是, 获取到的最小边界框有时候不是一个水平或者垂直的矩形而是一个旋转了一定角度的矩形

但是最小外接矩形(最小边界框)能够更加真实地反映出轮廓的几何结构大小 横纵比结果更能反映出轮廓的真实几何特征 所以有些时候我们计算的经常最小外接矩形

相关API函数如下:

RotatedRect minAreaRect(MatOfPoint2f points)

其中,points是轮廓的所有点的集合对象。注意其数据类型。

  • 调用该API会返回一个RotatedRect对象实例, 它是OpenCV关于旋转矩形的数据结构, 其包含了旋转角度,矩形的宽、高及四个顶点等信息, 通过相关的API都可以查询获得, 绘制旋转矩形对象的时候, 首先需要得到四个顶点, 然后通过OpenCV绘制直线的API完成旋转矩形的绘制
(3)面积与周长
  • 轮廓分析中包含了轮廓大小的度量, 这些度量最常见的就是计算轮廓的面积大小长度大小这些数据对分析轮廓过滤掉一些不符合条件的轮廓十分有用。

计算轮廓面积的API如下:

contourArea(Mat contour, boolean oriented)

contour:轮廓的所有点集合对象oriented:表示轮廓的方向,当oriented = true返回的面积是一个有符号值,默认为false,返回的是绝对值

计算轮廓周长的API如下:

arcLength(MatOfPoint2f curve, boolean closed)

curve:轮廓的所有点集合对象注意数据类型。 closed:表示是否为闭合曲线,默认是true

完整的发现获取轮廓、外接轮廓、最小外接轮廓、横纵比、面积与长度的代码演示如下:

private void measureContours(Mat src, Mat dst) {
  Mat gray= new Mat();
  Mat binary = new Mat();

  // 二值
  Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
  Imgproc.threshold(gray, binary, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);

  // 轮廓发现
  List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
  Mat hierarchy = new Mat();
  Imgproc.findContours(binary, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));

  // 测量轮廓
  dst.create(src.size(), src.type());
  for(int i=0; i<contours.size(); i++) {
      Rect rect = Imgproc.boundingRect(contours.get(i));
      double w = rect.width;
      double h = rect.height;
      double rate = Math.min(w, h)/Math.max(w, h);
    Log.i("Bound Rect", "rate:" + rate);//一个轮廓元素打印一次

    RotatedRect minRect = Imgproc.minAreaRect(new MatOfPoint2f(contours.get(i).toArray()));
    w = minRect.size.width;
    h = minRect.size.height;
    rate = Math.min(w, h)/Math.max(w, h);
    Log.i("Min Bound Rect", "rate:" + rate);

    double area = Imgproc.contourArea(contours.get(i), false);
    double arclen = Imgproc.arcLength(new MatOfPoint2f(contours.get(i).toArray()), true);
    Log.i("contourArea", "area:" + rate);
    Log.i("arcLength", "arcLength:" + arclen);
    Imgproc.drawContours(dst, contours, i, new Scalar(0, 0, 255), 1);
  }

  // 释放内存
  gray.release();
  binary.release();
}

运行结果(左侧是原图,右侧是轮廓发现与绘制,计算结果参见logcat):

上述的代码是求取图像的全部轮廓修改上述程序,把返回轮廓改为返回最外层轮廓RETR_EXTERNAL, 同时修改阈值化方法,将其改为THRESH_BINARY_INV, 则运行结果如下:

  • 感兴趣的小伙伴可以进一步细化该方法, 将计算得到的轮廓几何属性值如长度、面积等 通过putText函数显示到输出的图像上

参考材料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 机器人程序设计_ROS_note2

    凌川江雪
  • DSP_代码笔记(基于TMS320X281x)

    Debug: "DSP28_Gpio.c", line 51: warning: last line of file ends without a newli...

    凌川江雪
  • AT80C51串口通信编程

    凌川江雪
  • opencv 9 -- 轮廓 层次结构

    使用函数 cv2.findContours 来查找轮廓, 我们需要传入一个参数:轮廓提取模式(Contour_Retrieval_Mode)。 我们总是...

    wust小吴
  • C++ OpenCV轮廓发现

    轮廓即是以某种方式表示图像中的曲线的点的列表。这种表示可以根据实际的情形不同而不同。表示一条曲线的方式有很多种。

    Vaccae
  • TensorFlow 工程总监 Quora 问答:深度学习系统瓶颈及用户痛点

    【新智元导读】TensorFlow 工程总监Rajat Monga9月29日在Quora 上答疑,就深度学习效率瓶颈、TensorFlow 用户的痛点、如何用T...

    新智元
  • 一致性哈希算法(consistent hashing)

    Mister24
  • 操作系统-进程

    (2)阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态转换为就绪态。

    CherishTheYouth
  • IO模型梳理-从操作系统到应用层

    IO模型是编程语言和软件开发中重要的知识。本篇从IO模型这个切入点横向梳理了从操作系统到应用层IO模型相关知识。考虑到技术本身具有横向迁移的特点,也可以帮助大家...

    春哥大魔王
  • 【CSDN AI 周刊】第11期 | 周志华提出深度森林 引发持续热议

    用户1737318

扫码关注云+社区

领取腾讯云代金券