【OpenCV 例程200篇】223. 特征提取之多边形拟合(cv.approxPolyDP)

『youcans 的 OpenCV 例程200篇 - 总目录』



【youcans 的 OpenCV 例程200篇】223. 特征提取之多边形拟合


目标特征的基本概念

通过图像分割获得多个区域,得到区域内的像素集合或区域边界像素集合。我们把感兴趣的人或物称为目标,目标所处的区域就是目标区域。
特征通常是针对于图像中的某个目标而言的。图像分割之后,还要对目标区域进行适当的表示和描述,以便下一步处理。
“表示”是直接具体地表示目标,以节省存储空间、方便特征计算。目标的表示方法,有链码、多边形逼近(MPP)、斜率标记图、边界分段、区域骨架。
“描述”是对目标的抽象表达,在区别不同目标的基础上,尽可能对目标的尺度、平移、旋转变化不敏感。


边界特征描述子

目标的边界描述符(Boundary descriptors),也称为边界描述子。
轮廓就是对目标边界的描述,轮廓属性是基本的边界描述子。

例如:

  • 边界的长度,轮廓线的像素数量是边界周长的近似估计;
  • 边界的直径,边界长轴的长度,等于轮廓最小矩形边界框的长边长度;
  • 边界的偏心率,边界长轴与短轴之比,等于轮廓最小矩形边界框的长宽比;
  • 边界的曲率,相邻边界线段的斜率差;
  • 链码,通过规定长度和方向的直线段来表示边界;
  • 傅里叶描述符,对二维边界点进行离散傅里叶变换得到的傅里叶系数,对旋转、平移、缩放和起点不敏感;
  • 统计矩,把边界视为直方图函数,用图像矩对边界特征进行描述,具有平移、灰度、尺度、旋转不变性。

### 例程 12.12:轮廓的多边形拟合

OpenCV 中的函数 cv.approxPolyDP() 可以用于对图像轮廓点进行多边形拟合。

函数说明:

	cv.approxPolyDP(curve, epsilon, closed[, approxCurve=None]) → approxCurve

函数 cv.approxPolyDP 使用 Douglas-Peucker 算法求得一条顶点较少的多折线/多边形,以指定的精度近似输入的曲线或多边形。(参考:拟合直线,拟合椭圆)

参数说明:

  • curve:输入点集,二维点向量的集合
  • approxCurve:输出点集,表示拟合曲线或多边形,数据与输入参数 curve 一致
  • epsilon:指定的近似精度,原始曲线与近似曲线之间的最大距离
  • close: 闭合标志,True 表示闭合多边形,False 表示多边形不闭合

注意事项:

Douglas-Peucker算法:
(1)在曲线的起点 A 和终点 B 之间做一条直线 AB,是曲线的弦;
(2)寻找曲线上离该直线段距离最大的点 C,计算其与 AB 的距离 d;
(3)比较距离 d 与设定的阈值 threshold,如果小于设定阈值则该直线段作为曲线的近似,该段曲线处理完毕。
(4)如果距离 d 大于设定阈值,则以 C 点将曲线 AB 分为两段 AC 和 BC,并分别对这两段进行以上步骤的处理。
(5)当所有曲线都处理完毕时,依次连接所有分割点形成的折线,作为曲线的近似。


    #  12.12 轮廓的多边形拟合
    img = cv2.imread("../images/Fig1105.tif", flags=1)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度图像
    blur = cv2.boxFilter(gray, -1, (5, 5))  # 盒式滤波器,9*9 平滑核
    _, binary = cv2.threshold(blur, 205, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)

    # 寻找二值化图中的轮廓
    contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # OpenCV4~
    print('len:', len(contours))
    # 绘制全部轮廓,contourIdx=-1 绘制全部轮廓
    imgCnts = np.zeros(gray.shape[:2], np.uint8)  # 绘制轮廓函数会修改原始图像
    imgCnts = cv2.drawContours(imgCnts, contours, -1, (255, 255, 255), thickness=2)  # 绘制全部轮廓

    plt.figure(figsize=(9, 6))
    plt.subplot(231), plt.axis('off'), plt.title("Origin")
    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    plt.subplot(232), plt.axis('off'), plt.title("Binary")
    plt.imshow(binary, 'gray')
    plt.subplot(233), plt.axis('off'), plt.title("Contour")
    plt.imshow(imgCnts, 'gray')

    cnts = sorted(contours, key=cv2.contourArea, reverse=True)  # 所有轮廓按面积排序
    cnt = cnts[0]  # 第 0 个轮廓,面积最大的轮廓,(664, 1, 2)
    print("shape of max contour:", cnt.shape[0])

    eps = [50, 30, 10]
    for i in range(len(eps)):
        polyFit = cv2.approxPolyDP(cnt, eps[i], True)
        print("eps={}, shape of fitting polygon:{}".format(eps[i], polyFit.shape[0]))
        fitContour = np.zeros(gray.shape[:2], np.uint8)  # 初始化最大轮廓图像
        cv2.polylines(fitContour, [cnt], True, 205, thickness=2)  # 绘制最大轮廓,多边形曲线
        cv2.polylines(fitContour, [polyFit], True, 255, 3)
        plt.subplot(2,3,i+4), plt.axis('off'), plt.title("approxPoly(eps={})".format(eps[i]))
        plt.imshow(fitContour, 'gray')

    plt.tight_layout()
    plt.show()

【OpenCV 例程200篇】223. 特征提取之多边形拟合(cv.approxPolyDP)_第1张图片

运行结果:
shape of max contour: 547
eps=50, shape of fitting polygon:5
eps=30, shape of fitting polygon:8
eps=10, shape of fitting polygon:13

运行结果表明,用 13个顶点的多边形可以很好地逼近该轮廓的边界,描述轮廓的边界特征,显著降低了数据量。


【本节完】

版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/125598167)
Copyright 2022 youcans, XUPT
Crated:2022-6-30

197.轮廓的基本特征
200.轮廓的基本属性
223. 特征提取之多边形拟合

你可能感兴趣的:(opencv,计算机视觉,人工智能,python)