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

如何在ARFaceTrackingConfiguration中计算双眼瞳孔的三维距离?

计算ARFaceTracking中两个瞳孔的三维距离

嘿,我来帮你搞定这个三维瞳孔距离计算的问题!核心思路是把Vision检测到的2D瞳孔点,映射到ARFaceAnchor提供的面部三维顶点数据,然后计算两个三维点之间的欧氏距离就行啦。下面是具体的实现步骤:

具体实现步骤

1. 在面部跟踪代理方法中处理数据

首先确保你的ViewController遵循ARSCNViewDelegate,然后在面部更新的代理方法里,同时获取ARFaceAnchor和Vision的面部landmarks:

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
    guard let faceAnchor = anchor as? ARFaceAnchor else { return }
    
    // 先更新你的面部几何
    faceGeo?.update(from: faceAnchor.geometry)
    
    // 获取当前帧的图像和视图尺寸,用于Vision检测
    guard let currentFrame = sceneView.session.currentFrame else { return }
    let imageSize = sceneView.bounds.size
    
    // 创建Vision面部landmark请求
    let landmarkRequest = VNDetectFaceLandmarksRequest { [weak self] request, error in
        guard let self = self,
              let faceObservations = request.results as? [VNFaceObservation],
              let firstFace = faceObservations.first else {
            print("没检测到面部landmarks")
            return
        }
        
        // 调用计算距离的方法
        self.computePupil3DDistance(faceObservation: firstFace, faceAnchor: faceAnchor, imageSize: imageSize)
    }
    
    // 执行Vision请求
    let imageHandler = VNImageRequestHandler(cvPixelBuffer: currentFrame.capturedImage, options: [:])
    do {
        try imageHandler.perform([landmarkRequest])
    } catch {
        print("Vision请求失败:\(error.localizedDescription)")
    }
}

2. 映射2D点到三维顶点并计算距离

接下来实现核心的计算方法,这里的关键是利用Vision返回的瞳孔点索引,直接从ARFaceAnchor的三维顶点数组中取出对应点:

private func computePupil3DDistance(faceObservation: VNFaceObservation, faceAnchor: ARFaceAnchor, imageSize: CGSize) {
    guard let faceLandmarks = faceObservation.landmarks,
          let rightPupil = faceLandmarks.rightPupil,
          let leftPupil = faceLandmarks.leftPupil,
          // 瞳孔区域默认只有1个关键点,取第一个索引
          let rightPupilIndex = rightPupil.pointIndexes.first,
          let leftPupilIndex = leftPupil.pointIndexes.first else {
        print("无法获取瞳孔关键点")
        return
    }
    
    // 获取ARFaceAnchor的面部三维顶点数组
    let faceVertices = faceAnchor.geometry.vertices
    
    // 确保索引在有效范围内
    guard rightPupilIndex < faceVertices.count, leftPupilIndex < faceVertices.count else {
        print("瞳孔索引超出顶点数组范围")
        return
    }
    
    // 取出左右瞳孔的三维坐标
    let rightPupil3D = faceVertices[rightPupilIndex]
    let leftPupil3D = faceVertices[leftPupilIndex]
    
    // 计算两点间的三维距离(单位是米,ARKit用米作为坐标系单位)
    let distance = calculateSCNVectorDistance(a: rightPupil3D, b: leftPupil3D)
    print("两个瞳孔的三维距离:\(String(format: "%.4f", distance)) 米")
}

// 辅助工具函数:计算两个SCNVector3的欧氏距离
private func calculateSCNVectorDistance(a: SCNVector3, b: SCNVector3) -> CGFloat {
    let dx = a.x - b.x
    let dy = a.y - b.y
    let dz = a.z - b.z
    return CGFloat(sqrt(dx*dx + dy*dy + dz*dz))
}

3. 一些需要注意的细节

  • ARKit的面部坐标系是以面部中心为原点的局部空间,单位是米,所以计算出来的距离就是真实世界中瞳孔的物理距离哦。
  • 因为面部表情会实时变化,ARFaceAnchor的顶点数据也会跟着更新,所以距离结果会实时变动,如果需要更稳定的数值,可以做个简单的平滑处理(比如最近几次结果的平均值)。
  • 确保Vision请求用的是当前帧的capturedImage,图像尺寸和sceneView的bounds匹配,避免坐标转换出错。

内容的提问来源于stack exchange,提问作者Rohan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:35:53