目录
论文:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
来源:NIPS 2015
1. Motication
Fast R-CNN仍然采用Selective Search提取候选区域,并未真正做到端到端的训练。
- Selective Search:CPU上运行,2 seconds per image
- Fast R-CNN的后续部分:GPU上运行,0.32 seconds per image for VGG16
能否提出新的候选区域生成方法,既实现完全端到端的训练,又能减小生成候选区域的时间,成为Faster R-CNN的研究重点。
从R-CNN到SPPnet的改进方法中可以看出,共享卷积(share convolutions)避免了大量冗余的计算,大大地加快了检测速度。既然Fast R-CNN已经使用一系列连续的卷积池化层提出图像的深度特征,那么能否利用这些特征来生成候选区域呢?
于是,Faster R-CNN提出著名的Region Proposal Networks (RPN),RPN与Fast R-CNN共享了卷积网络,因此,在给定图像深度卷积特征的条件下,大大缩短了生成候选区域的时间(10ms per image)。
2. Faster R-CNN
2.1 网络结构
Faster R-CNN网络结构 = RPN + Fast R-CNN detector,如下所示:
2.2 RPN
2.2.1 RPN是如何利用图像深度卷积特征来生成候选区域的?
候选区域:实际上是可能存在目标的候选边界框。
“可能存在目标”表示我们应该要知道候选区域存在目标的概率(前景-背景类的二分类问题);
“候选边界框”表示我们应该知道目标的大概位置(四维坐标表示的边界框)
于是,可将候选区域的生成看成是二分类问题+回归问题。Fast R-CNN分类分支+回归分支的输入是固定长度的特征向量,分类子网络和采用回归子网络均采用全连接层。
这种方法不适用于生成候选区域,原因是:输入图像任意尺寸,得到的特征层也是任意的,特征的维度不是固定的。为解决这种问题,RPN的分类分支和回归分支均采用卷积层,于是RPN是全卷积网络(backbone+分类子网络+回归子网络)
2.2.2 anchor的引入
- Fast R-CNN在分类和回归时,是有候选区域作为参照框的,所谓回归,即是在这个参照框的基础上进行精修(refine)。但是RPN没有参照框,无法进行回归。
- 为解决这个问题,我们可以事先预设一些虚拟边界框(比如同一尺寸的正方形框),并把这些虚拟边界框作为参照框。但是,Selective Search生成的候选区域框是不同尺寸不同宽高比的,所以我们设置的这些虚拟边界框也应该有多种尺寸多种宽高比,目的是适应大小不一的多类物体。在RPN中,这种虚拟边界框被称为“anchor”。
- 尺度变化问题(Scale variance)
三种方法:(a)图像金字塔;(b)多尺度卷积核;(c)anchor
2.2.2 提取区域特征
- Fast R-CNN在经过候选区域映射后,会在特征图上得到不同大小的特征区域,也就是说,分类和回归是基于区域特征的,而不是单点特征的,所以RPN应该也要基于区域特征来进行分类和回归,于是,RPN使用sliding window来提取区域特征(实际上,就是采用 n × n n\times n n×n的卷积核)。
2.2.3 RPN head
-
n = 3 , k = 9 , W × H ≈ 2400 n=3,k=9,W\times H\approx2400 n=3,k=9,W×H≈2400, C = 256 C=256 C=256 for ZF and C = 512 C=512 C=512 for VGG
网络将输出 W H k WHk WHk个anchor,每个anchor有6维信息。前景概率大于一定阈值的anchor,将成为最终的候选区域。 -
RPN给出了很多anchor(~21k),相当于以不同尺寸不同宽高比在图像中进行了一次密集均匀采样,如果把设定anchor看成是没有任何先验知识的候选区域,那么RPN可以看成是进行了一次粗分类+粗回归。此外,使用 1 × 1 1\times1 1×1的卷积核,卷积核深度为 4 k 4k 4k,使得每一种回归器只对于一种anchor进行归回(9种anchor,9种回归器),并且把4维坐标信息看成是相互独立的变量。
Pytorch官方实现的RPN如下所示,需要注意的是:用于判别anchor是否包含物体的类别输出如果只有一维,表示属于前景或背景的概率,最终是通过sigmoid函数(逻辑回归);如果有两维,只表示属于前景和属于背景的概率,后面接的是softmax函数(Softmax回归)。Pytorch官方实现的RPN是使用逻辑回归。
class RPNHead(nn.Module):
"""
Adds a simple RPN Head with classification and regression heads
Args:
in_channels (int): number of channels of the input feature
num_anchors (int): number of anchors to be predicted
"""
def __init__(self, in_channels, num_anchors):
super(RPNHead, self).__init__()
# 3x3 滑动窗口
self.conv = nn.Conv2d(in_channels, in_channels, kernel_size=3, stride=1, padding=1)
# 计算预测的目标分数(这里的目标只是指前景或者背景)
self.cls_logits = nn.Conv2d(in_channels, num_anchors, kernel_size=1, stride=1)
# 计算预测的目标bbox regression参数
self.bbox_pred = nn.Conv2d(in_channels, num_anchors * 4, kernel_size=1, stride=1)
# 网络参数初始化
for layer in self.children():
torch.nn.init.normal_(layer.weight, std=0.01)
torch.nn.init.constant_(layer.bias, 0)
def forward(self, x):
# type: (List[Tensor]) -> Tuple[List[Tensor], List[Tensor]]
logits = []
bbox_reg = []
# 使用for循环的原因时,方便将其扩展到多输入,比如FPN就是将RPNHead应用在不用尺寸的特征图上
for feature in x:
t = F.relu(self.conv(feature))
logits.append(self.cls_logits(t))
bbox_reg.append(self.bbox_pred(t))
return logits, bbox_reg
2.2.4 RPN是怎样进行训练的?
(1)正负样本的判定
- 我们既然把anchor看成是没有任何先验知识的候选区域,现在anchor的四维位置信息有了,应该怎么样给anchor贴上合适的正负样本标签呢?采用R-CNN、Fast R-CNN给region proposal贴标签的方法给anchor贴标签:
正样本 | 负样本 | 中间样本 | |
---|---|---|---|
描述 | 表示该anchor负责预测某个gt,即含有object | 表示该anchor不负责预测任何gt,即不含有object | 表示该anchor覆盖较少区域的gt,忽略样本 |
准则 | (1)对于每个gt,选择与其IoU最大的anchor:保证所有的gt至少有一个anchor负责预测它。(2)若某个anchor与任何一个gt的IoU大于0.7,则为positive | 该anchor与所有gt的IoU都小于0.3 | 既不是positive,也不是negative的anchor |
作用 | 用于二分类和边界框回归 | 用于二分类 | 没有任何作用 |
(2)损失函数
- p i p_i pi是第 i i i个anchor为object的概率;
- p i ∗ p_i^* pi∗是第 i i i个anchor的真实类别, p i ∗ p_i^* pi∗ is 1 if the anchoris positive, and is 0 if the anchor is negative;
- t i t_i ti是第 i i i个anchor的坐标偏移量;
- t i ∗ t_i^* ti∗是第 i i i个anchor的真实坐标偏移量;
- N c l s N_cls Ncls是mini-batch size;
- N r e g N_reg Nreg是网格数 W H WH WH。
- 回归损失采用SmoothL1损失。
(3)正负样本平衡采样策略
- 图像中的grund truth是非常少的,而anchor的数量是非常多的,所以positive anchor要比negative anchor少很多,在构成mini-batch时保证正负样本的比例为1:1。另外,一个mini-batch只来自一张图像。
(4)如何进行端到端的训练?
4-Step Alternating Training:
- 用ImageNet-pre-trained model初始化backbone,训练RPN(backbone+RPN head);
- 用ImageNet-pre-trained model初始化backbone,由步骤1得到的RPN产生候选区域,训练Fast R-CNN(backbone+Fast R-CNN head);
- 固定步骤2得到的backbone,微调RPN head
- 固定步骤2得到的backbone和步骤3得到的RPN head,微调Fast R-CNN head
- 步骤3和步骤4交替训练。