Raw Depth API 为相机图像提供深度数据,其准确性比完整 Depth API 数据高,但不一定能覆盖每个像素。原始深度图像及其匹配的置信度图像也可以进一步处理,让应用仅使用准确度足够高的深度数据来满足具体用例的要求。
设备兼容性
原始深度数据可在所有支持 Depth API 的设备上使用。与完整的 Depth API 一样,原始 Depth API 不需要受支持的硬件深度传感器,例如飞行时间 (ToF) 传感器。不过,Raw Depth API 和完整 Depth API 均可利用设备可能具备的任何受支持硬件传感器。
原始深度 API 与完整深度 API
Raw Depth API 提供准确度更高的深度估计值,但原始深度图像可能不包含相机图像中所有像素的深度估计值。相比之下,Full Depth API 为每个像素提供估算的深度,但由于深度估算值的平滑和插值,每像素的深度数据可能不太准确。两个 API 中的深度图像格式和大小相同。只有内容不同。
下表使用厨房中的椅子和桌子的图片说明了 Raw Depth API 与完整 Depth API 之间的区别。
API | 返回 | 相机图像 | 深度图片 | 置信度图片 |
---|---|---|---|---|
原始深度 API |
|
|||
全深度 API |
|
不适用 |
置信度图片
在 Raw Depth API 返回的置信度图像中,颜色较浅的像素具有较高的置信度值,白色像素表示完整的置信度,黑色像素表示没有置信度。一般来说,相机图像中纹理多的区域(例如树木)要比纹理不多的区域(例如空白墙)具有更高的原始深度置信度。没有纹理的表面产生的置信度通常为零。
如果目标设备具有受支持的硬件深度传感器,那么图片中距离相机足够近的区域的置信度可能会提高,即使在无纹理的表面上也是如此。
计算费用
Raw Depth API 的计算费用大约是完整 Depth API 计算费用的一半。
使用场景
借助原始深度 API,您可以获取深度图像,从而更详细地呈现场景中对象的几何图形。在打造 AR 体验时,原始深度数据非常有用,在这些体验中,几何图形理解任务需要更高的深度准确性和细节。一些用例包括:
- 3D 重建
- 效果衡量
- 形状检测
前提条件
确保您了解 AR 基础概念 以及如何在继续之前配置 ARCore 现场录像。
启用景深数据
在新的 ARCore 会话中,检查用户的设备是否支持深度。由于处理能力限制,并非所有与 ARCore 兼容的设备都支持 Depth API。为节省资源,ARCore 默认停用深度。启用深度模式,让应用使用 Depth API。
Java
Config config = session.getConfig(); // Check whether the user's device supports Depth. if (session.isDepthModeSupported(Config.DepthMode.AUTOMATIC)) { // Enable depth mode. config.setDepthMode(Config.DepthMode.AUTOMATIC); } session.configure(config);
Kotlin
if (session.isDepthModeSupported(Config.DepthMode.AUTOMATIC)) { session.configure(session.config.apply { depthMode = Config.DepthMode.AUTOMATIC }) }
获取最新的原始深度和置信度图像
调用 frame.acquireRawDepthImage16Bits()
以获取最新的原始深度图像。并非所有通过 Raw Depth API 返回的图像像素都包含深度数据,也并非每个 ARCore 帧都会包含新的原始深度图像。如需确定当前帧的原始深度图像是否为新的,请将其时间戳与上一原始深度图像的时间戳进行比较。如果时间戳不同,则原始深度图像基于新的深度数据。否则,深度图像是先前深度数据的重新投影。
调用 frame.acquireRawDepthConfidenceImage()
以获取置信度图片。您可以使用置信度图像来检查每个原始深度像素的准确率。置信度图片以 Y8 格式返回。每个像素都是一个 8 位无符号整数。0
表示置信度最低,而 255
表示置信度最高。
Java
// Use try-with-resources, so that images are released automatically. try ( // Depth image is in uint16, at GPU aspect ratio, in native orientation. Image rawDepth = frame.acquireRawDepthImage16Bits(); // Confidence image is in uint8, matching the depth image size. Image rawDepthConfidence = frame.acquireRawDepthConfidenceImage(); ) { // Compare timestamps to determine whether depth is is based on new // depth data, or is a reprojection based on device movement. boolean thisFrameHasNewDepthData = frame.getTimestamp() == rawDepth.getTimestamp(); if (thisFrameHasNewDepthData) { ByteBuffer depthData = rawDepth.getPlanes()[0].getBuffer(); ByteBuffer confidenceData = rawDepthConfidence.getPlanes()[0].getBuffer(); int width = rawDepth.getWidth(); int height = rawDepth.getHeight(); someReconstructionPipeline.integrateNewImage(depthData, confidenceData, width, height); } } catch (NotYetAvailableException e) { // Depth image is not (yet) available. }
Kotlin
try { // Depth image is in uint16, at GPU aspect ratio, in native orientation. frame.acquireRawDepthImage16Bits().use { rawDepth -> // Confidence image is in uint8, matching the depth image size. frame.acquireRawDepthConfidenceImage().use { rawDepthConfidence -> // Compare timestamps to determine whether depth is is based on new // depth data, or is a reprojection based on device movement. val thisFrameHasNewDepthData = frame.timestamp == rawDepth.timestamp if (thisFrameHasNewDepthData) { val depthData = rawDepth.planes[0].buffer val confidenceData = rawDepthConfidence.planes[0].buffer val width = rawDepth.width val height = rawDepth.height someReconstructionPipeline.integrateNewImage( depthData, confidenceData, width = width, height = height ) } } } } catch (e: NotYetAvailableException) { // Depth image is not (yet) available. }
后续步骤
- 学习原始深度 Codelab,了解如何使用原始深度构建自己的应用。