nuScenes3D⽬标检测数据集解析(完整版附python代码)
  最近在⽤nuScenes3D⽬标检测数据集,可能由于官⽅已经提供了解析⼯具包nuscenes-devkit,绝⼤多数博客只介绍了如何使⽤⼯具包进⾏数据解析和可视化,对于数据解析的内部逻辑就不是很关注了。本⽂根据官⽹说明、论⽂以及⼯具包源码整理归纳得到,对其他博客未提及的数据集结构、坐标系转换、传感器同步等问题进⾏了详细分析。
1.
2.
3.
4.
1. 数据集概述
1.1 传感器配置
  nuScenes的数据采集车辆为Renault Zoe迷你电动车,配备6个周视相机,5个毫⽶波雷达,具备360°的视野感知能⼒。具体传感器信息即分布见下⾯的图表。
传感器类型详细信息
python解析json文件相机6台彩⾊相机,1600×900的分辨率,采⽤JPEG格式压缩,采样频率为12Hz
激光雷达1台32线旋转式激光雷达,20Hz采样频率,360°⽔平FOV,-30°-10°的垂直FOV,探测距离70m,探测精度2cm,每秒140万点云
毫⽶波雷达5个77GHz的毫⽶波雷达,FMCW调频,13Hz采样频率,探测距离250m,速度精度±0.1km/h GPS和IMU20mm的RTK定位精度,1000Hz采样频率
1.2 数据采集
  nuScenes数据集使⽤了两辆传感器配置相同的雷诺电动车进⾏采集,采集地点为波⼠顿和新加坡,这两个城市以交通密集和驾驶场景复杂闻名。
  整个数据集包含了由⼈⼯挑选的84段log,时长约15⼩时,距离约242km,平均车速16km/h。数据场景覆盖了城市、住宅区、郊区、⼯业区各个场景,也涵盖了⽩天、⿊夜、晴天、⾬天、多云等不同时段不同天⽓状况。最终数据集分为1000个⽚段,每个⽚段约
20s。
1.3 传感器同步和数据标注
  nuScenes和KITTI⼀样,也是采⽤激光来控制相机的曝光时刻,不过nuScenes有6个覆盖360°视野的相机。
  在nuScenes中,图像的时间戳表⽰相机开始曝光的时刻,激光的时间戳表⽰激光扫描⼀圈结束的时刻。当车顶激光的线束扫描到相机FOV中⼼区域时,便会给对应相机⼀个曝光信号,激光扫描⼀圈会触发6次相机曝光。
  这⾥我对训练集进⾏了简单的统计,850个场景共34149帧数据。统计结果及含义如下所⽰:
Total Scene  Num: 850
Total Sample Num: 34149
[ expo_time_bet_adj_cams] Avg:    8.52ms  2STD:    8.53ms
[max_delta_time_bet_cams] Avg:  42.61ms  2STD:  42.67ms
[      cam_refresh_time] Avg:  498.93ms  2STD:  503.95ms
数据库工程师好工作吗
[    lidar_refresh_time] Avg:  498.93ms  2STD:  503.97ms
[  delta_lidar_cam_time] Avg:    0.99ms  2STD:    2.37ms
统计结果含义
expo_time_bet_adj_cams 相邻两个相机曝光时间差,平均8.5ms,6个相机正好50ms,符合激光的扫描频率,侧⾯证明了每⼀圈激光会触发6次相机曝光
max_delta_time_bet_cams 6个周视相机依次曝光时刻的最⼤时间间隔,平均42ms,这意味着在相对40km/h相对速度下,第⼀个开始曝光的左前⽅相机和最后⼀个曝光的左后⽅相机,对同⼀个物体的观测距离会相差接近半⽶
cam_refresh_time相机采样间隔,平均500ms,对应2Hz的关键帧采样频率
lidar_refresh_time激光采样间隔,平均500ms,对应2Hz的关键帧采样频率
delta_lidar_cam_time激光时间戳和左后⽅相机曝光时刻的差值,均值仅1ms,说明激光扫描是从左后⽅相机附近位置开始的
1.4 建图定位
  nuScenes的定位数据的⽣成分为两个阶段,⾸先采⽤离线的⽅式使⽤激光点云⽣成⾼清地图,然后在线采集数据阶段,结合⾥程计和激光数据,使⽤蒙特卡洛定位算法进⾏车辆定位,最终定位误差可以达到10cm以内。
2. 数据集下载
  在注册⼀个账号下载数据集,完整数据集包含3个部分:浏览器silverlight加载不出来
Mini:从训练/验证集抽取10个场景组成,包含完整的原始数据和标注信息,主要⽤于数据集的熟悉;assets是什么文件夹
TrainVal:训练/验证集,包含850个场景,其中700个训练场景,150个验证场景
Test:测试集,包含150个场景,不包含标注数据。
  下载好的数据集包含4个⽂件夹:
maps:地图数据,四张地图对应着4个数据采集地点
衣服单词clothessamples:带有标注信息的关键帧数据,训练主要⽤这部分数据
sweeps:完整时序数据,不带有标注信息,⼀般⽤于跟踪任务
v1.0-version:存有数据依赖关系、标注信息、标定参数的各种json⽂件
3. 数据集解析
  nuScenes官⽅提供了⼀个数据集开发⼯具nuscenes-devkit,封装了数据读取、索引、可视化等常⽤操作,可以直接使⽤pip安装:
pip install nuscenes-devkit
  这个⼯具包⽤起来还⽐较⽅便,具体怎么使⽤这⾥就不做过多介绍了,官⽹有详细的教程。有⼀点要注意的是,nuScenes解析库要求v1.0-version等4个⽂件夹在同⼀级⽬录,否则会⽆法解析。
3.1 数据集结构
  在介绍如何使⽤⼯具包遍历数据集之前,先对nuScenes数据集结构做⼀个简单介绍。nuScenes数据集采⽤关系数据库来管理数据,数据库⼀共包含13张表,以json⽂件格式存储在./v1.0-version⽬录下。
self.table_names =['category','attribute','visibility','instance','sensor','calibrated_sensor',
'ego_pose','log','scene','sample','sample_data','sample_annotation','map']
  在使⽤⼯具包获得数据集的句柄nusc后,可以通过(table_name, token)函数来快速获取任意表中的任意数据,⼗分⽅便快捷。表和表之间的依赖关系图可以去nuScenes官⽹的Data format标签页中查看,这⾥我对官⽹的关系图进⾏了归纳和精简。
  总的来说,nuScenes数据集分为mini、trainval、test三个部分,每个部分的数据结构完全相同,可以
分成scene、sample、sample_data三个层级,数据访问通过token(可以理解为指针)来实现:
scene:是⼀段约20s的视频⽚段,由于关键帧采样频率为2Hz,所以每个scene⼤约包含40个关键帧,可以通过scene中
的pre和next来访问上下相邻的sample
sample:对应着⼀个关键帧数据,存储了相机、激光雷达、毫⽶波雷达的token信息,mini和trainval数据集中的sample还存储了标注信息的token
sample_data:sample中存储的token指向的数据,即我们最终真正关⼼的信息,⽐如图⽚路径、位姿数据、传感器标定结果、标注⽬标的3d信息等。获取到这些信息就可以开始训练模型了。
3.2 数据集遍历
  nuScenes以关系数据库的⽅式管理数据,scene、sample、sample_data之间可以通过token⾮常⽅便的互相访问。这⾥分别从scene、sample和annotation为起点对整个数据集进⾏访问,统计数据集的场景、关键帧、标注⽬标的数⽬。
from nuscenes.nuscenes import NuScenes
def get_dataset_info1(nusc):
scene_num =len(nusc.scene)
sample_num =0
ann_num =0
for scene in nusc.scene:
sample =None
while True:
if sample is None:
sample = ('sample', scene['first_sample_token'])
sample_num +=1
ann_num +=len(sample['anns'])
if sample['next']!='':
sample = ('sample', sample['next'])
else:
break
print('====== Start from scene')
print('Scene Num: %d\nSample Num: %d\nAnnotation Num: %d'%(scene_num, sample_num, ann_num))
def get_dataset_info2(nusc):
sample_num =len(nusc.sample)
ann_num =0
scene_tokens =set()
for sample in nusc.sample:
ann_num +=len(sample['anns'])
scene = ('scene', sample['scene_token'])
scene_tokens.add(scene['token'])
scene_num =len(scene_tokens)
print('====== Start from sample')
print('Scene Num: %d\nSample Num: %d\nAnnotation Num: %d'%(scene_num, sample_num, ann_num))
def get_dataset_info3(nusc):
ann_num =len(nusc.sample_annotation)
scene_tokens =set()
sample_tokens =set()
for ann in nusc.sample_annotation:
sample = ('sample', ann['sample_token'])
sample_tokens.add(sample['token'])
scene = ('scene', sample['scene_token'])
scene_tokens.add(scene['token'])
scene_num =len(scene_tokens)
sample_num =len(sample_tokens)
print('====== Start from annotation')
print('Scene Num: %d\nSample Num: %d\nAnnotation Num: %d'%(scene_num, sample_num, ann_num))
if __name__ =='__main__':
nusc = NuScenes(version='v1.0-mini',
dataroot=data_root,
verbose=True)
get_dataset_info1(nusc)
get_dataset_info2(nusc)
get_dataset_info3(nusc)
wps中滚动条怎么设置  运⾏结果如下,可以看到3种遍历⽅式的结果完全⼀致。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。