如何在Python中比较两条3D曲线?

3
我有一个庞大的数组,其中包含描述三维曲线的坐标,约20000个点。我正试图通过忽略一些点,例如每两个点中取1个点的方式来使用更少的点。当我这样做并绘制减少数量的点时,形状看起来相同。但是我想适当比较这两条曲线,类似于卡方检验,以查看减小的图形与原始图形相差多少。

是否有一种简单内置的方法来做到这一点,或者是否有任何思路可以解决这个问题。


你的数据是什么维度的?是三维形状还是二维曲线? - xdze2
2
这是一个三维曲线。 - Agustin
我能想到两种可能性:第一种是,您可以通过两个拟合模型传递减少的数据集本身,并比较诸如最大/最小误差、均方根误差和R平方等统计数据来比较两组结果。第二种方法是,您可以创建一个矩形网格,并将其通过两个模型进行类似的比较。第一种方法将比较拟合数据,而第二种方法将比较任何给定的数据范围。 - James Phillips
2个回答

3
"线简化"这个问题似乎是一个完整的研究领域。我建议您查看例如Ramer-Douglas-Peucker算法的维基百科页面。我找到了几个Python模块:rdpsimplification(它们还实现了Py-Visvalingam-Whyatt算法)。
无论如何,我正在尝试使用插值评估两条折线之间的差异。任何曲线都可以进行比较,即使没有共同点。
第一个想法是计算两条折线沿路径的距离。它们用作从第一条曲线上的给定点到另一条曲线上相对接近的点的地标。
然后,第一条曲线的点可以在另一条曲线上进行插值。现在,可以逐点比较这两个数据集。
在图表中,黑色曲线是xy2在曲线xy1上的插值。因此,可以计算并平均计算出“黑色方块”和“橙色圆圈”之间的距离。
这给出了一个平均距离度量,但没有什么可以进行比较并决定是否应用了足够好的减少...。 example graph
def normed_distance_along_path( polyline ):
    polyline = np.asarray(polyline)
    distance = np.cumsum( np.sqrt(np.sum( np.diff(polyline, axis=1)**2, axis=0 )) )
    return np.insert(distance, 0, 0)/distance[-1]

def average_distance_between_polylines(xy1, xy2):   
    s1 = normed_distance_along_path(xy1)
    s2 = normed_distance_along_path(xy2)

    interpol_xy1 = interp1d( s1, xy1 )
    xy1_on_2 = interpol_xy1(s2)

    node_to_node_distance = np.sqrt(np.sum( (xy1_on_2 - xy2)**2, axis=0 ))

    return node_to_node_distance.mean() # or use the max

# Two example polyline:
xy1 = [0, 1, 8, 2, 1.7],  [1, 0, 6, 7, 1.9]   # it should work in 3D too
xy2 = [.1, .6, 4, 8.3, 2.1, 2.2, 2],  [.8, .1, 2, 6.4, 6.7, 4.4, 2.3]

average_distance_between_polylines(xy1, xy2)  # 0.45004578069119189

请参考以下链接,了解如何在Python中比较两条曲线的相似性:https://stackoverflow.com/questions/51486120/similarity-between-two-curves-in-python - xdze2
谢谢您,这正是我所需要的。 - Agustin
你是否知道一种方法可以找到一个曲线,该曲线具有较少的点数,但这些点不必是原始数据的一部分?例如:我有20000个代表圆形的点,使用rdp算法,我的最终曲线会低估,所有点都在圆内。是否有一种算法可以将一些点移动到原始圆形外部,以最小化过度和低估?再次感谢您的帮助。 - Agustin
如果更适合拟合而不是插值,我建议尝试使用类似于 'spline smoothing' 的方法。也许根据您的领域和数据类型,还有其他专门的方法可供选择。请提供一个简短的数据样本并提出新问题。 - xdze2
如果您知道这是一个圆,那么您是否可以直接使用优化方法拟合一个圆,包括半径、中心位置和方向(7个参数)?请参见https://dev59.com/f4Tba4cB1Zd3GeqP8Zzb#42936444 - 好的,这是一个例子。 - xdze2
谢谢,我会写另一个问题,您的答案适合我想要的,我只是想估计我进一步丢失多少细节。这个圆是一个简化的例子。 - Agustin

1
如果对原始曲线进行子采样,评估逼近误差的简单方法是计算原始曲线和重新采样顶点之间的线段之间的最大距离。最大距离发生在原始顶点处,只需在这些点处进行评估即可。
顺便说一下,这提供了一种通过设置最大容差并减少直到超过容差的简单方法来执行子采样。
您还可以考虑计算平均距离,但这可能涉及讨厌的积分,并且可能会给出不太美观的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接