У меня есть изображение NIFTI размером 512x512x460. Я пытаюсь обрезать изображение до размера 512x216x460, сохранив его исходное положение.
Вот мой код, пытающийся обрезать изображение
import nibabel as nib
import numpy as np
def cropNifti(img_path, out_path, crop_width=256, crop_height=512):
# Load the NIfTI file
img = nib.load(img_path)
# Get the image data
data = img.get_fdata()
# Calculate the dimensions for the central crop
original_shape = data.shape
central_x = original_shape[0] // 2
central_y = original_shape[1] // 2
start_x = max(0, central_x - crop_width // 2)
end_x = min(original_shape[0], central_x + crop_width // 2)
start_y = max(0, central_y - crop_height // 2)
end_y = min(original_shape[1], central_y + crop_height // 2)
# Calculate the centering offsets
offset_x = (crop_width - (end_x - start_x)) // 2
offset_y = (crop_height - (end_y - start_y)) // 2
# Crop each slice to the central region and center it
cropped_data = np.zeros((crop_height, crop_width, original_shape[2]), dtype=data.dtype)
for i in range(original_shape[2]):
cropped_data[offset_y:(end_y - start_y + offset_y), offset_x:(end_x - start_x + offset_x), i] = data[start_y:end_y, start_x:end_x, i]
# Save the cropped and centered image
cropped_img = nib.Nifti1Image(cropped_data, img.affine, img.header)
nib.save(cropped_img, out_path)
img_path = r"some\path"
out_path = r"some\other\path"
cropNifti(img_path, out_path)
Когда я просматривал как исходное, так и обрезанное изображение, я ожидал, что обрезанное изображение будет перекрываться с центром исходного изображения. Однако в результате обрезанное изображение оказывается сбоку от исходного изображения (левый край обрезанного изображения выравнивается по центру исходного изображения). Я попытался немного изменить код и добавить в параметры img.affine и img.header в надежде, что он сохранит информацию о своем происхождении, но, похоже, это не сработало.
Я также попробовал обрезать изображение с помощью SimpleITK. Хотя результат обрезки центрирован, похоже, он изменил масштаб изображения или размеров вокселей, так что я больше не могу запускать результат в одном из моих конвейеров глубокого обучения.
Я относительно новичок в обработке изображений, спасибо за любые комментарии и помощь.
Аффинное изображение преобразует индексы IJK в координаты RAS по формуле RAS = img.affine @ IJK
. Когда вы удаляете строки, столбцы или фрагменты, то, что раньше было IJK из [0, 0, 0, 1]
, становится [di, dj, dk, 1]
. Чтобы сохранить координаты RAS этого первого воксела (и, следовательно, всех вокселей), нам нужно некоторое преобразование RAS = img.affine @ xfm @ IJK' = img.affine @ IJK + img.affine @ [di, dj, dk, 1]
.
Это преобразование просто:
[[1, 0, 0, di],
[0, 1, 0, dj],
[0, 0, 1, dk],
[0, 0, 0, 1]]
Итак, вы можете обновить свой аффин с помощью:
cropped_affine = nib.affines.from_matvec(np.eye(3), [start_x, start_y, 0])
Это аффинное обновление обрабатывается изображениями nibabel через свойство img.slicer:
import nibabel as nib
img = nib.load(img_path)
new_img = img.slicer[i_start:i_end, j_start:j_end, k_start:k_end]
Итак, в вашем случае:
import nibabel as nib
def cropNifti(img_path, out_path, crop_width=256, crop_height=512):
img = nib.load(img_path)
i_start = max(0, (crop_height - img.shape[0]) // 2)
j_start = max(0, (crop_width - img.shape[1]) // 2)
cropped_img = img.slicer[i_start:i_start + crop_height, j_start:j_start + crop_width]
nib.save(cropped_img, out_path)