web-dev-qa-db-ja.com

ベジエ曲線を一連のデータに適合させるにはどうすればよいですか?

ベジエ曲線 でフィットする必要があるデータポイントのセット(間引くことができます)があります。私は正確さよりも速度が必要ですが、適合は認識できるほどまともなはずです。ライブラリをあまり利用しない、使用可能なアルゴリズムも探しています(具体的には NumPy )。

私はいくつかの研究論文を読みましたが、完全に実装するのに十分な詳細はありません。オープンソースの例はありますか?

29
user791684

同様の問題があり、ベジエ曲線フィッティングについてGraphics Gems(1990)から「デジタル化された曲線を自動的にフィッティングするためのアルゴリズム」を見つけました。さらに、その記事の ソースコード を見つけました。

残念ながらそれは私がよく知らないCで書かれています。また、アルゴリズムは理解しにくいです(少なくとも私にとって)。私はそれをC#コードに変換しようとしています。成功したら共有しようと思います。

ファイルGGVecLib.cと同じフォルダにFitCurves.cには、基本的なベクター操作関数が含まれています。

同様のスタックオーバーフローの質問手書きの曲線のスムージングを見つけました。承認された回答は、Graphic GemsのカーブフィッティングアルゴリズムのC#コードを提供します。

17
Archibald

これらの回答の多くに欠けているのは、単一の3次ベジェ曲線をデータに適合させたくない場合があることです。より一般的には、一連の3次ベジエ曲線、つまり区分的3次ベジエフィットを任意のデータセットに当てはめます。

これを行う、MATLABコードを完備した1995年の素敵な論文があります。

% 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

これを使用するには、少なくとも、ノットポイントの数、つまり、最適化ルーチンがこれを適合させるために使用するデータポイントの数を指定する必要があります。オプションで、ノットポイント自体を指定できます。これにより、フィットの信頼性が向上します。論文は、かなり難しい例をいくつか示しています。レーンのアプローチは、3次ベジェセグメント、つまりスムーズジョイント間のG1連続性(隣接する接線ベクトルの方向が同一)を保証することに注意してください。ただし、曲率の不連続性(2次導関数の方向の変化)が存在する場合があります。

コードを再実装し、最新のMATLAB(R2015b)に更新しました。よろしければご連絡ください。

これは、3つのノットポイント(コードによって自動的に選択される)を使用して、2つの3次ベジェセグメントをリサジュー図形にフィットさせる例です。

Lissajous figure

9
Biofloat

ノイズの多いデータに適合する最小二乗として問題を設定できます。

参照 http://nbviewer.ipython.org/5688579

方程式を理解すると、実際の計算はかなり簡単になることに注意してください。実際の計算では、データを合計してから、4x4行列を反転して乗算します。

私はこのスレッドが長い間死んでいることを知っていますが、他の誰かがつまずいた場合に備えて、これは興味深い問題であることがわかりました。

最小二乗に関する優れたチュートリアルについては、 http://www.embedded.com/electrical-engineer-community/industry-blog/4027019/1/Why-all-the-math- を参照してください。

6
Luke Whittlesey

ここでは、python実装を示します。 https://github.com/volkerp/fitCurves

2
Fred Guth

ほとんどのデータがモデルに当てはまる場合、 [〜#〜] ransac [〜#〜] を試すことができます。 4つのポイントをランダムに選び、それらからベジエ曲線をフィットさせるのは簡単です。他のすべてのポイント(RANSACアルゴリズムの一部)に対して曲線を評価するのにどれほどの費用がかかるか、頭の上ではわかりません。しかし、それは線形ソリューションであり、RANSACは本当に簡単に記述できます(そしておそらくそこにオープンソースアルゴリズムがあるでしょう)。

2
Pace

まず第一に、あなたが求めるものが実際にあなたが望むものであることを確認してください。ポイントをベジェ曲線にフィットさせると、ポイントのハルにポイントが配置されます。スプラインを使用すると、曲線がすべての点を通過するようになります。

そうは言っても、どちらかを描画する関数を作成することはまったく複雑ではありません。ウィキペディアには、基本を説明する素晴らしい記事がありますベジエ曲線

0
Pedery

この問題に対する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コードはここから取得できます。

その後、ベジェ曲線の制御点ができました。ウェブ上の制御点によってベジェ曲線を構築する実装はたくさんあります。

0
lintseju