论文及代码链接
论文背景及动机
目前3D目标检测方法主要有Voxel-based方法与Point-based两大类。两种方法各个各的优点与不足,主要表现在:基于voxel的方法在点云进行体素化的时候,绝大部分体素都是空的,但是进行3DCNN卷积的时候,空的卷积需要补0,这就会造成很大的显存消耗与计算量,目前这个问题已经通过稀疏卷积得到较好的解决(可以看一下SECOND论文)。其次,Voxel-based方法会带来不可避免的信息损失,这主要由于每个Voxel内的点的数量最后是一个固定值(不然没法通过MLP求Voxel求体素特征了),这就会造成一个情况,如果一个体素内的点的数量超过了限制,就会把多余的点直接过滤掉。而基于point的方法主要限制就在于Grouping操作,也就是经过FPS得到采样点之后的近邻搜索操作大大限制Point-based方法的效率。有研究表明,Point-base方法的55%到80%的时间都花在了Grouping操作上。本文主要针对于Point-based方法效率低下的问题,作者认为始终保有准确的点的位置信息不是影响识别精度的关键,有一定信息损失的体素表示,也可以达到比较好的识别效果。最终该算法达到了一个较好的算法速度与准确性的平衡。
网络整体结构与关键module分析
整体结构
该网络的整体结构如上图所示,Voxel-RCNN算法的前面和SECOND一样,都是体素化、3DCNN卷积、转化成BEV二维特征图,通过2Dbackbone进一步提取特征,通过RPN生成Proposal。SECOND到这儿就结束了,而Voxel-RCNN通过进一步提取Proposal中的特征进行Proposal的refinement,通过两阶段的方法得到更优的检测精度。
关键module分析
文章中是先从Voexl ROI Polling进行分析的,也主要就介绍了这个部分,因为这个文章主要就是为SECOND添加了一个二阶段的Proposal-Refinement环节。本文主要是为了做笔记,还是按照整体网络的顺序来进行介绍。
a) 3D-backbones
3D主干网络采用了与SECOND一样的3DCNN特征提取网络,采用稀疏卷积来减少显存占用与减少计算量,采用了8x的下采样率,具体稀疏卷积如何实现的大家这儿就不细讲了,网上资料挺多,一般通过3D-backbone之后,就生成了BEV特征图了(BEV在Z向进行了压缩,这有个前提,要识别的物体不存在Z向的堆叠)。下面是3D主干网络的结构图:
b) 2D-backbones
2D-backbone就很多了,一般采用Encoder-Decoder结构,也就是先下采样在上采样,然后对应层的特征进行concat,最后通过特征进行分类与Proposal的回归。
c) Voxel ROI Pooling
首先,我们先解释一下Voxel ROI Pooling的实现流程。Voxel ROI Pooling是用来更细化地提取Proposal特征,进行第二阶段地Proposal的refinement。其详细流程如下:首先,将RPN网络提供的proposal划分成GxGxG个网格,然后我们分别计算每个网格点的特征,这个特征应该怎么计算呢,我们寻找网格点周围的K个体素,然后通过Pointnet系列的方法就可以进行网格特征的计算了。(Pointnet本身是计算量不大的,因为主要就是MLP,Point-based方法局限主要在Grouping那块)。得到网格特征之后,继续采用Pointnet进行特征聚合就行。当然,考虑到多尺度的要求,我们可以分别通过4x下采样率的voxel与8x下采样率的voxel来分别计算网格特征,并将不同尺度的网格特征进行concat得到多尺度的网格特征。
了解了整个流程之后,我们就可以按照文章的顺序分别讨论一下Voxel Query与ROI PooLing流程了。
a) Voxel Query
Voxel Query用来寻找proposal中划分的每个网格周围的K个体素,其采用了曼哈顿距离来寻找K个最近的体素,两个voxel之间的曼哈顿距离由体素的索引(i,j,k)决定:
(这块为什么作者要给出了Ball Query与Voxel Query的对比我还得阅读一下别的论文再来进行解释,因为我感觉针对于体素网格,采用Voxel Query来进行近邻搜索是很自然的,也许以前体素化的方法仍然是通过Ball Query进行Grouping???)
b) Voxel ROI Pooling
前面已经讲过了,就是把proposal划分成GxGxG个Grid,分别寻找每个Grid的周围的K个voxel,采用Pointnet进行特征聚合得到每个网格的特征描述,然后再通过pointnet聚合每个网格的特征得到proposal的特征描述,之后就可以通过MLP得到输出了。这块比较简单,不过作者进行了一点改进,就是通过把不太相关的特征进行拆分以减少计算量,具体如下图所示:
每个体素的体素特征应该包括每个体素的坐标以及之前通过卷积聚合的特征,作者认为,这两个部分之间没有关联,可以分开来计算。我们设一共有M个网格,每个网格需要寻找K个最近体素,每个体素的特征维度为(C+3),输出的网格特征维度为C’,那么按原来的方法,其计算量为(O(MxKx(C+3)xC’)),如果我们把坐标与卷积特征分开,那么计算量就是(O(MxKx3xC’)+O(NxC’xC)),其中N是proposal中体素的总数,也就是针对于卷积特征而言,一次性对proposal中的所有体素进行MLP而不是分别对每个Grid周围的K个体素。显然,N一定小于M。
LOSS function
和常见的的2阶段检测方法的损失函数定义类似。
一阶段的损失函数如下:
其包含了分类损失与回归损失两个部分,考虑到正负样本的不均衡,采用了Facol_loss来计算分类损失,对于回归损失,采用了Huber_loss进行优化,保证了Loss不会过大。
二阶段的损失如下:
包含了IOU的分类损失以及正样本的proposal的回归损失。
基于IOU的label定义如下:
属于个人的论文阅读笔记,由于本人尚处于刚学习阶段,水平有限,在所难免会有理解错的地方,望各位大佬指出,谢谢。