MMSegmentation 医学影像分割实战:GAMMA 挑战赛 Task3 视盘与视杯分割项目(Gamma3)全解析
【免费下载链接】mmsegmentationOpenMMLab Semantic Segmentation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmsegmentation
导读
本篇文章以 MMSegmentation 开源仓库中的projects/medical/2d_image/fundus_photography/gamma3项目为主体,系统讲解如何在 OpenMMLab 生态下复现GAMMA 挑战赛(Glaucoma grAding from Multi-Modality imAges)Task3——青光眼视盘(optic disc)与视杯(optic cup)分割任务。读完本文,你将掌握:Gamma3 眼底彩照数据集的结构与类别分布、数据预处理与训练/验证集切分的完整流程、基于 UNet + FCN 头的端到端训练/测试配置解析,以及通过mim一条命令完成训练与评测的具体操作方法。
项目背景:GAMMA 挑战赛 Task3 是什么
该项目对应的英文全称为"Glaucoma grAding from Multi-Modality imAges Task3",是 GAMMA 挑战赛中的常规赛任务之一,其核心任务是基于眼底彩照(fundus photography)完成视盘(optic disc)与视杯(optic cup)的语义分割。视盘与视杯的形态比例(杯盘比,CDR)是临床诊断青光眼的关键量化指标,因此该分割任务对青光眼的自动化筛查具有直接意义。
数据集由位于中国广州的**中山大学中山眼科中心(Sun Yat-sen Ophthalmic Center, Sun Yat-sen University)**提供。官方训练集与测试集各包含100 对眼底彩照与其对应的分割标注,共 200 张眼底彩照。官方数据集可从 GAMMA 挑战赛官方网站(百度 AI Studio 竞赛页面)下载。
官方数据集统计信息
| 数据集名称 | 解剖区域 | 任务类型 | 模态 | 类别数 | 训练/验证/测试图像 | 训练/验证/测试标注 | 发布时间 | 许可 |
|---|---|---|---|---|---|---|---|---|
| GammaTask3 | 眼(eye) | 语义分割 | 眼底彩照(fundus photography) | 3 | 100 / - / 100 | 有 / - / - | 2021 | CC-BY-NC 4.0 |
任务为3 分类语义分割,类别包括背景(background)、视盘(optic disc)与视杯(optic cup)。官方训练集的像素级类别分布如下:
| 类别名称 | 训练集数量 | 训练集像素占比(Pct) | 验证集数量 | 测试集数量 |
|---|---|---|---|---|
| background(背景) | 100 | 99.02 | - | - |
| optic disc(视盘) | 100 | 0.67 | - | - |
| optic cup(视杯) | 100 | 0.31 | - | - |
注:
Pct表示该类像素占全部像素的百分比。从表中可以清晰看到,视盘与视杯在整幅眼底图像中仅占不足 1% 的像素,属于典型的小目标、类别极不均衡的医学分割问题,这也对分割模型的细节表征能力提出了较高要求。
环境依赖与项目前提
根据项目 README,复现该项目需要以下软件环境(以仓库记录为准):
- Python v3.8
- PyTorch v1.10.0
- pillow(PIL)v9.3.0
- scikit-learn(sklearn)v1.2.0(用于数据集切分)
- MIM v0.3.4(OpenMMLab 模型管理工具)
- MMCV v2.0.0rc4
- MMEngine v0.2.0 或更高版本
- MMSegmentation v1.0.0rc5
所有下述命令都依赖PYTHONPATH的正确配置,使其指向项目目录,以便 Python 能够定位到模块文件。在gamma3/根目录下执行以下命令,将当前目录加入PYTHONPATH:
export PYTHONPATH=`pwd`:$PYTHONPATH数据集准备:从官方原始数据到 MMSegmentation 标准目录
第一步:下载并解压官方数据
从 GAMMA 挑战赛官方页面下载数据集,并解压到data/目录。官方原始数据的内部目录结构为(对应 prepare_dataset.py 中的硬编码路径):
data/ └── task3_disc_cup_segmentation/ ├── training/ │ ├── fundus color images/ # 训练集眼底彩照(.jpg) │ └── Disc_Cup_Mask/ # 训练集视盘视杯掩膜(.png) └── testing/ └── fundus color images/ # 测试集眼底彩照(.jpg)第二步:运行数据预处理脚本
在gamma3目录下执行:
python tools/prepare_dataset.py该脚本完成两类核心工作:
- 格式统一:将训练/测试眼底彩照从
.jpg统一转换为.png,并分别归档到data/images/train/与data/images/test/;将训练掩膜复制到data/masks/train/。 - 标签重映射:官方掩膜中使用的原始灰度值为
[0, 128, 255],分别对应['optic cup', 'optic disc', 'background'];脚本通过convert_dict = {0: 2, 128: 1, 255: 0}将其转换为 MMSegmentation 约定的连续类别编号[0, 1, 2],分别对应['background', 'optic disc', 'optic cup']。
对应源码片段(prepare_dataset.py):
def convert_label_pics_into_pngs(src_dir, tgt_dir, suffix, convert_dict={ 0: 2, 128: 1, 255: 0 }): ... # original: [0, 128, 255] for ['optic cup', 'optic disc', 'background'] # converted: [0, 1, 2] for ['background', 'optic disc', 'optic cup']第三步:切分数据集并生成标注文件
python ../../tools/split_seg_dataset.py注意,该切分脚本并不位于gamma3目录内,而是位于医学影像项目共用的 projects/medical/2d_image/tools/split_seg_dataset.py。脚本逻辑如下:
- 若存在
data/masks/val或data/masks/test,则直接基于官方划分生成对应的val.txt/test.txt; - 若官方验证集与测试集的标注无法获取(本项目即属此情形,官方仅公开训练集标注),脚本会调用
sklearn.model_selection.train_test_split,以test_size=0.2、random_state=0从训练集中随机切分出 80% 作为训练集、20% 作为验证集,并分别生成train.txt与val.txt。
切分完成后,目录结构如下:
mmsegmentation ├── mmseg ├── projects │ ├── medical │ │ ├── 2d_image │ │ │ ├── fundus_photography │ │ │ │ ├── gamma3 │ │ │ │ │ ├── configs │ │ │ │ │ ├── datasets │ │ │ │ │ ├── tools │ │ │ │ │ ├── data │ │ │ │ │ │ ├── train.txt │ │ │ │ │ │ ├── val.txt │ │ │ │ │ │ ├── images │ │ │ │ │ │ │ ├── train │ │ │ │ │ │ │ │ ├── xxx.png │ │ │ │ │ │ │ │ ├── ... │ │ │ │ │ │ │ │ └── xxx.png │ │ │ │ │ │ │ ├── test │ │ │ │ │ │ │ │ ├── yyy.png │ │ │ │ │ │ │ │ ├── ... │ │ │ │ │ │ │ │ └── yyy.png │ │ │ │ │ │ ├── masks │ │ │ │ │ │ │ ├── train │ │ │ │ │ │ │ │ ├── xxx.png │ │ │ │ │ │ │ │ ├── ... │ │ │ │ │ │ │ │ └── xxx.png自切分后的数据集统计
由于官方验证集/测试集标注不可用,本项目自行从训练集随机切分,切分后的分布如下:
| 类别名称 | 训练集数量 | 训练集像素占比(Pct) | 验证集数量 | 验证集像素占比(Pct) | 测试集数量 |
|---|---|---|---|---|---|
| background(背景) | 80 | 99.01 | 20 | 99.07 | - |
| optic disc(视盘) | 80 | 0.68 | 20 | 0.63 | - |
| optic cup(视杯) | 80 | 0.32 | 20 | 0.31 | - |
可以看到,自切分后训练/验证集的类别占比与官方训练集基本一致,保持了类别不均衡的原始特性。
数据集类实现:Gamma3Dataset
本项目通过 MMSegmentation 的注册机制实现了自定义数据集类 Gamma3Dataset,核心源码如下:
from mmseg.datasets import BaseSegDataset from mmseg.registry import DATASETS @DATASETS.register_module() class Gamma3Dataset(BaseSegDataset): """Gamma3Dataset dataset. In segmentation map annotation for Gamma3Dataset, ``reduce_zero_label`` is fixed to False. The ``img_suffix`` is fixed to '.png' and ``seg_map_suffix`` is fixed to '.png'. """ METAINFO = dict(classes=('background', 'disc', 'cup')) def __init__(self, img_suffix='.png', seg_map_suffix='.png', reduce_zero_label=False, **kwargs) -> None: super().__init__( img_suffix=img_suffix, seg_map_suffix=seg_map_suffix, reduce_zero_label=reduce_zero_label, **kwargs)关键实现细节:
METAINFO声明了 3 个类别('background', 'disc', 'cup'),与预处理脚本转换后的标签编号一一对应;img_suffix与seg_map_suffix均固定为.png,即输入图像与分割掩膜统一使用 PNG 格式;reduce_zero_label=False,即标签 0(背景)作为正常类别参与训练与评估,不会被剔除。这一设置在医学分割场景下通常是合理的,因为背景像素占比虽高,但仍是语义类别的一部分。
在配置文件中,通过custom_imports = dict(imports='datasets.gamma3_dataset')引入该自定义数据集模块,并在dataset_type = 'Gamma3Dataset'中直接引用。
配置文件逐项解析
数据集与数据流水线配置:gamma3_512x512.py
该文件是 Gamma3 任务的数据与评测公共配置,要点如下:
dataset_type = 'Gamma3Dataset' data_root = 'data/' img_scale = (512, 512)训练数据流水线(train_pipeline):
| 变换 | 参数 | 作用 |
|---|---|---|
LoadImageFromFile | - | 读取眼底彩照 |
LoadAnnotations | - | 读取分割掩膜 |
Resize | scale=(512, 512), keep_ratio=False | 强制缩放到 512×512,不保持宽高比 |
RandomFlip | prob=0.5 | 50% 概率水平随机翻转,进行数据增强 |
PhotoMetricDistortion | - | 亮度/对比度/饱和度/色调等光度扰动增强 |
PackSegInputs | - | 将图像与标注打包为模型输入格式 |
测试数据流水线(test_pipeline)仅包含LoadImageFromFile、Resize、LoadAnnotations与PackSegInputs,不包含任何随机增强,保证评测结果可复现。
Dataloader 与评测器配置:
- 训练:
batch_size=16、num_workers=4、InfiniteSampler(shuffle=True)(配合 20k 迭代式训练); - 验证/测试:
batch_size=1、DefaultSampler(shuffle=False); - 评测指标:
IoUMetric,同时计算mIoU与mDice两个指标,兼顾像素级交并比与区域重叠度的评估。
模型骨架:UNet + FCN 解码头
三个训练配置均继承自基础模型配置 fcn_unet_s5-d16.py,其结构为:
- 骨干网络
UNet:输入通道 3(RGB 眼底彩照),base_channels=64,5 个编码阶段(num_stages=5),每阶段 2 个卷积,下采样 4 次(downsamples=(True, True, True, True)),上采样使用InterpConv; - 解码头
FCNHead:in_channels=64、in_index=4,输出通道数默认为 2(在 Gamma3 配置中被覆盖为 3),损失函数为CrossEntropyLoss; - 默认的测试模式为
slide(滑窗,crop_size=256、stride=170),在 Gamma3 配置中被覆盖为whole(整图推理)。
三个训练配置:学习率消融实验
configs目录下提供了三个仅学习率不同的训练配置,构成了一个直观的学习率消融实验:
| 配置文件 | 优化器学习率 |
|---|---|
| fcn-unet-s5-d16_unet_1xb16-0.0001-20k_gamma3-512x512.py | 0.0001 |
| fcn-unet-s5-d16_unet_1xb16-0.001-20k_gamma3-512x512.py | 0.001 |
| fcn-unet-s5-d16_unet_1xb16-0.01-20k_gamma3-512x512.py | 0.01 |
以学习率为 0.001 的配置为例,完整配置如下(fcn-unet-s5-d16_unet_1xb16-0.001-20k_gamma3-512x512.py):
_base_ = [ 'mmseg::_base_/models/fcn_unet_s5-d16.py', './gamma3_512x512.py', 'mmseg::_base_/default_runtime.py', 'mmseg::_base_/schedules/schedule_20k.py' ] custom_imports = dict(imports='datasets.gamma3_dataset') img_scale = (512, 512) data_preprocessor = dict(size=img_scale) optimizer = dict(lr=0.001) optim_wrapper = dict(optimizer=optimizer) model = dict( data_preprocessor=data_preprocessor, decode_head=dict(num_classes=3), auxiliary_head=None, test_cfg=dict(mode='whole', _delete_=True)) vis_backends = None visualizer = dict(vis_backends=vis_backends)逐项说明:
_base_继承链:mmseg::_base_/models/fcn_unet_s5-d16.py(UNet 模型)、./gamma3_512x512.py(Gamma3 数据与评测配置)、mmseg::_base_/default_runtime.py(默认运行环境)、mmseg::_base_/schedules/schedule_20k.py(20k 迭代训练调度)。其中mmseg::前缀表示从 MMSegmentation 包的configs目录解析基础配置;custom_imports:显式导入datasets.gamma3_dataset模块,完成自定义数据集的注册;decode_head=dict(num_classes=3):将 FCN 解码头输出类别数由默认的 2 覆盖为 3(背景/视盘/视杯);auxiliary_head=None:关闭 UNet 的辅助解码头,仅使用主解码头输出;test_cfg=dict(mode='whole', _delete_=True):将测试推理模式由基础配置的slide(滑窗)切换为whole(整图),并删除被覆盖的旧字段;对于 512×512 的医学图像,整图推理在保证精度的同时更为高效;vis_backends = None:关闭可视化后端,降低训练过程中的额外开销(可根据需要开启 Tensorboard 等后端)。
训练与测试命令
训练
在单机单卡(默认)环境下训练模型:
mim train mmseg ./configs/${CONFIG_PATH}其中${CONFIG_PATH}替换为上述三个配置文件名之一,例如:
mim train mmseg ./configs/fcn-unet-s5-d16_unet_1xb16-0.001-20k_gamma3-512x512.pymim会自动解析配置中的依赖(如 MMCV、MMEngine、MMSegmentation),并拉起训练流程;训练迭代数为 20k,批大小为 16(对应配置名中的1xb16)。
测试
使用训练产出的权重对模型进行评测:
mim test mmseg ./configs/${CONFIG_PATH} --checkpoint ${CHECKPOINT_PATH}例如:
mim test mmseg ./configs/fcn-unet-s5-d16_unet_1xb16-0.001-20k_gamma3-512x512.py --checkpoint /path/to/checkpoint.pth测试阶段将依据 gamma3_512x512.py 中的test_evaluator输出mIoU与mDice两项指标,用于量化模型在背景、视盘、视杯三个类别上的分割质量。
项目质量状态(Checklist)解读
项目 README 末尾附带了一份 OpenMMLabprojects/目录的标准质量清单,当前状态为:
- 已完成:代码编写、基础 docstring 与文献引用、完整 README;
- 待完成:测试时正确性验证、训练时正确性验证、类型注解与单元测试、代码润色、
metafile.yml元数据文件,以及将模块迁移/重构进核心包等后续里程碑。
这意味着该项目当前定位为可供复现与二次开发的社区实验项目(位于projects/而非核心mmseg/models),使用前建议自行验证训练与测试的正确性,并根据实际 GPU 环境调整批大小等超参数。
相关文献引用
若在学术工作中使用该数据集或本项目,建议引用以下文献(来自项目 README 的 BibTeX):
@article{fu2018joint, title={Joint optic disc and cup segmentation based on multi-label deep network and polar transformation}, author={Fu, Huazhu and Cheng, Jun and Xu, Yanwu and Wong, Damon Wing Kee and Liu, Jiang and Cao, Xiaochun}, journal={IEEE transactions on medical imaging}, volume={37}, number={7}, pages={1597--1605}, year={2018}, publisher={IEEE} } @article{sevastopolsky2017optic, title={Optic disc and cup segmentation methods for glaucoma detection with modification of U-Net convolutional neural network}, author={Sevastopolsky, Artem}, journal={Pattern Recognition and Image Analysis}, volume={27}, pages={618--624}, year={2017}, publisher={Springer} }总结与实践建议
Gamma3 项目完整展示了在 MMSegmentation 中落地一个医学影像分割任务的标准工作流:自定义数据集类注册 → 原始数据格式统一与标签重映射 → 训练/验证集切分与标注文件生成 → 数据流水线与评测指标配置 → 基于 UNet 的模型训练与测试。项目中同时提供了三档学习率(1e-4 / 1e-3 / 1e-2)的对比配置,便于研究者快速开展超参数实验。
实践层面有三点值得注意:其一,视盘/视杯在图像中占比极小(合计不足 1%),训练时可关注类别不均衡对 mIoU/mDice 的影响;其二,官方仅公开训练集标注,本项目采用train_test_split(test_size=0.2, random_state=0)的自切分策略,复现时需保持相同的随机种子以保证结果可比;其三,若需进一步提升分割精度,可在projects/medical/2d_image/tools/split_seg_dataset.py与prepare_dataset.py的基础上按需改造,或参考mmseg核心包中的其他医学影像模型进行迁移实验。
【免费下载链接】mmsegmentationOpenMMLab Semantic Segmentation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmsegmentation
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考