34

我有一组需要与Bézier 曲线相匹配的数据点(我可以细化)。我需要速度而不是准确性,但合身性应该足够好才能被识别。我也在寻找一种我可以使用的算法,它不会大量使用库(特别是NumPy)。

我已经阅读了几篇研究论文,但没有一篇有足够的细节来完全实施。有没有开源的例子?

4

5 回答 5

23

我有类似的问题,我从 Graphics Gems (1990) 中找到了关于 Bezier 曲线拟合的“自动拟合数字化曲线的算法”。除此之外,我还找到了该文章的源代码

不幸的是,它是用 C 语言编写的,我不太了解。此外,该算法很难理解(至少对我而言)。我正在尝试将其翻译成 C# 代码。如果我会成功,我会尝试分享它。

GGVecLib.c同一文件夹中的文件包含FitCurves.c基本矢量操作功能。

我发现了一个类似的 Stack Overflow 问题,Smoothing a hand-drawn curve。批准的答案提供了来自 Graphic Gems 的曲线拟合算法的 C# 代码。

于 2011-06-10T10:02:00.003 回答
14

许多这些答案中缺少的是您可能不想将单个三次贝塞尔曲线拟合到您的数据中。更一般地,您希望将一系列三次贝塞尔曲线(即分段三次贝塞尔拟合)拟合到任意数据集。

有一篇不错的论文可以追溯到 1995 年,并附有 MATLAB 代码,它是这样做的:

% Lane, Edward J. Fitting Data Using Piecewise G1 Cubic Bezier Curves.
% Thesis, NAVAL POSTGRADUATE SCHOOL MONTEREY CA, 1995

http://www.dtic.mil/dtic/tr/fulltext/u2/a298091.pdf

要使用它,您必须至少指定结点的数量,即优化例程将使用的数据点数量以使其适合。或者,您可以自己指定结点,从而提高拟合的可靠性。论文展示了一些非常棘手的例子。请注意,Lane 的方法保证三次 Bézier 段之间的 G1 连续性(相邻切向量的方向相同),即平滑关节。但是,曲率可能不连续(二阶导数方向的变化)。

我重新实现了代码,将其更新为现代 MATLAB (R2015b)。如果您愿意,请与我联系。

这是一个仅使用三个结点(由代码自动选择)的示例,将两个三次贝塞尔线段拟合到 Lissajous 图形。

利萨如图

于 2015-09-22T17:50:06.377 回答
2

如果大多数数据符合模型,您可以尝试RANSAC。从这些点中选择 4 个点并随机拟合贝塞尔曲线就很容易了。我不确定根据所有其他点(RANSAC 算法的一部分)评估曲线会有多昂贵。但这将是一个线性解决方案,并且 RANSAC 非常容易编写(并且可能有开源算法)。

于 2011-06-10T00:54:24.403 回答
0

对于这个问题,我有一个 MATLAB 解决方案。我遇到了同样的问题,但是我的代码是用 MATLAB 编写的。我希望将它翻译成 Python 不会太难。

您可以通过此代码FindBezierControlPointsND.m找到控制点。 由于某种原因,它的存档中没有函数“ChordLengthNormND”,但它在第 45 行被调用。

我用以下几行替换它:

[arclen,seglen] = arclength(p(:,1),p(:,2),'sp');
t = zeros(size(p,1),1);
sums = seglen(1);
for i = 2:size(p,1)-1
    t(i) = sums / arclen;
    sums = sums + seglen(i);
end
t(end) = 1;

arclength的 MATLAB 代码可以在这里获得。

之后,我们有了贝塞尔曲线的控制点,网上有很多通过控制点构建贝塞尔曲线的实现。

于 2014-06-20T17:10:43.117 回答
-1

首先,确保你所要求的实际上是你想要的。将点拟合到贝塞尔曲线会将它们放置在点的外壳中。使用样条曲线将确保您的曲线通过所有点。

也就是说,创建绘制两者的函数一点也不复杂。维基百科有一篇很好的文章,将解释基本知识,贝塞尔曲线

于 2011-06-10T04:38:58.330 回答