首页 > 其他分享 >LiTS 数据集预处理(一) 肝脏肿瘤图像分割

LiTS 数据集预处理(一) 肝脏肿瘤图像分割

时间:2024-11-12 16:45:40浏览次数:3  
标签:slice 掩膜 array mask LiTS path 肝脏 预处理 ct

前言

最近在学习Unet等家族做肝脏肿瘤分割,肝脏肿瘤公开数据集有出名的(全球人都在研究的)LITS数据集,从网上下载下来的时候,格式是nii文件。
因为我是学习的2D模型训练,所以我需要对nii格式文件进行切片,经过研究学习网上几份代码,发现其中还有有点讲究的,所以想写篇文章分享介绍一下。
如果有对训练更有利的预处理方法,欢迎评论区讨论
在这里插入图片描述

目标:

  • 对nii文件切片成为npy格式
  • 数据集转换成png格式,方便自己查看或者验证
  • 对肝脏和肿瘤数据集进行分离,方便单独进行训练

先介绍一下代码的主处理逻辑:

  • 遍历CT图像文件,读取CT图像和相应的掩膜。
  • 对CT图像进行阈值处理,限制像素值在[-200, 200]之间,并进行归一化。
  • 找到肝脏区域的起始和结束切片,并进行扩展。
  • 裁剪CT图像和掩膜到指定大小(448x448)。
  • 对每个切片进行处理,检查掩膜中是否有病灶(即是否有非零值),如果有,则保存CT图像和掩膜为NumPy数组。

代码

代码的主要功能是从CT图像和相应的分割掩膜中提取训练集,并将处理后的图像和掩膜保存为NumPy数组格式。

'''
    Func:制作训练集
'''

import os
import numpy as np
import SimpleITK as sitk
from tqdm import tqdm
import cv2

ct_name = ".nii"
mask_name = ".nii"

ct_path = 'F:\datesate\datasetnii\image'
seg_path = 'F:\datesate\datasetnii\label'
png_path = './png/'

outputImg_path = "E:/seg_example/data/trainImage_k1_1217"
outputMask_path = "E:/seg_example/data/trainMask_k1_1217"

if not os.path.exists(outputImg_path):
    os.mkdir(outputImg_path)
if not os.path.exists(outputMask_path):
    os.mkdir(outputMask_path)

#遍历给定目录,根据参数返回子目录列表或文件列表。
def file_name_path(file_dir, dir=True, file=False):
    """
    get root path,sub_dirs,all_sub_files
    :param file_dir:
    :return: dir or file
    """
    for root, dirs, files in os.walk(file_dir):
        if len(dirs) and dir:
            print("sub_dirs:", dirs)
            return dirs
        if len(files) and file:
            print("files:", files)
            return files

#从图像中心裁剪出指定大小的区域。
def crop_ceter(img, croph, cropw):
    #for n_slice in range(img.shape[0]):
    height, width = img[0].shape
    starth = height//2 - (croph//2)
    startw = width//2 - (cropw//2)
    return img[:, starth:starth+croph, startw:startw+cropw]

if __name__ == "__main__":

    for index, file in enumerate(tqdm(os.listdir(ct_path))):

        # 获取CT图像及Mask数据   指定了读取 CT 图像时使用 16 位有符号整数类型来存储像素值。
        ct_src = sitk.ReadImage(os.path.join(ct_path, file), sitk.sitkInt16)
        mask = sitk.ReadImage(os.path.join(seg_path, file.replace('volume', 'segmentation')), sitk.sitkUInt8)
        # GetArrayFromImage()可用于将SimpleITK对象转换为ndarray
        ct_array = sitk.GetArrayFromImage(ct_src)
        mask_array = sitk.GetArrayFromImage(mask)

        # mask_array[mask_array == 1] = 0  # 肿瘤
        # mask_array[mask_array == 2] = 1

        # 阈值截取
        ct_array[ct_array > 200] = 200
        ct_array[ct_array < -200] = -200

        ct_array = ct_array.astype(np.float32)
        ct_array = ct_array / 200

        # 找到肝脏区域开始和结束的slice,并各向外扩张slice
        z = np.any(mask_array, axis=(1, 2))
        start_slice, end_slice = np.where(z)[0][[0, -1]]

        print('cs',start_slice,end_slice,file)
        start_slice = max(0, start_slice - 1)
        end_slice = min(mask_array.shape[0] - 1, end_slice + 2)

        ct_crop = ct_array[start_slice:end_slice, :, :]
        mask_crop = mask_array[start_slice+1:end_slice-1, :, :]

        #裁剪(偶数才行) 448*448
        ct_crop = ct_crop[:,32:480,32:480]
        mask_crop = mask_crop[:,32:480,32:480]

        print('ct_crop.shape',ct_crop.shape)

        # 切片处理,并去掉没有病灶的切片
        if int(np.sum(mask_crop))!=0:
            for n_slice in range(mask_crop.shape[0]):
                maskImg = mask_crop[n_slice, :, :]
                ctImageArray = np.zeros((ct_crop.shape[1], ct_crop.shape[2], 3), np.float32)
                ctImageArray[:, :, 0] = ct_crop[n_slice , :, :]
                ctImageArray[:, :, 1] = ct_crop[n_slice + 1, :, :]
                ctImageArray[:, :, 2] = ct_crop[n_slice + 2, :, :]

                imagepath = outputImg_path + "/" + str(index+1) + "_" + str(n_slice) + ".npy"
                maskpath = outputMask_path + "/" + str(index+1) + "_" + str(n_slice) + ".npy"
                    
                np.save(imagepath, ctImageArray)  # (448,448,3) np.float dtype('float64')
                np.save(maskpath, maskImg)  # (448,448) dtype('uint8') 值为0 1 2
        else:
            continue
    print("Done!")

代码运行过程

你可能有一些疑问

  • 是数据集是怎么区分肝脏和肿瘤的

  • 读取CT图像和相应的掩膜 如何找到对应的掩膜的

  • 对CT图像进行阈值处理,限制像素值在[-200, 200]之间,并进行归一化。 必须要归一化吗

  • 找到肝脏区域的起始和结束切片,并进行扩展。 这个是有必要的吗 是如何做到找到这个肝脏区域

  • 对每个切片进行处理,检查掩膜中是否有病灶(即是否有非零值),如果有,则保存CT图像和掩膜为NumPy数组。 这个病灶是指肿瘤吗?那没有病灶的图像就不保存了吗 如果保存 对最后训练的数据集准确度会不会有提升?

  • 如果我每个切片都输出固定的图片 不去掉没有病灶区域的图片 这样处理效率会不会高一点(对纯黑色图进行训练,我认为没有什么意义,不利于训练效率)

我的理解和 AI的回答:

  1. 数据集是怎么区分肝脏和肿瘤的
    • 在LiTS数据集中,CT图像的分割掩膜(mask)通常是由医学专家手动标注的。掩膜中每个像素的值代表不同的结构或区域,例如肝脏、肿瘤或背景。通常,肝脏区域会被标记为1,肿瘤区域会被标记为2,背景则为0。通过这种方式,模型可以学习到肝脏和肿瘤的特征。
  2. 如何找到对应的掩膜
    • 在代码中,掩膜是通过将CT图像文件名中的“volume”替换为“segmentation”来找到的。例如,如果CT图像的文件名是volume_01.nii,那么对应的掩膜文件名将是segmentation_01.nii。这样可以确保CT图像和掩膜之间的对应关系。
  3. 阈值处理和归一化的必要性
    • 阈值处理是为了去除CT图像中不必要的噪声和极端值,确保图像的像素值在一个合理的范围内。归一化是将像素值缩放到[0, 1]的范围,这样可以提高模型训练的稳定性和收敛速度。虽然不是绝对必要,但通常是一个良好的实践,尤其是在深度学习中。
  4. 找到肝脏区域的起始和结束切片的必要性
    • 找到肝脏区域的起始和结束切片是为了确保只处理包含肝脏的切片,避免处理无关的背景切片。这可以减少计算量并提高模型的训练效率。通过检查掩膜数组中是否有非零值,可以确定肝脏区域的起始和结束切片。
  5. 病灶的定义和保存策略
    • 在这里,病灶通常指的是肿瘤。如果掩膜中有非零值(即存在肿瘤或肝脏区域),则认为该切片是有病灶的。代码中只保存有病灶的切片是为了确保训练数据集中包含有用的信息。保存没有病灶的图像可能会导致模型学习到无关的特征,从而降低模型的准确性。因此,通常建议只保留有病灶的切片,以提高训练数据集的质量和模型的准确度。

到这里npy格式的切片文件已经完成,可以拿去训练了。
在这里插入图片描述

剩下两个目标,点赞后面会更新

  • 肝脏肿瘤分离

  • npy2png格式转换

标签:slice,掩膜,array,mask,LiTS,path,肝脏,预处理,ct
From: https://blog.csdn.net/qq_63860529/article/details/143713695

相关文章

  • 【C Language Program】预处理指令
    学习目标:掌握C语言的预处理指令以及使用学习步骤:预处理指令的概括预处理指令的使用总结主要内容:预处理指令的概括含义指令导入模块#include宏定义#define#undef条件编译#if#else#elif#endif条件定义#ifdef#ifndef预处理指令的使用#include#include用于在......
  • 医学图像分割综述(肝脏等器官与肿瘤的分割)——组会必备
    制作了一个思维脑图,下面的MakeDown格式的,脑图会截图发在下面,也可以找我要源文件。医学图像分割综述参考论文MedicalImageSegmentationUsingDeepLearning:ASurveySubmittedon28Sep2020(v1),lastrevised22Dec2021(thisversion,v3)]对基于深度学习......
  • (21-3)基于深度强化学习的量化交易策略(OpenAI Baselines +FinRL+DRL+PyPortfolioOpt):数据
    21.6 数据预处理数据预处理是训练高质量机器学习模型的关键步骤,在这一步需要检查缺失数据并进行特征工程,以将数据转换为适合模型训练的状态。本项目的数据预处理江湾城以下工作:添加技术指标:在实际交易中,需要考虑各种信息,例如历史股价、当前持仓股票、技术指标等。本文演示......
  • LitServe 服务多worker启动简单说明
    LitServe是一个基于fastapi包装的快速推理api服务,以下只简单说明下关于server启动部分的处理参考使用我们可以通过配置devices以及每个device对应的worker数执行以那种模式进行server的启动(多线程还是多进程)参考使用if__name__=="__main__":#EnabletheOp......
  • 虚假新闻检测:CSV格式数据集的预处理与模型选择
    ✅作者简介:2022年博客新星第八。热爱国学的Java后端开发者,修心和技术同步精进。......
  • LitServe 快速部署类openai 接口服务
    以前简单说明过LitServe支持openai接口格式的服务api,以下是一个简单试用参考代码app.pyimportlitserveaslsclassSimpleLitAPI(ls.LitAPI):defsetup(self,device):self.model=Nonedefpredict(self,prompt):#`prompt`isalisto......
  • opencv保姆级讲解——图像预处理(3)
    图像滤波所为图像滤波通过滤波器得到另一个图像什么是滤波器在深度学习中,滤波器又称为卷积核,滤波的过程成为卷积卷积核概念卷积核大小,一般为奇数,如3*35*57*7为什么卷积核大小是奇数?原因是:保证锚点在中间,防止位置发生偏移的原因卷积核大小的影响在深度学习中,卷积......
  • 基于Open-CV的多四边形检测方案(一):图像预处理与霍夫变换
    目录一、设计目标二、工作流程三、图像预处理与霍夫变换一、设计目标对于一个含有多个相邻四边形的图片,可以定位出其中每一个四边形的顶点。典型的案例如一个围棋棋盘,可以定位出所有的格子的点。软件工具:Python==3.9opencv-python==4.10.0.84numpy==1.22.4二......
  • opencv 图像预处理(一) python笔记
    图像预处理​在计算机视觉和图像处理领域,图像预处理是一个重要的步骤,它能够提高后续处理(如特征提取、目标检测等)的准确性和效率。OpenCV提供了许多图像预处理的函数和方法,以下是一些常见的图像预处理操作:图像空间转换图像大小调整图像仿射变换图像翻转图像裁剪图像二值......
  • Python数据分析NumPy和pandas(二十、数据清洗和预处理之二:数据转换)
    在数据分析和建模过程中,处理缺失数据很重要,另外对于数据的筛选、清理和转换同样很重要。一、删除重复数据删除重复的行。DataFrame的方法duplicated()返回一个布尔序列,判断每一行是否重复(其列值与前一行中的列值完全相等则为重复)。另一个方法drop_duplicates()返回一个去......