经典语义分割(二)医学图像分割模型UNet

news2024/12/23 22:25:46

经典语义分割(二)医学图像分割模型UNet

  • 我们之前介绍了全卷积神经网络( FCN) ,FCN是基于深度学习的语义分割算法的开山之作。

  • 今天我们介绍另一个语义分割的经典模型—UNet,它兼具轻量化与高性能,通常作为语义分割任务的基线测试模型,至今仍是如此。

  • UNet从本质上来说也属于一种全卷积神经网络模型,它的取名来源于其架构形状:模型整体呈现U形

    • 它原本是为了解决医疗影像语义分割问题的。在2015年的ISBI细胞跟踪挑战赛中,Ronnebreger等人利用UNet网络以较大优势赢得比赛。
      • 由于隐私问题、注释过程的复杂性、专家技能要求以及使用生物医学成像系统拍摄图像的高价格,在生物医学任务中,收集大量的数据很困难。
      • 而UNet能够在小样本数据集上训练并取得优秀成绩,因此各种基于其改进的网络模型广泛运用于医学图像分割任务中。特别是在肺结节、视网膜血管、皮肤病以及颅内肿瘤四大医学分割领域,出现了大量基于U-Net 改进的模型。
    • 下面几点或许能够解释为何UNet在医疗影像上表现突出:
      • UNet的U形网络结构密集融合了浅层特征与深层特征;
      • 医疗影像数据量与UNet模型体量上相匹配,有效避免了过拟合;
      • 医疗影像结构简单且固定,具有较低语义信息。
    • 不过,之后几年的发展,也证实了它是语义分割任务中的全能选手。
  • 论文地址:U-Net: Convolutional Networks for Biomedical Image Segmentation

1 UNet网络

1.1 UNet网络简述

UNet网络结构如下图所示,最主要的两个特点是:U型网络结构和Skip Connection跳层连接。

  • Unet通过跳接的U形网络结构结合了浅层特征与深层特征,用于最后的语义分割图生成。

    • 与FCN不同的是,UNet以拼接方式来结合浅层特征与深层特征;
    • 而FCN则是以相加方式来结合浅层特征与深层特征;
  • U形网络架构能够更充分地融合浅层特征和深层特征,这也是UNet性能优于FCN的主要原因。

    • 浅层特征图更倾向于表达例如点、线、边缘轮廓等基本特征单元;蕴含的空间信息更多。

    • 深层特征图更倾向于表达图像的语义信息;蕴含的空间信息更少,语义特征更多。

在这里插入图片描述

1.2 网络架构详解

UNet的主干分为对称的左右两部分:

  • 左边为特征提取网络(编码器,encoder),原始输入图像通过卷积-最大池化进行四次下采样,获得四层级的特征图;

  • 右边为特征融合网络(解码器,decoder),各层级特征图与经过反卷积获得的特征图通过跳接方式进行特征融合;

  • 最后一层通过与标签计算损失进行语义图预测。

1.2.1 DoubleConv模块

  • 从UNet网络中可以看出,不管是下采样过程还是上采样过程,每一层都会连续进行两次卷积操作,这种操作在UNet网络中重复很多次,可以单独写一个DoubleConv模块

    • 如下图所示,in_channels设为1,out_channels为64。
    • 输入图片大小为572×572,经过步长为1,padding为0的3×3卷积(注意原文没有进行填充),因此得到feature map为570×570,而非572×572,再经过一次卷积得到568×568的feature map。
    import torch.nn as nn
     
    class DoubleConv(nn.Module):
        """(convolution => [BN] => ReLU) * 2"""
     
        def __init__(self, in_channels, out_channels):
            super().__init__()
            self.double_conv = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=0),
                nn.BatchNorm2d(out_channels),
                nn.ReLU(inplace=True),
                nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=0),
                nn.BatchNorm2d(out_channels),
                nn.ReLU(inplace=True)
            )
     
        def forward(self, x):
            return self.double_conv(x)
    

在这里插入图片描述

1.2.2 Down模块

UNet网络一共有4次下采样过程,模块化代码如下:

  • Down模块先进行一个最大化池化,将高宽减半
  • 然后接一个DoubleConv模块,让通道加倍
  • 至此,UNet网络的左半部分的下采样过程的代码都写好了,接下来是右半部分的上采样过程
class Down(nn.Module):
    """Downscaling with maxpool then double conv"""
 
    def __init__(self, in_channels, out_channels):
        super().__init__()
        self.maxpool_conv = nn.Sequential(
            nn.MaxPool2d(2),
            DoubleConv(in_channels, out_channels)
        )
 
    def forward(self, x):
        return self.maxpool_conv(x)

在这里插入图片描述

1.2.3 Up模块

  • Up模块除了常规的上采样操作,还有进行特征的融合。
  • UP模块定义了两种方法:Upsample和ConvTranspose2d,即双线性插值反卷积
  • 在forward前向传播函数中,x1接收的是上采样的数据,x2接收的是特征融合的数据。特征融合方法就是先对小的feature map进行padding,再进行concat。
  • 注意:在下面代码中,上采样后会进行padding,和左边encoder相应的feature map的高宽一致,这点和图中不一样。
class Up(nn.Module):
    def __init__(self, in_channels, out_channels, bilinear=True):
        super(Up, self).__init__()
        if bilinear:
            self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
            self.conv = DoubleConv(in_channels, out_channels, in_channels // 2)
        else:
            self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2)
            self.conv = DoubleConv(in_channels, out_channels)

    def forward(self, x1: torch.Tensor, x2: torch.Tensor) -> torch.Tensor:
        x1 = self.up(x1)
        # [N, C, H, W]
        diff_y = x2.size()[2] - x1.size()[2]
        diff_x = x2.size()[3] - x1.size()[3]

        # padding_left, padding_right, padding_top, padding_bottom
        x1 = F.pad(x1, [diff_x // 2, diff_x - diff_x // 2,
                        diff_y // 2, diff_y - diff_y // 2])

        x = torch.cat([x2, x1], dim=1)
        x = self.conv(x)
        return x

1.2.4 OutConv模块

  • 用上述的DoubleConv模块、Down模块、Up模块就可以拼出UNet的主体网络结构了。

  • UNet网络的输出需要根据分割数量,整合输出通道。

  • 下图展示的是分类为2的情况

在这里插入图片描述

class OutConv(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(OutConv, self).__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)
 
    def forward(self, x):
        return self.conv(x)

1.2.5 UNet网络构建

import torch
import torch.nn as nn
import torch.nn.functional as F
# pip install torchinfo
from torchinfo import summary


class UNet(nn.Module):
    def __init__(self, n_channels, n_classes, bilinear=False):
        super(UNet, self).__init__()
        self.n_channels = n_channels
        self.n_classes = n_classes
        self.bilinear = bilinear

        self.inc = DoubleConv(n_channels, 64)
        self.down1 = Down(64, 128)
        self.down2 = Down(128, 256)
        self.down3 = Down(256, 512)
        self.down4 = Down(512, 1024)
        self.up1 = Up(1024, 512, bilinear)
        self.up2 = Up(512, 256, bilinear)
        self.up3 = Up(256, 128, bilinear)
        self.up4 = Up(128, 64, bilinear)
        self.outc = OutConv(64, n_classes)

    def forward(self, x):
        x1 = self.inc(x)
        x2 = self.down1(x1)
        x3 = self.down2(x2)
        x4 = self.down3(x3)
        x5 = self.down4(x4)
        x = self.up1(x5, x4)
        x = self.up2(x, x3)
        x = self.up3(x, x2)
        x = self.up4(x, x1)
        logits = self.outc(x)
        return logits


if __name__ == '__main__':
    net = UNet(n_channels=1, n_classes=1)
    summary(model=net, input_size=(1, 1, 572, 572))
===============================================================================================
Layer (type:depth-idx)                        Output Shape              Param #
===============================================================================================
UNet                                          [1, 1, 564, 564]          --
├─DoubleConv: 1-1                             [1, 64, 568, 568]         --
│    └─Sequential: 2-1                        [1, 64, 568, 568]         --
│    │    └─Conv2d: 3-1                       [1, 64, 570, 570]         640
│    │    └─BatchNorm2d: 3-2                  [1, 64, 570, 570]         128
│    │    └─ReLU: 3-3                         [1, 64, 570, 570]         --
│    │    └─Conv2d: 3-4                       [1, 64, 568, 568]         36,928
│    │    └─BatchNorm2d: 3-5                  [1, 64, 568, 568]         128
│    │    └─ReLU: 3-6                         [1, 64, 568, 568]         --
├─Down: 1-2                                   [1, 128, 280, 280]        --
│    └─Sequential: 2-2                        [1, 128, 280, 280]        --
│    │    └─MaxPool2d: 3-7                    [1, 64, 284, 284]         --
│    │    └─DoubleConv: 3-8                   [1, 128, 280, 280]        221,952
├─Down: 1-3                                   [1, 256, 136, 136]        --
│    └─Sequential: 2-3                        [1, 256, 136, 136]        --
│    │    └─MaxPool2d: 3-9                    [1, 128, 140, 140]        --
│    │    └─DoubleConv: 3-10                  [1, 256, 136, 136]        886,272
├─Down: 1-4                                   [1, 512, 64, 64]          --
│    └─Sequential: 2-4                        [1, 512, 64, 64]          --
│    │    └─MaxPool2d: 3-11                   [1, 256, 68, 68]          --
│    │    └─DoubleConv: 3-12                  [1, 512, 64, 64]          3,542,016
├─Down: 1-5                                   [1, 1024, 28, 28]         --
│    └─Sequential: 2-5                        [1, 1024, 28, 28]         --
│    │    └─MaxPool2d: 3-13                   [1, 512, 32, 32]          --
│    │    └─DoubleConv: 3-14                  [1, 1024, 28, 28]         14,161,920
├─Up: 1-6                                     [1, 512, 60, 60]          --
│    └─ConvTranspose2d: 2-6                   [1, 512, 56, 56]          2,097,664
│    └─DoubleConv: 2-7                        [1, 512, 60, 60]          --
│    │    └─Sequential: 3-15                  [1, 512, 60, 60]          7,080,960
├─Up: 1-7                                     [1, 256, 132, 132]        --
│    └─ConvTranspose2d: 2-8                   [1, 256, 120, 120]        524,544
│    └─DoubleConv: 2-9                        [1, 256, 132, 132]        --
│    │    └─Sequential: 3-16                  [1, 256, 132, 132]        1,771,008
├─Up: 1-8                                     [1, 128, 276, 276]        --
│    └─ConvTranspose2d: 2-10                  [1, 128, 264, 264]        131,200
│    └─DoubleConv: 2-11                       [1, 128, 276, 276]        --
│    │    └─Sequential: 3-17                  [1, 128, 276, 276]        443,136
├─Up: 1-9                                     [1, 64, 564, 564]         --
│    └─ConvTranspose2d: 2-12                  [1, 64, 552, 552]         32,832
│    └─DoubleConv: 2-13                       [1, 64, 564, 564]         --
│    │    └─Sequential: 3-18                  [1, 64, 564, 564]         110,976
├─OutConv: 1-10                               [1, 1, 564, 564]          --
│    └─Conv2d: 2-14                           [1, 1, 564, 564]          65
===============================================================================================
Total params: 31,042,369
Trainable params: 31,042,369
Non-trainable params: 0
Total mult-adds (G): 233.39
===============================================================================================
Input size (MB): 1.31
Forward/backward pass size (MB): 2683.30
Params size (MB): 124.17
Estimated Total Size (MB): 2808.78
===============================================================================================

2 针对UNet模型结构的改进

2.1 和transformers结合

在这里插入图片描述

2.2 概率设计

在这里插入图片描述

2.1.3 丰富表示增强

在这里插入图片描述

2.4 主干设计增强

在这里插入图片描述

2.5 跳过连接增强

在这里插入图片描述

2.6 bottleneck增强

在这里插入图片描述

以上改进总结来自这篇综述,感兴趣的可以参考:Medical Image Segmentation Review: The success of U-Net

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1498665.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

海格里斯HEGERLS助力服装业领域数智化转型 配备7000个托盘位 仓库容量增超110%

近年来,用工荒成为服装制造行业的一大痛点。对此,整个生产体系就要不断地向智能化、自动化生产设备进行转型,甚至在研发设计上都要面向自动化做一些新一代服装制造业的开发。 作为较早入局物流赛道的河北沃克,目前已构建起以AI赋能…

P2241 统计方形(数据加强版) python解法

求n*m网格内矩形的数目 - tenos - 博客园 (cnblogs.com) 法一(题解推规律暴力枚举得到): n,mmap(int,input().split()) sqr,rec0,0 #正方形和长方形个数 #以长宽做循环,每次求n*m大小的矩形的个数 #题解是从0开始的,我…

Java二级--操作题详解(1)

目录 1.第一套: 1.1 基本操作: 1.2 题解分析: 2.1 简单应用: 2.2 解题分析: 3.1 综合应用: 3.2解题分析: 1.第一套: 1.1 基本操作: 在考生文件夹中存有文件名为J…

浅析扩散模型与图像生成【应用篇】(八)——BBDM

8. BBDM: Image-to-Image Translation with Brownian Bridge Diffusion Models 本文提出一种基于布朗桥(Brownian Bridge)的扩散模型用于图像到图像的转换。图像到图像转换的目标是将源域 A A A中的图像 I A I_A IA​,映射到目标域 B B B中得…

【重要!!退税!退税!】一年一度个人所得税综合年度汇算开始了!

目录标题 如何退税?2023年度个人所得税综合所得汇算清缴操作指南汇算准备标准申报 退税骗局?1.“您有一笔退税待领取”骗局2.“专业人员帮你多退税”骗局3.“诱导填报虚假个税信息”骗局4.“税务稽查人员联系你”骗局 如何退税? 2023年度个人…

【elementplus】el-image图片预览的显示不全问题(和el-table、el-dialog组合使用时)

问题&#xff1a; 在和el-table、el-dialog组合使用时&#xff0c;el-image图片预览的时候&#xff0c;会可能出现显示不全图片的情况。 解决方法&#xff1a; <el-image-viewer:z-index"3000":teleported"true"/>element文档中有属性&#xff1a;…

【SpringBoot3.x教程03】SpringBoot自动配置详解

前言&#xff1a;什么是自动配置 自动配置的原理 Spring Boot自动配置尝试根据添加到项目中的jar依赖、定义的bean以及各种属性设置来自动配置Spring应用。这是通过EnableAutoConfiguration注解实现的&#xff0c;该注解通常是通过SpringBootApplication注解间接应用的。Spring…

如何实现数据中心布线变更管理?

前言 随着科技的不断发展&#xff0c;数据中心作为企业的核心基础设施之一&#xff0c;承载着大量重要的业务数据。在数据中心运维过程中&#xff0c;变更管理流程变得尤为重要&#xff0c;它是确保数据中心基础设施稳定运行和保障数据安全的关键环节。变更管理的定义是指在维…

阿珊解说Vue中`$route`和`$router`的区别

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

栈和队列OJ题:有效的括号,用栈实现队列,用队列实现栈,设计循环队列(C语言版,图文并茂,超级详细)

目录 前言 1. 有效的括号 &#xff08;1&#xff09;题目及示例 &#xff08;2&#xff09;思路及解法 2.用栈实现队列 &#xff08;1&#xff09;题目及示例 &#xff08;2&#xff09;解析及思路 &#xff08;3&#xff09;各部分代码 2.3.1 数据结构设计和创造队列…

官网:随便搞个?那不如不搞,搞不好就给公司减分了。

官网建设确实需要认真对待&#xff0c;不能随便搞。一个粗制滥造的官网可能会给公司带来负面影响&#xff0c;降低品牌形象和用户体验。以下是一些官网建设的重要原则&#xff1a; 专业性&#xff1a;官网应该展示公司的专业性和专业知识。它应该以专业的设计、内容和功能来展示…

1.4 Word2Vec是如何工作的? Word2Vec与LDA 的区别和联系?

1.4 Word2Vec&#xff1a;词嵌入模型之一 场景描述 谷歌2013年提出的Word2Vec是目前最常用的词嵌入模型之一。 Word2Vec实际是一种浅层的神经网络模型,它有两种网络结构&#xff0c;分别是CBOW(Continues Bag of Words)和Skip-gram。 知识点 Word2Vec,隐狄利克雷模型(LDA),…

nginx部署前端工程替代方案gateway

nginx部署前端工程替代方案gateway 有市场要求部署的前端vue工程不使用nginx中间件。想弄国产替代的东方通之类的&#xff0c;公司没有购买该产品&#xff0c;我参考了网上的一些java网关框架&#xff0c;springcloud组件&#xff1a;gateway实现代替。 注意后台都是用java编…

网络安全-appcms-master

一、环境 gethub上面自己找appcms-master 二、分析一下源码以及闯关思路 首先是有一个函数循环以及函数过滤&#xff0c;我们的post会将我们所传的所有val值去进行一个循环&#xff0c;之后通过htmlspecialchars这个函数进行过滤和转换所以val值不能通过单双引号闭合注入的方…

微信私域运营时如何有效降本增效?

在如今这个以流量为王的时代&#xff0c;成功地将流量转化为商业价值显得尤为重要。许多企业选择将流量转移到微信的私域流量中&#xff0c;以提高转化率和营销效果。 但是由于微信平台的限制&#xff0c;比如一台设备在正常情况下只能登录一个账号&#xff0c;无法实现聚合管理…

Pytorch从零开始实战20

Pytorch从零开始实战——指定生成手势图像 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——指定生成手势图像环境准备模型选择模型训练可视化分析生成指定图像总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c…

✅图片上传组件使用

简述 图片压缩、图片预览、图片多图上传、默认高清压缩 前情提示 暂仅支持:bmp, gif, jpg, jpeg, png格式,暂不支持svg、webp等格式【升级后支持】 一只哈基米~~ 截图 使用方式(主打一个代码可直接复制) 单张图:缩略图、头像、营业执照 <a-form-model-item label=…

如何将中科方德桌面操作系统加入Windows域

往期文章&#xff1a;自定义SSH客户端连接时的显示信息 | 统信UOS | 麒麟KYLINOS Hello&#xff0c;大家好啊&#xff0c;今天我非常高兴地给大家带来一篇关于如何将中科方德桌面操作系统加入Windows域的教程文章。对于使用中科方德桌面操作系统的用户来说&#xff0c;将其加入…

运算符重载(Operator Overloading)

定义 在C中&#xff0c;运算符重载&#xff08;Operator Overloading&#xff09;是一种允许程序员为自定义数据类型重新定义或重载已有的运算符的功能。通过运算符重载&#xff0c;我们可以使得自定义类型的对象能够像内置类型&#xff08;如int、float等&#xff09;一样使用…

基于iOS真机的Appium自动化测试

必要条件 XCode > 6.0, 7.1.1&#xff08;注意Appium并不一定支持最新版本的Xcode&#xff09;Mac OS X 10.10 or 更高, 建议使用10.11.1 Xcode 安装 APP Store安装 注意事项&#xff1a; Xcode 安装包很大&#xff08;5G左右&#xff09;&#xff0c;Xcode移动到应用程序…