• OpenCV 中的轮廓-查找轮廓的不同特征,例如面积,周长,重心,边界框等。


    轮廓特征

    目标

    • 查找轮廓的不同特征,例如面积,周长,重心,边界框等。
    • 你会学到很多轮廓相关函数


      图像的矩可以帮助我们计算图像的质心,面积等。详细信息请查看维基百科Image Moments。
      函数 cv2.moments() 会将计算得到的矩以一个字典的形式返回。如下:

    # -*- coding: utf-8 -*-
    """
    Created on Sun Jan 12 18:30:17 2014
    @author: duan
    """
    import cv2
    import numpy as np
    img = cv2.imread('star.jpg',0)
    ret,thresh = cv2.threshold(img,127,255,0)
    contours,hierarchy = cv2.findContours(thresh, 1, 2)
    cnt = contours[0] M = cv2.moments(cnt)
    print M
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    根据这些矩的值,我们可以计算出对象的重心:
    在这里插入图片描述

    cx = int(M['m10']/M['m00'])
    cy = int(M['m01']/M['m00'])
    
    • 1
    • 2

    轮廓面积
    轮廓的面积可以使用函数 cv2.contourArea() 计算得到,也可以使用矩(0 阶矩),M[‘m00’]。

    area = cv2.contourArea(cnt)
    
    • 1

    轮廓周长
      也被称为弧长。可以使用函数 cv2.arcLength() 计算得到。这个函数的第二参数可以用来指定对象的形状是闭合的(True),还是打开的(一条曲线)。

    perimeter = cv2.arcLength(cnt,True)
    
    • 1

    轮廓近似
      将轮廓形状近似到另外一种由更少点组成的轮廓形状,新轮廓的点的数目由我们设定的准确度来决定。使用的Douglas-Peucker算法,你可以到维基百科获得更多此算法的细节。
      
      为了帮助理解,假设我们要在一幅图像中查找一个矩形,但是由于图像的种种原因,我们不能得到一个完美的矩形,而是一个“坏形状”(如下图所示)。现在你就可以使用这个函数来近似这个形状()了。这个函数的第二个参数叫epsilon,它是从原始轮廓到近似轮廓的最大距离。它是一个准确度参数。选择一个好的epsilon 对于得到满意结果非常重要。

    epsilon = 0.1*cv2.arcLength(cnt,True)
    approx = cv2.approxPolyDP(cnt,epsilon,True)
    
    • 1
    • 2

    下边,第二幅图中的绿线是当 epsilon = 10% 时得到的近似轮廓,第三幅图是当 epsilon = 1% 时得到的近似轮廓。第三个参数设定弧线是否闭合。
    在这里插入图片描述
    凸包
      凸包与轮廓近似相似,但不同,虽然有些情况下它们给出的结果是一样的。函数 cv2.convexHull() 可以用来检测一个曲线是否具有凸性缺陷,并能纠正缺陷。一般来说,凸性曲线总是凸出来的,至少是平的。如果有地方凹进去了就被叫做凸性缺陷。例如下图中的手。红色曲线显示了手的凸包,凸性缺陷被双箭头标出来了。
    在这里插入图片描述
    关于他的语法还有一些需要交代:

    hull = cv2.convexHull(points[, hull[, clockwise[, returnPoints]]
    
    • 1

    参数:
    • points 我们要传入的轮廓
    • hull 输出,通常不需要
    • clockwise 方向标志。如果设置为 True,输出的凸包是顺时针方向的。否则为逆时针方向。
    • returnPoints 默认值为 True。它会返回凸包上点的坐标。如果设置为 False,就会返回与凸包点对应的轮廓上的点。

    要获得上图的凸包,下面的命令就够了:

    hull = cv2.convexHull(cnt)
    
    • 1

    但是如果你想获得凸性缺陷,需要把 returnPoints 设置为 False。以上面的矩形为例,首先我们找到他的轮廓 cnt。现在我把 returnPoints 设置为 True 查找凸包,我得到下列值:
      [[[234 202]], [[ 51 202]], [[ 51 79]], [[234 79]]],其实就是矩形的四个角点。
      现在把 returnPoints 设置为 False,我得到的结果是[[129],[ 67],[ 0],[142]]
      他们是轮廓点的索引。例如:cnt[129] = [[234, 202]],这与前面我们得到结果的第一个值是一样的。
      在凸检验中你我们还会遇到这些。
      
    凸性检测
    函数 cv2.isContourConvex() 可以可以用来检测一个曲线是不是凸的。它只能返回 True 或 False。没什么大不了的。

    k = cv2.isContourConvex(cnt)
    
    • 1

    边界矩形
    有两类边界矩形。

    直边界矩形 一个直矩形(就是没有旋转的矩形)。它不会考虑对象是否旋转。所以边界矩形的面积不是最小的。可以使用函数 cv2.boundingRect() 查找得到。
      (x,y)为矩形左上角的坐标,(w,h)是矩形的宽和高。

    x,y,w,h = cv2.boundingRect(cnt)
    img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
    
    • 1
    • 2

    旋转的边界矩形 这个边界矩形是面积最小的,因为它考虑了对象的旋转。用到的函数为 cv2.minAreaRect()。返回的是一个 Box2D 结构,其中包含矩形左上角角点的坐标(x,y),矩形的宽和高(w,h),以及旋转角度。但是要绘制这个矩形需要矩形的 4 个角点,可以通过函数 cv2.boxPoints() 获得。

    x,y,w,h = cv2.boundingRect(cnt)
    img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
    
    • 1
    • 2

    把这两中边界矩形显示在下图中,其中绿色的为直矩形,红的为旋转矩形。
    在这里插入图片描述
    最小外接圆
      函数 cv2.minEnclosingCircle() 可以帮我们找到一个对象的外切圆。它是所有能够包括对象的圆中面积最小的一个。

    (x,y),radius = cv2.minEnclosingCircle(cnt)
    center = (int(x),int(y))
    radius = int(radius)
    img = cv2.circle(img,center,radius,(0,255,0),2)
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述
    椭圆拟合
    使用的函数为 cv2.ellipse(),返回值其实就是旋转边界矩形的内切圆。

    ellipse = cv2.fitEllipse(cnt)
    im = cv2.ellipse(im,ellipse,(0,255,0),2)
    
    • 1
    • 2

    在这里插入图片描述
    直线拟合
      我们可以根据一组点拟合出一条直线,同样我们也可以为图像中的白色点拟合出一条直线。

    rows,cols = img.shape[:2]
    #cv2.fitLine(points, distType, param, reps, aeps[, line ]) → line
    #points – Input vector of 2D or 3D points, stored in std::vector<> or Mat.
    #line – Output line parameters. In case of 2D fitting, it should be a vector of
    #4 elements (likeVec4f) - (vx, vy, x0, y0), where (vx, vy) is a normalized
    #vector collinear to the line and (x0, y0) is a point on the line. In case of
    #3D fitting, it should be a vector of 6 elements (like Vec6f) - (vx, vy, vz,
    #x0, y0, z0), where (vx, vy, vz) is a normalized vector collinear to the line
    #and (x0, y0, z0) is a point on the line.
    #distType – Distance used by the M-estimator
    #distType=CV_DIST_L2
    #ρ(r) = r2 /2 (the simplest and the fastest least-squares method)
    #param – Numerical parameter ( C ) for some types of distances. If it is 0, an optimal value
    #is chosen.
    #reps – Sufficient accuracy for the radius (distance between the coordinate origin and the
    #line).
    #aeps – Sufficient accuracy for the angle. 0.01 would be a good default value for reps and
    #aeps.
    [vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)
    lefty = int((-x*vy/vx) + y)
    righty = int(((cols-x)*vy/vx)+y)
    img = cv2.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

  • 相关阅读:
    全国第一届学生(青年)运动会女子拳击比赛60公斤冠军载誉归来
    斩获 offer 的 Java 面试宝典
    cocosCreator2.4.x 打包 ios ,xcode问题记录
    Redis主从、哨兵、 Cluster集群一锅端!
    【MySQL教程】| (1-1) 2023MySQL-8.1.0 安装教程
    江苏魔百盒M301H_Hi3798MV300-300H-310芯片通刷-免费卡刷固件包
    Python 能力提升之这 9 个 Python 特性被严重低估了
    Freeswitch学习笔记(三):配置
    字学课程--实时音视频通讯技术--RTC使用场景
    codesys 6轴机器人正解程序
  • 原文地址:https://blog.csdn.net/yyyyyya_/article/details/125475617