数据格式与存储规范:Rosbag、NuScenes、KITTI格式解析,自定义数据格式设计原则
做车道线模型调优,最头疼的往往不是算法本身,而是数据。我见过太多团队,模型结构抄得一模一样,结果别人收敛了,自己这边死活不work。一查,数据格式乱成一锅粥。
说白了,数据格式就是你和传感器、和算法之间的「共同语言」。语言不通,什么都白搭。今天我就把几种主流格式掰开揉碎讲清楚,再聊聊我自己设计自定义格式的一些血泪教训。
一、三大主流格式:Rosbag、NuScenes、KITTI
这三种格式,基本覆盖了自动驾驶数据存储的「半壁江山」。你想想看,无论你从哪个公开数据集下载数据,大概率跑不出这仨。
1. Rosbag:机器人界的「通用语言」
Rosbag 是 ROS 生态下的标准容器。它本质上就是一个时间戳索引的「消息流水账」——每一帧图像、每一个点云、每一条控制指令,都按时间顺序往里塞。
核心特点:
- 基于 Topic 的发布/订阅模型,天然支持多传感器异步采集
- 时间戳精确到纳秒级,回放时能完美还原采集现场
- 支持压缩存储(BZ2、LZ4),但压缩后随机访问性能下降
我在项目中遇到过一个问题:用 rosbag 录了 3 个小时的高速场景,结果回放时发现某个 Topic 的 message definition 和当前环境不匹配。嗯,这里要注意——rosbag 的序列化依赖消息定义,换版本或者改字段名,老包可能直接废掉。
# 常用命令示例
rosbag record /camera/image_raw /lidar/points_raw -O highway_scene.bag
rosbag info highway_scene.bag
rosbag play highway_scene.bag --clock
我的习惯:每次录包前,先跑一遍 rosbag record -a 把所有 Topic 都录下来。虽然包会大一点,但后期排查问题的时候,你永远不知道哪个「无关」的 Topic 能救命。
2. NuScenes:结构化数据的「教科书」
NuScenes 格式是我个人比较推崇的。它把数据拆成了「数据库 + 原始文件」两层。数据库用 JSON 文件组织,记录了每一帧的元信息——传感器标定参数、物体标注、时间戳对应关系等。原始文件(图像、点云)单独存放。
为什么会这样设计?因为自动驾驶数据里,元信息比原始数据更容易「变」。你今天用 32 线激光雷达,明天换 128 线,标定参数变了,但标注框的坐标不用动。NuScenes 这种解耦方式,说白了就是「把不变的和变的分开管理」。
| 组件 | 说明 | 我的评价 |
|---|---|---|
| sample | 关键帧,包含所有传感器数据的时间戳 | 相当于「快照」 |
| sample_data | 单个传感器的一帧数据路径 | 指向具体文件 |
| calibrated_sensor | 传感器内参和外参 | 这个最容易出错 |
| ego_pose | 自车位姿(全局坐标系) | 做 BEV 感知必备 |
我曾经踩过的坑:NuScenes 的坐标系是「右-前-上」,而 KITTI 是「前-左-上」。两个数据集混着训练时,忘记转换坐标系,结果模型学出来的车道线偏移了半米。排查了整整两天。
3. KITTI:经典但「老派」
KITTI 格式很直接——图像是 PNG,点云是 BIN,标定文件是 TXT。没有数据库,没有索引,全靠文件名和时间戳硬对齐。
它的优点是简单、透明。你打开一个文件夹,所有东西一目了然。但缺点也很明显:
- 没有显式的时间戳对齐信息,全靠文件名里的序号
- 多传感器同步全靠采集时硬件触发,后期无法修正
- 标定文件格式不统一,不同版本可能字段名都不一样
我建议:如果你只是做算法验证,KITTI 格式够用。但如果你要搭建数据闭环系统,趁早换 NuScenes 或者自定义格式。
二、自定义数据格式设计原则
讲完现成的,聊聊怎么设计自己的格式。我在三家自动驾驶公司待过,每家都搞了一套「独门格式」。总结下来,好的设计都有这几个共性:
原则 1:元数据与原始数据分离
原始数据(图像、点云)体积大、不常变。元数据(标定、标注、时间戳)体积小、经常改。把它们混在一起,每次改标注都要重写整个文件,效率极低。
原则 2:时间戳是「一等公民」
所有传感器数据、标注信息,都必须有全局唯一的时间戳。不要依赖文件名排序,不要依赖采集顺序。我见过一个团队,用文件名里的毫秒数当时间戳,结果遇到跨秒边界时直接溢出——嗯,那天的数据全废了。
原则 3:支持增量写入和随机读取
自动驾驶数据采集是流式的。你不能等车跑完再写文件,必须边采边写。同时,训练时你不需要从头读到尾,要能根据时间戳或场景标签快速定位到某一段。
我推荐的结构:
dataset/
├── metadata.db # SQLite 数据库,存所有元信息
├── images/
│ ├── 000001.png
│ └── 000002.png
├── lidar/
│ ├── 000001.bin
│ └── 000002.bin
└── calib/
├── camera_intrinsic.yaml
└── lidar_to_camera.yaml
用 SQLite 做索引,既支持 SQL 查询(「找出所有弯道路段的数据」),又不用额外部署数据库服务。
三、知识体系总览
下面这张图,是我自己梳理的数据格式选型决策流程。每次新项目开始前,我都会拿出来看一眼。
一个小建议:不要一开始就追求「完美格式」。先用 Rosbag 或者 KITTI 把数据跑起来,等发现瓶颈了再迁移。我见过太多人花两个月设计格式,结果模型还没跑通一次。
最后说一句:数据格式没有银弹。Rosbag 适合采集和回放,NuScenes 适合训练和评测,KITTI 适合快速验证。搞清楚自己的场景,选最趁手的工具就行。