【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()
    

    运行结果:
    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. 特征提取之多边形拟合

    来源:YouCans

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【OpenCV 例程200篇】223. 特征提取之多边形拟合(cv.approxPolyDP)

    发表评论