nuScenes数据集实战:从安装到多传感器数据可视化
1. nuScenes数据集简介与安装指南
nuScenes是自动驾驶领域最受欢迎的公开数据集之一,由Motional(前身为nuTonomy)团队于2019年发布。这个数据集采集自波士顿和新加坡的复杂城市道路场景,包含1000个场景,每个场景时长约20秒。数据集最吸引人的特点是其多模态传感器配置:6个摄像头(覆盖360°视野)、1个激光雷达、5个毫米波雷达,以及完整的IMU和GPS数据。
我第一次接触这个数据集时,被它的规模震撼到了——完整版约400GB,包含140万张图像、39万帧激光雷达扫描数据。不过别担心,官方提供了mini版本(约4GB),非常适合快速验证想法。数据集的核心价值在于其精细的3D标注,包括23类物体的3D边界框、属性和可见度信息,这在同类数据集中非常罕见。
安装过程其实很简单,只需两步:
pip install nuscenes-devkit
然后下载数据集(建议从官网注册后获取mini版本)。解压后你会看到这样的目录结构:
/data/sets/nuscenes
├── samples # 关键帧传感器数据
├── sweeps # 非关键帧传感器数据
├── maps # 高精地图(PNG+JSON)
└── v1.0-mini # 元数据与标注(JSON)
遇到过一个小坑:如果自定义数据路径,需要修改devkit源码中的默认路径设置。建议初学者先用官方推荐路径,等熟悉了再调整。
2. 数据集结构深度解析
2.1 核心数据表关系
nuScenes的数据组织像一个小型数据库,所有信息通过token(唯一ID)关联。主要表格包括:
- scene:场景单元(如"雨天十字路口左转")
- sample:场景中的时间采样点(每0.5秒一帧)
- sample_data:具体传感器数据(如图像、点云文件路径)
- sample_annotation:3D物体标注
用个生活化的比喻:如果把scene比作一部电影,sample就是电影中的关键帧,sample_data是每帧的画面和声音,sample_annotation则是字幕里标注的人物信息。
2.2 传感器数据详解
数据集包含三类传感器:
- 摄像头:6个(前/后/左前/右前/左后/右后),1600×900分辨率
- 激光雷达:1个32线雷达(车顶),每秒20次扫描
- 毫米波雷达:5个(前/左前/右前/左后/右后),每秒13次扫描
特别要注意的是数据存储方式:
samples/文件夹存放关键帧数据sweeps/存放中间帧数据(无标注)
实际使用时有个技巧:如果只做目标检测,可以只下载samples数据;若要做时序分析,才需要完整的sweeps数据。
3. 多传感器数据可视化实战
3.1 基础可视化方法
devkit自带的NuScenesExplorer类提供了开箱即用的可视化工具。最常用的三个方法:
from nuscenes.nuscenes import NuScenes
nusc = NuScenes(version='v1.0-mini', dataroot='/data/sets/nuscenes')
# 渲染单帧传感器数据
nusc.render_sample_data('37091c75b9704e0daa829ba56dfa0906') # 传入sample_data token
# 渲染3D标注框
nusc.render_annotation('ef63a697930c4b20a6b9791f423351da')
# 渲染整个场景的追踪轨迹
nusc.render_instance('9cba9cd8af85487fb010652c90d845b5')
实测发现一个小技巧:在Jupyter Notebook中使用%matplotlib notebook可以获得交互式可视化窗口,方便旋转查看3D点云。
3.2 多传感器同步可视化
要实现多传感器数据叠加显示(如相机图像+雷达点云),需要处理坐标系转换。devkit已经封装好了相关方法:
from nuscenes.utils.data_classes import LidarPointCloud
import matplotlib.pyplot as plt
# 获取样本数据
sample = nusc.sample[10]
cam_token = sample['data']['CAM_FRONT']
lidar_token = sample['data']['LIDAR_TOP']
# 将激光雷达点云投影到图像
points = LidarPointCloud.from_file(nusc.get_sample_data(lidar_token)[0])
img = Image.open(nusc.get_sample_data(cam_token)[0])
# 可视化
plt.figure(figsize=(12,6))
plt.imshow(img)
points.render_height(plt.gca()) # 在图像上渲染点云高度信息
这里有个常见问题:点云在图像上位置不准?通常是没考虑传感器外参。devkit的get_sample_data()方法会自动完成坐标系转换,比自己手动计算更可靠。
4. 高级技巧与性能优化
4.1 高效数据加载方案
处理完整数据集时,I/O容易成为瓶颈。我的经验是:
- 预加载元数据:初始化时设置
verbose=False可加速加载 - 使用生成器:批量处理样本而非单帧处理
- 缓存常用数据:如校准参数、地图等
# 批量处理示例
for scene in nusc.scene:
first_sample_token = scene['first_sample_token']
while first_sample_token:
sample = nusc.get('sample', first_sample_token)
process_sample(sample) # 自定义处理函数
first_sample_token = sample['next']
4.2 自定义可视化技巧
官方可视化有时不够灵活,我们可以用pyviz或open3d实现更复杂的渲染:
from nuscenes.utils import visualization as viz
import open3d as o3d
# 创建带标注的3D场景
fig, ax = viz.visualize_sample(nusc, sample_token='ca9a282c9e77460f8360f564131a8af5')
plt.show()
# 使用Open3D交互式查看点云
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points.points[:3,:].T)
o3d.visualization.draw_geometries([pcd])
遇到过的一个坑:open3d默认坐标系与nuScenes不同(y轴向上 vs z轴向上),需要做坐标变换。
5. 实际项目中的应用建议
在真实项目中,我通常会这样使用nuScenes:
- 算法原型阶段:用mini版快速验证idea
- 模型训练:使用完整版的trainval split(约700场景)
- 测试评估:用test split(约150场景)提交到官方评测服务器
对于计算资源有限的团队,建议:
- 优先使用关键帧数据(samples)
- 从单一模态开始(如仅用摄像头或仅用激光雷达)
- 利用官方提供的baseline代码(如CenterPoint、BEVFusion)
最后分享一个实用脚本——批量导出所有场景的鸟瞰图:
from nuscenes.utils.geometry_utils import view_points
def export_bev(scene_token, output_dir):
scene = nusc.get('scene', scene_token)
sample_token = scene['first_sample_token']
while sample_token:
sample = nusc.get('sample', sample_token)
lidar_data = nusc.get_sample_data(sample['data']['LIDAR_TOP'])[0]
# 转换为BEV坐标
points = LidarPointCloud.from_file(lidar_data)
points = points.points[:3,:] # 取xyz
points[2,:] = 0 # 忽略高度
# 绘制并保存
plt.scatter(points[0,:], points[1,:], s=1)
plt.savefig(f"{output_dir}/{sample_token}.png")
plt.clf()
sample_token = sample['next']
更多推荐

所有评论(0)