如何从ARKit的3D人脸网格中获取双眼的真实世界3D坐标?
获取ARKit人脸网格中双眼的真实世界3D坐标
嘿,我来帮你搞定这个需求!其实ARKit给我们提供了两种靠谱的方式来获取双眼的真实世界3D坐标,一种是直接用ARFaceAnchor内置的眼位变换(推荐,精度更高),另一种是从人脸网格顶点中提取(适合需要自定义眼部关键点的场景),下面给你详细拆解:
方法一:用ARFaceAnchor内置的眼位变换(最便捷)
ARFaceAnchor已经直接帮我们计算好了双眼的变换矩阵,我们只需要把这个局部坐标转换成世界坐标就行,代码如下:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { guard let faceAnchor = anchor as? ARFaceAnchor else { return } // 把右眼的局部坐标转换成世界坐标 let rightEyeWorldPos = node.convertPosition( SCNVector3Zero, from: SCNNode(transform: faceAnchor.rightEyeTransform) ) // 左眼同理 let leftEyeWorldPos = node.convertPosition( SCNVector3Zero, from: SCNNode(transform: faceAnchor.leftEyeTransform) ) print("右眼真实世界坐标:\(rightEyeWorldPos)") print("左眼真实世界坐标:\(leftEyeWorldPos)") }
代码解释:
faceAnchor.rightEyeTransform是右眼相对于面部锚点的局部变换矩阵,这个矩阵的原点就是ARKit识别的眼球参考点- 我们创建一个临时SCNNode应用这个变换,再用面部节点(
node)的convertPosition方法,把临时节点的原点转换成世界坐标系下的位置,这就是双眼的真实世界3D坐标了
方法二:从ARSCNFaceGeometry网格顶点提取(自定义关键点)
如果你需要更精细的眼部关键点(比如瞳孔中心近似),可以从人脸网格的顶点中计算,代码如下:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { guard let faceAnchor = anchor as? ARFaceAnchor, let faceGeometry = virtualFaceNode.geometry as? ARSCNFaceGeometry else { return } // 先更新面部网格的最新数据 faceGeometry.update(from: faceAnchor.geometry) // 双眼区域的顶点索引范围(不同iOS版本可能略有差异,建议测试确认) let rightEyeVertexRange = 106...126 let leftEyeVertexRange = 336...356 // 获取网格的顶点缓冲区 guard let vertexBuffer = faceGeometry.geometryData(for: .vertex) else { return } vertexBuffer.contents().withMemoryRebound(to: SCNVector3.self, capacity: faceGeometry.vertexCount) { vertices in // 计算右眼顶点的平均位置(作为瞳孔中心近似) var rightEyeLocalPos = SCNVector3Zero for index in rightEyeVertexRange { rightEyeLocalPos += vertices[index] } rightEyeLocalPos /= Float(rightEyeVertexRange.count) // 转换成世界坐标 let rightEyeWorldPos = node.convertPosition(rightEyeLocalPos, from: virtualFaceNode) // 左眼同理计算 var leftEyeLocalPos = SCNVector3Zero for index in leftEyeVertexRange { leftEyeLocalPos += vertices[index] } leftEyeLocalPos /= Float(leftEyeVertexRange.count) let leftEyeWorldPos = node.convertPosition(leftEyeLocalPos, from: virtualFaceNode) print("右眼世界坐标(网格顶点平均):\(rightEyeWorldPos)") print("左眼世界坐标(网格顶点平均):\(leftEyeWorldPos)") } }
注意事项:
- 确保你的AR会话配置是
ARFaceTrackingConfiguration,并且设备支持人脸追踪(iPhone X及以上机型) virtualFaceNode要正确添加到AR场景中,并且和ARFaceAnchor绑定- 方法一中的内置变换精度更高,也更稳定,优先推荐使用;方法二适合需要自定义眼部关键点的场景,但要注意顶点索引可能随iOS版本变化,建议自行测试调整
内容的提问来源于stack exchange,提问作者Ankit Chauhan
相关产品推荐
相关产品推荐

