对Faster rcnn的部分源码进行讲解
下图是caffe版本的RPN网络结构图:
![](https://img.haomeiwen.com/i14205016/05460419b28e3488.png)
1) rpn-data
layer {
name: 'rpn-data'
type: 'Python'
bottom: 'rpn_cls_score' #仅提供特征图的height和width的参数大小
bottom: 'gt_boxes' #ground truth box
bottom: 'im_info' #包含图片大小和缩放比例,可供过滤anchor box
bottom: 'data'
top: 'rpn_labels'
top: 'rpn_bbox_targets'
top: 'rpn_bbox_inside_weights'
top: 'rpn_bbox_outside_weights'
python_param {
module: 'rpn.anchor_target_layer'
layer: 'AnchorTargetLayer'
param_str: "'feat_stride': 16 \n'scales': !!python/tuple [8, 16, 32]"
}
}
这一层主要是为特征图60x40上的每个像素生成的9个anchor boxes,并且对生成的Anchor boxes进行过滤和标记,其规则如下:
①去除超过1000x600原图边界的anchor boxes
②如果anchor box与ground truth的IoU值最大,标记为正样本,label = 1
③如果anchor box与ground truth的IoU>0.7,标记为正样本,label = 1
④如果anchor box与ground truth的IoU<0.3,标记为负样本,label = 0
剩下的既不是正样本也不是负样本,不用于最终的训练,label = -1
关于IoU的解释请见:https://www.jianshu.com/p/a4237e252087
除了对anchor boxes进行标记外,另一件事就是计算anchor box与ground truth之间的偏移量,即:
ground truth:标定的框会对应一个中心位置x*,y*和宽高w*,h*
anchor box:会有一个中心位置x_a,y_a和宽高w_a,h_a
所以偏移量:
通过ground truth与预测的anchor box之间的差异来进行训练,使得RPN网络权重能够学习到预测box的能力。
2)rpn_loss_cls,rpn_loss_bbox,rpn_cls_prob
其中前两个分别计算softmax,smooth L1损失函数,rpn_cls_prob 用来计算概率值(可用于一下层的nms非最大值抑制操作)
在rpn-data中已经为预测框anchor box进行标记,并且计算出gt_boxes之间的偏移量,利用RPN网络进行训练。
RPN训练:在训练RPN时,一个Mini-Batch是由一幅图像中任意选取256个proposal组成的,其中正负样本比例为1:1.如果正样本不足128,则多用一些负样本以满足256个proposal可以用于训练,反之亦然。
3)proposal
layer {
name: 'proposal'
type: 'Python'
bottom: 'rpn_cls_prob_reshape' #[1,18,40,60]==> [batch_size, channel,height,width]Caffe的数据格式,anchor box分类的概率
bottom: 'rpn_bbox_pred' # 记录训练好的四个回归值△x, △y, △w, △h
bottom: 'im_info'
top: 'rpn_rois'
python_param {
module: 'rpn.proposal_layer'
layer: 'ProposalLayer'
param_str: "'feat_stride': 16 \n'scales': !!python/tuple [4, 8, 16, 32]"
}
}
在输入中我们看到rpn_bbox_pred,记录着训练好的四个回归值,
,
,
。
源码中,会重新生成60x40x9个anchor boxes,然后累加上训练好的,
,
,
,从而得到了相较于之前更加准确的region proposal,进一步对预测框进行越界剔除和使用nms非最大值抑制,剔除重叠的框,如设置IoU为0.7的阈值,即保留覆盖率不超过0.7的局部最大分数的box(粗筛)。然后留下大约2000个anchor,然后再取N个boxes(比如300个),这样,进入下一层的ROI Pooing时的region proposal大约只用300个。(关于nms会在后续进行单独讲解)
4)roi_data
layer {
name: 'roi-data'
type: 'Python'
bottom: 'rpn_rois'
bottom: 'gt_boxes'
top: 'rois'
top: 'labels'
top: 'bbox_targets'
top: 'bbox_inside_weights'
top: 'bbox_outside_weights'
python_param {
module: 'rpn.proposal_target_layer'
layer: 'ProposalTargetLayer'
param_str: "'num_classes': 81"
}
}
为了避免定义上的误解,我们将经过proposal后的预测框称为region proposal(其实,RPN层的任务已经完成,roi_data属于为下一层准备数据)
其主要作用:
①RPN层只是来确定region proposal 是否是物体,这里是根据region proposal和ground truth box的最大重叠指定具体的标签(不再是二分类)
②计算region proposal和ground truth boxes的偏移量,计算方法和之前的偏移量公式相同
经过这一步后的数据输入到ROI Pooling层进行进一步的分类与定位。
5)ROI Pooling
layer {
name: "roi_pool5"
type: "ROIPooling"
bottom: "conv5_3" #输入特征图大小
bottom: "rois" #输入region proposal
top: "pool5" #输出固定大小的feature map
roi_pooling_param {
pooled_w: 7
pooled_h: 7
spatial_scale: 0.0625 # 1/16
}
}
从上述的Caffe代码中可以看出,输入的是RPN层产生的region proposal(假定有300个region proposal boxes)和VGG16最后一层产生的特征图(60x40x512),遍历每个region proposal,将其坐标值缩小16倍,这样就可以将在原图(1000x600)基础上产生的region proposal映射到60x40的特征图上,从而将在特征图上确定一个区域,根据参数pooled_w: 7,pooled_h: 7 ,将这个区域划分为7x7,即49个相同大小的区域,对于每个小区域,使用max pooling方式从中选取最大的像素点作为输出,这样就形成了7x7的特征图。
参照上述方法,遍历300个region proposal后,会产生很多7x7的特征图,故输出的数组是[300,512,7,7],作为下一层的全连接输入。
6)全连接层
经过roi pooling层之后,batch size= 300,proposal feature map的大小是7x7,512-d,对特征图进行全连接,参照下图,同样利用Softmax Loss和L1 Loss完成分类和定位
![](https://img.haomeiwen.com/i14205016/b388ea9422fa3841.png)
利用全连接层与softmax计算每个region proposal具体属于哪个类别(如人,马,车等),输出cls_prob概率向量,同时再次利用bounding box regression获得每个region proposal的位置偏移量bbox_pred,用于回归获得更加精确的目标检测框,即从ROI Pooling获取到的7x7的proposal feature map后,通过全连接主要做了:
①通过全连接和softmax对region proposal进行具体类别的分类
②再次对region proposal进行bounding box regression,获取更高的rectangle box
网友评论