|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
""" |
|
This code is copied from https://gist.github.com/nlessmann/24d405eaa82abba6676deb6be839266c. All credits go to the |
|
original author (user nlessmann on GitHub) |
|
""" |
|
|
|
import numpy as np |
|
import SimpleITK as sitk |
|
|
|
|
|
def reverse_axes(image): |
|
return np.transpose(image, tuple(reversed(range(image.ndim)))) |
|
|
|
|
|
def read_image(imagefile): |
|
image = sitk.ReadImage(imagefile) |
|
data = reverse_axes(sitk.GetArrayFromImage(image)) |
|
header = { |
|
'spacing': image.GetSpacing(), |
|
'origin': image.GetOrigin(), |
|
'direction': image.GetDirection() |
|
} |
|
return data, header |
|
|
|
|
|
def save_image(img: np.ndarray, header: dict, output_file: str): |
|
""" |
|
CAREFUL you need to restore_original_slice_orientation before saving! |
|
:param img: |
|
:param header: |
|
:return: |
|
""" |
|
|
|
img = reverse_axes(img) |
|
img_itk = sitk.GetImageFromArray(img) |
|
img_itk.SetSpacing(header['spacing']) |
|
img_itk.SetOrigin(header['origin']) |
|
if not isinstance(header['direction'], tuple): |
|
img_itk.SetDirection(header['direction'].flatten()) |
|
else: |
|
img_itk.SetDirection(header['direction']) |
|
|
|
sitk.WriteImage(img_itk, output_file) |
|
|
|
|
|
def swap_flip_dimensions(cosine_matrix, image, header=None): |
|
|
|
swap = np.argmax(abs(cosine_matrix), axis=0) |
|
flip = np.sum(cosine_matrix, axis=0) |
|
|
|
|
|
image = np.transpose(image, tuple(swap)) |
|
image = image[tuple(slice(None, None, int(f)) for f in flip)] |
|
|
|
if header is None: |
|
return image |
|
|
|
|
|
header['spacing'] = tuple(header['spacing'][s] for s in swap) |
|
header['direction'] = np.eye(3) |
|
|
|
return image, header |
|
|
|
|
|
def normalize_slice_orientation(image, header): |
|
|
|
header['original'] = header.copy() |
|
|
|
|
|
|
|
cosine = np.asarray(header['direction']).reshape(3, 3) |
|
cosine_inv = np.linalg.inv(np.round(cosine)) |
|
|
|
return swap_flip_dimensions(cosine_inv, image, header) |
|
|
|
|
|
def restore_original_slice_orientation(mask, header): |
|
|
|
|
|
cosine = np.asarray(header['original']['direction']).reshape(3, 3) |
|
cosine_rnd = np.round(cosine) |
|
|
|
|
|
return swap_flip_dimensions(cosine_rnd, mask), header['original'] |
|
|