纵目发表的这篇单目3D目标检测论文不同于以往用2D预选框建立3D信息,而是采取直接回归3D信息,这种思路简单又高效,并不需要复杂的前后处理,而且是一种one stage方法,对于实际业务部署也很友好。
来源:杰读源码 微信公众号
论文:SMOKE: Single-Stage Monocular 3D Object Detection via Keypoint Estimation
- 论文:https://arxiv.org/pdf/2002.10111.pdf
- 代码:https://github.com/open-mmlab/mmdetection3d
Introduction
2D目标检测目前已经在精度和速度上都取得了不错的成绩,而3D目标检测由于需要同时估计出目标的位置与姿态,因此相比2D是一个更具挑战的方向。 目前性能最好的3D目标检测还是需要依赖激光雷达的点云或者点云+图像融合,考虑到成本因素,仅依靠单目摄像头的3D目标检测还是非常值得研究的。 本作有以下几个贡献点:
- 提出了一个one-stage单目3D检测方法,思路简答,且end-to-end。
- 3D框8个角点的计算使用了多种方式得到,每种方式都参与了loss的计算,使训练更容易收敛。
- 在KITTI数据集上达到了SOTA。
Detection Problem
为了方便下面对细节详细展开描述,这里先将3D目标检测概述下: 给定一张RGB图像
I
∈
R
W
×
H
×
3
I\in R^{W\times H\times3}
I∈RW×H×3,
W
W
W和
H
H
H分别代表图像的宽高,需要识别出图像中每个目标的分类
C
C
C以及
3
D
3D
3D框
B
B
B的信息,
B
B
B将由下面7个变量代表
(
h
,
w
,
l
,
x
,
y
,
z
,
θ
)
(h,w,l,x,y,z,\theta)
(h,w,l,x,y,z,θ),
(
h
,
w
,
l
)
(h,w,l)
(h,w,l)代表目标的高度、宽度、长度单位为
m
m
m,
(
x
,
y
,
z
)
(x,y,z)
(x,y,z)是目标的中心坐标,单位为
m
m
m,
θ
\theta
θ代表目标框的航向角
y
a
w
yaw
yaw,
r
o
w
row
row和
p
i
t
c
h
pitch
pitch这两个角度在KITTI数据集中为0,此外,还假定相机的内参
K
K
K是已知的。
SMOKE Approach
Backbone
主干网络选择使用DLA-34,其中部分卷积换成了DCN,最后的输出相对于原始图4次下采样的特征图。论文还将BN换成了GN(GroupNorm),因为GN对batch size的大小不那么敏感,且在训练中对噪声更鲁棒。
3D Detection Network
head部分一共两条分支,一条用于检测目标中心点位置同时分类,另一条回归目标的3D信息。
Keypoint Branch
中心点的估计与
C
e
n
t
e
r
N
e
t
CenterNet
CenterNet那片论文的思路相似,不同的是
C
e
n
t
e
r
N
e
t
CenterNet
CenterNet里用的是2D框的中心点,而这里用的是3D框的中心点在图像上的投影点,如下图所示:
Regression Branch
回归分支在每张热图上预测3D信息,3D信息被编码成
τ
=
[
δ
z
,
δ
x
c
,
δ
y
c
,
δ
h
,
δ
w
,
δ
l
,
s
i
n
α
,
c
o
s
α
]
T
\tau=[\delta_z,\delta_{x_c},\delta_{y_c},\delta_h,\delta_w,\delta_l,sin\alpha,cos\alpha]^T
τ=[δz?,δxc??,δyc??,δh?,δw?,δl?,sinα,cosα]T,其中
δ
z
\delta_z
δz?为深度补偿值,
δ
x
\delta_x
δx?和
δ
y
\delta_y
δy?为下采样造成的误差所需的坐标补偿值,
δ
h
\delta_h
δh?,
δ
w
\delta_w
δw?,
δ
l
\delta_l
δl?为尺寸的补偿值,
s
i
n
(
α
)
sin(\alpha)
sin(α)和
c
o
s
(
α
)
cos(\alpha)
cos(α)为计算航向角所需的值。
深度值
z
z
z由预先定义的缩放系数和补偿值计算得到:
z
=
μ
+
δ
z
σ
z
z=\mu+\delta_z\sigma_z
z=μ+δz?σz?
得到了深度值
z
z
z,加上下采样中的补偿值
[
δ
x
c
,
δ
y
c
]
T
[\delta_{x_c},\delta_{y_c}]^T
[δxc??,δyc??]T和特征图上中心点的投影点
[
x
c
,
y
c
]
T
[x_c,y_c]^T
[xc?,yc?]T以及相机内参的逆矩阵
K
3
?
3
?
1
K^{-1}_{3*3}
K3?3?1?,可得目标的3D位置(单位
m
m
m):
[
x
y
z
]
=
K
3
×
3
?
1
[
z
?
(
x
c
+
δ
x
c
)
z
?
(
y
c
+
δ
y
c
)
z
]
\begin{bmatrix} {x}\\ {y}\\ {z}\\ \end{bmatrix}=K^{-1}_{3\times3}\begin{bmatrix} {z\cdot(x_c+\delta_{x_c})}\\ {z\cdot(y_c+\delta_{y_c})}\\ {z}\\ \end{bmatrix}
???xyz????=K3×3?1????z?(xc?+δxc??)z?(yc?+δyc??)z????
在3D框尺寸的计算前,先分析整个数据集得到得到所有目标的均值
[
h
ˉ
]
T
[\bar{h}]^T
[hˉ]T,然后使用预测得到的补偿系数
[
δ
h
,
δ
w
,
δ
l
]
[\delta_h,\delta_w,\delta_l]
[δh?,δw?,δl?]即可获取真正的尺寸:
[
h
w
l
]
=
[
h
ˉ
?
e
δ
h
w
ˉ
?
e
δ
w
l
ˉ
?
e
δ
l
]
\begin{bmatrix} {h}\\ {w}\\ {l}\\ \end{bmatrix}=\begin{bmatrix} {\bar{h}\cdot{e^{\delta_h}}}\\ {\bar{w}\cdot{e^{\delta_w}}}\\ {\bar{l}\cdot{e^{\delta_l}}}\\ \end{bmatrix}
???hwl????=???hˉ?eδh?wˉ?eδw?lˉ?eδl?????
在航向角
θ
\theta
θ的估计中,论文中采取回归角度
α
z
\alpha_z
αz?(如下图),来作为计算航向角
θ
\theta
θ:
θ
=
α
z
+
a
r
c
t
a
n
(
x
z
)
\theta=\alpha_z+arctan(\frac{x}{z})
θ=αz?+arctan(zx?)
最终,可得3D框的8个角点:
B
=
R
θ
[
±
h
/
2
±
w
/
2
±
l
/
2
]
+
[
x
y
z
]
B=R_{\theta}\begin{bmatrix} {\pm{h/2}}\\ {\pm{w/2}}\\ {\pm{l/2}}\\ \end{bmatrix}+\begin{bmatrix} {x}\\ {y}\\ {z}\\ \end{bmatrix}
B=Rθ????±h/2±w/2±l/2????+???xyz???? 其中
R
θ
R_{\theta}
Rθ?代表航向角
θ
\theta
θ转变而来的矩阵,
B
B
B代表8个角点表示的3D框。
Loss Function
Keypoint Classification分支的loss跟
C
e
n
t
e
r
N
e
t
CenterNet
CenterNet中一样,用的是focal loss。
Regression分支的loss计算比较有新意,没有采取直接计算
τ
\tau
τ中8个参数的loss,而是通过在角度、尺寸、坐标位置三种分支下得到的3D框的8个角点去和真值比较计算loss。
总loss:
L
=
L
c
l
s
+
∑
i
=
1
3
L
r
e
g
(
B
^
i
)
L=L_{cls}+\sum_{i=1}^3L_{reg}(\hat{B}_i)
L=Lcls?+i=1∑3?Lreg?(B^i?) 其中
L
c
l
s
L_{cls}
Lcls?代表中心点的分类loss,
i
i
i代表分支,
B
^
i
\hat{B}_i
B^i?代表预测框的8个角点,
L
r
e
g
L_{reg}
Lreg?代表角点回归loss。
bbox3d_yaws = self.bbox_coder.encode(gt_locations, gt_dimensions, orientations, img_metas)
bbox3d_dims = self.bbox_coder.encode(gt_locations, dimensions, gt_orientations, img_metas)
bbox3d_locs = self.bbox_coder.encode(locations, gt_dimensions, gt_orientations, img_metas)
...
...
loss_bbox_oris = self.loss_bbox(pred_bboxes['ori'].corners[reg_inds, ...], target_labels['gt_cors'][reg_inds, ...])
loss_bbox_dims = self.loss_bbox(pred_bboxes['dim'].corners[reg_inds, ...], target_labels['gt_cors'][reg_inds, ...])
loss_bbox_locs = self.loss_bbox(pred_bboxes['loc'].corners[reg_inds, ...], target_labels['gt_cors'][reg_inds, ...])
loss_bbox = loss_bbox_dims + loss_bbox_locs + loss_bbox_oris
Conclusion
纵目发表的这篇单目3D目标检测论文不同于以往用2D预选框建立3D信息,而是采取直接回归3D信息,这种思路简单又高效,并不需要复杂的前后处理,而且是一种one stage方法,对于实际业务部署也很友好。
如果本文对你有帮助,更多内容请关注微信公众号【杰读源码】
|