使用MONAI加载图片并构成DataSet、DataLoader
在处理医学数据时,最先遇到的问题就是如何加载数据,与普通的图片文件不同,医学影像数据集中提供的文件格式一般是.nii.gz格式的文件,使用MONAI可以很简单的加载这些文件,这里只记录自用的一种方式。
具体的问题
我使用的数据集是kit19,目录结构是case_??? > image.nii.gz & segmentation.nii.gz
具体思路
- 在网络要求输入三维数据时(代码中对应 datatype = “whole”)
构成path字典,直接由文件位置生成Dataset - 在网络要求输入二维数据时(代码中对应 datatype = “slice”)
构成path字典,取出对应位置的三维数据后,对数据进行切片、采样,由二维数据list生成Dataset
其不同点在于monai.transforms.LoadImaged()方法后需不需要对载入的数据进行个性化处理
import monai.transforms
import os
from monai import transforms
import logging
"""
利用MONAI加载.nii.gz格式的图片,并对图片进行预处理,并直接形成Dataset、DataLoader
"""
def get_dataloader(endindex, dataset_path, datatype="whole", startindex=1):
logging.info("loading data")
root_path = os.path.join(dataset_path)
# 构建样本地址字典 将数据用
# [{
# "image":f"{Image_Path}",
# "label":f"{Label_Path}"
# },]
# 的方式存储下来,这里仅展示数据单元的格式
samples_path = []
for i in range(startindex - 1, endindex):
sample_path = {}
imagefilename = 'case_' + str(i).zfill(5)
img_path = os.path.join(root_path, imagefilename, 'imaging.nii.gz')
seg_path = os.path.join(root_path, imagefilename, 'segmentation.nii.gz')
sample_path['image'] = img_path.replace('\\', '/')
sample_path['label'] = seg_path.replace('\\', '/')
samples_path.append(sample_path)
if datatype == "whole":
# 构建transform,在使用MONAI生成Dataset的时候作为参数传入
transform = transforms.Compose([
transforms.LoadImaged(keys=("image", "label")), # 由地址字符串到图片格式的必要transform
transforms.EnsureChannelFirstd(keys=['image', 'label']), # 确保通道在最前面,在加载数据为CT形式的时候最常用,实际作用为在1维上创建一个维度
# 原图像的大小为D H W
transforms.Resized(keys=['image', 'label'], spatial_size=(256, 256, 256)), # 重设图片大小,等比例放大(不是裁切!)
transforms.ToMetaTensord(keys=('image', 'label')) # 转换为Tensor格式
])
# 加载dataset
dataset = monai.data.Dataset(samples_path, transform=transform)
dataloader = monai.data.DataLoader(dataset, batch_size=4, shuffle=True, num_workers=4)
return dataloader
elif datatype == "slice":
samples_slice = [] # 片状样本的list
counter = 0
# 对所有地址的数据进行处理
for i in range(0, len(samples_path)):
counter += 1
logging.info(f"loading {counter}th data")
# 加载体数据
sample = transforms.LoadImaged(keys=("image", "label"))(samples_path[i])
deep = sample["image"].shape[0] # DHW
# 分解体数据
for j in range(0, deep, 10):
sample_slice = {} # 片状样本
sample_slice["image"] = sample["image"][j]
sample_slice["label"] = sample["label"][j]
samples_slice.append(sample_slice)
# 准备 transform
transform = transforms.Compose([
# 确保通道在最前面,在加载数据为CT形式的时候最常用,实际作用为在1维上创建一个维度
transforms.EnsureChannelFirstd(keys=['image', 'label']),
# 原图像的大小为D H W
transforms.Resized(keys=['image', 'label'], spatial_size=(256, 256)), # 重设图片大小,等比例放大(不是裁切!)
transforms.ToMetaTensord(keys=('image', 'label')) # 转换为Tensor格式
])
dataset = monai.data.Dataset(samples_slice, transform=transform)
dataloader = monai.data.DataLoader(dataset, batch_size=16, shuffle=True, num_workers=4, drop_last=True)
return dataloader
else:
logging.debug("no such datatype!")