如何以绝对值获取ARAnchor的偏航、俯仰和滚转角度?

6

我已经尝试了几天,但还是无法解决这个问题。

在一个基于ARKit的应用程序中,我跟踪用户的面部。如何从锚点获取面部的绝对旋转角度呢?

我可以获取ARAnchor的变换,它是一个simd_matrix4x4。关于如何从该矩阵中获取位置信息有很多资料(它是第三列),但没有关于旋转的说明!

我想通过传递偏航角、俯仰角和横滚角来控制应用程序外的3D对象。

最新的尝试实际上有些有效:

let arFrame = session.currentFrame!
guard let faceAnchor = arFrame.anchors[0] as? ARFaceAnchor else { return }

let faceMatrix = SCNMatrix4.init(faceAnchor.transform)
let node = SCNNode()

node.transform = faceMatrix
let rotation = node.worldOrientation

rotation.x、.y 和 .z 这三个值在 IT 技术中很常见,但随着我移动手机,这些值也在改变。比如,如果我旋转了 180 度并且继续看着手机,这些值就会根据手机的位置而疯狂地变化。
我尝试过在 ARConfiguration 中更改世界对齐方式,但没有任何改变。
是我读取了错误的参数吗?本应该更简单才对!

你需要计算俯仰、偏航和翻滚的欧拉角。关于此方面几乎没有文档,但可以看一下这里:https://michael-martinez.fr/arkit-transform-matrices-quaternions-and-related-conversions/ - Andrew21111
虽然这给了我一些值,但它们仍然不是“绝对的”。这意味着,如果我旋转自己和手机(例如在椅子上旋转而直视手机),旋转值会发生很大变化。 - Andre
你尝试使用node.convert将坐标转换为另一个坐标系了吗? - Andrew21111
是的。我尝试过 node.transform = node.convertTransform(node.transform, from: sceneView.scene.rootNode) 但它仍然受到相机移动的影响。我做错了吗? - Andre
2个回答

7

我已经想通了...

一旦你有了面部锚点,就需要使用它的变换矩阵和相机的变换进行一些计算。

像这样:

let arFrame = session.currentFrame!
guard let faceAnchor = arFrame.anchors[0] as? ARFaceAnchor else { return }

let projectionMatrix = arFrame.camera.projectionMatrix(for: .portrait, viewportSize: self.sceneView.bounds.size, zNear: 0.001, zFar: 1000)
let viewMatrix = arFrame.camera.viewMatrix(for: .portrait)

let projectionViewMatrix = simd_mul(projectionMatrix, viewMatrix)
let modelMatrix = faceAnchor.transform
let mvpMatrix = simd_mul(projectionViewMatrix, modelMatrix)

// This allows me to just get a .x .y .z rotation from the matrix, without having to do crazy calculations
let newFaceMatrix = SCNMatrix4.init(mvpMatrix)
let faceNode = SCNNode()
faceNode.transform = newFaceMatrix
let rotation = vector_float3(faceNode.worldOrientation.x, faceNode.worldOrientation.y, faceNode.worldOrientation.z)

rotation.x、.y和.z将返回面部的俯仰、偏航和翻滚(分别)。

我正在添加一个小乘数并反转其中的2个轴,因此它最终会变成这样:

yaw = -rotation.y*3
pitch = -rotation.x*3
roll = rotation.z*1.5

噢,终于完成了!

1
我知道你正在使用前置摄像头和“ARFaceTrackingConfiguration”,这不应该给你绝对值。我建议你配置第二个后置摄像头的“ARSession”并使用“ARWorldTrackingConfiguration”,它提供绝对值。最终解决方案可能需要两个“ARSession”的值。我还没有测试过这个假设,但似乎是唯一的方法。
更新ARWorldTrackingConfiguration中的引用-
ARWorldTrackingConfiguration类以六自由度(6DOF)跟踪设备的移动,具体来说,是三个旋转轴(横滚、俯仰和偏航)和三个平移轴(在x、y和z方向上的移动)。这种跟踪可以创建沉浸式的AR体验:虚拟对象似乎可以相对于真实世界保持在同一位置,即使用户倾斜设备以查看对象的上方或下方,或者移动设备以查看对象的侧面和背面。
显然,其他跟踪配置不具有此功能。

那似乎是一个疯狂的解决方案!通过了解ARFrame /相机位置,ARKit应该能够返回面部锚点的绝对旋转,而不考虑设备本身的旋转:x - Andre
ARWorldTrackingConfiguration类使用六自由度(6DOF)跟踪设备的运动,包括三个旋转轴(横滚、俯仰和偏航)和三个平移轴(x、y和z方向上的移动)。这种跟踪可以创建沉浸式的AR体验:虚拟对象可以看起来相对于真实世界保持不变,即使用户倾斜设备以查看对象上方或下方,或者移动设备以查看对象的侧面和背面。其他配置没有这种能力。 - Maxim Volgin
虽然你说的没错,在ARFaceAnchor文档中,苹果公司说:“继承的变换属性描述了面部在世界坐标系中的当前位置和方向;也就是说,相对于会话配置的worldAlignment属性指定的坐标空间。” 但是,我已经尝试了所有三个worldAlignment属性,但无法使变换忽略设备本身的面部变换。 - Andre
顺便提一下,“使用重力和方向对齐需要跟踪设备的地理位置。您的应用程序的 Info.plist 必须包括用户可见的文本 NSLocationUsageDescription 或 NSLocationWhenInUseUsageDescription 键,以便用户授予您的应用程序获取位置跟踪的权限。” - 您的 Info.plist 正确,并且已经授权许可了吗? - Maxim Volgin
没关系。我已经用解决方案回答了自己的问题。谢谢。 - Andre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接