从多个文件夹加载医学影像数据

数据挖掘 机器学习 数据 可视化 卡格尔
2022-03-09 11:58:31

我对 ML 算法和 CNN 有相当基本的数学和实现理解,并且我正在尝试为这项任务考虑一种方法:https ://www.kaggle.com/c/rsna-miccai-brain-tumor-radiogenomic-分类/数据?选择=测试

“数据”部分解释了任务并提供了数据集的预览。

对一般实施方法的怀疑:

据我了解,我们有 4 个输入参数:FLAIR、T1W、T1Gd 和 T2W。基于这 4 个参数,我们必须计算“MGMT 状态”(MGMT 的存在),它是二进制的,即取值()。0/1

我们可以使用使用 sigmoid 激活函数的 CNN 架构,它是最后一层(在中获得输出)。(0,1)

现在,我知道图像作为输入被馈送到神经网络,例如。然而,在对象检测程序中,在这些示例中,将单个图像作为输入输入,随后网络会提取特征。

我应该如何处理我的特殊情况,我有多个图像作为输入参数?

另外,火车数据集中的顶级文件夹00000,00002..etc 到底对应于什么?我最初认为它们表现得像“患者编号”(即训练示例),但是每个顶级文件夹中的 4 个子文件夹不应该只有一个图像吗?一张 FLAIR 图像,一张 T1W 图像……等等。然而,每个顶级文件夹对应多个 FLAIR (~200) 、 T1W 、..etc 图像。

编辑

在 Serali 的回答之后,我对我们应该如何处理预处理有了一些见解。顶级文件夹00000,00002,.. 等确实起到“患者编号”的作用,这就是文件train_labels.csv所指的“ BraTS21ID”。

现在例如我们选择文件夹00000其中有 4 个子文件夹,每个子文件夹包含各种图像:例如,FLAIR 子文件夹包含 200 个图像。这 200 张图像代表FLAIR MRI 的切片,我想它们将被堆叠在一起以提供完整的“FLAIR MRI”。

同样,如果我们对其余子文件夹中的所有图像都这样做,我们最终将在每个顶级文件夹中获得 4 张图像,对应于 FLAIR,T1W,T1gd,T2W。我找到了一个似乎可以做到这一点的脚本:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
import json
import glob
import random
import collections
import cv2
import pydicom
from pydicom.pixel_data_handlers.util import apply_voi_lut

from matplotlib import animation, rc
rc('animation', html='jshtml')

train_df = pd.read_csv("../input/rsna-miccai-brain-tumor-radiogenomic-classification/train_labels.csv")
def load_dicom(path):
    dicom = pydicom.read_file(path)
    data = dicom.pixel_array
    data = data - np.min(data)
    if np.max(data) != 0:
        data = data / np.max(data)
    data = (data * 255).astype(np.uint8)
    return data



def visualize_sample(
    brats21id, 
    slice_i,
    types=("FLAIR", "T1w", "T1wCE", "T2w")
):
    plt.figure(figsize=(10, 3))
    patient_path = os.path.join(
        "../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/", 
        str(brats21id).zfill(5),
    )
    for i, t in enumerate(types, 1):
        t_paths = sorted(
            glob.glob(os.path.join(patient_path, t, "*")), 
            key=lambda x: int(x[:-4].split("-")[-1]),
        )
        data = load_dicom(t_paths[int(len(t_paths) * slice_i)])
        plt.subplot(1, 4, i)
        plt.imshow(data, cmap="gray")
        plt.title(f"{t}", fontsize=10)
        plt.axis("off")
    plt.show()
    
_brats21id = train_df.iloc[0]["BraTS21ID"] #patient ID 0 
visualize_sample(brats21id=_brats21id,slice_i=0.55)

此脚本显示患者 ID 00000 的 4 个最终图像。输出:

在此处输入图像描述

现在,我有点困惑,我应该如何处理这 4 张图片。通过“3-D堆叠”将它们再次组合成一个?对于每个顶级文件夹,我有一段似乎最终只获得 1 张图像的代码:

https://www.kaggle.com/ammarnassanalhajali/brain-tumor-3d-training (“加载图像的功能”部分)

主要问题

我对这两个脚本在做什么有一些模糊的想法,但我想具体理解它们,因为我希望为此编写自己的代码。

脚本 1

  1. load_dicom()函数首先使用 .dcm 读取 .dcm 图像,但是变量pydicom.read()的操作发生了什么?data喜欢data=data-np.min(data)data= (data*255).astype(np.uint8)
  2. 函数中发生了visualise_sample()什么?

脚本 2

  1. 该功能到底在load_dicom_image()做什么?我得到了调整大小的部分,但我不明白rotateandvoi_lut参数。

  2. 主要功能似乎是load_dicom_images_3d我不知道这是在做什么。我认为glob.glob()正在用于迭代火车部分中的所有文件,但我不了解 lambda 随后的使用,我不知道定义 , 等的方法是p1什么p2 middle

  3. 可以修改第一个脚本以实现第二个脚本的功能吗?

1个回答

“数据描述”文本中提供了有关数据集的详细信息。如果您愿意,每个数字确实是一个单独的病例或患者。将给出的数字视为患者 ID 号。因此编号为 0、2、3、5 等的患者在训练数据集中,编号为 1、13、15、27 等的患者在公共测试或验证数据集中。剩下的任何数字都在用于评分的私有测试数据集中。

对于每个患者,每个病例都有四种不同类型的 MRI 图像,即 Flair、T1W、T1Gd、T2。每个 MRI 由多个称为“切片”的图像组成,这些图像是每个文件夹中的几个图像(FLAIR、T1W、T1Gd、T2)。我的意思是 FLAIR 文件夹的图像集合是 FLAIR MRI 的组成部分。

“BraTS21ID”看起来像是对该出版物命名的研究本身的引用:“RSNA-ASNR-MICCAI BraTS 2021 脑肿瘤分割和放射基因组分类基准”。比赛大概就是基于这篇论文。

根据实现,我不确定在这个特定的 Kaggle 比赛中允许什么或需要什么,但一种简单的方法可能是使用 3D 卷积。我没有检查每个文件夹的详细信息,但通常 MRI 由几个“切片”组成,在一天结束时将它们放在一起(我的意思是像这样并排放置)以获得单个图像。您可以尝试对所有图像执行此操作,并且在一天结束时,将创建的每个最终图像彼此叠加以获得 3D 张量。

让我对这个过程更具体一点:我的主要目标是获得这种形式的最终图像。如果所有文件夹都包含 200 张图像,则降低此数字可能是个好主意。归根结底,我们希望将所有图像并排放置以获得单个 NxM 维图像,其中 N,M 表示每行、列中的小图像(切片)的数量。因此,例如,我们可以获得 5X5 图像——代表 MRI 类型之一的图像——例如 FLAIR——其中包含 25 个小图像。为了以这种方式减少图像的数量,可以简单地取每 8 个图像中每个像素值的平均值——因此编号为 1-8 的图像将形成单个图像,9-16 将形成另一个图像,依此类推。

我们可以继续对所有 4 种类型的 MRI 应用相同的程序。因此,对于每种 MRI 类型,我们最终得到 4 张最终图像,每张图像都有 5 行和 5 列较小的图像——我们取平均值的切片。我们现在可以将它们堆叠在一起以获得 3 维张量,它可以用作 3D 卷积的输入。