平铺相机渲染#

备注

此功能仅在Isaac Sim 4.2.0及以上版本可用。

平铺渲染结合图像处理网络需要大量内存资源,尤其是在更大的分辨率下。我们建议在RTX 4090 GPUs或类似设备上在场景中运行512台摄像机。

平铺渲染API提供了一个矢量化接口,用于从摄像头传感器收集数据。这对需要视觉环节的强化学习环境非常有用。平铺渲染通过连接多个摄像头的相机输出并呈现为单个大图像,而不是由每个单独摄像头生成的多个较小图像。这减少了呈现所需的时间,并为处理视觉数据提供了更高效的API。

Isaac Lab 提供了用于 RGB、深度以及其他注释器的分块渲染 API,通过 TiledCamera 类。分块渲染 API 的配置可以通过 TiledCameraCfg 类来定义,指定诸如所有相机路径的正则表达式、相机的变换、所需的数据类型、要添加到场景中的相机类型以及相机分辨率等参数。

tiled_camera: TiledCameraCfg = TiledCameraCfg(
    prim_path="/World/envs/env_.*/Camera",
    offset=TiledCameraCfg.OffsetCfg(pos=(-7.0, 0.0, 3.0), rot=(0.9945, 0.0, 0.1045, 0.0), convention="world"),
    data_types=["rgb"],
    spawn=sim_utils.PinholeCameraCfg(
        focal_length=24.0, focus_distance=400.0, horizontal_aperture=20.955, clipping_range=(0.1, 20.0)
    ),
    width=80,
    height=80,
)

要访问平铺渲染接口,可以创建一个 TiledCamera 对象,并用于从摄像头获取数据。

tiled_camera = TiledCamera(cfg.tiled_camera)
data_type = "rgb"
data = tiled_camera.data.output[data_type]

返回的数据将转换为形状(num_cameras,height,width,num_channels),可以直接用作强化学习的观察数据。

在处理渲染时,请确保在启动环境时添加 --enable_cameras 参数。例如:

python source/standalone/workflows/rl_games/train.py --task=Isaac-Cartpole-RGB-Camera-Direct-v0 --headless --enable_cameras

注释器和数据类型#

TiledCameraCamera 类提供了从复制器中检索各种类型注释器数据的 API:

  • "rgb": 一个由 3 通道渲染的彩色图像。

  • "rgba": 一个由4个通道渲染的带有 Alpha 通道的彩色图像。

  • "distance_to_camera": 包含到相机光学中心的距离的图像。

  • "distance_to_image_plane": 包含 3D 点从相机平面沿相机Z轴的距离的图像。

  • "depth": 和 "distance_to_image_plane" 相同。

  • "normals": 包含每个像素处的局部表面法线向量的图像。

  • "motion_vectors": 包含每个像素的运动矢量数据的图像。

  • "semantic_segmentation": 语义分割数据。

  • "instance_segmentation_fast": 实例分割数据。

  • "instance_id_segmentation_fast": 实例 ID 分割数据。

RGB 和 RGBA#

rgb 数据类型返回一个类型为 torch.uint8 的3通道RGB彩色图像,尺寸为(B,H,W,3)。

rgba 数据类型返回一个类型为 torch.uint8 的4通道RGBA彩色图像,尺寸为(B,H,W,4)。

要将 torch.uint8 数据转换为 torch.float32 ,请将缓冲区除以255.0,以获得包含数据0到1的 torch.float32 缓冲区。

深度和距离#

distance_to_camera 返回一个单通道深度图像,显示到相机光学中心的距离。这个注释器的尺寸为(B,H,W,1),类型为 torch.float32

distance_to_image_plane 返回一个单通道深度图像,显示3D点从相机平面沿着相机的Z轴的距离。这个注释器的尺寸为(B,H,W,1),类型为 torch.float32

depth 提供了 distance_to_image_plane 的别名,并且会返回与 distance_to_image_plane 注释器相同的数据,尺寸为(B,H,W,1),类型为 torch.float32

法线#

normals 返回一个包含每个像素处的局部表面法线向量的图像。缓冲区的尺寸为(B,H,W,3),包含每个矢量的(x,y,z)信息,类型为 torch.float32

运动矢量#

motion_vectors 返回图像空间中每个像素的像素运动矢量,用包含相对于帧之间相机视口中像素的相对运动的运动矢量的二维数组表示。缓冲区的尺寸为(B,H,W,2),表示x-水平轴(图像宽度)上的运动距离,左侧图像的移动为正,右侧移动为负,y-垂直轴(图像高度)上的运动距离,图像顶部移动为正,向底部移动为负。数据类型为 torch.float32

语义分割#

semantic_segmentation 输出相机视口中具有语义标签的每个实体的语义分割。除了图像缓冲区外,还可以使用 tiled_camera.data.info['semantic_segmentation'] 检索到包含ID到标签信息的 info 字典。

  • 如果相机配置中 colorize_semantic_segmentation=True ,则会返回一个4通道RGBA图像,尺寸为(B,H,W,4),类型为 torch.uint8 。信息 idToLabels 字典将表示从颜色到语义标签的映射。

  • 如果 colorize_semantic_segmentation=False ,则会返回一个尺寸为(B,H,W,1)的类型为 torch.int32 的缓冲区,其中包含每个像素的语义ID。信息 idToLabels 字典将表示从语义ID到语义标签的映射。

实例ID分割#

instance_id_segmentation_fast 输出相机视口中每个实体的实例ID分割。每个prim在场景中具有不同路径的实例ID是唯一的。除了图像缓冲区外,还可以使用 tiled_camera.data.info['instance_id_segmentation_fast'] 检索到包含ID到标签信息的 info 字典。

instance_id_segmentation_fastinstance_segmentation_fast 之间的主要区别在于实例分割注释器会向下移动到具有语义标签的最低级别prim,而实例ID分割总会向下移动到叶prim。

  • 如果相机配置中 colorize_instance_id_segmentation=True ,则会返回一个4通道RGBA图像,尺寸为(B,H,W,4),类型为 torch.uint8 。信息 idToLabels 字典将表示从颜色到该实体的USD prim路径的映射。

  • 如果 colorize_instance_id_segmentation=False ,则会返回一个尺寸为(B,H,W,1)的类型为 torch.int32 的缓冲区,其中包含每个像素的实例ID。信息 idToLabels 字典将表示从实例ID到该实体的USD prim路径的映射。

实例分割#

instance_segmentation_fast 输出相机视口中每个实体的实例分割。与图像缓冲区一起,还可以检索到包含ID到标签和ID到语义信息的 info 字典。

  • 如果相机配置中 colorize_instance_segmentation=True ,则会返回一个4通道RGBA图像,尺寸为(B,H,W,4),类型为 torch.uint8 。信息 idToLabels 字典表示从颜色到该语义实体的USD prim路径的映射。信息 idToSemantics 字典表示从颜色到该语义实体的语义标签的映射。

  • 如果 colorize_instance_segmentation=False ,则会返回一个尺寸为(B,H,W,1)的类型为 torch.int32 的缓冲区,其中包含每个像素的实例ID。信息 idToLabels 字典表示从实例ID到该语义实体的USD prim路径的映射。信息 idToSemantics 字典表示从实例ID到该语义实体的语义标签的映射。

当前限制#

由于当前渲染器的限制,我们在场景中只能有 一个 TiledCamera 实例。对于需要多个相机的用例,我们可以通过在渲染调用之间移动相机的位置来模仿多相机行为。

例如,在立体视觉设置中,可以实现以下代码片段:

# render image from "first" camera
camera_data_1 = self._tiled_camera.data.output["rgb"].clone() / 255.0
# update camera transform to the "second" camera location
self._tiled_camera.set_world_poses(
    positions=pos,
    orientations=rot,
    convention="world"
)
# step the renderer
self.sim.render()
self._tiled_camera.update(0, force_recompute=True)
# render image from "second" camera
camera_data_2 = self._tiled_camera.data.output["rgb"].clone() / 255.0

请注意,这种方法仍然限制了所有相机的渲染分辨率必须相同。目前,使用 TiledCamera 实现不同分辨率图像没有解决方法。最佳方法是使用所有期望分辨率中最大的分辨率,并在渲染输出中添加额外的缩放或裁剪操作作为后处理步骤。

此外,在比较不同数量环境的渲染输出时,可能会有明显的质量差异。目前,任何组合分辨率的宽度小于 265 像素或高度小于 265 像素的情况下,将自动切换到 DLAA 抗锯齿模式,该模式在抗锯齿过程中不会进行上采样。对于宽度和高度均大于 265 像素的分辨率,我们默认使用 “性能” DLSS 模式进行抗锯齿,以获得性能上的好处。抗锯齿模式和其他渲染参数可以在 RenderCfg 中指定。