在waymo上测纯视觉baseline(多相机模式),分很多步:
- 处理数据集为kitti格式
- 修改dataloader代码
- 修改模型config
- 修改模型target和loss
- 修改eval pipeline的代码
mmdet3d官网的waymo dataset教程过于简略,处理的结果只能给pointpillar用,而且是旧版的数据集。对初学者的我非常不友好。下面基于mmdet的教程(以下简称教程),简要归纳一下具体流程,并解释如何修改mmdet3d的代码,使得detr3d在处理waymo的道路上,迈出第一步。
事实上,直接手写一遍处理比研究并修改这套代码更快,但是作为初学者,为了熟悉框架,我还是看了一遍
环境配置
update: 环境配置直接使用环境配置中的install_mmdet3d_rc2.sh即可。
waymo dataset v1.3.1或者v1.3.2在github上有配套的waymo-open-dataset工程,里面有tutorial和data frame的protobuf定义,基于tensorflow实现了一些提取数据集的功能。
使用mmdetection(3d)框架跑waymo dataset的时候,需要用到上述工程提取waymo dataset数据,并转换成kitti格式,这样,mmdet3d里的pointpillar就能直接跑dataset了。(detr3d还要做更多)
环境配置挺坑爹的,waymo的pip包有bug。推荐安装版本1.4.7。
(conda virtual env) user@unbuntu: pip install waymo-open-dataset-tf-2-6-0==1.4.7
tf版本根据自己环境的cudatoolkit选,我是cuda11.4。
这个版本有个问题是waymo_open_dataset/camera/ops底下缺少了文件py_camera_model_ops.py,直接在github上找到这个文件复制进安装的目录里即可,一般在anaconda3/env/[your env name]/lib/python3.7/site-package里面。
mmdet按照官方配置来就行了。如果是新环境,推荐先装waymo再装mmdet系列库。
一些坑:
1、装1.4.8会遇到某个依赖库build失败的问题,然后不仅没安装成功,环境还起包冲突了。
2、pip使用–user选项会让包装在~/.local下
dataset quick glance
waymo_format
在waymo官方网站里可以下载数据,按教程整理之后,整个waymo dataset格式如下:
mmdetection3d
├── mmdet3d
├── tools
├── configs
├── data
│ ├── waymo
│ │ ├── waymo_format
│ │ │ ├── training
│ │ │ ├── validation
│ │ │ ├── testing
│ │ │ ├── gt.bin
│ │ ├── kitti_format
│ │ │ ├── ImageSets
每个文件夹如training,底下都有若干个.tfrecord文件,是protobuf格式储存的dataframe。一般来说,一个文件里会有100~200个frame,每个frame包含5个camera image,若干gt_box的label以及lidar的信息如range_image等。具体可见工程里的dataset.proto。gt.bin是gt_box的点云信息,mmdet会重新生成,可以不用管。
ImageSets里放的是train/test/val的dataframe index,教程说,要从他那里下载,但也可以自己处理,之后会说。
kitti_format
按教程使用tools/create_data.py可以从.tfrecord里提取信息,并以kitti格式储存到kitti_format/下,文件结构如下:
│ │ ├── kitti_format
│ │ │ ├── ImageSets
│ │ │ ├── training
│ │ │ │ ├── calib
│ │ │ │ ├── image_0
│ │ │ │ ├── image_1
│ │ │ │ ├── image_2
│ │ │ │ ├── image_3
│ │ │ │ ├── image_4
│ │ │ │ ├── label_0
│ │ │ │ ├── label_1
│ │ │ │ ├── label_2
│ │ │ │ ├── label_3
│ │ │ │ ├── label_4
│ │ │ │ ├── label_all
│ │ │ │ ├── pose
│ │ │ │ ├── velodyne
│ │ │ ├── testing
│ │ │ │ ├── (the same as training)
│ │ │ ├── waymo_gt_database
│ │ │ ├── waymo_infos_trainval.pkl
│ │ │ ├── waymo_infos_train.pkl
│ │ │ ├── waymo_infos_val.pkl
│ │ │ ├── waymo_infos_test.pkl
│ │ │ ├── waymo_dbinfos_train.pkl
整体上看,create_data做3件事:
- 提取tfrecord信息生成training与testing文件夹,不同域的信息放入不同子文件夹里。其中validation也放到training里,这样就对齐了kitti格式。
比如calib储存的是每个frame的相机内外参,以txt方式储存。其命名方式为ABBBCCC.txt,其中A=[0,1,2]即表征[train,val,test],BBB表示第几个tfrecord文件,CCC表示该tfrecord的第几个dataframe。所以一个calib里储存了10多万个.txt文件 - 根据ImageSet,从第一步的结果中抽取每个帧ABBBCCC的信息,汇总入train/test/val/trainval.pkl中。pkl是二进制形式的dict
list,形如[dict(), dict(),…],每个dict对应一个帧的所有信息,如label,image_path等。 - 根据lidar点云数据,生成waymo_gt_database。这文件夹里面有许多.bin文件,代表每个gt_box内的点云。dbinfos_train.pkl则储存了每个gt_boox的label,以及.bin点云文件的path。
一些细节:
tfrecord大概1T多,转换完了之后3T多。
如果image_i的某个frame ABBBCCC里没有gt box,那么label_i里就没有对应的.txt文件
velodyne储存点云信息。
label_0/ABBBCCC.txt的每一行储存了gt box的参数,mmdet原本的代码,格式为:
#type + 是否截断 是否遮挡 alpha? 2Dbbox[l,b,r,t] 3Dbbox[h,w,l,x,y,z,rot]
line = my_type + ' {} {} {} {} {} {} {} {} {} {} {} {} {} {}\n'.format(...)
ImageSet 里的.txt事实上就是所有frame按照ABBBCCC方式命名下标后,下标的集合。所以自己可以直接用os.listdir处理一下得到。
database用于做lidar baseline的数据增强,给场景增添一些本来没有的物体,纯视觉的baseline不用,所以运行时可以把那块代码注释掉。
函数作用与关系一览
tools/create_data.py
def waymo_data_prep:
# from tfrecord extracting
splits = ['training', 'validation', 'testing']
converter = waymo.Waymo2KITTI(...)
converter.convert()
#注意上一步结束后,需要手动生成或者下载ImageSets文件
# Generate waymo infos
kitti.create_waymo_info_file(
out_dir, info_prefix, max_sweeps=max_sweeps, workers=workers)
# gt database
GTDatabaseCreater(
'WaymoDataset',
out_dir,
info_prefix,
f'{
out_dir}/{
info_prefix}_infos_train.pkl',
relative_path=False,
with_mask=False,
num_worker=workers).create()
tools\data_converter\waymo_converter.py
含有Waymo2KITTI converter,下面是没整理的函数笔记,重点是type名称的转换。注意到代码里的lidar_list似乎表示的是camera_list,感觉他写错了。这里面也有很多label信息没提取出来,如果之后要用的话还得修改这部分。
class waymo2kitti:
def init:
lidar有五个,仍然是没有back。但是我怎么感觉这是cam的name??
self.lidar_list = [
'_FRONT', '_FRONT_RIGHT', '_FRONT_LEFT', '_SIDE_RIGHT',
'_SIDE_LEFT'
]
label有5个:[ 'UNKNOWN', 'VEHICLE', 'PEDESTRIAN', 'SIGN', 'CYCLIST']
转成kitti对应的是['DontCare','Car','Pedestrian','Sign', 'Cyclist']
这个大小写和label名称应该挺重要的