论文:feature pyramid networks for object detection,论文链接
摘要:本文利用深度卷积网络固有的多尺度金字塔层次构造特征金字塔,并增加边际额外成本。开发了一个具有横向连接的自顶向下体系结构,用于在所有尺度上构建高级语义特征映射。这种结构被称为特征金字塔网络(FPN),在一些应用中显示出作为通用特征提取器的显著改进。在一个基本的Faster R-CNN系统中使用FPN,我们的方法在没有附加条件的COCO检测基准上获得了最先进的单模型结果,超过了所有现有的单模型作品,包括来自COCO 2016挑战赛获胜者的作品。此外,我们的方法可以在GPU上以6fps的速度运行,是一种实用而准确的多尺度目标检测方法。
针对目标检测任务:cocoAP提升2.3个点,pascalAP提升3.8个点
1.特征金字塔结构
几种利用特征的形式:
(a)图像金字塔,即将图像做成不同的scale,然后不同scale的图像生成对应的不同scale的特征。这种方法的缺点在于增加了时间成本。有些算法会在测试时候采用图像金字塔。
(b)像SPP net,Fast RCNN,Faster RCNN是采用这种方式,即仅采用网络最后一层的特征。
(c)像SSD(Single Shot Detector)采用这种多尺度特征融合的方式,没有上采样过程,即从网络不同层抽取不同尺度的特征做预测,这种方式不会增加额外的计算量。作者认为SSD算法中没有用到足够低层的特征(在SSD中,最低层的特征是VGG网络的conv4_3),而在作者看来足够低层的特征对于检测小物体是很有帮助的。
(d)本文作者是采用这种方式,顶层特征通过上采样和低层特征做融合,而且每层都是独立预测的。
上面一个带有skip connection的网络结构在预测的时候是在finest level(自顶向下的最后一层)进行的,简单讲就是经过多次上采样并融合特征到最后一步,拿最后一步生成的特征做预测。而下面一个网络结构和上面的类似,区别在于预测是在每一层中独立进行的。
2.FPN结构
FPN的backbone采用ResNet,大致的算法如图所示:一个自底向上的线路,一个自顶向下的线路,横向连接(lateral connection)。图中放大的区域就是横向连接,这里1*1的卷积核的主要作用是调整不同特征图的输出channel书均为256,因为需要融合,而只用使其有相同的shape才可以实现融合,使得上采样后的其他层特征可以相加,并不改变feature map的尺寸大小。
自底向上:其实就是网络的前向过程。在前向过程中,其实是有要求的,其是按2的整数倍进行选取的。feature map的大小在经过某些层后会改变,而在经过其他一些层的时候不会改变,作者将不改变feature map大小的层归为一个stage,因此每次抽取的特征都是每个stage的最后一个层输出,这样就能构成特征金字塔。在特征选取网络的backbone都是以2的整数倍进行缩放的。
自顶向下:过程中采用上采样(upsampling)进行,其中这里的上采样是一个2倍的上采样,上采样后便保证了高与宽相同,使用横向可以进行相加融合操作。其中这里的2倍上采样是一个简单的邻近的插值算法实现的。而横向连接则是将上采样的结果和自底向上生成的相同大小的feature map进行融合(merge)。在融合之后还会再采用3*3的卷积核对每个融合结果进行卷积,目的是消除上采样的混叠效应(aliasing effect)。并假设生成的feature map结果是P2,P3,P4,P5,和原来自底向上的卷积结果C2,C3,C4,C5一一对应。
具体的结构细节,这里使用b站up制作的一张图:
这里以640 x 640 x 3的输入图像为例。但是原paper中指出,FPN结构是不限制输入尺寸的大小的。由上图可以看出,在融合完得到新的特征图之后还会接上一个3x3的卷积层,也就是进一步的融合,得到了P2,P3,P4,P5,对P5进行一个下采样,得到P6.
需要注意,P6只用于RPN部分,不在Fast-RCNN部分使用。也就是RPN生成proposal的时候会在P2,P3,P4,P5,P6这5个特征图上进行预测。而针对Fast R-CNN中,其只会针对P2,P3,P4,P5这4个特征图中进行预测。
之前在Faster RCNN中,是在预测特征图中通过RPN网络生成得到一系列的proposal,然后会将proposal映射到特征图上,然后再将映射的这部分特征输入到Fast RCNN部分得到最终的预测结果。在FPN结构中,首先我们通过RPN结构在P2-P6中预测proposal,然后会将预测到的proposal映射到P2-P5上,然后再通过Fast RCNN部分得到最终的预测结果。但是,生成的proposal如何确定映射到哪一个特征图上呢?这是有公式计算的,如图
(其中:k0设置为4,wh是RPN预测得到的proposal在原图上的高度和宽度)
由于在RPN网络中生成了多个预测特征层,所以可以在不同的预测特征层上针对不同尺度的目标进行预测。之前的Faster RCNN中只有一个预测特征层,所以那时是在这一个预测特征层中生成不同面积以及不同比例的anchor。在FPN中,不同的预测特征层会针对不同的面积。
比如P2是一个比较底层的预测特征层,那么会保留更多的底层细节信息,也就是比较适合预测比较小型的目标。所以对于该预测特征层,会将面积为32的平方,比例为1:2,1:1,2:1的anchor在此处生成。其他同理64是在P3,128在P4,256在P5,512在P6。
在不同的预测特征层上共用同一个RPN和Fast RCNN和分别在不同的预测特征层上使用不同的RPN和Fast RCNN的效果其实是差不多的。所以共享之后是比较好的,因为减少了比较多的参数。所以在RPN部分在P2-P6使用的是同一个RPN模块;而在Fast RCNN部分P2-P5也是同样的Fast RCNN模块。
具体实现在特征图上预测得到的proposal具体映射在哪里的官方代码实现:
(在torchvision.ops.poolers 中)
class LevelMapper(object): """Determine which FPN level each RoI in a set of RoIs should map to based on the heuristic in the FPN paper. Arguments: k_min (int) k_max (int) canonical_scale (int) canonical_level (int) eps (float) """ def __init__( self, k_min: int, k_max: int, canonical_scale: int = 224, canonical_level: int = 4, eps: float = 1e-6, ): self.k_min = k_min self.k_max = k_max self.s0 = canonical_scale self.lvl0 = canonical_level self.eps = eps def __call__(self, boxlists: List[Tensor]) -> Tensor: """ Arguments: boxlists (list[BoxList]) """ # Compute level ids s = torch.sqrt(torch.cat([box_area(boxlist) for boxlist in boxlists])) # Eqn.(1) in FPN paper target_lvls = torch.floor(self.lvl0 + torch.log2(s / self.s0) + torch.tensor(self.eps, dtype=s.dtype)) target_lvls = torch.clamp(target_lvls, min=self.k_min, max=self.k_max) return (target_lvls.to(torch.int64) - self.k_min).to(torch.int64)
3.FPN+RPN结构
FPN是一个通用的提取特征结构,可以与其他的结构进行融合,正如上诉所示,在Faster RCNN中加入FPN结构会对效果进一步的提升。
回顾整个流程:
- 在Faster R-CNN中,可以输入任意尺寸大小的输入图像,将其输入到FPN结构中,获得多层次融合的特征图P2-P6.也就是将之前RPN结构中的一层特征图预测变成了现在的多层特征图进行预测。所以接下来就是在P2-P6这5层特征图中进行预测anchor,由于定义了anchor的大小为322 ,642,1282,2562,5122 一共5种,而且每个scale层都有3个长宽对比度:1:2,1:1,2:1。所以整个特征金字塔有15种anchor。
- 接着,同样的,需要对这些15种anchor进行筛选,因为他们会有大量的重叠或者是超出边界。另外再基于候选框的RPN结构中的分类cls得分,采用非极大值抑制,IoU设为0.7,(同样是两种损失去优化:分类损失与边界框回归损失),这样再次挑选出剩下最优质的anchor。而PRN结构的边界框回归是为了这些anchor更好的调整位置,配合有效的计算iou值。而此时的剩下的这些经过筛选anchor也就是候选框proposal。与SS算法提供的候选框数量大致相同。
- 接着,需要对这些筛选出来的候选框根据上述提到的公式,根据其本身anchor的大小,投影到不同的特征图P2-P5中(没有P6),从而得到相对应的特征矩阵。(也就是上述说道的,如果生成筛选的anchor面积为32,可能会投影到P2层,这是有数学公式计算的)
- 由于此时已在特征图上获得了对于候选框的特征矩阵,剩下的步骤与Fast R-CNN完全一样了。根据映射关系找到每一个候选区域的特征矩阵。将特征矩阵通过ROI Pooling层统一缩放到7*7的大小,然后将其展平处理,然后通过两个全连接层,得到ROI feature Vector。在ROI feature Vector的基础上,并联两个全连接层。其中的一个全连接层用于目标概率的预测,另外的一个全连接层用来边界框回归参数的预测。
以上是我对Faster R-CNN + FPN的结构处理流程的大致概括,如有错误恳请指教。
4.性能指标
FPN+RPN正负样本的界定和Faster RCNN差不多:如果某个anchor和一个给定的ground truth有最高的IOU或者和任意一个Ground truth的IOU都大于0.7,则是正样本。如果一个anchor和任意一个ground truth的IOU都小于0.3,则为负样本。
看看加入FPN的RPN网络的有效性,如下表Table1。网络这些结果都是基于ResNet-50。评价标准采用AR,AR表示Average Recall,AR右上角的100表示每张图像有100个anchor,AR的右下角s,m,l表示COCO数据集中object的大小分别是小,中,大。feature列的大括号{}表示每层独立预测。
从(a)(b)(c)的对比可以看出FRN的作用确实很明显。另外(a)和(b)的对比可以看出高层特征并非比低一层的特征有效。
(d)表示只有横向连接,而没有自顶向下的过程,也就是仅仅对自底向上(bottom-up)的每一层结果做一个11的横向连接和33的卷积得到最终的结果,有点像Fig1的(b)。从feature列可以看出预测还是分层独立的。作者推测(d)的结果并不好的原因在于在自底向上的不同层之间的semantic gaps比较大。
(e)表示有自顶向下的过程,但是没有横向连接,即向下过程没有融合原来的特征。这样效果也不好的原因在于目标的location特征在经过多次降采样和上采样过程后变得更加不准确。
(f)采用finest level层做预测(参考Fig2的上面那个结构),即经过多次特征上采样和融合到最后一步生成的特征用于预测,主要是证明金字塔分层独立预测的表达能力。显然finest level的效果不如FPN好,原因在于PRN网络是一个窗口大小固定的滑动窗口检测器,因此在金字塔的不同层滑动可以增加其对尺度变化的鲁棒性。另外(f)有更多的anchor,说明增加anchor的数量并不能有效提高准确率。
参考资料:
https://blog.csdn.net/u014380165/article/details/72890275
https://www.bilibili.com/video/BV1dh411U7D9
https://blog.csdn.net/weixin_44751294/article/details/117606017