ARFaceTrackingConfiguration:如何区分图片和真人脸?

ARFaceTrackingConfiguration: How to distinguish pictures from real faces?

我们的商店中有几个应用程序使用 ARFaceTrackingConfiguration 来检测 iOS 设备中带有 FaceID 摄像头的用户面部。

正如您可能已经看到的,ARKit 还会跟踪您放在 iPad Pro/iPhoneX 前面的面孔图片,就好像它们是面孔一样。例如。从 our apps (to replicate one can download&run Apples example app for ARFaceTrackingConfiguration):

中的一张照片中拍照

现在我注意到 ARKit 在内部处理真实人脸的方式与处理人脸图片的方式不同。因为通常(ARWorldTrackingConfigurationARFaceTrackingConfigurationARKit 会尝试匹配真实世界的大小和虚拟对象的大小,即 3D 编辑软件中 10x10cm 的对象将匹配真实的相同 10x10cm 的世界对象。 但是当使用面部跟踪时,phone 检测到异常大小的面部(如上图所示的 4 厘米宽的小面部或面部大得多的人的海报),它将缩放 FaceGeometry 就像检测到的面部是正常大小的头部,即头部宽度的测量值约为 14 厘米。然后所有虚拟对象将相应地缩放,这将在现实世界中产生错误的大小。 C.f。下一张图片:

眼镜3D模型宽约14cm,但只显示为4cm的物体

相比之下,如果你把眼镜戴在真实的 3D 脸上,它们的尺寸是正确的,在小人头上(比如 12 厘米)它们会稍微偏大,在大人头上(比如 16 厘米) ) 它们会稍微太小(因为在这两种情况下它们都是真正的 14 厘米)。

我什至可以看到 ARKit 在以下之间切换:

  1. 仅使用相机图像进行平面人脸检测
  2. 使用 FaceID 原深感摄像头进行人脸检测。

当您在应用程序前抱着婴儿时,这一点尤为突出。 对于婴儿的头部,ARKit 将首先尝试按比例放大所有内容,以便婴儿的头部在虚拟场景中为 14 厘米宽,并且眼镜适合成人。 然后,通常在头部出现在相机中后1-2秒ARFaceTrackingConfiguration会从模式(1)切换到模式(2)并显示 3D 对象的真实大小,这会导致带有成人尺寸眼镜的小婴儿头部的超可爱图片(此处未显示,因为 SO 不用于共享婴儿图片)。

所以,现在的问题是:

有没有办法确定 ARKit 是处于 1 还是 2 模式?

目前无法在 ARKit 3.0 API 中执行此操作。

ARKit session's ARFaceTrackingConfiguration is constantly getting data from motion sensors at 1000 Hz, from front RGB camera at 60 Hz, and from IR camera at 15 Hz. And TrueDepth sensor is working while the session is running. You can't manually stop TrueDepth sensor in ARKit.

working distance in ARFaceTrackingConfiguration is approximately 15...100 cm, so you can effectively detect up to 3 faces in ARKit 3.0 within that distance.但是 ARKit 面部检测中存在一些逻辑错误——您可以在跟踪身后海报上的一张大脸的同时跟踪您的面部(但海报上的面部是平面的,因为它具有等距深度)。因此,规范蒙版的比例取决于检测到的面部大小(如您之前所说),但 ARKit 无法暂时调整该规范蒙版 (ARFaceGeometry) 的比例,因为面部跟踪非常 CPU 密集.

Apple 的 TrueDepth 模块的工作距离范围如此之窄,因为来自 IR 投影仪的 30K 点必须具有确定的亮度、模糊度、覆盖范围和点大小才能被 ARKit 有效使用。

使用此代码,您可以测试 TrueDepth 模块是否参与进程:

@available(iOS 13.0, *)
class ViewController: UIViewController {

    @IBOutlet var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()

        sceneView.session.delegate = self
    }
}

extension ViewController: ARSessionDelegate {

    func session(_ session: ARSession, didUpdate frame: ARFrame) {

        print(sceneView.session.currentFrame?.capturedDepthData?.depthDataQuality as Any)
    }
}

通常,每四帧打印一次深度数据(但有时间隙大于 4 帧):

只有一种情况原深感传感器对 RGB 数据没有贡献:当您将智能手机移到离海报太近或离您的脸太近时 – 所以您您只会看到 nils 被打印出来。