
Apollo Scape阿波罗数据集在自动驾驶感知圈子里算是比较特别的一个存在。它不像KITTI那样被翻来覆去讲烂了也不像nuScenes那样几乎是多模态融合的标配但只要你真的动手做过中国城市道路场景的语义分割、车道线检测或者视觉自定位早晚都会碰到它。我第一次接触这个数据集是在做一个复杂路口的多类别语义分割项目当时用公开数据集跑出来的模型换到实地采集的图像上掉点掉得厉害后来才意识到场景分布差异这个事Apollo Scape恰好补上了这块拼图。这篇文章我会把Apollo Scape的整体设计、每个子数据集到底能干什么、下载和申请的完整流程、以及我踩过的那些坑掰开揉碎讲一遍。适合正在做自动驾驶感知、想找中国道路场景数据、或者单纯想扩充自己数据集工具箱的朋友参考新手也能照着一步步把数据拿到手开始训练。1. Apollo Scape数据集整体定位与设计思路拆解1.1 它到底解决了什么问题大部分早期公开的自动驾驶数据集采集地点集中在欧美城市。道路结构、车道线样式、交通标识、甚至光照和植被颜色分布都跟国内城市有明显区别。你把在KITTI上训得很好的分割模型拿到国内复杂路口会发现它对某些类别几乎完全失效比如形状特殊的非机动车道边界、颜色和形态都不同的交通标线、以及密集的非机动车和行人混行场景。Apollo Scape的出发点很直接用国内多个城市真实道路采集的数据覆盖这些被其他数据集忽略的场景细节。它最早由Apollo自动驾驶开放平台联合多家高校和研究机构发布定位是一个多任务、多模态、大规模的自动驾驶场景理解数据集。多任务指的是它不只提供语义分割标注还覆盖车道线检测、3D车辆实例、视觉自定位、轨迹预测等多个子方向。多模态指的是它同时包含RGB图像、深度信息、点云以及对应的标注文件部分子集还提供双目立体数据。大规模体现在总图像量达到十几万张级别标注像素数量更是天文数字这在2018年前后发布时是相当有分量的。我个人的判断是Apollo Scape最大的价值不在于刷新某个单一任务的SOTA而在于它的场景多样性和标注粒度。它把中国城市道路里那些“看起来乱糟糟但真实存在”的细节保留了下来这对模型落地到实际场景至关重要。1.2 与KITTI、nuScenes的差异定位很多人第一次听到Apollo Scape会问那我直接用KITTI或者nuScenes不行吗这里得说清楚三者的分工。KITTI更偏向车载视角下的目标检测、光流、立体匹配和视觉里程计它的数据采集车配置和场景比较单一主要是德国城市和郊区道路。nuScenes的强项是多传感器融合尤其是激光雷达和毫米波雷达配套齐全适合做3D检测和跟踪采集地在新加坡和波士顿。Apollo Scape的差异化在语义理解的深度和场景复杂度上它的语义分割标注类别更细覆盖了国内道路特有的元素而且采集场景包含大量拥堵、混行、复杂路口的情况。我用一个生活化的类比来说明KITTI像是给你一条标准化的高速公路让你练车nuScenes像是给你一套完整的车载传感器让你研究怎么感知周围而Apollo Scape更像是直接把你扔进早晚高峰的城市主干道逼你去处理那些杂乱但有价值的信息。1.3 数据集任务矩阵一览Apollo Scape并不是一个单一数据集而是一组围绕场景理解构建的子数据集集合。我把主要成员整理成一张表方便你快速对照自己的需求。子数据集核心任务数据规模量级主要标注形式Scene Parsing像素级语义分割十余万张图像逐像素类别标签Lane Segmentation车道线检测与分割数万张图像车道线像素掩码Self-localization视觉自定位多城市连续帧位姿与点云参考3D Car Instance3D车辆实例理解数万帧3D框与实例掩码Trajectory轨迹预测多目标时序数据轨迹坐标序列Stereo双目立体匹配成对双目图像视差图这张表不是摆设。你在立项前先看清楚自己要解决的任务落在哪一格再决定下载哪个子集。我见过有人想做人车混行的分割却跑去下了轨迹预测数据白折腾一周。2. 核心子数据集解析与标注体系拆解2.1 场景解析数据集像素级语义标注的主力场景解析Scene Parsing是Apollo Scape里使用频率最高的子集。它的核心是一张张真实道路图像加上逐像素的类别标注让你训练模型去判断每个像素属于哪个类别比如天空、道路、建筑、植被、车辆、行人、交通标线等等。类别体系上它经历了从早期较少的类别数逐步扩充到更细粒度的过程。不同版本发布的类别定义会有差异你在使用前一定要以你下载的那个版本附带的说明文件为准别拿着旧博客里的类别表去套新数据这是我早期踩过的一个坑。类别里有几个值得注意的点一是它把道路细分成可行驶区域和其他硬质地面二是对交通标线做了单独区分三是建筑和栅栏之类的垂直结构分得比较清楚。标注形式一般是每张图像对应一张标签图标签图是单通道图像像素值直接对应类别编号还有一部分会附带JSON或JSON格式的元信息描述图像尺寸和类别映射。这种设计的优势是读取快、存储省你写个自定义Dataset类就能直接映射。难点在于标注边界处的处理尤其是细小目标如远处的交通标志、被部分遮挡的非机动车标注可能存在一定的边缘不确定性训练时如果对边界过于苛刻反而会让模型学偏。2.2 车道线分割数据集国内复杂车道线的试金石车道线分割Lane Segmentation子集是我个人觉得最有意思的部分。国内道路的车道线样式比欧美复杂得多有虚线实线混排、有颜色褪色的旧标线、有被车辆反复碾压模糊的标线还有各种导流线和可变车道线。这个子集专门针对这些情况提供标注。它的标注思路是给出车道线的像素级掩码部分标注还会区分不同车道线的实例。你在做车道线检测时如果只做二分类是不是车道线会简单很多但如果你想做车道线实例分割用于后续的车道保持和路径规划那标注的实例信息就非常关键。实际使用中我建议先用二分类任务把模型跑通确认数据读取和增强流程没问题再升级到实例级别这样排查问题会清晰很多。需要注意的一点是车道线在图像中往往是细长结构占像素比例极低属于典型的类别不平衡问题。如果直接用普通交叉熵模型很容易学会全部预测为背景也能拿到很高的准确率但实际一点用都没有。我后面会在实操部分专门讲这个怎么破。2.3 自定位与3D车辆实例从感知到空间理解自定位Self-localization数据集面向的是视觉定位任务核心是让车辆通过视觉信息推断自己在世界坐标系中的位置。它通常包含连续帧图像、对应的位姿标注以及可用于验证的点云参考数据。这个任务的难点在于城市环境里的重复纹理、动态物体遮挡和光照变化数据集在这几个维度都做了覆盖。3D车辆实例3D Car Instance子集则把视角从像素级别提升到空间级别提供车辆的三维包围框和实例掩码。这对做3D检测、单目3D重建、以及车辆跟踪的人来说很有用。它的标注形式一般包含车辆在图像中的2D投影框、3D尺寸和朝向信息读取时需要自己写解析逻辑把标注映射到坐标系中。这两个子集的使用门槛比场景解析高一些因为涉及坐标系转换和相机内参外参的处理。我建议先把内参外参的定义搞清楚确认是相机坐标系还是车辆坐标系否则算出来的位置会差之毫厘谬以千里。2.4 轨迹预测与合成数据时序与仿真补充轨迹预测Trajectory子集把关注点从单帧感知转向多帧时序提供交通参与者在一段时间内的轨迹序列用于训练预测模型判断目标接下来会往哪走。这类任务在自动驾驶决策规划里非常关键因为感知只能告诉你现在有什么预测才能告诉你接下来会发生什么。合成数据Synthetic子集是另一种思路通过仿真环境生成图像和标注用来补充真实数据难以覆盖的极端场景比如罕见交通状况、危险工况等。合成数据的优势是标注绝对精确、可以任意生成劣势是存在与真实数据的域差异domain gap。我的经验是合成数据适合用来预训练或者做数据增强但最终一定要用真实数据微调否则模型在实车上的表现会打折扣。3. 下载流程与数据准备实操3.1 获取数据的正规渠道与申请流程Apollo Scape数据集的获取通常通过其官方发布平台进行一般是访问项目官网找到数据集下载页面注册账号后按子集分别申请或下载。部分子集可以直接下载部分需要填写用途说明并等待审核。这里我要提醒一句不同时期官网的页面结构和下载策略可能会有调整你如果发现某个链接失效不要慌先去官网首页找最新的入口或者查看项目在开源社区的公告。申请时通常需要填写你的机构、用途、研究方向和联系方式。我建议如实填写尤其是用途因为这直接关系到你能不能顺利拿到数据授权。有些子集的使用有学术研究用途的限制商用前一定要看清楚许可条款别抱着侥幸心理拿去商用这是原则问题。3.2 目录结构与文件命名解读拿到数据后第一件事不是急着训练而是把目录结构摸清楚。Apollo Scape的典型结构一般会把图像、标注、元信息分目录存放命名规则往往包含场景编号、帧编号和相机编号。举个例子一个图像文件名可能由采集片段ID和帧序号组成对应的标注文件用相同的前缀只是后缀不同。我建议你拿到数据后先做两件事一是用脚本统计一下图像数量和标注数量是否一一对应防止下载中断导致文件缺失二是随机抽几十张图像和标注做可视化肉眼确认对齐没问题。我早期就遇到过图像和标注错位的情况原因是文件名排序时的字典序和实际帧序不一致导致训练时把A图的标注配到了B图上模型怎么训都不收敛排查了大半天。3.3 标注格式解析与读取代码语义分割标注常见的存储方式是单通道PNG像素值等于类别ID。读取时不要用普通的图像读取方式直接当成RGB三通道处理否则通道数不对会导致维度错乱。下面给一个通用的读取和映射示例你可以按自己实际数据的类别映射调整。import numpy as np from PIL import Image # 读取标签图注意用单通道模式 label np.array(Image.open(label_0001.png)) # 形状 (H, W) print(唯一类别值:, np.unique(label)) # 假设类别映射表 id_to_class { 0: void, 1: road, 2: sidewalk, 3: building, 4: vegetation, 5: vehicle, 6: person, 7: traffic_line, } # 可视化统计每个类别占比 total label.size for cid, name in id_to_class.items(): ratio (label cid).sum() / total print(f{name}: {ratio:.4f})这段代码的价值在于它顺便帮你统计了类别分布。类别分布是后续设计损失函数和采样策略的依据。你如果发现某个关键类别占比不到千分之一那就必须考虑加权损失或者重采样不然模型基本学不到这个类别。3.4 数据预处理与格式转换实操Apollo Scape的原始数据往往不能直接喂给主流框架需要做一轮转换。以转成COCO格式或者自定义Dataset为例核心工作是建立图像路径和标注路径的映射把标签图按需转成索引掩码并处理类别合并。import os import json img_dir images lbl_dir labels samples [] for fname in os.listdir(img_dir): if not fname.endswith(.jpg): continue stem os.path.splitext(fname)[0] label_path os.path.join(lbl_dir, stem .png) if os.path.exists(label_path): samples.append({ image: os.path.join(img_dir, fname), label: label_path, }) # 按 8:1:1 划分记得固定随机种子保证可复现 import random random.seed(42) random.shuffle(samples) n len(samples) train samples[:int(n * 0.8)] val samples[int(n * 0.8):int(n * 0.9)] test samples[int(n * 0.9):] with open(splits.json, w) as f: json.dump({train: train, val: val, test: test}, f, indent2) print(训练/验证/测试:, len(train), len(val), len(test))这段脚本看起来简单但有两个细节决定成败固定随机种子和检查文件配对。前者保证你每次划分一致方便复现实验结果后者避免标注缺失的样本混进训练集。我见过有人没做配对检查训练时程序直接崩在读文件那一步白白浪费一次训练排队时间。数据增强方面语义分割要特别小心几何变换和标签的一致性。你旋转、裁剪、缩放图像时标签图必须用同样的变换参数同步处理。用现成的增强库时记得确认它是否支持对标签图做插值方式的区分图像可以用双线性插值标签图一般必须用最近邻插值否则会产生不存在的类别值。4. 常见问题与排查技巧实录4.1 数据申请与下载环节的坑第一个高频问题就是下载中断和文件不完整。十几万张图像的数据量动辄几十上百GB网络一抖动就可能导致压缩包损坏。我的做法是下载完成后先校验文件大小和数量再用解压工具测试压缩包完整性确认无误再删原始压缩包。别嫌麻烦一次损坏的重下成本远高于一次校验。第二个问题是版本混淆。Apollo Scape在不同阶段发布过不同版本类别定义和标注格式可能有变化。我建议你在项目里建一个文档目录把下载时附带的说明文件、类别映射表、许可条款都存进去避免过几个月自己也记不清用的是哪个版本。第三个问题出在权限和时间上。有些子集需要审核审核时间不确定。如果你的项目有明确的deadline建议提前一两周去申请别等到要跑实验了才发现数据还没批下来。4.2 标注对齐与坐标系处理问题前面提过图像和标注错位的问题这里再展开说排查思路。第一步用脚本打印前若干对文件名肉眼确认前缀一致。第二步随机抽几对做可视化叠加看标注边界是否和图像内容吻合。第三步如果发现错位检查你的排序逻辑很多时候问题出在字符串排序把第10帧排到了第2帧前面。修复方式是用自然排序或者直接按文件里记录的帧序号排序。坐标系问题主要集中在自定位和3D实例子集。常见错误是混淆了相机坐标系和车辆坐标系或者把内参矩阵用错方向。排查方法是选一帧已知位姿的数据手动把3D点投影到图像上看投影点和实际物体是否重合。如果不重合逐项检查内参、外参、坐标系定义别急着怀疑数据本身有问题十有八九是自己的转换写错了。4.3 训练与评估环节的陷阱类别不平衡是语义分割的老大难Apollo Scape因为场景复杂这个问题更突出。除了前面说的加权损失还可以考虑OHEM在线难例挖掘或者Dice损失与交叉熵结合。我自己实测下来对于车道线这类细长目标Dice损失收敛更快但边界容易糊交叉熵边界清晰但小目标学得慢。组合使用效果比较稳。评估环节有个特别隐蔽的坑标注里的忽略区域ignore区域。这类区域的像素在计算损失和评估指标时必须排除否则模型会被无关像素带偏指标也会虚高。你拿到数据后要先确认哪些像素值是忽略标记通常是一个特定数值比如255然后在损失计算和mIoU统计里显式排除。还有一个是数据泄漏问题。同一段连续采集的图像相隔帧之间高度相似。如果你随机划分训练集和验证集很可能把相邻帧分到了两边导致验证指标虚高。正确做法是按采集片段划分同一个片段要么全进训练要么全进验证。这个细节很多人忽略但直接影响你对模型真实性能的判断。4.4 常见问题速查表我把上面这些高频问题整理成表方便你遇到时快速对照。问题现象可能原因排查与解决训练loss不下降图像标注错位检查文件名前缀与帧序排序小目标几乎学不到类别极度不平衡加权损失、Dice损失、重采样评估指标虚高忽略区域未排除或数据泄漏显式排除ignore像素按片段划分数据读取报错标注缺失或格式不符先做文件配对完整性检查3D投影对不上坐标系或内外参用错手动投影验证逐项核对参数标签出现异常值增强时标签用了双线性插值标签统一用最近邻插值压缩包无法解压下载中断校验大小数量重新下载注意忽略区域的像素值一定要以官方说明为准不同版本可能不同不要凭经验猜。最后再分享一个我在实际项目里的小习惯拿到任何一个新数据集我都会先写一个五分钟的“数据体检脚本”统计图像数量、标注数量、类别分布、图像尺寸分布、文件大小分布。这套脚本花不了多少时间但能帮你在正式训练前把大部分数据层面的问题揪出来。Apollo Scape这种体量的数据集这个习惯尤其值得养成因为它的子集多、版本多一旦数据层面有隐患后面调模型调到头秃都找不到原因。至于Apollo Scape后续还有哪些子集细节值得单独展开比如自定位的位姿误差评估、3D实例的朝向回归技巧这些内容量比较大我打算在下一篇里单独拆。