医学数据常常都是三维的,但是如果网络是2D的网络,需要将数据进行切片处理,才能适应网络
另外,本代码只适用于单模态、单标签时的处理,处理后的结果为图片格式(如png、jpg等)
⚠️如果你的数据集是多模态、多标签一般不是这么处理,需要将数据合并成多通道数据,通常保存为npy格式,具体可以参考:链接
本代码的功能:
- 设置代码中的LABEL_NUM值选择标签值,输出相应的标签切片图
- 没有相应标签的切片会自动舍弃掉,缓解训练过程中的我类别不均衡问题.
- 若是CT,可以加窗调节对比度
1、针对单独一个Nii的切片
# coding=gbk
import SimpleITK as sitk
import skimage.io as io
import sys, os
import numpy as np
# 选择标签值,输出相应的标签切片图
LABEL_NUM = 1
#CT 加窗调对比度(hu值)
IF_WINDOWS = 0 #0是不加窗 ; 1 是加窗
WINDOW_WEIGHT = 325
WINDOW_LONGTH = 40
#图片输出路径及格式
IMAGE_OUT_PATH = './Image'
IMAGE_OUT_FORMAT = '.png'
LABEL_OUT_PATH = './Label'
LABEL_OUT_FORMAT = '.png'
np.set_printoptions(threshold=np.inf)
def read_img(path):
img = sitk.ReadImage(path)
data = sitk.GetArrayFromImage(img)
return data
def find_label_image(label_data, all_one_array,torch_CT):
index = -1
for i in range(label_data.shape[0]): #遍历所有切片
true_sum = np.sum(label_data[i] == LABEL_NUM*all_one_array[i]) # 找到有标签为label_lum的切片。
if true_sum > 0: # 没有打该标签的不切片,避免类别不平衡问题。
index+=1
file_dir1=os.path.join(LABEL_OUT_PATH,str(index) + LABEL_OUT_FORMAT) #标签图片的路径
file_dir2=os.path.join(IMAGE_OUT_PATH,str(index) + IMAGE_OUT_FORMAT) #数据图片的路径
print(i)
#二值化label
label_img = np.zeros(label_data[i].shape,dtype=np.uint8)
for x in range(label_img.shape[0]):
for y in range(label_img.shape[1]):
if label_data[i][x,y] == LABEL_NUM:
label_img[x,y] = 255;
#归一化image到[0,1]范围内,否则无法io.imsave(报错:Images of type float must be between -1 and 1)
a = 0
b = 1
Ymax = np.max(torch_CT[i])
Ymin = np.min(torch_CT[i])
k = (b - a) / (Ymax - Ymin)
norY = a + k * (torch_CT[i] - Ymin)
#保存带有label的image.png
io.imsave(file_dir1, label_img)
io.imsave(file_dir2, norY)
print("done!")
#Image图片的转换
def _img_transfor(itk):
img_arr = sitk.GetArrayFromImage(itk).astype(np.float32)
#img_arr = sitk.GetArrayFromImage(itk).astype(np.uint8)
#CT是否加窗
if IF_WINDOWS:
img_arr = window_normalize(img_arr, WW=325, WL=40)
return img_arr
def window_normalize(img, WW, WL, dst_range=(0, 1)):
"""
WW: window width
WL: window level
dst_range: normalization range
"""
src_min = WL - WW/2
src_max = WL + WW/2
outputs = (img - src_min)/WW * (dst_range[1] - dst_range[0]) + dst_range[0]
outputs[img >= src_max] = 1
outputs[img <= src_min] = 0
return outputs
def main():
#判断输出路径是否存在,若不存在创建一个目录
if not os.path.exists(IMAGE_OUT_PATH):
os.mkdir(IMAGE_OUT_PATH)
if not os.path.exists(LABEL_OUT_PATH):
os.mkdir(LABEL_OUT_PATH)
#单个nii的路径
train_filename = 'Brats18_2013_2_1_t2.nii.gz'
label_filename = 'Brats18_2013_2_1_seg.nii.gz'
label_data = read_img(label_filename)
#torch_CT = read_img(train_filename)
itk_CT = sitk.ReadImage(train_filename)
torch_CT = _img_transfor(itk_CT)
#生成与label维度一样的array,且元素都为1.
like_label_one_array = np.ones_like(label_data)
find_label_image(label_data, like_label_one_array,torch_CT)
if __name__ == "__main__":
main()
2、针对多个Nii的切片
import SimpleITK as sitk
import skimage.io as io
import sys, os
import numpy as np
# 选择标签值,输出相应的标签切片图
LABEL_NUM = 1
#CT 加窗调对比度(hu值)
IF_WINDOWS = 0 #0是不加窗 ; 1 是加窗
WINDOW_WEIGHT = 325
WINDOW_LONGTH = 40
#nii路径
NII_IN_DIR_PATH = './HGG'
#NII_IMAGES_IN_DIR_PATH = './HGG'
#NII_LABELS_IN_DIR_PATH = './HGG'
#图片输出路径
IMAGE_OUT_PATH = './Image'
LABEL_OUT_PATH = './Label'
np.set_printoptions(threshold=np.inf)
#index = -1
def read_img(path):
img = sitk.ReadImage(path)
data = sitk.GetArrayFromImage(img)
return data
def find_label_image(label_data, all_one_array,torch_CT, niidir_one):
index = -1
for i in range(label_data.shape[0]): #遍历所有切片
true_sum = np.sum(label_data[i] == LABEL_NUM*all_one_array[i]) # 找到有标签为label_lum的切片。
if true_sum > 0: # 没有打该标签的不生成图片,避免类别不平衡问题。
index+=1
file_dir1=os.path.join(LABEL_OUT_PATH,niidir_one + '_' + str(index) + '.png') #标签图片的路径
file_dir2=os.path.join(IMAGE_OUT_PATH,niidir_one + '_' + str(index) + '.png') #数据图片的路径
print(i)
#二值化label
label_img = np.zeros(label_data[i].shape,dtype=np.uint8)
for x in range(label_img.shape[0]):
for y in range(label_img.shape[1]):
if label_data[i][x,y] == LABEL_NUM:
label_img[x,y] = 255;
#归一化image到[0,1]范围内,否则无法io.imsave(报错:Images of type float must be between -1 and 1)
a = 0
b = 1
Ymax = np.max(torch_CT[i])
Ymin = np.min(torch_CT[i])
k = (b - a) / (Ymax - Ymin)
norY = a + k * (torch_CT[i] - Ymin)
#保存带有label的image.png
io.imsave(file_dir1, label_img)
io.imsave(file_dir2, norY)
def _img_transfor(itk):
img_arr = sitk.GetArrayFromImage(itk).astype(np.float32)
if IF_WINDOWS:
img_arr = window_normalize(img_arr, WW=325, WL=40)
# torch_itk = torch.from_numpy(img_arr)
return img_arr
def window_normalize(img, WW, WL, dst_range=(0, 1)):
"""
WW: window width
WL: window level
dst_range: normalization range
"""
src_min = WL - WW/2
src_max = WL + WW/2
outputs = (img - src_min)/WW * (dst_range[1] - dst_range[0]) + dst_range[0]
outputs[img >= src_max] = 1
outputs[img <= src_min] = 0
return outputs
def main():
#判断是否有输入数据目录,没有则报错
assert os.path.exists(NII_IN_DIR_PATH)
#判断输出路径是否存在,若不存在,则创建一个目录
if not os.path.exists(IMAGE_OUT_PATH):
os.mkdir(IMAGE_OUT_PATH)
if not os.path.exists(LABEL_OUT_PATH):
os.mkdir(LABEL_OUT_PATH)
#遍历所有样例
niidir_list = os.listdir(NII_IN_DIR_PATH) #获取子文件(包括目录)
print (niidir_list)
niidir_list_len = len(niidir_list) #获取子文件(包括目录)的数量
niidir_list_count = 0
for niidir_one in niidir_list:
nii_label_path = NII_IN_DIR_PATH + '/' + niidir_one + '/' + niidir_one +'_seg.nii.gz'
nii_image_path = NII_IN_DIR_PATH + '/' + niidir_one + '/' + niidir_one +'_t2.nii.gz'
label_filename = nii_label_path
train_filename = nii_image_path
label_data = read_img(label_filename)
train_data = read_img(train_filename)
# 生成与label维度一样的array,且元素都为1.
like_label_one_array = np.ones_like(label_data)
itk_gt = sitk.ReadImage(label_filename)
itk_CT = sitk.ReadImage(train_filename)
torch_CT = _img_transfor(itk_CT)
find_label_image(label_data, like_label_one_array, torch_CT, niidir_one)
if __name__ == "__main__":
main()
错误及解决
Non-UTF-8 code错误的解决办法:
导致错误的原因是程序中插入中文后的编码问题。
#coding=gbk
ValueError: Images of type float must be between -1 and 1.错误的解决办法: 链接