曲线相似度衡量——曲线距离计算Fréchet distance详解与python计算
论文可以参考:理论推导Eiter, Thomas, and Heikki Mannila. “Computing discrete Fréchet distance.” (1994).便于计算的离散距离求解Alt, Helmut, and Michael Godau. “Computing the Fréchet distance between two polygonal curves.” In
弗朗明歇距离(Fréchet distance)论文可以参考:
理论推导
Eiter, Thomas, and Heikki Mannila. “Computing discrete Fréchet distance.” (1994).
便于计算的离散距离求解
Alt, Helmut, and Michael Godau. “Computing the Fréchet distance between two polygonal curves.” International Journal of Computational Geometry & Applications 5.01n02 (1995): 75-91.
含义
这个图能够形象说明Fréchet distance
的含义:一个人牵着一条狗,共同走到目的地,尝试求:狗链子的最短值
算法思路
-
首先
Fréchet distance
是计算两个序列之间的最大差值,因此它是一个值,且是距离的最大值,不考虑曲线走势相似性等指标,公式如下: -
一个最简单的方法是遍历两个序列的每一对点,计算最大值即可。但是由于两个序列可能是不对齐的,因此需要先找到一条路径,然后在比较两个序列的每一对点,取最大值。核心就是:对齐序列
-
Fréchet distance对齐的方法与DTW神似,可以参考:DTW(动态时间归整)算法与DTW,fastDTW的python算例
4. Fréchet distance认为:在两个不同采样点的序列中,尝试找到一种,能使彼此配对的值的距离的和最小的路径,这条路径就是核心路径,配对的过程是:
- 捏着线段A的一个待匹配的点(如下图的点d)
- 首先判断 min( ab, ac, bd)
- 在上面的min
的优胜者与dc
比较,选择这两个中的最大的值,作为真实的配对点
- 因此下图中目测配对的是bd
(假如bd应该比ac短)
5. 在计算时,使用递归的方法可以在寻找路径的同时计算距离,代码详解与示例参考下面的内容
示例代码
import numpy as np
def cal_frechet_distance(curve_a: np.ndarray, curve_b: np.ndarray):
# 距离公式,两个坐标作差,平方,累加后开根号
def euc_dist(pt1, pt2):
return np.sqrt(np.square(pt2[0] - pt1[0]) + np.square(pt2[1] - pt1[1]))
# 用递归方式计算,遍历整个ca矩阵
def _c(ca, i, j, P, Q): # 从ca左上角开始计算,这里用堆的方法把计算序列从右下角压入到左上角,实际计算时是从左上角开始
if ca[i, j] > -1:
return ca[i, j]
elif i == 0 and j == 0: # 走到最左上角,只会计算一次
ca[i, j] = euc_dist(P[0], Q[0])
elif i > 0 and j == 0: # 沿着Q的边边走
ca[i, j] = max(_c(ca, i - 1, 0, P, Q), euc_dist(P[i], Q[0]))
elif i == 0 and j > 0: # 沿着P的边边走
ca[i, j] = max(_c(ca, 0, j - 1, P, Q), euc_dist(P[0], Q[j]))
elif i > 0 and j > 0: # 核心代码:在ca矩阵中间走,寻找对齐路径
ca[i, j] = max(min(_c(ca, i - 1, j, P, Q), # 正上方
_c(ca, i - 1, j - 1, P, Q), # 斜左上角
_c(ca, i, j - 1, P, Q)), # 正左方
euc_dist(P[i], Q[j]))
else: # 非法的无效数据,算法中不考虑,此时 i<0,j<0
ca[i, j] = float("inf")
return ca[i, j]
# 这个是给我们调用的方法
def frechet_distance(P, Q):
ca = np.ones((len(P), len(Q)))
ca = np.multiply(ca, -1)
dis = _c(ca, len(P) - 1, len(Q) - 1, P, Q) # ca为全-1的矩阵,shape = ( len(a), len(b) )
return dis
# 这里构造计算序列
curve_line_a = list(zip(range(len(curve_a)), curve_a))
curve_line_b = list(zip(range(len(curve_b)), curve_b))
return frechet_distance(curve_line_a, curve_line_b)
if __name__ == '__main__':
a_array = np.array([2, 4, 6, 8])
b_array = np.array([2, 3, 4, 6, 5, 7, 8])
result = cal_frechet_distance(a_array, b_array)
print(result) # 打印结果
更多推荐
所有评论(0)