如何比较Bezier曲线的形状

时间:2015-02-18 17:18:12

标签: javascript algorithm vector-graphics image-recognition paperjs

我想比较2条贝塞尔曲线。我知道端点和控制点的坐标,但对于2个比较曲线,这个坐标可能不一样。我需要比较这条曲线的形状。为了“真实”,形状必须大致相同。

我使用javascript和paper.js。

请看图片:

example https://habrastorage.org/files/825/6e5/36c/8256e536c9ce4f01bf12d792473038d5.png

出路在哪里?感谢名单。

2 个答案:

答案 0 :(得分:1)

一个三次Bézier样条由任意四个点定义:start,control-1,control-2和end,我将编号为0,1,2,3。现在我们假设这四个点是截然不同,没有三个是直线。

曲线可以采取三种根本不同的形式,取决于线0-1和1--2之间的转弯方向,以及1--2和2-3之间的转弯,以及0-1和0 2--3交叉。

在类型1中,两个转弯都在右侧,或者两个转弯都在左侧,而0--1不转换2--3。这会在提问者的例子中给出类似a,b或c的曲线。在类型2中,第一个转弯位于左侧,第二个转弯位于右侧,或者反之亦然,在提问者的示例中给出了像d一样的曲线,带有扭结。在类型3中,两个转弯处于相同的方向,但是线0-1和2--3交叉,给出了带有环的曲线。

我们可以先将单个三次样条曲线分类为三种类型之一,为它们提供一个类型字符串:普通('' - 空字符串),扭结('K')和循环('L')。

然而,示例e由两个平滑连接的三次样条组成。为了处理这样的序列,我们遍历它们并创建一个字符串,为每个扭曲曲线附加一个K,为每个循环曲线附加一个L.我们还为两个样条线之间的每个连接添加一个K,其中连接之前的转弯与转弯之后的转弯相反:左边然后右边,或者右边然后左边。

这为我们提供了类型字符串'K',例如e,根据需要将其与d匹配。

我们还允许匹配,其中一个类型字符串与另一个类型字符串相反:因此'KL'匹配'LK'。

答案 1 :(得分:0)

从您提供的示例中我假设

  • 尺寸不相关
  • 形状可以扭曲到某一点

如果旋转曲线不相同

  1. N点的样本曲线

    • 通过某个步骤直接参数...
    • 对于三次曲线,我将使用16到32个采样点
    • 分数越多,比较越精确
    • 但运行时间更长......
  2. 计算每个段的角度

    • 使用atan2或atanxy
    • 将这些角度存储在数组中
  3. 比较这些数组

    • 正确执行此操作的最佳和最简单的方法是correlation coefficient
    • 如果相关系数接近+1,那么形状相似或相同
  4. 如果旋转的相似曲线应该相同

      • 然后进行上述几次旋转(例如0,10,20,...,350度)
      • 如果有的话,如果这些是相同的停止并返回true
      • 如果没有则返回false
      • 曲线的旋转只是为它的所有角度添加一个常数......
    1. 旋转不变性

      • 如果您将两个比较的曲线角度偏移为从角度0开始
      • 所以只需从曲线的所有角度减去第一个角度
      • 然后您将两条曲线相互对齐,因此只需要比较两个位置
      • 所以你比较一下
      • 如果不相同,则向一条曲线添加180度并再次比较
      • 就够了
    2. [注释]

      • 你应该在关联之前对所有角度进行标准化(将其设置为间隔<0.0,2.0*PI>
      • 有关更多提示,请查看How to compare two shapes?