[切片]CT、MRI(Nii)的切片处理(转2D图像) + 代码

以下代码在这个环境下运行是正常的: 链接

本代码的功能:

  1. 原数据nii和分割nii分别同时切片
  2. 分割nii有多个标签时, 可以选择相应的标签进行切片,例如在BraTS_2018数据集(MRI)中的标签:0是背景、1是坏疽、2是浮肿、4是增强肿瘤区,可以设置代码中的LABEL_NUM值.
  3. 没有相应标签的切片会自动舍弃掉.

1、针对单独一个Nii的切片

# coding=gbk
import SimpleITK as sitk
import skimage.io as io
import sys, os 
import numpy as np

# 例子:BraTS_2018数据集(MRI)中的标签:0是背景、1是坏疽、2是浮肿、4是增强肿瘤区
# 选择标签值,输出相应的标签切片图
LABEL_NUM = 4

#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()

把nii放到文件同一级目录,然后直接运行指令: python 文件

2、针对多个Nii的切片

import SimpleITK as sitk
import skimage.io as io
import sys, os 
import numpy as np

# 例子:BraTS_2018数据集(MRI)中的标签:0是背景、1是坏疽、2是浮肿、4是增强肿瘤区
# 选择标签值,输出相应的标签切片图
LABEL_NUM = 4

#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()

至于文件和nii怎么分布,我的是这样放的:

[第一级]

[第二级]

[第三级]

 然后在第一级直接运行指令: python 文件

错误及解决

Non-UTF-8 code错误的解决办法:

导致错误的原因是程序中插入中文后的编码问题。

#coding=gbk

ValueError: Images of type float must be between -1 and 1.错误的解决办法: 链接

发布了52 篇原创文章 · 获赞 40 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_40519315/article/details/104626957