Android中的透视投影在增强现实应用程序中

Fra*_*e91 4 geometry android projection perspectivecamera augmented-reality

目前我正在编写一个增强现实应用程序,我在屏幕上获取对象时遇到了一些问题.对我来说非常令人沮丧的是,我无法将gps-points转换为我的Android设备上相应的屏幕点.我已经在stackoverflow上阅读了很多文章和许多其他帖子(我已经问了类似的问题),但我仍然需要你的帮助.

我做了维基百科中解释的透视投影.

我如何处理透视投影的结果以获得最终的屏幕点?

ben*_*che 13

维基百科的文章在我不久前读到它时也让我很困惑.以下是我尝试以不同方式解释它:


情况

让我们简化一下情况.我们有:

  • 我们的投影点D(x,y,z) - 你称之为relativePositionX | Y | Z.
  • 尺寸为w*h的图像平面
  • 视图的半角 α

......我们希望:

  • 图像平面中B的坐标(我们称之为XY)

X屏幕坐标的架构:

E是我们在这种配置中的"眼睛"的位置,我选择它作为简化的起源.

可以通过以下方式估计焦距f:

  • tan(?) = (w/2) / f (1)

有点几何

您可以在图片上看到三角形ECDEBM相似的,因此使用Side-Splitter定理,我们得到:

  • MB / CD = EM / EC<=> X / x = f / z (2)

有了(1)(2),我们现在有:

  • X = (x / z) * ( (w / 2) / tan(?) )

如果我们回到维基百科文章中使用的符号,我们的等式相当于:

  • b_x = (d_x / d_z) * r_z

你可以注意到我们错过了乘法s_x / r_x.这是因为在我们的例子中,"显示尺寸"和"记录表面"是相同的,所以s_x / r_x = 1.

注意:Y的推理相同.


实际使用

一些评论:

  • 通常,使用α= 45deg,这意味着tan(?) = 1.这就是为什么这个术语在许多实现中都没有出现.
  • 如果要保留您显示元素的比例,保持˚F恒定既XŸ,IE的替代计算:

    • X = (x / z) * ( (w / 2) / tan(?) )Y = (y / z) * ( (h / 2) / tan(?) )

    ......做:

    • X = (x / z) * ( (min(w,h) / 2) / tan(?) )Y = (y / z) * ( (min(w,h) / 2) / tan(?) )

    注意:当我说"显示尺寸"和"记录表面"是相同的时, "这不是真的,并且min 操作在这里是为了补偿这种近似,使方形表面r适应潜在的 -矩形表面小号.

    注2:Appunta使用你注意到的而不是使用min(w,h)/ 2screenRatio= (getWidth()+getHeight())/2.两种解决方案都保持元素比例.根据屏幕自身的比例,焦点和视角会略有不同.您实际上可以使用任何要定义的函数f.

  • 正如您在上图中所注意到的,屏幕坐标在此处定义为[-w/2; w/2]对于X和[-h/2; H/2]为Y,但你可能想 [0; w][0; h]相反.X += w/2Y += h/2-问题解决了.


结论

我希望这能回答你的问题.如果它需要版本,我会留在附近.

再见!

<自我提升警报>我实际上前段时间做了一篇 关于3D投影和渲染的文章.实现是在Javascript中,但它应该很容易翻译.

  • 在投影期间,当您执行"b_x =(d_x/d_z)*r_z"时,d_x和d_z是您选择的真实世界单位,而b_x和r_z位于屏幕的单位(可能是像素).因此,"(d_x/d_z)"是无单位的,因为您计算相对比例,并乘以r_z,将此比例应用于屏幕大小. (2认同)