论文地址:PointPillars: Fast Encoders for Object Detection from Point Clouds
Github 地址:PointPillars: Fast Encoders for Object Detection from Point Clouds
1. 解决了什么问题?
点云目标检测是自动驾驶领域的一个重要方向。自动驾驶要实时地检测和跟踪运动目标,如车辆、行人、骑车人。为此,自动驾驶车辆需要有多种传感器,尤其是激光雷达。近十年,CV 通过深度学习算法取得了巨大成绩,人们也试图将深度学习算法应用到点云的目标检测任务。但 2D 图像和 LiDAR 点云模态有两处关键差异:
- 点云是稀疏的表征,而图像是密集的。
- 点云是 3D 的,而图像是 2D 的。
这使得图像的卷积算法不能简单地直接套用在点云的目标检测上。
早期的方法要么关注在 3D 卷积,要么关注在点云到图像的投影。最近的方法则尝试从 BEV 看待 LiDAR 点云。BEV 有多个优点:
- BEV 保留了物体的大小。
- BEV 里的卷积运算保留了局部范围信息。
在图像视角进行卷积操作,会造成深度信息不明确。
但是,BEV 会非常稀疏,直接应用卷积网络会使效率很低。常用方法是将地平面切分为规则的网格,例如
10
×
10
c
m
10\times 10 cm
10×10cm,然后对每个网格内的点做手工特征编码。这类方法不是最优的,因为 hard-coded 特征提取的方法泛化性比较差。VoxelNet 是第一个用 PointNet 做 LiDAR 点云目标检测的工作。它将空间切分成体素,对每个体素应用 PointNet,后面用一组 3D 卷积层合并
z
z
z轴的信息,然后是 2D 卷积检测 head。VoxelNet 效果还行,但是推理速度太慢了,只有
4.4
H
z
4.4 Hz
4.4Hz。SECOND 提高了 VoxelNet 的推理速度,但是 3D 卷积仍是一个瓶颈。
2. 提出了什么方法?
本文研究了如何将点云编码成适合下游检测的格式。PointPillars 是一个端到端学习的 3D 目标检测方法,只使用 2D 卷积层。它使用一个新的编码网络,基于 PointNets 学习柱状(pillar)点云表征,再预测目标的 3D 框。首先,PointPillars 学习特征(而不是依赖固定的编码),能利用点云的全部信息。此外,它在 pillars 上操作(而不是 voxels),就无需手动调整垂直方向的 bins。最后,由于所有的核心操作都是 2D 卷积,pillars 速度快,在 GPU 上效率很高。学习特征的另一好处就是 PointPillar 无需手动调节,即可使用不同的点云配置,如多个 LiDAR 线扫或 RADAR 点云。
PointPillars 将点云作为输入,预测车辆、行人和骑车人的 3D 框。如下图所示,它包括三个阶段:
- 特征编码网络,将点云转换为稀疏的 pseudo-image;
- 2D 卷积网络从 pseudo-image 提取高层级表征;
- 检测 head 检测并回归 3D 框。
2.1 Pointcloud to Pseudo-Image
为了使用 2D 卷积网络,首先要将点云转换为稀疏的 pseudo-image。
- 用 l l l表示点云的一个点,其坐标为 x , y , z x,y,z x,y,z。首先,将点云离散为 x − y x-y x−y平面均匀分布的网格,得到一个 pillars 集合 P , ∣ P ∣ = B \mathcal{P},|\mathcal{P}|=B P,∣P∣=B。Pillar 是一个体素,在 z z z方向上其空间范围无限。所以无需额外的超参数来控制 z z z轴的 bins。
- 原始 LiDAR 的点是 4 4 4维的, ( x , y , z , r ) (x,y,z,r) (x,y,z,r)中 r r r是反射强度。作者对点云做了增强,每个 pillar 里的点用 r , x c , y c , z c , x p , y p r, x_c, y_c, z_c, x_p, y_p r,xc,yc,zc,xp,yp修饰, ( x c , y c , z c ) (x_c,y_c,z_c) (xc,yc,zc)表示某点到 pillar 中所有点的算术平均值的距离, ( x p , y p ) (x_p,y_p) (xp,yp)表示该点到 pillar 坐标的偏移。修饰点 l ^ \hat{l} l^就有了 D = 9 D=9 D=9个维度, ( x , y , z , r , x c , y c , z c , x p , y p ) (x,y,z,r,x_c,y_c,z_c,x_p,y_p) (x,y,z,r,xc,yc,zc,xp,yp)。
- 由于点云的稀疏性质,pillars 集合中大多数都是空的,非空的 pillars 一般也只有少量的点。例如,在 0.1 6 2 m 2 0.16^2 m^2 0.162m2的 bins 中,KITTI 使用的 HDL-64E Velodyne LiDAR 采集的点云中有 6 k − 9 k 6k-9k 6k−9k个非空 pillars,稀疏度为 ∼ 97 % \sim 97\% ∼97%。对每个样本非空 pillars 的个数( P = 30000 P=30000 P=30000)以及每个 pillar 的点数( N = 20 N=20 N=20)施加一个约束,得到一个大小是 ( D , P , N ) (D,P,N) (D,P,N)的密集张量。如果一个 pillar 内的点数 > 20 > 20 >20,则随机采样其中的数据。相反,如果一个 pillar 内的点数 < 20 < 20 <20,则使用 0 0 0值做 padding。
- 然后,我们使用一个简化版的 PointNet。对每个点使用一个线性层( 1 × 1 1\times 1 1×1卷积)和 BN、ReLU,生成一个形状为 ( C , P , N ) (C,P,N) (C,P,N)的张量。之后,在通道维度使用 MaxPooling \text{MaxPooling} MaxPooling操作,将每个 pillar 中最大响应的点提取出,得到形状为 ( C , P ) (C,P) (C,P)的的输出张量。
- 编码后,将该特征 scatter 回到原来的 pillar 位置,创建大小是 ( C , H , W ) (C,H,W) (C,H,W)的 pseudo-image, H , W H,W H,W分别是高度和宽度。记录每个 pillar 对应的 x , y x,y x,y坐标,也就是下图的 pillar index,维度是 P × 2 P\times 2 P×2, P P P是 pillar 个数, 2 2 2是 x , y x,y x,y对应的坐标。在学到的特征上构建 pseudo-image 时,需要根据 pillar index 将 pillar 填充到对应的 pseudo-image 上。用 pillars 而非体素使我们可以摆脱 3D 卷积。
( D , P , N ) → ( C , P , N ) → ( C , P ) + Pillar_Index → ( C , H , W ) (D,P,N)\rightarrow (C,P,N)\rightarrow (C,P) + \text{ Pillar\_Index }\rightarrow (C,H,W) (D,P,N)→(C,P,N)→(C,P)+ Pillar_Index →(C,H,W)
2.2 Backbone
PointPillars 结构如下图所示,包括一个 Pillar 特征网络、主干网络、SSD 检测 head。原始点云转换为 stacked pillar 张量和 pillar index 张量。编码器基于 stacked pillars 学习一组特征,再 scatter 回到 2D pseudo-image 做卷积计算。检测 head 使用主干网络预测的特征,预测目标的 3D 框。
主干网络包括两个子网络,一个 top-down 做下采样,输出空间分辨率递减的特征;另一个对 top-down 输出的特征做上采样,concat 到一起后输出特征。
Top-down 主干用一系列模块表示,
Block
(
S
,
L
,
F
)
\text{Block}(S,L,F)
Block(S,L,F)。每个模块的步长是相对于输入 pseudo-image 的
S
S
S。每个模块包含
L
L
L个输出通道为
F
F
F的
3
×
3
3\times 3
3×3卷积层,每个卷积层后面跟着一个 BN 和 ReLU。
每个 top-down 模块的特征会用上采样和 concat 操作做结合。首先使用一个
F
F
F通道的 2D 转置卷积来上采样特征
Up
(
S
i
n
,
S
o
u
t
,
F
)
\text{Up}(S_{in},S_{out},F)
Up(Sin,Sout,F),由初始步长
S
i
n
S_{in}
Sin上采样到最终步长
S
o
u
t
S_{out}
Sout。然后对该上采样特征使用 BN 和 ReLU。将不同步长的所有特征 concat 起来,得到最终的特征输出。
2.3 Detection Head
使用 SSD 做 3D 目标检测。使用 2D IoU 来匹配先验框和 ground-truth 框。匹配时不考虑边框的高度和海拔。回归时,高度作为额外的回归值。
2.4 Network
所有的权重都用均匀分布做随机初始化。
编码网络的输出特征通道为
C
=
64
C=64
C=64。车辆和行人/骑车人的主干是一样的,除了在第一个模块的步长(对于车辆
S
=
2
S=2
S=2;对于行人/骑车人,
S
=
1
S=1
S=1)。
- 下采样包括三个模块: Block1 ( S , 4 , C ) \text{Block1}(S,4,C) Block1(S,4,C)、 Block2 ( 2 S , 6 , 2 C ) \text{Block2}(2S,6,2C) Block2(2S,6,2C)、 Block3 ( 4 S , 6 , 4 C ) \text{Block3}(4S,6,4C) Block3(4S,6,4C)。
- 上采样包括三个模块: Up1 ( S , S , 2 C ) \text{Up1}(S,S,2C) Up1(S,S,2C)、 Up2 ( 2 S , S , 2 C ) \text{Up2}(2S,S,2C) Up2(2S,S,2C)、 Up3 ( 4 S , S , 2 C ) \text{Up3}(4S,S,2C) Up3(4S,S,2C)。
然后,将它们的特征 concat 起来,得到 6 C 6C 6C维度的特征输入检测 head。
2.5 Loss
使用了与 SECOND 相同的损失函数。用
(
x
,
y
,
z
,
w
,
l
,
h
,
θ
)
(x,y,z,w,l,h,\theta)
(x,y,z,w,l,h,θ)表示每个 Ground-truth 框和 anchors。Ground-truth 与 anchors 定位回归的残差是:
Δ
x
=
x
g
t
−
x
a
d
a
,
Δ
y
=
y
g
t
−
y
a
d
a
,
Δ
z
=
z
g
t
−
z
a
h
a
\Delta{x}=\frac{x^{gt}-x^a}{d^a},\Delta{y}=\frac{y^{gt}-y^a}{d^a},\Delta{z}=\frac{z^{gt}-z^a}{h^a}
Δx=daxgt−xa,Δy=daygt−ya,Δz=hazgt−za
Δ
w
=
log
w
g
t
w
a
,
Δ
l
=
log
l
g
t
l
a
,
Δ
h
=
log
h
g
t
h
a
\Delta{w}=\log\frac{w^{gt}}{w^a},\Delta{l}=\log\frac{l^{gt}}{l^a},\Delta{h}=\log\frac{h^{gt}}{h^a}
Δw=logwawgt,Δl=loglalgt,Δh=loghahgt
Δ
θ
=
sin
(
θ
g
t
−
θ
a
)
\Delta{\theta}=\sin(\theta^{gt}-\theta^a)
Δθ=sin(θgt−θa)
其中
x
g
t
x^{gt}
xgt和
x
a
x^{a}
xa分别是 ground-truth 和 anchors,
d
a
=
(
w
a
)
2
+
(
l
a
)
2
d^a=\sqrt{(w^a)^2 + (l^a)^2}
da=(wa)2+(la)2。定位损失如下:
L
l
o
c
=
∑
b
∈
(
x
,
y
,
z
,
w
,
l
,
h
,
θ
)
SmoothL1
(
Δ
b
)
\mathcal{L}_{loc}=\sum_{b\in(x,y,z,w,l,h,\theta)}\text{SmoothL1}(\Delta{b})
Lloc=b∈(x,y,z,w,l,h,θ)∑SmoothL1(Δb)
由于定位损失无法区分翻转物体,用
Softmax
\text{Softmax}
Softmax分类损失
L
d
i
r
\mathcal{L}_{dir}
Ldir学习物体的离散朝向:
L
d
i
r
=
−
α
a
(
1
−
p
a
)
γ
log
p
a
\mathcal{L}_{dir}=-\alpha_{a}(1-p^a)^\gamma\log{p^a}
Ldir=−αa(1−pa)γlogpa
p
a
p^a
pa是 anchor 的类别概率,默认
α
=
0.25
,
γ
=
2
\alpha=0.25, \gamma=2
α=0.25,γ=2。总损失如下:
L
=
1
N
p
o
s
(
β
l
o
c
L
l
o
c
+
β
c
l
s
L
c
l
s
+
β
d
i
r
L
d
i
r
)
\mathcal{L}=\frac{1}{N_{pos}}(\beta_{loc}\mathcal{L}_{loc}+\beta_{cls}\mathcal{L}_{cls}+\beta_{dir}\mathcal{L}_{dir})
L=Npos1(βlocLloc+βclsLcls+βdirLdir)
N
p
o
s
N_{pos}
Npos是正 anchors 的个数,
β
l
o
c
=
2
,
β
c
l
s
=
1
,
β
d
i
r
=
0.2
\beta_{loc}=2,\beta_{cls}=1, \beta_{dir}=0.2
βloc=2,βcls=1,βdir=0.2。
损失函数用 Adam 优化,初始学习率为
2
∗
1
0
−
4
2\ast 10^{-4}
2∗10−4,每
15
15
15个 epochs 乘以
0.8
0.8
0.8衰减。
2.6 空间分辨率
不同大小的 bin 能起到平衡速度和精度的作用。Pillars 越小,定位就越精细,特征就越丰富。而 pillars 较大,非空 pillars 就越少,则编码速度就越快,pseudo-image 就越小(CNN 主干就越快)。下图展示了 KITTI 验证集上,车辆、行人、骑车人的 BEV 检测表现(mAP)和速度(Hz)。蓝圈表示只用了 LiDAR 方法,红方块表示使用了 LiDAR 和相机的融合方法。PointPillars 使用了不同的 pillar 大小
{
0.1
2
2
,
0.1
6
2
,
0.
2
2
,
0.2
4
2
,
0.2
8
2
}
m
2
\left\{0.12^2, 0.16^2, 0.2^2, 0.24^2, 0.28^2\right\} m^2
{0.122,0.162,0.22,0.242,0.282}m2 ,pillar 个数分别是
16000
,
12000
,
12000
,
8000
,
8000
16000, 12000, 12000, 8000, 8000
16000,12000,12000,8000,8000。可以看到,bin 越大,网络速度就越快。下降主要出现在行人和骑车人类别,而车辆的表现比较稳定。
2.7 Per Box Data Augmentation
VoxelNet 和 SECOND 对每个框做了增广,但是,在本文实验中,边框增广越少越好。当对行人类别做增广,检测表现下降得非常明显。作者认为,引入 ground-truth 采样降低了边框增广的必要性。
2.8 Point Decorations
编码网络的输入为原始激光雷达的: x , y , z x,y,z x,y,z、反射率 r r r,pillar 里面各点距离聚类中心的偏移值 ( Δ x c , Δ y c , Δ z c ) (\Delta{x_c},\Delta{y_c},\Delta{z_c}) (Δxc,Δyc,Δzc),以及所有到 pillar 中心的距离 ( Δ x p , Δ y p ) (\Delta{x_p},\Delta{y_p}) (Δxp,Δyp)。 ( Δ x p , Δ y p ) (\Delta{x_p},\Delta{y_p}) (Δxp,Δyp)在每个 pillar 的局部坐标系编码点的坐标。它们独立于其它的点。作者没有涵盖 z z z方向的偏移,因为它对所有的点都是常数。聚类偏移值 ( Δ x c , Δ y c , Δ z c ) (\Delta{x_c},\Delta{y_c},\Delta{z_c}) (Δxc,Δyc,Δzc)提供了另一种标准化点的局部 context 的方式,它要计算出一个全局统计量,建立各点之间的关系。数据增强和 pillar 点的下采样会改变 pillar 的聚类中心。当只用聚类偏移而不用 pillar 偏移训练时,这会造成更大的差异。