これが取引です。「楕円のような」形状を形成する複数の点 (X、Y) があります。
可能な限り「最適な」楕円を評価/適合させ、そのプロパティ (a、b、F1、F2)、または楕円の中心だけを取得したいと考えています。
任意のアイデア/リードをいただければ幸いです。
ギラッド。
これが取引です。「楕円のような」形状を形成する複数の点 (X、Y) があります。
可能な限り「最適な」楕円を評価/適合させ、そのプロパティ (a、b、F1、F2)、または楕円の中心だけを取得したいと考えています。
任意のアイデア/リードをいただければ幸いです。
ギラッド。
仕事をすることができるMatlab 関数fit_ellipseがあります。楕円の直交距離フィッティングの方法に関するこの論文もあります。直交楕円フィットをウェブで検索すると、おそらく他の多くのリソースも見つかるでしょう。
によって提案された楕円フィッティング法:
ZL Szpak、W. Chojnacki、および A. van den Hengel。 信頼領域と、中心、軸、方向の不確実性測定による保証された楕円フィッティング。 J.Math.イメージングビジョン、2015年。
あなたに興味があるかもしれません。これらは、パラメーター推定の不確実性を表す共分散行列と共に、代数的および幾何学的な楕円パラメーターの両方の推定を提供します。また、推定に関連付けられた平面の 95% 信頼領域を計算する手段も提供します。これにより、楕円近似の不確実性を視覚化できます。
この論文の印刷前のバージョンは、著者の Web サイト ( http://cs.adelaide.edu.au/~wojtek/publicationsWC.html ) で入手できます。メソッドの MATLAB 実装もダウンロードできます: https://sites.google.com/site/szpakz/source-code/guaranteed-ellipse-fitting-with-a-confidence-region-and-an-uncertainty-中心軸と方向の測定
問題は、「最高」を定義することです。あなたの場合は何がベストですか?ポイントの n% を含む最小領域の楕円?
確率の観点から「最良」を定義すると、単純に点の共分散行列を使用して誤差楕円を計算できます。
この「多変量ガウス分布」の誤差楕円には、決定した信頼区間に対応する点が含まれます。
多くの計算パッケージは、対応する固有値と固有ベクトルを使用して共分散を計算できます。楕円の角度は、x 軸と最大固有値に対応する固有ベクトルの間の角度です。半軸は固有値の逆数です。
ルーチンが正規化されたすべてのものを返す場合 (正規化する必要があります)、アルファ信頼区間を取得するためにすべてのものを乗算する係数を決定できます。
Wild Magicライブラリには、楕円フィッティングの関数が含まれていると思います。メソッド解説記事あり
問題にどのようにアプローチするかを説明します。山登りのアプローチをお勧めします。最初に点の重心を開始点として計算し、何らかの方法で a と b の 2 つの値を選択します (おそらく任意の正の値で十分です)。フィット関数が必要です。特定の楕円上にある (に十分近い) ポイントの数を返すことをお勧めします。
int fit(x, y, a, b)
int res := 0
for point in points
if point_almost_on_ellipse(x, y, a, b, point)
res = res + 1
end_if
end_for
return res
今、いくつかから始めますstep
。step
楕円の最適な中心が最初の点から離れないように、十分に大きな値を選択します。それほど大きな値を選択する必要はありませんが、アルゴリズムの最も遅い部分は、最適な中心に近づくのにかかる時間であるため、値が大きいほど良いと思います。
これで、いくつかの初期ポイント ( x , y )、いくつかの初期値aとb、および初期ステップが得られました。アルゴリズムは、現在のポイントよりも優れた隣接ポイントがある場合は、現在のポイントの最良の隣接ポイントを繰り返し選択します。そうでない場合は、ステップを 2 回減らします。ここで「最高」とは、フィット関数を使用することを意味します。また、位置は 4 つの値 (x, y, a, b) で定義され、その近傍は 8 です: (x+-step, y, a, b),(x, y+-step, a, b), (x , y, a+-step, b), (x, y, a, b+-step)(結果が十分でない場合は、対角線を使用してさらに近隣を追加できます。たとえば、(x+-step, y+-step, a、b) など)。これがあなたのやり方です
neighbours = [[-1, 0, 0, 0], [1, 0, 0, 0], [0, -1, 0, 0], [0, 1, 0, 0],
[0, 0, -1, 0], [0, 0, 1, 0], [0, 0, 0, -1], [0, 0, 0, 1]]
iterate (cx, cy, ca, cb, step)
current_fit = fit(cx, cy, ca, cb)
best_neighbour = []
best_fit = current_fit
for neighbour in neighbours
tx = cx + neighbour[0]*step
ty = cx + neighbour[1]*step
ta = ca + neighbour[2]*step
tb = cb + neighbour[3]*step
tfit = fit(tx, ty, ta, tb)
if (tfit > best_fit)
best_fit = tfit
best_neighbour = [tx,ty,ta,tb]
endif
end_for
if best_neighbour.size == 4
cx := best_neighbour[0]
cy := best_neighbour[1]
ca := best_neighbour[2]
cb := best_neighbour[3]
else
step = step * 0.5
end_if
そして、step の値が特定のしきい値 (たとえば 1e-6) よりも小さくなるまで反復を続けます。どの言語を使用するかわからないため、すべてを疑似コードで記述しました。
この方法で見つけた答えが最適であるとは限りませんが、十分な近似になると確信しています。
山登りに関する記事はこちら。