点群からの楕円近似

Namespace: FVIL.CG
Assembly: FVILbasic (in FVILbasic.dll) Version: 3.1.0.0 (3.1.0.17)

Syntax

C#
public static CFviEllipse FitEllipse(
	DPNT_T_ARRAY points,
	FitMode fit_mode,
	double param
)
Visual Basic
Public Shared Function FitEllipse ( 
	points As DPNT_T_ARRAY,
	fit_mode As FitMode,
	param As Double
) As CFviEllipse

Parameters

points
Type: FVIL..::..DPNT_T_ARRAY
入力点群 (5個以上)
fit_mode
Type: FVIL.CG..::..FitMode
近似モード (※注) LSM_FAST は対応していません。)
param
Type: System..::..Double
最適化パラメータ(ロバスト推定法で利用)

Return Value

Type: CFviEllipse
算出された楕円を返します。

Remarks

与えれた座標点群から、最小二乗法または、ロバスト推定法で楕円の中心座標、主軸半径、副軸半径、主軸角度を算出します。


最適化パラメータ:

ロバスト推定法は、標準偏差によりインライアとアウトライアを判定しています。 点群の誤差は正規分布であることを前提として、標準偏差より信頼区間内の点をインライアと判定します。 param は、例外値の影響を軽減するために利用されるパラメータです。 近似モード(fit_mode)によって、パラメータの意味が異なります。
誤差の計算式は、楕円を2次曲線の式 で表すと、以下の通りとなります。


近似モード(fit_mode):
項目説明
ロバスト推定 (M推定法)MESTIMATORparam は 誤差の標準偏差です。 標準偏差より 95% 信頼区間内の点をインライアと判定します。 つまり、 [-1.96σ, 1.96σ] より、95%信頼区間が計算されます。 推定した、対象点群の標準偏差をパラメータとして入力してください。 例えば、以下の信頼区間内の点をインライアとして判定したい場合は、次の係数を入力してください。
  • 90.0%信頼区間内:1.645
  • 95.0%信頼区間内:1.960
  • 99.0%信頼区間内:2.567
  • 99.9%信頼区間内:3.291
ロバスト推定 (ランザック法)RANSAC 同上
ロバスト推定 (最小メディアン法)LMEDSparam は無視されます。 計算結果より自動的に標準偏差を計算します。 標準偏差より95%信頼区間内の点をインライアと判定します。
ロバスト推定 (M推定法)
標準偏差の自動決定
MESTIMATOR2param は 誤差の標準偏差の係数です。 標準偏差は、自動的に計算されます。
ロバスト推定 (最小メディアン法)
標準偏差の自動決定
LMEDS2 同上
最小二乗法LSMparam は無視されます。

入力点群の個数制限:

入力点群の個数は、近似モード毎に制限があります。 この制限は、内部計算で行列演算を用いていることに起因します。

項目説明
ロバスト推定 (M推定法)MESTIMATOR pnt_num * 6 < 228
ロバスト推定 (M推定法)
標準偏差の自動決定
MESTIMATOR2 pnt_num * 6 < 228
最小二乗法LSM pnt_num * 6 < 228

乱数:

fit_mode で、 RANSAC または LMEDS を選択した場合、 fnFIE_mtrand_real2 で発生させた擬似乱数を使用して処理をしています。 擬似乱数の初期化用シードは、現在時刻を取得して、その値にて設定をしています。 そのため、入力データが同じ点群でも、結果が異なることがあります。

処理に失敗した場合は例外を発行します。 例外の原因と発生位置を特定するには、発行された例外クラスの ErrorCode メンバと Function メンバを参照してください。


エラーコード:
ErrorCode メンバ内容
11FVIL.ErrorCode.INVALID_PARAMETER引数に指定された値が不正です。

関連する FIE 関数:

fnFIE_fit_ellipse

Examples

ソースコード:
C# Copy imageCopy
using System;
using System.Collections.Generic;
using System.Text;
using fvalgcli;

namespace User.SampleCode
{
    public partial class CG
    {
        /// <summary>
        /// 点群からの楕円近似.
        /// </summary>
        [FvPluginExecute]
        public void FitEllipse()
        {
            try
            {
                double center_x = 60.0;
                double center_y = 70.0;
                double axis_x = 80.0;
                double axis_y = 40.0;
                double degree = 45.0;
                List<FVIL.Data.CFviPoint> srcData = getPoints_Ellipse(center_x, center_y, axis_x, axis_y, degree);

                // 0) 入力点群の準備.
                FVIL.DPNT_T_ARRAY points = new FVIL.DPNT_T_ARRAY();
                points.Resize(srcData.Count);

                fvalgcli.DPNT_T_PTR ptr = points.Address;
                for (int i = 0; i < points.Count; i++)
                {
                    ptr[0] = fvalgcli.DPNT_T.init(srcData[i].X, srcData[i].Y);
                    ptr += 1;
                }

                // 1) 処理実行.
                FVIL.Data.CFviEllipse ellipse = FVIL.CG.Function.FitEllipse(points, FVIL.CG.FitMode.MESTIMATOR, 1.645);

                // E) 確認.
                Console.Out.WriteLine("-- Ellipse");
                Console.Out.WriteLine(" Source... Center = ({0:f},{1:f}), AxisX = {2:f}, AxisY = {3:f} Angle = {4:f}",
                    center_x, center_y, axis_x, axis_y, degree);
                Console.Out.WriteLine(" Result... Center = ({0:f},{1:f}), AxisX = {2:f}, AxisY = {3:f} Angle = {4:f}",
                    ellipse.Center.X, ellipse.Center.Y, ellipse.AxisX, ellipse.AxisY, ellipse.Angle.Degree );
            }
            catch (FVIL.CFviException ex)
            {
                Assert.Fail("{0}: ErrorCode={1} {2}", ex.Function, ex.ErrorCode, ex.Message);
            }
        }

        /// <summary>
        /// 楕円の外周上の点を取得します.
        /// </summary>
        /// <param name="center_x"></param>
        /// <param name="center_y"></param>
        /// <param name="axis_x"></param>
        /// <param name="axis_y"></param>
        /// <param name="degree"></param>
        /// <returns></returns>
        private  List<FVIL.Data.CFviPoint> getPoints_Ellipse(double center_x,
                                                            double center_y,
                                                            double axis_x,
                                                            double axis_y,
                                                            double degree)
        {
            FVIL.Data.CFviEllipse src = new FVIL.Data.CFviEllipse(center_x, center_y, axis_x, axis_y, degree);
            FVIL.Data.CFviPolyline polyline = src.ToCFviPolyline();

            return polyline.ToList();
        }
    }
}


Visual Basic Copy imageCopy
Imports System.Collections.Generic
Imports System.Text
Imports fvalgcli

Namespace SampleCode
    Public Partial Class CG
        ''' <summary>
        ''' 点群からの楕円近似.
        ''' </summary>
        <FvPluginExecute> _
        Public Sub FitEllipse()
            Try
                Dim center_x As Double = 60.0
                Dim center_y As Double = 70.0
                Dim axis_x As Double = 80.0
                Dim axis_y As Double = 40.0
                Dim degree As Double = 45.0
                Dim srcData As List(Of FVIL.Data.CFviPoint) = getPoints_Ellipse(center_x, center_y, axis_x, axis_y, degree)

                ' 0) 入力点群の準備.
                Dim points As New FVIL.DPNT_T_ARRAY()
                points.Resize(srcData.Count)

                Dim ptr As fvalgcli.DPNT_T_PTR = points.Address
                For i As Integer = 0 To points.Count - 1
                    ptr(0) = fvalgcli.DPNT_T.init(srcData(i).X, srcData(i).Y)
                    ptr += 1
                Next

                ' 1) 処理実行.
                Dim ellipse As FVIL.Data.CFviEllipse = FVIL.CG.[Function].FitEllipse(points, FVIL.CG.FitMode.MESTIMATOR, 1.645)

                ' E) 確認.
                Console.Out.WriteLine("-- Ellipse")
                Console.Out.WriteLine(" Source... Center = ({0:f},{1:f}), AxisX = {2:f}, AxisY = {3:f} Angle = {4:f}", center_x, center_y, axis_x, axis_y, degree)
                Console.Out.WriteLine(" Result... Center = ({0:f},{1:f}), AxisX = {2:f}, AxisY = {3:f} Angle = {4:f}", ellipse.Center.X, ellipse.Center.Y, ellipse.AxisX, ellipse.AxisY, ellipse.Angle.Degree)
            Catch ex As FVIL.CFviException
                Assert.Fail("{0}: ErrorCode={1} {2}", ex.[Function], ex.ErrorCode, ex.Message)
            End Try
        End Sub

        ''' <summary>
        ''' 楕円の外周上の点を取得します.
        ''' </summary>
        ''' <param name="center_x"></param>
        ''' <param name="center_y"></param>
        ''' <param name="axis_x"></param>
        ''' <param name="axis_y"></param>
        ''' <param name="degree"></param>
        ''' <returns></returns>
        Private Function getPoints_Ellipse(center_x As Double, center_y As Double, axis_x As Double, axis_y As Double, degree As Double) As List(Of FVIL.Data.CFviPoint)
            Dim src As New FVIL.Data.CFviEllipse(center_x, center_y, axis_x, axis_y, degree)
            Dim polyline As FVIL.Data.CFviPolyline = src.ToCFviPolyline()

            Return polyline.ToList()
        End Function
    End Class
End Namespace

Exceptions

ExceptionCondition
FVIL..::..CFviExceptionこの例外の原因については、上記のエラーコード表をご参照ください。

See Also