深度学习在脑MRI分割中的应用

在本文中,将探讨如何利用深度学习技术对脑磁共振成像(MRI)图像进行自动分割,以期达到接近专业放射科医生的准确度,并预测患者是否患有肿瘤。如果检测到肿瘤,需要提供尽可能多的肿瘤信息,以便医生能够为患者提供更好的治疗方案。最终,还将尝试预测患者的存活情况。

这项任务涉及到深度学习和放射学的知识,将使用由癌症基因组图谱(The Cancer Genome Atlas, TCGA)和癌症影像档案库(The Cancer Imaging Archive, TCIA)提供的110名不同患者的数据集,尝试生成能够提供肿瘤信息的影像生物标志物。

这项任务可以归类为监督学习任务,为每张图像提供了掩码,任务是创建带有掩码的图像。低级别胶质瘤是一组包括分化良好的和间变性星形细胞瘤、少突胶质瘤和少突星形细胞瘤在内的WHO II级和III级脑肿瘤。

数据集

TCGA之前已经公开提供了这个问题的数据集。提供的数据是图像类型,扩展名为*.tif,位于带有扩展名”lgg-mri-segmentation/kaggle_3m/*/*”的文件夹中。这个扩展名代表所有训练MR图像文件,而掩码的扩展名以“_mask”结尾。除此之外,还提供了一个包含每位患者基因组信息的数据.csv文件。

在医学工程领域,通常发现疾病存在的数据较少,因此这里的数据集通常是高度不平衡的。但在这种情况下,发现它几乎是平衡的。大约有3800张图像仅来自110名患者。这是因为每位患者有20到88次不等的多次扫描。

为了简化这项任务,数据集的创建者手动标记了数据,因此可以将其归类为监督学习问题。这个数据集可以在这里下载。

方法

主要目标是识别越来越多的肿瘤特征,以便医生能够利用这些信息来治疗患者。认为对医生有益的一些重要点包括肿瘤的面积、肿瘤的坐标以及肿瘤的形状/扩散。通过收集所有这些信息,可以利用它们来预测肿瘤的所有可见细节。

为了获得这些数据,需要预处理数据并将其转换为模型可接受的格式,选择最合适的度量和损失函数,构建最合适的模型架构,调整模型性能,预测肿瘤掩码,分析获得的掩码区域,其中非零像素值的计算坐标,获得标准差,展示结果,并使用这些结果预测患者的死亡。

数据预处理

数据预处理是最关键的步骤,因为在这里进行大部分的预处理和特征工程工作。这是案例研究解决方案的主要特点之一。首先,让看看单个患者“TCGA_CS_4941”的所有MR图像。红色圆圈显示了可以识别肿瘤的区域。

正如所看到的,有相当多的图像带有肿瘤。但由于不是训练有素的放射科医生或医生,所以需要开发一些使用已经测试过的掩码的掩码图像。从上面的图像中,可以观察到,图像中的所有颜色并不都是同样有用的。结果表明,当有肿瘤时,它会用绿色突出显示,因此可以说,当有高强度的绿色时,可能有肿瘤。此外,这里的图像也不够清晰,无法获得每种颜色的高强度,因此还需要一个图像锐化器,不需要执行图像增强,因为这些图像是来自标准医疗机器的图像输出。

基于这个观察,可以创建一个自定义的数据加载器类,用于图像预处理和数据加载的结合,应该在这个流程图上工作。

图像预处理和数据加载

# 这里是一个示例代码,用于说明如何加载和预处理图像及掩码 from torch.utils.data import Dataset, DataLoader from torchvision import transforms import pandas as pd import numpy as np import torch class MRIDataset(Dataset): def __init__(self, dataframe, transform=None): self.dataframe = dataframe self.transform = transform def __len__(self): return len(self.dataframe) def __getitem__(self, idx): img_path = self.dataframe.iloc[idx, 0] mask_path = self.dataframe.iloc[idx, 1] image = np.load(img_path) mask = np.load(mask_path) if self.transform: image = self.transform(image) return image, mask # 定义转换操作 transform = transforms.Compose([ transforms.ToTensor(), # 可以添加更多的转换操作 ]) # 创建数据集 dataset = MRIDataset(dataframe=pd.DataFrame({ 'image_path': [...], # 图像路径列表 'mask_path': [...] # 掩码路径列表 }), transform=transform) # 创建数据加载器 dataloader = DataLoader(dataset, batch_size=4, shuffle=True)

在这个类中,只需要传递一个包含图像路径和掩码路径的pandas数据框,以及患者名称,它将返回一个包含图像和掩码的元组。然后,这个元组被传递到Dataloader中,根据提供的批量大小,它被转换为模型可加载的数据集。

度量和损失

由于这些是图像分割任务,因此它们的评估度量并不简单。在这里,需要对实际掩码和预测掩码进行逐像素比较。因此,有2个提议的度量标准用于语义分割任务。

交集比(Jaccard指数)是语义分割中最常用的度量标准之一,IoU可以定义为预测分割和真实值之间的重叠区域除以预测分割和真实值之间的并集区域。IoU定义在范围(0-1)内。这里0被定义为没有区域重叠,而1被定义为没有噪声,整个定义的区域都被重叠。

Dice分数(语义分割的F1)是将在案例研究中使用的有用分数,因为这个度量最初是在论文中使用的,从那时起它就被用来比较模型与其他模型。Dice系数 = 2 * 重叠区域除以两张图像中总像素数。

损失和度量可以在Keras中使用以下代码获得:

# 这里是一个示例代码,用于说明如何计算IoU和Dice系数 from keras.metrics import MeanIoU, categorical_crossentropy from keras.losses import binary_crossentropy # 定义IoU度量 def iou_metric(y_true, y_pred): # 计算IoU的代码 pass # 定义Dice系数 def dice_coefficient(y_true, y_pred): # 计算Dice系数的代码 pass # 编译模型时使用 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[iou_metric, dice_coefficient])

模型选择

在研究了各种提出的生物医学图像分割模型后,得出结论,使用Unet及其版本以及迁移学习。使用迁移学习将帮助显著减少训练时间并获得更好的准确性,因为使用带有resnet50的Unet提供了一个架构,其中Resnet 50作为主干,帮助检测图像中的特征,并使用图像网数据集进行预训练。

Unet++是一个具有许多跳跃连接的Unet架构,这些跳跃连接有助于从图像中获得粒度特征。

带有Resnet作为主干的Unet是一个具有Resnet编码器作为主干的架构,这些编码器的权重被冻结。

在这里,可以看到每个模型的结果与DICE和IOU度量,也可以得出结论,unetxresnet是一个适合需求的架构。

特征计算

现在,让计算一些对医生分析患者状况有帮助的重要特征。

# 这里是一个示例代码,用于说明如何计算特征 def calculate_features(image, mask): # 计算特征的代码 pass

这个函数返回面积、标准差和坐标。

预测死亡

Death01是“lgg-mri-segmentation/kaggle_3m/data.csv”中的特征,它告诉患者是否会死亡。但这个表中有很多缺失值需要填补。为了填补所有这些未知值,使用插值器。在这里,决定选择scikitlearn中的KNNImputer,n-neighbors=4,然后四舍五入以获得整数。

将这两个数据框基于患者ID作为键和方法作为内连接合并,创建另一个。现在这些特征可以与提供的数据.csv文件一起使用,预测Death01特征作为y,看起来能够以100%的准确度对所有点进行分类。

现在的主要任务是将任何*.tif格式的图像输入,它应该能够为该图像创建一个掩码并生成上述讨论的特征。这里不会处理Data.csv。在这里,只会生成掩码和重要特征。为此将使用streamlit,进一步的代码可以在这里下载。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485