在 MMSegmentation 中使用 RAVIR 数据集:红外反射眼底影像动静脉语义分割完整实战指南
【免费下载链接】mmsegmentationOpenMMLab Semantic Segmentation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmsegmentation
导读
本文围绕 OpenMMLab 语义分割工具箱 MMSegmentation 中开箱即用的RAVIR 医学影像项目,系统讲解如何在红外反射(Infrared Reflectance, IR)眼底影像上训练一个能够自动区分**视网膜动脉(artery)与静脉(vein)**的语义分割模型。文章将完整覆盖 RAVIR 数据集的背景与统计信息、环境准备、数据下载与预处理、目录结构、基于 FCN-UNet 的配置解读、训练与测试命令,并结合仓库源码剖析数据标注映射、数据集注册与训练管线等底层实现。读完本文,你将能够独立完成从原始数据到模型推理的完整链路,并掌握 MMSegmentation 中医疗影像分割项目从数据到配置的通用接入方法。
RAVIR 数据集简介
RAVIR(Retinal Arteries and Veins in Infrared Reflectance imaging)是一个面向视网膜动脉与静脉语义分割任务的开源医学影像数据集,其完整名称与对应论文为RAVIR: A Dataset and Methodology for the Semantic Segmentation and Quantitative Analysis of Retinal Arteries and Veins in Infrared Reflectance Imaging。该项目在 MMSegmentation 仓库中位于 projects/medical/2d_image/infrared_reflectance_imaging/ravir,其 README(即本文所依据的主文档)保存在该目录下。
临床意义与任务背景
视网膜血管系统在高血压、糖尿病等系统性疾病的诊断与监测中具有重要参考价值。微血管系统是此类疾病的主要受累部位,而视网膜是人体内唯一能直接观察到微血管的解剖部位,因此对视网膜血管的客观评估长期以来被视为系统性血管疾病的替代生物标志物(surrogate biomarker)。随着视网膜成像与计算机视觉技术的进步,该课题近年来重新受到广泛关注。RAVIR 数据集的价值在于:它支持构建基于深度学习的分割模型,能够直接区分提取出的血管类型(动脉/静脉),而无需大量复杂的后处理。
数据集原始统计信息
根据项目 README 中的原始统计表,RAVIR 数据集的概况如下:
| 数据集名称 | 解剖区域 | 任务类型 | 模态 | 类别数 | Train/Val/Test 图像数 | Train/Val/Test 标注数 | 发布日期 | 许可证 |
|---|---|---|---|---|---|---|---|---|
| Ravir | eye(眼部) | segmentation(分割) | infrared reflectance imaging(红外反射成像) | 3 | 23/-/19 | yes/-/- | 2022 | CC-BY-NC 4.0 |
原始数据集的三个类别为background(背景)、artery(动脉)、vein(静脉),其训练集像素占比统计如下:
| 类别名称 | 训练图像数 | 训练像素占比(Pct. Train) |
|---|---|---|
| background | 23 | 87.22 |
| artery | 23 | 5.45 |
| vein | 23 | 7.33 |
说明:表中的
Pct表示该类别像素占全部像素的百分比。从统计可见,背景占比超过 87%,动脉与静脉合计不足 13%,这是一个典型的类别极不均衡的医学分割任务,后续训练时需要依赖数据增强与合适的损失配置来缓解。
项目结构总览
该医学影像项目以独立子项目形式组织在 MMSegmentation 的projects/目录下,其关键文件结构如下:
mmsegmentation ├── mmseg ├── projects │ ├── medical │ │ ├── 2d_image │ │ │ ├── infrared_reflectance_imaging │ │ │ │ ├── ravir │ │ │ │ │ ├── configs # 训练/测试配置文件 │ │ │ │ │ │ ├── fcn-unet-s5-d16_unet_1xb16-0.0001-20k_ravir-512x512.py │ │ │ │ │ │ ├── fcn-unet-s5-d16_unet_1xb16-0.001-20k_ravir-512x512.py │ │ │ │ │ │ ├── fcn-unet-s5-d16_unet_1xb16-0.01-20k_ravir-512x512.py │ │ │ │ │ │ └── ravir_512x512.py # 数据集/数据加载器公共配置 │ │ │ │ │ ├── datasets │ │ │ │ │ │ └── ravir_dataset.py # RAVIRDataset 数据集类 │ │ │ │ │ ├── tools │ │ │ │ │ │ └── prepare_dataset.py # 数据整理与标注重映射脚本 │ │ │ │ │ ├── data # 运行预处理后生成的数据目录 │ │ │ │ │ │ ├── train.txt / val.txt │ │ │ │ │ │ ├── images │ │ │ │ │ │ │ ├── train / test │ │ │ │ │ │ └── masks │ │ │ │ │ │ └── train其中configs/、datasets/、tools/三个目录是项目的核心代码;data/目录在运行 tools/prepare_dataset.py 与切分脚本后生成。
环境准备(Prerequisites)
项目 README 明确列出的运行环境依赖如下:
- Python v3.8
- PyTorch v1.10.0
- pillow(PIL)v9.3.0
- scikit-learn(sklearn)v1.2.0
- MIM v0.3.4
- MMCV v2.0.0rc4
- MMEngine v0.2.0 或更高版本
- MMSegmentation v1.0.0rc5
说明:以上版本号以项目 README 记载为准。在 MMSegmentation 当前仓库版本下,建议结合 requirements/mminstall.txt 与官方安装文档确认 mmcv/mmengine 与当前主干版本的匹配关系,避免版本不一致导致的兼容性问题。
设置 PYTHONPATH
所有后续命令都依赖正确的PYTHONPATH配置,使其指向项目根目录,从而让 Python 能够定位到模块文件。在ravir/根目录下执行以下命令,将当前目录加入PYTHONPATH:
export PYTHONPATH=`pwd`:$PYTHONPATH这一步非常关键:RAVIR 的配置文件通过custom_imports = dict(imports='datasets.ravir_dataset')动态导入自定义数据集类,只有将ravir/加入PYTHONPATH,该导入才能成功。
数据准备(Dataset preparing)
第一步:下载并解压原始数据
从 RAVIR 官方竞赛网站下载数据集,并解压到data/ravir/路径下。原始压缩包内包含RAVIR Dataset目录,其中train/training_images存放训练图像、train/training_masks存放训练掩码、test存放测试图像。
第二步:运行数据整理脚本
执行以下命令,将原始目录中的文件拷贝到标准结构,并将标注掩码的像素值重映射为类别索引:
python tools/prepare_dataset.py查看 tools/prepare_dataset.py 的源码可以清晰还原其逻辑:
- 创建
data/ravir/images/train、data/ravir/images/test、data/ravir/masks/train三个目录; - 将
RAVIR Dataset/train/training_images/*拷贝到images/train,将RAVIR Dataset/train/training_masks/*拷贝到masks/train,将RAVIR Dataset/test/*拷贝到images/test; - 删除临时解压目录
RAVIR Dataset; - 遍历
masks/train下的全部 PNG 掩码,执行像素值重映射:255 → 2(vein)、128 → 1(artery)、0 → 0(background),即脚本注释中的映射关系map = {255:2, 128:1, 0:0},并覆盖保存。
该重映射逻辑与 datasets/ravir_dataset.py 中METAINFO = dict(classes=('background', 'artery', 'vein'))的类别顺序严格对应,是保证训练标签正确的关键步骤。
第三步:切分数据集并生成标注文件
执行以下命令,将数据切分为训练/验证集,并生成train.txt、val.txt(必要时还有test.txt):
python ../../tools/split_seg_dataset.py --data_root data/ravir注意:这里
../../tools/相对于ravir/目录,实际指向 projects/medical/2d_image/tools/split_seg_dataset.py。
结合该脚本源码可以理解其切分策略:
- 若
masks/val或masks/test目录存在(即有官方验证/测试标注),则直接生成对应val.txt/test.txt; - 若官方验证集与测试集的标签无法获取(RAVIR 场景正是如此,官方仅公开训练标注),则使用
sklearn.model_selection.train_test_split,以test_size=0.2、random_state=0从训练集中随机划分出训练集与验证集,分别写入train.txt与val.txt; save_anno函数会去除文件后缀并保留images/train/xxx这种相对路径形式(去掉images/train前的目录层级),与数据加载时data_prefix的拼接方式匹配。
第四步:确认最终目录结构
完成上述三步后,data/ravir/下应呈现如下结构(README 中的标准形态):
data ├── train.txt ├── val.txt ├── images │ ├── train │ │ ├── xxx.png │ │ └── ... │ └── test │ ├── yyy.png │ └── ... └── masks └── train ├── xxx.png └── ...切分后的数据集统计信息
由于官方验证集/测试集标签不可得,验证集由训练集按 8:2 随机切分而来(README 中注明The table information below is divided by ourselves,即该统计是项目自切分结果):
| 类别名称 | 训练图像数 | 训练像素占比 | 验证图像数 | 验证像素占比 | 测试图像数 | 测试像素占比 |
|---|---|---|---|---|---|---|
| background | 18 | 87.41 | 5 | 86.53 | - | - |
| artery | 18 | 5.44 | 5 | 5.50 | - | - |
| vein | 18 | 7.15 | 5 | 7.97 | - | - |
即 23 张带标注训练图按 18/5 划分,测试集 19 张仅用于推理预测。
数据集实现源码解析
RAVIR 的自定义数据集类定义在 datasets/ravir_dataset.py:
from mmseg.datasets import BaseSegDataset from mmseg.registry import DATASETS @DATASETS.register_module() class RAVIRDataset(BaseSegDataset): """RAVIRDataset dataset. In segmentation map annotation for RAVIRDataset, 0 stands for background, which is included in 3 categories. ``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', 'artery', 'vein')) 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)几个值得注意的实现要点:
- 继承
BaseSegDataset:复用 MMSegmentation 自带的图像/掩码加载、ann_file解析与data_prefix路径拼接能力,无需重复实现; - 通过
@DATASETS.register_module()注册:使配置文件中dataset_type = 'RAVIRDataset'的字符串能够被注册表解析为对应类; METAINFO固定为 3 类:background(0)、artery(1)、vein(2),与预处理脚本的像素重映射严格对应;reduce_zero_label=False:由于背景(0)本身就是需要预测的有效类别,不执行"0 类标签剔除"操作,这与 Cityscapes 等把 0 当作 ignore 的任务不同;- 图像与掩码均为 PNG:
img_suffix与seg_map_suffix均固定为'.png'。
配置文件深度解读
公共数据集配置:ravir_512x512.py
configs/ravir_512x512.py 定义了数据集、数据管线与评估指标,是三个训练配置共同引用的基础文件,核心内容如下:
dataset_type = 'RAVIRDataset',data_root = 'data/ravir',统一缩放到img_scale = (512, 512);- 训练管线
train_pipeline:LoadImageFromFile→LoadAnnotations→Resize(scale=512x512,keep_ratio=False)→RandomFlip(概率 0.5)→PhotoMetricDistortion(光度/颜色扰动增强)→PackSegInputs; - 测试管线
test_pipeline:仅LoadImageFromFile→Resize→LoadAnnotations→PackSegInputs,不使用随机增强; - 训练数据加载器:
batch_size=16、num_workers=4、persistent_workers=True,采样器为InfiniteSampler(shuffle=True)(配合基于迭代数的训练循环); - 验证/测试数据加载器:
batch_size=1、DefaultSampler(shuffle=False),test_dataloader = val_dataloader复用验证集配置; - 评估指标:
val_evaluator与test_evaluator均使用IoUMetric,同时计算mIoU与mDice两个指标——mDice(Dice 系数)在医学影像分割中尤为常用。
训练配置:fcn-unet-s5-d16 三份学习率变体
以 configs/fcn-unet-s5-d16_unet_1xb16-0.01-20k_ravir-512x512.py 为例,配置通过继承多个基础配置拼装而成:
_base_ = [ 'mmseg::_base_/models/fcn_unet_s5-d16.py', './ravir_512x512.py', 'mmseg::_base_/default_runtime.py', 'mmseg::_base_/schedules/schedule_20k.py' ] custom_imports = dict(imports='datasets.ravir_dataset') img_scale = (512, 512) data_preprocessor = dict(size=img_scale) optimizer = dict(lr=0.01) optim_wrapper = dict(optimizer=optimizer) model = dict( type='EncoderDecoder', data_preprocessor=data_preprocessor, pretrained=None, 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)各组成部分的含义:
- 模型骨架 configs/base/models/fcn_unet_s5-d16.py:
EncoderDecoder框架 +UNet骨干(in_channels=3、base_channels=64、num_stages=5、编码器每阶段 2 个卷积、解码器 2 个卷积、InterpConv上采样、SyncBN+ ReLU)+FCNHead解码头。基础配置中解码头默认num_classes=2、且带有auxiliary_head,因此需要在本配置中覆写; custom_imports:声明动态导入datasets.ravir_dataset,是加载RAVIRDataset的入口;decode_head=dict(num_classes=3):将 FCN 解码头类别数由默认 2 修正为 3(background/artery/vein);auxiliary_head=None:关闭辅助头。因为 UNet 本身是多阶段特征复用结构,且 RAVIR 图像数量少、任务相对简单,去掉辅助损失以简化训练;test_cfg=dict(mode='whole', _delete_=True):测试推理模式由基础配置的mode='slide'(滑窗,crop_size=256/stride=170)改为整图推理mode='whole'。_delete_=True表示删除继承来的slide相关字段。整图推理在 512x512 小尺寸输入下即可覆盖全图,无需滑窗;- 学习率:
optimizer = dict(lr=0.01)覆盖继承自 configs/base/schedules/schedule_20k.py 的 SGD 优化器(lr=0.01, momentum=0.9, weight_decay=0.0005)。另外两份配置仅将lr分别改为0.001与0.0001,用于对比不同学习率下的收敛效果; - 训练计划:继承
schedule_20k.py,即IterBasedTrainLoop训练20000 个迭代、每 2000 迭代验证一次;学习率采用PolyLR(power=0.9, eta_min=1e-4);CheckpointHook每 2000 迭代保存一次 checkpoint; vis_backends = None:关闭可视化后端,避免在无显示环境(如服务器)下因初始化可视化相关组件而出错。
训练与测试命令
训练命令
在单机单 GPU 上训练模型(默认配置):
mim train mmseg ./configs/${CONFIG_PATH}其中${CONFIG_PATH}替换为具体配置文件路径,例如:
mim train mmseg ./configs/fcn-unet-s5-d16_unet_1xb16-0.01-20k_ravir-512x512.pymim(OpenMMLab 的模型安装管理工具)会自动定位已安装的 MMSegmentation 包并解析配置中_base_的继承关系,无需手动指定--config等参数。训练过程中会在工作目录下生成work_dirs/输出目录,保存日志、checkpoint 与可视化结果。
测试命令
在单机单 GPU 上测试模型:
mim test mmseg ./configs/${CONFIG_PATH} --checkpoint ${CHECKPOINT_PATH}--checkpoint指向训练得到的权重文件(如work_dirs/xxx/iter_20000.pth)。测试将按配置中的test_evaluator输出mIoU与mDice等评估结果。
结果汇总
项目 README 提供了基于fcn_unet_s5-d16(UNet 骨干)在 512x512 输入、20k 迭代下的三份配置,三者的唯一区别是学习率:
| 方法 | 骨干网络 | 裁剪尺寸 | lr | 配置文件 |
|---|---|---|---|---|
| fcn_unet_s5-d16 | unet | 512x512 | 0.01 | config |
| fcn_unet_s5-d16 | unet | 512x512 | 0.001 | config |
| fcn_unet_s5-d16 | unet | 512x512 | 0.0001 | config |
说明:README 中该结果表仅列出配置,未附上对应训练得到的 mIoU/mDice 数值,也不涉及预训练权重转换说明;如需复现,请直接运行上文训练命令并在
work_dirs中查看验证指标。
数据引用(Citation)
若在科研工作中使用 RAVIR 数据集,请按以下 BibTeX 引用原始论文(该引用信息完整收录于项目 README):
@article{hatamizadeh2022ravir, title={RAVIR: A dataset and methodology for the semantic segmentation and quantitative analysis of retinal arteries and veins in infrared reflectance imaging}, author={Hatamizadeh, Ali and Hosseini, Hamid and Patel, Niraj and Choi, Jinseo and Pole, Cameron C and Hoeferlin, Cory M and Schwartz, Steven D and Terzopoulos, Demetri}, journal={IEEE Journal of Biomedical and Health Informatics}, volume={26}, number={7}, pages={3272--3283}, year={2022}, publisher={IEEE} }项目成熟度与后续演进
项目 README 末尾以 Checklist 形式标注了该子项目的成熟度状态,从中可以客观了解其定位:
- Milestone 1(已完成):代码完成、具备基本 docstring 与正确引用、测试期正确性验证通过、README 完整——已达到并入
projects/的准入门槛; - Milestone 2(已完成):训练期正确性验证通过,即模型实现可成功训练;
- Milestone 3(未完成):类型注解(type hints)与 docstring 完善、单元测试、代码打磨、Metafile.yml 均未完成;
- 未完成项:将模块迁移进核心包(
mmseg/)、按代码库文件层级重构模块。
这解释了为什么该功能以projects/子项目而非核心模块的形式存在:它属于社区贡献的高质量复现/接入样例,尚处于"项目级"而非"核心包级"的成熟阶段。使用者可以放心训练与推理,但若需长期依赖,建议关注后续迁移进度。
小结
本文以 projects/medical/2d_image/infrared_reflectance_imaging/ravir/README.md 为主线,结合仓库源码完整还原了 RAVIR 医学分割项目从环境配置、数据预处理(像素重映射与 8:2 随机切分)、数据集类实现、配置文件继承逻辑到训练测试命令的全流程。核心要点可归纳为:
- 数据是关键:掩码像素必须经 tools/prepare_dataset.py 将 255/128/0 重映射为 2/1/0,与
RAVIRDataset.METAINFO的类别顺序严格一致; - 配置靠继承:通过
_base_组合 UNet 模型、数据集配置、默认运行时与 20k 训练计划,仅需覆写num_classes=3、关闭辅助头、改为整图推理并调节学习率即可适配任务; - 训练验证闭环:
mim train/mim test一条命令完成,评估同时报告 mIoU 与医学场景常用的 mDice。
该项目的实现模式同样适用于projects/medical/2d_image/下的其他医学影像数据集,可作为接入新医学分割数据集的通用模板参考。
【免费下载链接】mmsegmentationOpenMMLab Semantic Segmentation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmsegmentation
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考