MMSegmentation简介
- 项目地址:https://github.com/open-mmlab/mmsegmentation
- 文档:https://mmsegmentation.readthedocs.io/en/latest/
MMSegmentation的项目结构
- 整体架构
- 分割模型的模块化设计
MMSegmentation 将分割模型统一拆解为如下模块,方便用户根据自己的需求进行组装和扩展。
MMSegmentation代码实践
1. 配置环境
1)使用conda创建虚拟环境
# 创建 python=3.8 的det环境
conda create --name mmsegmentation python=3.8
# 激活环境
source activate mmsegmentation
2)安装torch
# 安装 torch
conda install pytorch torchvision torchaudio pytorch-cuda=11.6 -c pytorch -c nvidia
3)安装mmcv
mmcv模块安装时候需要注意 torch 和 cuda 版本,参考安装文档https://mmcv.readthedocs.io/zh_CN/latest/get_started/installation.html
pip install mmcv-full==1.7.0 -f https://download.openmmlab.com/mmcv/dist/cu116/torch1.13/index.html
pip install mmengine
4)安装MMSegmentation模块(从源码)
git clone https://github.com/open-mmlab/mmsegmentation.git
# git clone https://github.com/open-mmlab/mmsegmentation.git -b dev-1.x
cd mmsegmentation
# "-v "指详细说明,或更多的输出
# "-e" 表示在可编辑模式下安装项目,因此对代码所做的任何本地修改都会生效,从而无需重新安装。
pip install -v -e .
2. 创建数据集
1)下载数据集
# 进入mmsgementation目录
cd mmsegmentation
# 创建data目录
mkdir data && cd data
# 下载数据集
wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20230130-mmseg/dataset/Glomeruli-dataset.zip
# 解压
unzip Glomeruli-dataset.zip
2)划分数据集
# 进入mmsgementation目录
cd mmsegmentation
# 创建脚本
vim split_data.py
# 执行数据划分
python split_data.py
split_data.py
import os
import random
# 获取全部数据文件名列表
PATH_IMAGE = 'data/Glomeruli-dataset/images'
all_file_list = os.listdir(PATH_IMAGE)
all_file_num = len(all_file_list)
# 随机打乱全部数据文件名列表
random.shuffle(all_file_list)
# 指定训练集和测试集比例
train_ratio = 0.8
test_ratio = 1 - train_ratio
train_file_list = all_file_list[:int(all_file_num*train_ratio)]
test_file_list = all_file_list[int(all_file_num*train_ratio):]
print('数据集图像总数', all_file_num)
print('训练集划分比例', train_ratio)
print('训练集图像个数', len(train_file_list))
print('测试集图像个数', len(test_file_list))
os.mkdir('data/Glomeruli-dataset/splits')
with open('Glomeruli-dataset/splits/train.txt', 'w') as f:
f.writelines(line.split('.')[0] + '\n' for line in train_file_list)
with open('Glomeruli-dataset/splits/val.txt', 'w') as f:
f.writelines(line.split('.')[0] + '\n' for line in test_file_list)
spilt文件夹划分了数据集为训练和验证集,train.txt val.txt
3. 编写配置文件
1)下载权重
# 进入mmsgementation目录
cd mmsegmentation
mkdir checkpoints && cd checkpoints
wget https://download.openmmlab.com/mmsegmentation/v0.5/pspnet/pspnet_r50-d8_512x1024_40k_cityscapes/pspnet_r50-d8_512x1024_40k_cityscapes_20200605_003338-2966598c.pth
2)配置文件
编写pspnet_r50_Glomeruli.py
_base_ = [
'../_base_/models/pspnet_r50-d8.py', '../_base_/datasets/cityscapes.py',
'../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py'
]
norm_cfg = dict(type='BN', requires_grad=True) # 只使用GPU时,BN取代SyncBN
crop_size = (256, 256) # 训练时的裁剪大小
# 分割前景的种类数目。 通常情况下,cityscapes 为19,VOC为21,ADE20k 为150。
model = dict(
data_preprocessor=dict(size=crop_size),
backbone=dict(norm_cfg=norm_cfg),
decode_head=dict(num_classes=2 ,norm_cfg=norm_cfg
),
auxiliary_head=dict(num_classes=2,norm_cfg=norm_cfg
)
)
# 修改数据集的 type 和 root
dataset_type = 'StanfordBackgroundDataset'
# 数据集图片和标注路径
data_root = './data/Glomeruli-dataset'
img_dir = './data/Glomeruli-dataset/images'
ann_dir = './data/Glomeruli-dataset/masks'
# 训练集的预处理方法
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations'),
dict(type='RandomResize', scale=(320, 240), ratio_range=(0.5, 2.0), keep_ratio=True),
dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75),
dict(type='RandomFlip', prob=0.5),
dict(type='PackSegInputs')
]
# 测试集的预处理方法
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='Resize', scale=(320, 240), keep_ratio=True),
# add loading annotation after ``Resize`` because ground truth
# does not need to do resize data transform
dict(type='LoadAnnotations'),
dict(type='PackSegInputs')
]
train_dataloader =dict(
batch_size=8,
num_workers=4,
dataset=dict(
type = dataset_type,
data_root = data_root,
data_prefix = dict(img_path=img_dir, seg_map_path=ann_dir),
pipeline = train_pipeline,
ann_file = './data/Glomeruli-dataset/splits/train.txt')
)
val_dataloader =dict(
batch_size=8,
num_workers=4,
dataset=dict(
type = dataset_type,
data_root = data_root,
data_prefix = dict(img_path=img_dir, seg_map_path=ann_dir),
pipeline = test_pipeline,
ann_file = './data/Glomeruli-dataset/splits/val.txt')
)
test_dataloader =dict(
batch_size=8,
num_workers=4,
dataset=dict(
type = dataset_type,
data_root = data_root,
data_prefix = dict(img_path=img_dir, seg_map_path=ann_dir),
pipeline = test_pipeline,
ann_file = './data/Glomeruli-dataset/splits/val.txt')
)
# 载入预训练模型权重
load_from = './checkpoints/pspnet_r50-d8_512x1024_40k_cityscapes_20200605_003338-2966598c.pth'
# 训练迭代次数 ,对于 EpochBasedRunner 使用 `max_epochs`
# 将使用的 runner 的类别 (例如 IterBasedRunner 或 EpochBasedRunner) 对于 EpochBasedRunner 使用 `max_epochs` 。
runner = dict(type='EpochBasedRunner', max_epochs=50)
# 评估模型间隔
evaluation = dict(interval=10, metric='mIoU') # 评估的指标
# logging
log_config = dict(interval=10, hooks=[dict(type='TextLoggerHook')])
# 模型权重保存间隔
checkpoint_config = dict(interval=10)
4. 模型训练
编写run.sh脚本,起程序训练模型
#!/bin/bash
# 激活环境
source activate mmsegmentation
# 刷新⽇志缓存
export PYTHONUNBUFFERED=1
# 训练模型
python tools/train.py \
configs/pspnet50/pspnet_r50_Glomeruli.py \
--work-dir work/pspnet_r50_Glomeruli