1. 我想把RPI转成RAI
2. 方案(目前测试行不通)
import nibabel as nib
import numpy as np
def compute_orientation(init_axcodes, final_axcodes):
"""
A thin wrapper around ``nib.orientations.ornt_transform``
:param init_axcodes: Initial orientation codes
:param final_axcodes: Target orientation codes
:return: orientations array, start_ornt, end_ornt
"""
ornt_init = nib.orientations.axcodes2ornt(init_axcodes)
ornt_fin = nib.orientations.axcodes2ornt(final_axcodes)
ornt_transf = nib.orientations.ornt_transform(ornt_init, ornt_fin)
return ornt_transf, ornt_init, ornt_fin
def do_reorientation(data_array, init_axcodes, final_axcodes):
"""
source: https://niftynet.readthedocs.io/en/dev/_modules/niftynet/io/misc_io.html#do_reorientation
Performs the reorientation (changing order of axes)
:param data_array: 3D Array to reorient
:param init_axcodes: Initial orientation
:param final_axcodes: Target orientation
:return data_reoriented: New data array in its reoriented form
"""
ornt_transf, ornt_init, ornt_fin = compute_orientation(init_axcodes, final_axcodes)
if np.array_equal(ornt_init, ornt_fin):
return data_array
return nib.orientations.apply_orientation(data_array, ornt_transf)
# I test the code by the following simple demo, and it works.
init_path = r"\path1\Necrosis_000_0000.nii.gz"
target_path = r"\path2\Necrosis_000_0000.nii.gz"
init_nii = nib.load(init_path)
lits_data = init_nii.get_fdata() # shape = (512, 512, 123)
lits_axcodes = tuple(nib.aff2axcodes(init_nii.affine)) # ('R', 'A', 'S')
tatget_nii = nib.load(target_path)
kits_axcodes = tuple(nib.aff2axcodes(tatget_nii.affine)) # ('I', 'P', 'L'
new_lits_img = do_reorientation(lits_data, lits_axcodes, kits_axcodes) # shape = (123, 512, 512)
header_info = init_nii.header
new_image = nib.Nifti1Image(new_lits_img, tatget_nii.affine, header_info)
nib.save(new_image, r"\target_path\test.nii.gz")
左是转换前,右是转换后
基本信息,
但是发现转换后ITKSnap的显示并没有变化
而且ITKSnap显示的方向和代码里显示的有些是反的(R-L, S-I)
不懂为啥,好像这个方法行不通
3. 其他方案
(1)
reoriented = sitk.DICOMOrient(img, 'RAI')
这个方法行不通,转换后图像并没有变化,而且操作后Orientation的显示再ITKSnap的显示并不是RAI,相反的是IPS
该死的,我好像知道为什么了,因为这个图像的Direction是,根据之前的方向理解(CSDN),是对的上的
参考How to change the orientation of SimpleITK image in Python - Stack Overflow
SimpleITK: itk::simple::DICOMOrientImageFilter Class Reference
看官方的解释,我感觉就是我要的函数啊,不懂为啥行不通。
(2)直接SetDirection()
这个是目前我行得通的,而且非常简单的
a = sitk.ReadImage(init_path)
a.SetDirection((1,0,0,0,1,0,0,0,1)) # RAI
sitk.WriteImage(a, out_path)
可以看到方向已经转过来了,而且Spacing和Orientation是一致的
3. nib.as_closest_canonical(这个方法还没有试)
def reorient_to_RAS(img_fname: str, output_fname: str = None):
img = nib.load(img_fname)
canonical_img = nib.as_closest_canonical(img)
if output_fname is None:
output_fname = img_fname
nib.save(canonical_img, output_fname)