You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:59:48