如何在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
相关产品推荐
相关产品推荐

