읽은 3D 데이터의 크기가 (75, 512,512)이고 간격이 (0.703125, 0.703125, 5.0) (x, y, z)라고 가정하면 z 축의 간격을 1mm로 조정해야 하므로 먼저 실제 3D 데이터의 크기를 계산합니다 . 즉, 현재 3D 데이터 크기 = (375/1, 360/1, 360/1) = (375, 360, 360) 즉, 간격은 (0.703125, 0.703125, 5.0)이고 읽어온 3D 데이터 크기는 (75, 512,512). 간격이 (1, 1, 1)일 때 읽어들인 3D 데이터의 크기는 (375, 360, 360)이고 실제 3D 데이터의 크기는 그대로 유지되어 (375, 360) , 360)mm. 예를 들어 다운샘플링 후 판독된 3D 데이터를 다운샘플링하면 크기는 (375, 256, 256) 이고 간격은 (375 / 375 , 360 / 256, 360 / 256) ~ (1.40625)여야 합니다. , 1.40625, 1) 위의 내용은 계산 수준이며 코드 수준이 없습니다 너무 번거롭습니다: 3D 데이터를 리샘플링하고 다운샘플링하고 이를 완료하는 데 한 문장만 있으면 됩니다 . 입력 ct 이미지는 (75, 512, 512)이고 간격은 (0.703125, 0.703125, 5.0)입니다 z축 간격을 1mm로 조정하고 이미지를 256*256으로 다운샘플링합니다. . 1. ct의 간격 얻기, ÷ 원하는 간격, ct.GetSpaing()[-1] / 1 2. 다운샘플링 속도 얻기, down_scale = 512 / 256 execute ct_array = ndimage.zoom(ct_array, (ct.GetSpaing ()[-1] / 1, down_scale, down_scale)) 위의 문장 크기를 실행하면 (75 * 5 / 1, 256, 256) = (375, 256, 256) 이 때 원하는 크기가 됩니다. , z축의 간격은 1mm가 되었고, 간격은 (375/375, 360/256,360/256) = (1.40625, 1.40625, 1) 다음으로 이미지에 대해 슬라이싱과 같은 다른 전처리 작업을 수행합니다 . 등. new_ct_array = 슬라이스 (ct_array) new_ct = sitk.GetArrayFromImage(new_ct_array) sitk.GetArrayFromImage를 실행하면 간격이 기본적으로 (1,1,1)로 설정됩니다(아직 이유는 모르겠습니다). new_ct는 ( 1.40625, 1.40625, 1) new_ct.SetSpacing((1.40625, 1.40625, 1)) 으로 설정되어야 합니다.
이렇게 하면 전처리가 완료됩니다.
lits 챌린지의 전처리 코드는 이해를 돕기 위해 아래에 첨부합니다.
"""
获取可用于训练网络的训练数据集
需要四十分钟左右,产生的训练数据大小3G左右
"""
import os
import sys
sys.path.append(os.path.split(sys.path[0])[0])
import shutil
from time import time
import numpy as np
from tqdm import tqdm
import SimpleITK as sitk
import scipy.ndimage as ndimage
import lits_para as para
if os.path.exists(para.training_set_path):
shutil.rmtree(para.training_set_path)
new_ct_path = os.path.join(para.training_set_path, 'imgae')
new_seg_dir = os.path.join(para.training_set_path, 'label')
# os.mkdir(para.training_set_path)
# os.mkdir(new_ct_path)
# os.mkdir(new_seg_dir)
start = time()
os.listdir()
patients = os.listdir(para.train_ct_path)
patients.sort(key=lambda x:int(x.split('.')[0].split('-')[-1]))
for i in tqdm(range(len(patients))):
# 将CT和金标准入读内存
ct = sitk.ReadImage(os.path.join(para.train_ct_path, patients[i]), sitk.sitkInt16)
ct_array = sitk.GetArrayFromImage(ct)
seg = sitk.ReadImage(os.path.join(para.train_seg_path, patients[i].replace('volume', 'segmentation')), sitk.sitkUInt8)
seg_array = sitk.GetArrayFromImage(seg)
# 将金标准中肝脏和肝肿瘤的标签融合为一个
seg_array[seg_array > 0] = 1
# 将灰度值在阈值之外的截断掉
# print(ct_array.max())
# print(ct_array.min())
# ct_array[ct_array > para.upper] = para.upper
# ct_array[ct_array < para.lower] = para.lower
# 对CT数据在横断面上进行降采样,并进行重采样,将所有数据的z轴的spacing调整到1mm
print(ct.GetSpacing())
# ct(0.703125, 0.703125, 5.0)
print(ct.GetSpacing()[-1] / para.slice_thickness, para.down_scale, para.down_scale)
# 5.0 0.5 0.5
ct_array = ndimage.zoom(ct_array, (ct.GetSpacing()[-1] / para.slice_thickness, para.down_scale, para.down_scale), order=3)
seg_array = ndimage.zoom(seg_array, (ct.GetSpacing()[-1] / para.slice_thickness, para.down_scale, para.down_scale), order=0)
# ct_array size从(75,512,512)->(375,256,256)
# 其他操作
# 找到肝脏区域开始和结束的slice,并各向外扩张slice
z = np.any(seg_array, axis=(1, 2))
start_slice, end_slice = np.where(z)[0][[0, -1]]
# 两个方向上各扩张slice
start_slice = max(0, start_slice - para.expand_slice)
end_slice = min(seg_array.shape[0] - 1, end_slice + para.expand_slice)
# 如果这时候剩下的slice数量不足size,直接放弃该数据,这样的数据很少,所以不用担心
if end_slice - start_slice + 1 < para.size:
print('!!!!!!!!!!!!!!!!')
print(patients[i], 'have too little slice', ct_array.shape[0])
print('!!!!!!!!!!!!!!!!')
continue
ct_array = ct_array[start_slice:end_slice + 1, :, :]
seg_array = seg_array[start_slice:end_slice + 1, :, :]
# 最终将数据保存为nii.gz
new_ct = sitk.GetImageFromArray(ct_array)
new_ct.SetDirection(ct.GetDirection())
new_ct.SetOrigin(ct.GetOrigin())
print((ct.GetSpacing()[0] * int(1 / para.down_scale), ct.GetSpacing()[1] * int(1 / para.down_scale), para.slice_thickness))
# (1.40625, 1.40625, 1)
# 最后调整好spacing
new_ct.SetSpacing((ct.GetSpacing()[0] * int(1 / para.down_scale), ct.GetSpacing()[1] * int(1 / para.down_scale), para.slice_thickness))
new_seg = sitk.GetImageFromArray(seg_array)
new_seg.SetDirection(ct.GetDirection())
new_seg.SetOrigin(ct.GetOrigin())
new_seg.SetSpacing((ct.GetSpacing()[0], ct.GetSpacing()[1], para.slice_thickness))
sitk.WriteImage(new_ct, os.path.join(new_ct_path, 'volume-' + str(i) + '.nii.gz'))
sitk.WriteImage(new_seg, os.path.join(new_seg_dir, 'segmentation-' + str(i) + '.nii.gz'))