Как обрезать изображение NIFTI, сохранив его происхождение?

У меня есть изображение 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. Хотя результат обрезки центрирован, похоже, он изменил масштаб изображения или размеров вокселей, так что я больше не могу запускать результат в одном из моих конвейеров глубокого обучения.

Я относительно новичок в обработке изображений, спасибо за любые комментарии и помощь.

Применение градиента к изображению с помощью CSS
Применение градиента к изображению с помощью CSS
Здравствуйте, братья и сестры, как дела? Недавно я застрял на применении градиента к изображению. Я применял это много раз, но иногда наши требования...
Получение URL-адреса изображения курса в Moodle с помощью PHP
Получение URL-адреса изображения курса в Moodle с помощью PHP
Moodle - это популярная система управления обучением с открытым исходным кодом, используемая многими учебными заведениями и организациями по всему...
0
0
84
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Аффинное изображение преобразует индексы 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)

Другие вопросы по теме