原标题 What do we learn from region based object detectors (Faster R-CNN,R-FCN, FPN)?,作者为 Jonathan Hui 。
翻译 | 唐青 李振 整理 | 凡江
在这个系列中,我们将对目标检测算法进行全面探讨。 第 1 部分,我们介绍常见的基于区域的目标检测器,包括 Fast R-CNN , Faster R-CNN , R-FCN 和 FPN 。 第 2 部分,我们介绍单步检测器(single shoot dectors, SSD )。第 3 部分,我们探讨算法性能和一些具体的例子。通过在相同的环境研究这些算法,我们研究哪些部分在其作用,哪些部分是重要的,可以在哪些部分进一步改进。希望通过对算法如何发展到今天的研究,会给我们未来的研究提供方向。
第1部分:我们从基于区域的目标检测器中学到了什么(Faster R-CNN,R-FCN,FPN)?
第2部分:我们从单步检测器中学到了什么(SSD,YOLO),FPN 和 Focal loss?
第3部分:目标检测的设计选型,经验教训和发展趋势?
滑动窗口检测器(Sliding-window detectors)
自从 AlexNet 赢得了 2012 年 ILSVRC 挑战的冠军,使用 CNN 进行分类成为领域的主导。一种用于目标检测的简单粗暴的方法是将滑动窗口从左到右,从上到下滑动使用分类来识别目标。为了区分在不同视觉距离下的目标类型,我们使用了不同尺寸和高宽比的窗口。
我们按照滑动窗口从图片中剪切出部分图像块。由于通常分类器都采用固定的图像大小,所以图像块需要进行形变。然而,这对分类精度并没有什么影响,应为分类器训练时也使用了形变的图像。
形变的图像块被送进 CNN 分类器中提取 4096 个特征。然后,我们用一个 SVM 分类器进行分类,用一个线性回归器得到边界框。
以下是伪代码。 我们生成了很多窗口来检测不同位置、不同形状的目标。 为了提高性能,减少窗口数量是一个显而易见的解决方案。
选择性搜索(Selective Search)
不再用简单粗暴的方法,我们用区域提议方法(region proposal method)生成感兴趣区域 ( regins of interest, ROIs ) 来进行目标检测。在选择性搜索算法(Selective Search, SS)中,我们让每个独立像素作为一个起始的组。然后,计算每个组的纹理,合并最接近的两个组。为了避免一个区域吞所有,我们优先合并较小的组。持续进行合并,直到所有可能合并的区域均完成合并。下图中,第一行展示了如何进行区域生长。第二行展示了在合并过程中所有可能的 ROIs 。
R-CNN
R-CNN 利用区域提议方法(region proposal method)生成了约 2000 个感兴趣区域(regins of interest, ROIs)。这些图像块进行形变到固定的大小,分别送入到一个 CNN 网络中。然后,经过全连接层,进行目标分类和边界框提取。
以下是系统的工作流。
利用数量更少,但质量更高的 ROIs ,R-CNN 比滑动窗口的方法运行的更快、更准确。
边界框回归器(Boundary box regressor)
区域提议方法的计算量很大。为了加速这个过程,我们常采用一个简易版的区域提议网络来生成 ROIs ,然后,接线性回归器(使用全连接层)来提取边界框。
Fast R-CNN
R-CNN 需要足够多的提议区域才能保证准确度, 而很多区域是相互重叠的。R-CNN 的训练和推理过程都很缓慢。例如,我们生成了 2000 个的区域提议,每个区域提议分别进入 CNN。换句话说,我们对不同的 ROIs 重复了进行了 2000 次的提取特征。
CNN 中的特征映射表达了一个更紧密的空间中的空间特征。我们能否利用这些特征映射来进行目标检测,而不是原始图像?
我们不再为每个图像块重新提取特征,而是在开始时采用一个特征提取器(一个 CNN 网络)为整个图像提取特征。然后,直接在特征映射上应用区域提议方法。例如,Fast R-CNN 选择 VGG16 的卷积层 conv5 来生成待合并 ROIs 来进行目标检测,其中,包括了与相应特征的映射。我们利用 ROI Pooling 对图像块进行形变转换成固定大小,然后将其输入到全连接层进行分类和定位(检测出目标的位置)。由于不重复特征提取,Fast R-CNN 显著的缩短了处理时间。
以下是网络工作流:
在下面的伪代码中,计算量很大的特征提取操作被移出了 for 循环。由于同时为 2000 个 ROIs 提取特征,速度有显著的提升。Fast R-CNN 比 R-CNN 的训练速度快 10 倍,推理速度快 150 倍。
Fast R-CNN 的一个主要特点是整个网络(特征提取器,分类器和边界框回归器)可以通过多任务损失 multi-task losses(分类损失和定位损失)进行端到端的训练。这样的设计提高了准确性。
ROI Pooling
由于 Fast R-CNN 使用了全连接层,因此我们应用 ROI Pooling 将不同大小的 ROIs 转换为预定义大小形状。
举个例子,我们将 8×8 特征映射转换为预定义的 2×2 大小。
-
左上:特征映射图。
-
右上:ROI(蓝色)与特征映射图重叠。
-
左下:我们将 ROI 分成目标维度。 例如,我们的目标大小是 2×2,我们将 ROI 分为 4 个大小相似或相等的部分。
-
右下:取每个部分的最大值,结果是特征映射转换后的结果。
结果,得到了一个 2×2 的特征块,我们可以将它输入到分类器和边界框回归器中。
Faster R-CNN
Fast R-CNN 采用类似选择性搜索(Selective Search)这样额外的区域提议方法。 但是,这些算法在 CPU 上运行,且速度很慢。测试时, Fast R-CNN 需要 2.3 秒进行预测,而其中 2 秒花费在生成 2000 个ROIs 上。
Faster R-CNN 采用与 Fast R-CNN 相似的设计,不同之处在于它通过内部深度网络取代区域提议方法。 新的区域提议网络(Region Proposal Network, RPN)效率更高。单副图像生成 ROIs 只需要 10ms 。
网络工作流。区域提议方法被新的卷积网络(RPN)取代。
区域提议网络(Region proposal network)
区域提议网络( RPN )用第一个卷积网络输出的特征图作为输入。在特征图上用 3×3 的滤波器进行滑动(滤波),采用诸如 ZF 网络(如下图)的卷积网络来得到未知类的建议区域。其他如 VGG 或者 ResNet 可以被用来提取更全面的特征,但需以速度为代价。 ZF 网络输出的 256 个值分别被送入两个不一样的全连接层来预测边界框和对象性分数(2 objectness score)。对象性描述了框内是否包含有一个物体。我们可以用回归器来计算单个物体的分数,但是为了简单起见,Faster R-CNN使用了一个分类器分类出两种可能的类别:「 存在物体 」类和「 不存在物体/背景 」类。
RPN 对特征图里的每个位置(像素点)做了 K 次猜测。因此 RPN 在每个位置都输出 4×k 个坐标和 2×k 个分数。以下图例演示了一个使用 3×3 过滤器的 8×8 特征图,它一共输出 8×8×3 个兴趣区( ROI )( 当k=3时)。右侧图例展示了在单个位置得到的 3 个提议区域。
我们现在有 3 个猜测,随后我们也会逐渐改善我们的猜想。因为我们最终只需要一个正确的猜测,所以我们使用不同形状和大小的的初始猜测会更好。因此, Faster R-CNN 不是随机的选择提议边界框。而是预测了相对于一些被称为锚的参考框的左上角的偏移量,比如 ?x, ?y 。因为我们约束了偏移量,所以我们的猜测仍然类似与锚。
为了对每个位置都进行 k 次预测,我们需要在每个位置中心放置 k 个锚。每次预测都和不同位置但是相同形状的特定锚相关。
这些锚都是精心预选好的,所以它们多种多样,同时非常合理的覆盖了不同尺度和不同长宽比的现实生活中的物体。这使了初始训练将具有更好的猜测,同时允许每次预测都有特定、不同的形状。这种方式使早期的训练更加稳定和容易。
Faster R-CNN 使用了更多的锚。Faster R-CNN 在一个位置上使用了 9 个锚:3 种不同尺度并使用三种长宽比。在每个位置使用 9 种锚,所以对于每个位置,它一共产生了 2×9 个对象性分数和 4×9 个坐标。
锚在不同的论文中也被称为先验或者默认边界框。
R-CNN的性能
如下图,Faster R-CNN 要快得多。
基于区域的全卷积网络
假设我们只有一张特征图用来检测脸上的右眼。我们是否可以用此来决定脸的位置呢?是可以的。因为右眼应该位于一张面部图像的左上角,我们也可以用此信息来确定脸的位置。
如果我们有另外的特征图专门用来分别检测左眼、鼻子、嘴,我们可以将这些结果结合在一起使对脸部的定位更准确。
那为什么我们要如此麻烦呢?在 Faster R-CNN 里,检测器使用多个全连接层来做预测,有 2000 多个 ROI ,这消耗很高。
R-FCN 通过减少每个 ROI 需要的工作总量来提高速度,以上基于区域的特征图独立于 ROIs ,同时可以在每一个ROI的外部进行计算。接下来的工作就更简单了,因此 R-FCN 比 Faster R-CNN 要快。
我们可以想想一下这种情况,M 是一个 5*5 大小,有一个蓝色的正方形物体在其中的特征图,我们将方形物体平均分割成 3*3 的区域。现在我们从 M 中创建一个新的特征图并只用其来检测方形区域的左上角。这个新的特征图如下右图,只有黄色网格单元被激活。
因为我们将方形分为了 9 个部分,我们可以创建 9 张特征图分别来检测对应的物体区域。因为每张图检测的是目标物体的子区域,所以这些特征图被称为位置敏感分数图(position-sensitive score maps)。
比如,我们可以说,下图由虚线所画的红色矩形是被提议的 ROIs 。我们将其分为 3*3 区域并得出每个区域可能包含其对应的物体部分的可能性。例如, ROIs 的左上区域中存在左眼的可能性。我们将此结果储存在 3*3 的投票阵列(如下右图)中。比如,投票阵列 [0][0] 中数值的意义是在此找到方形目标左上区域的可能性。
将分数图和 ROIs 映射到投票阵列的过程叫做位置敏感 ROI 池化(position-sensitive ROI-pool)。这个过程和我们之前提到的 ROI pool 非常相似。这里不会更深入的去讲解它,但是你可以参考以后的章节来获取更多信息。
在计算完位置敏感 ROI 池化所有的值之后,分类的得分就是所有它元素的平均值。
如果说我们有 C 类物体需要检测。我们将使用 C+1个类,因为其中多包括了一个背景(无目标物体)类。每类都分别有一个 3×3 分数图,因此一共有 (C+1)×3×3 张分数图。通过使用自己类别的那组分数图,我们可以预测出每一类的分数。然后我们使用 softmax 来操作这些分数从而计算出每一类的概率。
接下来是数据流(图),比如我们的例子中,k=3。
至今为止我们的历程
我们从最基础的滑动窗口算法开始。
然后我们尝试减少窗口数,并尽可能的将可以移出 for-loop 的操作移出。
在第 2 部分里,我们更加完全的移除了 for-loop 。单次检测器(single shot detectors)使物体检测能一次性完成,而不需要额外的区域提议步骤。
RPN,R-FCN,Mask R-CNN的延伸阅读
FPN 和 R-FCN 都要比我们在这里所描述的更加复杂,如果您想进一步学习,请参考如下:
-
https://medium.com/@jonathan_hui/understanding-feature-pyramid-networks-for-object-detection-fpn-45b227b9106c
-
https://medium.com/@jonathan_hui/understanding-region-based-fully-convolutional-networks-r-fcn-for-object-detection-828316f07c99