能否借助CATransform3D通过ARKit人脸网格获取眼部尺寸?
Hey there! Let's clear up what's going on here and get you on the right track to calculate eye width and interocular distance with ARKit.
First: Why Your Current Values Are Useless
The data you're getting right now is uninitialized garbage values—here's why:
ARFaceAnchor.blendShapes[.eyeBlinkLeft]returns aFloat(a weight between 0 and 1) that represents how closed the left eye is, not a transform.- Calling
caTransform3DValueon this float is a mistake—this property isn't meant for blend shape weights, so you're just reading random memory values that don't relate to any actual facial measurements.
How to Actually Calculate Eye Width & Interocular Distance
To get real facial dimensions, you need to use the 3D face mesh vertices from ARFaceAnchor or ARFaceGeometry. Here's how to do it:
Step 1: Understand the Data You Need
ARFaceAnchor.geometrygives you the full 3D mesh of the face, with vertices in the anchor's local coordinate space.- You can also use pre-defined facial feature locations from
ARFaceAnchor, likeleftEyeandrightEye(these areSIMD3<Float>positions), or reference specific vertex indices for eye edges (ARKit has standard vertex indices for facial features—you can test by logging vertex positions to identify which correspond to eye edges).
Step 2: Convert Vertices to World Space & Calculate Distances
If you want measurements in real-world units (meters), convert the local vertices to world space using the face node's transform, then compute the distance between relevant points:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { guard let faceAnchor = anchor as? ARFaceAnchor else { return } // Calculate interocular distance (distance between eye centers) let leftEyeLocalPos = faceAnchor.leftEye let rightEyeLocalPos = faceAnchor.rightEye // Convert local positions to world space let leftEyeWorldPos = simd_mul(node.simdTransform, simd_float4(leftEyeLocalPos, 1)).xyz let rightEyeWorldPos = simd_mul(node.simdTransform, simd_float4(rightEyeLocalPos, 1)).xyz let interocularDistance = simd_distance(leftEyeWorldPos, rightEyeWorldPos) print("Interocular distance: \(interocularDistance) meters") // Calculate left eye width (using mesh vertices) guard let device = MTLCreateSystemDefaultDevice() else { return } let faceGeometry = ARFaceGeometry(device: device)! faceGeometry.update(from: faceAnchor.geometry) // Replace with actual vertex indices for left eye outer/inner edges let leftEyeOuterVertex = faceGeometry.vertices[123] let leftEyeInnerVertex = faceGeometry.vertices[456] let leftEyeOuterWorld = simd_mul(node.simdTransform, simd_float4(leftEyeOuterVertex, 1)).xyz let leftEyeInnerWorld = simd_mul(node.simdTransform, simd_float4(leftEyeInnerVertex, 1)).xyz let leftEyeWidth = simd_distance(leftEyeOuterWorld, leftEyeInnerWorld) print("Left eye width: \(leftEyeWidth) meters") }
Step 3: Notes on Vertex Indices
ARKit's ARFaceGeometry uses consistent vertex indices for key facial features. You can find the exact indices by testing: log a range of vertex positions, then move your eye to see which coordinates shift to match the eye edges.
Key Takeaways
- Forget the
caTransform3DValuefrom blend shapes—it's completely irrelevant to facial measurements. - Use
ARFaceAnchor's face mesh vertices or pre-defined feature positions to calculate real-world distances. - All measurements will be in meters (since ARKit uses a real-world coordinate system).
内容的提问来源于stack exchange,提问作者Rohan

