MMDetection 中的 Mask Scoring R-CNN:用 MaskIoUHead 校准掩码质量的实例分割方案
【免费下载链接】mmdetectionOpenMMLab Detection Toolbox and Benchmark项目地址: https://gitcode.com/gh_mirrors/mm/mmdetection
Mask Scoring R-CNN(MS R-CNN)是 MMDetection 中一个经典的实例分割算法实现,它通过在标准 Mask R-CNN 之上新增 MaskIoUHead 分支,学习预测掩码与真实掩码之间的 IoU,从而解决"分类置信度与掩码质量不相关"的固有缺陷。本文以仓库中的 configs/ms_rcnn/README.md 为骨架,结合 mask_scoring_roi_head.py 与 maskiou_head.py 的源码实现,系统讲解其算法原理、配置细节、COCO 实验结果与训练使用方法,帮助读者理解并直接上手 MS R-CNN。
问题背景:分类分数为何不能代表掩码质量
绝大多数实例分割框架(包括 Mask R-CNN)在评估与排序实例时,直接使用实例分类的置信度作为"掩码质量分数"。但正如 configs/ms_rcnn/README.md 的摘要所指出的,掩码质量——即预测掩码与其真实掩码之间的 IoU——通常与分类分数相关性很差:一个分类分数很高的检测框,其分割出的掩码可能边缘粗糙、与目标严重偏离;反之亦然。
这种"分数与质量错位"(misalignment)会直接影响 COCO AP 评估:评估过程中实例按得分排序并参与 PR 曲线计算,得分虚高的低质量掩码会拖累整体指标。Mask Scoring R-CNN 的核心动机,就是让网络"意识到自己预测的质量",用一个额外的网络块去学习预测掩码的 IoU,再用这个预测值重新校准排序分数,从而优先输出更准确的掩码预测。
算法原理:从 Mask R-CNN 到 Mask Scoring R-CNN
整体架构
MS R-CNN 以 Mask R-CNN 为基座(RPN + FPN + 检测/分割双头),只在 ROI 头(RoIHead)上叠加一个MaskIoUHead。论文原文(Mask Scoring R-CNN,CVPR 2019)给出的结构可概括为:
- 主干 + FPN 提取多尺度特征,RPN 生成候选框;
- BBox Head 输出分类分数与框回归;
- Mask Head 输出逐像素掩码预测与掩码特征;
- MaskIoUHead 将"掩码特征 + 对应的掩码预测"拼接输入,回归该实例的掩码 IoU;
- 推理阶段,将分类分数与预测的掩码 IoU 相乘,得到校准后的最终得分。
在 MMDetection 中,这一结构对应三层注册实现:
- 检测器 MaskScoringRCNN:继承
TwoStageDetector,本身不新增逻辑,仅在构造时指定roi_head类型; - ROI 头 MaskScoringRoIHead:继承
StandardRoIHead,在训练与推理流程中串联 mask head 与 mask iou head; - 掩码 IoU 头 MaskIoUHead:具体实现 IoU 回归网络、训练目标与推理校准。
MaskIoUHead 的网络结构
MaskIoUHead 的构造参数及默认值如下(与 ms-rcnn_r50-caffe_fpn_1x_coco.py 中的配置一一对应):
| 参数 | 默认值 | 含义 |
|---|---|---|
num_convs | 4 | 卷积层数量,最后一层 stride 为 2 做下采样 |
num_fcs | 2 | 全连接层数量 |
roi_feat_size | 14 | RoI 特征尺寸(对应 RoIAlign 输出 14×14) |
in_channels | 256 | 输入特征通道数(FPN 输出通道) |
conv_out_channels | 256 | 卷积层输出通道 |
fc_out_channels | 1024 | 全连接层输出通道 |
num_classes | 80 | 类别数(不含背景,COCO 为 80) |
loss_iou | dict(type='MSELoss', loss_weight=0.5) | IoU 回归损失,使用 MSE 损失,权重 0.5 |
其前向过程(forward)可拆解为:
- 对掩码预测做 sigmoid 后接 MaxPool2d(2, 2) 下采样,得到与
mask_feat同尺寸的"掩码池化图"; - 将掩码特征与池化后的掩码预测按通道拼接(
torch.cat((mask_feat, mask_pred_pooled), 1),第一层卷积输入通道因此为in_channels + 1); - 依次经过 4 个卷积 + ReLU(最后一层 stride=2)、flatten、2 个全连接 + ReLU;
- 最终由
fc_mask_iou(Linear(fc_out_channels, num_classes))输出每个类别的掩码 IoU 预测值。
训练目标:如何构造 mask IoU 的真实值
与分类头、掩码头不同,MaskIoUHead 的监督信号不是人工标注,而是由预测掩码与真实掩码动态计算而来。在 loss_and_target 与 get_targets 中:
- 将预测掩码按
rcnn_train_cfg.mask_thr_binary(配置中为 0.5)二值化; - 计算预测掩码与掩码 target 在框内的重叠面积、预测面积、以及通过"框内面积占比"反推的完整实例掩码面积(
gt_full_areas = mask_targets.sum((-1,-2)) / (area_ratios + 1e-7)); - 由三者计算 IoU:
overlap / (pred_area + gt_full_area - overlap),得到每个正样本的 mask IoU 回归目标; - 只对 IoU 目标大于 0 的正样本计算 MSE 损失
loss_mask_iou,叠加到 mask 损失中一起回传。
推理校准:分数相乘
推理阶段,predict_mask 先通过 mask head 得到掩码预测与特征,再喂给 MaskIoUHead 得到预测 IoU;最终由 predict_by_feat 完成关键一步:
results.scores = scores * mask_iou_pred[range(labels.size(0)), labels]即把每个实例的分类分数与其预测的掩码 IoU 相乘,作为最终排序分数。这样掩码质量差的实例分数被压低、掩码质量高的实例分数被抬高,从根源上修复了"分数与质量错位"问题,使 COCO AP 评估能优先选中更准确的分割结果。
配置解析:从一行配置看懂 MS R-CNN
MS R-CNN 的所有配置都建立在对应 Mask R-CNN 配置之上,改动极小。以 ms-rcnn_r50-caffe_fpn_1x_coco.py 为例:
_base_ = '../mask_rcnn/mask-rcnn_r50-caffe_fpn_1x_coco.py' model = dict( type='MaskScoringRCNN', roi_head=dict( type='MaskScoringRoIHead', mask_iou_head=dict( type='MaskIoUHead', num_convs=4, num_fcs=2, roi_feat_size=14, in_channels=256, conv_out_channels=256, fc_out_channels=1024, num_classes=80)), # model training and testing settings train_cfg=dict(rcnn=dict(mask_thr_binary=0.5)))逐项说明:
_base_:直接继承 Mask R-CNN 的 R50 配置(其自身又继承 mask-rcnn_r50_fpn.py、coco_instance.py、schedule_1x.py 与 default_runtime.py),数据流水线、训练策略、运行时全部复用;type='MaskScoringRCNN':将检测器从MaskRCNN切换为 MaskScoringRCNN;type='MaskScoringRoIHead':将 ROI 头切换为 MaskScoringRoIHead,它要求必须传入mask_iou_head(构造时会断言非空);mask_iou_head:定义 MaskIoUHead,参数与默认值一致,实际使用中仅需确认num_classes与数据集类别数一致;mask_thr_binary=0.5:训练时构造 mask IoU 目标所用的二值化阈值,测试时的对应阈值来自test_cfg.rcnn.mask_thr_binary(由基类 Mask R-CNN 配置提供)。
仓库共提供 8 个官方配置(见 configs/ms_rcnn 目录):
- R-50-FPN(caffe 风格):1x、2x 两种训练计划;
- R-101-FPN(caffe 风格):1x、2x;
- R-101-FPN(pytorch 风格):1x(
ms-rcnn_r50_fpn_1x_coco.py之外的另一个); - X-101-32x4d-FPN:1x;
- X-101-64x4d-FPN:1x、2x。
其中 caffe 风格配置(如 ms-rcnn_r101-caffe_fpn_2x_coco.py)在基类中通过 mask-rcnn_r50-caffe_fpn_1x_coco.py 指定了 caffe 风格的图像归一化均值[103.530, 116.280, 123.675]、bgr_to_rgb=False,以及style='caffe'的骨干与 detectron2 预训练权重,切换骨干时只需替换_base_与init_cfg的 checkpoint 即可。
COCO 实验结果与模型
以下为 configs/ms_rcnn/README.md 与 metafile.yml 中记录的 COCO 验证集结果(训练数据均为 COCO,训练资源为 8×V100,优化器为 SGD + Momentum + Weight Decay):
| 骨干网络 | 风格 | 训练计划 | 显存 (GB) | box AP | mask AP | 配置文件 |
|---|---|---|---|---|---|---|
| R-50-FPN | caffe | 1x | 4.5 | 38.2 | 36.0 | ms-rcnn_r50-caffe_fpn_1x_coco.py |
| R-50-FPN | caffe | 2x | — | 38.8 | 36.3 | ms-rcnn_r50-caffe_fpn_2x_coco.py |
| R-101-FPN | caffe | 1x | 6.5 | 40.4 | 37.6 | ms-rcnn_r101-caffe_fpn_1x_coco.py |
| R-101-FPN | caffe | 2x | — | 41.1 | 38.1 | ms-rcnn_r101-caffe_fpn_2x_coco.py |
| X-101-32x4d | pytorch | 1x | 7.9 | 41.8 | 38.7 | ms-rcnn_x101-32x4d_fpn_1x_coco.py |
| X-101-64x4d | pytorch | 1x | 11.0 | 43.0 | 39.5 | ms-rcnn_x101-64x4d_fpn_1x_coco.py |
| X-101-64x4d | pytorch | 2x | 11.0 | 42.6 | 39.5 | ms-rcnn_x101-64x4d_fpn_2x_coco.py |
两点说明:
- 各模型的预训练权重、训练日志等下载信息均登记在 metafile.yml 中(字段
Weights),同时该文件记录了 X-101-64x4d 在 V100 上约 8.0 fps(125 ms/im,batch size 1,输入分辨率 800×1333,FP32)的推理耗时,可作为部署选型的参考; - 原文档表格中 X-101-32x4d 的配置链接指向 1x 文件,本文按 metafile.yml 的实际登记结果修正为该文件,2x 的 AP 数据同样以 metafile 为准。
训练与测试:动手复现
仓库为只读镜像,模型权重与日志需按 metafile.yml 中的Weights字段下载;训练与推理则使用 MMDetection 标准工具脚本,例如:
# 单机单卡训练 R-50 caffe 1x python tools/train.py configs/ms_rcnn/ms-rcnn_r50-caffe_fpn_1x_coco.py # 单机 8 卡分布式训练 bash tools/dist_train.sh configs/ms_rcnn/ms-rcnn_r50-caffe_fpn_1x_coco.py 8 # 使用预训练权重评估 python tools/test.py configs/ms_rcnn/ms-rcnn_r50-caffe_fpn_1x_coco.py \ /path/to/ms_rcnn_r50_caffe_fpn_1x_coco_20200702_180848-61c9355e.pth # 单张图片推理 python demo/image_demo.py demo/demo.jpg \ configs/ms_rcnn/ms-rcnn_r50-caffe_fpn_1x_coco.py \ /path/to/ms_rcnn_r50_caffe_fpn_1x_coco_20200702_180848-61c9355e.pth前提是已按仓库 README.md 完成 MMDetection 依赖(PyTorch、MMEngine、MMCV)的安装并准备好 COCO 数据集。若要将 MS R-CNN 迁移到自定义数据集,只需像其他两阶段模型一样,修改_base_中的数据集配置(num_classes同步改为自定义类别数),并保留mask_iou_head各通道参数即可。
小结
Mask Scoring R-CNN 用一个结构轻量(4 卷积 + 2 全连接)、改造成本极低(仅一行_base_+ 一个mask_iou_head配置块)的附加头,就为 Mask R-CNN 带来了实例分割上的稳定增益,且与不同骨干组合均保持一致的正向效果。对希望提升分割排序质量、或在已有 Mask R-CNN 工程上做最小侵入式升级的开发者而言,它是直接可复用的首选方案。如需进一步深入,可重点阅读 mask_scoring_roi_head.py(训练/推理串联逻辑)、maskiou_head.py(IoU 回归与目标构造)两份源码。
引用
若在研究中使用了 Mask Scoring R-CNN,可按原文档给出的文献条目引用:
@inproceedings{huang2019msrcnn, title={Mask Scoring R-CNN}, author={Zhaojin Huang and Lichao Huang and Yongchao Gong and Chang Huang and Xinggang Wang}, booktitle={IEEE Conference on Computer Vision and Pattern Recognition}, year={2019}, }【免费下载链接】mmdetectionOpenMMLab Detection Toolbox and Benchmark项目地址: https://gitcode.com/gh_mirrors/mm/mmdetection
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考