影像組學(xué)學(xué)習(xí)筆記(35)-基于2D超聲影像的影像組學(xué)特征提取

本筆記來(lái)源于B站Up主: 有Li 的影像組學(xué)系列教學(xué)視頻
本節(jié)(35)主要介紹: 2D超聲影像組學(xué)的特征提取
視頻中李博士情境再現(xiàn)了小白研究者可能碰到的各種技術(shù)難題跨蟹,并演示了解決這些問(wèn)題的思路。

  1. dicom格式的2D 超聲圖像轉(zhuǎn)為壓縮的nifti格式橘沥,將其命名為test.nii.gz; 勾畫ROI后同樣保存為壓縮的nifti格式窗轩,命名為mask.nii.gz

    Fig1.jpg

  2. 嘗試提取影像學(xué)特征:

import radiomics 
from radiomics import featureextractor

imageFile = "/Users/Mac/Documents/JianShuNotes/2D_Ultrasound/test.nii.gz"
maskFile = "/Users/Mac/Documents/JianShuNotes/2D_Ultrasound/mask.nii.gz"
extractor = featureextractor.RadiomicsFeatureExtractor()
featureVector = extractor.execute(imageFile, maskFile)
#print(featureVector.items())
for featureName in featureVector.keys():
    print("%s: %s" % (featureName, featureVector[featureName]))

出現(xiàn)了如下報(bào)錯(cuò)信息:

sitk::ERROR: Pixel type: vector of 8-bit unsigned integer is not supported in 3D byN3itk6simple26LabelStatisticsImageFilterE

  1. 按照提示,有可能是數(shù)據(jù)格式的問(wèn)題座咆∑沸眨回到源代碼,修改文件相應(yīng)的格式箫措,將其命名為 test1.nii.gz
import SimpleITK as sitk
import numpy as np

folderPath = "/Users/Mac/Documents/JianShuNotes/2D_Ultrasound/"

reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(folderPath)
reader.SetFileNames(dicom_names)
image = reader.Execute()

image_arr = sitk.GetArrayFromImage(image) # Note: order:z, y, x !!
size = image.GetSize()
origin = image.GetOrigin() #order: x, y, z
spacing = image.GetSpacing() #order:x, y, z
direction = image.GetDirection()
#print(spacing) 

pixelType = sitk.sitkInt8 #注意這里是Int8
image_new = sitk.Image(size,pixelType)

#image_arr_new = image_arr[:,:,::-1] #鏡像翻轉(zhuǎn)操作
image_arr_new = image_arr
#print(image_arr_new.shape)

image_new = sitk.GetImageFromArray(image_arr_new)
image_new.SetDirection(direction)
image_new.SetSpacing(spacing)
image_new.SetOrigin(origin)
sitk.WriteImage(image_new,folderPath + "test1.nii.gz")
  1. 將步驟[2]中的test.nii.gz替換為test1.nii.gz,再次執(zhí)行該步驟
    此時(shí)又出現(xiàn)了報(bào)錯(cuò)信息:

sitk::ERROR: Input "labelImage" for "LabelStatisticsImageFilter" has dimension of 3 which does not match the primary input's dimension of 2!

  1. 執(zhí)行 print(image_arr_new.shape) 后顯示為:

(1, 900, 1600, 3)

Notes: 這里涉及python讀入nifti文件的格式問(wèn)題,其順序?yàn)?z,y,x(對(duì)應(yīng)這里的1,900,1600); 這里的3為不同的slice

  1. 探索這個(gè)“3”代表的意義:將每一個(gè)slice導(dǎo)出來(lái)衬潦,通過(guò)對(duì)比發(fā)現(xiàn)其中的端倪斤蔓。執(zhí)行代碼:
image_arr_new = image_arr[:,:,:,0]
#image_arr_new = image_arr[:,:,:,1]
#image_arr_new = image_arr[:,:,:,2]
#print(image_arr_new.shape)

image_new = sitk.GetImageFromArray(image_arr_new)
image_new.SetDirection(direction)
image_new.SetSpacing(spacing)
image_new.SetOrigin(origin)
sitk.WriteImage(image_new,folderPath + "test-slice0.nii.gz")
#sitk.WriteImage(image_new,folderPath + "test-slice1.nii.gz")
#sitk.WriteImage(image_new,folderPath + "test-slice2.nii.gz")
  1. test-slice0.nii.gztest-slice1.nii.gz镀岛,test-slice2.nii.gz在軟件中打開弦牡,查看它們之間的差異(肉眼似乎看不出啥區(qū)別)
  2. 使用寫代碼的方法來(lái)探索test-slice0.nii.gztest-slice1.nii.gz漂羊,test-slice2.nii.gz之間的差異(視頻里李博士演示了對(duì)比前二者)
import SimpleITK as sitk
import numpy as np

slicer0 = sitk.ReadImage("test-slice0.nii.gz")
slicer1 = sitk.ReadImage("test-slice1.nii.gz")

slicer0_arr = sitk.GetArrayFromImage(slicer0)
slicer1_arr = sitk.GetArrayFromImage(slicer1)

comp = slicer0_arr == slicer1_arr
print(comp)
Fig2.jpg
  1. 將差異的部分保存為影像導(dǎo)出
image_arr = slicer0_arr - slicer1_arr
image_arr[image_arr != 0] = 1

size = slicer0.GetSize()
origin = slicer0.GetOrigin() #order: x, y, z
spacing = slicer0.GetSpacing() #order:x, y, z
direction = slicer0.GetDirection()

image_new = sitk.GetImageFromArray(image_arr)
image_new.SetDirection(direction)
image_new.SetSpacing(spacing)
image_new.SetOrigin(origin)
sitk.WriteImage(image_new,"comp.nii.gz")
  1. 此時(shí)在軟件中打開comp.nii.gz文件驾锰,查看差異(在于右下角的水印部分)(視頻中是左下角的水印)。換句話說(shuō)走越,這3張test-slice0.nii.gz椭豫,test-slice1.nii.gztest-slice2.nii.gz是一樣的旨指,差別僅在于右下角的水印赏酥。所以,后續(xù)的工作只需選擇其中的一個(gè)即可。
  2. 再次查看test-slice0.nii.gz和mask文件,發(fā)現(xiàn)mask文件和源文件不對(duì)應(yīng)欠橘。mask.nii.gz是基于test.nii.gz文件畫出并保存的啃勉,但是在test.nii.gz保存為test1.nii.gz時(shí)存在一個(gè)翻轉(zhuǎn)(我沒(méi)有搞明白這一點(diǎn)),所以應(yīng)重新保存一下mask文件
    Fig3.jpg
import SimpleITK as sitk
import numpy as np

folderPath = "/Users/Mac/Documents/JianShuNotes/2D_Ultrasound/"
mask = sitk.ReadImage('mask.nii.gz')
mask_arr = sitk.GetArrayFromImage(mask)

reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(folderPath)
reader.SetFileNames(dicom_names)
image = reader.Execute()

image_arr = sitk.GetArrayFromImage(image) # Note: order:z, y, x !!
size = image.GetSize()
origin = image.GetOrigin() #order: x, y, z
spacing = image.GetSpacing() #order:x, y, z
direction = image.GetDirection()

pixelType = sitk.sitkInt8 #注意這里是Int8
image_new = sitk.Image(size,pixelType)
mask_new = sitk.Image(size,pixelType)

#image_arr_new = image_arr[:,:,::-1] #鏡像翻轉(zhuǎn)操作
image_arr_new = image_arr[:,:,:,0]
print(image_arr.shape)

image_new = sitk.GetImageFromArray(image_arr_new)
image_new.SetDirection(direction)
image_new.SetSpacing(spacing)
image_new.SetOrigin(origin)

mask_new = sitk.GetImageFromArray(mask_arr) # 視頻里勘誤為mask_new,其實(shí)就應(yīng)該是mask_arr, print二者可以看出區(qū)別來(lái)
mask_new.SetDirection(direction)
mask_new.SetSpacing(spacing)
mask_new.SetOrigin(origin)

sitk.WriteImage(image_new,"test0.nii.gz")
sitk.WriteImage(mask_new,"mask0.nii.gz")

Fig4.jpg
  1. 再次嘗試提取影像組學(xué)特征(代碼[2])诡右,發(fā)現(xiàn)代碼可以運(yùn)行鲜侥。但是這里有一個(gè)隱藏的bug漂坏,就是mask文件雖然重新保存了摸屠,但是并不能和原來(lái)的位置匹配谓罗。通過(guò)軟件查看圖像可以發(fā)現(xiàn)其中的區(qū)別


    Fig5.jpg
  2. 再次回到原始代碼里查找問(wèn)題來(lái)源

import SimpleITK as sitk
import numpy as np

folderPath = "/Users/Mac/Documents/JianShuNotes/2D_Ultrasound/"
mask = sitk.ReadImage('mask.nii.gz')
mask_arr = sitk.GetArrayFromImage(mask)

#reader = sitk.ImageSeriesReader()
#dicom_names = reader.GetGDCMSeriesFileNames(folderPath)
#reader.SetFileNames(dicom_names)
#image = reader.Execute()

image = sitk.ReadImage('test.nii.gz')

image_arr = sitk.GetArrayFromImage(image) # Note: order:z, y, x !!
size = image.GetSize()
origin = image.GetOrigin() #order: x, y, z
spacing = image.GetSpacing() #order:x, y, z
direction = image.GetDirection()

pixelType = sitk.sitkInt8 #注意這里是Int8
image_new = sitk.Image(size,pixelType)
mask_new = sitk.Image(size,pixelType)

#image_arr_new = image_arr[:,:,::-1] #鏡像翻轉(zhuǎn)操作
image_arr_new = image_arr[:,:,:,0]
print(image_arr.shape)

image_new = sitk.GetImageFromArray(image_arr_new)
image_new.SetDirection(direction)
image_new.SetSpacing(spacing)
image_new.SetOrigin(origin)

mask_new = sitk.GetImageFromArray(mask_arr)
mask_new.SetDirection(direction)
mask_new.SetSpacing(spacing)
mask_new.SetOrigin(origin)

sitk.WriteImage(image_new,"test0.nii.gz")
sitk.WriteImage(mask_new,"mask0.nii.gz")
  1. 歷盡周折,現(xiàn)在test0.nii.gz文件和mask0.nii.gz文件相匹配了餐塘!可以愉快地提取影像組學(xué)特征了
Fig6.jpg
import radiomics 
from radiomics import featureextractor

imageFile = "/Users/Mac/Documents/JianShuNotes/2D_Ultrasound/test0.nii.gz"
maskFile = "/Users/Mac/Documents/JianShuNotes/2D_Ultrasound/mask0.nii.gz"
extractor = featureextractor.RadiomicsFeatureExtractor()
featureVector = extractor.execute(imageFile, maskFile)
#print(featureVector.items())
for featureName in featureVector.keys():
    print("%s: %s" % (featureName, featureVector[featureName]))
Fig7.jpg
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末妥衣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子戒傻,更是在濱河造成了極大的恐慌税手,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件需纳,死亡現(xiàn)場(chǎng)離奇詭異芦倒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)不翩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門兵扬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人口蝠,你說(shuō)我怎么就攤上這事器钟。” “怎么了妙蔗?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵傲霸,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我眉反,道長(zhǎng)昙啄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任寸五,我火速辦了婚禮梳凛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梳杏。我一直安慰自己韧拒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布十性。 她就那樣靜靜地躺著叭莫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烁试。 梳的紋絲不亂的頭發(fā)上雇初,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音减响,去河邊找鬼靖诗。 笑死郭怪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的刊橘。 我是一名探鬼主播鄙才,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼促绵!你這毒婦竟也來(lái)了攒庵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤败晴,失蹤者是張志新(化名)和其女友劉穎浓冒,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尖坤,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稳懒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了慢味。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片场梆。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖纯路,靈堂內(nèi)的尸體忽然破棺而出或油,到底是詐尸還是另有隱情,我是刑警寧澤驰唬,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布顶岸,位于F島的核電站,受9級(jí)特大地震影響定嗓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜萍桌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一宵溅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧上炎,春花似錦恃逻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至裳食,卻和暖如春矛市,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诲祸。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工浊吏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留而昨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓找田,卻偏偏與公主長(zhǎng)得像歌憨,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子墩衙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容