C# 尝试从2D图像精确测量3D距离
我试图提取出二维图像中两个已知点之间的三维距离,单位为mm。我使用方形AR标记来获得相对于场景中标记的摄影机坐标。这些点是这些标记的角 下面显示了一个示例: 代码是用C#编写的,我使用的是XNA。我正在使用forge.net进行共面假设 我为计算距离而采取的步骤: 1.在屏幕上标记拐角。角点以2D矢量形式表示,图像中心为(0,0)。向上在Y方向为正,向右在X方向为正 2.使用org.net共面定位算法获取每个标记的姿势:C# 尝试从2D图像精确测量3D距离,c#,math,graphics,xna,computer-vision,C#,Math,Graphics,Xna,Computer Vision,我试图提取出二维图像中两个已知点之间的三维距离,单位为mm。我使用方形AR标记来获得相对于场景中标记的摄影机坐标。这些点是这些标记的角 下面显示了一个示例: 代码是用C#编写的,我使用的是XNA。我正在使用forge.net进行共面假设 我为计算距离而采取的步骤: 1.在屏幕上标记拐角。角点以2D矢量形式表示,图像中心为(0,0)。向上在Y方向为正,向右在X方向为正 2.使用org.net共面定位算法获取每个标记的姿势: float focalLength = 640; //Neede
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旋转/平移矩阵(FORGE使用OpenGL矩阵形式):
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.查看标记上两个角之间的3D距离,这表示100毫米。查找将此三维距离转换为100mm所需的比例因子。(我实际上得到了平均比例因子):
for(int i=0;i<4;i++)
{
//距离标度;
距离标度1+=(半角尺寸*2)/矢量3.距离(角位置S3d1[i],角位置S3d1[(i+1)%4]);
}
距离标度1/=4;
6.最后,我找到相关角点之间的3D距离,然后乘以比例因子,得到以mm为单位的距离:
for(int i = 0; i < 4; i++)
{
distance[i] = Vector3.Distance(cornerPositions3d1[i], cornerPositions3d2[i]) * scalingFactor;
}
for(int i=0;i<4;i++)
{
距离[i]=矢量3.距离(转角位置S3d1[i],转角位置S3d2[i])*缩放因子;
}
获得的距离永远不会真正正确。我使用了砧板,因为它可以让我很容易地计算出距离应该是多少。上图计算出拐角1(红色到紫色)的距离为147mm(预计为150mm)。下图显示为188mm(预计为200mm)
同样令人担忧的是,当测量共享同一标记上的边的标记角之间的距离时,获得的三维距离从来都不相同。我注意到的另一件事是,棕色的圆点似乎永远不会与彩色的圆点完全匹配。彩色点是用作共面位置输入的坐标。棕色点是通过POSIT计算的标记中心的计算位置
有人知道这里可能出了什么问题吗?我在拔头发,想弄明白。代码应该很简单,我认为我没有犯任何明显的错误。我的数学不是很好,所以请指出我的基础数学可能也错在哪里…你的问题中有很多黑匣子。第二步的焦距是多少?为什么要在步骤3中进行ypr?如何校准?我建议您从头开始,不要使用您不了解的库 步骤1:创建相机模型。理解错误,建立投影。如果需要,为镜头畸变应用2d过滤器。这可能很难 第2步:在消除镜头失真后,在2d中查找标记。确保您知道错误,并获得中心。可能在多个帧上 步骤3:将项目取消到3d。在1和2之后,这应该很容易 第四步:
第五步:盈利!(用3d测量距离,知道你的误差)我认为你需要3d照片(一组距离中的两张照片)因此,你可以从图像差异中获得视差距离2D->3D脑海中最明显的是立体视觉。这应该与单个网络摄像头一起工作,因此我在已知目标上使用姿势估计的原因。我认为你从所有计算中得到了大量噪音和舍入误差。XNA数学方法旨在提高速度,而不是准确性。看看使用双打,和/或使用自定义数学函数。我考虑了舍入误差,我尝试手动使用双打计算,但它给出了类似的结果。你检查了镜头像差在你的相机?如果在垂直于图像轴的平面上移动相机,而不旋转它,使对象在图像中改变位置,但在其他情况下保持不变,估计值会发生什么变化?
for (int i = 0; i < 4; i++)
{
//Distance scale;
distanceScale1 += (halfCornerSize * 2) / Vector3.Distance(cornerPositions3d1[i], cornerPositions3d1[(i + 1) % 4]);
}
distanceScale1 /= 4;
for(int i = 0; i < 4; i++)
{
distance[i] = Vector3.Distance(cornerPositions3d1[i], cornerPositions3d2[i]) * scalingFactor;
}