肺结节3D图像分割-VNet(一)

该文介绍了利用Yolo模型进行3D肺结节检测时对LUNA16数据集的处理,包括数据集介绍、.mhd和.raw文件解析、图像预处理步骤如坐标变换,以及如何将结节坐标转换为图像坐标并保存。同时,文章还提到了滤除不含结节图像的处理方法。
摘要由CSDN通过智能技术生成

近期用Yolo训练肺结节检测模型感觉缺少3D结构信息,尝试一下3D图像分割,博文用以记录。

1、LUNA16数据集

1.1 Luna16数据集介绍

简介:来自于公开的LIDC/IDRI数据集。该数据集剔除了LIDC/IDRI数据集中切片厚度大于2.5mm的扫描数据,共产生了888套CT。Luna16数据集中结节的判定标准为四名放射科专家中至少有三名认定该结节半径大于3mm。因此在数据集的注释中,非结节、半径小于3mm的结节和被1名或两名放射科专家认为是半径大于3mm的结节被认定为无关的发现。

1.2 所用数据

Luna16数据集:

点此跳转

subset0-subset10:10个zip文件中包含的所有的CT图像。

annotations.csv:包含1186个结节的注释。

LIDC/IDRI数据集:

点此跳转

LIDC-XML-only.zip:放射科医生注释/分割(XML 格式)

1.3  mhd文件和raw文件

subset0-10中每一个病例的CT扫描都给出了.mhd和.raw

.mhd文件包含了CT图像的基本信息,.raw文件用来储存CT的图像

1.4 annotations.csv文件

文件包含了各个CT中结节的世界坐标和半径

2、图像预处理

2.1 读取结节图像信息

从subset0-9中找到.mhd文件,读取图像相关信息

def read_data(mhd_file):       #读取图像数据,img, origin, spacing, flag
    with open(mhd_file) as f:
        mhd_data = f.readlines()
        for i in mhd_data:     
            if i.startswith('TransformMatrix'):
                tmp = i.split('=')[1]
                if tmp == '1 0 0 0 1 0 0 0 1\n':   #判断是否翻转
                    flag = True
                else:
                    flag = False
        itkimage = sitk.ReadImage(mhd_file)
        numpyImage = sitk.GetArrayFromImage(itkimage)   #从mhd读取raw,图像
        print("读取数据,读取的图片大小(zyx):",numpyImage.shape)
        origin = itkimage.GetOrigin()
        print("读取数据,读取的坐标原点(xyz):",origin)  #x,y,z
        spacing = itkimage.GetSpacing()
        print("读取数据,读取的像素间隔(xyz):",spacing)  #x,y,z
        return numpyImage, origin, spacing, flag

2.2 坐标变换

从annotations.csv文件读取到的坐标是世界坐标系下的坐标,我们需要将其转换为图像坐标系下的坐标,像素间隔为[1,1,1].

需要注意的是一张CT图像可能包含不止一个结节,我们需要将其全部遍历完才能遍历下一张图

annos_all_list = []           #读取到的原始坐标
    for i in range(len(annos)):
        if annos[i][0] == img_name:  
            annos_all_list.append(list(annos[i])) 
    print(annos_all_list)

读取到图像包含的所有结节后,将其进行坐标转换

    for annos_one_list in annos_all_list:       #其中一个结点
        print("annos_one_list:",annos_one_list) #世界坐标
        w_center = [annos_one_list[1], annos_one_list[2], annos_one_list[3]]  #世界坐标:[x,y,z]
        print("世界坐标:",w_center)
        #世界坐标 --> 图像坐标
        #(世界坐标中心 - 原点) / 像素间隔
        v_center = list(abs(w_center - np.array(origin)))#/np.array(spacing) 此处像素间隔为[1,1,1] 图像坐标:[x,y,z]
        if flag is False:  #图像翻转,拍CT时为俯拍,需转换为仰拍. 
            #img.shape(z,y,x)   v_center(x,y,z)
            v_center = [(img.shape[2]-1 - v_center[0]), (img.shape[1]-1 - v_center[1]), v_center[2]]    #z轴不需要翻转
        diam = annos_one_list[4]   #直径
        print("结节直径:",diam)

将转换后的结节坐标保存下来

one_annos = []
one_annos.append(v_center[0])  #图像坐标x
one_annos.append(v_center[1])  #图像坐标y
one_annos.append(v_center[2])  #图像坐标z
return_list.append(one_annos)
print("one_annos:",one_annos,"[坐标(x,y,z)]")

2.3 结节信息保存 

所有结节全部转换完后,将保存的数据保存输出至nodule_annos.xls文件

nodule_annos = pd.DataFrame(nodule_list)  # 把nodule_list转换成excel文件
nodule_annos.to_excel(nodule_annos_path)   #保存至指定路径

查看输出文件

 

2.4  滤除不含结节图像

def annos_clean():
    annos = pd.read_excel(nodule_annos_path)
    annos = annos.tolist()
    annos_c = []
    for i in annos:
        if i[2] != "[]":
            annos_c.append(i[1])
    return annos_c

肺结节图像分割是医学图像处理领域的一个重要研究方向,旨在从医学影像中自动地、准确地提取肺结节区域。其应用广泛,可以用于肺癌的早期检测、病变的定位和跟踪、手术前的诊断和治疗方案的制定等。 目前,常用的肺结节图像分割方法包括基于阈值的方法、基于区域生长的方法、基于边缘检测的方法、基于模型的方法和深度学习方法等。其中,深度学习方法由于其能够自动从数据中学习特征,已经成为肺结节图像分割领域的研究热点。 肺结节图像分割的难点主要有以下几个方面: 1. 影像质量不稳定:肺结节图像由于受到呼吸运动、噪声、分辨率等因素的影响,可能存在扭曲、模糊、噪声等问题,这会影响肺结节分割的准确性。 2. 结节形态多样性:肺结节的形态和大小各异,有些肺结节可能是有规律的球形或椭圆形,而有些则是不规则的形状,这也给分割带来了挑战。 3. 背景干扰:肺结节通常位于胸腔内部,周围可能存在一些与肺结节形态相似的结构,如肺血管、淋巴管等,这些结构容易被错误地识别为肺结节,从而干扰了肺结节分割。 4. 数据样本不足:由于肺结节是一种罕见的疾病,且采集真实的肺结节图像需要进行复杂的医学成像技术,因此数据集通常较小,这给深度学习算法的训练带来了挑战。 针对这些难点,研究者们正在不断探索和改进肺结节图像分割的方法,以提高其准确性和稳定性。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值