Faster-rcnn学习笔记,从理论到代码思路详解。

Faster-rcnn学习小记

整整花了两天时间才看懂faster-rcnn,悟出来一个道理,纸上得来终觉浅,绝知此事要coding。
先放几个讲得很好的大佬博主的链接。
真大佬,我见过最详细的Faster-rcnn
也很牛逼,徒手撸Faster-rcnn
[讲的也很好]
我下面写的应该没有第一位大佬写的详细,我仅仅是从我学习过程中理解展开讲解。若是零基础的童鞋强烈建议大家看看第一个大佬的讲解。最后觉得有帮助的记得点个赞和关注,会持续更新机器学习,计算机视觉的内容。
废话不多说,放图!!!
在这里插入图片描述
这就是faster-rcnn的网络结构图。首先输入图片可能是PxQ或者其他尺寸的,我们统一对齐进行resize到MxN。然后进过我们都熟悉的VGG-16网络,输出feature-map。下面放一下vgg16的示意图:
在这里插入图片描述
这里有一个需要注意的地方就是:

所有的conv层都是:kernel_size=3,pad=1,stride=1
所有的pooling层都是:kernel_size=2,pad=0,stride=2

这些设置就是为了保证图片经过conv层output_size == input_size,但是经过pooling层以后output_size ==1/2input_size.(我相信你应该知道为什么!)
现在生成了feature-map了,到了下面真正的rpn网络的部分了。

这个时候我们先不急于介绍rpn的网络,我们先来科普几个专有词汇(若是现在看不懂的话,看到后面在翻上来看):

BBox:全称是bounding box,边界框。其中Ground Truth Bounding Box是每一张图中人工标注的框的位置。一张图中有几个目标,就有几个框(一般小于10个框)。Faster R-CNN的预测结果也可以叫bounding box,不过一般叫 Predict Bounding Box.

Anchor:锚?是人为选定的具有一定尺度、比例的框。一个feature map的锚的数目有上万个(比如 20000)。

RoI:region of interest,候选框。Faster R-CNN之前传统的做法是利用selective search从一张图上大概2000个候选框框。现在利用RPN可以从上万的anchor中找出一定数目更有可能的候选框。在训练RCNN的时候,这个数目是2000,在测试推理阶段,这个数目是300(为了速度)我个人实验发现RPN生成更多的RoI能得到更高的mAP。

RoI不是单纯的从anchor中选取一些出来作为候选框,它还会利用回归位置参数,微调anchor的形状和位置。

可以这么理解:在RPN阶段,先穷举生成千上万个anchor,然后利用Ground Truth Bounding Boxes,训练这些anchor,而后从anchor中找出一定数目的候选区域(RoIs)。RoIs在下一阶段用来训练RoIHead,最后生成Predict Bounding Boxes。

loc: bbox,anchor和RoI,本质上都是一个框,可以用四个数(y_min, x_min, y_max, x_max)表示框的位置,即左上角的座标和右下角的座标。这里之所以先写y,再写x是为了数组索引方便,但也需要千万注意不要弄混了。 我在实现的时候,没注意,导致输入到RoIPooling的座标不对,浪费了好长时间。除了用这四个数表示一个座标之外,还可以用(y,x,h,w)表示,即框的中心座标和长宽。在训练中进行位置回归的时候,用的是后一种的表示。

接下来真正开始介绍Faster-rcnn的核心RPN:
在这里插入图片描述

RPN网络结构

可以看到RPN网络实际分为2条线,上面一条通过softmax分类anchors获得positive和negative分类,下面一条用于计算对于anchors的bounding box regression偏移量,以获得精确的proposal。而最后的Proposal层则负责综合positive anchors和对应bounding box regression偏移量获取proposals,同时剔除太小和超出边界的proposals。其实整个网络到了Proposal Layer这里,就完成了相当于目标定位的功能。
至于一开始的这个3x3的卷积是干什么的,相当于每个点又融合了周围3x3的空间信息,我猜测是为了使模型的鲁棒性更好吧。下面接两个1x1的卷积,假设在conv5 feature map中每个点上有k个anchor(默认k=9),而每个anhcor要分positive和negative,所以每个点由256d feature转化为cls=2k scores;而每个anchor都有(x, y, w, h)对应4个偏移量,所以reg=4k coordinates。
至于多通道图像卷积的知识,不懂得可以看看第一个链接,或者你只需要记住:对于某个卷积层,无论输入图像有多少个通道,输出图像通道数总是等于卷积核数量!
下面讲一个主要的东西:Anchor,anchor_ratio就是这些框框的长宽比,anchor_scale就是放缩比例,也就是输入图片的尺寸比上feature map的尺寸。比如输入图片是3×224×224,feature map 是 512×14×14,那么scale就是 14/224=1/16。(下面还会重点讲一下Anchor的前世今生!!!
在这里插入图片描述
其实RPN最终就是在原图尺度上,设置了密密麻麻的候选Anchor。然后用cnn去判断哪些Anchor是里面有目标的positive anchor,哪些是没目标的negative anchor。所以,仅仅是个二分类而已!

那么Anchor一共有多少个?原图800x600,VGG下采样16倍,feature map每个点设置9个Anchor,所以:(800/16) x (600/16)x9=50x38x9=17100 除不尽,注意向上取整
在这里插入图片描述

分类

回到我们的rpn网络,先来看上面的这一条,上面这一条的作用是用于分类,区分出anchor中的正样本和负样本:
在这里插入图片描述
这里先做了1x1卷积,由于卷积层的输出定义为18,所以我们最后的feature_map的输出也为18维。经过reshape和softmax以后feature maps每一个点都有9个anchors,同时每个anchors又有可能是positive和negative,所有这些信息都保存WxHx(9*2)大小的矩阵。至于前后这两个reshape是干啥的,就是因为caffe的实现形式,将[1, 2x9, H, W]变为[1, 2, 9xH, W]大小,即单独“腾空”出来一个维度以便softmax分类,之后再reshape回复原状。

回归

接下来该讲下面这一条线了,又到了数学知识的时候了。看图!
在这里插入图片描述
绿色框为飞机的Ground Truth(GT),红色为提取的positive anchors,明显看得出来我们的预测是不准确的。对于窗口一般使用四维向量 (x,y,w,h)表示,分别表示窗口的中心点坐标和宽高。为了省事,我就直接贴图了(第一个链接的大佬的图):
在这里插入图片描述
在这里插入图片描述
接下来我们的任务就是求出下面这四个量:
在这里插入图片描述
下面结论的建立都是在预测框与目标框相接近的情况下,这是我们就可以使用线性的方法。
在这里插入图片描述
在这里插入图片描述
数学完了,接下来看网络结构,下面这条线很简单一个1x1的卷积,输出是36维。

proposal Layer

Proposal Layer负责综合所有 [公式] 变换量和positive anchors,计算出精准的proposal,送入后续RoI Pooling Layer。再看一遍这个图,我们可以观察到 右下角有一个im_info输入到proposal了,这个im_info就是前面讲到的scale,用于计算最后偏移量。
在这里插入图片描述
Proposal Layer forward(caffe layer的前传函数)按照以下顺序依次处理:

1、生成anchors,利用dx,dy,dw,dh对所有的anchors做bbox regression回归(这里的anchors生成和训练时完全一致)
2、按照输入的positive softmax scores由大到小排序anchors,提取前pre_nms_topN(e.g. 6000)个anchors,即提取修正位置后的positive anchors
3、限定超出图像边界的positive anchors为图像边界,防止后续roi pooling时proposal超出图像边界(见文章底部QA部分图21)
4、剔除尺寸非常小的positive anchors
5、对剩余的positive anchors进行NMS(nonmaximum suppression)
6、Proposal Layer有3个输入:positive和negative anchors分类器结果rpn_cls_prob_reshape,对应的bbox reg的(e.g. 300)结果作为proposal输出
之后输出proposal=[x1, y1, x2, y2],注意,由于在第三步中将anchors映射回原图判断是否超出边界,所以这里输出的proposal是对应MxN输入图像尺度的,这点在后续网络中有用。另外我认为,严格意义上的检测应该到此就结束了,后续部分应该属于识别了。
RPN网络结构就介绍到这里,总结起来就是:
生成anchors -> softmax分类器提取positvie anchors -> bbox reg回归positive anchors -> Proposal Layer生成proposals
重点来了:
看到现在我们的RPN就算是讲完了,原理是懂得差不多了,但是具体实现的话还是有一些不清不楚的地方。(反正我是有这么一个疑问,大概是源于我对神经网络的理解比较浅吧)
问题:我们经过vgg16得到的是feature_map,那我们的9种anchors是怎么对应到原图的呢?又是怎么对所有的anchors做bbox regression回归的呢?看一张另一位大神的流程图,先忽略右下角的那个部分(后面会讲。)**我们可以看到,最终传入rpn的只有feature_map和bbox,那么anchor是怎么来的呢?其实还有一个参数也传进来了,细心的同学应该马上就知道了,就是scale!所以,我们可以根据我们设定的每个feature_map点有k==9个anchors,根据anchors_ratio=(0.5,1,2)还有anchor_scale=[8,16,32],这里我们默认基础的anchor的大小是16x16的,所以我们得到的三个尺度的框就是16x8=128,16x16=256,16x32=512.然后我们再计算出针对每一个feature_map点上的位置偏移量(因为我们的基础anchor是16x16的,所以要想对应回原图的话,就得算出相应的位置偏移量,也就是0,16,32,48…等),最后把每个feature_map的9个anchor与位置偏移量进行对应就可以得到最后的原图上的anchor了。我们就可以设计出9种anchors然后再用scale就定位到原图了。这时候返回的anchors参数就是anchors在原图中的4歌位置参数。**下面是一组返回的参数。
[[ -84. -40. 99. 55.]
[-176. -88. 191. 103.]
[-360. -184. 375. 199.]
[ -56. -56. 71. 71.]
[-120. -120. 135. 135.]
[-248. -248. 263. 263.]
[ -36. -80. 51. 95.]
[ -80. -168. 95. 183.]
[-168. -344. 183. 359.]]

在这里插入图片描述
有了anchors以后我们又知道bbox,所以很轻松可以求出iou。
接下来我们先对近20000个anchors筛选掉超出图片大小的部分,也叫clip anchor。
在这里插入图片描述
这里需要注意一下,我们最终的loss函数有4个组成部分(先记住):
RPN 分类损失:anchor是否为前景(二分类)
RPN位置回归损失:anchor位置微调
RoI 分类损失:RoI所属类别(21分类,多了一个类作为背景)
RoI位置回归损失:继续对RoI位置微调

开始我一直不明白第一个分类损失是用来干啥的,后来看了源码以后才知道,第一个分类损失是用来进行训练RPN网络的,挑选出128个正样本来训练20000多个anchor然后选出2000个rois输入到下面的roi head网络中。
上面就是第一个损失函数RPN 分类损失

理解了上面这个以后下面这个回归损失也就简单了。再回到我们的valid_anchors,接下来该计算回归损失了。我们知道了每个anchors在原图的位置,也知道了ground_trues,所以我们可以轻松的计算出偏移量。这时候我们就相当于有ground_trues_anchors了!跟上面一样,不过我们现在的ground_trues_anchors有mxnx4xk个,所以我们人为的给网络指定这么多anchors,让他去学,最后得出来的损失就是RPN位置回归损失。(这里的这个位置回归损失也是用上面的128个正样本进行训练得到的!)
具体步骤如下:
1、对于每张图片,利用它的feature map, 计算 (H/16)× (W/16)×9(大概20000)个anchor属于前景的概率,以及对应的位置参数。
2、选取概率较大的12000个anchor
3、利用回归的位置参数,修正这12000个anchor的位置,得到RoIs
4、利用非极大值((Non-maximum suppression, NMS)抑制,选出概率最大的2000个RoIs
注意:在inference的时候,为了提高处理速度,12000和2000分别变为6000和300.
这里先记住,后面两个损失函数要用到。

rol pooling

为什么要用rol pooling,因为上面的bbox regression对anchors的调整使得我们最后抠出来的部分size有很大区别。所以常规我们有两种解决办法,crop和warp。
在这里插入图片描述
显而易见这样会破坏feature_map的特征,所以我们有了rol pooling。
rol pooling将传入的proposals进行hxw的划分,这个h,w是人为设定的,与后面要用道的全链接层的纬度是相关的,然后对每一块区域进行maxpooling,再reshape成一维向量连接起来。,如下图。下图中黑色部分相当于整张图片,proposals也就是提取出的anchors分割成7x7的网格。
在这里插入图片描述
留一个小问题,为什么是7x7的网格呢???

Classfiction

Classification部分利用已经获得的proposal feature maps,通过full connect层与softmax计算每个proposal具体属于那个类别(如人,车,电视等),输出cls_prob概率向量;同时再次利用bounding box regression获得每个proposal的位置偏移量bbox_pred,用于回归更加精确的目标检测框。
在这里插入图片描述
从RoI Pooling获取到7x7=49大小的proposal feature maps后,送入后续网络,可以看到做了如下2件事:

通过全连接和softmax对proposals进行分类,这实际上已经是识别的范畴了
再次对proposals进行bounding box regression,获取更高精度的rect box
具体步骤就是:
由于RoIs给出的2000个候选框,分别对应feature map不同大小的区域。再根据iou>0.5和iou<0.1挑选出128个sample_rois(32个正样本,96个负样本)。为了便于训练,对选择出的128个RoIs,还对他们的gt_roi_loc 进行标准化处理(减去均值除以标准差)

对于分类问题,直接利用交叉熵损失. 而对于位置的回归损失,一样采用Smooth_L1Loss, 只不过只对正样本计算损失.而且是只对正样本中的这个类别4个参数计算损失。举例来说:

一个RoI在经过FC 84后会输出一个84维的loc 向量. 如果这个RoI是负样本,则这84维向量不参与计算 L1_Loss
如果这个RoI是正样本,属于label K,那么它的第 K×4, K×4+1 ,K×4+2, K×4+3 这4个数参与计算损失,其余的不参与计算损失。
这里跟前面一样会产生两个损失函数。
RoI 分类损失:RoI所属类别(21分类,多了一个类作为背景)
RoI位置回归损失:继续对RoI位置微调

现在你知道为什么要用7x7的网格了吧,就是为了将vgg16网络最后的全连接层给利用起来,直接用vgg16训练好的参数,也就是共享权重。(为了节省计算真抠,哈哈)

到此为止,Faster-rcnn基本上就已经讲完了。其实你要是懂了上面的4个loss的话,接下来的训练过程就很容易了。

训练

Faster R-CNN的训练,是在已经训练好的model(如VGG_CNN_M_1024,VGG,ZF)的基础上继续进行训练。实际中训练过程分为6个步骤(这里的fast-rcnn也就是我们上面的rol pooling+classfition):

在这里插入图片描述
最后放一张代码流程图,很详细!!
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值