ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Cityscapes 数据集全解析:从下载到标注,语义分割与自动驾驶视觉的实战指南

Cityscapes 数据集全解析:从下载到标注,语义分割与自动驾驶视觉的实战指南 简介Cityscapes 数据集的 gtFine 子集标注文件是面向城市街景语义分割任务的核心数据资源。这套压缩包内含 2000 个 JSON 文件整体约 730MB每个文件保存一张高分辨率街景图像的精细多边形标注覆盖道路、建筑、行人、车辆等 30 个类别可供研究者直接用于训练 FCN、U-Net、DeepLab 等分割网络或结合原始 RGB 图进行数据增强与预处理。由于标注精度达到像素级、且来自多个欧洲城市的不同天气与时段它在自动驾驶、智能交通等场景中具有很强的实用价值能够有效验证模型在真实复杂城市环境下的泛化能力。已有 2130 人学习/下载适合计算机视觉、深度学习领域的学生与工程师使用可省去大量人工标注成本专注开展模型设计与调优。配合其他分卷还可构建完整训练流程支撑城市级场景理解与无人驾驶技术研究。 做语义分割和自动驾驶视觉这块的人几乎绕不开 Cityscapes 这个数据集。不管是发论文刷榜单还是做工业级感知模型的评估基准Cityscapes 都是默认的“第一站”。我最初接触这个数据集是在做车道线检测和可行驶区域分割时当时为了把数据下载下来并且正确解析标注文件折腾了不少时间。这篇就把 Cityscapes 数据集本身讲透包括它的任务定义、目录结构、标注体系以及实际操作中容易踩的坑给后面要上手的朋友一个完整的参考。1. 项目背景与核心价值1.1 Cityscapes 是做什么的Cityscapes 是一个面向城市街道场景理解的图像数据集由奔驰实验室联合多个学术机构在 2016 年发布CVPR 上那篇论文《The Cityscapes Dataset for Semantic Urban Scene Understanding》是它的官方出处。数据集采集了德国和法国多个城市的街道影像涵盖 50 个不同城市的白天、良好天气条件下的驾驶场景一共包含 5000 张精细标注图像和 20000 张粗糙标注图像。从任务角度来看Cityscapes 主要支持三类视觉任务语义分割把图像中每个像素分类到预定义的类别比如道路、人行道、建筑、车辆、行人等。这是 Cityscapes 最核心的任务也是绝大多数人使用它的目的。实例分割在语义分割的基础上区分同一类别的不同个体比如两辆相邻的汽车要分为 car 1 和 car 2。Cityscapes 对车辆、行人、自行车等类别提供了实例级标注。全景分割将语义分割和实例分割统一起来既要给每个像素语义标签又要区分可数物体的个体。Cityscapes 的标注结构天然支持全景分割任务。所以不管你是研究语义分割、实例分割还是全景分割Cityscapes 都是一个绕不开的标准数据集。1.2 为什么它这么重要Cityscapes 之所以能成为行业标准原因有三点。第一是数据质量高。图像分辨率达到 2048x1024远高于当时其他数据集比如 CamVid 只有 960x720标注精细到像素级多边形轮廓而不是简单的矩形框。这意味着模型能学到更精细的边界信息。第二是场景复杂度高。Cityscapes 采集的真实道路画面包含大量挑战性元素——行人遮挡、车辆密集、建筑阴影、光照变化、不同材质的路面等。一个模型如果能在 Cityscapes 上取得好的表现基本可以说明它在真实城市场景中有较强的泛化能力。第三是评估体系成熟。官方提供了严格的 train/val/test 划分test 集的标注不公开需要提交到官网服务器评估这保证了论文之间对比的公平性。语义分割、实例分割、全景分割三种任务都有独立的评估指标大家可以在同一起跑线上比较算法效果。1.3 适合谁使用这个数据集如果你是下面这几类人Cityscapes 会是你需要认真研究的数据集刚入门语义分割的研究生或工程师需要在一个公认的数据集上验证自己的模型效果做自动驾驶感知的算法工程师需要训练道路场景的分割模型比如用 mmsegmentation 训练 Cityscapes 是很多公司内部的标准流程做模型压缩、知识蒸馏、域自适应等方向的研究者Cityscapes 常作为源域数据集或基准数据集使用用 nnUNet 等框架做医疗或其他领域分割的同学也经常先把 Cityscapes 作为算法验证的标准数据集。这篇先讲透数据集的获取、目录结构、标注文件格式和可视化方法下一部分再展开训练细节。2. 数据集获取与目录结构详解2.1 下载方式与账号注册Cityscapes 的下载入口在官网和很多学术数据集不同它不是直接给一个链接让你点而是需要先注册账号同意数据使用协议后才能下载。这个流程卡住了不少人我第一次下载时就因为网络延迟和注册审核等了两天。具体操作流程是访问 Cityscapes 官网点击右上角的 Register 注册账号。填写个人信息包括姓名、单位、邮箱、使用目的等。这里建议使用学校或公司的企业邮箱审核通过率更高。提交后等待审核通常在 1-2 个工作日内会收到激活邮件。激活账号后登录在 Downloads 页面就能看到数据集的 6 个部分gtFine、gtCoarse、leftImg8bit、leftImg8bit_trainextra、camera、vehicle、disparity。下载时建议用官方提供的脚本在服务器上直接拉取比较方便。官方 GitHub 仓库 cityscapesScripts 里提供了prepare_cityscapes_dataset.py和Download相关脚本也可以用简单的 wget 或者 curl 加上账号 cookie 下载。注意登录后的下载链接是临时的带有 session 信息直接用 wget 下载时需要在浏览器里复制带有 token 的完整链接或者用脚本配合账号密码自动获取。手动复制链接时不要用迅雷等多线程工具容易被服务器断开连接。2.2 六大文件包的职责划分下载解压后你会看到 6 个文件夹每个文件夹的职责非常清晰我整理成了一张表文件夹内容作用leftImg8bit原始图像8-bit PNG分辨率 2048x1024模型输入图像gtFine精细标注包含语义、实例、多边形等语义/实例/全景分割训练与评估gtCoarse粗糙标注包含语义标签大规模预训练或半监督学习camera相机参数内外参矩阵3D 重建、深度估计等任务vehicle车辆轨迹、GPS、速度等信息轨迹预测、多任务学习disparity视差图DispNet 预测结果深度估计任务其中最常用的是leftImg8bit和gtFine。leftImg8bit其实就是原始拍摄图像按城市和序列组织成 train/val/test 三个子集。gtFine则是人工精细标注的结果也是我们做语义分割时最关心的部分。2.3 图像文件命名规则Cityscapes 的文件命名非常规范从文件名就能提取全部信息。格式是城市名_序列号_帧号_leftImg8bit.png比如aachen_000000_000019_leftImg8bit.png对应的是 aachen 城市、序列 000000、第 000019 帧的图像。注意leftImg8bit表示这是左侧摄像头拍摄的 8-bit 图像。对应的标注文件命名格式是aachen_000000_000019_gtFine_labelIds.png aachen_000000_000019_gtFine_instanceIds.png aachen_000000_000019_gtFine_color.png aachen_000000_000019_gtFine_polygons.json这里能看到 gtFine 下会有多种文件分别是:_labelIds.png像素值为 0~33 的语义标签图每个像素的数值直接对应类别 ID这也是训练模型时实际使用的文件。_instanceIds.png像素值为实例 ID 的图其中物体实例的 ID 编码是类别 ID * 1000 实例编号背景区域像素值为 0。_color.png用彩色标注的语义可视化图方便人眼查看。_polygons.jsonJSON 格式的多边形标注文件记录了每个物体实例的轮廓点坐标。理解这些文件命名规则很重要因为后续写数据加载代码时你需要根据leftImg8bit的文件名去拼接出对应的标注文件路径。3. 标注体系与任务类型全面拆解3.1 33 类标注与 19 类评估Cityscapes 的标签体系经过精心设计官方定义了 30 个类别加上 ignore 区域共 33 个标签值。这 30 个类别被划分为 8 个大类平面flat、人human、车辆vehicle、建筑construction、物体object、自然nature、天空sky、未知void。但在实际训练和评估时我们通常只用 19 个类别。原因在于很多类别在真实场景中出现频率极低比如卡车、巴士、房车如果都参与训练和评估会造成严重的类别不平衡模型会偏向学习高频类别。官方推荐使用的 19 类分别是道路、人行道、建筑、墙、围栏、电线杆、交通灯、交通标志、植被、地形、天空、人、骑手、汽车、卡车、巴士、火车、摩托车、自行车这 19 个类别是语义分割论文中通行的标准mIoU 的计算基准。下载的gtFine_labelIds.png中像素值虽然包含 0~33但在实际训练时需要做一个映射把 33 类映射到 19 类映射关系在官方脚本labels.py中有定义。3.2 精细标注与粗糙标注的区别Cityscapes 提供两套标注精细标注gtFine和粗糙标注gtCoarse。gtFine5000 张图像像素级精细标注质量高。分为 train2975 张、val500 张、test1525 张。这是官方推荐的训练和评估标准。gtCoarse20000 张图像标注相对粗糙多边形轮廓没有那么精细。主要用于大规模预训练或者作为半监督学习中的无标注数据补充。需要注意的是gtCoarse 只有 train 和 val 的划分对应leftImg8bit_trainextra文件夹额外的 20000 张原始图像。如果你决定用 gtCoarse 做预训练需要额外下载leftImg8bit_trainextra因为它不在默认的leftImg8bit里。3.3 三种任务的数据支撑Cityscapes 的标注结构可以同时支撑三种分割任务这也是它的设计精妙之处。语义分割直接使用_labelIds.png。每个像素的值就是 19 类映射后的类别 ID。模型输出的预测图也是 19 通道的概率图计算交叉熵损失时直接用这个文件做 ground truth。这是最简单直接的方式也是入门第一个要做对的任务。实例分割使用_instanceIds.png。这张图中每个像素的值为category_id * 1000 instance_id。比如一辆汽车的实例 ID 是 24000汽车类别 ID 24 实例 0另一辆是 24001。背景和不可数类别比如道路、建筑的像素值为 0。处理时先对 instanceIds 除以 1000 取整得到语义类别对 1000 取余得到实例编号。Cityscapes 官方对实例标注的范围覆盖 person、rider、car、truck、bus、train、motorcycle、bicycle 这 8 个类别。全景分割结合_labelIds.png和_instanceIds.png。全景分割的评价体系分 stuff 类和 thing 类Cityscapes 已经把这套体系设计好了。不可数的 stuff 类别直接用语义标签可数的 thing 类别用实例标签。有些框架如 mmsegmentation 在训练全景分割时会直接读取这两个文件并将其合并成全景标签图panoptic label。我个人的经验是先把语义分割跑通再扩展实例分割和全景分割不要一上来就三线作战容易在数据加载时出各种问题。4. 数据读取与可视化实操4.1 安装官方工具包 cityscapesscriptsCityscapes 官方提供了一个 Python 工具包cityscapesscripts它不仅能帮我们验证标注文件是否完整、可视化标注结果还提供将 labelIds 映射到 trainIds 的完整逻辑。这个工具包很重要因为官方训练时使用的 trainId 和原始 labelId 不同。安装非常简单pip install cityscapesscripts然后把项目仓库克隆下来或者直接从 pip 的安装路径下找脚本git clone https://github.com/mcordts/cityscapesScripts.git cd cityscapesScripts仓库里的helpers/labels.py定义了所有类别信息包括name、id、trainId、category、color等关键字段。这个文件是我做数据处理时最重要的参考文件。4.2 将标注转换为训练可用的 trainId 格式原始的gtFine_labelIds.png中像素值对应的是id字段0~33其中很多类别的 id 是不连续的比如汽车是 24自行车是 33。在语义分割训练中类别 ID 必须是连续的 0~18对应 19 类这样在计算交叉熵损失和评估 mIoU 时才不会出错。官方提供了createTrainIdLabelImgs.py用于将 labelIds 转换为使用 trainId 的图片python cityscapesscripts/preparation/createTrainIdLabelImgs.py \ --gtFineDir /path/to/gtFine \ --outputDir /path/to/gtFine_trainIds \ --trainId转换后每个标注图的像素值就是 0~18或 255 表示 ignore 区域。实际训练时我都是直接读取转换后的 trainId 图像而不是在训练时动态映射这样可以少写不少调试代码。4.3 可视化标注快速理解数据在动手训练之前强烈建议先可视化几张标注图直观理解数据长什么样。官方提供了visualizeAnnotations.py脚本python cityscapesscripts/visualization/visualizeAnnotations.py \ --city aachen \ --sequence 000000 \ --frame 000019它会显示原始图像、语义标注、实例标注三者的对比。另外你也可以直接用 OpenCV 读取_color.png文件这个文件就是官方预先做好的人眼可读的彩色标注图。我自己还写过一个简单的可视化脚本把原始图和 labelIds 叠加起来半透明显示方便快速查看某个区域的标注是否精细。这个步骤对排查标注边界模糊、类别空洞等问题很有帮助。4.4 数据加载的两种常见方式在实际项目里Cityscapes 数据加载有两种常见方式。第一种是直接写一个 Dataset 类用 OpenCV 或者 PIL 读取图像文件。流程是读取leftImg8bit图像。根据文件名拼接出对应的 trainId 标注图路径。对原始图像做数据增强缩放、裁剪、翻转、色彩抖动等对标注图做相同的几何变换注意不要对标注图做颜色增强。将图像转为 Tensor进行归一化。返回图像、标注和文件名。第二种是使用现成的框架比如 mmsegmentation。mmsegmentation 里已经内置了 Cityscapes 数据集的加载器你只需要配置好数据路径和类别信息即可dataset_type CityscapesDataset data_root data/cityscapes/这种方式的好处是不用重复造轮子mmsegmentation 的 dataloader 已经把 trainId 映射、ignore_index 处理等细节都封装好了。我目前更多的训练流程用的是 mmsegmentation但建议初学者还是先自己写一遍 Dataset 类彻底理解图像和标注的对应关系遇到问题才能自己排查。5. 常见问题与避坑指南5.1 下载慢、断连怎么办Cityscapes 官方服务器在欧洲国内访问速度不稳定经常下载到一半断开。我实测过的几个方案使用浏览器直接下载不要用多线程下载工具。浏览器会带着 session 信息基本能保持连接速度慢点但稳定。分割下载把每个压缩包单独下载不要一次性下载整个文件夹。比如先下载 gtFine再下载 leftImg8bit每个包都独立传输。如果服务器在国外可以用wget --user账号 --password密码配合官方脚本。如果服务器在国内建议用 filezilla 等 FTP 工具配合浏览器复制出的带 token 的完整链接断点续传能力更强实测比 wget 更稳。5.2 解压后路径对不上很多人在配置 mmsegmentation 时会遇到路径对不上的问题。Cityscapes 解压后的原始目录结构是cityscapes/ ├── leftImg8bit/ │ ├── train/ │ ├── val/ │ └── test/ ├── gtFine/ │ ├── train/ │ ├── val/ │ └── test/ └── gtCoarse/而 mmsegmentation 期望的目录结构通常是把数据集放在data/cityscapes下并且gtFine中要有 trainId 转换后的文件。如果直接拷贝原始数据进去训练时会报找不到 gtFine_trainIds之类的错误。解决办法是先运行createTrainIdLabelImgs.py生成 trainId 文件或者注意 mmsegmentation 的数据预处理说明有时根本不需要转换而是要在配置中指定reduce_zero_labelTrue和ignore_index255。我在这里踩过坑明明数据路径对但训练时 loss 一直不下降查了半天发现是标签映射没有对齐。5.3 trainId 映射错误导致 mIoU 异常Cityscapes 训练时最容易出问题的就是类别映射。直接使用原始的 labelIds0~33去算损失会导致某些类别缺失因为训练时只会使用出现过的类别 ID评估时类别 ID 和 mIoU 计算不匹配导致结果完全错误。正确做法是严格使用 trainId 映射。官方labels.py中的映射关系是固定的下面是常用的几个原始 id名称trainId0road01sidewalk12building23wall34fence45pole56traffic light67traffic sign78vegetation89terrain910sky1011person1112rider1213car1314truck1415bus1516train1617motorcycle1718bicycle18-1ignore2555.4 类别不平衡问题Cityscapes 中类别分布极不平衡道路像素占比远超行人、摩托车等类别。直接用交叉熵损失训练模型会偏向把大部分像素预测为道路导致小车类别的 mIoU 很低。实际处理中我常用的策略是使用带类别权重的损失函数CrossEntropyLoss(weight...)权重和类别像素占比成反比。使用 OHEM在线难例挖掘或多尺度监督加强对小目标区域的学习。在数据增强时增加随机裁剪和多尺度缩放让模型能看到更多小物体的细节。很多开源实现里默认是不加类别权重的需要自己根据数据集统计计算。如果想偷懒可以直接用 mmsegmentation 提供的OHEMPixelSampler效果也不错。5.5 粗糙标注与精细标注混用导致评估失真有些朋友为了提升训练数据量把 gtCoarse 也加入训练集但评估时还是用 val 的 500 张精细标注图。注意 gtCoarse 的标注质量比 gtFine 差轮廓粗糙边缘噪声大。直接混用会导致模型在精边缘上的表现下降。建议的做法是用 gtCoarse 做预训练或半监督学习的伪标签增强但权重要调低或者在 fine-tune 阶段最后几十个 epoch只用 gtFine让模型适应精细标注的分布。6. 关于 Cityscapes 的进一步规划在做完基本的数据解析和可视化之后Cityscapes 数据集的下一步通常就是训练分割模型。从我个人的实际体验来看在动手训练前把数据准备、类别映射、评估指标这些问题彻底搞明白能帮你节省至少一周的排错时间。对于后面要发的系列文章我大致规划了三个方向一是用 mmsegmentation 从零训练 Cityscapes 语义分割模型包括配置文件的详细解读和训练命令二是深入解读 Cityscapes 在实例分割与全景分割上的数据加载与评估细节三是在实际工业项目中Cityscapes 预训练模型如何迁移到自有数据集比如无人机航拍、x 光安检物品检测等场景上的经验。每个方向都有不少坑值得单独写一篇。Cityscapes 虽然是个老数据集但凡是做视觉感知的人总会在某个时刻和它打交道。把基础打牢后续无论换什么数据集、什么框架你都会轻松很多。这篇先到这里下一篇我们直接上手训练。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进