\(\newcommand{L}[1]{\| #1 \|}\newcommand{VL}[1]{\L{ \vec{#1} }}\newcommand{R}[1]{\operatorname{Re}\,(#1)}\newcommand{I}[1]{\operatorname{Im}\, (#1)}\)

Making and saving new images in nibabelΒΆ

We often want to do some processing on an image, then save the processed image back to an image file on disk.

When we load an image from disk, we get back an image object. When we load a NIfTI .nii image, we get an image object of type Nifti1Image.

>>> import numpy as np
>>> import nibabel as nib
>>> img = nib.load('ds114_sub009_highres.nii')
>>> type(img)
<class 'nibabel.nifti1.Nifti1Image'>

Maybe we were worried about some very high values in the image, and we wanted to clip them down to a more reasonable number:

>>> data = img.get_data()
>>> data.max()  # doctest: +SKIP
3237.0

We might consider clipping the top 5 percent of voxel values:

>>> data = img.get_data()
>>> top_95_thresh = np.percentile(data, 95)
>>> top_95_thresh
722.0
>>> new_data = data.copy()
>>> new_data[new_data > top_95_thresh] = top_95_thresh
>>> new_data.max()  # doctest: +SKIP
722.0

We can make a new Nifti1Image by constructing it directly. We pass the new data, the image affine, and (optionally) a template header for the image:

>>> clipped_img = nib.Nifti1Image(new_data, img.affine, img.header)
>>> type(clipped_img)
<class 'nibabel.nifti1.Nifti1Image'>

The nib.Nifti1Image call copies and adapts the passed header to the new image data shape, and affine.

>>> # Show the original data array shape from the original header
>>> img.header.get_data_shape()
(256, 156, 256)
>>> # Here we construct a new empty header
>>> empty_header = nib.Nifti1Header()
>>> empty_header.get_data_shape()
(0,)

If we make a new image with this header, the constructor routine fixes the header to have the correct shape for the data array:

>>> another_img = nib.Nifti1Image(new_data, img.affine, empty_header)
>>> another_img.header.get_data_shape()
(256, 156, 256)

We can save the new image with nib.save:

>>> nib.save(clipped_img, 'clipped_image.nii')

This image has the clipped data:

>>> clipped_back = nib.load('clipped_image.nii')
>>> clipped_back.get_data().max()  # doctest: +SKIP
722.0