图像分割实战-系列教程3:unet医学细胞分割实战1(医学数据集、图像分割、语义分割、unet网络、代码逐行解读)

图像分割实战-系列教程 总目录

有任何问题欢迎在下面留言
本篇文章的代码运行界面均在Pycharm中进行
本篇文章配套的代码资源已经上传

上篇内容:
Unet系列算法
下篇内容:
unet医学细胞分割实战2

1、医学细胞数据集介绍

1.1 数据集

图像分割实战-系列教程3:unet医学细胞分割实战1(医学数据集、图像分割、语义分割、unet网络、代码逐行解读)_第1张图片 图像分割实战-系列教程3:unet医学细胞分割实战1(医学数据集、图像分割、语义分割、unet网络、代码逐行解读)_第2张图片

如图所示,右图就是原始数据,而左边就是标签,一共670条训练数据

1.2 原始数据集预处理

上面的数据是经过处理的,实际上的原始数据是在Kaggle上下载的公开数据集

图像分割实战-系列教程3:unet医学细胞分割实战1(医学数据集、图像分割、语义分割、unet网络、代码逐行解读)_第3张图片

是包含的一个一个的文件夹,每个文件夹中分别是数据和标签

图像分割实战-系列教程3:unet医学细胞分割实战1(医学数据集、图像分割、语义分割、unet网络、代码逐行解读)_第4张图片 图像分割实战-系列教程3:unet医学细胞分割实战1(医学数据集、图像分割、语义分割、unet网络、代码逐行解读)_第5张图片

而标签中是细胞图像中,对每一个细胞都做成了标签,分成了很多张小图片,我们首先要做的是把这些小图片拼到一起

import os
from glob import glob
import cv2
import numpy as np
from tqdm import tqdm 
img_size = 96
paths = glob('inputs/stage1_train/*')
os.makedirs('inputs/dsb2018_%d/images' % img_size, exist_ok=True)
os.makedirs('inputs/dsb2018_%d/masks/0' % img_size, exist_ok=True)
for i in tqdm(range(len(paths))):
    path = paths[i]
    img = cv2.imread(os.path.join(path, 'images',
                     os.path.basename(path) + '.png'))
    mask = np.zeros((img.shape[0], img.shape[1]))
    for mask_path in glob(os.path.join(path, 'masks', '*')):
        mask_ = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE) > 127
        mask[mask_] = 1
    if len(img.shape) == 2:
        img = np.tile(img[..., None], (1, 1, 3))
    if img.shape[2] == 4:
        img = img[..., :3]
    img = cv2.resize(img, (img_size, img_size))
    mask = cv2.resize(mask, (img_size, img_size))
    cv2.imwrite(os.path.join('inputs/dsb2018_%d/images' % img_size,
                os.path.basename(path) + '.png'), img)
    cv2.imwrite(os.path.join('inputs/dsb2018_%d/masks/0' % img_size,
                os.path.basename(path) + '.png'), (mask * 255).astype('uint8'))

这部分代码只需要把那些小图片按照顺序汇总,使用OpenCV拼在一起就可以了,然后所有的数据都是这样的处理方式,最后会得到1.1形式的数据集,这里就不演示以及解释代码了,如果对OpenCV不熟悉的可以参数这篇教程

2、训练参数解读

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--name', default=None, help='model name: (default: arch+timestamp)')
    parser.add_argument('--epochs', default=100, type=int, metavar='N', help='number of total epochs to run')
    parser.add_argument('-b', '--batch_size', default=8, type=int, metavar='N', help='mini-batch size (default: 16)')
    parser.add_argument('--arch', '-a', metavar='ARCH', default='NestedUNet', choices=ARCH_NAMES, help='model architecture: ' +
                        ' | '.join(ARCH_NAMES) + ' (default: NestedUNet)')
    parser.add_argument('--deep_supervision', default=False, type=str2bool)
    parser.add_argument('--input_channels', default=3, type=int, help='input channels')
    parser.add_argument('--num_classes', default=1, type=int, help='number of classes')
    parser.add_argument('--input_w', default=96, type=int, help='image width')
    parser.add_argument('--input_h', default=96, type=int, help='image height')
    parser.add_argument('--loss', default='BCEDiceLoss', choices=LOSS_NAMES, help='loss: ' +
                        ' | '.join(LOSS_NAMES) + ' (default: BCEDiceLoss)')
    
    # dataset
    parser.add_argument('--dataset', default='dsb2018_96', help='dataset name')
    parser.add_argument('--img_ext', default='.png', help='image file extension')
    parser.add_argument('--mask_ext', default='.png', help='mask file extension')

    # optimizer
    parser.add_argument('--optimizer', default='SGD', choices=['Adam', 'SGD'], help='loss: ' +
                        ' | '.join(['Adam', 'SGD']) + ' (default: Adam)')
    parser.add_argument('--lr', '--learning_rate', default=1e-3, type=float, metavar='LR', help='initial learning rate')
    parser.add_argument('--momentum', default=0.9, type=float, help='momentum')
    parser.add_argument('--weight_decay', default=1e-4, type=float, help='weight decay')
    parser.add_argument('--nesterov', default=False, type=str2bool, help='nesterov')

    # scheduler
    parser.add_argument('--scheduler', default='CosineAnnealingLR',
                        choices=['CosineAnnealingLR', 'ReduceLROnPlateau', 'MultiStepLR', 'ConstantLR'])
    parser.add_argument('--min_lr', default=1e-5, type=float,
                        help='minimum learning rate')
    parser.add_argument('--factor', default=0.1, type=float)
    parser.add_argument('--patience', default=2, type=int)
    parser.add_argument('--milestones', default='1,2', type=str)
    parser.add_argument('--gamma', default=2/3, type=float)
    parser.add_argument('--early_stopping', default=-1, type=int,
                        metavar='N', help='early stopping (default: -1)')
    
    parser.add_argument('--num_workers', default=0, type=int)

    config = parser.parse_args()

    return config
  1. 参数函数
  2. 参数实例化对象
  3. 指定网络的名字(Unet++)
  4. 训练epochs,数据很小,h和w很小、量也小,100轮够了,20分钟就能跑完
  5. batch_size根据自己显卡资源指定
  6. 网络架构,在后面部分会解释
  7. 是否需要在每个位置都加上监督
  8. 输入通道数
  9. 类别个数,当前任务比较简单,只有是细胞和不是细胞
  10. 输入图像H
  11. 输入图像W
  12. 指定损失函数为交叉熵
  13. 数据集名字
  14. 图像文件的扩展名
  15. 掩码文件的扩展名
  16. 优化器SGD
  17. 学习率
  18. 动量加速
  19. 学习率衰减
  20. 使用了一个自定义的类型转换函数 str2bool 来处理输入值
  21. scheduler,指定使用默认值为 'CosineAnnealingLR’为学习率调度器
  22. 最小学习率
  23. factor,指定在特定条件下调整学习率时的乘法因子,默认值为0.1
  24. patience,对于一些调度器(如 ReduceLROnPlateau),这个参数定义了在性能不再提升时要等待多少周期之后才减少学习率。默认值为 2。类型为 int。
  25. milestones,对于 MultiStepLR 调度器,这个参数定义了何时降低学习率的周期数。默认值是 ‘1,2’(表示一个字符串,您可能需要在代码中将其分割为多个数值)。类型为 str。
  26. gamma值
  27. 设置提前停止
  28. 用于指定在数据加载时用于数据预处理的进程数。

上篇内容:
Unet系列算法
下篇内容:
unet医学细胞分割实战2

你可能感兴趣的:(图像分割实战,计算机视觉,图像分割,unet)