【计算机视觉】新冠肺炎COVID-19 CT影片阳性检测,感染区域分割,肺部分割,智慧医疗实践,医疗影像处理示例

引言

新型冠状病毒肺炎(Corona Virus Disease 2019,COVID-19),简称“新冠肺炎”,世界卫生组织命名为“2019冠状病毒病”。截止至2021年12月5日,全球累计确诊病例264047110例,累计死亡5240683例,并且这个数字还在继续高速攀升。

基于肺部CT(computed tomography)影像的人工智能诊断是针对新型冠状病毒肺炎的有效辅助诊断方法之一。

本次实验基于COVID-19 CT scans数据集,根据患者肺部的CT扫描分析,对患者COVID阳性还是阴性进行分类。如果患者Covid阳性,则这行肺部和感染区域的分割。实验还实现了交互性良好的可视化界面,更有助于医护人员对病情的快速筛查。

数据集概述

COVID-19 CT scans数据集包含20例诊断为COVID-19的患者的CT扫描以及专家对肺部和感染的分割。具体参数如下:
· 平均每类162图 大小有630630,512512,401*630;
· 有病区域占总体面积比:11170073 / 993762820 = 1.12%;
· 有病区域占有病图像面积比: 11170073 / 525924858 = 2.12%;
· 有病图占正常图比例: 1718 / 3250 = 52.86%。
数据集包含的四个文件分别是original image,lung mask,infection mask, lung and infection mask,为了更好的理解里面是什么东西,我们找到数据集给出的样例图片:
在这里插入图片描述

实验方法

为了系统的完善,本次实验切分为五个小任务:图像预处理、新冠肺炎阴阳性识别、肺部分割、感染区域分割、可视化界面搭建。

图像预处理主要应用本学期所学的图像增强的一些方法,比如直方图均衡,轮廓检测等,然后还引入了形态学的腐蚀和膨胀操作。

阴阳性识别是一个经典的二分类任务,我们使用较为简单的CNN网络进行分类任务的训练,最终的准确率达到0.96以上。

肺部分割与感染区域分割是语义分割任务,前者的语义相对简单,而后者的语义相对比较复杂。这两个任务都基于U-net网络进行训练,不同的是,用于训练感染区域分割任务的U-net网络要更为复杂一些。此外,使用dice loss作为损失函数(后续具体介绍),最终得到的dice系数分别为0.8353、0.7821。

可视化界面的搭建使用pyqt5依赖包,搭建较为简易的交互界面,并将训练好的网络模型应用到该界面,从而得到一个具有实际应用价值的新冠肺炎识别系统。

结果预览

在这里插入图片描述

实验步骤与过程

1. 图像预处理

1.1 加载metadata

metadata文件存放着COVID-19 CT scans数据集的文件目录,我们可以通过read_scv函数加载这个文件,从而获得所有数据文件的目录,并在后续能够访问他们。

# 加载文件目录
metadata = pd.read_csv('../input/metadata.csv')
# print(metadata.shape)
# print(metadata.head())
1.2 图像增强

为了后续更好的识别与预测,我们需要对图像进行增强,最简单的做法便是增强图像的对比度。这里我们使用OpenCV的createCLAHE函数以统一的方式进行直方图均衡化,使得暗区可见,而亮区以动态格式清晰可见,从而增强图像的对比度。
在这里插入图片描述

1.3 图像分割(ROI提取)

观察CT图片,除了我们感兴趣的肺部区域之外,还有一些黑色的背景,当然为了后续更好的识别与预测,我们只提取感兴趣的肺部区域,所以我们需要对图像进行一个剪裁。因为这个数据集有lung mask已经为我们标注了大概的位置,所以具体的做法如下:

(1)检测轮廓
首先使用cv.findContours函数,选择提取所有轮廓,并简单地保存拐点位置,然后我们画出对应的图像,关键代码如图3-1-5所示,检测出来的轮廓如图3-1-4(Binarization)所示。cv.findContours具体原理参见博客https://www.cnblogs.com/wojianxin/p/12602490.html。
在这里插入图片描述
(2)检测肺部的位置
正如我们在图3-1-4所看到的,轮廓提取之后只有左右两侧的肺叶,并没有完全提取出整个我们感兴趣的肺部区域,因此还需要做进一步的处理。

为了更好地提取出整个肺部区域,经过探索分析,发现肺部的像素值都比较接近,可以和其他背景很好地分开,换言之我们可以使用聚类的方法,将肺部检测出来。

做完聚类之后,可以使用形态学技术里面的腐蚀和膨胀(参考:https://zhuanlan.zhihu.com/p/110330329)对聚类得到的肺部区域先进行腐蚀,然后接着进行膨胀(即开操作),这样做的目的是使对象的轮廓变得光滑,断开狭窄的间断和消除细的突出物。

(3)图像剪裁
根据前面的分析,我们已经提取到了边界的信息,这时候图像剪裁只需要根据这个边界信息,创建一个矩形框,然后进行切割即可。

这样我们就完成了肺部的ROI提取,下面我们挑取10张图片,分别打印出它们对应的原图、增强图、以及提取到的ROI。
在这里插入图片描述

1.4 推广到infection和lung mask两个数据集

前面是基于ct_scan这一组数据做的处理,现在我们需要将这一处理方法推广到其他两个数据集,处理的流程与前面的大致相同,都是先图像增强然后再做ROI的提取,详细的代码可以参见提交的附件中的DataPreprocessing中的print_all函数。这个函数里面,我们挑取了5张图片,分别打印出其对应的原图、增强之后的图像、原来的lung mask、处理之后的lung mask、原来的infection mask以及处理之后的infection mask。
在这里插入图片描述
在这里插入图片描述

2. 阴阳性分类

2.1 网络架构

新冠肺炎的阴阳性分类属于一个二分类任务,标签‘1’代表阳性,‘0’代阴性。由于上面对数据做了预处理,并保存在文件中,所以做分类任务的时候只需要加载出来就可以了。

二分类任务有很多的方法可以做,比如经典机器学习的SVM、LDA、线性回归等模型,或者深度学习 的U-net网络、CNN、AlexNet等网络模型。在本任务中,我们选择自己设计一个简单的CNN网络,该网络有4个卷积层,每个卷积层之后有一个最大池化层和normalization,其网络架构如图3-2-1所示。我们可以看到该网络的输入是1281281大小的图像,经过神经网络处理之后,输出一个一维特征。
在这里插入图片描述
其中,卷积层的卷积核为3*3,其主要作用是提取局部特征,以利于分类;最大池化层大小为2,其主要作用是通过消除非极大值,降低了上层的计算复杂度;而normalization的主要作用是平衡数据的分布,防止出现无穷大无穷小的值,另外还可以平滑特征,使得分类更加精准。

2.2 网络搭建

本次实验使用TensorFlow框架搭建2DCNN网络,网络搭建分为两步,首先是定义网络框架,然后是定义网络的学习率等参数然后编译网络。

(1)定义网络框架
TensorFlow搭建网络比较简单,我们只需要定义好输入大小和输出大小,然后用搭积木的方式搭建起来就可以了。其关键代码如图3-2-2-所示,我们首先定义一个2维卷积层,随后定义一个MaxPooliing2D,然后加一个normalization,按照此架构重复4次,但是每次的特征维度有所不同,这是为了更好地进行非线性变化,提取更有利于分类的特征。最后,我们需要做一个平均池化层,然后dense之后dropout随机去掉一些特征,最后再dense成一维特征输出。

在这里插入图片描述
(2)编译网络
网络框架定义之后,我们需要去引用它,这里可以理解你定义了一个类,然后你要去实例化这个类,你才能去调用这个类相关的函数(train,predicct等)。在网络编译的时候,最重要的是要定义好学习率、损失函数和优化器。
在这里插入图片描述
在本实验中,我们定义学习率为0.0001,学习率的定义不宜太大(这样学不到很好的特征,容易跳来跳去),同时也不宜太小(训练太慢,消耗算力资源)。同时由于是二分类任务,因此我们选择交叉熵损失作为我们网络的损失函数,然后选择Adam作为网络的优化器。

2.3 数据集准备

我们都知道神经网络需要大量的数据进行训练,因此我们定义好神经网络之后,要先准备好数据,然后再进行训练。

数据集只需要从前面的数据预处理保存的文件中加载出来即可,然后我们需要将数据集划分为训练集/验证集/测试集,其比例分别为6:2:2。注意,这里比经典机器学习多了一个验证集,其作用是验证网络的好坏,计算loss作为梯度反向传播的依据,这样做有利于防止网络过拟合。

2.4 训练网络

准备好网络框架和数据集之后,我们接下里就是训练网络了,训练的过程中,网络会进行梯度反向传播,不断优化各个参数,然后我们只取其中loss最小的一个模型。
在这里插入图片描述
在这里插入图片描述

3. 阳性肺部区域分割

3.1 肺部区域分割的必要性与做法

为什么要做肺部区域的预测分割呢?虽然在数据集上已经标记好了肺部的区域,但是这是人工所标记的,后续我们搭建的可视化界面,作为一个应用平台,用户不会告诉你肺部在哪个位置。这个时候就要求我们的系统可以自动地对肺部区域进行分割,然后再出感染的部位(这将在第四个部分进行叙述)。因此,肺部区域的分割不仅有利于提高系统的交互性,更有利于后续感染区域的分割。

同时,因为我们这个时候不是分类任务了,而是图像分割任务,因此我们需要定义新的网络框架进行训练,当然也可以使用其他粗糙的方法,但是往往并不鲁棒。这里我们选择使用U-net网络(后续会详细介绍)进行特征的提取,然后使用Dice Loss作为损失函数,其中dice看理解为是两个轮廓区域的相似程度。

3.2 网络架构

(1)关于语义分割
语义分割(Semantic Segmentation)是图像处理和机器视觉一个重要分支。与分类任务不同,语义分割需要判断图像每个像素点的类别,进行精确分割。语义分割目前在自动驾驶、自动抠图、医疗影像等领域有着比较广泛的应用。Unet可以说是最常用、最简单的一种分割模型了,它简单、高效、易懂、容易构建、可以从小数据集中训练。

(2)关于U-net
U-net最早出现与2015年,是《U-Net: Convolutional Networks for Biomedical Image Segmentation》一文中提出的模型。
在这里插入图片描述
这个结构就是先对图片进行卷积和池化,在Unet论文中是池化4次,比方说一开始的图片是224x224的,那么就会变成112x112,56x56,28x28,14x14四个不同尺寸的特征。然后我们对14x14的特征图做上采样或者反卷积,得到28x28的特征图,这个28x28的特征图与之前的28x28的特征图进行通道伤的拼接concat,然后再对拼接之后的特征图做卷积和上采样,得到56x56的特征图,再与之前的56x56的特征拼接,卷积,再上采样,经过四次上采样可以得到一个与输入图像尺寸相同的224x224的预测结果。

Unet网络非常的简单,前半部分就是特征提取,后半部分是上采样。在一些文献中把这种结构叫做编码器-解码器结构,由于网络的整体结构是一个大些的英文字母U,所以叫做U-net。

由于网络层越深得到的特征图,有着更大的视野域,浅层卷积关注纹理特征,深层网络关注本质的那种特征,所以深层浅层特征都是有格子的意义的;另外一点是通过反卷积得到的更大的尺寸的特征图的边缘,是缺少信息的,毕竟每一次下采样提炼特征的同时,也必然会损失一些边缘特征,而失去的特征并不能从上采样中找回,因此通过特征的拼接,来实现边缘特征的一个找回。

而医疗影像语义较为简单、结构固定。因此语义信息相比自动驾驶等较为单一,因此并不需要去筛选过滤无用的信息。医疗影像的所有特征都很重要,因此低级特征和高级语义特征都很重要,所以U型结构的skip connection结构(特征拼接)更好派上用场。

在这里插入图片描述

3.3 网路搭建

跟前面一样,我们依然使用TensorFlow框架搭建网络,这里代码比较长,就不截图了,详细的可以参考附件的代码。
在这里插入图片描述
在这里插入图片描述

3.4 Dice Loss

dice loss 的提出是在V-net中,其中的一段原因描述是在感兴趣的解剖结构仅占据扫描的非常小的区域,从而使学习过程陷入损失函数的局部最小值。所以要加大前景区域的权重。
Dice 可以理解为是两个轮廓区域的相似程度,用A、B表示两个轮廓区域所包含的点集,定义为:
在这里插入图片描述
设TP,FP,FN分别是真阳性、假阳性、假阴性的个数。Dice也可以表示为:
在这里插入图片描述
dice coefficient取值范围在0到1之间,取值越大表示越相似,dice loss也可以由dice coefficient表出:
在这里插入图片描述
由于1是常数,所以在网络训练的过程中,将其省略(提高运算速度),只用-dice coeff代替dice loss。

4. 阳性感染区域分割

4.1 肺部区域分割的必要性与做法

当我们预测出新冠肺炎阳性之后,工作做得还是不够的,一个好的系统除了能帮助医生诊断之外,更理想的效果是同时预测出感染的区域。阳性感染区域的预测正是在做这个工作。 我们用数据集中标记好的infection mask作为目标,使用更加复杂的U-net网络去提取拟合特征,使用dice loss损失函数,最终我们的dice系数达到了0.78219,已经可以很好的预测出感染区域了。

4.2 网络架构

阳性感染区域的分割说到底还是一个语义分割的任务,只不过这个语义相对于肺部分割来说要更加困难和复杂。具体体现在:1)感染区域的位置不稳定,分布方差很大,2)感染区域的大小也有很大的差别,3)感染区域的形状不像肺部那样有潜在的规律。

因此,为了达到阳性感染区域分割的目的,我们必须使用更加复杂的网络来训练。但我们还是在U-net的基础上进行设计,多加了一些卷积层和池化层,使得网络的非线性特征提取能力更强,使网络语义分割能力更加鲁棒。

在损失函数上,我们依然使用衡量两个区域相似度的dice系数,并由dice系数表达出dice loss。

除此之外,在学习率的设置上,这次我们区别于之前固定的学习率,让网络自适应去调整学习率,具体怎么做的呢?TensorFlow框架开放了相关的接口,我们只需要调用就可以了。

4.3 网络搭建

这一次为了实现更加复杂的网络结构,区别于上两个任务的网络搭建,这次采用block的形式来搭建网络。Block的好处是将网络相同结构的块进行包装形成一个新的block,这样既方便代码的编写,也有助于理清网络架构。
在这里插入图片描述

4.4 训练

训练和之前也类似,但是这一次因为数据量大,网络复杂,我们需要自己定义batch size(实际上最好是自己定义),防止笔记本吃不消,这里选择的是8。训练过程如图3-4-3所示,可以看到最好的dice是0.78219,已经达到了初步应用的基础。
在这里插入图片描述
和之前一样我们打印出loss曲线,判断收敛性和是否过拟合,如图3-4-4所示,可以看到尽管曲线有所波动,但是总体上趋于收敛,并且没有过拟合的现象,有一点点的欠拟合(计算机算力不行,epoch=100训练了6个小时,所以就没继续炼丹)。
在这里插入图片描述

5. 可视化系统搭建

5.1 预览

在这里插入图片描述
四个图分别有其具体含义:第一个图是CT原图,用于作为系统的输入;第二个图是使用原来的CT图进行图像增强和cropped之后的结果,用于作为网络的输入;第三个图是像素分布直方图,用于验证图像增强之后的效果;第四个图是预测得到的结果,如果没有干扰不会有任何标记,如果是阳性的,就标记出感染的区域。

然后上方最左侧是文件路径,可以用于我们选择输入的CT,往右是开始诊断按钮,再往右用于显示识别结果,黄色表示阴性,红色表示阳性。

5.2 操作说明

进入界面之后,首先点击“…”选择CT图像,然后会看到加载出来原CT图像,CT增强之后的图像和相应的像素分布直方图。然后点击开始诊断按钮,即可进行诊断,等待3s左右,便可看到结果。由于有一定的误差,建议多次识别以获得更加准确的结果。

5.3 原理介绍

怎么实现的呢?界面的设计我使用的是pyqt5,这要是粘贴图片和显示文字,然后识别的过程是用前几个任务训练好的模型(已经保存)进行识别。

首先需要注意的是pyqt5不能直接显示pyplot画的图,这里采用的做法比较粗暴,就是先保存下来,然后再用图片的方式给pyqt5获取.

另外一个比较关键的是,如何加载模型并进行识别,我的做法是保存训练好的模型参数,然后load进来之外,以处理后的CT图作为输入,先做阴阳性识别任务,如果识别的是阳性,再进行infection区域的分割,然后将分割之后的图像和处理后的CT图像进行图层复合。

参考文献

[1]. 唐迁, 杜博, 恽爽, 高莉, 吴爽, 张超, 兰猛, 陈紫业, 李亮, 查云飞, 张良培, 李平湘. COVID-19 CT影像智能诊断系统[J]. 武汉大学学报·信息科学版, 2020, 45(6): 846-853. doi: 10.13203/j.whugis20200225. http://ch.whu.edu.cn/cn/article/doi/10.13203/j.whugis20200225.

[2]. 百度百科·新型冠状病毒肺炎.
https://baike.baidu.com/item/%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92%E8%82%BA%E7%82%8E/24282529.

[3]. Kaggle COVID-19 CT scans. https://www.kaggle.com/andrewmvd/covid19-ct-scans.

[4]. 知乎·图像分割必备知识点 | Unet详解 理论+ 代码:
https://zhuanlan.zhihu.com/p/313283141

[5]. 知乎·最全综述 | 图像分割算法:https://zhuanlan.zhihu.com/p/70758906.

[6]. 知乎·U-Net:https://zhuanlan.zhihu.com/p/311519960.

[7]. 博客园·python+opencv+dlib+pyqt5人脸识别实践:
https://www.cnblogs.com/tonasy/p/9664181.html。

附加说明

实验环境说明:操作系统为Windows10,python版本为3.8,pycharm为2021专业版,TensorFlow=v2.4.0,keras=v2.2.5,nibabel=3.2.1,可视化界面使用pyqt5,网络模型3D作图使用PlotNeuralNet。

如需源码,或者有学术交流的需要,请私信联系我。需要源码的请在评论区留下您的邮箱。

  • 32
    点赞
  • 162
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 213
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 213
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kim‘s blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值