根據(jù)mmDetection的mask rcnn的配置文件來進(jìn)行理解囊颅。
網(wǎng)絡(luò)結(jié)構(gòu)
model = dict(
type='MaskRCNN',
pretrained='torchvision://resnet50',
backbone=dict(
type='ResNet',
depth=50,
num_stages=4,
out_indices=(0, 1, 2, 3), #使用resnet50作為主干網(wǎng)絡(luò)瀑构,/4辖所,/8叁执,/16咙俩,/32作為FPN的輸入
frozen_stages=1, #stage 1及其之前層不進(jìn)行參數(shù)更新僧凤,-1表示參數(shù)都更新
norm_cfg=dict(type='BN', requires_grad=True),
style='pytorch'),
neck=dict(
type='FPN',
in_channels=[256, 512, 1024, 2048],
out_channels=256, #利用1*1的卷積改變通道數(shù)蜻拨,低分辨率的進(jìn)行最近鄰上采樣,然后進(jìn)行相鄰尺度的相加融合眠冈,然后通過3*3的卷積進(jìn)行輸出飞苇。
num_outs=5), #此處額外加了一個(gè)尺度輸出菌瘫,即在/32尺度利用2*2的最大池化輸出\64尺度。一起作為RPN網(wǎng)絡(luò)的輸入布卡。
rpn_head=dict(
type='RPNHead',
in_channels=256,
feat_channels=256,
anchor_scales=[8],
anchor_ratios=[0.5, 1.0, 2.0], #3個(gè)base_anchors雨让,面積一樣。其中1.0表示8*8的大小忿等,數(shù)值表示長(zhǎng)寬比栖忠。
anchor_strides=[4, 8, 16, 32, 64], #對(duì)于輸入的5個(gè)尺度,生成對(duì)應(yīng)的anchor贸街。設(shè)有A個(gè)anchors (1, A, 4)庵寞, 有K個(gè)shifts (K, 1, 4),
#其中K為特征圖的大小W*H薛匪,得到(K*A, 4)的坐標(biāo)值捐川。
#shift_x = torch.arange(0, feat_w, device=device) * stride
#shift_y = torch.arange(0, feat_h, device=device) * stride
#shift_xx, shift_yy = self._meshgrid(shift_x, shift_y)
#shifts = torch.stack([shift_xx, shift_yy, shift_xx, shift_yy], dim=-1)
target_means=[.0, .0, .0, .0],
target_stds=[1.0, 1.0, 1.0, 1.0],
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
loss_bbox=dict(type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=1.0)), #RPN網(wǎng)絡(luò)有2條支路——分類支路(anchor數(shù)目*2,
#如果使用sigmoid逸尖,不需要乘2 )古沥,和回歸支路(anchor數(shù)目*4)
bbox_roi_extractor=dict(
type='SingleRoIExtractor',
roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2),
out_channels=256,
featmap_strides=[4, 8, 16, 32]), #ROI Align層,對(duì)于一個(gè)ROI娇跟,根據(jù)其大小岩齿,進(jìn)行映射,取相應(yīng)的尺度上的特征圖苞俘。
#- scale < finest_scale * 2: level 0
#- finest_scale * 2 <= scale < finest_scale * 4: level 1
#- finest_scale * 4 <= scale < finest_scale * 8: level 2
#- scale >= finest_scale * 8: level 3
bbox_head=dict(
type='SharedFCBBoxHead',
num_fcs=2,
in_channels=256,
fc_out_channels=1024,
roi_feat_size=7,
num_classes=81,
target_means=[0., 0., 0., 0.],
target_stds=[0.1, 0.1, 0.2, 0.2], #預(yù)測(cè)的dx和dy需要*0.1,dw和dh需要*0.2
reg_class_agnostic=False,
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0)), #輸入7*7的ROI 特征盹沈,進(jìn)行類別預(yù)測(cè)和框的回歸
mask_roi_extractor=dict(
type='SingleRoIExtractor',
roi_layer=dict(type='RoIAlign', out_size=14, sample_num=2),
out_channels=256,
featmap_strides=[4, 8, 16, 32]), #ROI Align層,同上吃谣,只是輸出大小為14*14
mask_head=dict(
type='FCNMaskHead',
num_convs=4,
in_channels=256,
conv_out_channels=256,
num_classes=81,
loss_mask=dict(
type='CrossEntropyLoss', use_mask=True, loss_weight=1.0))) #輸入14*14的ROI特征襟诸,F(xiàn)CN進(jìn)行Mask預(yù)測(cè)
訓(xùn)練
train_cfg = dict(
rpn=dict(
assigner=dict(
type='MaxIoUAssigner',
pos_iou_thr=0.7,
neg_iou_thr=0.3,
min_pos_iou=0.3,
ignore_iof_thr=-1),#對(duì)于每個(gè)box,分配真值框或者背景基协。遍歷每個(gè)bbox歌亲,
#與一gt的iou超過pos_iou_thr為正樣本,與所有g(shù)t的iou低于neg_iou_thr的為負(fù)樣本澜驮。
#遍歷每個(gè)gt陷揪,如果與其最重合的box的iou大于min_pos_iou,此gt分配給此box杂穷。
sampler=dict(
type='RandomSampler',
num=256,
pos_fraction=0.5,
neg_pos_ub=-1,
add_gt_as_proposals=False),#采樣正負(fù)樣本悍缠,進(jìn)行損失計(jì)算
allowed_border=0,
pos_weight=-1,
debug=False),
rpn_proposal=dict(
nms_across_levels=False,
nms_pre=2000,
nms_post=2000,
max_num=2000,
nms_thr=0.7,
min_bbox_size=0),#按照置信度選取前nms_pre的前景,進(jìn)行nms
#然后選前nms_post個(gè)框耐量,送入bbox分支
rcnn=dict(
assigner=dict(
type='MaxIoUAssigner',
pos_iou_thr=0.5,
neg_iou_thr=0.5,
min_pos_iou=0.5,
ignore_iof_thr=-1), #同上
sampler=dict(
type='RandomSampler',
num=512,
pos_fraction=0.25,
neg_pos_ub=-1,
add_gt_as_proposals=True),#同上
mask_size=28,
pos_weight=-1,
debug=False))
推理
#推理時(shí)飞蚓,rpn網(wǎng)絡(luò)輸出roi,roi特征圖輸入bbox分支廊蜒,得到預(yù)測(cè)框趴拧。
#預(yù)測(cè)的框所對(duì)應(yīng)的特征圖輸入到mask分支溅漾。
test_cfg = dict(
rpn=dict(
nms_across_levels=False,
nms_pre=1000,
nms_post=1000,
max_num=1000,
nms_thr=0.7,
min_bbox_size=0), #1000個(gè)roi框送到bbox分支中
rcnn=dict(
score_thr=0.05,
nms=dict(type='nms', iou_thr=0.5),
max_per_img=100,
mask_thr_binary=0.5)) #100個(gè)bbox分支預(yù)測(cè)框送入到mask分支中