乐趣区

关于计算机视觉:拯救脂肪肝第一步以飞桨3D医疗影像分割方案MedicalSeg自主诊断脂肪肝

明天带来的是飞桨开发者技术专家冯嘉骏利用飞桨 3D 医疗影像宰割计划 MedicalSeg 自主诊断脂肪肝的案例分享,欢送大家关注~

我的项目背景

当初人们的日常生活形式和饮食结构产生了微小的变动,大略就是吃好了,动少了。体内的适量的甘油三酯无奈代谢,最终汇集在肝细胞内,导致人体中失常肝脏逐渐变成脂肪肝。长期患有脂肪肝可能会导致肝硬化,并最终减少患慢性肝病的危险。医学影像学畛域能够通过 CT 或者 B 超技术来判断患者是否患有脂肪肝,其中 CT 的脂肪肝检出比例高于 B 超,其用于诊断脂肪肝时准确率更高、特异性更强。

在 CT 查看中,次要是通过计算肝脏与脾脏的 CT 值的比值来确定患者是否患有脂肪肝以及重大水平。依据中华医学会肝病学分会制订的规范,肝、脾 CT 比值大于 1 为失常肝脏,CT 比值在 [0.7,1.0] 之间为轻度脂肪肝,[0.5,0.7]之间为中度脂肪肝,小于 0.5 为重度脂肪肝。在日常工作中,喷射医师须要手工抉择肝脏和脾脏的最大层面,在肯定范畴内进行 ROI 的选取,之后计算 ROI 范畴内肝脏和脾脏的 CT 总值以及计算两者 ROI 范畴内 CT 总值的比值,从而确定患者是否患有脂肪肝。这个过程须要投入较多的工作量。

目前,深度学习技术中的语义宰割正被广泛应用于医学畛域。该技术能够通过训练模型来预测出影像中的不同组织类型的准确边界、地位和区域,在腹部 CT 上主动取得肝脏和脾脏的宰割后果,对肝脏和脾脏屡次随机取出肯定体积的立方体来计算 CT 总值的比值,从而评估被检测者是否有脂肪肝以及脂肪肝的重大水平。这种形式加重医生的工作强度,也防止人为的主观性带来的偏差。如下图展现人工测量和基于语义宰割主动测量之间的优劣。关注 AI Studio 我的项目和我一起探讨️

  • 我的项目链接

https://aistudio.baidu.com/aistudio/projectdetail/5574909

医学临床上进行诊断时会人为抉择 CT 平扫肝、脾显示最大层面,各选取边长为 1.0cm 以上的正方形 ROI 对肝、脾取 CT 值。本我的项目为了升高随机选取 ROI 时可能纳入肝内血管和伪影局部,影响计算肝脾比值后果的真实性,提出如下解决办法:1. 减少随机取出立方体 ROI 的个数;2. 两两配对,减少肝脾比值的样本。

主动宰割与评估脂肪肝操作步骤

环境版本要求

数据集介绍

用医疗软件 itk-snap 软件读取原始数据和对应宰割标签,展现成果如下图:

VNet 模型和医疗宰割套件 MedicalSeg

绝对于二维语义宰割,三维语义宰割利用体素的三维构造信息来宰割医学影像,具备更强的抓取空间信息的能力。因为三维宰割利用了四周邻近切片及沿着 z 轴的轴向信息,具备更好的上下文信息,进一步提高了模型的泛化能力。此外,三维语义宰割相较二维语义宰割也有利于打消噪声和伪影的影响。以后应用的医疗影像数据具备较高的空间分辨率且为三维影像数据,因而应用三维语义宰割模型进行宰割通常是更适宜的解决形式。这次应用的三维语义宰割模型 VNet 采纳了一种自下而上的办法,并且应用了 U 形连贯搭建网络结构,以捕捉到影像数据的不同尺度的细节信息。因为相邻的体素往往具备亲密的相关性,因而 VNet 引入了 3D 卷积、转置卷积操作以及残差 U 形连贯来捕捉和利用交融上下文信息,从而进步模型的精度和泛化能力。宰割医疗影像数据时,因为病变区域可能会占整个影像的很小一部分,导致标注数据的散布不平衡,VNet 提出 Dice 损失函数,来缩小不均衡散布对模型训练的影响,使模型更加稳固。VNet 整体构造如下。

MedicalSeg 是一个繁难、弱小、全流程的 3D 医学图像宰割工具,作为 PaddleSeg 宰割套件中的宰割工具,继承了 PaddleSeg 配置化训练的模式,一行代码实现对医疗数据的解决和模型的训练,本我的项目就是基于 MedicalSeg 宰割套件实现在腹部 CT 上对肝脏和脾脏的 3D 宰割。

模型训练和推理

数据处理

因为医疗数据较为非凡,须要进行预处理操作,例如重采样、像素裁剪,再转换成 NumPy 格局。须要自定义数据预处理脚本 prepare_SpleenAndLiver.py。脚本次要设置数据的门路和像素裁剪等参数设置。设置如下:

1.        self.preprocess = {
2.            "images": [
3.                wrapped_partial(4.                    HUnorm, HU_min=-100, HU_max=300),# 设置窗宽窗位的裁剪范畴
5.                wrapped_partial(6.                    resample, new_shape=[128,128,128], order=1)# 设置输出网络的数据形态,程序是[z,y,x]
7.            ],
8.            "labels": [
9.                wrapped_partial(10.                    resample, new_shape=[128,128,128], order=0),
11.            ],
12.            "images_test":[
13.                wrapped_partial(14.                    HUnorm, HU_min=-100, HU_max=300),
15.                wrapped_partial(16.                    resample, new_shape=[128, 128, 128], order=1)
17.            ]
18.        }

而后通过一行代码转换数据,并按肯定比例宰割训练集和验证集。

1.# 运行预处理文件,把 SimpleITK 文件转换成 numpy 文件,生成对应的 train.txt 和 val.txt,和数据参数无关的 json 文件
2.!python tools/prepare_SpleenAndLiver.py

模型训练

MedicalSeg 采纳配置化训练,须要新建一个配置化 Yaml 文件,而后再以代码进行训练。配置文件次要设置数据的门路、数据加强形式、优化器、学习率和宰割模型等主要参数。不过个别状况下次要设置数据的门路,其它设置只须要放弃默认即可。当训练成果不好的时候,能够依据教训对数据加强、学习率等参数进行批改。Yaml 配置如下:

1.data_root: /home/aistudio/work/
2.batch_size: 2 #32GB 显存,shape=256x128x128,batchsize 能够设置 2
3.iters: 10000 #训练轮次
4.train_dataset:
5.  type: MedicalDataset 
6.  dataset_root: /home/aistudio/work/SpleenAndLiver_Np #转换后的 Numpy 文件门路
7.  result_dir: /home/aistudio/result  
8.# 设置数据加强
9.  transforms:
10.    - type: RandomRotation3D  #3d 抉择
11.      degrees: 90
12.    - type: RandomFlip3D #程度翻转
13.  mode: train
14.  num_classes: 3  #宰割类别数
15.val_dataset:
16.  type: MedicalDataset
17.  dataset_root: /home/aistudio/work/SpleenAndLiver_Np
18.  result_dir: /home/aistudio/result
19.  num_classes: 3
20.  transforms: []
21.  mode: val
22.  dataset_json_path: "/home/aistudio/work/dataset.json"
23.# 设置优化器
24.optimizer:
25.  type: sgd
26.  momentum: 0.9
27.  weight_decay: 1.0e-4
28.# 设置学习率
29.lr_scheduler:
30.  type: PolynomialDecay
31.  decay_steps: 10000
32.  learning_rate: 0.05
33.  end_lr: 0
34.  power: 0.9
35.# 设置损失函数
36.loss:
37.  types:
38.    - type: MixedLoss
39.      losses:
40.        - type: CrossEntropyLoss
41.        - type: DiceLoss
42.      coef: [0.3, 0.7]
43.  coef: [1]
44.# 设置 VNet 模型参数
45.model:
46.  type: VNet
47.  elu: False
48.  in_channels: 1
49.  num_classes: 3
50.  pretrained: null
51.  kernel_size: [[2,2,4], [2,2,2], [2,2,2], [2,2,2]]
52.  stride_size: [[2,2,1], [2,2,1], [2,2,2], [2,2,2]]

配置好 Yaml 文件之后,就能够实现一行代码进行训练。

1.!python3 train.py --config /home/aistudio/SpleenAndLiver.yml \
2.    --save_dir  "/home/aistudio/output/SpleenAndLiver_vent_128" \
3.    --save_interval 70 --log_iters 20 \
4.    --keep_checkpoint_max 3 \
5.    --num_workers 1 --do_eval --use_vdl 

模型验证

训练完之后,模型验证也只须要一行代码即可实现。

1.!python3 val.py --config /home/aistudio/SpleenAndLiver.yml \
2.    --model_path /home/aistudio/output/SpleenAndLiver_vent_128/best_model/model.pdparams \
3.    --save_dir  /home/aistudio/output/SpleenAndLiver_vent_128/best_model

最终通过 10000 iters 的训练,验证集达到均匀 Dice 0.9531,肝脏 Dice0.944,脾脏  Dice0.918。整体宰割成果达到不错的精度。

1.2023-03-22 04:57:21 [INFO] [EVAL] #Images: 18, Dice: 0.9531, Loss: 0.097088
2.2023-03-22 04:57:21 [INFO] [EVAL] Class dice: 
3.[0.9964 0.9444 0.9183]

模型导出

为了模型推理,须要导出训练模型,实现代码如下。

1.!python export.py --config /home/aistudio/SpleenAndLiver.yml \
2.--model_path /home/aistudio/output/SpleenAndLiver_vent_128/best_model/model.pdparams \
3.--save_dir /home/aistudio/export_model

判断是否脂肪肝以及脂肪肝的重大水平

实现主动判断脂肪肝,须要对预测的宰割后果进行解决。解决步骤如下:

1)对宰割后果的每一类保留最大连通域;

2)依据原始图像的图像参数,把宰割后果转换成 Nifit 格局;

3)在宰割后果中别离训练肝脏、脾脏的最小边界范畴;

4)别离在肝脏、脾脏的范畴里,切割 n 个立方体;

5)对两组立方体,两两配对,计算两者的 CT 比值;

6)对所有两两配对的 CT 比值,求均值,即为肝脏与脾脏的 CT 比值;7)依据 CT 比值对应诊断规范判断是否脂肪肝以及重大水平。局部要害代码如下:

  • 保留最大连通域
1.def GetLargestConnectedCompont(binarysitk_image):
2.    # 最大连通域提取,binarysitk_image 是掩膜
3.    cc = sitk.ConnectedComponent(binarysitk_image)
4.    stats = sitk.LabelIntensityStatisticsImageFilter()
5.    stats.SetGlobalDefaultNumberOfThreads(8)
6.    stats.Execute(cc, binarysitk_image)# 依据掩膜计算统计量
7.    maxlabel = 0
8.    maxsize = 0
9.    for l in stats.GetLabels():# 掩膜中存在的标签类别
10.        size = stats.GetPhysicalSize(l)
11.        if maxsize < size:# 只保留最大的标签类别
12.            maxlabel = l
13.            maxsize = size
14.    labelmaskimage = sitk.GetArrayFromImage(cc)
15.    outmask = labelmaskimage.copy()
16.    if len(stats.GetLabels()):
17.        outmask[labelmaskimage == maxlabel] = 255
18.        outmask[labelmaskimage != maxlabel] = 0
19.    return outmask
  • 放大肝脏、脾脏的范畴
1.def maskcroppingbox(mask):
2.    #寻找 mask 范畴的 3D 最大边界范畴
3.    mask_2 = np.argwhere(mask)
4.    (zstart, ystart, xstart), (zstop, ystop, xstop) = mask_2.min(axis=0), mask_2.max(axis=0) + 1
5.    if zstart- zstop < 0 :  zmax,zmin = zstop,zstart
6.    if ystart- ystop < 0 :  ymax,ymin = ystop,ystart
7.    if xstart- xstop < 0 :  xmax,xmin = xstop,xstart
8.    return zmax,zmin,ymax,ymin,xmax,xmin
  • 两两配对计算肝脏和脾脏的 CT 比值
1.# 当初有 5 个肝脏的立方体和 5 个脾脏的立方体,找出两个的所有组合,而后计算它们比值
2.tupleNums = list(itertools.product(label[1], label[2]))
3.cts = [tupleNum[0]/tupleNum[1] for tupleNum in tupleNums]

论断

宰割预测成果

须要把预测后果转换成和原始数据的空间、维度、尺度等参数统一的 Nifit 格局医疗数据文件。对预测的宰割后果解决后失去的地位映射到原始数据上能力保障取 ROI 计算 CT 值时,没有额定的插值。因为肝脏和脾脏都是一个整体间断的器官,因而预测后果转换之前,还需对后果只保留最大连通域,去掉小指标。对 88 例带标签的数据,通过以上的解决,再从新计算 Dice。最终反馈肝脏有 0.954mDice,脾脏有 0.911mDice。

在临床中的事实成果

为了测验“基于 3D 宰割实现主动判断脂肪肝和重大水平”在理论临床上的成果,随机抉择 10 名病例,别离应用手动测量和主动测量的办法对 10 名病例进行肝、脾 CT 值的测量,并应用非参数检验办法对后果进行测验。测量数据如下:

应用 Mann-Whitney U 测验判断手动测量与主动测量程度是否有差别。依据直方图判断两组测量后果散布的形态基本一致。人工测量的中位数为 0.714,主动测量的中位数为 0.740。Mann-Whitney U 测验结果显示,人工测量与主动测量差别无统计学意义(U=48.000,P=0.912)。

我的项目意义

目前主动判断脂肪肝的办法大多应用阈值或者直方图等传统宰割形式。本我的项目是应用深度学习中三维语义宰割来实现肝脏和脾脏的精准宰割,再采纳屡次随机取三维 ROI 来计算比值。从而加重了医生的工作量和主观性偏差,进步医疗品质和效率。以上就是基于 3D 宰割实现主动判断脂肪肝和其重大水平的相干内容。欢送大家来我的 AI Studio 页面互关交换,与我独特体验飞桨的乐趣!

https://aistudio.baidu.com/aistudio/personalcenter/thirdview/…

退出移动版