如何将贝塞尔曲线拟合到一组数据?

问题描述 投票:0回答:5

我有一组数据点(我可以将其稀疏化),需要与 Bézier 曲线 进行拟合。我需要的是速度而不是准确性,但贴合度应该足够好,可以被识别。我也在寻找一种可以使用的算法,该算法不会过多使用库(特别是NumPy)。

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

python algorithm bezier curve-fitting
5个回答
25
投票

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

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

GGVecLib.c

 位于同一文件夹中的
文件
FitCurves.c
包含基本向量操作函数。

我发现了一个类似的堆栈溢出问题,平滑手绘曲线。批准的答案提供了来自 Graphic Gems 的曲线拟合算法的 C# 代码。


15
投票

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

有一篇 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 的方法保证三次贝塞尔线段之间的 G1 连续性(相邻切向量的方向相同),即平滑关节。然而,曲率可能存在不连续性(二阶导数方向的变化)。

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

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


3
投票

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


0
投票

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

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


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代码可以在这里获得。

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

© www.soinside.com 2019 - 2024. All rights reserved.