1.复制粘贴数据增广

       复制粘贴(copy-paste)数据增广又叫GT增广,是将其余帧的边界框及其内部点云复制到当前帧,以增加当前帧数据丰富性的一种数据增广方法。复制前后的边界框在帧内的坐标不变,需要满足“不与已有边界框重合”的条件,且添加时会删除当前帧在复制边界框内的点。

2.mmdetection3d中物体点云数据库的建立


本节以nuScenes数据集为例,介绍mmdetection3d中复制粘贴数据增广的实现。

  在运行create_data.py文件生成数据集info文件的同时,会调用create_groundtruth_database()函数生成物体点云数据库,对应的文件是nuscenes_dbinfos_train.pklnuscenes_gt_database文件夹(内含名称格式为$token$_$类别名称$_$序号$.bin的点云文件)。

2.1 数据库的建立过程


  create_groundtruth_database()函数会首先建立数据集类(NuScenesDataset),对应的pipeline仅包含LoadPointsFromFile、LoadPointsFromMultiSweeps和LoadAnnotations3D
  随后遍历各帧,将各边界框内部的点取出(对应的函数为box_np_ops.points_in_rbbox()),并平移到以边界框中心为原点的坐标系下,保存为nuscenes_gt_database文件夹下的文件。同时将数据库的info信息保存为nuscenes_dbinfos_train.pkl文件。

2.2 nuscenes_dbinfos_train.pkl文件的内容

nuscenes_dbinfos_train.pkl的存储内容为字典,格式如下:

dbinfos = dict(
	pedestrian = 列表,
	car = 列表,
	...
	human.pedestrian.personal_mobility = 列表
)
即键值对为类别名: 列表的形式,其中各类列表的长度为训练集中各帧含有的该类物体数之和。列表的每一个元素是一个字典,对应某一帧中的一个该类物体。字典格式如下:
info = dict(
	name = 字符串,									# 类别名
	path = 字符串, 	 								# 数据库中对应的bin文件相对路径
	image_idx = 字符串,								# 所属帧的token信息
	gt_idx = 整数,									# 在该帧中的物体序号
	box3d_lidar = 大小为 9 的数值矩阵(ndarray),		# 激光雷达下的9维边界框表达
	num_points_in_gt = 整数,							# 边界框内的激光雷达点数
	difficulty = 0,									# nuScenes数据集无检测难度区分,统一为0
	group_id = 整数,									# 与gt_idx相同
)

3.mmdetection3d中pipeline内的ObjectSample步骤


通常的模型会在默认pipeline的基础上添加ObjectSample步骤(位于LoadAnnotations3D后)。该步骤也属于数据增广。
相关的代码见mmdetection3d/mmdet3d/datasets/pipelines/transforms_3d.py

  • 该步骤会首先初始化DataBaseSampler类的一个实例db_sampler
  • 然后,调用db_sampler.sample_all()方法:
  • 统计当前帧内的各类物体数量n,然后用预设的该类最大采样数量n max减去n ,并乘以预设的、各类统一的采样率r,得到该类实际采样数量m。
  • 当m > 0 m>0m>0时,使用sample_class_v2()函数,从物体点云数据库中采样m mm个物体:
  • 采样规则:初始时随机打乱数据库,在每次采样时从前往后依次取m mm个未取过的物体。若某次刚好将数据库取完或数据库中未取过的物体不足,则将剩下的物体取完,同时重新打乱数据库以备后续采样。
  • 求取真实边界框(含之前类别采样的边界框)和当前类别采样边界框在BEV下投影的角点坐标(对应box_np_ops.center_to_corner_box2d()函数:根据尺寸计算中心在原点、朝向角为0时的角点坐标,然后根据朝向角旋转,最后平移到激光雷达坐标系下),并一起输入到data_augment_utils.box_collision_test()函数中检测原始边界框与采样边界框,以及采样边界框与采样边界框之间是否相交。
  • 若某采样边界框与原始边界框或之前的采样边界框相交,则丢弃之。
  • 读取各采样边界框内的点云,并平移到激光雷达坐标系下。
  • 输出采样边界框及其类别、点云。
  • 最后,将原始点云中处于采样边界框内的点移除(remove_points_in_boxes()),并加入采样边界框内的点。