LIDC数据集XML标注信息的介绍+处理

LIDC数据集共有1012例数据(CT数据文件类型为Dicom),这里不讲Dicom的数据读取,只介绍XML标注文件及处理方法。

每例数据下面有两个文件夹,其中一个文件夹是侧面的CT(里面大概只有1-2个文件),一般不采用这个文件夹中的数据参与训练;另一个文件是肺尖——肺底方向的横向切片,为全肺切片。

文件夹中包含一个标注信息文件,(一般命名为 XXX.xml),XML中包含大量的标注信息。接下来对这部分标注信息进行介绍及给出相关处理代码。

标注信息包含三类:<unblindedReadNodule>, <unblindedReadNodule(small_nodules)>, <nonNodule>,其中第一类第二类(似乎)没有明确的区分。

第一类,大结节:在XML标注中读取"unblindedReadNodule"的Tag;读取"roi"的Tag;读取"imageSOP_UID" 得到切片信息,对应Dicom的SOPInstanceUID,读取"edgeMap"的Tag并读取其中的"xCoord"和"yCoord"的Tag,得到大结节Mask的横纵坐标。

第二类,小结节:与第一类的读取几乎完全一致,唯一区别在于xCoord和yCoord仅包含一个坐标(即整个Mask只包含一个坐标点)。但从可视化来看尽管结节较小,但一个坐标肯定无法包含整个小肺结节的Mask,这对分割任务是非常不利的,不清楚这个地方如何处理。

第三类,非肺结节:"nonNodule" Tag下的 "imageSOP_UID"和"locus"下的"xCoord"和"yCoord"。其中,非肺结节这一类标注的含义网上没有相关的参考。医学上没有“非肺结节”这一名词,正常理解没有肺结节的区域就是非肺结节区域,为何还需要“非肺结节”这一标注?经过可视化,我认为这一标注是给出“与肺结节特征极其相似但并非肺结节的区域”,也就相当于分割任务中的“困难样本”。这一标注可以省去深度学习训练时Hard Mining的难度。

拥有这些标注后就可以得到肺部区域的肺结节Mask,其中可以包含“非肺结节”信息。

处理代码:

大结节和小结节

import pydicom as dicom
import os
import cv2
import numpy as np
import lxml.etree as etree

def xml_reader(path):
    xmlns = '{http://www.nih.gov}'
    tree = etree.parse(path)    
    Res = tree.findall(xmlns + 'ResponseHeader')[0]
    if tree.findall(xmlns + 'readingSession')==[]: return {}
    i = tree.findall(xmlns + 'readingSession')[0]
    Nodules = []
    if i.findall(xmlns + 'unblindedReadNodule')==[]: return {}
    for j in i.findall(xmlns + 'unblindedReadNodule'):
        Nodule = []
        for k in j.findall(xmlns + 'roi'):
            roi = {}
            roi['imageSOP_UID'] = k.findall(xmlns + 'imageSOP_UID')[0].text
            roi['roi'] = []
            for l in k.findall(xmlns + 'edgeMap'):
                x = int(l.findall(xmlns + 'xCoord')[0].text)
                y = int(l.findall(xmlns + 'yCoord')[0].text)
                roi['roi'].append([x,y])
            Nodule.append(roi)
        Nodules.append(Nodule)
    return Nodules

非肺结节:

from xml.dom.minidom import parse

def parseXML(xml_path):
    non_nodules_coor = {}
    domTree = parse(xml_path)
    # print(domTree)  # <xml.dom.minidom.Document object at 0x0000000003FD4E88>
    # print(type(domTree))  # <class 'xml.dom.minidom.Document'>
    # 文档根元素
    rootNode = domTree.documentElement
    print(rootNode.nodeName)  # LidcReadMessage
    # 所有医生标注
    readingSessions = rootNode.getElementsByTagName("readingSession")
    # print(readingSessions)
    for rS in readingSessions:
        non_nodules = rS.getElementsByTagName("nonNodule")
        # 解析非结节
        for non_nodule in non_nodules:
            #this_dict = {}
            Z_w = non_nodule.getElementsByTagName("imageSOP_UID")[0].childNodes[0].data
            locus = non_nodule.getElementsByTagName("locus")[0]
            X_v = locus.getElementsByTagName("xCoord")[0].childNodes[0].data
            Y_v = locus.getElementsByTagName("yCoord")[0].childNodes[0].data
            non_nodules_coor[Z_w] = [X_v,Y_v]
            # coor = (int(X_v), int(Y_v), float(Z_w))
            # if coor not in non_nodules_coor:
            #     non_nodules_coor.append(coor)
            #non_nodules_coor.append(this_dict)
    print(r"Finish ", xml_path)
    return non_nodules_coor

参考博客:

LIDC数据集由xml提取小结节和非结节_dreamandgo的博客-CSDN博客

LIDC-IDRI数据集的dicom文件XML标注读取_qq_782808845的博客-CSDN博客

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值