我正在尝试提取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. 找到角落的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. 查看标记上两个角之间的3D距离,这代表100mm。找到将此3D距离转换为100毫米所需的缩放系数。 (我实际得到平均比例因子):
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)。下图显示188毫米(预计200毫米)。
同样令人担忧的是,当测量在同一标记上共享边缘的标记角之间的距离时,所获得的3D距离永远不会相同。我注意到的另一件事是棕色点似乎永远不会与彩色圆点完全匹配。彩色点是用作CoPlanar位置输入的坐标。褐色点是通过POSIT计算的标记中心的计算位置。
有没有人知道这里可能有什么问题?我正在拔出我的头发试图找出它。代码应该很简单,我不认为我在代码中犯了任何明显的错误。我不擅长数学,所以请指出我的基本数学也可能出错......
答案 0 :(得分:1)
你正在使用问题中的许多黑匣子。第二步的焦距是多少?为什么要在第3步中查看ypr?你如何校准?我建议从头开始,不使用你不理解的库。
步骤1:创建相机模型。理解错误,构建投影。如果需要,可以使用2d滤镜来抑制镜头失真。这可能很难。
步骤2:在消除镜头失真后,在2d内找到标记。确保您知道错误并获得中心。也许超过多个框架。
第3步:取消投影到3d。在1和2之后,这应该很容易。
第4步:???
第5步:获利! (用3d测量距离并知道你的错误)
答案 1 :(得分:0)
我认为您需要拥有3D照片(一组距离中的两张照片),以便您可以从图像差异中获得视差距离