mmsegmentation教程1:自定义数据集、config文件修改、训练教程

简介

mmsegmentation作为OpenLab重要的开源分割训练框架,统一了之前大家各写个的训练网络,导致很多工作无法复现。并且每次大家下载开源项目一打开项目,要面对各种千奇百怪的风格的代码,每次都要花费时间去适应,降低工作效率。

OpenLab的mmsegmentation统一了训练分割框架代码,把重要部分全面模块化,只要按照API,就可以很轻松的添加自己的工作,个人是很喜欢OpenLab的mm系列的。

但是OpenLab的工作给适应了之前千奇百怪代码的朋友们一定的难度,OpenLab的代码风格一打开,如果代码能力不是特别强的话,肯定是懵逼状态的。

其实mm系列需要修改的地方挺少的,以mmsegmentation为例,你要是想成功跑起来,只需要修改以下几个地方:

1、在mmseg/datasets下面对数据集进行初始定义
2、在configs/base/datasets下面对数据加载进行定义
3、在configs/下面选择你需要的模型参数进行修改
4、返回tools/train.py进行训练

其他的mmclassfication和mmdetection的修改方式也是相似的,下面进行具体讲解

文章目录

  • 简介
  • 下载和基础环境安装
  • 在mmseg/datasets下面对数据集进行初始定义
  • 在configs/_ _base_ _/datasets下面对数据加载进行定义
  • 在configs/下面选择你需要的模型参数进行修改
  • 返回tools/train.py进行训练
  • 测试的还没看

下载和基础环境安装

下载

https://github.com/open-mmlab/mmsegmentation

打不开的话就用下面这个(我下的是这个)

https://gitee.com/monkeycc/mmsegmentation

我使用实验室的Ubuntu环境,所以只需要下一个mmcv-full

pip install mmcv-full

ps:我下的这个包下面要求mmcv-full在1.3.13到1.5.0之间

在mmseg/datasets下面对数据集进行初始定义

由于自身水平有限,没法根据自己数据集原有的格式去修改框架中数据集读取方式,所以只能按照框架中规定的数据格式去更改自己数据集的格式:

  1. 按照官方给的文档,先把自己的数据集改成官方存放数据集格式

    ├── data
    │   ├── my_dataset
    │   │   ├── img_dir
    │   │   │   ├── train
    │   │   │   │   ├── xxx{img_suffix}
    │   │   │   │   ├── yyy{img_suffix}
    │   │   │   │   ├── zzz{img_suffix}
    │   │   │   ├── val
    │   │   ├── ann_dir
    │   │   │   ├── train
    │   │   │   │   ├── xxx{seg_map_suffix}
    │   │   │   │   ├── yyy{seg_map_suffix}
    │   │   │   │   ├── zzz{seg_map_suffix}
    │   │   │   ├── val
    

    img_dir中全部存在原图
    ann_dir中全部存放mask

  2. dataset class文件配置;
    在mmseg/datasets/目录下找到stare.py文件
    mmsegmentation教程1:自定义数据集、config文件修改、训练教程_第1张图片
    复制一份stare.py并粘贴在mmseg/datasets/目录下,重命名为my_dataset.py,打开my_dataset.py
    mmsegmentation教程1:自定义数据集、config文件修改、训练教程_第2张图片
    你需要修改标红的三个地方
    STAREDataset:表示你定义的数据的名字,顺便取一个名字即可
    CLASSES:表示你数据集的背景+类别
    PALETTE :表示你数据集各类别的像素值
    img_suffix:原图图像后缀
    seg_map_suffix:mask图像后缀
    比如我的数据集就需要修改为以下内容

    # Copyright (c) OpenMMLab. All rights reserved.
    import os.path as osp
    
    from .builder import DATASETS
    from .custom import CustomDataset
    
    
    @DATASETS.register_module()
    class MyDataset(CustomDataset):
        """DRIVE dataset.
    
        In segmentation map annotation for DRIVE, 0 stands for background, which is
        included in 2 categories. ``reduce_zero_label`` is fixed to False. The
        ``img_suffix`` is fixed to '.png' and ``seg_map_suffix`` is fixed to
        '_manual1.png'.
        """
    
        CLASSES = ('background', 'egc')
    
        PALETTE = [[0, 0, 0], [255, 255, 255]]
    
        def __init__(self, **kwargs):
            super(MyDataset, self).__init__(
                img_suffix='.jpg',
                seg_map_suffix='.png',
                reduce_zero_label=False,
                **kwargs)
            assert osp.exists(self.img_dir)
    
    

    PALETTE好像是调色板,我随便更改里面的数值发现对训练没啥影响,翻了一下其他大佬的回答,这个好像是训练完后进行测试后的结果保存,mmseg默认为把分割出来的mask结果直接画在原图上进行显示,PALETTE好像指定了画上原图的mask蒙版的颜色。

    PS:mmseg要求mask的像素在[0,num_classes-1]范围内,比如我是2分类,背景像素值为0,那么目标像素值应该为1。如果你也是二分类,mask为单通道(8 bit)二值化的0(背景)/255(目标)图像的话,先去把图像改为0(背景)/1(目标)图像,否则能跑起来,但是指标异常,几乎全是0。(这是个大坑!!!一定要注意)

    修改mmseg/datasets/目录下的_init_.py
    mmsegmentation教程1:自定义数据集、config文件修改、训练教程_第3张图片
    把图中标红的加到原_init_.py中

在configs/_ base _/datasets下面对数据加载进行定义

在configs/__ base __/datasets/目录下找到stare.py文件,复制一份重命名为my_dataset.py。进行修改

# dataset settings
dataset_type = 'MyDataset' #上一步中你定义的数据集的名字
data_root = '/data/egc224mmsegStyle' #数据集存储路径
img_norm_cfg = dict(
    mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) #数据集的均值和标准差,空引用默认的,也可以网上搜代码计算
crop_size = (224, 224) #数据增强时裁剪的大小
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='LoadAnnotations', reduce_zero_label=True),
    dict(type='Resize', img_scale=(224, 224), ratio_range=(0.5, 2.0)), #img_scale图像尺寸
    dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75),
    dict(type='RandomFlip', prob=0.5),
    dict(type='PhotoMetricDistortion'),
    dict(type='Normalize', **img_norm_cfg),
    dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255),
    dict(type='DefaultFormatBundle'),
    dict(type='Collect', keys=['img', 'gt_semantic_seg']),
]
test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(
        type='MultiScaleFlipAug',
        img_scale=(224, 224), #img_scale图像尺寸
        # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75],
        flip=False,
        transforms=[
            dict(type='Resize', keep_ratio=True),
            dict(type='RandomFlip'),
            dict(type='Normalize', **img_norm_cfg),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img']),
        ])
]
data = dict(
    samples_per_gpu=16, #batch_size
    workers_per_gpu=1, #nums gpu
    train=dict(
        type=dataset_type,
        data_root=data_root,
        img_dir='img_dir/train', #训练图像路径
        ann_dir='ann_dir/train', #训练mask路径
        pipeline=train_pipeline),
    val=dict(
        type=dataset_type,
        data_root=data_root,
        img_dir='img_dir/val',  #验证图像路径
        ann_dir='ann_dir/val',  #验证mask路径
        pipeline=test_pipeline),
    #我的数据集没有测试集,和验证集用同一路径,问题不大
    test=dict(
        type=dataset_type,
        data_root=data_root,
        img_dir='img_dir/val',  #测试图像路径
        ann_dir='ann_dir/val',  #测试mask路径
        pipeline=test_pipeline)
)

需要修改的地方在上面的代码中用中文标出来了

在configs/下面选择你需要的模型参数进行修改

以DANet为例子吗,找到configs/danet/下的danet_r50-d8_512x512_20k_voc12aug.py
mmsegmentation教程1:自定义数据集、config文件修改、训练教程_第4张图片
打开并修改这几个位置
mmsegmentation教程1:自定义数据集、config文件修改、训练教程_第5张图片

_base_ = [
    '../_base_/models/danet_r50-d8.py',   #这个是网络的骨架,使用单卡记得去骨架模型里将SyncBN改成BN
    '../_base_/datasets/my_dataset.py',   #换成自己定义的数据集
    '../_base_/default_runtime.py',
    '../_base_/schedules/schedule_20k.py'
]
model = dict(
    decode_head=dict(num_classes=2), auxiliary_head=dict(num_classes=2)) #换成自己的分类类别数

找到configs/base/models/下面的danet_r50-d8.py

# model settings
norm_cfg = dict(type='BN', requires_grad=True) #SyncBN代表分布式训练,单卡训练将其改成BN
model = dict(
    type='EncoderDecoder',
    pretrained='open-mmlab://resnet50_v1c',
    backbone=dict(
        type='ResNetV1c',
        depth=50,
        num_stages=4,
        out_indices=(0, 1, 2, 3),
        dilations=(1, 1, 2, 4),
        strides=(1, 2, 1, 1),
        norm_cfg=norm_cfg,
        norm_eval=False,
        style='pytorch',
        contract_dilation=True),
    decode_head=dict(
        type='DAHead',
        in_channels=2048,
        in_index=3,
        channels=512,
        pam_channels=64,
        dropout_ratio=0.1,
        num_classes=19,
        norm_cfg=norm_cfg,
        align_corners=False,
        loss_decode=dict(
            type='DiceLoss', use_sigmoid=False, loss_weight=1.0)), #type处可以指定loss类型
    auxiliary_head=dict(
        type='FCNHead',
        in_channels=1024,
        in_index=2,
        channels=256,
        num_convs=1,
        concat_input=False,
        dropout_ratio=0.1,
        num_classes=19,
        norm_cfg=norm_cfg,
        align_corners=False,
        loss_decode=dict(
            type='DiceLoss', use_sigmoid=False, loss_weight=0.4)), #type处可以指定loss类型
    # model training and testing settings
    train_cfg=dict(),
    test_cfg=dict(mode='whole'))

需要修改的地方在代码中已经中文注释
同理,如果你要是用其他的模型,同样需要修改两个地方就行上面提到的模型骨架和数据集即可

返回tools/train.py进行训练

弄完上面那些就可以基本开始训练了,官方的训练教程是

python tools/train.py ${配置文件} --work-dir ${YOUR_WORK_DIR}

${配置文件}:表示你配置文件的位置,也就是上一步的danet_r50-d8_512x512_20k_voc12aug.py所在位置
work-dir:是用来存储模型和日志的地方,你可以自己指定,不指定的话会自己创建
我觉得这样每次打太烦了,就在tools/train.py里面进行指定,随后直接运行train.py就行

在train.py中你需要修改的只有以下几个内容:
1、–config指定网络文件加载配置文件的位置
2、–work-dir是你结果存储路径
3、–gpu-id是你指定哪个GPU进行训练,–gpus与–gpu-id作者在API文档中已经介绍这两弃用了,至于为啥不删,估计是在其他地方还在加载。

# Copyright (c) OpenMMLab. All rights reserved.
def parse_args():
    parser = argparse.ArgumentParser(description='Train a segmentor')
    parser.add_argument('--config',
                        default='/home/hdc1996dl/MyProject/mmsegmentation-master/configs/'
                                'RepLKNet/RepLKNet-31B_1Kpretrain_upernet_80k_egc.py',
                        help='train config file path')
    parser.add_argument('--work-dir',
                        default='/data/hdc1996dl/segDatasates/save/'
                                'mmseg/upernet_RepLKNet',
                        help='the dir to save logs and models')
    #已弃用
    group_gpus.add_argument(
        '--gpus',
        type=int,
        help='(Deprecated, please use --gpu-id) number of gpus to use '
        '(only applicable to non-distributed training)')
    # 已弃用
    group_gpus.add_argument(
        '--gpu-ids',
        type=int,
        nargs='+',
        help='(Deprecated, please use --gpu-id) ids of gpus to use '
        '(only applicable to non-distributed training)')
    #指定GPU
    group_gpus.add_argument(
        '--gpu-id',
        type=int,
        default=0,
        help='id of gpu to use '
        '(only applicable to non-distributed training)')

运行起来大致是这样的
mmsegmentation教程1:自定义数据集、config文件修改、训练教程_第6张图片
如果报错

未发现mmseg包

最简单的方式直接把train.py赋值粘贴到根目录下,再run就行
mmsegmentation教程1:自定义数据集、config文件修改、训练教程_第7张图片

测试的还没看

看完这个,想深入了解mmseg怎么用的,可以移步这里
mmsegmentation教程2:如何修改loss函数、指定训练策略、修改评价指标、指定iterators进行val指标输出

参考:

> https://blog.csdn.net/weixin_44044411/article/details/118196847

你可能感兴趣的:(python,深度学习)