ios - 从 ARKit 中的 faceAnchor 中提取 yaw/pitch/roll
问题描述
使用 ARKit 进行人脸跟踪,一旦检测到人脸,我就会得到 faceAnchor (ARFaceAnchor),它提供了一个 simd_float4x4 矩阵。我知道转换矩阵,并且也知道该主题已被部分解决(此处:How to get values from simd_float4 in objective-c和此处:simd_float4x4 Columns),但是否有一种直接的方法来获得偏航/俯仰/来自面部锚点的 rool 值?(为了在下面的代码中提供我的 y/p/r 值)。
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
let faceAnchor = anchor as? ARFaceAnchor
let data = faceAnchor?.transform
print(data!)
let message = OSCMessage(
OSCAddressPattern("/orientation"),
yawValue,
pitchValue,
rollValue
)
client.send(message)
print(message)
}
仅供参考,OSCMessage 来自嵌入在我的项目中的 SwiftOSC 框架。
解决方案
由于 Apple 显然没有(还)为此目的提供函数,因此它是实现四元数到欧拉角计算的先验要求。借助这些数学资源和弧度到度数的转换函数,可以将其实现为扩展,如下所示:
extension matrix_float4x4 {
// Function to convert rad to deg
func radiansToDegress(radians: Float32) -> Float32 {
return radians * 180 / (Float32.pi)
}
var translation: SCNVector3 {
get {
return SCNVector3Make(columns.3.x, columns.3.y, columns.3.z)
}
}
// Retrieve euler angles from a quaternion matrix
var eulerAngles: SCNVector3 {
get {
// Get quaternions
let qw = sqrt(1 + self.columns.0.x + self.columns.1.y + self.columns.2.z) / 2.0
let qx = (self.columns.2.y - self.columns.1.z) / (qw * 4.0)
let qy = (self.columns.0.z - self.columns.2.x) / (qw * 4.0)
let qz = (self.columns.1.x - self.columns.0.y) / (qw * 4.0)
// Deduce euler angles
/// yaw (z-axis rotation)
let siny = +2.0 * (qw * qz + qx * qy)
let cosy = +1.0 - 2.0 * (qy * qy + qz * qz)
let yaw = radiansToDegress(radians:atan2(siny, cosy))
// pitch (y-axis rotation)
let sinp = +2.0 * (qw * qy - qz * qx)
var pitch: Float
if abs(sinp) >= 1 {
pitch = radiansToDegress(radians:copysign(Float.pi / 2, sinp))
} else {
pitch = radiansToDegress(radians:asin(sinp))
}
/// roll (x-axis rotation)
let sinr = +2.0 * (qw * qx + qy * qz)
let cosr = +1.0 - 2.0 * (qx * qx + qy * qy)
let roll = radiansToDegress(radians:atan2(sinr, cosr))
/// return array containing ypr values
return SCNVector3(yaw, pitch, roll)
}
}
}
推荐阅读
- ios - 启动屏幕图像未出现在 SwiftUI 应用程序中
- java - 如何在 MutableLivedata 中进行更改
- >(从 UI 中删除项目 + 添加新项目)?
- sql - 将列名与其他表中的数据匹配
- python - 计算给定字符串中元音和辅音的数量
- c# - 手动编辑后 TextArea 对更改没有反应
- java - Java作业问题我一直没能解决
- javascript - 有没有办法对我需要的 javascript 文件列表进行分组?
- amazon-web-services - Lambda 不在 DynamoDB 中创建数据
- swift - 使列表只更新一次
- r - Shinyapp 中的错误:分组因子必须恰好有 2 个级别