Faster RCNN

Faster R-CNN for object detector

简单画了一个Faster RCNN:

Faster-RCNN

上图简单画了下faster rcnn的结果部分的流程图。大致faster rcnn分为:vgg、get anchor、rpn、proposal、prediction几部分。下面每个模块具体解释一下。

一、 VGG

​ 这层的cnn功能就是特征提取。对输入[1, W, H, 3]的图片(这个batch size我设为1了)。进行多层卷积操作。输出是一个[1, W/16, H/16, 512]维的特征形式。我们可以称为feature map。后面很多操作都是基于feature map来的。我们令P = W/16, Q=H/16。这里的倍数16是在后面找原图和feature map的anchor对应关系时要用到的比例。

二、 Get all Anchor

这一块呢是对feature map上的每个点,我们都产生9个anchor值。则一共有 个anchor。这里的anchor就是以每个点为中心的box。作者写的generate_anchor函数运行之后得到的9个anchor输出如下:

-83 -39 100 56

​ -175 -87 192 104

-359 -183 376 200

-55 -55 72 72

-119 -119 136 136

​ -247 -247 264 264

-35 -79 52 96

-79 -167 96 184

-167 -343 184 360

每一行四个数分别代表xmin, ymin, xmax, yamx。中心点坐标都是(7.5, 7.5)。分别对应了三个box面积尺寸分别为[128, 256, 512],进行宽高ratio=[0.5, 1, 2]三个尺寸的缩放。过程:

首先三个面积分别为:[512, 256, 128],然后开方求对应边长(取整数):[23, 16, 11]作为宽w。高h等于w*ratio=[12, 16, 22]。以7.5,7.5为中心以上面w, h可以得到如下anchor:

(xmin, ymin, xmax, ymax) <—> (w, h, x_ctr, y_ctr)

[[-3.5 2 18.5 13], [[23.0 12.0 7.5 7.5],

[0, 0, 15, 15], [16.0 16.0 7.5 7.5],

[2.5, -3, 12.5, 18]] [11.0 22.0 7.5 7.5]]

这样得到对每一行处理,第一行[-3.5,2,18.5,13]得到[23.0,12.0,7.5,7.5]。对宽和高再取 [8, 16, 32] 三个比例值得到w:[184,368,736.],h:[96,192, 384]。这样然后再以(7.5, 7.5)为中心得到3个anchor。比如w=184,h=96。得到:-83 -39 100 56这个anchor。同理其他两行也一样。

anchor得到以后都要映射到原图像上的。上面说了一个点有9个anchor,那么对于特征图大小[P, Q]每个点都有9个anchor。但是[P, Q, 512]不是原图像,我们要找到[P, Q]上每个点和原图像[W, H]每个点的对应关系。方便说明我们假设P =4, Q=4。那么P,Q在原图像对应点左边就是:

P/Q:[0, 1, 2, 3] 原图上W/H:[0, 16, 32, 48]

因为一般图像上原点是图像左上角,向下为y轴正方向(高),向右为x正方向(宽)。分别以W为图像横坐标位置,H为纵坐标得到(0, 0),(0, 16), (0, 32), (0, 48), (16, 0), (16, 16), ….(48, 48)。一共16个坐标点。然后以每个坐标点为中心在应用上面9个anchor,每个点得到9个box。每个新的anchor=[xmin + x_ctre, ymin+y_ctre, xmax+x_ctre, ymax+y_ctre]。这样就得到了初始的每个点的anchor。我们用 来表示上面得到的每个anchor的中心点坐标以及这个anchor的宽和高,我们称其为标准的anchor输出。其实这里的anchor已经可以叫box了。

三、 RPN

Anchor得到后我们就可以进行rpn部分了。这里主要是通过卷积网络得到每个anchor的是否是目标的概率值以及每个anchor的偏差值。

由上图可以看出模型输入就是vgg得到的feature map,大小是[P, Q, 512](省略了batch size)。论文里说以33为感知野进行卷积操作,即相当于对整个feature map做一个卷积核大小为[3, 3],卷积核个数为512512的卷积操作。输出大小任然是[P, Q, 512]。然后对这个特征在并行两路分别处理。

cls regression:一路进行[1, 1, 512, 18]的卷积操作。输出大小是[P, Q, 92]。这里很好理解,每个点有9个anchor,相当于对每个anchor对应生成一个12的向量,用来表示这个anchor是不是目标。我们可以令[1, 0]代表这个anchor是目标,[0, 1]表示是框的是背景。当然,因为要归一化到0,1所以要经过一个简单的reshape把每个12的向量单独分出来再做一个softmax分类。这样分类之后再reshape回去就可以了。这一路输出得到输出大小是[1, P, Q, 92]。

bounding box:另一路同样经过[1, 1, 512, 94]的卷积操作得到[P, Q, 94]的输出,对应的是每个点的每个anchor的四个偏移量 。为什么要四个偏移量呢,因为我们前面的anchor就是一个定值,而实际的物体box和前面的anchor肯定有偏差。所以我们再用四个偏差来进行一次box的修正。修正方法如下:

我们默认如下变量定义:rpn输出的anchor偏移值 。标准的anchor生成函数得到的anchor值对应到不同坐标点上后得到的box的值: 。这都是上面介绍过的了。那么我们的修正后的box如下公式:

修正后的box: 分别为中心点以及宽和高,我们称为第一次修正后的box。这里相当于对标准的anchor先做中心点平移再做宽高的尺度缩放。下图黑色输出的标准的anchor,我们想将其修正为红色的box(即第一次修正后的box),绿色的是真实的box(即ground true)。

四、 Proposal

通过上面我们得到了第一次修正后所有的box以及每个box所对应的概率,下面这个是proposal过程,这一过程是再根据每个box的值选取出合适的部分box,并再反向投影到前面得到的[1, P, Q, 512]的feature map上。我们需要的是rpn输出的rpn cls prob这一项(shape:[1, P, Q, 29]代表每个box是目标物体的概率)还有我们第一次修正后的box值(shape:[1, P, Q, 49]):

首先我们对所有第一次修正后的box进行判断,如果box的大小超出了边界,那么就将这一边改成边界值,我们令这个修正后的输出是proposal_clip_box:

然后对所有输出的proposal_clip_box和真实的边界ground-true来求重合度IOU值。

IOU比较好理解,假设proposal_clip_box的面积为SA,真实box面积为SB,两者的重叠面积为 。那么IOU:

IOU代表了我们的输出proposal_clip_box和标准box的重合率,我们希望的是重合度越大越好。当然这里有点问题就是真实的box可能有很多个,那么对于proposal_clip_box我们怎么比较IOU呢?按照代码里的理解:

首先用scores表示rpn cls prob这一项。[1, P, Q, 2*9],我们先取出第四个维度的后九个数。用后九个数的大小表示fg(真实物体)的概率。

那么reshape成向量:scores=[1, PQ9]。我们再按大小排序后取出对应的索引值(这里用了argsort()函数,并没有改变scores每个数的位置,只返回其从小到大的数的位置的索引)。我们再取scores比较大的前topN个(12000),然后因为有scores的索引值就可以将对应proposal_clip_box的值取出来。然后再进行NMS(非极大值抑制)。

所谓非极大值抑制:先假设有6个输出的矩形框(即proposal_clip_box),根据分类器类别分类概率做排序,从小到大分别属于车辆的概率(scores)分别为A、B、C、D、E、F。

(1)从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU是否大于某个设定的阈值;

(2)假设B、D与F的重叠度超过阈值,那么就扔掉B、D;并标记第一个矩形框F,是我们保留下来的。

(3)从剩下的矩形框A、C、E中,选择概率最大的E,然后判断E与A、C的重叠度,重叠度大于一定的阈值,那么就扔掉;并标记E是我们保留下来的第二个矩形框。

就这样一直重复,找到所有被保留下来的矩形框。

如上图F与BD重合度较大,可以去除BD。AE重合度较大,我们删除A,保留scores较大的E。C和其他重叠都小保留C。最终留下了C、E、F三个。

上面整个过程:

我们得到的就是保留下来的2000个box(称为blob)。然后下面就是真正的proposal过程,将这些blob反向投影到前面的feature map上得到对应的2000个rois。Blob表示的是原图上的box大小,rois表示的是投影到[1, P, Q, 512]的feature map上时对应的box大小。经过这个反向投影就得到了2000个roils了(图里维度是[2000,5]而不是[2000,4]是因为加了一维全0的项用于表示一个图片,要是多张图片就要改了)。

五、 Predicton

前面得到了所有的roils后就可以进行最后的预测模型了。假设我们的一个roils取出来大小是[10, 10, 512]即从原图像投影到feature map上大小变成[10, 10]。我们后面分类的时候要复用同一个卷积网络,所以对不同大小的roils要池化成同一个大小的输入:这里统一池化成[7, 7, 512]。

Roi pooling也比较清楚,将输入特征先进行 的均匀划分,然后对分的每一块进行max pooling即可。 太大,我们以 输出为例子:

输入是 ,所以划分为 ,第一个格大小为: ,第二个格子: 。划分为格子后在对每个小格子做max pooling就好了。 输出一样。如果输入大小还不到 的话那么可以再输入周围进行简单的补零操作就好了。

经过前面roil pooling后我们对每个roils得到了固定尺寸的特征矩阵。然后可以进行分类卷积操作。分类时一样进行两路。两路输入都是[256, 7, 7, 512],256代表有多少个roils。将这个值进行两次全连接输出[256, 4096]。然后再分开两个全连接,一个输出大小[256, classes numbers], classes numbers是我们的目标物体分类数,假设是10分类的任务,那么就是10。输出经过softmax后是One hot形式。另一路输出[256, classes numbers*4],表示对256个box的第二次修正偏差值 。因为上面虽然修正一次了但是可能还不太正确,这里再修正一次。修正方法和上面一样。修正后就可以得到我们最后真正的输出了。同样还可以得到每个box的分类概率。通过分类概率大小我们设置一个阈值,当分类概率达到一定阈值之后才输出。这样就可以将所有可能的目标的box和分类类别画出来了。

六、 Loss Function

​ 模型loss function分为两部分,一部分是第一次修正时的输出和标准label的loss,第二部分是最后的输出和标准label的Loss,第一部分:

:模型预测含有目标的概率,[0, 1]之间。

是标准的label,表示这个box有没有目标。

:一个minibatch中anchors的个数,我们取的是256个。 是交叉熵损失函数。所以这里的 应该是上面的rpn cls scores,是未经过softmax处理的值。 即第一次修正的输出 。 表示由ground true算出来的偏差值。即:

其中 分别表示ground true的中心点坐标以及宽和高。 表示标准的anchor输出的中心点以及宽高,和上文介绍一样。这样我们就算出来了ground true的偏差值,就可以和模型的输出进行loss计算。 是常量系数10, 表示bounding box回归的anchor数,这里取是2000。 表示smooth l1 loss函数:

同理对于第二次修正我们又可以算一次loss,但是这里输入稍微有些改变:

​ 这里 表示模型最后输出的cls predicition的分类概率形式(未经过softmax的), 表示真正的分类概率,是个one hot形式。然后 这里也是交叉熵函数。 是第二次修正的偏差值(中心点及高宽)。 还是表示由ground true算出的真实偏差。最后我们将两个loss相加就可以求导了。

RCNN:根据颜色纹理等来找框,归一化到227*227,分类SVM。

YOLO: 整张图化为77网格,图片直接卷积操作输出,每个格子预测两个目标,输出结果为每个格子的置信度和坐标位置。但是77太粗糙,对小物体检测不好。

SSD:SSD除了再最终特征图上预测之外还在之前的5个特征图上进行预测。整张图化为88网格+多个anchor形式,然后使用FCN网络。不同层的feature map也是33但是感知野就不同了可以都用做分类检测不同的尺寸物体。