目标检测系列:
目标检测(object detection)系列(一) R-CNN:CNN目标检测的开山之作
目标检测(object detection)系列(二) SPP-Net:让卷积计算可以共享
目标检测(object detection)系列(三) Fast R-CNN:end-to-end的愉快训练
目标检测(object detection)系列(四) Faster R-CNN:有RPN的Fast R-CNN
目标检测(object detection)系列(五) YOLO:目标检测的另一种打开方式
目标检测(object detection)系列(六) SSD:兼顾效率和准确性
目标检测(object detection)系列(七) R-FCN:位置敏感的Faster R-CNN
目标检测(object detection)系列(八) YOLOv2:更好,更快,更强
目标检测(object detection)系列(九) YOLOv3:取百家所长成一家之言
目标检测(object detection)系列(十) FPN:用特征金字塔引入多尺度
目标检测(object detection)系列(十一) RetinaNet:one-stage检测器巅峰之作
目标检测(object detection)系列(十二) CornerNet:anchor free的开端
目标检测(object detection)系列(十三) CenterNet:no Anchor,no NMS
目标检测(object detection)系列(十四)FCOS:用图像分割处理目标检测
目标检测扩展系列:
目标检测(object detection)扩展系列(一) Selective Search:选择性搜索算法
目标检测(object detection)扩展系列(二) OHEM:在线难例挖掘
目标检测(object detection)扩展系列(三) Faster R-CNN,YOLO,SSD,YOLOv2,YOLOv3在损失函数上的区别
前言:用特征金字塔引入多尺度
SSD算法证明了多层分支对于目标检测的有效性,在此之前two-stage的目标检测方法已经优化改进过很多代,但是一直没有加入多尺度的方法。终于在FPN中,two-stage引入了多尺度,并且在SSD多层分支方法的基础上进一步改进,提出了特征金字塔网络。FPN的论文是《Feature Pyramid Networks for Object Detection》。
FPN原理
设计理念
特征金字塔的概念在很早之前就已经有了,比如目标检测还在使用滑动窗的时候,特征金字塔可以改善目标尺度变化的问题。
上图中是四种金字塔相关的操作:
- 图(a)是一个图像金字塔,金字塔的构建只靠缩放图像来完成,然后再不同尺度的图像上分别提取特征,这样一来特征是相互独立的,而且非常耗时,当然它和CNN没有半毛钱关系;
- 图(b)是一个常规的卷积操作,金字塔的每一层就不再是图像了,而是提取得到的特征,然后再最后一层特征上做预测,YOLO和Faster R-CNN都是这样,它只要用到了单层的信息;
- 图(c)和图(b)的前向过程是一致的,区别在于预测的时候,拉取的多层的分支,就有了多尺度的概念,比如SSD;
- 图(d)的自底向上的过程和之前两个也是一致的,但是除此之外,有加入了一个逆过来的自顶向下的过程,并且两个过程间有横向的交互,最后的预测在第二个过程的特征图上进行,这个结构被作者称为特征金字塔网络。 那么下面我们具体说明下。
特征金字塔的优势
SSD是第一个在目标检测任务中引入多层特征图分支结构,而且这个特征金字塔结构在最后预测的时候其实和SSD的多层分支结构是一样的,那么特征金字塔好在哪里呢?
上图是SSD的结构图,首先SSD的选取的分支不够浅,最靠前的一层是VGG-16的conv4-3层,这个都已经到了VGG-16的倒数第二个卷积层了,SSD的6层分支,是SSD在VGG-16后面多加的层拉取出来的,而更靠前的特征图信息被证明对小目标的检测是有用的,但是SDD没有用到。
这样的话,类似SSD的结构直接更向前面的特征图拉取分支行不行?直接这样来做也不太好,因为毕竟靠前的特征图语义信息太少了,所以需要一种可以利用起靠前位置特征图的结构,这个结构就是特征金字塔,相比于SSD的多层分支,特征金字塔结构具有两个不同之处:
- 一个自顶到底的逐层上采样操作
- 横向的1times1 卷积连接
上采样操作从最顶层的特征图逐层反卷积得到,反卷积将顶层特征图的尺寸还原之外,还可以还原顶层提取到的语义信息,这些信息忽略了图像中的背景类,并将前景物体向对应的位置还原。这也是为什么反卷积会在图像分割任务中起作用。但是这种还原一定是存在信息丢失的,就像我们把图像先缩小2倍,然后再放大回来,肯定会变得模糊一样。本来就因为下采样操作在顶层特征图中消失的小物体,不会因为反卷积就被还原回来。所以还需要自底向上的那条路径中的特征图配合,所以FPN对这这两路特征图做了信息融合,1times1 卷积的目的是为了升降通道,能让特征图做对应位置的相加。就像下面这样:
在特征融合之后,预测输出之前,每个层还会在做一次不做下采样的卷积,为了减少上采样层和原特征层融合带来的混淆。
就是这样的结构,让FPN做到了高分辨率、低级语义信息的特征图和低分辨率、高级语义信息的特征图的结合。
说到这里,其实如果把特征金字塔这张图旋转个180度,让它底冲上面、顶冲下面,就会发现,这分明就是一个UNet。╮( ̄▽  ̄)╭
不过这也侧面验证了一点,反卷积和横向连接在语义分割中都起作用,那放到目标检测中也是奏效的。
FPN应用于RPN
FPN要应用到RPN中做区域建议,下面这个图就是个传统的RPN,它只有一层特征图,RPN在这个特征图上用3times3times256 的卷积核,一共用了256个。那么卷积核每滑动一次输出的特征就是1times1times256 ,也就是下图中的256-d,之后该特征出两个分支:
- 第一个分支(reg layer)用4k个1times1times256 的卷积核对256-d进行卷积,最后输出4k个数,这里的4是一个建议框的参数,即(x,y,w,h);
- 第二个分支(cls layer)用2k个1times1times256 的卷积核卷积,最后输出2k个数,这里的2是该区域到底有没有物体,即(object,non-object)的二分类问题。
而FPN要想RPN中添加,就是加层就好了,FPN中RPN的backbone是ResNet,下面是ResNet的网络结构:
ResNet结构从18层到152层,不管层数怎么变,它们下采样的位置和倍数都是一致的,第一个卷积层完成一次下采样,之后每个残差组结束后也下采样2倍,下采样的位置在conv2_x,conv3_x,conv4_x,conv5_x后,文中将它们依次定义为{C_{2},C_{3},C_{4},C_{5}} ,分别对应下采样的倍率为4,8,16,32 ,FPN的金字塔层数也就对应这个四层,其中顶层就是C_{5} 后的输出,底层是C_{2} 的输出。分层的结构有了,剩下的就是怎么选取Anchor,Faster R-CNN选择了9种Anchor,分别是三个比例和三个尺度,都在同一张特征图上,但是在FPN中,采用了和SSD相似的策略,不同的尺度分摊到不同的层上,而不是在一层上产生。所以最后FPN的Anchor尺度为32^2,64^2,128^2,256^2,512^2 ,比例还是1:1,2:1,1:2,所以FPN会产生15种Anchor。
但是问题是,特征图明明只有四层,为啥尺度会有5个?这是因为在最顶层多出来一个s=2的滑动窗,让这个滑动窗产生的感受野又大了2倍,于是就有了512^2 这个尺寸。
FPN每层都有3个Anchor,一共有4层,最后一层滑动两次,假设它是448的输入,那每层的特征图尺寸就是112^2,56^2,28^2,14^2,7^2 ,这样算下来Anchor就已经50K个了,但是FPN的输入图像比这个更大,因为感受野就有最大512,并且论文实验中提到了最短边是800,所以FPN的Anchor超过了200K个。这是一个很大的量级了, YOLOv3有10647个,SDD有8732个,YOLOv2有845个, YOLO总共只有49个类别结果和98个预测框,但是好在FPN是two-stage的结构,框多无所谓,卡阈值筛选就好了,这个筛选的策略和Faster R-CNN相同,最后会剩下200-1000个区域建议框。
FPN应用于Fast R-CNN
注意这个应用是在Fast R-CNN,而不是Faster R-CNN,虽然RPN Fast R-CNN = Faster R-CNN,但是这里认为区域建议和分类、回归预测是两个独立的部分,在Fast R-CNN中,所有筛选剩下的ROI区域建议框要向最后一层特征图映射,但是在FPN中,特征图不止一层,所以具体要向哪一层特征图映射呢?文中给出了一个策略,根据ROI的尺寸,计算要映射的层:
是一个预设值4,假设这个ROI是224^2 ,那么k 就应该等于4,也就是想最顶层那个特征图映射。
但是这里有一个疑问,如果是对Faster R-CNN应用的话,本来这些区域建议不就是通过不同的层生成的,即便经过的筛选也可以去对应到原来的层,那还需不需要弄得这么复杂呢?这个问题在原文中也没给出解释。
映射的问题解决了,就剩下最后的预测类别和回归bbox了,在R-FCN的文章中我们介绍过,如果Faster R-CNN想要ResNet做主干,那么RPN的卷积共享不在最后一层,而是要往前走一个残差组,这是为了让后面的子网络能力不至于太弱。但是在FPN中没有这样用,原因有两点:
- 最后的残差组已经被RPN给占用了;
- 子网络计算量太大会让模型速度很慢。
所以FPN里最后的子网络只有一层,ROI-Pooling将输出控制在7times7 ,接了一层全连接之后直接就预测类别和回归bbox了。这样子操作,简直就是无视R-FCN的存在,R-FCN认为的主要问题,在FPN里就不是个问题。╮( ̄▽  ̄)╭
FPN性能评价
首先上图是6种结构的RPN对比,(a)是只从conv4引出分支,(b)是只从conv5引出分支,(c)是完整了FPN结构。可以看出FPN的效果是很明显的,而且FPN的区域建议超过了200k个。
(d)是一个类似SSD的结构,自底到顶,(e)是没有横向连接,只靠上采样的结构,(f)是没有多层输出,全部在最后一层输出的结构,由于特征图更大,所以archors也就更多,达到750k个。当然他们的结果都不如(c)。
上图是6种结构的Fast R-CNN对比,就是把SS算法的输出替换为FPN的输出,然后把区域建议固定住,比较6种结构,还是(c)的结果最好。
这个对比才是特征金字塔在Faster R-CNN上的对比,这是RPN和Faster R-CNN才是结合起来的。
最后就是个综合实验了,是在Faster R-CNN上应用FPN,主干网络是ResNet-101,在COCO上AP50为59.1,AP为36.2。作为一个two-stage检测器,效果还是可以的,就是不可避免的慢。