【学习笔记】Fréchet距离的 C 语言实现

Fréchet 距离

Fréchet 距离,又称为弗雷歇距离,是一种衡量两条曲线(或两个路径)之间相似性的度量方法。这个概念最初在度量空间理论中被定义,后来被广泛应用于计算机科学、地理信息系统、图像处理、生物信息学等多个领域,特别是在比较和匹配形状、路径或序列时非常有用。

数学背景

首先,我们需要一个基础的数学框架。假设有两个参数化的曲线 A ( t ) A(t) A(t) B ( t ) B(t) B(t),它们定义在一个闭区间 [ 0 , 1 ] [0, 1] [0,1] 上,并且映射到一个度量空间 ( X , d ) (X, d) (X,d) 中,其中 d d d 是这个空间内的两点间距离函数。度量空间可以简单理解为一个集合 X X X 加上一个定义在这个集合上任意两点间距离的方式 d d d

Fréchet距离的定义

Fréchet 距离试图量化这样的场景:假设有两个人分别沿着曲线 A A A B B B 行走,他们可以从各自的起点出发,以任意的速度前进,但要求两人始终保持同步,即每个人在自己路径上的位置与另一人在其路径上的位置之间有一个对应关系。Fréchet 距离是保持彼此距离尽可能小的情况下所需的最大距离。

Fréchet距离的数学定义可以用以下公式表达:

A : [ 0 , 1 ] → X A: [0, 1] \rightarrow X A:[0,1]X B : [ 0 , 1 ] → X B: [0, 1] \rightarrow X B:[0,1]X 是定义在度量空间 ( X , d ) (X, d) (X,d) 中的两条连续曲线,其中 d d d X X X 中两点间的距离函数。Fréchet距离 F ( A , B ) F(A, B) F(A,B) 定义为:

F ( A , B ) = inf ⁡ α , β max ⁡ t ∈ [ 0 , 1 ] d ( A ( α ( t ) ) , B ( β ( t ) ) ) F(A, B) = \inf_{\alpha, \beta} \max_{t \in [0, 1]} d(A(\alpha(t)), B(\beta(t))) F(A,B)=α,βinft[0,1]maxd(A(α(t)),B(β(t)))

这里, α \alpha α β \beta β 是从区间 [ 0 , 1 ] [0, 1] [0,1] 到自身的连续单调递增函数,代表了沿曲线 A A A B B B 的“行走”速度。 α ( t ) \alpha(t) α(t) β ( t ) \beta(t) β(t) 分别表示在时间 t t t 时,沿曲线 A A A B B B 的位置。 inf ⁡ \inf inf 表示 infimum(下确界),即所有可能的 α \alpha α β \beta β 对中最大的 d ( A ( α ( t ) ) , B ( β ( t ) ) ) d(A(\alpha(t)), B(\beta(t))) d(A(α(t)),B(β(t))) 的最小值。

简单来说,这个公式表达了找到两个函数(代表两条路径)上的点对,这些点对在它们各自的路径上以某种方式“同步行走”,使得在任何给定时间点 t t t 上,这两点之间的最大距离尽可能小,最终得到的就是Fréchet距离。

在离散情况下,如果我们将曲线 A A A B B B 近似为点集 { A 1 , A 2 , . . . , A n } \{A_1, A_2, ..., A_n\} {A1,A2,...,An} { B 1 , B 2 , . . . , B m } \{B_1, B_2, ..., B_m\} {B1,B2,...,Bm},则可以通过动态规划等方法来近似计算Fréchet距离,此时的公式和计算方法会有所不同,但基本思想仍然遵循上述原理。

C语言实现

以下是计算 Fréchet 距离的C语言实现示例:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// 定义点结构体
typedef struct {
    double x;
    double y;
} Point;

// 计算两点之间的欧几里得距离
double euclidean_distance(Point p1, Point p2) {
    return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
}

// 递归计算Fréchet距离
double recursive_frechet_distance(Point* P, int i, Point* Q, int j, double** cache) {
    if (cache[i][j] != -1) {
        return cache[i][j];
    }

    double dist = euclidean_distance(P[i], Q[j]);

    if (i == 0 && j == 0) {
        cache[i][j] = dist;
    } else if (i == 0) {
        cache[i][j] = fmax(recursive_frechet_distance(P, i, Q, j - 1, cache), dist);
    } else if (j == 0) {
        cache[i][j] = fmax(recursive_frechet_distance(P, i - 1, Q, j, cache), dist);
    } else {
        double minPrevDist = fmin(fmin(recursive_frechet_distance(P, i - 1, Q, j, cache),
                                       recursive_frechet_distance(P, i - 1, Q, j - 1, cache)),
                                  recursive_frechet_distance(P, i, Q, j - 1, cache));
        cache[i][j] = fmax(minPrevDist, dist);
    }

    return cache[i][j];
}

// 计算Fréchet距离
double frechet_distance(Point* P, int n, Point* Q, int m) {
    // 创建缓存数组并初始化
    double** cache = (double**)malloc(n * sizeof(double*));
    for (int i = 0; i < n; i++) {
        cache[i] = (double*)malloc(m * sizeof(double));
        for (int j = 0; j < m; j++) {
            cache[i][j] = -1;
        }
    }

    double result = recursive_frechet_distance(P, n - 1, Q, m - 1, cache);

    // 释放缓存数组
    for (int i = 0; i < n; i++) {
        free(cache[i]);
    }
    free(cache);

    return result;
}

int main() {
    // 定义两条曲线
    Point P[] = {{0, 0}, {1, 1}, {2, 2}};
    Point Q[] = {{0, 0}, {1, 2}, {3, 3}};

    // 计算Fréchet距离
    double distance = frechet_distance(P, 3, Q, 3);
    printf("Fréchet Distance: %f\n", distance);

    return 0;
}

实际意义

在实际应用中,这个概念可以用来解决多种问题,例如:

  • 地形匹配:在地图学中,用于比较两条路径或地形轮廓的相似性,帮助确定它们是否可能是同一区域的不同表示。
  • 图像分析:在图像处理和计算机视觉中,用来比较形状边界,如手写字符识别。
  • 序列比对:在生物信息学中,用于比较DNA序列或蛋白质结构的相似性,尽管这里的序列通常需要转换成某种曲线形式。
  • 路径规划:在机器人导航中,评估不同路径之间的相似度,帮助选择最佳路径。

优点与缺点

优点

  • 考虑了曲线的整体形状和几何结构,能够更准确地度量两条曲线之间的相似性。
  • 对曲线的参数化方式敏感,能够反映出曲线在不同参数化下的形状变化。

缺点

  • 计算复杂度较高,特别是对于长曲线或高维曲线。
  • 对噪声较敏感,需要对曲线进行预处理以消除噪声影响。

总之,Fréchet距离是一种强大而灵活的工具,用于度量曲线或路径之间的相似性。它在轨迹分析、形状识别等领域有着广泛的应用,但在实际使用中需要考虑其计算复杂度和对噪声的敏感性。


本文链接:https://blog.csdn.net/u012028275/article/details/140139463

离散 Fréchet 距离是用于测量两个离散曲线之间相似程度的一种度量方法。它基于 Fréchet 距离的概念,但适用于离散曲线而不是连续曲线。 在计算离散 Fréchet 距离时,我们考虑两个离散曲线中的每个点对之间的距离。对于每个点对,我们可以通过直线距离、曼哈顿距离或其他距离度量方法来计算它们之间的距离。然后,我们通过计算最小的距离来确定两个曲线之间的 Fréchet 距离。 具体地说,我们通过以下步骤计算离散 Fréchet 距离: 1. 创建一个大小为 m × n 的矩阵 D,其中 m 和 n 分别为两个离散曲线的点数。 2. 初始化矩阵 D 的第一行和第一列,使得 D[i,0] 和 D[0,j] 分别等于曲线1和曲线2的第 i 个点和第 j 个点之间的距离。 3. 对于每个 D[i,j],计算曲线1的第 i 个点和曲线2的第 j 个点之间的距离。这可以使用直线距离、曼哈顿距离或其他距离度量方法来实现。 4. 使用递归的方式填充矩阵 D,直到达到右下角的 D[m,n]。 5. 返回 D[m,n] 的值,它代表了曲线1和曲线2之间的离散 Fréchet 距离。 离散 Fréchet 距离可以用于比较离散曲线的相似性,例如路径规划中的路径匹配、图像处理中的轮廓匹配等。该距离度量方法的优势在于它考虑了曲线上的点对之间的相对位置,因此可以更准确地捕捉到曲线的形状相似程度。但是,离散 Fréchet 距离的计算复杂度较高,需要使用动态规划或其他优化算法来加快计算速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值