U-net

news2025/6/28 14:53:16

文章目录

  • 1、U-net 简介
  • 2、U-net网络详解
    • 2.1、U-net结构图
    • 2.2、U-net主要创新
    • 2.3、U-net网络优势
  • 3、目前常用方法U-net改动
  • 4、U-net网络程序代码

1、U-net 简介

U-net 发表于 2015 年,属于 FCN 的一种变体 。Unet 的初衷是为了解决生物医学图像方面的问题,由于效果确实很好后来也被广泛的应用在语义分割的各个方向,比如卫星图像分割,工业瑕疵检测等。

U-net采用 Encoder-Decoder 和 跳跃链接 的结构,结构简单但很有效。Encoder 负责特征提取,也可以将自己熟悉的各种特征提取网络放在这个位置,例如,vgg、resnet等常用网络。

U-Net是比较早的使用全卷积网络进行语义分割的算法之一,论文中使用包含压缩路径和扩展路径的对称U形结构在当时非常具有创新性,且一定程度上影响了后面若干个分割网络的设计,

该网络的名字也是取自其U形形状。

2、U-net网络详解

2.1、U-net结构图

如下图所示,U-net网络结构就像一个U形状,因此得名。

网络结构的左半部分是论文中的压缩路径(contracting path),主要负责提取图像中的特征。其中共有四个block组成,包含了两次卷积和最大池化操作,每次下采样之后的通道数翻倍,
特征图尺寸缩小一半。得到了512维度大小为32x32的特征,再次经过两次卷积然后送入decoder路径(无池化操作)。

网络结构的右半部分是论文中的扩展路径(expansive path),主要用以恢复特征尺寸并融合高分辨率的特征信息。其中同样包含了四个Block,每个block包含了一次上采样操作+拼接+两次卷积操作。
上采样常见的有转置卷积和插值法,论文中使用的是转置卷积操作。每次上采样之后,通道数减半,特征尺寸增大一倍,然后和对应的高分辨率特征图进行拼接以恢复维度,(由于卷积的过程中没有填充,导致尺寸不匹配,通过Crop裁剪以满足相同大小)。

最后得到64维度大小为388x388的特征图。

网络结构的最后一层是通过卷积操作进行降维并分类,根据数据集的类别个数选择输出对应的通道个数的特征图。论文中是二分类任务,所以输出通道为2。
在这里插入图片描述

2.2、U-net主要创新

采取将低级特征图与后面的高级特征图进行融合操作

完全对称的U型结构使得前后特征融合更为彻底,使得高分辨率信息与低分辨率信息在目标图片中增加

结合了下采样时的低分辨率信息(提供物体类别识别依据)和上采样时的高分辨率信息(提供精准分割定位依据),此外还通过融合操作(跳跃结构)填补底层信息以提高分割精度.(分辨率就是图片的尺寸)

2.3、U-net网络优势

网络层越深得到的特征图,有着更大的视野,浅层卷积关注纹理特征,深层网络关注本质特征,所以深层浅层特征都是有各自的意义;

另外一点是通过反卷积得到的更大的尺寸的特征图的边缘,是缺少信息的,毕竟每一次下采样提炼特征的同时,也必然会损失一些边缘特征,而失去的特征并不能从上采样中找回,因此通过特征的拼接(跳跃连接),来实现边缘特征的一个找回。

在医疗影像上效果好的原因分析:

医疗影像语义较为简单、结构固定。因此语义信息相比自动驾驶等较为单一,因此并不需要去筛选过滤无用的信息。医疗影像的所有特征都很重要,因此低级特征和高级语义特征都很重要,所以U型结构的skip connection结构(特征拼接)更好派上用场。
医学影像的数据较少,获取难度大,数据量可能只有几百甚至不到100,大型网络容易过拟合。

3、目前常用方法U-net改动

从U-net的结构图中可以看出,编码器和解码器的特征尺寸是不同的,所以需要经过裁剪才可以进行后续的拼接操作,增加了模型设计的难度和普适性。目前主流的方法是保持输入输出尺寸相同,并且采用插值法来进行上采样操作,卷积操作加上了BN。此外,对编码器使用常见的网络来提取图像特征,vgg16、resnet18等。

如下图所示:
在这里插入图片描述

4、U-net网络程序代码

from typing import Dict
import torch
import torch.nn as nn
import torch.nn.functional as F
 
## 两次3x3卷积操作
class DoubleConv(nn.Sequential):
    def __init__(self, in_channels, out_channels, mid_channels=None):
        if mid_channels is None:
            mid_channels = out_channels
        super(DoubleConv, self).__init__(
            nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1, bias=False),
            nn.BatchNorm2d(mid_channels),
            nn.ReLU(inplace=True),
            nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1, bias=False),
            nn.BatchNorm2d(out_channels),
            nn.ReLU(inplace=True)
        )
 
## 池化+两次卷积
class Down(nn.Sequential):
    def __init__(self, in_channels, out_channels):
        super(Down, self).__init__(
            nn.MaxPool2d(2, stride=2),
            DoubleConv(in_channels, out_channels)
        )
 
## 上采样+拼接+两次卷积
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
 
## 最后的分类层
class OutConv(nn.Sequential):
    def __init__(self, in_channels, num_classes):
        super(OutConv, self).__init__(
            nn.Conv2d(in_channels, num_classes, kernel_size=1)
        )
 
 
class UNet(nn.Module):
    def __init__(self,
                 in_channels: int = 1,
                 num_classes: int = 2,
                 bilinear: bool = True,
                 base_c: int = 64):
        super(UNet, self).__init__()
        self.in_channels = in_channels
        self.num_classes = num_classes
        self.bilinear = bilinear
 
        self.in_conv = DoubleConv(in_channels, base_c)
        self.down1 = Down(base_c, base_c * 2)
        self.down2 = Down(base_c * 2, base_c * 4)
        self.down3 = Down(base_c * 4, base_c * 8)
        factor = 2 if bilinear else 1
        self.down4 = Down(base_c * 8, base_c * 16 // factor)
        self.up1 = Up(base_c * 16, base_c * 8 // factor, bilinear)
        self.up2 = Up(base_c * 8, base_c * 4 // factor, bilinear)
        self.up3 = Up(base_c * 4, base_c * 2 // factor, bilinear)
        self.up4 = Up(base_c * 2, base_c, bilinear)
        self.out_conv = OutConv(base_c, num_classes)
 
    def forward(self, x: torch.Tensor) -> Dict[str, torch.Tensor]:
        x1 = self.in_conv(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.out_conv(x)
 
        return {"out": logits}

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

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

相关文章

锁分实锤!B站三体动画评分只有…好文!拆解追溯GPT-3.5各项能力起源;餐饮店后厨AI解决方案PreciTaste… | ShowMeAI资讯日报

👀日报合辑 | 🎡AI应用与工具大全 | 🔔公众号资料下载 | 🍩韩信子 📢 分析了三体动画近万条评分数据,扒下B站最后一块遮羞布… https://www.bilibili.com/video/BV1JM411m7HU/ 命运多舛的《三体》动画终于…

DBCO-PEG-FA二苯基环辛炔-聚乙二醇-叶酸;DBCO-PEG叶酸是一种无需任何催化剂即可进行化学反应的叶酸PEG衍生物

结构式: 英文名称:DBCO-PEG-Folic acid DBCO-PEG-FA 中文名称:二苯基环辛炔-聚乙二醇-叶酸 分子量:1k,2k,3.4k,5k 存储条件:-20C,避光干燥 用 途:仅…

让人恶心的多线程代码,性能怎么优化

Java 中最烦人的,就是多线程,一不小心,代码写的比单线程还慢,这就让人非常尴尬。 通常情况下,我们会使用 ThreadLocal 实现线程封闭,比如避免 SimpleDateFormat 在并发环境下所引起的一些不一致情况。其实…

转行学编程的人,都是怎么找到第一份程序员工作的?

对于我们打工人来说,薪资福利待遇好的公司可谓是人人争抢的香饽饽。 优秀的企业也越来越注重以薪酬福利吸引人才和留住人才。这一点,互联网大厂做的尤为出色。前有#OPPO给应届生开出40w+待遇#,今有#雷军给员工发放上亿股权激励#。…

VSCode连GitHub的代理服务器配置和获取历史版本命令

1. 在VSCode中配置代理: 在设置中查找“Proxy”直接编辑配置文件。或者在如下菜单中点击打开配置文件 在配置文件中添加如下两条。注意http和https的代理都要配置上 "http.proxy": "http://192.168.8.*:8080", "https.proxy": &qu…

算法leetcode|25. K 个一组翻转链表(rust重拳出击)

文章目录25. K 个一组翻转链表:样例 1:样例 2:提示:进阶:分析:题解:rustgoccpythonjava25. K 个一组翻转链表: 给你链表的头节点 head ,每 k 个节点一组进行翻转&#x…

是谣传还是真强?GitHub一战封神的“SQL优化手册”获赞过百万

这份“SQL优化本质手册”的口碑之所以能够火爆,完全是因为这部作品本身就是作者付诸于自己的多年开发经验之作的原因,所以只要走进书中,看过之后的人都知道,你很难不把自己代入其中与作者一起产生深深地共鸣。 收获,不…

DFS——剪枝优化迭代加深

文章目录概述优化搜索顺序排除等效冗余可行性剪枝最优性剪枝例题小猫爬山木棒迭代加深概述加成序列总结概述 优化搜索顺序 不同的搜索顺序会产生不同的搜索树形态,与可行性剪枝结合,去除非法状态,按照一定顺序可使规模大幅度减小。 例&#…

新能源电池进入高速发展阶段,数商云S2B2C商城赋能企业分销渠道管理更便捷

在国家政策扶持下,我国新能源汽车市场飞速发展,产品供给不断丰富、企业创新活力竞相迸发、使用环境日臻完善以及消费者认可度日益提高,近年来更是产销两旺,新能源汽车产销量屡创新高,作为新能源车的核心部件——电池&a…

面试官问我 ,try catch 应该在for循环里面还是外面?

前言 有个老哥昨天被面试官欺负了,但是是被这个问题(标题)欺负的? 其实是个比较基础的问题,只要有了解过,叙述是非常简单OK的。 只要有初学者觉得有疑惑,那么我相信不止是他一个。 所以&#…

青少年等级考试【Python通关干货】(一级)

青少年等级考试【Python通关干货】(一级) 1. 编程模式 1)交互式编程 在交互式环境的提示符>>>下,直接输入代码,按回车,就可以立刻得到代码执行结果。 交互式编程缺憾是没有保存下来,下…

2023 目标,与君共勉

新的一年,立一些目标,与君共勉 技术相关目标 csdn申请专业领域创作认证通过、博客专家认证通过掘金创作等级可以达到LV6等级掘金发表两个小册,有50人以上订阅csdn原先的进阶专栏,增加到100篇文章,有50人以上订阅csdn…

2021地理设计组一等奖:面向游客的旅游路线优化设计——以丹霞山景区为例

作品简介 一、背景与意义 随着旅游业的快速发展与人们对旅行质量要求的提升,旅游者对旅游服务的内容要求也越来越高,其中的旅游导航便是一项需求率极高的服务。然而传统的导航服务多是基于时间或距离成本进行网络分析而提供的路径设计,极少考…

R16 Dormant BWP

微信同步更新欢迎关注同名modem协议笔记 接上篇BWP结尾,R15时SCell的激活和去激活是通过Pcell的MAC CE,R16在Scell上引入dormant BWP的概念,可以通过DCI 控制Scell在dormant BWP和non-dormant BWP间进行切换,相比于MAC CE的控制方…

SpringBoot 基于 OAuth2 统一身份认证流程详解

1. 目标 了解OAUTH2统一认证基本概念了解OAUTH2协议流程了解OAUTH2各种模式类型了解Spring Security OAuth设计 2. 分析 传统登陆认证介绍 单点登陆认证介绍 OAuth2简介 OAuth2角色 OAuth2协议流程介绍 OAuth2授权类型 OAuth2授权码模式流程 OAuth2简化模式 OAuth2密码…

JavaScript 入门基础 / 概念介绍(一)

JavaScript 入门基础 / 概念介绍(一) 1.初识JavaScript 1.1 JavaScript历史 1995年,网景公司一名程序员布兰登艾奇利用十天完成了JavaScript设计,网景公司最初将它命名为LiveScript,后与Sun公司合作将其改名为JavaS…

外行人如何通过学习软件测试转行IT

随着互联网的快速发展,现在很多行业都被智能化取代,IT行业从业人员剧增,很多不是IT行业的人都想转行IT,那么对于不是IT行业的人,如何能快速转行变成IT人呢?软件测试是你最好的选择。对于一个不是本行业的人…

内科大深度学习期末复习笔记

文章目录一.选择判断1.1矩阵与 神经网络模型 与 深度学习模型 关系1.2 机器学习 与 深度学习 在训练数据中的区别1.3点乘与叉乘区别1.4 深度学习模型 浅层与深层 关系1.5线性关系与非线性 权重和偏置1.6 超参数(训练数据与可调整数据(var)&am…

10年经验hr亲授:刷完阿里P8架构师的RocketMQ核心手册,进大厂稳了

为什么要选择RocketMQ? 市场上几大消息队列对比如下: 总结一下: 选择中间件的可以从这些维度来考虑:可靠性,性能,功能,可运维行,可拓展性,社区活跃度。目前常用的几个中间件&…

基于容器的PaaS混合云的几种形式

概述 这是 Gartner 的一个图,提供了全球的基于容器的 PaaS 公有云、混合云服务的梳理展示: 这里提供一个其他的视角: 中国市场,基于容器的 PaaS 混合云(公有云 私有云)的相关厂商及产品。 ❗️ 注意&am…