如何改进 ARKit 3.0 中的 People Occlusion

How to improve People Occlusion in ARKit 3.0

我们正在开发一个使用 ARKit 中人物遮挡的演示应用程序。因为我们想在最终场景中添加视频,所以我们使用 SCNPlanes 渲染视频,使用 SCNBillboardConstraint 确保它们面向正确的方向。这些视频也是部分透明的,在我们应用的 SCNMaterial 上使用自定义着色器(因此一次播放 2 个视频)。

现在我们遇到了一些人的遮挡非常不稳定的问题(见图)。我们用来测试的视频是一个穿着深色裤子和裙子的女人(如果你想知道图像中的黑色是什么的话)。

我们遇到的问题是遮挡并不总是与人对齐(如图所示),并且某人的头发并不总是被正确检测到。

现在我们的问题是导致这些问题的原因是什么?我们如何改进问题,直到它们看起来像 this?我们目前正在探索问题是否是因为我们使用的是飞机,但仅使用 SCNBox 并不能解决问题。

更新时间:2021 年 7 月 4 日

由于新的 Depth API,您可以提高 ARKit 5.0/4.0/3.5 中 People OcclusionObject Occlusion 功能的质量 和可以 60 fps 捕获的更高质量的 ZDepth 通道。但是,为此您需要 iPhone 12 Pro 或 iPad Pro 和 LiDAR 扫描仪。

但在 ARKit 3.0 中,除非使用 Metal 或 MetalKit,否则无法改进 People Occlusion 功能。但是使用 Metal-family 框架在 ARKit 3.0 中改进 People Occlusion 并不容易,相信我。

提示:考虑RealityKitAR QuickLook 框架也支持 People Occlusion


为什么使用 People Occlusion 时会出现此问题

这是由于第五频道的性质——ZDepth频道。我们都知道渲染的 3D 场景最终图像可以包含 5 个用于数字合成的主要通道 – Red, GreenBlueAlphaZDepth .

当然,还有其他有用的渲染通道(也称为 AOV)用于合成:NormalsMotionVectors , PointPosition, UVs, Disparity,等等。但是这里我们只对两个主要的渲染集感兴趣——RGBAZDepth .


ZDepth 通道在 ARKit 3.0 中存在三个严重缺陷。

Problem 1. Aliasing and Anti-aliasing of ZDepth.

在任何 High-End 软件(如 Nuke、Fusion、Maya 或 Houdini)中渲染 ZDepth 通道,默认情况下会导致 锯齿状边缘 或所谓的别名边。游戏引擎也不例外——SceneKit、RealityKit、Unity、Unreal 或 Stingray 也有这个问题。

当然,你可以说在渲染之前我们必须打开一个叫做Anti-aliasing的功能。而且,是的,它几乎适用于所有通道,但不适用于 ZDepth。 ZDepth 的问题是——如果 anti-aliased,每个前景 object(尤其是透明的)的边界像素都“过渡”到背景 object。也就是说,FG和BG的像素在FG的边缘object.

处混合

坦率地说,有一个解决深度问题的有效解决方案——您应该使用 Deep channel 而不是 ZDepth channel。但是没有一个游戏引擎支持它,因为 Deep channel 非常大。所以深度通道合成既不适用于游戏引擎,也不适用于 ARKit。唉!


Problem 2. Resolution of ZDepth.

常规 ZDepth 通道必须以 32 位 呈现,即使 RGBAlpha 通道均为 8 位 。 32 位文件的颜色位深度对 CPU 和 GPU 来说是一个沉重的负担。并记住在 ARKit 视口中合成多个层——这里是前景角色在 3D 模型和背景角色上的合成。你不觉得这对你的设备来说太过分了吗,即使这些合成在 viewport resolution 而不是真正的屏幕 rez?然而,在 ZDepth 通道中渲染 16 位 8 位 compresses 深度真实场景,降低合成质量。

为了减轻 CPU 和 GPU 的负担并节省电池寿命,Apple 工程师决定在捕获阶段使用 scaled-down ZDepth 图像,然后 scale-up 渲染 ZDepth 图像使用 Alpha 通道(a.k.a. 分段)达到视口分辨率和 Stencil,然后使用 Dilate 合成操作修复 ZDepth 通道的边缘.因此,这导致我们发现了我们可以在您的图片上看到的令人讨厌的人工制品(某种“踪迹”)。

请查看 Presentation Slides pdf of Bringing People into AR here


Problem 3. Frame rate of ZDepth.

第三个问题源于 ARKit 以 60 fps 的速度工作。仅降低 ZDepth 图像分辨率并不能完全解决问题。因此,Apple 工程师的下一个合乎逻辑的步骤是 – 在 ARKit 3.0 中将 ZDepth 的帧速率降低到 15 fps。然而,最新版本的 ARKit 5.0 以 60 fps 捕获 ZDepth 通道,这大大提高了 People Occlusion 和 Objects Occlusion 的质量。但在 ARKit 3.0 中,这也带来了瑕疵(ZDepth 通道的某种“掉帧”导致“拖尾”效果)。

当您使用类型 属性:

时,您无法更改最终合成图像的质量
static var personSegmentationWithDepth: ARConfiguration.FrameSemantics { get }

因为它是一个可获取的属性并且在 ARKit 3.0 中没有 ZDepth 质量设置。

当然,如果您想在 ARKit 3.0 中增加 ZDepth 通道的帧速率,您应该实施数字合成中的 帧插值技术(其中 in-between 帧是 computer-generated 个):

但是这帧插值tchnique 不仅 CPU 密集而且非常耗时,因为我们需要每秒生成 45 个额外的 32 位 ZDepth-frames(45 个插值 + 15 个实际 = 60 帧每秒)。

我相信有人可能会通过使用 Metal 开发代码来改进 ARKit 3.0 中的 ZDepth 合成功能,但现在这是一个真正的挑战!

You must look at sample code of People Occlusion in Custom Renderers app here.


ARKit 5.0 和 LiDAR 扫描仪支持

ARKit 5.0、ARKit 4.0 和 ARKit 3.5 支持 LiDAR(Light Detection And Ranging 扫描仪)。 LiDAR 扫描仪提高了人员遮挡功能的质量和速度,因为 ZDepth 通道的质量更高,即使您在跟踪周围环境时身体没有移动也是如此。 LiDAR 系统还可以帮助您绘制墙壁、天花板、地板和家具的地图,以快速获得 real-world 表面的虚拟网格,以便与之动态交互,或者简单地在其上定位 3d objects(甚至部分遮挡的 3d objects)。具有 LiDAR 扫描仪的小工具可以实现无与伦比的精度检索 real-world 表面的位置。通过考虑网格,ray-casts 可以与非平面表面或具有 no-features-at-all 的表面相交,例如白墙或 barely-lit 墙。

要激活 sceneReconstruction 选项,请使用以下代码:

let arView = ARView(frame: .zero)
    
arView.automaticallyConfigureSession = false

let config = ARWorldTrackingConfiguration()

config.sceneReconstruction = .meshWithClassification

arView.debugOptions.insert([.showSceneUnderstanding, .showAnchorGeometry])

arView.environment.sceneUnderstanding.options.insert([.occlusion,
                                                      .collision,
                                                      .physics])
arView.session.run(config)

但在您的代码中使用 sceneReconstruction 实例 属性 之前,您需要检查设备是否有 LiDAR 扫描仪。您可以在 AppDelegate.swift 文件中完成:

import ARKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, 
                       didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        guard ARWorldTrackingConfiguration.supportsSceneReconstruction(.meshWithClassification) 
        else {
            fatalError("Scene reconstruction requires a device with a LiDAR Scanner.")
        }            
        return true
    }
}


RealityKit 2.0

在 iPhone 12 Pro 或 iPad Pro 上使用 RealityKit 2.0 应用程序时,您有多个遮挡选项 - ARKit 5.0 中提供相同的选项 - 改进 People OcclusionObject Occlusion(例如家具或墙壁)和Face Occlusion。要在 RealityKit 2.0 中打开遮挡,请使用以下代码:

arView.environment.sceneUnderstanding.options.insert(.occlusion)