MMDetection 全景分割测试结果提交指南:COCO test-dev 推理、格式化与上传全流程
【免费下载链接】mmdetectionOpenMMLab Detection Toolbox and Benchmark项目地址: https://gitcode.com/gh_mirrors/mm/mmdetection
导读
本文以 MMDetection 官方用户指南 docs/en/user_guides/test_results_submission.md 为核心,完整讲解如何在 COCO 数据集的 test-dev 无标注测试集上运行全景分割(Panoptic Segmentation)模型推理,并将预测结果整理为 COCO 官方评测服务器可接受的提交包。读者完成本文学习后,将掌握:test-dev 测试数据的下载与标注信息修补、test_dataloader/test_evaluator的两种切换方式(改配置文件与命令行--cfg-options覆盖)、单卡 / 多卡 / Slurm 三种推理命令,以及按 COCO 命名规范重命名并打包提交结果的完整流程。
一、背景:为什么 test-dev 需要一套单独的提交流程
COCO 数据集的官方评测分为多个阶段。日常训练和调参阶段,我们使用带有标注的train2017/val2017子集,通过CocoPanopticMetric直接计算 PQ(Panoptic Quality)、SQ(Segmentation Quality)、RQ(Recognition Quality)等指标;而test-dev是官方评测服务器使用的测试集,其图像是公开的,但标注不对外发布——因此模型在 test-dev 上只能做推理,无法在本地计算真实指标,必须将预测结果以指定格式打包提交到 COCO 评测服务器,由官方后台统一评测打分。
这带来两个直接后果:
- 数据侧:test-dev 只有图像与图像元信息(image info),没有目标标注;而且其官方提供的
image_info_test-dev2017.json中,类别信息缺少全景分割评测所必需的isthing属性,需要先修补。 - 评测侧:本地评测指标需要真实标注参与匹配计算,而在 test-dev 上无标注可用,因此需要让评测器进入
format_only(仅格式化输出)模式——只负责把模型预测结果落盘为 COCO 规定的提交格式,跳过指标计算。
这两个问题正是本文要解决的核心。
二、准备工作:下载数据并修补类别信息
2.1 下载 COCO test-dev 数据集与标注信息
进入仓库根目录,按如下命令下载并解压三个压缩包。假设data/coco/目录尚不存在:
# suppose data/coco/ does not exist mkdir -pv data/coco/ # download test2017 wget -P data/coco/ http://images.cocodataset.org/zips/test2017.zip wget -P data/coco/ http://images.cocodataset.org/annotations/image_info_test2017.zip wget -P data/coco/ http://images.cocodataset.org/annotations/panoptic_annotations_trainval2017.zip # unzip them unzip data/coco/test2017.zip -d data/coco/ unzip data/coco/image_info_test2017.zip -d data/coco/ unzip data/coco/panoptic_annotations_trainval2017.zip -d data/coco/ # remove zip files (optional) rm -rf data/coco/test2017.zip data/coco/image_info_test2017.zip data/coco/panoptic_annotations_trainval2017.zip三个压缩包各自的用途:
| 压缩包 | 解压后的关键产物 | 用途 |
|---|---|---|
test2017.zip | data/coco/test2017/*.jpg | 测试图像,推理输入 |
image_info_test2017.zip | data/coco/annotations/image_info_test2017.json及image_info_test-dev2017.json | 测试图像元信息(id、宽高、文件名) |
panoptic_annotations_trainval2017.zip | data/coco/annotations/panoptic_train2017.json/panoptic_val2017.json及对应 mask 压缩包 | 提供带isthing属性的完整类别表 |
2.2 修补 test-dev 的类别信息
image_info_test-dev2017.json中的类别信息缺少全景分割评测所需的isthing(thing / stuff 类别标识)属性。MMDetection 提供了专门的脚本 tools/misc/gen_coco_panoptic_test_info.py 来完成修补:它读取panoptic_val2017.json中完整的categories(含isthing),替换掉 test-dev 信息文件中的对应字段,并写出新的panoptic_image_info_test-dev2017.json:
python tools/misc/gen_coco_panoptic_test_info.py data/coco/annotations从脚本源码(tools/misc/gen_coco_panoptic_test_info.py)可以看到其核心逻辑:
val_info = load(osp.join(data_root, 'panoptic_val2017.json')) test_old_info = load(osp.join(data_root, 'image_info_test-dev2017.json')) # replace categories from image_info_test-dev2017.json # with categories from panoptic_val2017.json which # has attribute `isthing`. test_info = test_old_info test_info.update({'categories': val_info['categories']}) dump(test_info, osp.join(data_root, 'panoptic_image_info_test-dev2017.json'))该脚本接收的唯一参数是 COCO 标注目录路径。运行完成后,data目录结构应如下:
data `-- coco |-- annotations | |-- image_info_test-dev2017.json | |-- image_info_test2017.json | |-- panoptic_image_info_test-dev2017.json | |-- panoptic_train2017.json | |-- panoptic_train2017.zip | |-- panoptic_val2017.json | `-- panoptic_val2017.zip `-- test2017说明:
panoptic_train2017.zip/panoptic_val2017.zip解压后的 mask 目录在此流程中并非必需,但保留它们便于日后在 val 集上复算指标。这里为与官方指南保持一致而完整列出。
三、切换 test 配置:让评测器输出提交格式
在 test-dev 上推理前,需要修改两处设置:
test_dataloader:把ann_file指向修补好的annotations/panoptic_image_info_test-dev2017.json,并把data_prefix.img指向test2017/(test-dev 不提供seg前缀,因为无标注)。test_evaluator:把type保持为CocoPanopticMetric,并设置format_only=True与outfile_prefix——前者让评测器只格式化不计算指标,后者决定结果文件的落盘位置与文件名前缀。
CocoPanopticMetric的源码(mmdet/evaluation/metrics/coco_panoptic_metric.py)对这两个参数有明确约束:当format_only=True时,outfile_prefix必须非空,否则结果会被写入临时目录并在评测结束时被清理;outfile_prefix被解读为“路径 + 文件名前缀”,实际会生成<prefix>.panoptic.json与<prefix>.panoptic/两个产物(见 coco_panoptic_metric.py 中result2json的实现)。
MMDetection 在基础配置 configs/base/datasets/coco_panoptic.py 末尾以注释形式预置了这份 test-dev 设置,便于直接启用或复制。
3.1 方式一:修改配置文件
Case 1:直接取消注释
编辑 configs/base/datasets/coco_panoptic.py,启用文件末尾预置的配置块:
test_dataloader = dict( batch_size=1, num_workers=1, persistent_workers=True, drop_last=False, sampler=dict(type='DefaultSampler', shuffle=False), dataset=dict( type=dataset_type, data_root=data_root, ann_file='annotations/panoptic_image_info_test-dev2017.json', data_prefix=dict(img='test2017/'), test_mode=True, pipeline=test_pipeline)) test_evaluator = dict( type='CocoPanopticMetric', format_only=True, ann_file=data_root + 'annotations/panoptic_image_info_test-dev2017.json', outfile_prefix='./work_dirs/coco_panoptic/test')Case 2:覆盖到你正在使用的配置文件中
如果你不想改动基础配置,也可以把以下片段复制进当前使用的实验配置。注意dataset内通过_delete_=True删除基础配置里data_prefix中的seg键——因为 test-dev 没有分割标注前缀,保留它会触发加载错误:
test_dataloader = dict( dataset=dict( ann_file='annotations/panoptic_image_info_test-dev2017.json', data_prefix=dict(img='test2017/', _delete_=True))) test_evaluator = dict( format_only=True, ann_file=data_root + 'annotations/panoptic_image_info_test-dev2017.json', outfile_prefix='./work_dirs/coco_panoptic/test')配置就绪后,使用标准测试入口推理:
python tools/test.py \ ${CONFIG_FILE} \ ${CHECKPOINT_FILE}3.2 方式二:命令行覆盖(推荐,不改任何文件)
用--cfg-options以key=value形式临时覆盖配置,效果与改文件一致,且不会污染配置文件。这也是官方指南最推荐的免修改方案:
# test with single gpu CUDA_VISIBLE_DEVICES=0 python tools/test.py \ ${CONFIG_FILE} \ ${CHECKPOINT_FILE} \ --cfg-options \ test_dataloader.dataset.ann_file=annotations/panoptic_image_info_test-dev2017.json \ test_dataloader.dataset.data_prefix.img=test2017 \ test_dataloader.dataset.data_prefix._delete_=True \ test_evaluator.format_only=True \ test_evaluator.ann_file=data/coco/annotations/panoptic_image_info_test-dev2017.json \ test_evaluator.outfile_prefix=${WORK_DIR}/results注意此处
ann_file在--cfg-options中被写为相对仓库根目录的路径(data/coco/...),因为命令行覆盖不再经过data_root拼接;而_delete_=True与配置覆盖方式一样用于清除data_prefix中继承的seg键。
三个细节值得留意:
test_dataloader.dataset.data_prefix.img=test2017不带尾部斜杠也能正常匹配test2017/前缀;--cfg-options由 tools/test.py 中的DictAction解析,支持点号嵌套键与_delete_等特殊操作符;tools/test.py会把命令行传入的 checkpoint 写入cfg.load_from并构建 Runner 执行测试(tools/test.py),因此无需再修改配置里的load_from。
四、多卡与 Slurm 集群推理
4.1 多卡分布式推理
通过 tools/dist_test.sh 可在一台多卡机器上分布式推理。该脚本内部通过torch.distributed.launch以--nproc_per_node=$GPUS拉起tools/test.py,并把--launcher pytorch与其余参数透传(tools/dist_test.sh):
# test with four gpus CUDA_VISIBLE_DEVICES=0,1,3,4 bash tools/dist_test.sh \ ${CONFIG_FILE} \ ${CHECKPOINT_FILE} \ 8 \ # eights gpus --cfg-options \ test_dataloader.dataset.ann_file=annotations/panoptic_image_info_test-dev2017.json \ test_dataloader.dataset.data_prefix.img=test2017 \ test_dataloader.dataset.data_prefix._delete_=True \ test_evaluator.format_only=True \ test_evaluator.ann_file=data/coco/annotations/panoptic_image_info_test-dev2017.json \ test_evaluator.outfile_prefix=${WORK_DIR}/results原文此例的第三个位置参数写为
8并注释 "eights gpus",同时上方注释又写 four gpus,属于原文档中的笔误。dist_test.sh的第三个参数是并行进程数,与CUDA_VISIBLE_DEVICES指定的卡数保持一致即可,例如用0,1,2,3四张卡就应传4。若省略,可先export GPUS=4之类的环境变量(该脚本默认未设默认值,必须显式传入)。
4.2 Slurm 集群推理
在 Slurm 管理的集群上使用 tools/slurm_test.sh。脚本接收 分区 / 作业名 / 配置 / 权重 四个位置参数,GPUS(默认 8)与GPUS_PER_NODE(默认 8)等通过环境变量控制(tools/slurm_test.sh):
# test with slurm GPUS=8 tools/slurm_test.sh \ ${Partition} \ ${JOB_NAME} \ ${CONFIG_FILE} \ ${CHECKPOINT_FILE} \ --cfg-options \ test_dataloader.dataset.ann_file=annotations/panoptic_image_info_test-dev2017.json \ test_dataloader.dataset.data_prefix.img=test2017 \ test_dataloader.dataset.data_prefix._delete_=True \ test_evaluator.format_only=True \ test_evaluator.ann_file=data/coco/annotations/panoptic_image_info_test-dev2017.json \ test_evaluator.outfile_prefix=${WORK_DIR}/results4.3 完整示例:用 MaskFormer R50 在 test-dev 上推理
官方指南以 MaskFormer + ResNet-50 预训练权重为例。注意:原文档示例中引用的配置文件名maskformer_r50_mstrain_16x1_75e_coco.py在当前仓库版本中已更名为 configs/maskformer/maskformer_r50_ms-16xb1-75e_coco.py(其基础配置同样继承自 configs/base/datasets/coco_panoptic.py,并通过panoptic_fusion_head+test_cfg.panoptic_on=True输出全景结果,见 maskformer_r50_ms-16xb1-75e_coco.py)。请以实际下载的权重文件名为准:
# test with single gpu CUDA_VISIBLE_DEVICES=0 python tools/test.py \ configs/maskformer/maskformer_r50_ms-16xb1-75e_coco.py \ checkpoints/maskformer_r50_ms-16xb1-75e_coco.pth \ --cfg-options \ test_dataloader.dataset.ann_file=annotations/panoptic_image_info_test-dev2017.json \ test_dataloader.dataset.data_prefix.img=test2017 \ test_dataloader.dataset.data_prefix._delete_=True \ test_evaluator.format_only=True \ test_evaluator.ann_file=data/coco/annotations/panoptic_image_info_test-dev2017.json \ test_evaluator.outfile_prefix=work_dirs/maskformer/results推理完成后,CocoPanopticMetric会在outfile_prefix指向的目录下产出两个结果(可对照 coco_panoptic_metric.py 中result2json与 coco_panoptic_metric.py 中seg_out_dir的定义):
work_dirs/maskformer/ |-- results.panoptic.json # 每张图的 segments_info 聚合(annotations 数组) `-- results.panoptic/ # 每张图一张 RGB 编码的 mask PNG(与 json 一一对应)其中 mask PNG 的写盘逻辑在_parse_predictions中:模型输出的全景图先过滤 VOID 类别(sem_label等于类别数或ignore_index的像素被置为VOID),再通过id2rgb转为 RGB 并以img_id对应的文件名写入seg_out_dir(coco_panoptic_metric.py)。
五、重命名结果并打包提交
COCO 官方评测服务器对提交文件有严格的命名约定。按官方指南,得到results.panoptic.json与results.panoptic/之后:
- 将 mask 目录重命名为
panoptic_test-dev2017_[algorithm_name]_results; - 将 json 重命名为
panoptic_test-dev2017_[algorithm_name]_results.json; - 将两者打包为同名 zip,且zip 包根目录必须直接包含这两个文件(不能嵌套一层子目录)。
其中[algorithm_name]替换为所用算法名称。官方命令如下:
# In WORK_DIR, we have panoptic segmentation results: 'panoptic' and 'results.panoptic.json'. cd ${WORK_DIR} # replace '[algorithm_name]' with the name of algorithm you used. mv ./panoptic ./panoptic_test-dev2017_[algorithm_name]_results mv ./results.panoptic.json ./panoptic_test-dev2017_[algorithm_name]_results.json zip panoptic_test-dev2017_[algorithm_name]_results.zip -ur panoptic_test-dev2017_[algorithm_name]_results panoptic_test-dev2017_[algorithm_name]_results.json若你按本文第 3.2 节的命令把outfile_prefix设为work_dirs/maskformer/results,则实际产物名为results.panoptic.json与results.panoptic/,对应替换mv命令中的源文件即可,最终得到panoptic_test-dev2017_[algorithm_name]_results.zip。
提交到 COCO 评测服务器后,服务器会依据panoptic_image_info_test-dev2017.json中记录的图像 id / 尺寸对预测 mask 逐图匹配,并计算 PQ / SQ / RQ 以及 Things / Stuff 分组指标——这正是全景分割任务的标准评测口径。
六、常见问题与排查要点
panopticapi未安装:CocoPanopticMetric初始化时会直接抛错提示安装panopticapi(coco_panoptic_metric.py)。请按错误提示安装后再运行。outfile_prefix未设置:format_only=True时若未给outfile_prefix,评测器会断言失败并提示结果将写入临时目录、结束后被清理(coco_panoptic_metric.py)。务必显式设置一个持久路径。- 加载报错找不到
seg前缀:基础配置data_prefix含seg键,而 test-dev 无分割标注;在--cfg-options或配置覆盖中忘记_delete_=True就会触发此问题。 ann_file路径不一致:配置文件内ann_file相对data_root解析,命令行--cfg-options中则需写全相对仓库根的路径(如data/coco/annotations/...),两者混用是常见坑。- zip 解包结构不对:COCO 要求 zip 根目录直接包含 json 与 mask 目录;若提交后在服务器侧报文件缺失,先检查是否多包了一层目录。
相关资源
- 用户指南原文:docs/en/user_guides/test_results_submission.md
- 基础数据配置:configs/base/datasets/coco_panoptic.py
- 测试信息修补脚本:tools/misc/gen_coco_panoptic_test_info.py
- 评测指标实现:mmdet/evaluation/metrics/coco_panoptic_metric.py
- 全景数据集实现:mmdet/datasets/coco_panoptic.py
- 测试入口:tools/test.py、tools/dist_test.sh、tools/slurm_test.sh
- MaskFormer 示例配置:configs/maskformer/maskformer_r50_ms-16xb1-75e_coco.py
【免费下载链接】mmdetectionOpenMMLab Detection Toolbox and Benchmark项目地址: https://gitcode.com/gh_mirrors/mm/mmdetection
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考