我正在尝试从2D图像中提取两个已知点之间的3D距离(以毫米为单位)。我使用正方形AR标记来获取相机坐标与场景中标记的相对位置。这些点是这些标记的角落。
下面是一个示例:
这段代码是用 C# 写的,我使用 XNA。 我使用 AForge.net 来进行 CoPlanar POSIT。
我的步骤如下,以计算距离:
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. 找到角落的三维坐标:
//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. 查看标记上两个角之间的三维距离,表示100mm。找到将此三维距离转换为100mm所需的比例因子。(我实际上获取平均比例因子):
for (int i = 0; i < 4; i++)
{
//Distance scale;
distanceScale1 += (halfCornerSize * 2) / Vector3.Distance(cornerPositions3d1[i], cornerPositions3d1[(i + 1) % 4]);
}
distanceScale1 /= 4;
6. 最后,我找到相关角落之间的3D距离,并乘以缩放因子以获得毫米单位的距离:
for(int i = 0; i < 4; i++)
{
distance[i] = Vector3.Distance(cornerPositions3d1[i], cornerPositions3d2[i]) * scalingFactor;
}
获取的距离从未真正正确。我使用切菜板,因为它让我轻松计算距离应该是多少。上面的图像计算出第1个角(红色到紫色)的距离为147毫米(预期为150毫米)。下面的图像显示188毫米(预期为200毫米)。
令人担忧的是,当测量共享同一标记边缘的标记角之间的距离时,所得到的三维距离永远不相同。我还注意到的一件事是,棕色点似乎从未与彩色点完全匹配。彩色点是作为CoPlanar posit输入使用的坐标。棕色点是通过POSIT计算出的从标记中心计算出的位置。
有人知道这里可能出了什么问题吗?我正在拼命地想办法解决它。代码应该很简单,我不认为我在代码方面犯了任何明显的错误。我不擅长数学,请指出我的基本数学可能出错的地方...