U-Net

U − N e t U-Net UNet


1.视频教程:
B站、网易云课堂、腾讯课堂
2.代码地址:
Gitee
Github
3.存储地址:
Google云
百度云:
提取码:

一 原理解析

《U-Net:Convolutional Networks for Biomedical Image Segmentation》
—医学图像分割卷积网络
作者:Olaf Ronneberger,etc,
单位:香港大学与德国弗莱堡大学
发表会议及时间:MICCA 2015
Submission history
[v1] Mon, 18 May 2015 11:28:37 UTC (1,385 KB)

https://arxiv.org/abs/1505.04597


  • Abstract

There is large consent that successful training of deep networks requires many thousand annotated training samples. In this paper, we present a network and training strategy that relies on the strong use of data augmentation to use the available annotated samples more efficiently. The architecture consists of a contracting path to capture context and a symmetric expanding path that enables precise localization. We show that such a network can be trained end-to-end from very few images and outperforms the prior best method (a sliding-window convolutional network) on the ISBI challenge for segmentation of neuronal structures in electron microscopic stacks. Using the same network trained on transmitted light microscopy images (phase contrast and DIC) we won the ISBI cell tracking challenge 2015 in these categories by a large margin. Moreover, the network is fast. Segmentation of a 512x512 image takes less than a second on a recent GPU. The full implementation (based on Caffe) and the trained networks are available at this http URL .



  • 摘要

➢主要贡献:本文提出了一个网络和训练策略,使用数据增强,以便更有效的使用可用的带标签样本
➢网络结构:网络由两部分组成,定义一个收缩路径来获取全局信息,同时定义一个对称的扩张路径用以精确定位
➢网络效果:该网络可以用很少的图片进行端到端训练,处理速度也比较快
➢实验结果:以很大的优势赢得了2015 ISBI细胞跟踪挑战赛


  • 医学图像分割是医学图像处理与分析领域的复杂而关键的步骤,目的是将医学图像中具有某些特殊含义的部分分割出来,并提取相关特征,为临床诊疗和病理学研究提供可靠的依据,辅助医生作出更为准确的诊断。当前,医学图像分割仍在从手动分割或半自动分割向全自动分割发展。

在这里插入图片描述


应用

  • 处理对象∶各种不同成像机理的医学影像,主要有X-射线成像(X-CT)、核磁共振成像(MRI)、核医学成像(NMI)和超声波成像(UI)、电子显微镜成像(EM)
  • 应用方向:医疗教学、手术规划、手术仿真及各种医学研究
  • 应用场景:病变检测、图像分割、图像配准及图像融合
  • 应用思路∶首先对二维切片图像进行分析和处理,实现对人体器官、软组织和病变体的分割提取,然后进行三维重建和三维显示,可以辅助医生对病变体及其它感兴趣区域进行定性甚至定量的分析,从而大大提高医疗诊断的准确性和可靠性

难点

1.数据量少。一些挑战赛只提供不到100例的数据
2.图片尺寸大。单张图片尺寸大、分辨率高,对模型的处理速度有一定的要求
3.要求高。医学图像边界模糊、梯度复杂,对算法的分割准确度要求极高
4.多模态。以ISLES脑梗竞赛为例,其官方提供了CBF,MTT,CBV,TMAX,CTP等多种模态的数据



U-net的成果及意义

  • 赢得了ISBl cell tracking challenge 2015
  • 速度快,对一个512*512的图像,使用一块GPU只需要不到一秒的时间
  • 成为大多做医疗影像语义分割任务的baseline,也启发了大量研究者去思考U型语义分割网络
  • UNet结合了低分辨率信息(提供物体类别识别依据)和高分辨率信息(提供精准分割定位依据),较适用于医学图像分割。

网络结构

在这里插入图片描述

在这里插入图片描述

二 代码实现

2.1 模型构建


import torch
import torch.nn as nn

class UNet(nn.Module):

    def __init__(self, in_channels=3, num_classes=1, init_features=32):
        super(UNet, self).__init__()
        # 初始卷积层层数
        features = init_features
        '''
        编码层
        '''
        # 编码层1
        self.encoder1 = UNet._block(in_channels, features, name="enc1")
        # 池化层1
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
        # 编码层2
        self.encoder2 = UNet._block(features, features * 2, name="enc2")
        # 池化层2
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        # 编码层3
        self.encoder3 = UNet._block(features * 2, features * 4, name="enc3")
        # 池化层3
        self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)
        # 编码层4
        self.encoder4 = UNet._block(features * 4, features * 8, name="enc4")
        # 池化层4
        self.pool4 = nn.MaxPool2d(kernel_size=2, stride=2)

        '''
        瓶颈层
        '''
        self.bottleneck = UNet._block(features * 8, features * 16, name="bottleneck")

        '''
        解码层
        '''
        # 转置卷积层4
        self.upconv4 = nn.ConvTranspose2d(features * 16, features * 8, kernel_size=2, stride=2)
        # 解码器层4
        self.decoder4 = UNet._block((features * 8) * 2, features * 8, name="dec4")
        # 转置卷积层3
        self.upconv3 = nn.ConvTranspose2d(features * 8, features * 4, kernel_size=2, stride=2)
        # 解码器层3
        self.decoder3 = UNet._block((features * 4) * 2, features * 4, name="dec3")
        # 转置卷积层2
        self.upconv2 = nn.ConvTranspose2d(features * 4, features * 2, kernel_size=2, stride=2)
        # 解码器层2
        self.decoder2 = UNet._block((features * 2) * 2, features * 2, name="dec2")
        # 转置卷积层1
        self.upconv1 = nn.ConvTranspose2d(features * 2, features, kernel_size=2, stride=2)
        # 解码层
        self.decoder1 = UNet._block(features * 2, features, name="dec1")

        '''
        卷积输出层
        '''
        self.conv = nn.Conv2d(
            in_channels=features, out_channels=num_classes, kernel_size=1
        )

    def forward(self, x):
        '''
         编码
        '''
        enc1 = self.encoder1(x);print('enc1:', enc1.size())
        enc2 = self.encoder2(self.pool1(enc1));print('enc2:', enc2.size())
        enc3 = self.encoder3(self.pool2(enc2));print('enc3:', enc3.size())
        enc4 = self.encoder4(self.pool3(enc3));print('enc4:', enc4.size())

        '''
        瓶颈输出
        '''
        bottleneck = self.bottleneck(self.pool4(enc4));print('bottleneck:', bottleneck.size())

        '''
        解码
        '''
        dec4 = self.upconv4(bottleneck);print('dec4:', dec4.size())
        dec4 = torch.cat((dec4, enc4), dim=1);print('dec4:', dec4.size())  # 那根线
        dec4 = self.decoder4(dec4);print('dec4:', dec4.size())

        dec3 = self.upconv3(dec4);print('dec3:', dec3.size())
        dec3 = torch.cat((dec3, enc3), dim=1);print('dec3:', dec3.size())
        dec3 = self.decoder3(dec3);print('dec3:', dec3.size())

        dec2 = self.upconv2(dec3);print('dec2:', dec2.size())
        dec2 = torch.cat((dec2, enc2), dim=1);print('dec2:', dec2.size())
        dec2 = self.decoder2(dec2);print('dec2:', dec2.size())

        dec1 = self.upconv1(dec2);print('dec1:', dec1.size())
        dec1 = torch.cat((dec1, enc1), dim=1);print('dec1:', dec1.size())
        dec1 = self.decoder1(dec1);print('dec1:', dec1.size())

        '''
        激活输出
        '''
        output = torch.sigmoid(self.conv(dec1))

        return output

    @staticmethod
    def _block(in_channels, features, name):
        block = nn.Sequential(
            # 卷积层1
            nn.Conv2d(
                      in_channels=in_channels,
                      out_channels= features,
                      kernel_size=3,
                      padding=1,
                      bias=False,
                      ),
            # 正则化层1
            nn.BatchNorm2d(num_features=features),
            # relu激活层1
            nn.ReLU(inplace=True),

            # 卷积层2
            nn.Conv2d(
                in_channels = features,
                out_channels = features,
                kernel_size=3,
                padding=1,
                bias=False
            ),
            # 正则化层2
            nn.BatchNorm2d(num_features=features),
            # relu激活层2
            nn.ReLU(inplace=True)
        )

        return block




if __name__ == '__main__':
    # 随机生成输入数据
    rgb = torch.randn(1, 3, 512, 512)
    # 定义网络
    net = UNet(in_channels=3,num_classes=8)
    # 前向传播
    out = net(rgb)
    # 打印输出大小
    print('-----'*5)
    print(out.shape)
    print('-----'*5)

2.2 模型训练

2.3 模型预测

2.4 模型验证

三 问题思索

四 改进方案

五 额外补充

补充:ISBI挑战赛

ISBI: IEEE International Symposium on Biomedical lmaging(IEEE国际生物医学影像研讨会)
致力于涵盖所有观察规模的生物和生物医学影像的数学,算法和计算方面。ISBI是IEEE信号处理协会(SPS)和IEEE医学与生物学工程学会(EMBS)的一项联合计划。要求高质量的论文,包括图像形成和重建,图像处理和分析,动态成像,可视化,图像质量评估,大图像数据的机器学习以及物理,生物学和统计建模。
生物影像学已经在从诊断到个性化治疗再到对生物过程的机械理解的广泛应用中不断发展。对更健壮的方法以及与临床和分子数据集成的需求不断增长,该领域继续受到挑战

向下:图像尺寸降低,学习特征图向上:图像尺寸上升(还原),输出图像分割
所有的图像分类、图像分割、目标检测等任务都包含向下的路径
然而向上的路径是图像分割任务特有的


UNet是编码器-解码器架构,四次下采样(maxpooling),四次上采样(转置卷积),形成了U型结构


应对小样本的数据集进行较快、有效地分割,能够泛化到很多应用场景中去


UNet结合了低分辨率信息(提供物体类别识别依据)和高分辨率信息(提供精准分割定位依据),较适用于医学图像分割。


连接组学

连接组学绘制与研究神经连接组:一种刻画有机体神经系统(尤其是脑和眼)的连接方式的完整线路图。连接组学旨在全面地映射神经系统中发现的神经元网络的结构,以便更好地理解大脑如何工作。该过程需要以纳米级分辨率(通常使用电子显微镜)对3D脑组织进行成像,然后分析所得到的图像数据追踪大脑的神经节并识别各个突触连接。
由于成像的高分辨率,即使是1mm^3的脑组织也可以产生超过1,000TB
的数据.再加上这些图像中的结构可能非常微妙和复杂,构建大脑映射的主要瓶颈并不是获取数据本身,而是自动解释这些数据。

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值