4、传感器入门:传感器类型概览、RGB相机、深度相机、语义分割相机

做自动驾驶仿真,传感器就是你的「眼睛」。没有传感器,车就是瞎子。CARLA 里内置了好几种传感器,今天咱们就把最常用的三种相机摸透:RGB 相机、深度相机、语义分割相机。

我个人习惯,刚开始学的时候,先别急着调参。先搞清楚每个传感器「看到了什么」,再想「怎么用」。你想想看,连数据长啥样都不知道,调参数不是瞎蒙吗?

4.1 传感器类型概览

CARLA 的传感器系统,说白了就是一个「挂载」机制。你把传感器绑在车上,它就开始往外吐数据。常见的传感器有这些:

传感器类型 输出数据 典型用途
RGB 相机 彩色图像 (H×W×3) 视觉感知、目标检测
深度相机 深度图 (H×W×1) 距离估计、避障
语义分割相机 标签图 (H×W×1) 场景理解、车道线识别
LIDAR 点云 (N×3) 3D 感知、建图
雷达 目标列表 速度测量、远距检测

嗯,这里要注意:每种传感器都有自己的「蓝图 ID」,创建的时候别搞混了。我在项目中遇到过有人把深度相机的蓝图写成了 RGB 的,结果跑了一下午才发现数据不对——全是彩色图,根本没有深度信息。

4.2 RGB 相机——最直观的「眼睛」

RGB 相机就是咱们平时用的摄像头。它输出的是三通道彩色图像,每个像素有 R、G、B 三个值。说白了,你看到的是什么颜色,它就输出什么颜色。

创建 RGB 相机的代码很简单:

# 创建 RGB 相机蓝图
blueprint = world.get_blueprint_library().find('sensor.camera.rgb')
# 设置图像分辨率
blueprint.set_attribute('image_size_x', '800')
blueprint.set_attribute('image_size_y', '600')
# 设置视野角度
blueprint.set_attribute('fov', '90')
# 设置感光度(影响亮度)
blueprint.set_attribute('sensor_tick', '0.1')  # 每 0.1 秒采集一帧

挂载到车上之后,你需要写一个回调函数来接收数据:

def process_rgb_image(image):
    # 将原始数据转为 numpy 数组
    array = np.frombuffer(image.raw_data, dtype=np.uint8)
    array = array.reshape((image.height, image.width, 4))  # 注意:CARLA 返回的是 RGBA
    # 去掉 Alpha 通道,只保留 RGB
    rgb_array = array[:, :, :3]
    # 显示或保存
    cv2.imshow('RGB Camera', rgb_array)
    cv2.waitKey(1)
小技巧:CARLA 返回的图像数据是 RGBA 格式(多了一个 Alpha 通道),记得用 [:, :, :3] 切掉。我第一次用的时候没注意,直接显示出来颜色全乱了,排查了半天才发现是通道顺序的问题。

4.3 深度相机——给图像加上「距离」

深度相机输出的不是彩色图,而是一张灰度图。每个像素的值代表该点到相机的距离。越近越亮,越远越暗。

创建深度相机:

blueprint = world.get_blueprint_library().find('sensor.camera.depth')
blueprint.set_attribute('image_size_x', '800')
blueprint.set_attribute('image_size_y', '600')
blueprint.set_attribute('fov', '90')

深度数据的处理方式有点不一样。CARLA 把深度值编码到了 RGB 三个通道里,需要解码才能得到真实的距离:

def process_depth_image(image):
    # 将深度数据转为 numpy
    array = np.frombuffer(image.raw_data, dtype=np.uint8)
    array = array.reshape((image.height, image.width, 4))
    
    # 解码深度值(CARLA 的深度编码方式)
    depth = array[:, :, 2] + array[:, :, 1] * 256 + array[:, :, 0] * 256 * 256
    depth = depth / (256 * 256 * 256 - 1)  # 归一化到 [0, 1]
    depth = depth * 1000  # 转换为米(最大 1000 米)
    
    # 显示深度图
    cv2.imshow('Depth Camera', depth / 100)  # 除以 100 让图像可见
    cv2.waitKey(1)
避坑指南:我曾经在项目里直接用 image.save_to_disk() 保存深度图,结果发现保存出来的图片全是黑的。后来才明白,深度值需要做归一化处理才能正常显示。直接用原始数据保存,值域太大,显示出来就是一片黑。

为什么会这样?因为深度值的范围是 0~1000 米,而图像像素值只有 0~255。不压缩的话,大部分像素都落在 255 以上,自然就全白了或者全黑了。

4.4 语义分割相机——让车「看懂」场景

语义分割相机是我个人觉得最酷的传感器。它输出的图像里,每个像素不是颜色,而是一个标签编号。比如:

  • 0 = 未标记
  • 1 = 道路
  • 2 = 人行道
  • 3 = 建筑
  • 4 = 车辆
  • 5 = 行人
  • ... 等等

创建语义分割相机:

blueprint = world.get_blueprint_library().find('sensor.camera.semantic_segmentation')
blueprint.set_attribute('image_size_x', '800')
blueprint.set_attribute('image_size_y', '600')
blueprint.set_attribute('fov', '90')

处理语义分割数据时,CARLA 同样用了编码技巧。每个像素的标签值被编码到了 RGB 通道里:

def process_semantic_image(image):
    # 转为 numpy
    array = np.frombuffer(image.raw_data, dtype=np.uint8)
    array = array.reshape((image.height, image.width, 4))
    
    # 解码标签(和深度解码类似)
    semantic = array[:, :, 2] + array[:, :, 1] * 256 + array[:, :, 0] * 256 * 256
    semantic = semantic.astype(np.uint8)  # 只取低 8 位,就是标签值
    
    # 显示(需要映射为彩色才能看)
    # CARLA 提供了内置的调色板
    colored = image.colorize()  # 直接调用这个方法就能得到彩色标签图
    colored.save_to_disk('semantic_output.png')
重点:语义分割相机返回的原始数据是编码后的标签值,直接用肉眼看是灰蒙蒙的。调用 image.colorize() 方法,CARLA 会自动用预定义的调色板给每个标签上色,这样你就能看到彩色的语义分割图了。

嗯,这里有个坑:语义分割的标签值范围是 0~255,但 CARLA 内部用了 24 位编码。如果你直接取 array[:, :, 0] 作为标签,得到的是错误的。一定要用上面那个解码公式,或者直接用 image.colorize() 省事。

4.5 三种相机的对比与选择

三种相机各有各的用处。我一般这样选:

  • RGB 相机:做目标检测、车道线识别、交通标志识别。说白了,就是模仿人眼看到的画面。
  • 深度相机:做避障、距离估计、3D 重建。你想想看,如果车不知道前面障碍物有多远,怎么刹车?
  • 语义分割相机:做场景理解、可行驶区域检测。它告诉车「哪里是路,哪里是墙,哪里是人」。

在实际项目中,我经常把 RGB 和语义分割结合起来用。RGB 提供纹理信息,语义分割提供类别信息,两者互补。比如检测行人时,RGB 能看清人的样子,语义分割能精确知道人的轮廓边界。

个人经验:刚开始学的时候,建议三种相机各挂一个,同时显示三个画面。这样你能直观地看到同一个场景下,三种传感器「看到」的东西有什么不同。我当年就是这么干的,看了半小时就彻底理解了。

4.6 本章知识体系

下面这张图帮你理清三种相机的核心逻辑:

CARLA 三种相机传感器对比 传感器类型 RGB 相机 深度相机 语义分割相机 输出:彩色图像 H×W×3 (RGB) 输出:深度图 H×W×1 (距离) 输出:标签图 H×W×1 (类别) 目标检测 / 车道线识别 避障 / 距离估计 场景理解 / 可行驶区域 注意:三种传感器都需要挂载到车上,并注册回调函数接收数据 深度和语义数据需要解码后才能正确显示

三种传感器,三种「看世界」的方式。RGB 看颜色,深度看距离,语义看类别。把它们组合起来,你的自动驾驶车就有了「火眼金睛」。

好了,这一章就到这里。记住:多动手,多观察。把三种相机都跑一遍,看看同一个场景下它们输出的数据长什么样。实践出真知,这话一点不假。

可可精品资料库