ITK是一個功能很強大的醫學圖像處理公開庫,搭配VTK用以顯示圖像,可以實現幾乎所有醫學圖像處理的功能需要。ITK通常以C++包進行提供,當然也可以自己編譯為Python包,不過編譯過程比較繁瑣耗時,而且很容易踩坑。但ITK官方進行的Python封裝SimpleITK,則直接可以拿來使用;雖然有部分ITK的功能沒有包含,但已基本夠用了。我們在處理醫學圖像時,使用的基本都是SimpleITK。
本文就簡單總結一下我們在處理這些圖像時的經驗,以便備忘,並為后來者參考。
1.讀取文件
讀取DICOM序列
醫學圖像中一個CT序列包含很多張圖片,即一個case包含許多slice,使用SimpleITK可以直接讀取一個序列,並方便地得到各種參數,將圖像數據轉換成numpy Array:
- import SimpleITK as sitk
- import numpy as np
- reader = sitk.ImageSeriesReader()
- dicom_names = reader.GetGDCMSeriesFileNames(case_path)
- reader.SetFileNames(dicom_names)
- image = reader.Execute()
- image_array = sitk.GetArrayFromImage(image) # z, y, x
- origin = image.GetOrigin() # x, y, z
- spacing = image.GetSpacing() # x, y, z
需要注意的是,SimpleITK讀取的圖像數據的坐標順序為zyx,即從多少張切片到單張切片的寬和高;而據SimpleITK Image獲取的origin和spacing的坐標順序則是xyz。這些需要特別注意。
讀取DICOM單張圖片
可以將一個DICOM序列作為一個整體一次讀入,也可以一張一張地讀入每張切片:
- import SimpleITK as sitk
- import numpy as np
- image = sitk.ReadImage(slice_path)
- image_array = sitk.GetArrayFromImage(image) # z, y, x
這里需要注意的除了坐標順序是zyx之外,還需注意,即使讀取單張切片,所得到的結果也是3維的,只不過第一維是1。
讀取mhd文件
涉及DICOM序列時,為了傳輸方便(從上百個dcm文件到一個mhd文件),很多情況下以mhd文件格式進行呈現,不過mhd文件只是一個很小的包含數據信息的文件,同時搭配的通常還有一個二進制的數據文件(格式為raw或zraw等)。使用SimpleITK讀取這種文件也比較方便。
- import SimpleITK as sitk
- import numpy as np
- image = sitk.ReadImage(mhd_path)
- image_array = sitk.GetArrayFromImage(image) # z, y, x
- origin = image.GetOrigin() # x, y, z
- ...
有時候不想整個讀取數據(因為比較大,讀取處理比較慢),想要讀取的只是一些基本信息,比如origin、spacing等等。這時可以只讀取mhd文件,據此獲取信息,讀取方法比較簡單,不再贅述。
2.處理文件
處理DICOM文件主要有插值等操作,可以直接使用SimpleITK(或者說是ITK)的相關函數,並通過pipeline結構進行處理。
插值
- import SimpleITK as sitk
- reader = sitk.ImageSeriesReader()
- dicom_names = reader.GetGDCMSeriesFileNames(case_path) reader.SetFileNames(dicom_names)
- image = reader.Execute()
- resample = sitk.ResampleImageFilter()
- resample.SetOutputDirection(image.GetDirection())
- resample.SetOutputOrigin(image.GetOrigin())
- newspacing = [1, 1, 1]
- resample.SetOutputSpacing(newspacing)
- newimage = resample.Execute(image)
