本文分享单目3D目标检测,CUPNet 模型的论文解读,了解它的设计思路,论文核心观点,模型结构,以及效果和性能。
一、CUPNet简介
CUPNet是基于几何约束和回归方式输出3D框信息,在不依赖dcn的情况下获得了较好的性能。
它也是一款两阶段的单目3d检测器,先回归2D框信息,在ROI区域进一步提取特征,生成3D框信息。
开源地址:https://github.com/SuperMHP/GUPNet
论文地址:Geometry Uncertainty Projection Network for Monocular 3D Object Detection
二、论文核心观点
论文核心观点,主要包括为两点:
- 1、物体高度估计误差,对深度计算有着较大的影响。
- 2、模型训练的稳定性。在模型训练初期,物体高度的预测往往存在较大偏差,也因此导致了深度估算偏差较大。较大误差往往导致网络训练困难,从而影响整体网络性能。
- 3、推断可靠性问题。如果物体的高度预测存在较大偏差,相应计算出的深度值也会存在较大误差。
三、模型框架
CUPNet是一个两阶段的框架,实现单目3d检测的。模型结构如下:
Backbone:DLA34
Neck:DLAUp
第一部分 2D 检测:3个分支
- 分支一 通过输出heatmap,预测所有类别的中心点(默认类别为3)。
- 分支二 预测的2D框中心点的偏移。
- 分支三 预测2D框的size。
第二部分 3D 检测:4个分支
- 分支一 预测偏航角。
- 分支二 预测3D框的size。
- 分支三 预测中心点的深度值,和和其不确定性(深度学习偏差)。
- 分支四 预测2D框中心点与真实的3D投影坐标之间的偏移。
模型结构如下图所示:(基于CenterNet的2D检测+ROI特征提取+基础3D检测头)
整体的模型结构,可分为4步:
- 输入图像,经过主干网络提取特征。
- 基于CenterNet的2D框预测部分,用于输出热力图,信息包括:2D中心点、偏移量、2D框的尺寸。
- 提取出ROI的特征。
- 利用所提取的ROI特征,输入到不同的网络头,以获得物体3D框信息,包括:偏转角度、尺寸、深度值、物体3d框中心在图像投影点的偏移量。
在第四步时,首先估计出3D框除了“深度值”以外的所有参数,然后2D框与3D框的高度将被输入到GUP模块中,提取出最终的depth。
在输入端,图像将缩放到384×1280的大小,然后经过DLA的backbone获得96×320,通道数为64的特征图。随后经过三个简单的网络头输出2d信息
2D 检测3个分支结构代码:
self.heatmap = nn.Sequential(nn.Conv2d(channels[self.first_level], self.head_conv, kernel_size=3, padding=1, bias=True), nn.ReLU(inplace=True), nn.Conv2d(self.head_conv, 3, kernel_size=1, stride=1, padding=0, bias=True)) self.offset_2d = nn.Sequential(nn.Conv2d(channels[self.first_level], self.head_conv, kernel_size=3, padding=1, bias=True), nn.ReLU(inplace=True), nn.Conv2d(self.head_conv, 2, kernel_size=1, stride=1, padding=0, bias=True)) self.size_2d = nn.Sequential(nn.Conv2d(channels[self.first_level], self.head_conv, kernel_size=3, padding=1, bias=True), nn.ReLU(inplace=True), nn.Conv2d(self.head_conv, 2, kernel_size=1, stride=1, padding=0, bias=True))
3D 检测4个分支结构代码:
self.depth = nn.Sequential(nn.Conv2d(channels[self.first_level]+2+self.cls_num, self.head_conv, kernel_size=3, padding=1, bias=True), nn.BatchNorm2d(self.head_conv), nn.ReLU(inplace=True),nn.AdaptiveAvgPool2d(1), nn.Conv2d(self.head_conv, 2, kernel_size=1, stride=1, padding=0, bias=True)) self.offset_3d = nn.Sequential(nn.Conv2d(channels[self.first_level]+2+self.cls_num, self.head_conv, kernel_size=3, padding=1, bias=True), nn.BatchNorm2d(self.head_conv), nn.ReLU(inplace=True),nn.AdaptiveAvgPool2d(1), nn.Conv2d(self.head_conv, 2, kernel_size=1, stride=1, padding=0, bias=True)) self.size_3d = nn.Sequential(nn.Conv2d(channels[self.first_level]+2+self.cls_num, self.head_conv, kernel_size=3, padding=1, bias=True), nn.BatchNorm2d(self.head_conv), nn.ReLU(inplace=True),nn.AdaptiveAvgPool2d(1), nn.Conv2d(self.head_conv, 4, kernel_size=1, stride=1, padding=0, bias=True)) self.heading = nn.Sequential(nn.Conv2d(channels[self.first_level]+2+self.cls_num, self.head_conv, kernel_size=3, padding=1, bias=True), nn.BatchNorm2d(self.head_conv), nn.ReLU(inplace=True),nn.AdaptiveAvgPool2d(1), nn.Conv2d(self.head_conv, 24, kernel_size=1, stride=1, padding=0, bias=True))
四、损失函数
CUPNet 的损失由7部分组成,
2D 框检测损失:3部分
- 分支一 通过输出heatmap,预测所有类别的中心点;使用 Focal Loss 函数。
- 分支二 预测的2D框中心点的偏移;使用 L1 Loss 函数。
- 分支三 预测2D框的size;使用 L1 Loss 函数。
3D Detection损失:4部分
- 分支一 预测偏航角。类别使用交叉熵损失,偏航角使用L1 Loss。
- 分支二 预测3D框的size。长和宽为L1 Loss,权重占2/3,3D 高使用laplacian_aleatoric_uncertainty_loss() 函数,权重占1/3。
- 分支三 预测中心点的深度值,和和其不确定性;使用 laplacian_aleatoric_uncertainty_loss() 函数。
- 分支四 预测2D框中心点与真实的3D投影坐标之间的偏移;使用 L1 Loss 函数。
五、核心观点——3D高度估计误差 引起深度推断误差
在相机投影模型引入几何信息,在估计深度时采用“相似三角形模型”,如下图所示:
depth 是深度值、f是焦距、h_3d是实际物体高度、h_2d是图像中物体的高度。(h_3d、h_2d这种表述方式是打字比较方便,有些编辑公式支持)
在该关系下,depth估计可以转化为先估计h_3d与h_2d,再通过投影的方式得到。如果物体的高度预测存在较大偏差,相应计算出的深度值也会存在较大误差。
下面作者做了实验,由 ±0.1m 3D 高度抖动引起的深度偏移的可视化示例,图中画了一些BEV鸟瞰图的例子来展示误差放大的效果。
该图中,横轴和纵轴的单位均为米,纵轴对应深度方向。 绿色框表示原始投影输出。 蓝色和红色框分别是由 +0.1m和 -0.1m 3D高度偏差引起的移位框。
从图中可以看出,即使高度估计误差只有0.1m,也可能导致4m的深度值偏差。
解决方案:
解决的问题其实是投影模型中的误差放大现象。我们对投影模型的输入加入一个微小的偏置,其输出则会变成原始的投影结果与不确定性项(偏差项)引发的depth误差的和:
详细设计看GUP模块
六、核心内容——GUP模块、HTL模块
6.1 提出GUP模块处理推断可靠性问题
如果只会输出单一的深度值,作者提出Geometry Uncertainty Projection (GUP) 模块,它输出深度值+不确定度,这里的不确定度是用来表征当前深度值的可靠性。
思路流程:预测物体3D高度 → 做映射得到深度值 → 预测偏移量 → 深度值+偏移量得到最终的不确定度
a)预测物体3D高度。作者这里引入了Laplace distribution的假设,也就是假设物体3D高度的预测值是符合拉普拉斯分布的。
拉普拉斯分布可以用两个变量描述,均值和方差。期望3D高度预测值,均值越接近于ground-truth,方差=1最好。方差越趋近于1,表明当前高度预测值越稳定。
通过设计损失函数,让网络朝着我们希望的方向发展:
b)做映射得到深度值,如下式:
将预测出的3D高度带入,即可得到深度值。
c)预测偏移量,给深度值又加了一层不确定度的保障。
d)深度值+偏移量得到最终的不确定度。假设深度值和偏移量是符合拉普拉斯分布,最终的深度估计值可以有如下表示:
希望depth的均值无限接近于真值,其方差无限趋近于1。也就得到了下式的损失函数
6.2 提出HTL模块处理训练稳定性问题
在训练开始时,对h_2d和h_3d的预测都很不准确,会误导整体训练,损害训练表现。
- 作者提出了一个多级task学习策略Hierarchical Task Learning (HTL) ,来进行多任务学习。
- 既然所有模块合在一起训练不稳定,那就分开好了,分级训练,为不同模块指定不同的训练权重,用以控制其在模型训练中的重要性。
七、实验对比与模型效果
在KITTI 测试集上的 3D物体检测,用以粗体突出显示最佳结果
在KITTI 验证集,汽车类别,进行消融实验:
模型效果:
分享完成~