做醫學圖像時,SimpleITK是一個很常用的庫。實際上大家往往喜歡把不同類型的數據割裂開,nrrd用pynrrd處理,dicom用dicom處理,nii用nibabel處理……實際上根本沒必要,SimpleITK完全可以統一處理,各種類型的讀取和保存一步搞定。
1. 讀取
首先是最常見的DICOM。這個文件格式是CT機器直接輸出的結果,每個病人會是一個文件夾,里面有若干個DICOM文件,每個DICOM文件都是一個切片,可以被單獨查閱(通過SimpleITK的ReadImage)。但是,處理起來一般我們會希望把這些DICOM組合起來形成一個3D的矩陣,這樣就可以用到SimpltITK里的ImageSeriesReader()來實現:
reader = sitk.ImageSeriesReader() img_names = reader.GetGDCMSeriesFileNames(img_path) reader.SetFileNames(img_names) image = reader.Execute() image_array = sitk.GetArrayFromImage(image) # z, y, x
然后還有就是MHD。這種格式的文件由一個MHD文件和一個RAW文件組成,其中MHD里面是病人和CT掃描結果的相關信息,RAW里面存的是真正的數組,對於這種格式,SimpleITK可以這樣讀取:
itk_img = sitk.ReadImage(filename)
img_array = sitk.GetArrayFromImage(itk_img)
其次,還有NII格式的文件,想要讀取也是類似的代碼:
itk_img = sitk.ReadImage(filename)
img_array = sitk.GetArrayFromImage(itk_img)
不過,對於NII類型的文件,SimpleITK在保存上會有一些問題(讀取沒問題保存上竟然有問題我真是服了),如果slice的數量很大(之前有碰到過300多個slice的),保存起來會直接報錯,所以如果碰到這種情況我會選擇保存成nrrd(用pynrrd庫)。
2. 保存
說到保存,有幾個天坑一定要說一下。
首先,保存的通用代碼是:
savedImg = sitk.GetImageFromArray(outputs3D) savedImg.SetSpacing(spacing) savedImg.SetOrigin(origin) sitk.WriteImage(savedImg, input_nii[:-4]+'_liverSegResult.nii')
這個里面,SetOrigin和SetSpacing我常常會忘記,所以導致保存的CT用ITKsnap看會變形。這里面的spacing和origin均可以從之前ReadImage()返回的對象上通過GetOrigin()和GetSpacing()獲取,千萬別忘了。當然,除了這兩個之外還有個direction也是可以get和set的,不過一般情況下只要你代碼沒有搞一些矩陣的翻轉等操作這個是不用管的。
還有,就是如果要保存的是分割的二值化結果的話,千萬記得outputs3D得是一個float類型的ndarray矩陣,否則保存出來的結果會非常詭異!!
暫時先說這么多,以后碰到問題再補充。