首页 > 技术文章 > SimpleITK处理医学图像

dotman 2020-11-23 20:05 原文

做医学图像时,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矩阵,否则保存出来的结果会非常诡异!!

 

 

暂时先说这么多,以后碰到问题再补充。

 

推荐阅读