4、经典数据集详解:Cityscapes、KITTI、BDD100K,数据标注格式与特点
做语义分割,尤其是道路场景理解,数据集就是你的“弹药库”。
我见过不少新手,模型结构搭得挺漂亮,结果在数据集上翻了车——要么标注格式搞错,要么类别对不上,白白浪费几天时间。今天咱们就把三个最经典的数据集掰开揉碎了讲清楚。
4.1 Cityscapes:城市道路场景的“标杆”
Cityscapes 是我个人用得最多的数据集,没有之一。它专注于城市街道场景,覆盖了 50 个不同城市,包含 5000 张精细标注的图像和 20000 张粗略标注的图像。
核心特点:
- 分辨率高:图像尺寸为 2048×1024,细节非常丰富。我在做小目标检测(比如远处的交通灯)时,Cityscapes 的高分辨率帮了大忙。
- 类别精细:定义了 30 个类别,但通常只用其中的 19 个进行训练和评估。这 19 类涵盖了道路、车辆、行人、建筑等关键元素。
- 标注质量:每张图都经过人工精细标注,边缘贴合度极高。说白了,这是“教科书级”的标注。
避坑指南:Cityscapes 的标注是
trainId 和 id 两套体系。id 是原始类别编号(0~33),trainId 才是训练时用的(0~18,255 表示忽略区域)。我曾经直接拿 id 去训练,结果模型把“道路”和“人行道”搞混了,因为它们的 id 是连续的。
标注格式:
Cityscapes 使用 JSON 格式的标注文件,但语义分割任务通常直接使用 PNG 图像作为标签。每个像素的值就是类别 ID。
# Cityscapes 标签图像示例
# 像素值 0 表示道路,1 表示人行道,2 表示建筑...
# 注意:训练时通常使用 trainId,而不是 id
# 读取标签图像
import cv2
label = cv2.imread('gtFine_trainvaltest/leftImg8bit/train/aachen/aachen_000000_000019_gtFine_labelIds.png', cv2.IMREAD_GRAYSCALE)
print(np.unique(label)) # 输出: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 255]
我的习惯:写一个
cityscapes_utils.py 工具脚本,专门处理 id 到 trainId 的映射。这样不管数据集怎么变,我都能快速适配。
4.2 KITTI:自动驾驶的“老前辈”
KITTI 数据集诞生于 2012 年,由德国卡尔斯鲁厄理工学院和丰田美国研究院联合创建。它虽然年头久,但在道路场景理解领域依然是绕不开的基准。
核心特点:
- 多模态:包含双目图像、激光雷达点云、GPS/IMU 数据。如果你做多传感器融合,KITTI 是首选。
- 场景真实:数据采集于卡尔斯鲁厄市区、乡村和高速公路,包含晴天、阴天、傍晚等多种光照条件。
- 标注稀疏:语义分割标注只有 200 张训练图和 200 张测试图。嗯,数量确实少,但每张图的质量很高。
注意:KITTI 的语义分割标注只覆盖了 11 个类别(道路、人行道、汽车、行人、自行车等),而且没有“建筑”这个类别。如果你需要识别建筑物,Cityscapes 会更合适。
标注格式:
KITTI 使用 PNG 图像作为标签,但它的像素值编码方式与 Cityscapes 不同。KITTI 的标签图像是 彩色图像,每个像素的 RGB 值对应一个类别。
# KITTI 标签图像示例
# 颜色编码示例:
# (128, 64, 128) -> 道路
# (244, 35, 232) -> 人行道
# (0, 0, 142) -> 汽车
# 读取标签图像
label = cv2.imread('training/semantic_rgb/000000_10.png')
# 需要将 RGB 值映射到类别 ID
color_to_class = {
(128, 64, 128): 0, # 道路
(244, 35, 232): 1, # 人行道
(0, 0, 142): 2, # 汽车
# ... 其他类别
}
避坑指南:KITTI 的标签图像中,有些像素的 RGB 值不在预定义的颜色映射表中。这些像素通常属于“忽略区域”(比如远处的物体)。我在处理时,会把这些像素统一设为 255(忽略类别)。
4.3 BDD100K:大规模、多样化的“后起之秀”
BDD100K 是伯克利大学在 2018 年发布的数据集,包含 10 万张图像,覆盖了美国多个城市的不同天气、时间和场景。它最大的优势就是——大。
核心特点:
- 规模大:10 万张图像,其中 7 万张用于训练,1 万张用于验证,2 万张用于测试。相比 Cityscapes 的 5000 张,BDD100K 的规模是它的 20 倍。
- 多样性高:包含晴天、阴天、雨天、雪天、雾天,以及白天、夜晚、黄昏等多种条件。你想想看,一个模型如果在 BDD100K 上表现好,那它在真实场景中的泛化能力大概率不会差。
- 多任务标注:除了语义分割,还包含目标检测、车道线检测、实例分割、全景分割等标注。一个数据集搞定多个任务。
我的经验:BDD100K 的语义分割标注有 19 个类别,与 Cityscapes 的 19 类高度重合。所以,我经常先在 Cityscapes 上预训练模型,然后在 BDD100K 上微调。这样既能利用 Cityscapes 的高质量标注,又能享受 BDD100K 的大规模多样性。
标注格式:
BDD100K 使用 JSON 格式存储标注信息,但语义分割标签也提供了 PNG 图像格式。它的标签图像是灰度图,像素值直接对应类别 ID。
# BDD100K 标签图像示例
# 像素值 0 表示道路,1 表示人行道,2 表示建筑...
# 与 Cityscapes 的 trainId 几乎一致
# 读取标签图像
label = cv2.imread('bdd100k/labels/sem_seg/train/0000f77c-6257be58.png', cv2.IMREAD_GRAYSCALE)
print(np.unique(label)) # 输出: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 255]
注意:BDD100K 的 JSON 标注文件中,语义分割的标注是以
polygon(多边形)形式存储的。如果你需要从 JSON 生成 PNG 标签图像,需要自己写一个渲染函数。我个人建议直接下载官方提供的 PNG 标签文件,省时省力。
4.4 三个数据集的对比总结
| 特性 | Cityscapes | KITTI | BDD100K |
|---|---|---|---|
| 发布年份 | 2016 | 2012 | 2018 |
| 图像数量 | 5000(精细)+ 20000(粗略) | 400(语义分割) | 100000 |
| 图像分辨率 | 2048×1024 | 1242×375 | 1280×720 |
| 类别数 | 19(常用) | 11 | 19 |
| 标注格式 | PNG(灰度图,trainId) | PNG(彩色图,RGB映射) | PNG(灰度图,类别ID) |
| 场景多样性 | 中等(城市街道) | 低(德国城市) | 高(美国多城市、多天气) |
| 多模态支持 | 无 | 有(双目、激光雷达) | 无 |
我的建议:
- 如果你刚入门,从 Cityscapes 开始。标注质量高,社区资源丰富,踩坑少。
- 如果你做多传感器融合或目标跟踪,KITTI 是绕不开的。
- 如果你追求模型的泛化能力,BDD100K 的大规模多样性会让你受益匪浅。
好了,三个数据集的核心内容就这些。记住,数据集的选择取决于你的具体任务和资源。没有最好的数据集,只有最合适的。