LIDC-IDRI肺結節(jié)Dicom數據集解析與總結


一金抡、數據源

訓練數據源為LIDC-IDRI,該數據集由胸部醫(yī)學圖像文件(如CT腌且、X光片)和對應的診斷結果病變標注組成梗肝。該數據是由美國國家癌癥研究所(National Cancer Institute)發(fā)起收集的,目的是為了研究高危人群早期癌癥檢測铺董。

該數據集中统捶,共收錄了1018個研究實例。對于每個實例中的圖像柄粹,都由4位經驗豐富的胸部放射科醫(yī)師進行兩階段的診斷標注。在第一階段匆绣,每位醫(yī)師分別獨立診斷并標注病患位置驻右,其中會標注三中類別:1) >=3mm的結節(jié), 2) <3mm的結節(jié), 3) >=3mm的非結節(jié)。在隨后的第二階段中崎淳,各位醫(yī)師都分別獨立的復審其他三位醫(yī)師的標注堪夭,并給出自己最終的診斷結果。這樣的兩階段標注可以在避免forced consensus的前提下,盡可能完整的標注所有結果森爽。

文件位置LIDC-IDRI -> lidc-idri nodule counts (6-23-2015).xlsx


文件位置LIDC-IDRI -> tcia-diagnosis-data-2012-04-20.xls

二恨豁、圖像文件格式

1. 圖像Dicom格式

圖像文件為Dicom格式,是醫(yī)療圖像的標準格式爬迟,其中除了圖像像素外橘蜜,還有一些輔助的元數據如圖像類型、圖像時間等信息付呕。
一張CT圖像有 512x512 個像素點计福,在dicom文件中每個像素由2字節(jié)表示,所以每張圖片約512KB大小徽职。圖像中每個像素都是整數象颖,專業(yè)名稱為 Hounsfield scale 或 CT Number,是描述物質的放射密度的量化值(參考Wikipedia)姆钉。下表為常見物質的HU值说订。

由于圖片為單通道,畫圖渲染出來為黑白圖潮瓶,放射密度越高的位置越亮陶冷。

除了像素圖以外,元數據中有一些其它主要Tag (參考DICOM的常用Tag分類和說明)

在LIDC-IDRI上面可以直接網頁上搜索圖像數據信息筋讨,通過Dicom里面的tag可以對比上述tag描述埃叭,我們在實際過程中只取上述tag使用,其他tag暫時不管:

2. HDF文件格式

在之后的數據處理中可能還會用到hdf格式的數據悉罕,下面介紹一下hdf文件格式:

HDF是用于存儲和分發(fā)科學數據的一種自我描述赤屋、多對象文件格式。HDF是由美國國家超級計算應用中心(NCSA)創(chuàng)建的壁袄,以滿足不同群體的科學家在不同工程項目領域之需要类早。HDF可以表示出科學數據存儲和分布的許多必要條件。HDF被設計為:

  • 自述性:對于一個HDF文件里的每一個數據對象嗜逻,有關于該數據的綜合信息(元數據)涩僻。在沒有任何外部信息的情況下,HDF允許應用程序解釋HDF文件的結構和內容栈顷。
  • 通用性:許多數據類型都可以被嵌入在一個HDF文件里逆日。例如,通過使用合適的HDF數據結構萄凤,符號室抽、數字和圖形數據可以同時存儲在一個HDF文件里。
  • 靈活性:HDF允許用戶把相關的數據對象組合在一起靡努,放到一個分層結構中坪圾,向數據對象添加描述和標簽晓折。它還允許用戶把科學數據放到多個HDF文件里。
  • 擴展性:HDF極易容納將來新增加的數據模式兽泄,容易與其他標準格式兼容漓概。
  • 跨平臺性:HDF是一個與平臺無關的文件格式。HDF文件無需任何轉換就可以在不同平臺上使用病梢。

除了NCSA在用它胃珍,我想還有國家衛(wèi)星氣象中心因為國家衛(wèi)星氣象中心提供了一個中文版的翻譯HDF5.0 使用簡介 - 國家衛(wèi)星氣象中心!
注:hdf具體介紹詳見下述鏈接:
關于HDF文件的一點概述(HDF4,HDF5)
HDF5 小試——高大上的多對象文件格式

三飘千、診斷標注

診斷標注以XML格式提供堂鲜,目前已有XML parser (DeepLearning:medical_image/src/data/annotation.py)

  • XML文件頭部ResponseHeader:
<?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>
  • XML文件ReadingSession (<nonNodule> 標注 ):
<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>
  • XML文件ReadingSession (<noduleID>標注 ):
<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>

四、數據處理代碼分析

1. nodule_structs.py

【基本結構】

  • NoduleCharstics
  • NoduleRoi
  • Nodule(所有結節(jié)類型的基類)

【結節(jié)分類 -> 普通結節(jié)护奈,小結節(jié)缔莲,非結節(jié)】

  • NormalNodule
  • SmallNodule
  • NonNodule

【結節(jié)標注】

  • RadAnnotation

【結節(jié)頭】

  • AnnotationHeader

【讀取XML信息】

  • IdriReadMessage

2. annotation.py(部分)

  • 【分析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
  • 【分析結節(jié)頭】
 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
  • 【分析結節(jié),非結節(jié)】
    具體詳見源代碼

3. dicom_set.py(部分)

CT圖像有三種霉旗,分別是CT,CR,DX,這個也可以查看LIDC-IDRI中的Modality痴奏,如下圖所示:

【基類DcmImage】

【三種子類 -> CTImage, CRImage, RXImage】

  • CTImage
  • CRImage
  • DXImage

4. lidc_xml_parser.py(部分)

主要就是分析XML文件,提取所有需要用到的信息厌秒,詳見源代碼读拆。

5. prepare_data.py(部分)

【判斷指定位置是否有結節(jié)】

【One-hot編碼】

【處理結節(jié)】

五、數據特征分析

由于數據具有很多不同的特征鸵闪,有的對后期訓練比較有利檐晕,有的卻不利于后期的訓練,需要進行各種預處理之類的蚌讼。
【有利點】

  • CT圖像的連續(xù)性(等間隔多次斷層掃描辟灰,可以更有利于對結節(jié)的判別)
  • 三維CT圖像(不同軸切方向掃描)
  • 進行預處理(如去噪,增強篡石,平滑等處理)

【不利點】

  • 數據不平衡芥喇,不對稱(帶標注的數據點所占的比例太低,不到1/1000)凰萨,可以考慮對positive進行旋轉继控,增加數據源,對negtive進行削減胖眷,只取部分等武通;
  • 圖像的模糊性(灰度模糊性,幾何模糊性珊搀,和不確定性等)厅须,存在偽影(被測者自主或者不自主的運動所致)
  • 原始圖像的格式采用的是Dicom格式,需要進行各種預處理才能拿來用食棕,前期比較麻煩朗和,如果處理好了,就相對比較好用了

【數據切割方法】

  • 順序切割
    切割方法:CT圖片大小為 512x512簿晓,按32個像素為步長眶拉,截取 64x64 大小的塊,每張原始圖可切出225張訓練圖憔儿。
    標注方法:若64x64圖片中忆植,存在結節(jié)的中心點,則標注為True谒臼,否則標注為False朝刊。
  • 僅取標注點
    由于在原始標注中描述了所有的結節(jié)和非結節(jié),他們在數量上相當蜈缤,所以只采集所有有標注的圖片來進行識別拾氓。
    切割方法:讀取結節(jié)的坐標,以結節(jié)中心點為切割中心點截取64x64大小的圖片底哥。
    標注方法:若圖像為結節(jié)點咙鞍,則標注為True,否則標注為False趾徽。
  • 標注圖+其他非標注切割
    由于僅取標注點的圖片來訓練续滋,無法讓分類器識別影像邊緣位置,會造成大量誤判孵奶,因此再重新調整數據集疲酌,將有標注的圖和沒有標注的圖都加入訓練集。
    切割方法:對于所有標注的點了袁,采用 #僅取標注點# 的方法截取朗恳。對于其它所有沒有標注的方格,按 #順序切割# 的方式獲得早像。
    標注方法:將數據分為4類:1) >=3mm結節(jié), 2) <3mm結節(jié), 3) >=3mm非結節(jié), 4) 無標注僻肖。有原始標注的圖片會組成1, 2, 3類,其它順序截取的圖片會構成第4類卢鹦。

注:
【Data Imbalance】
  對于醫(yī)療圖像來說臀脏,大部分圖像是正常的,非標記的數據只占非常小的比例冀自。以本例中揉稚,標記數據與非標記數據的比例至少為 1:1000 以上。在先驗概率如此小的情況下熬粗,按照正確率而言搀玖,即使將所有數據都判定為正常非病患,正確率也可以高達99.9%以上驻呐。然而對于病患診斷灌诅,不能漏診則是重中之重芳来。因此,需要調整數據集的分布猜拾,放大Positive數據的比例即舌,減小Negative數據的比例,讓分類器可以有效識別positive挎袜。

在實驗中顽聂,按以下方法調整數據集:

  • 旋轉有標記的圖片,每次旋轉27度盯仪,每次旋轉后形成一張新的圖片紊搪。這樣所有有原始標記的圖片則擴大了10倍。
  • 所有沒有原始標記的圖片全景,只取2%耀石,剩下則全部舍棄。

Loss Function:
對于醫(yī)療診斷而言蚪燕,漏診的代價更大娶牌,即將positive判定為negative的代價是更大的更嚴重的錯誤。
判定錯誤的代價定義為:

六馆纳、短期總結

1. 知識儲備

  • 做出一個checklist诗良,逐步完善
  • 將自己學的,做的的東西寫出來鲁驶,總結成文鉴裹,發(fā)出去
  • 能夠將自己掌握的知識講出來,并且讓別人能夠聽懂

2.經驗積累(項目)

  • 對于簡單的問題钥弯,能夠穩(wěn)定到一個比較好的結果径荔,比較高的準確率
  • 對于沒有接觸過的項目,遇到新問題時脆霎,能夠快速定位总处,及時解決(比如服務器出現問題,能夠半小時定位睛蛛,三小時解決恢復服務)

Reference:

[1] LIDC-IDRI 官網
[2] Lung Image Database Consortium (LIDC) Nodule Size Report
[3] 肺部CT圖像分析及特征提取研究
[4] 肺結節(jié)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] 肺結節(jié)CT征象及顯示
[9] CT影像的識別
[10] 基于分類技術的肺部CT圖像識別
[11] 關于HDF文件的一點概述(HDF4,HDF5)
[12] HDF5 小試——高大上的多對象文件格式
[13] 基于ct影像孤立性肺結節(jié)識別與分析
[14] 肺結節(jié)的影像診斷和鑒別診斷 (ppt)
[15] 肺部結節(jié)的CT鑒別診斷 (ppt)


(注:感謝您的閱讀鹦马,希望本文對您有所幫助。如果覺得不錯歡迎分享轉載忆肾,但請先點擊 這里 獲取授權袁梗。本文由 版權印 提供保護颈墅,禁止任何形式的未授權違規(guī)轉載,謝謝爪瓜!)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末剥懒,一起剝皮案震驚了整個濱河市反浓,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖退疫,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異鸽素,居然都是意外死亡蹄咖,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門付鹿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚜迅,你說我怎么就攤上這事舵匾。” “怎么了谁不?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵坐梯,是天一觀的道長。 經常有香客問我刹帕,道長吵血,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任偷溺,我火速辦了婚禮蹋辅,結果婚禮上,老公的妹妹穿的比我還像新娘挫掏。我一直安慰自己侦另,他們只是感情好,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布尉共。 她就那樣靜靜地躺著褒傅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪袄友。 梳的紋絲不亂的頭發(fā)上殿托,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天,我揣著相機與錄音剧蚣,去河邊找鬼支竹。 笑死,一個胖子當著我的面吹牛券敌,可吹牛的內容都是我干的唾戚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼待诅,長吁一口氣:“原來是場噩夢啊……” “哼叹坦!你這毒婦竟也來了?” 一聲冷哼從身側響起卑雁,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤募书,失蹤者是張志新(化名)和其女友劉穎绪囱,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體莹捡,經...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡鬼吵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了篮赢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片齿椅。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖启泣,靈堂內的尸體忽然破棺而出涣脚,到底是詐尸還是另有隱情,我是刑警寧澤寥茫,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布遣蚀,位于F島的核電站,受9級特大地震影響纱耻,放射性物質發(fā)生泄漏芭梯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一弄喘、第九天 我趴在偏房一處隱蔽的房頂上張望玖喘。 院中可真熱鬧,春花似錦限次、人聲如沸芒涡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽费尽。三九已至,卻和暖如春羊始,著一層夾襖步出監(jiān)牢的瞬間旱幼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工突委, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留柏卤,地道東北人。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓匀油,卻偏偏與公主長得像缘缚,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子敌蚜,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內容