本文介绍一篇单目3D物体检测模型:CaDDN,论文收录于 CVPR2021。 单目3D物体检测的主要挑战在于准确预测物体深度,由于缺乏直接的距离测量,因此必须根据物体和场景线索来推断物体深度。过去许多方法试图直接估计深度来辅助3D检测,但由于深度预测不准确,性能都比较有限。
本文提出了分类深度分布网络(CaDDN),通过预测每个像素的分类深度分布,将丰富的上下文特征信息投影到3D空间中合适的深度区间。然后,本文使用计算效率高的鸟瞰图投影和单阶段检测器来产生最终的输出检测。本文将CaDDN设计为一种完全可微的端到端方法,用于联合深度估计和目标检测。
论文链接:https://arxiv.org/abs/2103.01100
项目链接(推荐使用OpenPCDet来复现CaDDN,代码结构简洁,原作者模型使用PyTorch版本较低,搭配环境不方便):https://github.com/open-mmlab/OpenPCDet
1. Introduction
首先是论文引言部分,这里简单介绍下。3D感知任务中,基于激光雷达和双目相机的检测算法效果更好;但是单目3D检测效果要落后于上面两种方法,是因为场景信息投影到图像平面上时会丢失深度信息。
为了解决这种问题,一种方法是单独训练一个深度估计网络,然后深度估计结果在3D检测中被直接使用,网络会过度相信深度估计结果。对深度估计的过度相信在远距离情况下尤其是一个问题,导致定位不佳。此外,在训练阶段,深度估计网络与3D检测网络分开训练,也会阻止深度估计无法被检测任务优化。 另一种方法是图像数据中的深度信息可以通过将特征从图像转换到三维空间,最终转换到鸟瞰(BEV)图来隐式学习。然而,隐式方法往往会受到 feature smearing 的影响,相似的特征可存在在投影空间中的多个位置,增加了在场景中定位物体的难度。
为了解决这些问题,本文提出了一种单目3D检测方法 CaDDN,该方法通过学习分类深度分布来实现精确的 3D 检测。通过利用概率深度估计,CaDDN 能够以端到端的方式从图像生成高质量的鸟瞰特征表示。
下图是有无深度分布监督和有深度分布监督的鸟瞰图特征,可以看到有深度分布监督可以编码更多有意义的深度置信度,物体检测也能更准确。
2. Methodology
CaDDN通过将图像特征投影到3D空间学习生成BEV特征。然后,使用高效的BEV检测网络,利用丰富的BEV特征来进行3D检测,整个网络结构如下图所示:网络输入是一张图片,使用估计的分类深度分布网络构造锥体特征网格 G G G,然后利用已知的相机标定参数将锥体特征网格变换为体素网格 V V V,然后压缩为鸟瞰特征网格 B B B,最后使用一个3D检测器进行检测。
下面是OpenPCDet中提供的CaDDN模型的配置参数:
- Lidar点云范围为:[2, -30.08, -3.0, 46.8, 30.08, 1.0],对应 X 、 Y 、 Z X、Y、Z X、Y、Z 轴距离范围;
- voxel size 为: [0.16, 0.16, 0.16],最终生成的 Voxel Grid 尺寸为: ( 280 , 376 , 25 ) (280,376,25) (280,376,25);
- 深度图下采样系数为4;
- 将深度划分为了80个区间,实际模型输出为81类,最后一类表示估计深度超出46.8m;
- 深度估计网络使用的预训练好的deeplabv3权重;
- BEV主干网和PointPillars结构相似,层数增加到了10层,检测头和PointPillars检测头一样;
CLASS_NAMES: ['Car', 'Pedestrian', 'Cyclist']
DATA_CONFIG:
_BASE_CONFIG_: cfgs/dataset_configs/kitti_dataset.yaml
POINT_CLOUD_RANGE: [2, -30.08, -3.0, 46.8, 30.08, 1.0]
GET_ITEM_LIST: ["images", "depth_maps", "calib_matricies", "gt_boxes2d"]
DATA_PROCESSOR:
- NAME: mask_points_and_boxes_outside_range
REMOVE_OUTSIDE_BOXES: True
- NAME: calculate_grid_size
VOXEL_SIZE: [0.16, 0.16, 0.16]
- NAME: downsample_depth_map
DOWNSAMPLE_FACTOR: 4
DATA_AUGMENTOR:
DISABLE_AUG_LIST: ['placeholder']
AUG_CONFIG_LIST:
- NAME: random_image_flip
ALONG_AXIS_LIST: ['horizontal']
MODEL:
NAME: CaDDN
VFE:
NAME: ImageVFE
FFN:
NAME: DepthFFN
DDN:
NAME: DDNDeepLabV3
BACKBONE_NAME: ResNet101
ARGS: {
"feat_extract_layer": "layer1",
"pretrained_path": "../checkpoints/deeplabv3_resnet101_coco-586e9e4e.pth"
}
CHANNEL_REDUCE: {
"in_channels": 256,
"out_channels": 64,
"kernel_size": 1,
"stride": 1,
"bias": False
}
DISCRETIZE: {
"mode": LID,
"num_bins": 80,
"depth_min": 2.0,
"depth_max": 46.8
}
LOSS:
NAME: DDNLoss
ARGS: {
'weight': 3.0,
'alpha': 0.25,
'gamma': 2.0,
'fg_weight': 13,
'bg_weight': 1
}
F2V:
NAME: FrustumToVoxel
SAMPLER: {
"mode": "bilinear",
"padding_mode": "zeros"
}
MAP_TO_BEV:
NAME: Conv2DCollapse
NUM_BEV_FEATURES: 64
ARGS: {
"kernel_size": 1,
"stride": 1,
"bias": False
}
BACKBONE_2D:
NAME: BaseBEVBackbone
LAYER_NUMS: [10, 10, 10]
LAYER_STRIDES: [2, 2, 2]
NUM_FILTERS: [64, 128, 256]
UPSAMPLE_STRIDES: [1, 2, 4]
NUM_UPSAMPLE_FILTERS: [128, 128, 128]
DENSE_HEAD:
NAME: AnchorHeadSingle
CLASS_AGNOSTIC: False
USE_DIRECTION_CLASSIFIER: True
DIR_OFFSET: 0.78539
DIR_LIMIT_OFFSET: 0.0
NUM_DIR_BINS: 2
ANCHOR_GENERATOR_CONFIG: [
{
'class_name': 'Car',
'anchor_sizes': [[3.9, 1.6, 1.56]],
'anchor_rotations': [0, 1.57],
'anchor_bottom_heights': [-1.78],
'align_center': False,
'feature_map_stride': 2,
'matched_threshold': 0.6,
'unmatched_threshold': 0.45
},
{
'class_name': 'Pedestrian',
'anchor_sizes': [[0.8, 0.6, 1.73]],
'anchor_rotations': [0, 1.57],
'anchor_bottom_heights': [-0.6],
'align_center': False,
'feature_map_stride': 2,
'matched_threshold': 0.5,
'unmatched_threshold': 0.35
},
{
'class_name': 'Cyclist',
'anchor_sizes': [[1.76, 0.6, 1.73]],
'anchor_rotations': [0, 1.57],
'anchor_bottom_heights': [-0.6],
'align_center': False,
'feature_map_stride': 2,
'matched_threshold': 0.5,
'unmatched_threshold': 0.35
}
]
TARGET_ASSIGNER_CONFIG:
NAME: AxisAlignedTargetAssigner
POS_FRACTION: -1.0
SAMPLE_SIZE: 512
NORM_BY_NUM_EXAMPLES: False
MATCH_HEIGHT: False
BOX_CODER: ResidualCoder
LOSS_CONFIG:
LOSS_WEIGHTS: {
'cls_weight': 1.0,
'loc_weight': 2.0,
'dir_weight': 0.2,
'code_weights': [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
}
POST_PROCESSING:
RECALL_THRESH_LIST: [0.3, 0.5, 0.7]
SCORE_THRESH: 0.1
OUTPUT_RAW_SCORE: False
EVAL_METRIC: kitti
NMS_CONFIG:
MULTI_CLASSES_NMS: False
NMS_TYPE: nms_gpu
NMS_THRESH: 0.01
NMS_PRE_MAXSIZE: 4096
NMS_POST_MAXSIZE: 500
OPTIMIZATION:
BATCH_SIZE_PER_GPU: 4
NUM_EPOCHS: 80
OPTIMIZER: adam_onecycle
LR: 0.001
WEIGHT_DECAY: 0.01
MOMENTUM: 0.9
MOMS: [0.95, 0.85]
PCT_START: 0.4
DIV_FACTOR: 10
DECAY_STEP_LIST: [35, 45]
LR_DECAY: 0.1
LR_CLIP: 0.0000001
LR_WARMUP: False
WARMUP_EPOCH: 1
GRAD_NORM_CLIP: 10
3. Experimental Results
下面来看本文的消融实验,下面表格是作者在KITTI 验证集上做的实验,使用的指标是 A P ∣ R 40 AP|_{R40} AP∣R40。可以看到:
- 使用深度分布预测 D D D 分别可以提高 1.5、0.77、0.46个点左右;
- 使用深度分布监督 L d e p t h L_{depth} Ldepth 可以大幅提高检测性能(分别是提高10.4、7.6、6.54个点),深度分布监督对提高模型性能很有帮助,很好理解,深度估计越准,检测也越准;
- 本文提出的LID离散化方法也是对提升模型性能也很有帮助;
下面一个消融实验,可以看到:
- 实验4表示 同时训练目标检测和深度估计对最终检测性能有较大的提高;
- 实验5表示使用所有的深度分布而不是ont-hot分布对最终检测性能也有很大提高;