在使用SimpleITK
处理MRI医学图像数据的时候遇到了以下问题:
File "d:\PythonProgramme\GenerateDatasetTxt\xx.py", line 12, in <module>
img = sitk.ReadImage("0000264276/T2.nii.gz")
File "D:\Program Files\Anaconda3\envs\simpleitk\lib\site-packages\SimpleITK\extra.py", line 346, in ReadImage
return reader.Execute()
File "D:\Program Files\Anaconda3\envs\simpleitk\lib\site-packages\SimpleITK\SimpleITK.py", line 8015, in Execute
return _SimpleITK.ImageFileReader_Execute(self)
RuntimeError: Exception thrown in SimpleITK ImageFileReader_Execute: C:\Miniconda\envs\bld\conda-bld\work\b\ITK\Modules\IO\NIFTI\src\itkNiftiImageIO.cxx:1980:
ITK ERROR: ITK only supports orthonormal direction cosines. No orthonormal definition found!
简单翻译过来是 “ITK只支持标准正交方向。没有找到标准正交定义!”,这是一个发生在读取数据的错误,直接第一步扼杀你想处理数据的欲望。
这里先说一下解决方案,
方案一:
将SimpleITK
的版本转换至2.0.2
但如果你使用ANTsPy
这种内置ITK
的库对数据进行处理,就没办法通过切换版本解决了。
方案二:
使用nibabel
库,读取nii
数据的qform
信息和sform
信息,然后再将这些信息写回数据,并保存一份新的数据,然后就可以对新保存的数据进行SimpleITK
或ANTsPy
的读取了。
以下是处理代码,非常简单,甚至有点傻。
import nibabel as nib
img = nib.load("xxxxx.nii.gz")
qform = img.get_qform()
img.set_qform(qform)
sfrom = img.get_sform()
img.set_sform(sfrom)
nib.save(img, "xxxxx.nii.gz")
方案一是网上给出的一个解决方案,而方案二由本人自己摸索,这里简单的描述一下方案二的摸索过程,并不高深。
首先
首先一个最直接想法就是:找到源码的报错位置C:\Miniconda\envs\bld\conda-bld\work\b\ITK\Modules\IO\NIFTI\src\itkNiftiImageIO.cxx
,直接把这个相关报错的代码删了。
可惜我的电脑不存在这个路劲,而且是cxx
文件,大概是c语言的代码,经过cython还是什么其他的过程编译成了无法修改代码的形式。
然后
那就只好去网上的官方github上看看源码,看看触发错误的条件,将数据处理成不会触发错误的形式。
这是源码网址,相关报错代码在第1980
行
往上看,从1789
行到1981
行的代码都与报错代码处于同一个函数NiftiImageIO::SetImageIOOrientationFromNIfTI
下
妄想看懂这么多代码不现实,本人水平有限,但可以确定的是函数内有大量关于qform
和sform
的判断语句,我截选了一些,如下所示(觉得不适可以忽视):
总的来说,如果这些判断一个都不符合,就无法跳出该函数从而“触碰”到最后的报错代码。
再者
那么qform
和sform
是啥,这里出于经验上判断,去使用ITK-SNAP
直接查看数据的metadata
可以发现qform
的信息有点异常,NIFTI_XFORM_UNKNOWN
正好出现在源码的判断中。
依旧是直接想法,把这个信息改了。
最后
因为SimpleITK
无法读取,这里借助nibabel
库,去官方文档查阅一下是否有修改的函数。
这是官方文档:https://nipy.org/nibabel/reference/nibabel.nifti1.html
好耶,有修改的函数,可以直接设置参数code
将qform_code
或sform_code
替换成了非0值,也就是非NIFTI_XFORM_UNKNOWN
。不过红色方框的自适应设置貌似更好,但需要接收一个affine
参数。
那很好办,那原本affine
是什么,就设置成什么就行了,毕竟目的只是修改qform_code
或sform_code
。
import nibabel as nib
img = nib.load("xxxxx.nii.gz")
qform = img.get_qform()
img.set_qform(qform)
sfrom = img.get_sform()
img.set_sform(sfrom)
nib.save(img, "xxxxx.nii.gz")
再新保存文件的metadata
,果然修改成了希望的效果,随后使用SimpleITK
或ANTsPy
就可以顺利读取了。
后续N4矫正,配准都没有报错,效果也ok,因此我认为算是解决。