[切片]医学三维数据且又单模态单标签的切片处理

本文介绍了一种处理三维医学影像数据的方法,通过切片处理将数据适配于二维网络,特别关注了标签筛选与数据增强。文章详细解释了如何通过设定标签值来选择并输出特定的图像切片,并提供了代码实现,包括CT对比度调整和数据归一化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

医学数据常常都是三维的,但是如果网络是2D的网络,需要将数据进行切片处理,才能适应网络

另外,本代码只适用于单模态、单标签时的处理,处理后的结果为图片格式(如png、jpg等)

⚠️如果你的数据集是多模态、多标签一般不是这么处理,需要将数据合并成多通道数据,通常保存为npy格式,具体可以参考:链接

 

本代码的功能:

  1. 设置代码中的LABEL_NUM值选择标签值,输出相应的标签切片图
  2. 没有相应标签的切片会自动舍弃掉,缓解训练过程中的我类别不均衡问题.
  3. 若是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.错误的解决办法: 链接

 

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玖零猴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值