更新日期:2021 年 7 月 4 日。
借助新的 Depth API 和更高质量的 ZDepth 通道,您可以提高 ARKit 5.0/4.0/3.5 中 People Occlusion 和 Object Occlusion 功能的质量可以以 60 fps 的速度拍摄。但是,为此您需要配备激光雷达扫描仪的 iPhone 12 Pro 或 iPad Pro。
但在 ARKit 3.0 中,您无法改进 People Occlusion 功能,除非您使用 Metal 或 MetalKit。然而,使用 Metal 系列框架在 ARKit 3.0 中改进 People Occlusion 并不容易,相信我。
提示:请考虑 RealityKit 和 AR QuickLook 框架也支持 People Occlusion。
为什么在使用 People Occlusion 时会出现此问题?
这是由于第五频道的性质 - ZDepth 频道。我们都知道,渲染后的 3D 场景最终图像可以包含 5 个用于数字合成的主要通道——Red、Green、Blue strong>、Alpha 和 ZDepth。
当然,还有其他有用的渲染通道(也称为 AOV)可用于合成:Normals、MotionVectors、PointPosition 、UVs、Disparity等。但这里我们只对两个主要的渲染集感兴趣——RGBA strong> 和 ZDepth。
ZDepth 通道在 ARKit 3.0 中存在三个严重缺陷。
问题1. ZDepth的锯齿和抗锯齿。
在任何高端软件(如 Nuke、Fusion、Maya 或 Houdini)中渲染 ZDepth 通道,默认情况下会导致锯齿状边缘或所谓的锯齿状边缘。游戏引擎也不例外——SceneKit、RealityKit、Unity、Unreal 或 Stingray 也有这个问题。
当然,您可以说,在渲染之前我们必须打开一个名为Anti-aliasing 的功能。而且,是的,它几乎适用于所有通道,但不适用于 ZDepth。 ZDepth 的问题是——如果anti-aliased,每个前景对象(特别是如果它是透明的)的边界像素被“转换”为背景对象。换句话说,FG和BG的像素混合在FG对象的边缘。
坦率地说,有一个解决深度问题的有效解决方案 - 您应该使用 Deep channel 而不是 ZDepth channel。但是没有一个游戏引擎支持它,因为 Deep channel 非常庞大。所以深度通道合成既不适用于游戏引擎,也不适用于 ARKit。唉!
问题2。ZDepth的分辨率。
常规 ZDepth 通道必须以 32 位 呈现,即使 RGB 和 Alpha 通道都是仅限 8 位。 32 位文件的颜色位深度对 CPU 和 GPU 来说是一个沉重的负担。记住在 ARKit 视口中合成多个图层——这里是前景字符在 3D 模型和背景字符上的合成。你不觉得这对你的设备来说太多了吗,即使这些合成在viewport resolution而不是真正的屏幕rez?但是,以 16-bit 或 8-bit compresses 真实场景的深度渲染 ZDepth 通道,会降低合成质量。
为了减轻 CPU 和 GPU 的负担并延长电池寿命,Apple 工程师决定在捕获阶段使用缩小的 ZDepth 图像,然后将渲染的 ZDepth 图像放大到视口分辨率和 Stencil 它使用 Alpha 通道(也称为分段),然后使用 Dilate 合成操作修复 ZDepth 通道的边缘。因此,这导致了我们可以在您的照片中看到的令人讨厌的人工制品(某种“线索”)。
请看Bringing People into ARhere的Presentation Slides pdf。
问题3.ZDepth的帧率。
第三个问题源于 ARKit 以 60 fps 的速度工作。仅降低 ZDepth 图像分辨率并不能完全解决问题。因此,Apple 工程师的下一个合乎逻辑的步骤是 – 在 ARKit 3.0 中将 ZDepth 的帧速率降低到 15 fps。然而,最新版本的 ARKit 5.0 以 60 fps 的速度捕获 ZDepth 通道,这大大提高了人物遮挡和物体遮挡的质量。但在 ARKit 3.0 中,这也带来了伪影(ZDepth 通道的某种“丢帧”会导致“轨迹”效果)。
当您使用类型属性时,您无法更改最终合成图像的质量:
static var personSegmentationWithDepth: ARConfiguration.FrameSemantics { get }
因为它是一个可获取的属性,并且在 ARKit 3.0 中没有 ZDepth 质量设置。
当然,如果你想在 ARKit 3.0 中增加 ZDepth 通道的帧速率,你应该实现在数字合成中发现的 帧插值技术(中间帧是计算机生成的)那些):
但是这种帧插值技术不仅占用大量 CPU,而且非常耗时,因为我们需要每秒生成 45 个额外的 32 位 ZDepth 帧(45 个插值 + 15 个实际 = 60 帧每秒)。
我相信有人可能会通过使用 Metal 开发代码来改进 ARKit 3.0 中的 ZDepth 合成功能,但现在这是一个真正的挑战!
您必须查看People Occlusion in Custom Renderers应用程序here的示例代码。
ARKit 5.0 和 LiDAR 扫描仪支持
在 ARKit 5.0、ARKit 4.0 和 ARKit 3.5 中,支持 LiDAR(Light Detection And Ranging 扫描仪)。 LiDAR 扫描仪提高了人物遮挡功能的质量和速度,因为 ZDepth 通道的质量更高,即使您在跟踪周围环境时没有物理移动。 LiDAR 系统还可以帮助您绘制墙壁、天花板、地板和家具的地图,以快速获得真实世界表面的虚拟网格,以便与之动态交互,或者简单地在其上定位 3d 对象(甚至是部分遮挡的 3d 对象)。具有 LiDAR 扫描仪的小工具可以实现无与伦比的精度,以检索真实世界表面的位置。通过考虑网格,光线投射可以与非平面表面或完全没有特征的表面相交,例如白墙或光线不足的墙。
要激活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 实例属性之前,您需要检查设备是否具有激光雷达扫描仪。您可以在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 Occlusion, Object Occlusion(例如家具或墙壁)和Face Occlusion。要在 RealityKit 2.0 中打开遮挡,请使用以下代码:
arView.environment.sceneUnderstanding.options.insert(.occlusion)