VoxelNet
我们可以把上面的PointNet或者PointNet++理解为用于图像分类任务中的ResNet等CNN网络。不同的是,ResNet等用来提取图片的特征,而PointNet用来提取3D点云的特征。
今天要解析的是用于3D物体检测任务的VoxelNet,也就是要给检测出来的ROI(Region of Interest)套上一个Bounding box了。
该网络和PointNet的关系,就类似YOLO 和ResNet的关系,一个用于检测位置,一个用来提取特征。
填补了点云特征学习与RPN用于3D目标检测之间的鸿沟。 顾名思义,VoxelNet就是将3D点云数据看做一个个的Voxel(立体块)进行处理。总的来说,VoxelNet的网络结构分为三部分,分别为(1)特征学习网络(2)中部卷积层(3)RPN层,如下图所示。 先给3D空间画网格,然后将每一个点分配到网格中去,每一个网格有不同数量的点,设定点的数量,如果一个网格点数过多,就进行下采样,如果点比较少,就进行上采样,保证每一个有点的网格数目是一致的。
VFE:先用全连接层对点进行提取,3维升维到64或者128.再求所有点的均值mean pooling,得到一个网格所有点的一个整体描述,灰色特征向量为之后的特征向量,将pooling后的特征向量,再和每一个点进行拼接。那么每一个点包含本身的特征和网格整体的特征,每个点就包含了临域的信息。
stacked VFE:重复多次的VFE
我们输出是一个4D的tersor,我们会用3D卷积对4D的tersor进行特征的提取。空号内是x,y,z的分别stride。倒数第2层,将高度和通道进行融合,高度的信息就融合在了128的通道特征里。这样就输出了一个2D的图像+一个chanal,不是真实的图像,但是结构上是。 特征学习网络是VoxelNet中最重要的一个网络,也是创新点最足的一个网络。
可以具体分解为:
(1)Voxel Partition:也就是将空间划分为一个个堆叠的、相同大小的Voxel
(2)Grouping:上面将空间划分为一个个的Voxel了,Grouping这一步的作用就是将3D点云数据装进这一个个的Voxel中,实现分组。
(3)Random Sampling:3D点云的数据量往往都是10万以上的。要是直接在这个数量级上进行特征提取,是非常消耗计算资源的,而且可能会引发检测偏差(bias the detection)。所以作者提出了随机采样方法,将点云数量超过 的Voxel中的点云数量降至 。
(4)Stacked Voxel Feature Encoding:这一步是最重要的一步。作者在这一步提出了VFE层(VFE= Voxel Feature Encoding)。我相信作者提出这个层,应该是受到了PointNet的启发。这里我们给出这个层的实现图,入下图所示。
上图中Voxel有3个点云数据。作者先用一个FCN层(印象中FCN指的是全卷积层,但这里指的是全连接层)提取这3个点云数据的特征,获得3个Point-wise Feature。
因为这个操作是逐点运算的,并没有引入点与点之间的关系,也就是local feature。作者在此基础上引入Element-wise maxpool,获得Locally Aggregated Feature。Locally Aggregated Feature反应了这些点的一个局部关系。
作者将Point-wise Feature和Locally Aggregated Feature进行了简单的堆叠融合,作为下一个VFE层的输入。
这样连续堆叠几次VFE层后,就获得更丰富的特征表示。最后,使用一个Element-wise maxpool获得最后的一个Voxel-wise Feature,也就是图1中的
这里举例,可以看出,首先在整个点云,取一块。分别在zxy的方向取[-3, 1] * [-40, 40] * [0, 70.4] 按照voxel的大小[0.4, 0.2, 0.2]去划分,得到[10400352]个voxel。每个voxel取35个点,每个点7个维度,(x, y, z, r, xi-vx, yi-vy, zi-vz)。通过VFE框架后,VFE2层神经网络,732和32128,VFE框架中,还要和全局的进行拼接,然后经过max pooling。所以最后输出是128voxel的个数,也就是12810400352. 前面我写的voxel采样中,如果一个voxel中没有T个点,就直接补0直到点的数量达到35个,如果超出35个点就随机采样35个点。但是在原论文中的具体实现如下。
原作者为Stacked Voxel Feature Encoding的处理设计了一个高效实现,如下图。
由于每个voxel中包含的点的个数都是不一样的,所以这里作者将点云数据转换成了一种密集的数据结构,使得后面的Stacked Voxel Feature Encoding可以在所有的点和voxel的特征上平行处理。
1、首先创建一个KT7的tensor(voxel input feature buffer)用来存储每个点或者中间的voxel特征数据,其中K是最大的非空voxel数量,T是每个voxel中最大的点数,7是每个点的编码特征。所有的点都是被随机处理的。
2、遍历整个点云数据,如果一个点对应的voxel在voxel coordinate buffer中,并且与之对应的voxel input feature buffer中点的数量少于T,直接将这个点插入Voxel Input Feature Buffer中;否则直接抛弃这个点。如果一个点对应的voxel不在voxel coordinate buffer,需要在voxel coordinate buffer中直接使用这个voxel的坐标初始化这个voxel,并存储这个点到Voxel Input Feature Buffer中。这整个操作都是用哈希表完成,因此时间复杂度都是O(1)。整个Voxel Input Feature Buffer和voxel coordinate buffer的创建只需要遍历一次点云数据就可以,时间复杂度只有O(N),同时为了进一步提高内存和计算资源,对voxel中点的数量少于m数量的voxel直接忽略改voxel的创建。
3、再创建完Voxel Input Feature Buffer和voxel coordinate buffer后Stacked Voxel Feature Encoding就可以直接在点的基础上或者voxel的基础上进行平行计算。再经过VFE模块的concat操作后,就将之前为空的点的特征置0,保证了voxel的特征和点的特征的一致性。最后,使用存储在voxel coordinate buffer的内容恢复出稀疏的4D张量数据,完成后续的中间特征提取和RPN层。
SECOND
论文提出的主要动机为:
(1)考虑到VoxelNet论文在运算过程中运算量较大,且速度不佳。作者引入了稀疏3D卷积去代替VoxelNet中的3D卷积层,提高了检测速度和内存使用;
(2)VoxelNet论文有个比较大的缺点就是在训练过程中,与真实的3D检测框相反方向的预测检测框会有较大的损失函数,从而造成训练过程不好收敛。
顺带着动机,作者又提出了一些其他的创新点:
(1)比如数据增强这块,作者使用了数据库采样的操作;
(2)对于正负样本数量的极度不平衡问题,作者借鉴了RetinaNet中采用的Focal Loss。
这篇文章有关稀疏卷积部分稍微有些难懂,我找遍了全网有关SECOND的解读,大家都跳过了稀疏卷积这块,这确实让人头大。
主要改进在稀疏卷积和角度回归上。在Feature Learning Network没有太多变化。相比于VoxelNet。 稀疏卷积有自己的问题,看上左图的红框,虽然有地方是0,但是这个卷积在边缘,0的位置是有意义的,如果这么做稀疏卷积,就会导致子流形膨胀的问题。导致特征的失真。由于碰到,原来本来没有值的位置,膨胀完就有值了。所以SECOND作者就提出了子流形卷积的概念。
对于稀疏卷积的补充:
PointPillar
motivation其实就是跟着VoxelNet 和 SECOND 的思路做下去。VoxelNet 的方法是直接用体素做3D卷积,SECOND 用了稀疏的卷积,而这篇文章则使用了pillar的方式,很讨巧地转成了2维卷积。从而做到加深网络,增加速度准度。
PointPillar 是 2019 年提出来的模型,相比于之前的点云处理模型,它有 3 个要点:
提出 Pillar 这个概念,将类 PointNets 模型能够以 Pillar 为基础单位学习点云特征 运用标准化的 2D 卷积进行后续处理(这很关键) 满足实时要求,平均检测速度达到了62Hz,最快的版本到达 105 Hz
分为三个步骤:
- 从点云到伪图像的转换
- 2D backbone 网络学习高层次表征
- 检测头进行 3D Box 的检测和回归
顺带提一下backbone是什么,有些自学的人对一些术语可能不清楚。backbone这个单词原意指的是人的脊梁骨,后来引申为支柱,核心的意思。在神经网络中,尤其是CV领域,一般先对图像进行特征提取(常见的有vggnet,resnet,谷歌的inception),这一部分是整个CV任务的根基,因为后续的下游任务都是基于提取出来的图像特征去做文章(比如分类,生成等等)。所以将这一部分网络结构称为backbone十分形象,仿佛是一个人站起来的支柱。
从点云到伪图像的转换
backbone 的处理流程有 3 步:
- 渐进式下采样,形成金字塔特征
- 对应特征上采样到统一的尺寸
- 拼接
PointPillar 中是用 SSD 来做 3D 检测的。 与先验的 box 对比采样的也是 2D 的 IoU。 向上的 height 和 elevation 没有参与 IoU,但添加到了额外的回归任务当中。
代码流程
|