您想要的答案将取决于您需要的结果的准确性。正如 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中纹理坐标的透视校正和重心坐标纹理映射。