基于ARKit与TrueDepth相机的真人活体检测实现问题咨询
法向量计算逻辑校验与真假人脸区分方案
一、当前法向量计算逻辑的问题
你当前的实现存在两个核心错误,无法得到正确的人脸网格法向量:
- 顶点取值逻辑错误:
ARFaceAnchor.geometry.vertices存储的是单个人脸网格顶点的有序集合,并非按三角面分组的三元组。你直接连续取3个顶点拼接三角面,得到的不是真实的人脸拓扑结构,计算结果无参考意义。 - 叉乘方向无统一规则:你使用
vector1 = vertex2 - vertex1、vector2 = vertex2 - vertex3计算叉乘,得到的法向量朝向是随机的,无法进行后续的分布统计。
正确的计算逻辑需要基于官方提供的三角面索引取值,示例代码如下:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { guard let faceAnchor = anchor as? ARFaceAnchor else { return } let faceGeometry = faceAnchor.geometry let vertices = faceGeometry.vertices let triangleIndices = faceGeometry.triangleIndices // 官方提供的三角面顶点索引 var normals = [simd_float3]() for i in stride(from: 0, to: triangleIndices.count, by: 3) { let idx1 = Int(triangleIndices[i]) let idx2 = Int(triangleIndices[i+1]) let idx3 = Int(triangleIndices[i+2]) let v1 = vertices[idx1] let v2 = vertices[idx2] let v3 = vertices[idx3] // 统一逆时针顺序计算,保证法向量朝人脸外侧 let vector1 = v2 - v1 let vector2 = v3 - v1 let normal = simd_normalize(simd_cross(vector1, vector2)) normals.append(normal) } }
二、基于法向量区分真假人脸的方案
核心判断逻辑基于三维结构和二维平面的法向量分布差异:
- 真人是立体3D结构,不同面部区域的法向量朝向差异极大:额头区域法向量基本朝向相机,脸颊区域法向量朝向左右两侧,下巴区域法向量朝向斜下方,整体法向量在X、Y、Z三个轴上的分布方差很高。
- 照片、视频中的人脸是2D平面结构,所有检测到的顶点实际都在同一个平面上,几乎所有法向量的朝向都和平面垂直(基本正对相机),三个轴上的法向量分布方差极低。
具体落地步骤:
- 计算所有法向量在X、Y、Z三个分量上的方差值,求和得到总方差
- 提前测试不同场景下真人、照片/视频人脸的总方差区间,设置合适的判定阈值,低于阈值即可判定为虚假人脸
- 可结合TrueDepth相机的深度数据交叉验证:真人脸不同区域的深度值差异大,2D假脸的深度值几乎均匀,二者结合可以将准确率提升到95%以上
内容的提问来源于stack exchange,提问作者Virgil Adumitroae
相关产品推荐
相关产品推荐

