【深度学习】U-Net 网络分割多分类医学图像解析

这把我C 2021-05-11 15:08:10 12811

【深度学习】U-Net 网络分割多分类医学图像解析

文章目录
【深度学习】U-Net 网络分割多分类医学图像解析
1 U-Net 多分类
2 Keras 利用Unet进行多类分割
    2.1 代码实现
    2.2 结果
3 多分类标签验证
4 数据变换
    4.1 概述
    4.2 图像数据变化代码(为了满足多分类需求)
    4.3 随机亮度(为了数据增强)
5 Unet训练自己的数据

在这里插入图片描述

1 U-Net 多分类

Unet图像分割在大多的开源项目中都是针对于二分类,理论来说,对于多分类问题,依旧可行。
在这里插入图片描述
U-net前半部分作用是特征提取,后半部分是上采样。在一些文献中也把这样的结构叫做编码器-解码器结构。由于此网络整体结构类似于大写的英文字母U,故得名U-net。
U-net与其他常见的分割网络有一点非常不同的地方:U-net采用了完全不同的特征融合方式:拼接,U-net采用将特征在channel维度拼接在一起,形成更厚的特征。而FCN融合时使用的对应点相加,并不形成更厚的特征。

所以语义分割网络在特征融合时有两种办法:

FCN式的对应点相加,对应于TensorFlow中的tf.add()函数;
U-net式的channel维度拼接融合,对应于TensorFlow的tf.concat()函数,比较占显存。
除了上述新颖的特征融合方式,U-net还有以下几个优点:
1、5个pooling layer实现了网络对图像特征的多尺度特征识别。
2、上采样部分会融合特征提取部分的输出,这样做实际上是将多尺度特征融合在了一起,以最后一个上采样为例,它的特征既来自第一个卷积block的输出(同尺度特征),也来自上采样的输出(大尺度特征),这样的连接是贯穿整个网络的,你可以看到上图的网络中有四次融合过程,相对应的FCN网络只在最后一层进行融合。

2 Keras 利用Unet进行多类分割

2.1 代码实现

所采用的数据集是CamVid,图片尺寸均为360*480,训练集367张,校准集101张,测试集233张,共计701张图片。所采用的深度学习框架是tensorflow+keras.数据来源在此:https://github.com/preddy5/segnet/tree/master/CamVid

我们从main2.py开始查看整个项目的实现步骤。

# -*- coding:utf-8 -*-
# Author : Ray
# Data : 2019/7/25 2:15 PM

from datapre2 import *
from model import *
import warnings

warnings.filterwarnings('ignore')   #忽略警告信息
# os.environ['CUDA_VISIBLE_DEVICES'] = '0'  #设置GPU
#测试集233张,训练集367张,校准集101张,总共233+367+101=701张,图像大小为360*480,语义类别为13类

aug_args = dict( #设置ImageDataGenerator参数
    rotation_range = 0.2,
    width_shift_range = 0.05,
    height_shift_range = 0.05,
    shear_range = 0.05,
    zoom_range = 0.05,
    horizontal_flip = True,
    vertical_flip = True,
    fill_mode = 'nearest'
)

train_gene = trainGenerator(batch_size=2,aug_dict=aug_args,train_path='CamVid/',
                        image_folder='train',label_folder='trainannot',
                        image_color_mode='rgb',label_color_mode='rgb',
                        image_save_prefix='image',label_save_prefix='label',
                        flag_multi_class=True,save_to_dir=None
                        )
val_gene = valGenerator(batch_size=2,aug_dict=aug_args,val_path='CamVid/',
                       image_folder='val',label_folder='valannot',
                       image_color_mode='rgb',label_color_mode='rgb',
                       image_save_prefix='image',label_save_prefix='label',
                       flag_multi_class=True,save_to_dir=None
                       )
tensorboard = TensorBoard(log_dir='./log')
model = unet(num_class=13)
model_checkpoint = ModelCheckpoint('camvid.hdf5',monitor='val_loss',verbose=1,save_best_only=True)

history = model.fit_generator(train_gene,
                              steps_per_epoch=100,
                              epochs=20,
                              verbose=1,
                              callbacks=[model_checkpoint,tensorboard],
                              validation_data=val_gene,
                              validation_steps=50   #validation/batchsize
                              )
# model.load_weights('camvid.hdf5')
test_gene = testGenerator(test_path='CamVid/test')
results = model.predict_generator(test_gene,233,verbose=1)
saveResult('CamVid/testpred/',results)

从上述代码中可以看到,整个项目的思路比较明确,概括而言就是:

数据准备
模型训练
预测结果

先利用trainGenerator、valGenerator准备训练数据,利用tensorboard = TensorBoard(log_dir='./log')保存日志信息,能够查看训练过程的loss、acc变化。调用ModelCheckpoint保存模型。模型训练时采用fit_generator模式输入。最后在调用predict_generatorj进行预测时先准备好测试集数据,然后调用saveResult保存预测结果。
注意到main.py中在model.fit_generator()中设置callbacks=[model_checkpoint,tensorboard],我们可以在训练结束之后查阅loss和acc的训练过程。
打开terminal,进入项目所在路径,输入tensorboard --logdir ./log(是你代码中所写的),然后出现以下界面就说明你的路径正确了
在浏览器键入http://http:localhost:6006即可查阅loss及acc的训练过程。

2.2 结果

在这里插入图片描述

3 多分类标签验证

0 255 128=>0 1 2
a = np.unique(A)
对于一维数组或者列表,unique函数去除其中重复的元素,并按元素由大到小返回一个新的无元素重复的元组或者列表

import numpy as np
A = [1, 2, 2, 5,3, 4, 3]
a = np.unique(A)
B= (1, 2, 2,5, 3, 4, 3)
b= np.unique(B)
C= ['fgfh','asd','fgfh','asdfds','wrh']
c= np.unique(C)
print(a)
print(b)
print(c)
#   输出为 [1 2 3 4 5]
# [1 2 3 4 5]
# ['asd' 'asdfds' 'fgfh' 'wrh']

c,s=np.unique(b,return_index=True)
return_index=True表示返回新列表元素在旧列表中的位置,并以列表形式储存在s中。
a, s= np.unique(A, return_index=True)
print(a)
print(s)
运行结果
[1 2 3 4 5]
[0 1 4 5 3]

a, s,p = np.unique(A, return_index=True, return_inverse=True)
return_inverse=True 表示返回旧列表元素在新列表中的位置,并以列表形式储存在p中

a, s,p = np.unique(A, return_index=True, return_inverse=True)
print(a)
print(s)
print(p)
运行结果
[1 2 3 4 5]
[0 1 4 5 3]

1. 对于一维列表或数组A: 

import numpy as np
A = [1, 2, 2, 3, 4, 3]
a = np.unique(A)
print a            # 输出为 [1 2 3 4]
a, b, c = np.unique(A, return_index=True, return_inverse=True)
print a, b, c      # 输出为 [1 2 3 4], [0 1 3 4], [0 1 1 2 3 2]
2. 对于二维数组(“darray数字类型”): 

A = [[1, 2], [3, 4], [5, 6], [1, 2]]
A = np.array(A)   #列表类型需转为数组类型
a, b, c = np.unique(A.view(A.dtype.descr * A.shape[1]), return_index=True, return_inverse=True)
print a, b, c     #输出为 [(1, 2) (3, 4) (5, 6)], [0 1 2], [0 1 2 0]
可以看出, Python中unique函数与Matlab完全一致. 

数据预处理最重要的一步就是要对gt进行one-hot编码,

4 数据变换

4.1 概述

图像方面的数据增强可以从下面几个角度来看.

仿射变换 (Random crop, Random flip, Random rotation, Random zoom, Random shear, Random translation…)
彩色失真 (Random gamma, Random brightness, Random hue, Random contrast, Gaussian Noise …)
信息丢弃(Gridmask, Cutout, Random Erasing, Hide-and-seek…)
多图融合(Mixup, Cutmix, Fmix…)
另类 (Augmix …)

4.2 图像数据变化代码(为了满足多分类需求)

下面代码主要目的是将一个不符合网络输出要求的图像进行处理,可以理解为一个标准化的流程。


class CenterCrop(object):
    def __init__(self, size):
        if isinstance(size, numbers.Number):
            self.size = (int(size), int(size))
        else:
            self.size = size

    def __call__(self, img, mask):
        assert img.size == mask.size
        w, h = img.size
        th, tw = self.size
        x1 = int(math.ceil((w - tw) / 2.))
        y1 = int(math.ceil((h - th) / 2.))
        return img.crop((x1, y1, x1 + tw, y1 + th)), mask.crop((x1, y1, x1 + tw, y1 + th))

class SingleCenterCrop(object):
    def __init__(self, size):
        if isinstance(size, numbers.Number):
            self.size = (int(size), int(size))
        else:
            self.size = size

    def __call__(self, img):
        w, h = img.size
        th, tw = self.size
        x1 = int(math.ceil((w - tw) / 2.))
        y1 = int(math.ceil((h - th) / 2.))
        return img.crop((x1, y1, x1 + tw, y1 + th))

class CenterCrop_npy(object):
    def __init__(self, size):
        self.size = size

    def __call__(self, img, mask):
        assert img.shape == mask.shape
        if (self.size <= img.shape[1]) and (self.size <= img.shape[0]):
            x = math.ceil((img.shape[1] - self.size) / 2.)
            y = math.ceil((img.shape[0] - self.size) / 2.)

            if len(mask.shape) == 3:
                return img[y:y + self.size, x:x + self.size, :], mask[y:y + self.size, x:x + self.size, :]
            else:
                return img[y:y + self.size, x:x + self.size, :], mask[y:y + self.size, x:x + self.size]
        else:
            raise Exception('Crop shape (%d, %d) exceeds image dimensions (%d, %d)!' % (
                self.size, self.size, img.shape[0], img.shape[1]))

4.3 随机亮度(为了数据增强)

随机亮度通过调整图像像素值改变图像亮度,这种方式对图像进行数据增强的代码如下:

defrandom_brightness():

results = np.copy(batch_xs)

fori inrange( 9):

image = sess.run(tf.image.random_brightness(batch_xs[i].reshape( 28, 28), 0.9))

results[i, :, :, :] = image.reshape( -1, 28, 28)

show_images(results, "random_brightness")

在这里插入图片描述

5 Unet训练自己的数据

整个模型训练过程如下图所示:
在这里插入图片描述
Unet网络调参
网络调参涉及以下几个方面:
(1)加入BN层
(2)将最后一层激活函数替换成ReLU
(3)损失函数替换成mse
多分类一般最后一层原本是softmax,使用了这个激活函数跑完后,没有达到分割效果,所以替换成了之前做过的图对图项目激活函数,效果就出来了,纯属经验之谈,理论还没有进行验证。多分类的损失函数多是交叉熵,经过验证也是不能达到效果,替换成均方根误差。

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 95 6 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
这把我C
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区