FPN改装faster-RCNN

请输入图片描述

利用FPN构建Faster R-CNN检测器步骤
首先,选择一张需要处理的图片,然后对该图片进行预处理操作;
然后,将处理过的图片送入预训练的特征网络中(如ResNet等),即构建所谓的bottom-up网络;
接着,如图5所示,构建对应的top-down网络(即对层4进行上采样操作,先用1x1的卷积对层2进行降维处理,然后将两者相加(对应元素相加),最后进行3x3的卷积操作,最后);
接着,在图中的4、5、6层上面分别进行RPN操作,即一个3x3的卷积后面分两路,分别连接一个1x1的卷积用来进行分类和回归操作;
接着,将上一步获得的候选ROI分别输入到4、5、6层上面分别进行ROI Pool操作(固定为7x7的特征);
最后,在上一步的基础上面连接两个1024层的全连接网络层,然后分两个支路,连接对应的分类层和回归层;

请输入图片描述

reference:


RPN详解

目的是筛选出图片中有可能存在物体的坐标,供后面的分类使用

请输入图片描述

首先anchor是人为定义的,不是体现在网络里的具体结构,每个feature的像素在3x3卷积后的数据就包含k个anchor的信息在里面了

经过backbone输出一个512维向量(featuremap是例如vgg这类特征提取网络出来的,所以是512),再分别喂给两个网络class(cls)和regression(reg)网络,前者输出2-d的数据,代表是前景、背景的概率,也就是单纯判断是否存在物体(逻辑回归),后者输出4-d的数据,其代表物体的具体位置(x,y,h,w)(线性回归输出数值);

请输入图片描述

如果这个anchor有k个,那么cls就会产生2k个分类值和reg的4k个位置信息

其中cls决定了k个anchor中哪些是有物体的,reg则是决定了所有的anchor的具体大小

进一步理解RPN的操作(这里我的理解和网上的大都不一样,毕竟没有去看caffe写的源码((( )

当backbone为VGG-16时,去掉FC和最后一层池化输出的strides为16,当输入的图为800x600,则到featuremap中的大小为$512*50*37$,那么经过3x3滑动窗口后会产生$512*50*37$的featuremap输出给后面的cls和reg

当k=9时

在cls中:

利用1x1卷积输出$18*50*37$的数据,reshape成$2*9*50*37$,这里相当于有$50*37$个点的判断,通过softmax判断0轴,即9个anchor中,哪个置信度最大,输出$9*50*37$

reg中:

同上先利用1x1转换为$36*50*37$的数据,reshape成$4*9*50*37$(4代表w,h,x,y),在proposal中输出上面cls中各自对应的置信度最大的anchor对应通道的值(也就是前面的9里选1个),输出为$4*50*37$,这里相当于输出了$50*37$个某类anchor的坐标

于是最后经过proposal处理后,RPN对应每个feature上的点,输出一个5维向量(p,w,h,x,y)(p是cls输出的置信度),即最后输出的shape为$5*50*37$,也就是$50*37$个候选框,在这里才会通过例如NMS这样的算法合并或者舍弃保留候选框。

经过Proposal Layer的时候,其loss为

请输入图片描述

i为被选中的anchor框,$ p^*_i$是anchor是否是有效的意思,取值为(0,1),$t^*_i$是维度为4的(w,h,x,y)标签位置向量,$t_i$是偏移量,下面解释。

$N$为归一化项

$N_{cls}$可以简单定义为输入图片的Size(比如输入图片为256x256($H*W$),那么经过vgg16输出后为16x16,那么$N_{cls}=\frac{H*W}{Stride^2}=16*16=256$就可以了),

$N_{reg}$为被定位的anchor的数量,当feature的每个像素有9个anchor,输入图片的size=256时,$N_{reg}=9*16*16=2304$,文中取了个大约值2400

$L_{cls}$用的是L1范数

$L_{reg}$是bounding box regression的拟合方法(在这篇2.4节讲的很透彻

$\lambda$是分类和位置的权重,默认为10

$t_i$是偏移量,里面有4个参数,用来平移、缩放预测框,以此与groundtruth的$t^*_i$衡量。

如果只使用坐标之间的平移量就是复杂线性问题,需要通过$t_i$中的变换成为可以用cnn解决的简单线性问题

细说$L_{reg}$

这个loss主要解决的,是如何将复杂的线性关系(如真实值与预测值直接的差值)转变为可以计算的y=wx 可以被cnn计算的方法

变换的原理bounding box regression原理(在这篇2.4节讲的很透彻),这里讨论只实现的方法:

首先,$L_{reg}(t_i,t^*_i)=R(t_i-t^*_i)$,R代表L1范数,$t$是偏移量,$i$是被选中的anchor序列;

$t_i$代表预测偏移量,里面包含4个变量数:$t_x,t_y,t_w,t_h$代表anchor的$x_a,y_a,w_a,h_a$相对于预测值$x,y,z,w$的偏移量,

$t^*_i$代表ground truth,同理里面也有四个变量,代表$x^*,y^*,w^*,h^*$对应相对于anchor的偏移量,实现的方法如下:

$$ t_x = (x − x_a)/w_a, \ t_y = (y − y_a)/h_a, \\ t_w = log(w/w_a), t_h = log(h/h_a), \\ t^∗_x = (x^∗ − x_a)/w_a, t^∗_y = (y^∗ − y_a)/h_a, \\ t^∗_w = log(w^∗/w_a), t^∗_h = log(h^∗/h_a), $$

这个loss的意义,就在于让预测值和真实值相对于anchor的偏差量最小化,因此,我们可以让reg网络直接输出预测偏差值$t_x,t_y,t_w,t_h$,然后基于anchor的坐标算出$t^*_x,t^*_y,t^*_w,t^*_h$再进行loss计算,这样可以使得每个侦测到物体的预测框都能学习到物体特征。

那么anchor的思想体现在哪呢?

体现在训练网络的时候,先确定每个点的anchor大小,

请输入图片描述

当图像中对某点的物体与anchor的IOU大于一定值时(这个值应该设置为接近1),将该点的对应的anchor置信度label标记为1,小于某个接近0的值时标记为0,这样就可以使得网络中的对应anchor只有当尺寸合适时置信度才会高,所以这就是一开始说的anchor大小是人为定制的,它并不体现在网络结构上


PS:RPN利用了CNN的平移不变性来决定区域

ROIpooling

请输入图片描述

输入通过RPN网络输出建议的区域坐标,映射在featuremap对应位置上

类似于spp根据输入图片的大小来改变池化层大小和步长,产生固定大小的输出

举个例子,假设我现在有一个8x8的featuremap,我的RPN给出了一个对应下图的5x7的区域:

请输入图片描述

我要输出的大小为2x2,那么根据类似sppnet的想法,roi中bin大小的计算方法:

请输入图片描述

上面这句注释的意思是RoI Pooling结果的每个bin在RoI中起始和结束的index。
比如对于上图来说最终RoI Pooling的结果的第0个bin,其实际计算应该是:

$start_{0h}=floor(0*5/2)=0 $

$end_{0h}=ceil(1*5/2)=3 $

$start_{0w}=floor(0*7/2)=0 $

$end_{0w}=ceil(1*7/2)=4 $

所以

$Pool[0,0]=Max(Roi[0:3,0:4])$

同理可得

$Pool[0,1]=Max(Roi[0:3,3:7])$

$Pool[1,0]=Max(Roi[2:5,0:4])$

$Pool[1,1]=Max(Roi[2:5,3:7])$

也就是实际上应该如下图划分bin:

请输入图片描述

最后输出的结果为:

请输入图片描述

  • reference:

https://zhuanlan.zhihu.com/p/66124459


但是这种ROIpooling有两个量化误差的问题

只会在训练的时候出现的问题

1.图片缩放时,标记位置取整造成的误差

训练的时候原图Size为800x800,标记的区域为600*600,经过backbon(假设是上面的VGG16)后原图尺寸缩小为25x25,而标记区域则变为18.75x18.75,根据c++源码中取整的操作,会变成18x18,这就会0.75的偏差,放大了就是24像素的偏差。

2.Roi池化时,为输出对应尺寸造成的误差

拿上面的结果来说,假设我现在要把这个18x18的proposal区域经过ROi变成7x7,根据源码可知会通过

$ ksize=math.floor(\frac{20}{7})=2$

$ stride=math.ceil(\frac{20}{7})=3$

来构造池化核。

这个ksize中的尺寸本应为2.857,但是为了池化核的构造而向下取整,并且因为stride比ksize还大就造成再一次的量化误差。


为了解决这两个问题,何凯明提出了

ROI Align(论文地址)

不是使用普通池化的方法滑动池化核,而是一种直接按对应位置给出池化值的方法

1.图片标记位置时,保留其小数点,并在featuremap上映射出带小数点的对应位置,这就是proposal区域

2.根据pool后要输出的尺寸定义bin的个数(如要输出7x7那就是7x7个bins)

3.把proposal区域用上面的bin等比例划分区域

4.每个bin再等分为4个dots,每个dot的取值根据featuremap中的像素点双线性插值确定

5.每个bin的值取其dot的极值(Roi中是取极值),起到池化的作用

6.得到7x7后的池化值。


Precise ROI Pooling

如果对你有帮助就太好了)))