相机帧访问(实验性)

相机帧访问示例


警告!

相机帧访问功能被标记为实验性,因为它目前不完全支持所有公共 AR Foundation API,并且由于包和 Snapdragon Spaces 服务端的优化,版本之间的向后兼容性可能会受到影响。


这个示例演示了如何获取 RGB 相机帧和内部属性用于图像处理。有关相机帧访问的基本信息及 AR Foundation 的 AR Camera Manager 组件的功能,请参阅 Unity 文档。要使用此功能,需要在 OpenXR 插件设置中启用它,路径为:项目设置 > XR 插件管理 > OpenXR(> Android 标签)。

 

示例工作原理

将 AR Camera Manager 组件添加到 AR Session Origin > AR Camera 游戏对象中,将启用相机访问子系统。启动时,子系统会从设备中检索有效的传感器配置。如果找到有效的 Y'UV420sp 或 YUY2 传感器配置,子系统将选择该配置作为 CPU 相机图像的提供者。从概念上讲,AR Camera Manager 代表一个单一的相机,不能同时管理多个传感器。

 

示例场景包含两个面板:

● 一个相机视频面板,显示来自设备相机的最新 CPU 图像,并带有暂停和恢复按钮。

● 一个相机信息面板,列出设备相机的各种属性。

 

图片9.png

 

获取 CPU 图像

每当子系统获得新的相机帧时,AR Camera Manager 将触发 frameReceived 事件。订阅此事件可以让其他脚本尽早获取最新的相机帧并对其进行处理。一旦相机帧可用,Camera Manager 的 TryAcquireLatestCpuImage 函数将返回一个 XRCpuImage 对象,这个对象代表来自选定设备相机的单张原始图像。可以使用 XRCpuImage 的 Convert 函数提取该图像的原始像素数据,Convert 函数会返回一个 NativeArray<byte>。Snapdragon Spaces 不支持通过 XRCpuImage.ConvertAsync 进行异步图像转换。

 

 图片10.png

 

有关如何使用 frameReceived、TryAcquireLatestCpuImage 和 XRCpuImage 的详细信息,请参阅 Unity 文档

 

警告!

根据所使用的设备,相机帧访问可能需要几秒钟才能初始化。在子系统成功初始化之前,请不要尝试访问帧。强烈建议使用 AR Foundation API 的 frameReceived 事件,以避免出现错误。


以下示例代码在触发 frameReceived 事件时,从 AR Camera Manager 请求 CPU 图像。如果成功,它将直接将 XRCpuImage 的原始像素数据提取到托管的 Texture2D 的 GetRawTextureData<byte> 缓冲区中,并使用 Apply 方法应用纹理缓冲区。最后,它会更新目标 RawImage 中的纹理,使新帧在应用程序的 UI 中可见。

 

图片11.png

 

以下是 AR Camera Manager 支持的纹理格式:

● RGB24

● RGBA32

● BGRA32

 

检索 YUV 平面数据

Snapdragon Spaces 目前支持 Y′UV420sp 和 YUY2 格式。Y′UV420sp 包含一个 Y 缓冲区,后跟交错的 2x2 子采样 U/V 缓冲区。YUY2 包含一个单一的缓冲区,其中交错了 Y 和 U/V 样本,每个样本以 Y-U-Y-V 的形式表示,代表两个水平像素的色度信息,没有垂直子采样。有关 YUV 颜色模型的详细信息,请参阅 YCbCr 维基百科文章中的 YUV 部分。

 

如果不需要 RGB 转换,可以通过 XRCpuImage 的 GetPlane 方法检索原始 YUV 平面数据。此方法返回一个 XRCpuImage.Plane 对象,可以从中读取平面数据。通过 XRCpuImage.planeCount 可以区分格式,该属性指示表示帧的平面数量。

 

Y'UV420sp

 

● Y 平面数据的索引为 0,可以通过 GetPlane(0) 访问。

● UV 平面数据的索引为 1,可以通过 GetPlane(1) 访问。


YUY2

YUYV 平面数据的索引为 0,可以通过 GetPlane(0) 访问。

 

图片12.png

 

有关 XRCpuImage.GetPlane 的详细信息,请参阅 Unity 文档

 

有关 XRCpuImage.Plane 的详细信息,请参阅 Unity 文档。


以下示例代码在 frameReceived 事件触发时请求来自 AR Camera Manager 的 CPU 图像,如果成功,它会获取 XRCpuImage 的原始平面数据,并根据 YUV 格式应用不同的图像处理算法。

 

图片13.png

 

检索传感器/内部信息

摄像头管理器的 TryGetIntrinsics 函数将返回一个 XRCameraIntrinsics 对象,该对象描述了所选传感器的物理特性。有关 XRCameraIntrinsics 的详细信息,请参阅 Unity 文档。(https://docs.unity3d.com/Packages/com.unity.xr.arsubsystems@4.2/api/UnityEngine.XR.ARSubsystems.XRCameraIntrinsics.html)

以下示例代码检索所选传感器的内参,并在应用程序 UI 中显示这些信息。

 

图片14.png


检索传感器/外部参数

AR Foundation API 不提供传感器的外参,不过,您可以使用以下两种方法来获取传感器的外参:

 

方法 1:Snapdragon Spaces 输入绑定

Snapdragon Spaces 提供了 ColorCameraPosition 和 ColorCameraRotation 的输入动作。您可以将这些输入动作与 Tracked Pose Driver (Input System) 配合使用,通过将它们绑定到 Position Input 和 Rotation Input 上。将 Tracked Pose Driver (Input System) 组件添加到一个 GameObject 上,该 GameObject 的位姿将与彩色摄像头的外参位姿匹配。

 

 图片15.png

 

下图展示了如何使用这些输入绑定。

 

图片16.png


方法二:Snapdragon Spaces 相机姿态提供器

Space相机姿态提供器组件添加到场景中,并使用 GetPoseFromProvider 函数来获取与 AR 相机管理器最新的 frameReceived 事件相关的相机姿态。这个姿态是相对于 AR 会话坐标系统的。

 

下面的示例代码演示了如何获取所选传感器的外参并在应用程序的 UI 中显示。

 

图片17.png


Spaces Camera Pose Provider还可以用作Tracked Pose Driver的姿势提供程序。

 

提升性能的提示:

相机访问操作可能会消耗较多计算资源,无论是由于图像分辨率较大还是算法的复杂性。

● 使用 XRCpuImage.Convert 转换图像时,提供较小的 outputDimensions 以减少计算量。

● 使用 XRCpuImage.GetPlane 处理图像时,可以考虑对数据缓冲区进行下采样。

 

Snapdragon Spaces 提供了直接内存访问转换设置,这改变了 XRCpuImage.Convert 读取和写入数据的方式。默认情况下,Snapdragon Spaces 使用 Marshal.Copy 进行帧数据的移动。启用此设置后,Spaces 将使用 NativeArray<byte> 直接表示源和目标缓冲区。可以在 Project Settings > XR Plug-in Management > OpenXR (> Android Tab) > Snapdragon Spaces > Camera Frame Access (Experimental) > Direct Memory Access Conversion 中找到这个设置。启用此设置可能会在某些设备上提高性能,但在其他架构上的表现可能会有所下降。以下是建议启用直接内存访问转换设置的设备表:


设备

建议

Lenovo ThinkReality A3

性能提升,推荐使用

Lenovo ThinkReality VRX

性能不足,不推荐使用

 

Spaces AR C相机管理器配置和 DownsamplingStride 属性在版本 0.21.0 中已被弃用。请改用 XRCpuImage.ConversionParams 设置较小的 outputDimensions,或者使用 XRCpuImage.GetPlane 并设置自定义下采样因子。

 

检索其他的传感器数据

Spaces AR Camera Manager Config 可以通过 GetActiveCameraCount 方法获取设备中的相机传感器数量。这些信息对于区分双镜头设备和 VR 设备,以及正确处理相机图像可能非常重要。