训练数据源为LIDC-IDRI,该数据集由胸部医学图像文件(如CT、X光片)和对应的诊断结果病变标注组成。该数据是由美国国家癌症研究所(National Cancer Institute)发起收集的,目的是为了研究高危人群早期癌症检测。
该数据集中,共收录了1018个研究实例。对于每个实例中的图像,都由4位经验丰富的胸部放射科医师进行两阶段的诊断标注。在第一阶段,每位医师分别独立诊断并标注病患位置,其中会标注三中类别:1) >=3mm的结节, 2) <3mm的结节, 3) >=3mm的非结节。在随后的第二阶段中,各位医师都分别独立的复审其他三位医师的标注,并给出自己最终的诊断结果。这样的两阶段标注可以在避免forced consensus的前提下,尽可能完整的标注所有结果。
文件位置: LIDC-IDRI -> lidc-idri nodule counts (6-23-2015).xlsx
文件位置: LIDC-IDRI -> tcia-diagnosis-data-2012-04-20.xls
图像文件为Dicom格式,是医疗图像的标准格式,其中除了图像像素外,还有一些辅助的元数据如图像类型、图像时间等信息。 一张CT图像有 512x512 个像素点,在dicom文件中每个像素由2字节表示,所以每张图片约512KB大小。图像中每个像素都是整数,专业名称为 Hounsfield scale 或 CT Number,是描述物质的放射密度的量化值(参考Wikipedia)。下表为常见物质的HU值。
由于图片为单通道,画图渲染出来为黑白图,放射密度越高的位置越亮。
除了像素图以外,元数据中有一些其它主要Tag (参考DICOM的常用Tag分类和说明)
在LIDC-IDRI上面可以直接网页上搜索图像数据信息,通过Dicom里面的tag可以对比上述tag描述,我们在实际过程中只取上述tag使用,其他tag暂时不管:
在之后的数据处理中可能还会用到hdf格式的数据,下面介绍一下hdf
文件格式:
HDF是用于存储和分发科学数据的一种自我描述、多对象文件格式。HDF是由美国国家超级计算应用中心(NCSA)创建的,以满足不同群体的科学家在不同工程项目领域之需要。HDF可以表示出科学数据存储和分布的许多必要条件。HDF被设计为:
除了NCSA在用它,我想还有国家卫星气象中心因为国家卫星气象中心提供了一个中文版的翻译HDF5.0 使用简介 - 国家卫星气象中心! 注:hdf具体介绍详见下述链接: 关于HDF文件的一点概述(HDF4,HDF5) HDF5 小试——高大上的多对象文件格式
诊断标注以XML格式提供,目前已有XML parser (DeepLearning:medical_image/src/data/annotation.py)
<?xml version="1.0" encoding="UTF-8"?>
<LidcReadMessage uid="1.3.6.1.4.1.14519.5.2.1.6279.6001.1308168927148.0" xmlns="http://www.nih.gov">
<ResponseHeader>
<Version>1.7</Version>
<MessageId>1152727</MessageId>
<DateRequest>2006-06-05</DateRequest>
<TimeRequest>17:08:37</TimeRequest>
<RequestingSite>removed</RequestingSite>
<ServicingSite>removed</ServicingSite>
<TaskDescription>Second unblinded read</TaskDescription>
<CtImageFile>removed</CtImageFile>
<SeriesInstanceUid>1.3.6.1.4.1.14519.5.2.1.6279.6001.340202188094259402036602717327</SeriesInstanceUid>
<StudyInstanceUID>1.3.6.1.4.1.14519.5.2.1.6279.6001.584233139051825667176600857752</StudyInstanceUID>
<DateService>2006-06-05</DateService>
<TimeService>17:08:37</TimeService>
<ResponseDescription>1 - Reading complete</ResponseDescription>
<ResponseComments>Merged, reader anonymized, unblinded responses</ResponseComments>
</ResponseHeader>
<readingSession>
<annotationVersion>3.12</annotationVersion>
<servicingRadiologistID>anonymous</servicingRadiologistID>
<unblindedReadNodule>
<noduleID>16448</noduleID>
<roi>
<imageZposition>-181.0</imageZposition>
<imageSOP_UID>1.3.6.1.4.1.14519.5.2.1.6279.6001.156388264492529846911221229696</imageSOP_UID>
<inclusion>TRUE</inclusion>
<edgeMap><xCoord>61</xCoord><yCoord>198</yCoord></edgeMap>
</roi>
</unblindedReadNodule>
<nonNodule>
<nonNoduleID>16446</nonNoduleID>
<imageZposition>-187.0</imageZposition>
<imageSOP_UID>1.3.6.1.4.1.14519.5.2.1.6279.6001.270634182491671360557327079123</imageSOP_UID>
<locus><xCoord>373</xCoord><yCoord>225</yCoord>
</locus>
</nonNodule>
</readingSession>
<readingSession>
<annotationVersion>3.12</annotationVersion>
<servicingRadiologistID>anonymous</servicingRadiologistID>
<unblindedReadNodule>
<noduleID>12468</noduleID>
<roi>
<imageZposition>-70.0</imageZposition>
<imageSOP_UID>1.3.6.1.4.1.14519.5.2.1.6279.6001.350028248790971951374528707491</imageSOP_UID>
<inclusion>TRUE</inclusion>
<edgeMap><xCoord>398</xCoord><yCoord>252</yCoord></edgeMap>
</roi>
</unblindedReadNodule>
<unblindedReadNodule>
<noduleID>12453</noduleID>
<characteristics>
<subtlety>3</subtlety>
<internalStructure>1</internalStructure>
<calcification>6</calcification>
<sphericity>2</sphericity>
<margin>4</margin>
<lobulation>1</lobulation>
<spiculation>1</spiculation>
<texture>5</texture>
<malignancy>1</malignancy>
</characteristics>
<roi>
<imageZposition>-250.0</imageZposition>
<imageSOP_UID>1.3.6.1.4.1.14519.5.2.1.6279.6001.100791367364990316173567441168</imageSOP_UID>
<inclusion>TRUE</inclusion>
<edgeMap><xCoord>49</xCoord><yCoord>316</yCoord></edgeMap>
<edgeMap><xCoord>50</xCoord><yCoord>315</yCoord></edgeMap>
<edgeMap><xCoord>51</xCoord><yCoord>314</yCoord></edgeMap>
<edgeMap><xCoord>51</xCoord><yCoord>313</yCoord></edgeMap>
<edgeMap><xCoord>51</xCoord><yCoord>312</yCoord></edgeMap>
<edgeMap><xCoord>51</xCoord><yCoord>311</yCoord></edgeMap>
<edgeMap><xCoord>51</xCoord><yCoord>310</yCoord></edgeMap>
<edgeMap><xCoord>51</xCoord><yCoord>309</yCoord></edgeMap>
<edgeMap><xCoord>51</xCoord><yCoord>308</yCoord></edgeMap>
<edgeMap><xCoord>51</xCoord><yCoord>307</yCoord></edgeMap>
<edgeMap><xCoord>50</xCoord><yCoord>306</yCoord></edgeMap>
<edgeMap><xCoord>49</xCoord><yCoord>305</yCoord></edgeMap>
<edgeMap><xCoord>48</xCoord><yCoord>306</yCoord></edgeMap>
<edgeMap><xCoord>48</xCoord><yCoord>307</yCoord></edgeMap>
<edgeMap><xCoord>49</xCoord><yCoord>308</yCoord></edgeMap>
<edgeMap><xCoord>48</xCoord><yCoord>309</yCoord></edgeMap>
<edgeMap><xCoord>48</xCoord><yCoord>310</yCoord></edgeMap>
<edgeMap><xCoord>48</xCoord><yCoord>311</yCoord></edgeMap>
<edgeMap><xCoord>49</xCoord><yCoord>312</yCoord></edgeMap>
<edgeMap><xCoord>48</xCoord><yCoord>313</yCoord></edgeMap>
<edgeMap><xCoord>49</xCoord><yCoord>314</yCoord></edgeMap>
<edgeMap><xCoord>48</xCoord><yCoord>315</yCoord></edgeMap>
<edgeMap><xCoord>49</xCoord><yCoord>316</yCoord></edgeMap>
</roi>
</unblindedReadNodule>
<unblindedReadNodule>
<noduleID>12461</noduleID>
<roi>
<imageZposition>-253.0</imageZposition>
<imageSOP_UID>1.3.6.1.4.1.14519.5.2.1.6279.6001.150739457477763063347777523734</imageSOP_UID>
<inclusion>TRUE</inclusion>
<edgeMap><xCoord>202</xCoord><yCoord>398</yCoord></edgeMap>
</roi>
</unblindedReadNodule>
<nonNodule>
<nonNoduleID>12471</nonNoduleID>
<imageZposition>-199.0</imageZposition>
<imageSOP_UID>1.3.6.1.4.1.14519.5.2.1.6279.6001.267363953457812811093234965009</imageSOP_UID>
<locus><xCoord>372</xCoord><yCoord>153</yCoord>
</locus>
</nonNodule>
</readingSession>
【基本结构】
【结节分类 -> 普通结节,小结节,非结节】
【结节标注】
【结节头】
【读取XML信息】
def parse(xml_filename):
logging.info("Parsing %s" % xml_filename)
annotations = []
# ET is the library we use to parse xml data
tree = etree.parse(xml_filename)
root = tree.getroot()
# header = parse_header(root)
# readingSession-> holds radiologist's annotation info
for read_session in root.findall('nih:readingSession', NS):
# to hold each radiologists annotation
# i.e. readingSession in xml file
rad_annotation = RadAnnotation()
rad_annotation.version = \
read_session.find('nih:annotationVersion', NS).text
rad_annotation.id = \
read_session.find('nih:servicingRadiologistID', NS).text
# nodules
nodule_nodes = read_session.findall('nih:unblindedReadNodule', NS)
for node in nodule_nodes:
nodule = parse_nodule(node)
if nodule.is_small:
rad_annotation.small_nodules.append(nodule)
else:
rad_annotation.nodules.append(nodule)
# non-nodules
non_nodule = read_session.findall('nih:nonNodule', NS)
for node in non_nodule:
nodule = parse_non_nodule(node)
rad_annotation.non_nodules.append(nodule)
annotations.append(rad_annotation)
return annotations
def parse_header(root):
header = AnnotationHeader()
print root.findall('nih:*', NS)
resp_hdr = root.findall('nih:ResponseHeader', NS)[0]
header.version = resp_hdr.find('nih:Version', NS).text
header.message_id = resp_hdr.find('nih:MessageId', NS).text
header.date_request = resp_hdr.find('nih:DateRequest', NS).text
header.time_request = resp_hdr.find('nih:TimeRequest', NS).text
header.task_desc = resp_hdr.find('nih:TaskDescription', NS).text
header.series_instance_uid = resp_hdr.find('nih:SeriesInstanceUid', NS).text
date_service = resp_hdr.find('nih:DateService', NS)
if date_service is not None:
header.date_service = date_service.text
time_service = resp_hdr.find('nih:TimeService', NS)
if time_service is not None:
header.time_service = time_service.text
header.study_instance_uid = resp_hdr.find('nih:StudyInstanceUID', NS).text
return header
CT图像有三种,分别是CT,CR,DX,这个也可以查看LIDC-IDRI中的Modality,如下图所示:
【基类DcmImage】
【三种子类 -> CTImage, CRImage, RXImage】
主要就是分析XML文件,提取所有需要用到的信息,详见源代码。
【判断指定位置是否有结节】
【One-hot编码】
【处理结节】
由于数据具有很多不同的特征,有的对后期训练比较有利,有的却不利于后期的训练,需要进行各种预处理之类的。 【有利点】
【不利点】
【数据切割方法】
注: 【Data Imbalance】 对于医疗图像来说,大部分图像是正常的,非标记的数据只占非常小的比例。以本例中,标记数据与非标记数据的比例至少为 1:1000 以上。在先验概率如此小的情况下,按照正确率而言,即使将所有数据都判定为正常非病患,正确率也可以高达99.9%以上。然而对于病患诊断,不能漏诊则是重中之重。因此,需要调整数据集的分布,放大Positive数据的比例,减小Negative数据的比例,让分类器可以有效识别positive。
在实验中,按以下方法调整数据集:
Loss Function: 对于医疗诊断而言,漏诊的代价更大,即将positive判定为negative的代价是更大的更严重的错误。 判定错误的代价定义为:
[1] LIDC-IDRI 官网 [2] Lung Image Database Consortium (LIDC) Nodule Size Report [3] 肺部CT图像分析及特征提取研究 [4] 肺结节CT图像特征提取及SVM分类方法研究 [5] Computer-aided classification of lung nodules on computed tomography images via deep learning technique (paper) [6] Computerized Detection of Lung Nodules in Thin-Section CT Images by use of Selective Enhancement Filters and an Automated Rule-Based Classifier (paper) [7] DICOM的常用Tag分类和说明 [8] 肺结节CT征象及显示 [9] CT影像的识别 [10] 基于分类技术的肺部CT图像识别 [11] 关于HDF文件的一点概述(HDF4,HDF5) [12] HDF5 小试——高大上的多对象文件格式 [13] 基于ct影像孤立性肺结节识别与分析 [14] 肺结节的影像诊断和鉴别诊断 (ppt) [15] 肺部结节的CT鉴别诊断 (ppt)
(注:感谢您的阅读,希望本文对您有所帮助。如果觉得不错欢迎分享转载,但请先点击 这里 获取授权。本文由 版权印 提供保护,禁止任何形式的未授权违规转载,谢谢!)