之前的文章简要介绍了Faster-RCNN等物体检测的算法,本文将从代码角度详细分析介绍Faster-RCNN的实现。本文使用的代码参考了chenyuntc的实现,代码的位置看这里。需要注意的是,本文使用的框架是Pytorch。
数据载入部分的代码主要见./data/dataset.py
中的类Dataset
与TestDataset
。
数据载入部分的逻辑如下:
img, bbox, label
img, bbox
进行放缩(放缩的目的是让图片处于合适的大小,这样预先指定锚框才有意义)img
进行标准化正则处理img
翻转以增加训练数据FasterRCNN的网络结构如下图所示:
FasterRCNN结构的代码主要见./model.faster_rcnn.py
,其结构包含三大部分:
decom_vgg16
RegionProposalNetwork
VGG16RoIHead
下面,将以放缩后大小为[1, 3, 600, 800]
的图片为例针对每个部分分别介绍。图像类别共计21类(包含背景)。
该部分代码见./model/vgg16.py
。
输入:图片,大小[1, 3, 600, 800]
输出:特征图features
,大小[1, 512, 37, 50]
其逻辑如下:
extractor
, classifier
。其中,extractor
的参数固定。extractor
可以得到特征图features
。根据extractor
中池化参数可知图像通过extractor
缩小了16倍。该部分代码见./model/rpn.py
。
输入:特征图features
,大小[1, 512, 37, 50]
输出:
rpn_locs
:rpn对位置的修正,大小[1, 16650, 4]
rpn_scores
:rpn判断区域前景背景,大小[1, 16650, 2]
rois
:rpn筛选出的roi的位置,大小[300, 4]
roi_indices
:rpn筛选出的roi对应的图片索引,大小[300]
anchor
:原图像的锚点,大小[16650, 4]
其中,16650是放缩后的图像所产生的所有锚点(37*50*9),每个锚点都对应了一个rp。通过 rpn_scores
以及nms可以得到筛选后的大小为300的roi。
其逻辑如下:
features
以基准长度为16、选择合适的ratios
和scales
取基准锚点anchor_base
。(选择长度为16的原因是图片大小为600*800左右,基准长度16对应的原图区域是256*256,考虑放缩后的大小有128*128,512*512比较合适)anchor_base
在原图上获得anchors
。features
采用卷积得到rpn_locs
和rpn_scores
anchors
和rpn_locs
获得修正后的rp
rp
进一步修正获得rois
和roi_indices
,修正包括超出边界的部分截断、移除太小的、nms。该部分代码见./model/roi_module.py
。
输入:
features
:特征图,大小[1, 512, 37, 50]
rois
:rpn筛选出的roi的位置,大小[300, 4]
roi_indices
:rpn筛选出的roi对应的图片索引,大小[300]
输出:
roi_cls_locs
:roi
位置的修正,大小[300, 84]
roi_scores
:roi
各类的分数,大小[300, 21]
其逻辑如下:
RoIPooling2D
将大小不同的roi
变成大小一致,得到pooling后的特征,大小为[300, 512, 7, 7]
classifier
roi_cls_locs
、roi_scores
训练部分的代码主要见./trainer/trainer.py
中的FasterRCNNTrainer
中的train_step
函数。
训练部分的核心是loss如何求取。
loss求取前网络的步骤如下:
img
到extractor
获得features
features
到rpn
获得rpn_locs
, rpn_scores
, rois
, roi_indices
, anchor
rois
,bbox
,label
到ProposalTargetCreator
获得sample_roi
, gt_roi_loc
, gt_roi_label
。该步骤的含义是得到正负例比例和位置合适的roi
。features
,sample_roi
,sample_roi_index
得到roi_cls_loc
, roi_score
各个loss求取的方式如下:
rpn_loc_loss
:已知rpn_loc
,需要先根据anchor
和bbox
得到真实的gt_rpn_loc
和gt_rpn_label
。该处loss的计算只考虑前景,所以根据rpn_loc
,gt_rpn_loc
,gt_rpn_label
计算L1-LOSS即可。rpn_cls_loss
:根据rpn_score
和gt_rpn_label
计算二分类的交叉熵即可。roi_loc_loss
:已知roi_loc
,在sample roi的过程中已获得gt_roi_loc
, gt_roi_label
。根据roi_loc
,gt_roi_loc
,gt_roi_label
计算L1-LOSS即可。roi_cls_loss
:根据roi_score
和gt_roi_label
计算多分类的交叉熵即可。整体的loss为以上各loss相加求和。
训练部分的代码主要见./model/faster_rcnn.py
中的FasterRCNNTrainer
中的predict
函数。
其步骤如下:
img
到extractor
获得features
features
到rpn
获得rpn_locs
, rpn_scores
, rois
, roi_indices
, anchor
features
,rois
,roi_indices
得到roi_cls_loc
, roi_score
roi_cls_loc
、roi_score
、rois
,采用nms等方法得到预测的bbox
。