VGAN实现视网膜图像血管分割(基于pytorch)

news2024/9/28 5:23:39

背景介绍

VGAN(Retinal Vessel Segmentation in Fundoscopic Images with Generative Adversarial Networks)出自2018年的一篇论文,尝试使用生成性对抗网络实现视网膜血管分割的任务,原论文地址:https://arxiv.org/abs/1706.09318
在github上有相应的源码仓库,不过由于版本的原因也会出现一些bug,本篇博客在复现项目的过程中也对源码进行了相应的修改,源码地址: https://github.com/guyuchao/Vessel-wgan-pytorch?tab=readme-ov-file

另一方面,刚好这个项目作为我2023年的最后一个项目,就斗胆当作是2023年编程之旅的回顾,博主是在茫茫知识海洋漂泊的一叶小舟,还有许多的知识尚未学习,希望可以和大家互相交流学习!

2024年,冲鸭!!!!!


前言

生成对抗网络(Generative Adversarial Networks)在提出的时候是为了实现模型创造性的能力,如今在AI图像生成领域已经有非常广阔的应用,例如知名的Midjourney网站,就是通过用户输入的prompt提示,利用GAN的框架生成对应用户想要生成的图片;我自己对于这个模型的名声也是早有耳闻,刚好前一段时间看到了《Retinal Vessel Segmentation in Fundoscopic Images with Generative Adversarial Networks》这篇文章,内容里探究了把GAN模型应用到视网膜血管分割的领域,刚好可以与我本学期的生物医学创新实践联系在一起。

生成对抗网络介绍

生成对抗网络(Generative Adversarial Network)简称GAN,是深度学习领域的一种重要模型,由Ian Goodfellow在2014年提出。

GAN模型包括两部分:一个是生成器(Generator),另一个是判别器(Discriminator)。这两部分模型相互博弈,共同训练,赋予网络生成特定分布的数据的能力。

1. 生成器(Generator):该部分的目标是生成尽可能真实的数据。例如,如果我们想让网络生成一张风景图片,生成器的目标就是生成一张看上去就像是某个摄影师拍摄的风景照片。

2. 判别器(Discriminator):该部分的目标是尽可能好地区分出真实的和生成的数据。在风景图片的例子中,判别器需要区分出哪些图片是真实的风景照片,哪些是生成器生成的假照片。

两者相互博弈的过程中,判别器会不断提高对真假数据的判断能力,生成器也会不断提高生成数据的逼真度,理想状态下,生成器生成的数据将和真实数据无法区分,判别器对生成器的生成结果的判断是50%,即做出了随机猜测。这样,就完成了GAN的训练过程。

视网膜分割的GAN模型(VGAN)

从上图中可以看出,模型中的GAN的generator是一个U-net形状的网络模型,每一层上采样层都与对称的下采样的输出进行连接,能够很好的处理图像的边缘及其他的细节特征;discriminator是一个多层的下采样的网络模型,最后是输出是实现一个二分类的效果,即{(0,1)}^N,接近0表示判断机器生成的(generator),接近1表示判断为真实的血管分割标签,每层的generator和discriminator都是由基本的block卷积神经网络组成,block的代码构建为:

class block(nn.Module):
    def __init__(self,in_filters,n_filters):
        super(block,self).__init__()
        self.deconv1 = nn.Sequential(
            nn.Conv2d(in_filters, n_filters, 3, stride=1, padding=1),
            nn.BatchNorm2d(n_filters),
            nn.ReLU())
    def forward(self, x):
        x=self.deconv1(x)
        return x

 是用nn.Sequential()连接的包含卷积,标准化和池化的经典卷积层,卷积核为3\times3,步长为1,边缘补充为1,处理的视网膜图片是三通道彩色图盘,第一层的intput_channel为3;下面用pytorch的tensorboard工具对搭建的generator和discriminator进行网络结构的可视化

这里需要注意的是,在原论文中,Discriminator的输入并不是Generator直接生成的图片或者原数据集中的label,而是需要在C通道上与进行分割的原视网膜图片进行合并再进行输入。

损失函数

在训练Generator和训练Discriminator时,使用不同的损失函数,我们最后是使用Generator进行mask的生成,也就是使用Generator输入需要进行视网膜血管分割的图片,输出分割的结果,所以我们更加注重Generator损失函数的设计。

GAN整体的损失函数可以定义为

对于D(Discriminator),在代码中不设计具体的损失函数,从任务设计中可以得出,当输入到D的是真实的标签图像时,我们期望D输出越接近1越好;当输入到D的是Generator生成的图像时,我们期望D输出越接近0越好,基于这种关系,我们直接把D的输出作为损失函数,同时,为了避免GAN模型中常见的断层问题,引入了经典的WGAN方法(Gradient Penalty),即获得一个1-Lipschitz函数,保证GAN模型的训练曲线是足够平滑从而生成稳定的图片,在梯度计算中引入作为梯度惩罚,则D的损失函数可以表示为:

对于G,为适应分割的任务不需要使用隐含空间的向量而是直接获取img的输入,具体地,在代码中使用二分类交叉熵损失函数获取与对应标签的loss值,同时加上来自D的反馈,具体的损失函数为:

数据集预处理

本次项目使用的数据集是经典的视网膜血管分割数据集,含有20张训练集和20张测试集,每张视网膜眼底的图片是584\times565\times3像素的三通道彩色tif格式图片,对应的标签是584\times565像素单通道灰度tif图片

对img的预处理包括随机改变图片的亮度、对比度和色相,图片像素标准化、转换成tensor数据的经典图片训练格式[B,C,H,W];

对label的预处理包括图片像素标准化、转换成tensor数据的经典图片训练格式[B,C,H,W];

同时对img和label的预处理包括随机裁剪图片高和宽为512\times512像素大小,随机水平翻转和垂直翻转;

下面是对训练数据中的进行预处理后的结果可视化

训练过程

一开始打算把本项目放到colab上跑或者服务器上跑,在此之前抱着试一试的态度先用本地的显卡1080ti加4G显存跑了50个epoch,结果竟然能跑得动!于是就先跑了300个epoch,显卡没崩,结果保存在./pth中。

对于GAN的结果,除了使用传统的评估方法外,也会对训练过程的结果进行输出可视化看看结果有没有生成奇奇怪怪的图像从而停止训练重新调整,不过对于本次项目,Generator的输入不包含隐含空间z,而且加入了WGAN进行约束,所以生成的图像基本上是比较完整的;作为视觉上直观地对GAN的效果进行评估,我们每跑50个epoch对应输出测试集生成的分割图像,保存在对应的文件夹名称里面,跑完全部epoch后,对应把D和G训练好的checkpoint也保存在./pth路径下。

300个epoch跑了一个多小时,显卡的散热吹风机感觉可以起飞了,不过结果其实可圈可点,为了不浪费训练好的资料,后面又写了一个re_train脚本,读取前一次训练好的模型权重再进行训练,又花了一个小时跑了300个epoch,结果保存在./pth2目录下,结构与./pth中文件相同,所以综合起来一共训练了600个epoch。

结果分析

 先对比每50个epoch生成的图像,选取测试集中的第一张图片

对于测试集的预处理也包括随机裁剪像素512\times512像素大小与随机水平翻转与垂直翻转,所以生成的图像包含有不同的方向和裁剪风格。

从第50个epoch到第600个epoch结果,可以明显的看出图片质量提升的效果,说明Generator的学习是非常有效果的,没有出现GAN中经常出现的图片断层效果。

对比一下对应的眼底原图和血管分割标签图:

从视觉上来看,GAN生成图像与原图像的分割标签是比较接近的。

接下来我们使用训练好的Generator模型进行量化的对比:

绘制对应的PR曲线与ROC曲线:

从两个曲线的效果可以看出,训练出来的模型在测试集上也具有比较好的效果,本次项目使用的VGAN在处理视网膜血管分割的任务上体现出比较好的性能。

参考文献

  1. Son, J., Park, S.J., & Jung, K. (2017). Retinal Vessel Segmentation in Fundoscopic Images with Generative Adversarial Networks. ArXiv, abs/1706.09318.
  2. Arjovsky, M., Chintala, S., & Bottou, L. (2017). Wasserstein GAN. ArXiv, abs/1701.07875.

彩蛋

我们都知道GAN以创作能力而闻名,那我们试一下用上面训练好的模型接受随机初始化满足正态分布的z隐含空间的数据会输出怎么样的图像

嗯...看来想要GAN生成像样的图片,还是需要再训练机制里面下手

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

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

相关文章

automa插件使用的一些实战经验2

automa的工程还是要经常导出备份,因为经常出现突然模块消失的情况。 1 滑动分页条件区分 传统的页面都是有分页标签,这样你很容易知道,应该用分页来做。但是现在手机端的应用基本都是上滑就可以分页,再混合式开发的环境下&#xf…

【模块系列】STM32BMP280

前言 最进想练习下I2C的应用,手上好有BMP280也没用过,就看着机翻手册和原版手册,开始嘎嘎写库函数了。库的命名应该还1是比较规范了吧,就是手册对于最终值的计算方式很迷糊,所以现在也不能保证有可靠性啊,大…

SSM框架整合:掌握Spring+Spring MVC+MyBatis的完美结合!

SSM整合 1.1 流程分析1.2 整合配置步骤1:创建Maven的web项目步骤2:添加依赖步骤3:创建项目包结构步骤4:创建SpringConfig配置类步骤5:创建JdbcConfig配置类步骤6:创建MybatisConfig配置类步骤7:创建jdbc.properties步骤8:创建SpringMVC配置类步骤9:创建Web项目入口配…

力扣日记1.13-【二叉树篇】669. 修剪二叉搜索树

力扣日记:【二叉树篇】669. 修剪二叉搜索树 日期:2023.1.13 参考:代码随想录、力扣 669. 修剪二叉搜索树 题目描述 难度:中等 给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树…

1992年-2020年ESA_CCI土地覆盖数据介绍、下载与数据分享

数据介绍 ESA CCI Land Cover是欧洲空间局(European Space Agency,ESA)的一个项目,其目标是生成全球土地覆盖的高质量、一致性和长期的时间序列数据,分辨率大约为300米。 该项目是ESA气候变化计划(Climate…

Linux中安装字体

问题说明 wps 安装后打开文件部分字体出现乱码,原因主要是linux中缺少windows中的相关字体,只要从windows电脑中的字体拷贝到linux系统中并安装就能解决问题 对ubuntu 和manjora有效。 安装字体 字体下载地址可参考附录 在 Linux 中,一次…

强化学习应用(五):基于Q-learning的无人机物流路径规划研究(提供Python代码)

一、Q-learning简介 Q-learning是一种强化学习算法,用于解决基于马尔可夫决策过程(MDP)的问题。它通过学习一个价值函数来指导智能体在环境中做出决策,以最大化累积奖励。 Q-learning算法的核心思想是通过不断更新一个称为Q值的…

机器人模仿学习之动作分块ACT算法的代码剖析、部署训练

前言 本文最早是属于《斯坦福Mobile ALOHA背后的关键技术:动作分块ACT算法的原理解析》的第二、第三部分,涉及到动作分块ACT的代码剖析与部署训练 但因为想把ACT的代码逐行剖析的更细致些,加之为避免上一篇文章太过于长,故把动作…

使用Nginx作为反向代理服务器在Linux中的最佳实践

在Linux环境下,Nginx因其高效性能、稳定性以及丰富的功能集而广泛用于作为反向代理服务器。以下是在Linux中使用Nginx作为反向代理服务器的最佳实践: 1. 安装与配置 首先,确保你的Linux发行版已经安装了Nginx。大多数Linux发行版都提供了Ng…

【上分日记】第369场周赛(分类讨论 + 数学 + 前缀和)

文章目录 前言正文1.3000. 对角线最长的矩形的面积2.3001. 捕获黑皇后需要的最少移动次数3.3002. 移除后集合的最多元素数3.3003. 执行操作后的最大分割数量 总结尾序 前言 终于考完试了,考了四天,也耽搁了四天,这就赶紧来补这场周赛的题了&a…

java求链表中倒数第k个结点

下面我用两种方法求解: 第一种方法:通常我们做这种题就是求出链表的长度length,然后呢length-k的值就是我们要从链表头部走几步就可以了,代码解释: public class Solution {public class ListNode {int val;ListNode…

Star 8K+,使用.NET开发的开源NoSQL数据库

LiteDB 是一个轻量级、快速、易用的 .NET NoSQL 嵌入式数据库,完全用 C# 托管代码开发,并且是免费和开源的。它非常适合在移动应用(Xamarin iOS/Android)和小型的桌面/Web 应用中使用。 主要特点 简单易用的 API,类似…

信号量机制

1965年,由荷兰学者迪科斯彻Dijkstra提出(P、V分别代表荷兰语的Proberen (test)和Verhogen (increment))、是一种卓有成效的进程同步机制。 信号量-软件解决方案: 保证两个或多个代码…

Javascript jQuery简介

✨前言✨ 1.如果代码对您有帮助 欢迎点赞👍收藏⭐哟 后面如有问题可以私信评论哟🗒️ 2.博主后面将持续更新哟😘🎉本章目录🎉 🥝一.jQuery简介🥥二.JQeury常用API🍇1.jQeury选择…

c JPEG编码,此程序没有处现MCU中亮度分量的排序

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/videodev2.h> //v4l2 头文件 #include <strin…

UE5蓝图-脚部IK

引擎版本&#xff1a;UE5.2 脚部IK做不做的区别&#xff1a; 图1是没有做脚步IK&#xff0c;我们的角色一部分的脚像是浮在半空中&#xff0c;图2是做了脚步IK&#xff0c;我们的角色就是一部分在地上&#xff0c;一部分在物体上。从上面的两个图可以看出&#xff0c;制作脚步…

Leetcode 剑指 Offer II 061. 查找和最小的 K 对数字

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定两个以升序排列的整数数组 nums1 和 nums2 , 以及一个整数 k…

[oeasy]python0004_游乐场_和python一起玩耍_python解释器_数学运算

和python玩耍 &#x1f94a; Python 回忆 上次 了解shell环境中的命令 命令作用whoami显示当前用户名pwd显示当前文件夹ls列出当前文件夹下的内容python3仿佛进入大于号黑洞 这python3 怎么玩啊&#xff01;&#x1f620; 说好的python教程呢&#xff1f;&#x1f914; 运…

2023一带一路暨金砖国家技能发展与技术创新大赛“网络安全”赛项省选拔赛样题卷②

2023金砖国家职业技能竞赛"网络安全" 赛项省赛选拔赛样题 2023金砖国家职业技能竞赛 省赛选拔赛样题第一阶段&#xff1a;职业素养与理论技能项目1. 职业素养项目1. 职业素养项目2. 网络安全项目3. 安全运营 第二阶段&#xff1a;安全运营项目1. 操作系统安全配置与加…

哈希表的实现(1)----除留余数法实现

一&#xff0c;哈希表的介绍 哈希表是一种通过哈希思想实现的一种数据结构。哈希表这种数据结构的特点便是可以通过一个值快速的定位这个值所在的位置实现插入&#xff0c;删除&#xff0c;查找。在这篇博客里面&#xff0c;我们便来实现一个通过除留余数法实现的一个哈希表。 …