数据格式与存储规范: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 查询(「找出所有弯道路段的数据」),又不用额外部署数据库服务。

三、知识体系总览

下面这张图,是我自己梳理的数据格式选型决策流程。每次新项目开始前,我都会拿出来看一眼。

数据格式选型决策流程 原始传感器数据 需要多传感器时间同步? (激光雷达、相机、IMU 频率不同) 是 否 Rosbag 格式 天然支持异步采集 KITTI 格式 简单直接,适合验证 需要频繁查询/修改元数据? (标注更新、场景筛选) 是 否 NuScenes 格式 自定义轻量格式

一个小建议:不要一开始就追求「完美格式」。先用 Rosbag 或者 KITTI 把数据跑起来,等发现瓶颈了再迁移。我见过太多人花两个月设计格式,结果模型还没跑通一次。

最后说一句:数据格式没有银弹。Rosbag 适合采集和回放,NuScenes 适合训练和评测,KITTI 适合快速验证。搞清楚自己的场景,选最趁手的工具就行。

可可精品资料库