1、写在前面
从零开始入门物体检测。物体检测的网络架构和普通的任务有所不同,简单来讲就是子模块更多,从图像到最终结果的过程更加复杂。本文是FasterRCNN的框架解读,还没有具体到代码层面(即将更新代码解读)。其中涉及一些概念,比如anchor,bbox,FPN等等。这些概念对于没了解过物体检测的人来讲肯定十分陌生。为了对物体检测有个大概的了解,在看了许多许多的博客之后,我认为这篇最有帮助:https://zhuanlan.zhihu.com/c_1167555485703315456
想要深入了解FasterRCNN,仅仅读博客是不够用的,我建议先读论文(https://arxiv.org/abs/1506.01497)。这篇论文读起来需要一些先验知识,看了上面提到的入门链接之后基本就可以理解里面提到的各种概念了。看完论文看讲解,我认为这篇讲的最好:https://zhuanlan.zhihu.com/p/31426458。本文可以说是那篇文章加入个人理解之后的精简版。看完讲解看代码。论文中虽然有代码地址,但是现在pytorch已经在torchvision里官方集成了此模型,可以直接看官方的代码:https://pytorch.org/vision/stable/_modules/torchvision/models/detection/faster_rcnn.html。
代码解读可以看我的另一篇博客(暂时还没写)。
2、整体框架
FasterRCNN的主要框架如图所示。主要分为4个部分:transform,backbone,RPN,RoIHead。这样的划分对应于官方代码的子模块划分结构。下面来一一介绍各个子模块。
2.1、Transform
这个部分相当于对图像进行预处理。在这里主要进行图像放缩和数据增强。物体检测的数据除了图像之外还包括标注信息(annotations),标注信息指出了图像当中每个object的框框位置和类别。首先是方便起见,把所有图像都放缩成一个固定的大小,假设放缩后的图像大小为M*N。然后可能还需要对图像进行一系列的数据增强。图像的放缩过程和数据增强过程肯定会对目标的所在位置造成改动,这个过程需要同时修改图像的label信息,确保annotations和增强后的图像都是对的上的。
2.2、Backbone
主干网络。这里指的是特征提取层。传统的分类网络就是backbone加predictor。物体检测中的backbone可以直接用分类网络中的backbone。分类网络上预训练好参数之后拿到物体检测任务中来,可以提高物体检测的效果。backbone的选择可以有很多,比如resnet,vgg等等。在具体实现的时候,官方采用的backbone是resnet50+FPN。FPN是什么?这个在开头的科普性链接中有讲到。这里不细讲,读者可以先理解为backbone可以用resnet50来充当。使用backbone进行特征提取之后,可以得到一个大小为256*m*n的特征图。这个256*m*n是个假设的大小。在实际代码中,选择的backbone不同,输出的特征图的大小也不同。为了方便理解,这里假设输出的特征图大小是256*m*n,其中m=M/16,n=N/16。
2.3、RPN
接下来进入了FasterRCNN的主要贡献部分,Region Proposal Network。对于backbone提取出来的特征图,会在该特征图上设置m*n个anchor中心。每个中心拥有不同形状的9个anchor。anchor中心之间的间距即为特征图缩小的幅度。比如m = M/16,那么在这里,anchor中心之间的间距就是16。在每个像素点都设置不同尺度的9个anchor,那么一共就有9*m*n个anchor。对这么多个anchor,RPN的作用就是选出可能包含了object的anchor,并且预测anchor的偏移量。首先,预测anchor是否包含物体,这是一个2分类问题。RPNhead网络中,首先对整个特征图来两个3*3卷积,卷完之后特征图的大小依旧是256*m*n。然后再使用一个1*1卷积来将256*m*n的特征图变为9*m*n的2分类结果,最终加个sigmoid就可以判断每个anchor是否包含了object。(如果分类器是使用softmax的话,则变为18*m*n)。另外,object不可能正正好好地落在anchor里面,所以,模型需要对每个anchor学习一个偏移量。偏移量对应4个值,所以RPNHhead中使用了另外一个1*1卷积,来将特征图映射为36*m*n。
有了每个anchor是否包含物体以及每个anchor的偏移量之后,接下来就是初步的筛选anchor。object总共就那么几个,模型却产生了那么多个anchor,肯定是要筛选的。图中的proposal layer的作用就是筛选anchor。首先proposal layer将学习出来的anchor偏移量应用到anchor上。然后提取可能包含正样本的anchors,然后根据置信度对他们进行排序,选取前x(x是一个可以设置的参数)个进行下一步处理。将选取出来的x个anchor进行边界检测,修改超出边界的anchor,然后删除面积太小的anchor,然后进行NMS(一个物体可能被很多个anchor框住了,NMS用于去除冗余的框框),得到最终的经过筛选的可能包含object的proposal(那些anchor到了这里就改名叫proposal了)。这个过程除了需要RPN head提取出的anchor置信度和偏移量信息之外,还需要一些元信息来做处理,如图像大小,特征图相对于原图的缩小幅度等,这些算是参数,并没有在图中画出来。
2.4、ROI Head
在RPN那里,我们得到了筛选出来的可能包含object的proposals。接下来,根据proposal的框框,在原特征图中将这些框框里面的部分抠出来。对于抠出来的子图,划分成7*7的网格(7是一个可设置的参数)。对每个网格进行MaxPooling,那么每个proposal就变为了一个7*7的向量。剩下的就简单了,两层全连接来把7*7的向量扩展到1024(1024也是可设置的参数)维,然后使用一个全连接来层来进行softmax分类,使用另外一个全连接再次预测一组proposal偏移量,使框框能够框的更加准确。
2.5、后话
由于时间关系,我写的不够详细,只是把脉络理了一遍,不够细节。还有很多概念我没详细解释。概念可以在一开始的科普性链接中看到。细节则可以在我给出的FasterRCNN讲解链接中看到。这篇文可能只有我自己一个人能看懂。这篇博客的价值不过是我的个人总结,以及茫茫网络中挑选出来的几个不错的博客链接。