opencv中的轨迹数据压缩的Douglas-Peucker算法以及cv2.approxPolyDP()函数解析

轨道数据压缩算法

引用于:https://zhuanlan.zhihu.com/p/136286488?utm_id=0


上图演示了Douglas-Peucker算法的前两个步骤:

如图所示,在第一步(见图 (a)中,选择起点P0和终点P16,生成近似线段P0~P16。导出了从原始轨迹上的每个采样点到近似线段P0~P16的垂直欧几里德距离。由于某些垂直误差距离大于预先定义的误差距离阈值,因此选择与P0~P16偏差最大的采样点P16,即本例中的P9作为分割点

因此,在算法的第二步(见图(b))中,使用轨迹p0、p9、p16来近似原始轨迹。在这一步中,原问题被分成两个子问题,其中线段p0 ~ p9是{p0, p1,…, p9}近似的子轨迹,而线段p9~p16则近似于另一个{p9, p10,…,p16}的子轨迹。

如图所示,在第一个子问题中,几个采样的位置点的垂直误差距离p0 p9大于预先定义的误差距离阈值。因此,选取与p0 p9偏差最大的采样定位点p5作为分割点,对分割子轨迹进行递归处理,直到所有采样定位点在误差阈值内与近似线段都有垂直距离。另一方面,在第二个子问题中,所有样本点到线段p9~p16的垂直距离都小于误差阈值。因此,没有必要进一步拆分。

以上就是书中对DP算法的说明,下面介绍DP算法具体的步骤:

(1)在轨迹曲线在曲线首尾两点A,B之间连接一条直线AB,该直线为曲线的弦;

(2)遍历曲线上其他所有点,求每个点到直线AB的距离,找到最大距离的点C,最大距离记为dmax;

(3)比较该距离dmax与预先定义的阈值Dmax大小,如果dmax<Dmax,则将该直线AB作为曲线段的近似,曲线段处理完毕;

(4)若dmax>=Dmax,则使C点将曲线AB分为AC和CB两段,并分别对这两段进行(1)~(3)步处理;

(5)当所有曲线都处理完毕时,依次连接各个分割点形成的折线,即为原始曲线的路径。


cv2.approxPolyDP()函数解析

def approxPolyDP(curve, epsilon, closed, approxCurve=None): # real signature unknown; restored from __doc__
    """
    approxPolyDP(curve, epsilon, closed[, approxCurve]) -> approxCurve
    .   @brief Approximates a polygonal curve(s) with the specified precision.
    .   
    .   The function cv::approxPolyDP approximates a curve or a polygon with another curve/polygon with less
    .   vertices so that the distance between them is less or equal to the specified precision. It uses the
    .   Douglas-Peucker algorithm <http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm>
    .   
    .   @param curve Input vector of a 2D point stored in std::vector or Mat
    .   @param approxCurve Result of the approximation. The type should match the type of the input curve.
    .   @param epsilon Parameter specifying the approximation accuracy. This is the maximum distance
    .   between the original curve and its approximation.
    .   @param closed If true, the approximated curve is closed (its first and last vertices are
    .   connected). Otherwise, it is not closed.
    """
    pass
  • curve:第一个参数是轮廓的点集。
  • epsilon:第二个参数epsilon的含义如下所述,滤掉的线段集离新产生的线段集的距离为d,若d小于epsilon,则滤掉,否则保留。
  • 第三个参数指示新产生的轮廓是否闭合,返回的是一些列点组成的多边形。

注意:以下例子为opencv项目形状检测涉及的部分代码

def getContours(img):
    '''获取边界轮廓函数'''
    # mode=cv2.RETR_EXTERNAL 检测外部(outer detail)
    # method=cv2.CHAIN_APPROX_NONE (返回的相邻两个点的像素位置差不超过1)
    conters, hierarchy = cv2.findContours(image=img, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_NONE)
    # conters中的轮廓是list类型
    for cnt in conters:
        # cnt_image = cnt
        ares = cv2.contourArea(contour=cnt)
        # print('cnts_shape', cnt_image.shape)
        print('cnts', ares)
        if ares > 500:
            # 绘制边界
            cv2.drawContours(image=imgContour, contours=cnt, contourIdx=-1, color=(255, 0, 0), thickness=3)
            # 弧 True表示闭合
            peri = cv2.arcLength(cnt, True)
            print(peri)
            # 轮廓近似函数
            approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
            # print('approx', approx)
            print('approx_len:', len(approx))
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值