• 离散Fréchet算法


    离散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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    参考:


    1. Eiter T, Mannila H. Computing discrete Fréchet distance[J]. 1994. ↩︎

    2. GitHub - spiros/discrete_frechet: Compute the Fréchet distance between two polygonal curves in Euclidean space. ↩︎

  • 相关阅读:
    外贸行业常用英文邮件模板分享
    Fiddler之Replay功能详解
    frp服务利用云主机docker服务实现Windows远程连接
    <计算机网络自顶向下> 路由器组成
    JAVA【设计模式】适配器模式
    字节国际化TnS算法实习的碎碎念
    【Android进阶】12、Fragment Navigation
    2023 年 API 安全状况
    labelImg
    算法时间复杂度
  • 原文地址:https://blog.csdn.net/KPer_Yang/article/details/126680777