在 ARKit 中获取相机的向上向量

Posted

技术标签:

【中文标题】在 ARKit 中获取相机的向上向量【英文标题】:Get the up vector of the camera in ARKit 【发布时间】:2018-05-23 00:01:35 【问题描述】:

我正在尝试在ARKit中获取构成截锥体边界的四个向量,我想出的解决方案如下:

找出相机的视野角度 然后找到相机的方向和向上向量 使用这些信息,使用叉积和旋转找到四个向量

这可能是一种草率的做法,但它是迄今为止我得到的最好的方法。

我能够从ARCamera.intrinsicsARCamera.transform 属性中获取FOV 角度和方向矢量。但是,我现在不知道如何获取相机的向上向量。

下面是我用来查找 FOV 角度和方向矢量的一段代码:

func session(_ session: ARSession, didUpdate frame: ARFrame) 
  if xFovDegrees == nil || yFovDegrees == nil 
    let imageResolution = frame.camera.imageResolution
    let intrinsics = frame.camera.intrinsics
    xFovDegrees = 2 * atan(Float(imageResolution.width) / (2 * intrinsics[0,0])) * 180 / Float.pi
    yFovDegrees = 2 * atan(Float(imageResolution.height) / (2 * intrinsics[1,1])) * 180 / Float.pi
  

  let cameraTransform = SCNMatrix4(frame.camera.transform)
  let cameraDirection = SCNVector3(-1 * cameraTransform.m31,
                                   -1 * cameraTransform.m32,
                                   -1 * cameraTransform.m33)

我也愿意接受有关如何找到我想要获得的四个向量的建议。

【问题讨论】:

【参考方案1】:

我不明白这条线是如何工作的:

let cameraDirection = SCNVector3(-1 * cameraTransform.m31,
                                 -1 * cameraTransform.m32,
                                 -1 * cameraTransform.m33)

这给出了相机的方向向量,因为变换矩阵的第 3 行给出了变换后的相机的新 z 方向指向的位置。我们将它乘以 -1,因为相机的默认方向是负 z 轴。

考虑到这些信息以及相机的默认向上向量是正 y 轴这一事实,变换矩阵的第 2 行为我们提供了相机的向上向量。下面的代码给了我我想要的:

let cameraUp = SCNVector3(cameraTransform.m21,
                          cameraTransform.m22,
                          cameraTransform.m23)

【讨论】:

【参考方案2】:

可能是我误解了您要执行的操作,但我想提供一个替代解决方案(方法和结果与您的答案不同)。

出于我的目的,当手机指向上方时,我将向上向量定义为 (0, 1, 0) - 基本上我想要直接指向手机顶部的单位向量。当手机向左水平时,ARKit 将向上向量定义为 (0, 1, 0) - 因此 y 轴指向手机的右侧 - 据说是因为他们希望 AR 应用程序更喜欢水平方向。

camera.transform 返回相机在 AR 会话开始时相对于其初始方向的方向。它是一个 4x4 矩阵——前 3x3 是旋转矩阵——所以当你写 cameraTransform.m21 等时,你引用的是旋转矩阵的一部分,它与向上向量不同(不管你如何定义它)。

因此,如果我将向上向量定义为 y 轴指向手机顶部的单位 y 向量,我必须在 ARKit 空间中将其写为 (-1, 0, 0)。然后简单地将这个向量(稍微修改......见下文)乘以相机的变换将给我我正在寻找的“向上向量”。下面是在 ARSessionDelegate 回调中使用此计算的示例。

func session(_ session: ARSession, didUpdate frame: ARFrame) 
    // the unit y vector is appended with an extra element
    // for multiplying with the 4x4 transform matrix
    let unitYVector = float4(-1, 0, 0, 1)
    let upVectorH = frame.camera.transform * unitYVector
    // drop the 4th element
    let upVector = SCNVector3(upVectorH.x, upVectorH.y, upVectorH.z)

如果您使用 ARKit 的水平方向,您可以使用let unitYVector = float4(0, 1, 0, 1)

您还可以通过将单位向量 (0, 0, 1, 1) 乘以相机变换来执行相同类型的计算,以获得“方向向量”(指向手机正面)。

【讨论】:

以上是关于在 ARKit 中获取相机的向上向量的主要内容,如果未能解决你的问题,请参考以下文章

在 ARKit 中同时显示相机捕获图像和场景背景

没有渲染/虚拟内容的 ARKit/SceneKit 屏幕截图

SceneKit + ARKit:无需相机滚动的广告牌

ARKit从入门到精通-ARCamera介绍

从 ARKit 获取 RGB“CVPixelBuffer”

如何在 ARKit 3 动作捕捉中获取所有关节 XYZ 坐标