一金抡、數據源
訓練數據源為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ī)轉載,謝謝爪瓜!)