离散Fréchet算法
总结
实现Fréchet算法的过程中巩固递归算法的基本操作,就是终止条件和Max或Min的计算;而且使用尾递归而不是普通的递归在python和C中实现更好的效率。
Fréchet算法原理1
度量空间中两条曲线之间的 Fréchet 距离是曲线之间相似性的度量。 算法的离散实现提供了连续测量的良好近似值,并且可以使用简单的算法有效地计算。
给定度量空间中的两条曲线,它们之间的 Fréchet 距离 δF 可以直观地定义如下。
一个人用皮带牵狗:人可以在一条曲线上移动,而狗在另一条曲线上;两者都可以改变它们的速度,但不允许回溯。足以穿过两条曲线的最短皮带长度是多少? Fréchet 距离是曲线之间相似性的度量,它考虑了沿曲线的点的位置和顺序。因此它通常比众所周知的豪斯多夫距离要好。这个距离函数是由 Fréchet 在 1906 年引入的 。 Alt 和 Godau对 Fréchet 距离的计算特性进行了基础研究。他们给出了一种算法,可以在 O(pq log2 pq) 时间内计算两条多边形曲线之间的精确 Fréchet 距离,其中 p 和 q 是多边形曲线上的段数。该算法相当复杂,因为它使用参数搜索技术。在本文中,描述了多边形曲线的 Fréchet 距离的离散变化。这种变化称为耦合距离δdF。它基于查看多边形曲线的线段端点之间所有可能的耦合的想法。我们证明 δdF 提供了很好的 δF 近似值。具体来说,我们表明 δdF 是 δF 的上限,并且这些度量之间的差异受多边形曲线最长边的长度的限制。我们还表明,可以使用非常简单的算法在 O(pq) 时间内计算 δdF。在这些结果的基础上,以下近似计算两条任意曲线之间的 Fréchet距离的方法不言自明:首先计算曲线的适当多边形近似,然后计算它们的耦合距离,而不是计算它们的精确 Fréchet距离。
Fréchet算法实现
算法的伪代码如下:
算法的python代码实现如下,参考2:
# 部分代码参考:https://github.com/spiros/discrete_frechet
import numpy as np
def frechet_distance_recursion(ca, i, j, p, q):
if ca[i, j] > -1:
return ca[i, j]
elif i == 0 and j == 0:
ca[i, j] = np.linalg.norm(p[i]-q[j])
elif i > 0 and j == 0:
ca[i, j] = max(frechet_distance_recursion(ca, i-1, 0, p, q), np.linalg.norm(p[i]-q[j]))
elif i == 0 and j > 0:
ca[i, j] = max(frechet_distance_recursion(ca, 0, j-1, p, q), np.linalg.norm(p[i]-q[j]))
elif i > 0 and j > 0:
ca[i, j] = max(
min(
frechet_distance_recursion(ca, i-1, j, p, q),
frechet_distance_recursion(ca, i-1, j-1, p, q),
frechet_distance_recursion(ca, i, j-1, p, q)
),
np.linalg.norm(p[i]-q[j])
)
else:
ca[i, j] = float('inf')
return ca[i, j]
def frechet_distance(p, q):
p = np.array(p, np.float64)
q = np.array(q, np.float64)
len_p = len(p)
len_q = len(q)
if len_p == 0 or len_q == 0:
raise ValueError('Input curves are empty.')
if len_p != len_q or len(p[0]) != len(q[0]):
raise ValueError('Input curves do not have the same dimensions.')
ca = (np.ones((len_p, len_q), dtype=np.float64) * -1)
dist = frechet_distance_recursion(ca, len_p-1, len_q-1, p, q)
return dist
if __name__=='__main__':
p=[[1,1], [2,1], [2,2]]
q=[[2,2], [0,1], [2,4]]
dist = frechet_distance(p, q) # 2.0
参考:
Eiter T, Mannila H. Computing discrete Fréchet distance[J]. 1994. ↩︎
GitHub - spiros/discrete_frechet: Compute the Fréchet distance between two polygonal curves in Euclidean space. ↩︎