2D 画像の既知の 2 点間の 3D 距離を mm 単位で抽出しようとしています。シーン内のマーカーに対するカメラ座標を取得するために、正方形の AR マーカーを使用しています。ポイントは、これらのマーカーの角です。
以下に例を示します。
コードは C# で記述されており、XNA を使用しています。CoPlanar POSIT に AForge.net を使用しています。距離を計算するために実行する手順は次のとおりです。
1.画面の角をマークします。コーナーは 2D ベクトル形式で表され、画像の中心は (0,0) です。上が Y 方向の正、右が X 方向の正です。
2. AForge.net Co-Planar POSIT アルゴリズムを使用して、各マーカーのポーズを取得します。
float focalLength = 640; //Needed for POSIT
float halfCornerSize = 50; //Represents 1/2 an edge i.e. 50mm
AVector[] modelPoints = new AVector3[]
{
new AVector3( -halfCornerSize, 0, halfCornerSize ),
new AVector3( halfCornerSize, 0, halfCornerSize ),
new AVector3( halfCornerSize, 0, -halfCornerSize ),
new AVector3( -halfCornerSize, 0, -halfCornerSize ),
};
CoplanarPosit coPosit = new CoplanarPosit(modelPoints, focalLength);
coPosit.EstimatePose(cornersToEstimate, out marker1Rot, out marker1Trans);
3. XNA 回転/平行移動マトリックスに変換します (AForge は OpenGL マトリックス形式を使用します)。
float yaw, pitch, roll;
marker1Rot.ExtractYawPitchRoll(out yaw, out pitch, out roll);
Matrix xnaRot = Matrix.CreateFromYawPitchRoll(-yaw, -pitch, roll);
Matrix xnaTranslation = Matrix.CreateTranslation(marker1Trans.X, marker1Trans.Y, -marker1Trans.Z);
Matrix transform = xnaRot * xnaTranslation;
4.コーナーの 3D 座標を見つけます。
//Model corner points
cornerModel = new Vector3[]
{
new Vector3(halfCornerSize,0,-halfCornerSize),
new Vector3(-halfCornerSize,0,-halfCornerSize),
new Vector3(halfCornerSize,0,halfCornerSize),
new Vector3(-halfCornerSize,0,halfCornerSize)
};
Matrix markerTransform = Matrix.CreateTranslation(cornerModel[i].X, cornerModel[i].Y, cornerModel[i].Z);
cornerPositions3d1[i] = (markerTransform * transform).Translation;
//DEBUG: project corner onto screen - represented by brown dots
Vector3 t3 = viewPort.Project(markerTransform.Translation, projectionMatrix, viewMatrix, transform);
cornersProjected1[i].X = t3.X; cornersProjected1[i].Y = t3.Y;
5.マーカーの 2 つのコーナー間の 3D 距離を見てください。これは 100mm を表します。この 3D 距離を 100 mm に変換するために必要な倍率を求めます。(私は実際に平均倍率を取得します):
for (int i = 0; i < 4; i++)
{
//Distance scale;
distanceScale1 += (halfCornerSize * 2) / Vector3.Distance(cornerPositions3d1[i], cornerPositions3d1[(i + 1) % 4]);
}
distanceScale1 /= 4;
6.最後に、関連するコーナー間の 3D 距離を見つけ、倍率を掛けて距離を mm で取得します。
for(int i = 0; i < 4; i++)
{
distance[i] = Vector3.Distance(cornerPositions3d1[i], cornerPositions3d2[i]) * scalingFactor;
}
得られた距離は決して正確ではありません。距離を簡単に計算できるように、まな板を使用しました。上の画像は、コーナー 1 (赤から紫) の距離を 147mm (予想 150mm) と計算しました。下の画像は 188mm (予想 200mm) を示しています。
また、同じマーカーのエッジを共有するマーカー コーナー間の距離を測定する場合、得られる 3D 距離が決して同じではないという事実も懸念されます。私が気付いたもう 1 つの点は、茶色の点が色付きの点と完全に一致していないように見えることです。色付きの点は、CoPlanar 位置への入力として使用される座標です。茶色の点は、POSIT を介して計算されたマーカーの中心から計算された位置です。
ここで何が間違っているのか誰にも分かりますか? 私はそれを理解しようとして髪を引っ張っています。コードは非常に単純である必要があります。コードで明らかな間違いを犯したとは思いません。私は数学が苦手なので、基本的な数学のどこが間違っているのか指摘してください...