12

对不起,我的英语不好。我有以下问题:

1

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

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

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

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

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

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

非常感谢你!

4

3 回答 3

5

我看到了几个问题。

唯一真正的错误是您将投影放大 _canvasWidth/2 等,而不是从主点平移那么远 - 将这些值添加到投影结果中,乘法就像“缩放”到投影那么远。

其次,处理全局笛卡尔坐标空间是一个坏主意。使用您使用的公式,(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 里面有参数。

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

最后,我不确定android API,但请确保您获得的是真正的北向轴承而不是磁北向轴承。某些平台根据参数或配置返回。(如果这就是 API 想要的等等,那么你的度数就是弧度 - 愚蠢的事情,但我已经减少了调试时间:))。

于 2013-04-02T16:53:20.530 回答
5

您想要的答案将取决于您需要的结果的准确性。正如 danaid 所指出的,图像传感器的非线性和大气失真等其他因素可能会导致误差,但在不同设备上使用不同的相机等将是难以解决的问题。因此,让我们首先获得一个合理的近似值,当需要更高的精度时可以对其进行调整。

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

关于一致坐标的说明。在他的尺度上,一旦你使用将经纬度转换为米,使用 cos(lat) 作为比例因子,你应该能够从“平坦地球”的角度对待每个人。然后您只需要记住相机的 xy 平面大致是全局 xz 平面。

概念背景 下图展示了点在图像平面上的投影。用于透视的 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)

因此,应用于矩形顶点的透视因子将是与线之间顶点的距离的比例。简化:

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

回答

透视变换相对于焦点在观察方向上的距离是线性的。下图是 X 轴平行于图像平面,Y 轴指向视图方向绘制的。在该坐标系中,对于任意点 P 和距原点任意距离的图像平面,投影点 p 的 X 坐标 px 与 Px/Py 成正比,这些值可以进行线性插值。

在图中,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 方法校准相机的位置和方向。可以在此处找到此方法的简明证明(使用重心坐标) 。

由于所需的变换都是基于齐次坐标的线性变换,因此您可以应用重心坐标基于任意三个或更多点进行插值,假设它们在齐次 3 空间中的 X、Y、Z、W 坐标和它们的 (x,y) 坐标在图像空间。点越接近目标点,非线性可能越不显着,因此在您的示例中,您将使用 POS 1 和 POS3,因为矩形在左侧,而 POS2 或 POS4 取决于相对距离.

(重心坐标可能是最熟悉的用于在 3D 图形中的三角形(片段)上插入颜色的方法。)

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

两个相关的 SO 问题:3d中纹理坐标的透视校正和重心坐标纹理映射此图可能有助于解释基于全局坐标的图像坐标插值

于 2013-04-05T21:53:27.490 回答
3

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

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

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

于 2013-03-27T22:21:11.247 回答