如何计算图片内的特定距离?

时间:2013-03-27 22:00:40

标签: android android-camera augmented-reality coordinate-systems coordinate-transformation

抱歉我的英语不好。我有以下问题:

1

让我们说我的移动设备的相机正在显示这张照片。

在图片中,您可以看到4个不同的位置。我知道每个位置(经度,纬度)。

现在我想知道,图片中的具体位置在哪里。例如,我想在前面20米处和我左边5米处有一个矩形。我只知道这一点的纬度/经度,但我不知道,我必须把它放在图片的内部(x,y)。例如,在我看来,POS3位于(0,400)。 POS4为(600,400),依此类推。

我必须在哪里放置新点,即前方20米,左侧5米? (所以我的输入是:(LatXY,LonXY),我的结果应该是(x,y)在屏幕上)

我还得到了相机的高度以及相机的x,y和z轴角度。

我可以使用简单的数学运算来解决这个问题吗?

非常感谢!

3 个答案:

答案 0 :(得分:5)

我看到了一些问题。

唯一真正的错误是你通过_canvasWidth / 2等缩放你的投射,而不是转换远离主点的那些 - 将这些值添加到投影结果中,乘法就像"缩放&#34 ;远远超出预测。

其次,处理全球笛卡尔坐标空间是一个坏主意。使用您正在使用的公式,(60.1234,20.122)和(60.1235,20.122)之间的差异(即小的纬度差异)会导致所有3个轴中相似幅度的变化,这些变化感觉不对。

采用与计算机图形相同的方法更为直接:将相机设置为相机空间的原点",并通过获得半径距离在世界物体和相机空间之间进行转换(或相似)您的相机位置和对象的位置。见这里:http://www.movable-type.co.uk/scripts/latlong.html

第三,您的透视投影计算是针对理想的针孔相机,您可能没有。它只是一个小的校正,但为了准确,你需要弄清楚如何额外应用与你的相机的固有相机参数相对应的投影。有两种方法可以实现这一点:你可以将它作为你已经拥有的方案的后乘法,或者你可以从乘以3x3矩阵改为使用完整的4x4相机矩阵:http://en.wikipedia.org/wiki/Camera_matrix参数in那里。

使用这种方法,透视投影关于原点是对称的 - 如果你不检查z深度,你可以将你后面的点投射到你的屏幕上,好像它们在你面前的z距离相同。

然后最后我不确定Android API,但要确保你获得真正的北方轴承而不是磁性北方轴承。某些平台根据参数或配置返回。 (你的学位是弧度,如果这是API想要的东西等等 - 愚蠢的事情,但我已经失去了几个小时的调试:))。

答案 1 :(得分:5)

您想要的答案取决于您所需结果的准确性。正如danaid指出的那样,图像传感器中的非线性和其他因素(例如大气失真)可能会导致错误,但在不同的设备上使用不同的相机等解决这些问题将是困难的。因此,让我们从合理的近似开始,可以调整,因为需要更高的精确度。

首先,如果您愿意,您可以忽略设备中的方向信息。如果您有五个位置(POS1 - POS4和摄像机,在一致的坐标系列中,您拥有所需的一切。事实上,您甚至不需要所有这些点。

关于一致坐标的说明。在他的规模上,一旦你使用转换lat和long到米,使用cos(lat)作为缩放因子,你应该能够从“扁平地球”的角度对待每个人。然后你只需要记住摄像机的x-y平面大致是全局x-z平面。

概念背景 下图列出了点在图像平面上的投影。用于透视的dz可以直接使用远点和近点之间的距离与其物理距离的比例来导出。在简单情况中,POS1到POS2线与POS3到POS4的线平行,透视系数只是两条线的比例:

Scale (POS1, POS2) = pixel distance (pos1, pos2) / Physical distance (POS1, POS2)
Scale (POS3, POS4) = pixel distance (pos3, pos4) / Physical distance (POS3, POS4)
Perspective factor = Scale (POS3, POS4) / Scale (POS1, POS2)

因此,应用于rect的顶点的透视因子将是到行之间的顶点的距离的比例。简化:

Factor(rect) ~= [(Rect.z - (POS3, POS4).z / ((POS1, POS2).z - (POS3, POS4).z)] * Perspective factor.

<强>答案

透视变换相对于焦点在视线方向上的距离是线性的。下图是X轴平行于图像平面,Y轴指向视图方向。在该坐标系中,对于距离原点任何距离的任何点P和图像平面,投影点p具有与P.x / P.y成比例的X坐标p.x。这些值可以线性插值。

在图中,tp是目标点的期望投影。获取tp.x,使用对距离的调整在例如pos1.x和pos3.x之间进行插值,如下所示:

tp.x = pos1.x + ((pos3.x-pos1.x)*((TP.x/TP.y)-(POS1.x/POS1.y))/((POS3.x/POS3.y)-(POS1.x/POS1.y))

这种方法的优点在于它不需要任何先前的每个像素观察角度的知识,并且相对于相机的位置和方向的合理误差将相对稳健。

进一步完善

使用更多数据意味着能够弥补更多错误。通过多个视点,可以使用Tienstra method校准摄像机位置和方向。可以找到这种方法的简明证明(使用重心坐标)here

由于所需的变换都是基于齐次坐标的线性变换,因此可以基于任意三个或更多个点应用barycentric coordinates进行插值,给定它们在均匀3空间中的X,Y,Z,W坐标及其(x,y)图像空间中的坐标。点越接近目标点,非线性可能越小,因此在您的示例中,您将使用POS 1和POS3,因为rect在左侧,POS2或POS4取决于相对距离

(重心坐标可能是最常见的用于在3D图形中对三角形(片段)上的颜色进行插值的方法。)

编辑:重心坐标仍然需要W齐次坐标因子,这是表示距焦点距离的透视校正的另一种方式。有关详细信息,请参阅GameDev上的this article

两个相关的SO问题:3d中的perspective correction of texture coordinatesBarycentric coordinates texture mappingThis diagram may help in explaining the interpolation of image coordinates based on global coordinates

答案 2 :(得分:3)

如果您知道相机框架中的点和真实世界坐标,一些简单的线性代数就足够了。像OpenCV这样的软件包将具有此类功能,或者您也可以自己创建投影矩阵:

http://en.wikipedia.org/wiki/3D_projection

一旦你有了一组点,就像填充几个向量来解决方程组一样简单。这将为您提供投影矩阵。一旦有了投影矩阵,就可以假设4个点是平面的。将任何3D坐标相乘以找到相应的2D图像平面坐标。