为了方便查阅,在摘要之前先列出一下本文用到的名词目录。
CNN - Convolution Neural Network 卷积神经网络
RCNN - Region-CNN
SS - Selective Search 选择性搜索
ROI - Region Of Interst 感兴趣区域
RPN - Region Proposal Network 区域推荐网络
bbox - bounding box 边界框
SPP - Spatial Pyramid Pooling 空间金字塔池化
GT - Ground Truth 检测框的真实位置,大小,形状
NMS - Non Maximum Suppression 非极大抑制
本文重点介绍Faster RCNN的结构以及其中的一些注意事项。重点以偏重直观理解为主,不求严谨。对于Faster RCNN网络的训练方法并未在本文中提及。对于Faster RCNN的总体介绍放在了文章的后面,前面先介绍了一些具体组件,如果读者不习惯这样的顺序可以先大致了解下本文的最后一章,然后再从前到后的阅读本文。Fast RCNN提出了将SS找出的ROI映射到CNN网络提取出的feature map上的方法(ROI projection)。而Faster RCNN 也继承了这一思路,并且在此基础上参考了SPP-Net中的思想对ROI的提取方式做了改进。本文先简要介绍了ROI projection及其“配套”操作ROIpooling,然后介绍了Faster RCNN对Fast RCNN的改进——RPN的引入。如果你已经了解过Fast RCNN,那么请直接跳到RPN部分开始阅读。如果本文中有理解不对或者不到位的地方欢迎指正!阅读本文之前需要对RCNN (RCNN 论文重点摘要简记) 的基本内容进行了解,不需要完全理解,只需要明白大概的技术路线 。
这里先介绍一下Faster RCNN中用到的一个很重要的组件,之所以放到开头,是因为这个组件继承自SPP-Net和Fast RCNN,本文作为一个前提知识来预先说明。
ROI(感兴趣区域)的命名非常巧妙,如果将目标检测任务比作零件加工任务的话,ROI就相当于铸造生产的零件毛坯,虽然和成品相差很大,但至少为后续的车削精加工过程减少了许多需要的进给量。对于目标检测,对ROI进行正例判定和bbox回归就相当于这个精加工的过程,如果没有ROI的话,我们就需要使用类似划窗的方式尽量穷举所有可能的边框,再对所有的边框进行正例判定和bbox回归。
实际上我们通常对于ROI精度的要求并没有那么高,我只要求在这一步提取“感兴趣”的区域,并不要求这个区域内绝对包含目标物体或者要求这个区域形状完全正好包裹住目标物体,这些精细的操作可以留给后面的环节进行。
在RCNN,提取ROI的方式是SS,这点在Fast RCNN中也有继承(不过在Faster RCNN中移除了,后文中会详细说明)RCNN会用一个CNN+全连接的网络对所有的ROI区域进行特征提取,当然ROI在输入到网络前会进行Resize,不过在这篇文章中这不重要。根据提取的特征,我们可以对这片ROI区域进行判定和推理,判定是用逻辑回归模型得出这片区域是否存在某个目标物体或者只是背景。推理是使用bbox回归来对相对比较“准确”的ROI进行校正,就像下图在目标检测中边框回归的直观理解中举的例子那样,如果bbox回归器看到这个框里面检测到了一个只有半只身体的猫,那么就将这个bbox框稍微扩大点,如果看到两边“猫”不相关的区域过大,则把这个bbox框稍微减小一点。
这种方式有什么问题呢?首先我们需要将所有的ROI过一遍CNN网络。第二就是需要思考一个事情,还是上面检测猫的问题。如果不单考虑这一只猫,如果宏观看整体图像,我需要检测的目标物体的“猫”就是“半只猫”呢?这听上去很恐怖,但你完全可以想象一下你在客厅的书桌上打着字,突然看到旁边的沙发底下探出一个可爱的毛茸茸的小脑袋,瞪着伶俐的圆眼睛在向你示好。因为你知道它的身体被沙发遮挡住了,所以对于你来说,将这只小脑袋标注为检测的“目标”是完全合理的,而你不需要去脑补它的身体在沙发下面是何种形状(毕竟猫是液体)。对于我们的目标检测任务也是一样,如果检测系统能够推理出“因为有沙发的遮挡所以我只需要框柱一个猫头就可以了”这件事情那也是一件挺不错的事情。
实际上Fast RCNN是怎么做的呢?它将输入的图像本身(注意这是一个完全没有被提取过ROI的图像)输入到一个CNN网络中,如果没有后面的全连接层,那么CNN网络的输出的将会是一个W*H的特征图(feature map)。我们可以通过CNN网络中各pooling层和COV层的映射关系,在feature map中找到ROI对应区域的特征图片段,比如说我们在原图中找到了一个以像素坐标(x0,y0)为中心的ROI,原图输入到一个CNN网络后输出feature map的长宽size都是原图的1/2(这个比例也叫作subsampling rate),那么我们可以在feature map的(x0/2,y0/2)处找到一个大小为原ROI 1/2的区域作为原ROI区域的特征映射。这个过程就叫做ROI projection。当然可能你计算出来的区域大小和中心点像素坐标不是一个整数,这时候你可以使用简单的向下取整来近似。
现在说一些我自己的理解,没有经过验证。因为经过了多层的卷积和池化这个图中的每个像素的感受野都很宽,你可以认为这个特征图中的每个像素都含有在原图像中提取的,以该像素对应位置为中心的一大片区域的特征。下图展现了原图经过两层带padding的3X3卷积后输出的特征图中一个像素点的感受野,可以看到特征图中的每个像素的感受野映射回原图也都是以原图中相同以相同像素位置为中心的一片区域,当然如果使用不同参数的卷积核或者加pooling层的话这种对应关系会发生改变,不过我们还是可以通过计算来将特征图中的像素映射回原图。这样特征图中每个像素点既能反映出原图相应像素点的特征(猫本体),也能兼顾整张图中该像素附近一片区域的特征(遮挡猫的沙发)。在Fast RCNN原论文中,使用了小中大三种规格的主干网络进行了训练和测试的对比,结果发现无论是哪种规格的网络,Fast RCNN训练和预测的速度都远比RCNN快,但是在小中型网路中,模型的mAP评分Fast RCNN要略微低一些,而对于大型网络Fast RCNN的mAP评分要高一些,如果用本段的理论来解释的话就是在使用ROI projection后,就需要提取更多的特征,所以网络越大,提取特征的能力越强,目标检测的精准度就会越高。而小中型网络提取特征的能力不够强,所以使用ROI projection增加感受野后反而会引入更多的噪声。
最后强调一点,使用这种方法其实最显著的效果是通过减少CNN网络的数量来加快目标检测系统的运行和训练的速度
现在我们把ROI projection中ROI映射的feature map区域作为该ROI的特征,对ROI特征进行一个resize的操作,这个resize操作通过一个pooling层来完成。不过这个pooling层有一些特殊。对于普通的pooling层来说,我们用一个固定大小的窗口来在原图像或者原feature map上进行滑动来进行下采样。但问题是一旦我们设计一个窗口大小不变、滑动步长不变的pooling层,那输出的feature map大小就会和输入的feature map大小相关。事实上我们想要建立一种对图像或者feature map进行尺寸标准化的方式,无论输入的宽高(Wi,Hi)如何变化输出的标准化后的feature map宽高都是固定的(Wo,Ho),或者更干脆一些,直接输出一个固定维度的特征向量以供后续的全连接层使用。
首先介绍第一种pooling的设计方式,这也是Faster RCNN所使用的pooling方式。这种方式一般输出的(Wo,Ho)都小于(Wi,Hi),然后将原Feature map划分为Wo*Ho个格子,每个格子里面包含了(Wi/Wo)*(Hi/Ho)个像素,当然求出一个浮点值也是可能的,但是我们可以直接向下取整(在Mask RCNN中改进了这一方式)可能最终原Feature map的一些边框会因为计算误差而被舍去,但经过参数的设计和实验,可以保障关键的特征不会丢失。在每个格子中选取最大特征值作为每个格子提取出来的特征图像素,即类似max pooling的操作。最后将所有格子提取出来的特征值像素点拼接,我们就可以得到一个(Wo,Ho)大小的特征图了。
另外一种方式是使用不只一个空间块划分的尺度,比如我们可以分别将原图划分为由小及大,由微观到宏观的(4*4)(2*2)还有(1*1)个格子,这些格子叫做Spatial bins,构建的方式就跟建造一个金字塔(Pyramid)一样,之后求得每个Spatial bin的最大特征值后将特征值拼接为一个特征向量。这个特征向量就是ROI pooling的输出。
在Fast RCNN后,Faster RCNN也继承了ROI projection 和 ROI pooling。和之前的检测系统相比,Faster RCNN主要是改进了ROI的提取方法,放弃了使用SS,转而使用RPN的方法来提取ROI。
在ROI projection 方法中CNN提取的feature map只是被用来进行ROI特征图的映射,ROI的区域划定还是靠SS组件完成。RPN使用了CNN提取的feature map作为输入,提取一些其认为很可能包裹目标的ROI作为输出,也叫作ROI proposal.
由前文的说明我们知道,一个经过多层卷积后的特征图中的像素提取了以原图中该像素点映射坐标为中心附近一片区域的图像特征。要注意到,特征图中的一个像素点通常并不是一维的,而是很多维度的,所以特征图中的一个像素点就可以携带“大量”且经过“提取”的“信息”。我们可以利用这些“信息”做更多的事情。
在RPN的起始,会有一个卷积层加一个激活层来对主干CNN网络的输出特征图进行进一步的特征提取,生成一个新的特征图。这一步你既可以理解为是根据主干网络输出的特征图来提取更适合IOU边框proposal的特征,也可以理解为是提升特征图中每一个像素点的感受野。
之后我们暂时先只把特征图中的一个像素点拿出来看看我们可以对它做什么操作。对于一个像素点,我们可以把它的通道数作为它的维度,这样看起来就像是一个特征向量了。对于这个特征向量我们可以对它分别做以下两种操作(提前说一下,这对应着RPN中1x1卷积及其后续的操作,如果读者看到后面RPN构造的时候再回来看这段就会理解的更明白)。4.1.1 和 4.1.2分别介绍了单个像素级别的背景分类器和bbox回归器,我们可以先不纠结下面两个操作到底有什么作用,等看完后续RPN整体结构的部分再回来看就能理解了。
一次全连接提取特征输出一个二维的向量(这个全连接相当于后面RPN中的1x1卷积)。我们姑且先把这个输出向量的两个维度命名为(“背景度”,“非背景度”),这事暂时先不要纠结这两个命名的含义。然后过一个softmax层就能得到(“是背景的概率”,“不是背景的概率”)。当然我们也可以令全连接的输出为一个18维向量,然后把各输出的维度分为9组,每组中都含有一对(“背景度”,“非背景度”)。至于为什么是这些数字,请结合后面Anchor的讲解。发现了吗,这就是对这个像素的特征向量过了一个线性分类器。
我们还可以对这个特征向量做另外一个操作,就是我们还是可以过另外一个全连接层,然后输出一个四维向量,我们姑且还是先将这个四维向量的各个维度命名为(tx , ty ,tw , th)。当然同样我们也可以把输出的维度设置为36维,其中有9组(tx , ty ,tw , th)。
Anchor 是Faster RCNN中提出的创新性概念。它有点像bbox,目的都是为了找出某种框来正好包裹住目标物体,但是不同的是Anchor是先验的目标框。这里的先验是什么意思呢?简单来说就是人为的先估计一些框的形状和大小,然后用神经网络来检验这些框是否包裹了目标物体以及这些框的大小形状位置是否需要调整。
在RPN中,每个特征图中的像素点都被分配了9个anchor(9个! 熟悉的数字)即我们假设了,以每个像素为中心,都有9种大小形状不同的框有可能会包裹住目标物体。这9种框是这样设计的:
首先我们选取三个级别的大小,比如128*128,256*256,512*512。以特征图中该像素对应的原图坐标点为中心,我们可以画出三个矩形框。此外对于每个大小级别,我们还可以在原图上画出另外两个1:2, 2:1比例的框,这样对于一个像素点我们可以画出9个边框,也就是9个anchor。
9个边框的形状如下图所示
那么接下来的任务有两个,一是去检测这些anchor里是否有目标(即是否不是背景),二是将这些anchor距离真正的GT的转换关系尽可能的预测出来。
RPN网络如上图所示,首先主干CNN网络输出一个特征图,然后RPN使用一层3x3 CNN和一层Relu对特征图进一步的特征提取。然后分别输入到两个1x1卷积层中,其中classification卷积层用来提取一个9*2维的关于每个像素9个anchor是否为背景的逻辑回归预测。因为整个特征图有W*H个像素,所以为了方便计算还需要将特征图resize成一个向量,这样softmax比较好处理,处理完之后再次resize成特征图。这部分对应着本文4.1.1提到的内容
另外还有一个bbox回归卷积层,这层用来将每个像素输出一组9*4的平移加缩放参数,这组参数能够说明如果我想要将每个像素点对应的9个anchor调整成刚好能包裹目标的大小和位置,我需要做什么样的变换,具体的变换原理请参照目标检测中边框回归的直观理解。这部分也对应着本文4.1.2提到的内容。
最后综合bbox回归和背景分类的结果,RPN能根据特征图和原图像的映射关系生成一些ROI的proposal. 这些proposal会在下一步进行ROI projection和ROI pooling,ROI projection和ROI pooling请参照本文的第3章节。
1. 首先根据背景分类结果对所有的anchor进行排名,选出那些最有可能含有目标的anchor
2. 将这些anchor的bbox回归结果提取出来,并且将anchor变换为最有可能的形状
3. 将计算出的anchor尺寸超出原图的部分砍掉
4. 剔除尺寸过小的anchor
5. 对anchor进行NMS进一步筛选
6. 输出proposal
本文摘要部分的附图来自于Faster RCNN论文原文,非常简洁的说明了Faster RCNN的架构。这里稍微再次整理一下。
如下图,输入图像首先经过主干CNN网络进行特征提取,提取出来一个Feature map以供后续组件使用。然后RPN网络使用该Feature map来生成一些ROI。根据RPN生成的ROI和主干网络生成的Feature map将RPN生成的ROI映射到feature map对应的区域上面去,然后进行ROI pooling操作来进行ROI feature map片段尺寸的标准化。最后使用统一尺寸的ROI feature map通过几层全连接提取特征后再进行目标分类的预测和第二次的bbox regression微调。
其中, 主干CNN, 最后的目标分类和bbox回归都属于RCNN的内容,本文没有介绍。ROI projection & pooling 在本文的第3章介绍了。RPN网络在本文的第4章介绍了。