> 文档中心 > 【youcans 的 OpenCV 例程200篇】197.轮廓的基本特征

【youcans 的 OpenCV 例程200篇】197.轮廓的基本特征

OpenCV 例程200篇 总目录-202205更新

文章目录

  • 【youcans 的 OpenCV 例程200篇】197.轮廓的基本特征
    • 2. 轮廓的特征描述
      • 2.2 轮廓的面积、周长、质心近似多边形
        • 2.2.1 轮廓的面积
        • 2.2.2 轮廓的周长
        • 2.2.3 轮廓的质心
        • 2.2.4 轮廓的近似
        • 2.2.5 轮廓的凸包(凸壳)
      • 例程 12.4:轮廓的面积、周长、质心和近似多边形

【youcans 的 OpenCV 例程200篇】197.轮廓的基本特征

2. 轮廓的特征描述

在对实际图像进行轮廓查找时,得到的轮廓数量很多。获取轮廓后,通常基于轮廓的特征进行筛选、识别和处理。例如,基于轮廓的周长和面积对轮廓进行筛选,然后绘制筛选的目标轮廓或其最小外接矩形。

常用的轮廓特征,包括图像距、轮廓周长、轮廓近似、凸包、边界矩形、拟合图形等特征。

2.2 轮廓的面积、周长、质心和近似多边形

面积、周长、质心是常用的轮廓特征。

2.2.1 轮廓的面积

几何矩实质是面积或质量。函数 cv.moments() 的返回值 Moments[‘m00’] 表示轮廓面积。
轮廓的面积也可以使用函数 cv2.contourArea() 计算。

函数说明:

cv.contourArea(contour[, oriented]) → retval
  • contour:顶点构成的二维向量组(如轮廓列表 contours 中的一个轮廓)
  • oriented:定向区域标志,默认值为 False,返回面积的绝对值,Ture 时则根据轮廓方向返回带符号的数值

2.2.2 轮廓的周长

轮廓的周长可以使用函数 cv2.arcLength() 计算。

函数说明:

cv.arcLength(curve, closed=True) → retval
  • curve:以顶点构成的二维向量组表示的曲线(如轮廓列表 contours 中的一个轮廓)
  • closed:曲线闭合标志,True 表示闭合曲线

2.2.3 轮廓的质心

轮廓的质心 (Cx,Cy) 可以通过一阶矩计算:
C x =M10 /M00C y =M01 /M00 Cx = M_{10} / M_{00} \\ Cy = M_{01} / M_{00} Cx=M10/M00Cy=M01/M00

2.2.4 轮廓的近似

轮廓的近似是用顶点数量较少的多边形对轮廓进行近似,可以使用函数 cv2. approxPolyDP() 实现。近似多边形的边数取决于设定的最大近似距离。

函数说明:

cv.approxPolyDP(curve, epsilon, closed[, approxCurve]) → approxCurve
  • curve:以顶点构成的二维向量组表示的曲线(如轮廓列表 contours 中的一个轮廓)
  • approxCurve:近似多边形顶点坐标 (x,y) 的二维向量组
  • epsilon:近似精度,浮点数,原始曲线与近似多边形之间的最大距离
  • closed:曲线闭合标志,True 表示近似曲线是闭合的

2.2.5 轮廓的凸包(凸壳)

物体的凸包(凸壳)是指包含该物体的最小凸面体。在二维图像中凸壳可以想象为一条刚好包着所有点的橡皮圈。在凸壳与物体边缘之间的部分称为凸陷(Convexity defect)。

OpenCV 中的函数 cv.isContourConvex() 测试轮廓是否为凸面体,函数 cv.convexHull() 获取轮廓的凸壳 。

函数说明:

cv.convexHull(points[, hull[, clockwise[, returnPoints]]]) → hullcv.isContourConvex(contour) → retval

参数说明:

  • points:二维点向量集
  • contour:二维点向量集(如轮廓列表 contours 中的一个轮廓)
  • hull:输出凸包,凸包顶点的索引向量,或凸包顶点坐标 (x,y) 的二维向量组
  • clockwise:方向标志,默认值 False 表示逆时针方向输出凸包,True 为是顺时针
  • returnPoints:操作标志,默认值 True 表示返回凸包点集, False 返回凸包点的索引

注意事项:
函数 cv.isContourConvex() 测试轮廓是否为凸面,输入的轮廓必须没有自交叉线。
函数 cv.convexHull() 与函数 cv.drawContours() 配合,可以用来检测物体是否存在缺陷。

例程 12.4:轮廓的面积、周长、质心和近似多边形

    # 12.4 轮廓的面积、周长、质心和近似多边形    img = cv2.imread("../images/seagull01.png", flags=1)    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度图像    plt.figure(figsize=(9, 6))    plt.subplot(231), plt.axis('off'), plt.title("Origin")    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))    # HSV 色彩空间图像分割    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)  # 将图片转换到 HSV 色彩空间    lowerBlue, upperBlue = np.array([100, 43, 46]), np.array([124, 255, 255])  # 蓝色阈值    segment = cv2.inRange(hsv, lowerBlue, upperBlue)  # 背景色彩图像分割    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))  # (5, 5) 结构元    binary = cv2.dilate(cv2.bitwise_not(segment), kernel=kernel, iterations=3)  # 图像膨胀    plt.subplot(232), plt.axis('off'), plt.title("Tree contour")    plt.imshow(binary, 'gray')    # 寻找二值化图中的轮廓    # binary, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # OpenCV3    contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # OpenCV4~    print("len(contours) = ", len(contours))  # 所有轮廓的列表    # #  绘制全部轮廓,contourIdx=-1 绘制全部轮廓    for i in range(len(contours)):  # 绘制第 i 个轮廓 if hierarchy[0][i][3]==-1:  # 最外层轮廓     rect = cv2.minAreaRect(contours[i])  # 最小外接矩形     x, y = int(rect[0][0]), int(rect[0][1])  # 最小外接矩形的中心(x,y)     text = "{}:({},{})".format(i, x, y)     img = cv2.drawContours(img, contours, i, (255, 255, 255), -1)  # 绘制第 i 个轮廓, 内部填充     img = cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255))     # print("i=", i, ",contours[i]:", contours[i].shape, ",hierarchy[0][i] =", hierarchy[0][i], "text=", text)    plt.subplot(233), plt.axis('off'), plt.title("Contours")    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))    # 轮廓的特征矩    cnt = contours[0]  # 第 0 个轮廓    moments = cv2.moments(cnt)  # 返回字典,几何矩 mpq, 中心矩 mupq 和归一化矩 nupq    huM = cv2.HuMoments(moments)  # 计算 Hu 不变矩    # 轮廓面积    area = cv2.contourArea(cnt)    print("area by moments['m00']: ", moments['m00'])    print("area of contour: ", area)    # 轮廓的质心 (Cx, Cy)    if moments['m00'] > 0: cx = round(moments['m10'] / moments['m00']) cy = round(moments['m01'] / moments['m00']) print("centroid of contour: ({}, {})".format(cx, cy)) cv2.circle(img, (cx, cy), 5, (0, 0, 255), -1)  # 在轮廓的质心上绘制圆点 plt.subplot(234), plt.axis('off'), plt.title("Contour centroid") plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))    else: print("moments['m00'] = 0")    # 轮廓的周长    perimeter = cv2.arcLength(cnt, True)  # True  表示输入是闭合轮廓    print("centroid of perimeter: {:.1f}".format(perimeter))    # 轮廓近似多边形    epsilon = 0.01 * cv2.arcLength(contours[1], True)    approx = cv2.approxPolyDP(contours[1], epsilon, True)    approx.shape:  (15, 1, 2)    cv2.polylines(img, [approx], True, (0, 0, 255), 2)  # 绘制多边形    plt.subplot(235), plt.axis('off'), plt.title("Approximate polygon")    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))    # 检查轮廓是否为凸面体    isConvex = cv2.isContourConvex(contours[2])  # True 凸面体, False 非凸    print("contours[2] ContourConvex?", isConvex)    # 获取轮廓的凸壳    hull = cv2.convexHull(contours[2], returnPoints=True)  # 返回轮廓凸壳顶点坐标    print("hull.shape: ", hull.shape)  # 凸壳顶点坐标 (x,y), (24, 1, 2)    cv2.polylines(img, [hull], True, (0, 0, 255), 2)  # 绘制多边形    plt.subplot(236), plt.axis('off'), plt.title("Contour convex")    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))    plt.tight_layout()    plt.show()

运行结果:

len(contours) =  6area by moments['m00']:  15523.0area of contour:  15523.0centroid of contour: (394, 380)centroid of perimeter: 783.5approx.shape:  (15, 1, 2)contours[2] ContourConvex? Falsehull.shape:  (24, 1, 2)

在这里插入图片描述

(本节完)


版权声明:

youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/125023990)

Copyright 2022 youcans, XUPT
Crated:2022-5-31

欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中
欢迎关注 『youcans 的 OpenCV学习课』 系列,持续更新中

【youcans 的 OpenCV 例程200篇】194.寻找图像轮廓(cv.findContours)
【youcans 的 OpenCV 例程200篇】195.绘制图像轮廓(cv.drawContours)
【youcans 的 OpenCV 例程200篇】196.图像的矩和不变矩(cv.moments)
【youcans 的 OpenCV 例程200篇】197.轮廓的基本特征
OpenCV 例程200篇 总目录-202205更新