Faster RCNN原理篇(二)——RoIPooling和RoIAlign的学习和理解

绪论

附上Mask R-CNN的学习资料链接:

Mask R-CNN原文链接:http://cn.arxiv.org/pdf/1703.06870v3
Mask R-CNN源码链接:
https://github.com/facebookresearch/maskrcnn-benchmark
https://github.com/matterport/Mask_RCNN

RoI pooling的前世今生

引言

在FAST R-CNN中,特征被共享卷积层一次性提取,因此对于每个roi而言,需要从共享卷积层上摘取对应的特征,并且送入全连接层进行分类。因此,ROI Pooling做2件事:

task 1: 为每个roi选取对应的特征;

task 2: 满足全连接层的输入需求,将每个roi对应的特征的维度转化为某个定值。

下面以Fast R-CNN为例:
在这里插入图片描述
参考链接:
详解ROI Polling和 ROI Align 的基本原理和实现细节

1、(Why?)为何需要RoI Pooling?

目标检测的典型架构(typical architecture)通常可以分为两个阶段:

  1. region proposal:给定一张输入image找出objects可能存在的所有位置。这一阶段的输出应该是一系列object可能位置的bounding box。这些通常称为region proposals或者 regions of interest(ROI)。
  2. final classification:确定上一阶段的每个region proposal是否属于目标一类或者背景。

这个architecture存在一些问题:

  1. 产生大量的region proposals 会导致performance problems,即:很难达到实时目标检测;
  2. 在处理速度方面是suboptimal;
  3. 无法做到end-to-end training。

另一方面,对于传统的CNN(如:AlexNet和VGG),当网络训练好之后,需要同时满足以下两点:

1. 输入的图像尺寸必须是固定值;
2. 网络输出也是固定大小的vector or matrix。

如果输入图像大小不固定,这个问题就变得比较麻烦。在提出RoI Pooling之前,有以下两种解决办法:

  1. 从图像中crop一部分传入网络;
  2. 将图像warp成需要的大小后传入网络;

在这里插入图片描述
如上图所示,将原图crop后破坏了图像的完整结构,而将原图warp后则破坏了图像的原始形状信息,均不是一种两全其美的方法。

再者,在利用RPN网络生成region proposals的过程中:需对positive anchors进行bounding box regression得到的region proposals也是形状、大小各异,同样存在上述问题。

因此,在Faster R-CNN中首次提出了RoI Pooling来解决这个问题。

参考链接:
详解ROI Polling和 ROI Align 的基本原理和实现细节

2、(What?)什么是RoI Pooling?

ROI pooling是简化版SPP(全称:Spatial Pyramid Pooling),在Fast RCNN和Faster RCNN中使用。

ROI 是Region of Interest的简写,指的是在“特征图上的框” 。具体而言:

  1. SPP NetFast RCNN网络中, ROIS 是指Selective Search(选择搜索算法)完成后得到的所有“候选框”在特征图上的映射;

  2. Faster RCNN网络中,候选框是经过RPN算法产生的,然后再把 各个“候选框”映射到特征图上,得到ROIS。

一言概之:在RCNN系列算法中,输入的原始图像经过卷积网络产生整个原始图像的feature map;再将利用Selective Search或RPN算法提取的多个目标候选框映射到整个原始图像的feature map上,这些以输入图片为参考坐标的候选框在feature maps上的映射区域,即为目标检测中所说的ROI(Region of Interest,即“特征图上的框”)

RoIPooling在Faster RCNN中使用,旨在实现使生成的候选框region proposal映射产生固定大小的feature map。

在这里插入图片描述

ROI pooling具体操作如下:(以单个候选框为例)

1. 根据输入image,将提取的候选框region proposal映射到feature map的对应位置上,得到ROI;
2. 将映射后的ROI区域划分为相同大小的块sections(块sections的数量是我们指定的,它与输出的维度相同);
3. 对每个块sections进行max pooling操作;

这样我们就可以从不同大小的候选框得到固定大小的相应的feature maps。

注意事项:

  • 通过ROI Pooling实现从具有多个卷积核池化的深度网络中获得固定大小的feature maps。最终返回一个表示所有ROI的N*5的矩阵。其中,“N”表示ROI的数目,“5”的第一列表示图像index,其余四列表示其余的左上角和右下角坐标;
  • 执行ROI Pooling所得输出结果,即:固定大小的feature maps的尺寸只取决于我们指定的划分块sections的数量,而与ROI、卷积所得整个原始图像的feature map的大小无关。
  • ROI pooling 最大的好处就在于实现了training和testing的显著加速,并提高检测accuracy。

ROI Pooling过程中涉及的公式计算:

\quad


在这里插入图片描述
RoI Pooling的过程如上图所示,其中涉及两个计算细节:

\quad


问题1、以输入图片为参考坐标的候选框在feature maps上如何映射?

\quad


{

s

c

a

l

e

=

S

f

S

i

X

f

=

s

c

a

l

e

X

i

,

Y

f

=

s

c

a

l

e

Y

i

(1)

\begin{cases} scale = \frac{S_f}{S_i} \\[2ex] X_f = scale * X_i, \\[2ex] Y_f = scale * Y_i\end{cases} \tag{1}

scale=SiSfXf=scaleXi,Yf=scaleYi(1)
其中,

S

f

S_f

Sf 为整个原始image的feature map的Size,Si 为输入原始image的Size,

X

f

Y

f

(X_f,Y_f)

XfYf为 feature map上的坐标点,

X

i

Y

i

(X_i,Y_i)

XiYi为输入原始image的坐标点。

\quad


问题2、如何把形状和大小各异的ROIS归一化为固定大小的目标识别区域?

\quad


通过对feature map分块池化实现归一化到固定大小。 假设ROI Pooling层的输出大小为

W

r

×

H

r

W_r ×H_r

Wr×Hr,输入候选区域ROI的大小为

W

i

×

H

i

W_i×H_i

Wi×Hi,则ROI Pooling的过程包括两个步骤:

  1. 根据

    W

    r

    ×

    H

    r

    W_r ×H_r

    Wr×Hr的尺寸大小把输入候选区域划分为多个块,每块的大小是

    (

    H

    i

    /

    H

    r

    )

    ×

    (

    W

    i

    /

    W

    r

    )

    ( H_i / H_r) × (W_i / W_r)

    (Hi/Hr)×(Wi/Wr),这里会有一个取整量化的操作;

  2. 对每块取最大元素作为输出,最终得到大小固定为

    W

    r

    ×

    H

    r

    W_r × H_r

    Wr×Hr的输出。

3、(How?)RoI Pooling的计算过程?

在这里插入图片描述
针对上图,RoI Pooling的实现原理 如下:

为了输出固定大小(

7

×

7

7×7

7×7)的feature map,我们需要做两次量化操作:1)原始图像坐标

\Rightarrow

ROI坐标,2)ROI坐标

\Rightarrow

固定大小ROI坐标。 具体过程如下:

1. 根据输入的原始image,将提取的候选框region proposal映射到feature map的对应位置上,得到ROI

输入一张

800

×

800

800×800

800×800的图像,在图像中有两个目标(猫和狗)。其中,某一region proposal(如:狗)的Bounding Box大小为

665

×

665

665×665

665×665。经过VGG16网络后,可以获得region proposal映射到feature map上,所得ROI的特征图大小为

20.78

×

20.78

20.78×20.78

20.78×20.78,取整后,得到 第一次量化后映射的ROI特征图大小为

20

×

20

20×20

20×20

备注:
Conv layers使用的是VGG16,feat_stride=32(代表经过网络层后图片缩小为原图的1/32)。

\quad


在该VGG16中,我们使用了5个池化操作,每个池化操作都是

2

×

2

2×2

2×2 Pooling,因此,原图为

800

×

800

800×800

800×800,最后一层特征图feature map为

800

/

32

×

800

/

32

=

25

×

25

800/32×800/32 = 25×25

800/32×800/32=25×25(是整数)。但是,将候选框(如:狗)的Bounding Box对应到feature map上,我们得到的结果是

665

/

32

×

665

/

32

=

20.78

×

20.78

665/32×665/32 = 20.78 × 20.78

665/32×665/32=20.78×20.78(浮点数)。由于像素值没有小数,所以,作者就对其进行了 量化操作(即:取整操作) ,结果变为

20

×

20

20×20

20×20,此处引入了 第一次的量化误差

2. 将映射后的ROI区域划分为相同大小的块sections

假定输出的

p

o

o

l

e

d

w

=

7

,

p

o

o

l

e

d

h

=

7

pooled_w=7, pooled_h=7

pooledw=7,pooledh=7(即:经过max pooling后固定成

7

×

7

7×7

7×7大小的特征图。)所以,将第一次量化后得到的ROI对应的

20

×

20

20×20

20×20的feature map划分成49个同等大小的块sections,每块的大小为

2.86

×

2.86

2.86×2.86

2.86×2.86(计算公式:

20

/

7

=

2.86

20/7=2.86

20/7=2.86),再次取整, 得到第二次量化后每一小块section对应的特征图大小为

2

×

2

2×2

2×2

备注:
我们的feature map中有不同大小的ROI,但是我们后面的网络却要求我们有固定大小的输入,因此,我们需要将不同大小的ROI转化为固定大小的ROI feature,在这里假定固定输出的是

7

×

7

7×7

7×7大小的ROI feature。

3. 对每一小块section进行max pooling操作;

在每个

2

×

2

2×2

2×2的小块section中,取出其中最大的像素值,作为这一个区域的‘代表’,这样,49个小区域就输出49个像素值,最终组成一个

7

×

7

7×7

7×7大小的feature map。

综上所述,在ROI Pooling过程中共经过两次 量化,即:将浮点数取整 ,这里引入的误差会导致图像中的像素和特征中像素的偏差,即:将feature空间的ROI对应到原图上面会出现很大的偏差。

偏差分析;
比如用我们第二次引入的误差来分析,本来是2.86,我们将其量化为2,使得原本在特征图上映射的20 x 20大小的region proposal,偏差成大小为14 x 14的。这期间引入了0.86的误差,看起来是一个很小的误差,但是你要记得这是在feature map空间,我们的feature map空间和原始图像空间是有比例关系的,在这里是1:32,那么对应到原图上面的差距就是0.86 x 32 = 27.52。这个差距不容小觑,这还是仅仅考虑了第二次的量化误差。这样的像素偏差势必会对后层的回归定位产生影响,降低整个检测算法的性能,因此是一个严重的问题。

4、Region of interest pooling — example

ROI Pooling的计算实例:

以下过程摘自原文《Region of interest pooling explained》

假定一个

8

×

8

8×8

8×8大小的feature map,一个ROI,以及输出大小为

2

×

2

2×2

2×2

附原文:Let’s consider a small example to see how it works. We’re going to perform region of interest pooling on a single 8×8 feature map, one region of interest and an output size of 2×2.
(1)Our input feature map looks like this:
(2)Let’s say we also have a region proposal (top left, bottom right coordinates): (0, 3), (7, 8). In the picture it would look like this:
Normally, there’d be multiple feature maps and multiple proposals for each of them, but we’re keeping things simple for the example.
(3)By dividing it into (2×2) sections (because the output size is 2×2) we get:
Notice that the size of the region of interest doesn’t have to be perfectly divisible by the number of pooling sections (in this case our RoI is 7×5 and we have 2×2 pooling sections).(即:RoI的size不必保证恰好被pooling sections的size整除
(4)The max values in each of the sections are:
And that’s the output from the Region of Interest pooling layer. Here’s our example presented in form of a nice animation:
What are the most important things to remember about RoI Pooling?

\quad


It’s used for object detection tasks
It allows us to reuse the feature map from the convolutional network
It can significantly speed up both train and test time
It allows to train object detection systems in an end-to-end manner

1. 输入一个固定大小的feature map,例如:

8

×

8

8×8

8×8
在这里插入图片描述
2. 候选框(region proposal)在feature map上投影之后对应的位置坐标:(左上角,右下角坐标)依次为(0,3),(7,8);
在这里插入图片描述
3. 将 region proposal划分为

2

×

2

2×2

2×2个sections(划分块sections的大小等于输出大小

2

×

2

2×2

2×2),我们可以得到:
在这里插入图片描述
4. 对每个section做max pooling,可以得到:
在这里插入图片描述
整个ROI Pooling计算过程的动态示意图如下:
在这里插入图片描述
ROI pooling的主要优势:

(1)用于目标检测任务;
(2)允许我们对CNN中的feature map进行reuse;
(3)可以显著加速training和testing速度;
(4)允许以end-to-end的形式训练目标检测系统。

参考链接:
目标检测之RoI Pooling及其改进RoI Align

RoIAlign的提出和原理

1、(Why?)RoIAlign提出的原因

经过RoI Pooling将不同大小的ROI转化为固定大小的ROI的过程中共经过两次 取整量化 ,导致将feature空间的ROI对应到原图上面会出现很大的偏差,从而影响检测或者分割的准确度。在论文里,作者把它总结为“区域不匹问题”(misalignment)。 所以,产生了替代方案:RoiAlign。

ROI Align 在Mask RCNN中首次提出,用以实现将生成的候选框region proposal映射产生固定大小的feature map。实验显示,在检测测任务中将 ROI Pooling 替换为 ROI Align 可以提升检测模型的准确性。

值得一提的是,试验发现,ROI Align在VOC2007数据集上的提升效果并不如在COCO上明显。经过分析为造成这种区别的原因是COCO上小目标的数量更多,而小目标对misalignment问题的影响更为明显(比如:同样是0.5个像素点的偏差,对于较大的目标而言显得微不足道,但是对于小目标,误差的影响就要高很多)

2、(What?)什么是RoIAlign

ROI Align的核心思想:

ROI Pooling的改进版,解决了映射误差和均分误差问题,提高了后续处理的准确率。ROI Align取消量化操作,主要是利用虚拟像素的方法,即用双线性插值的方法获得坐标为浮点数的像素点上的图像数值,从而将整个特征聚集过程转化为一个连续的操作

  1. 遍历每一个候选区域,保持浮点数边界不做量化。
  2. 将候选区域分割成

    k

    ×

    k

    k × k

    k×k 个单元,每个单元的边界也不做量化。

  3. 在每个单元中计算固定四个坐标位置(即:假定4个采样点),用双线性插值的方法计算出这四个位置的值,然后进行最大池化操作。

备注:
这里对上述步骤的第三点作一些说明:此处 固定位置是指在每一个矩形单元(bin)中按照固定规则确定的位置。 比如:

  1. 如果采样点数是1,那么就是这个单元的中心点;
  2. 如果采样点数是4,那么就是把这个单元平均分割成四个小方块以后它们各自的中心点。

    \quad

RoI Align不再采用取整量化操作,显然 这些采样点的坐标通常是浮点数,也就是没有落到真实的像素点上,那么就用最近像素点对这一点虚拟的像素点进行双线性插值,得到这个像素点的值 。再对每个区域进行max pooling操作得到固定尺度的feature map。

\quad


在相关实验中,作者发现将采样点设为4时会获得最佳性能,甚至直接设为1在性能上也相差无几。事实上,ROI Align 在遍历取样点的数量上没有ROIPooling那么多,但却可以获得更好的性能,这主要归功于解决了misalignment的问题。

假定采样点数为4,则ROI Align的具体执行步骤如下:

  1. 假设需要输出的固定尺度的feature map为

    2

    ×

    2

    2×2

    2×2

  2. 先将ROI切分成

    2

    ×

    2

    2×2

    2×2 的单元格;

  3. 假设采样点数是4,将每个单元格子均分成四个小方格,以每个小方格的中心作为采样点;
  4. 对采样点像素进行双线性插值,得到该采样点的像素值;
  5. 对每个单元格内的 4 个采样点进行 max pooling,得到最终的 ROI Align 结果。
    在这里插入图片描述

3、(How?)如何实现RoIAlign

先贴出一张图,接着通过这图解释Roi Align的工作原理。
在这里插入图片描述
1. 根据输入的原始image,将提取的候选框region proposal映射到feature map的对应位置上,得到ROI

输入一张

800

×

800

800×800

800×800的图像,在图像中有两个目标(猫和狗)。其中,某一region proposal(如:狗)的Bounding Box大小为

665

×

665

665×665

665×665。经过VGG16网络后,可以获得region proposal映射到feature map上,所得ROI的特征图大小为

20.78

×

20.78

20.78×20.78

20.78×20.78,此时,没有像ROI Pooling那样就行取整操作,直接 保留浮点数

2. 将映射后的ROI区域划分为相同大小的块sections

假定输出的

p

o

o

l

e

d

w

=

7

,

p

o

o

l

e

d

h

=

7

pooled_w=7, pooled_h=7

pooledw=7,pooledh=7(即:经过max pooling后固定成

7

×

7

7×7

7×7大小的特征图。)将

20.78

×

20.78

20.78×20.78

20.78×20.78的ROI的feature map划分成49个同等大小的块sections,每块的大小为

2.97

×

2.86

2.97×2.86

2.97×2.86(计算公式:

20.78

/

7

=

2.97

20.78/7=2.97

20.78/7=2.97)。此时,仍不做取整操作,继续 保留浮点数

3. 确定采样点数,对每一小块section先进行再次分块(分块数量等于采样点数),获得各个采样点的像素值,然后进行max pooling操作;

假定采样点数为4,即表示:对于每个

2.97

×

2.97

2.97×2.97

2.97×2.97的小区域,平分四份,每一份取其中心点位置,关于中心点位置的像素,采用双线性插值法进行计算(双线性插值核心思想就是哪个点举例采样点近,那个点发挥的作用就更大)。这样,得到四个采样点的像素值,如下图:
在这里插入图片描述

上图中的四个 x 对应四个小区域的中心点。(备注: 更加精细的插值会得到更加平滑的边界。)最后,取这四个中心点像素值的max作为这个小区域(即:

2.97

×

2.97

2.97×2.97

2.97×2.97大小的区域)的像素值,如此类推,同样是49个小区域得到49个像素值,组成

7

×

7

7×7

7×7大小的feature map。

综上可知:RoI Align主要解决了RoI pooling在回归框定位时出现的偏差,在对于小目标的精细回归问题上,RoI Align精度更高。所以,在以后的项目中可以根据实际情况进行方案的选择;对于检测图片中大目标物体时,两种方案的差别不大,而如果是图片中有较多小目标物体需要检测,则优先选择RoiAlign,更精准些…

参考链接:
目标检测特殊层:ROI Align层详解

RoIPooling、RoIAlign笔记

ROI Pooling和ROI Align详解

【温故知新】RoI Pooling与RoI Align

【Mask RCNN】论文详解(真的很详细)

在这里插入图片描述

ROI-Pooling与ROI-Align的异同

ROI-Pooling与ROI-Align的相同点:

RoI pooling与RoI Align都是在ROI生成的feature map上进行下采样,使得固定输出特定尺寸(一般为

7

×

7

7×7

7×7)的新的feature map,再进行后续的分类与框的回归。由于要进行框的回归,所以位置的准确度就尤为重要。

ROI-Pooling与ROI-Align的不同点:
在这里插入图片描述
在Faster RCNN中,步骤二和步骤三要经过量化处理,来对齐特征图坐标。每经过一次量化,就会造成原图目标的像素丢失。

在特征图中,只有整数坐标的位置会有像素值,而浮点坐标没有对应像素值,所以需要向下取整,对齐特征图。
在这里插入图片描述
在Mask RCNN中,步骤二和步骤三不做量化处理,保留浮点数坐标位置不变,经过双线性插值为浮点坐标匹配特征值。

在特征图中,整数坐标和浮点坐标的位置都会有特征值,而浮点坐标的特征值需要通过整数坐标的特征值做双线性插值处理。

上图中,每一个小方格有两层含义:1、特征的坐标;2、表示的特征值

参考链接:
目标检测之ROI-Pooling与ROI-Align的异同
Deep learning for satellite imagery via image segmentation

RoIPooling与SPP的异同

SPP具体结构:
在这里插入图片描述
SPP层的具体结构如上图,使用三层ROI Pooling层组成的SPP层,分别设置将图片切分成(1,4,16)块。这里是采用了论文中的设置参数(1,4,16);

将Selective Search算法提供的1000-2000个候选框的位置记录下来,然后通过比例映射到整张图像的feature map上,每个候选框得到一个自己的候选区域的特征图B,然后将B同时送入上面的SPP层的3个ROI Pooling层;

SPP层第一层将整个特征图B进行池化,第二层将特征图B切分成4个小的特征图再池化,第三层将特征图B切分成16个小的特征图再池化。分别得到1、4、16个特征值;这21个特征值经过softmax函数后就可以分类了。

参考链接:
ROI pooling层计算过程

和SPP对比,RoIPooling就是只有一层(尺度)的SPP。
在这里插入图片描述

附录:双线性插值法

一维线型插值法:

如下图所示,我们最了解的直线之间的插值示意图:
在这里插入图片描述
我们已经知道(x0,y0)与(x1, y1)的值,并且已知 x 的值,要求 y 的值。根据初中的知识:
在这里插入图片描述
就是直线上的点,正切值,是一样的,下面进行变换,让x轴上的比例为一个a:
在这里插入图片描述
再变换,我们要求出y:
在这里插入图片描述
变换一下,更方便记忆,如下式:

y

=

(

1

k

)

y

0

+

k

y

1

y=(1-k)*y_0+k*y_1

y=(1k)y0+ky1
二维线型插值法:

双线性插值是做了二次一维的线性插值,我们用四个最近邻估计给定的灰度。我们新图像的像素点对应输入图像的

u

0

,

v

0

(

u

0

,

v

0

)

(u_0 , v_0)(u_0,v_0不是整数)

u0,v0(u0,v0),则其必定落在原始图像四个像素点中间。四个像素点分别是

u

,

v

u

,

v

+

1

u

+

1

,

v

u

+

1

,

v

+

1

(u’ , v’ )、(u’ , v’ +1)、(u’+1 , v’ )、(u’ +1, v’+1 )

u,vu,v+1u+1,vu+1,v+1。如下图1所示:

(图中,

u

v

u ,v

uv 分别是平面上的位置坐标,

g

g

g 轴是色深,也就是可以想象为颜色值的坐标)
在这里插入图片描述
图一

如图1所示:在红色平面内,在红色平面内,只有

u

u’

u 是变量,

v

v’

v 是常值,连线

g

(

u

,

v

)

g

(

u

+

1

,

v

)

g(u’ , v’ )、 g(u’+1 , v’ )

g(u,v)g(u+1,v),相当于做一次一维线性插值,求出

g

(

u

0

,

v

)

g(u_0, v’ )

g(u0,v)的值。同理,如图3中,在蓝色的平面内我们可以再做一次一维线性插值,求出

g

(

u

0

,

v

+

1

)

g(u_0, v’ +1)

g(u0,v+1)的值。同理如图4,在黑色的平面内,我们可以求出

(

u

0

,

v

0

)

(u_0, v_0)

(u0,v0)对应的值

g

(

u

0

,

v

0

)

g(u_0, v_0)

g(u0,v0)的值。(双线性插值就是分别在

u

v

u、v

uv方向上做线性插值)数学推导过程如下:(图中用线圈起来的就是代表每一个公式)
在这里插入图片描述
图二
在这里插入图片描述
图四
在这里插入图片描述
最后的推导公式:

总推导公式

在这里插入图片描述
ROI-Align 原理理解

双线性插值的平面示意图:
在这里插入图片描述
上图即为双线性插值计算近似像素的方法:利用四个角点的像素以及与需计算点构成的矩形面积比例进行加权求和。
已知

Q

12

Q

22

Q

11

Q

21

Q_{12},Q_{22},Q_{11},Q_{21}

Q12Q22Q11Q21,但是要插值的点为

P

P

P,这时就要用双线性插值了,首先在

x

x

x 轴方向上,对

R

1

R_1

R1

R

2

R_2

R2 两个点进行插值,这个很简单,然后根据

R

1

R_1

R1

R

2

R_2

R2

P

P

P 点进行插值,这就是所谓的双线性插值。

参考链接:【摘记】ROI Pooling and ROI Align

版权声明:本文为CSDN博主「Yale曼陀罗」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42782150/article/details/110946903

Yale曼陀罗

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐