轨道数据压缩算法
引用于: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))