Reputation: 310
I'm changing the voxel size of some 3D volumes. How do I edit the pixdim
field and calculate the new affine
?
I have some MR volumes which are anisotropic, the voxel sizes are, say, 0.5 x 0.5 x 3
mm. And I've some code to interpolate them into isotropic (like 0.5 x 0.5 x 0.5
mm voxel size) volumes.
The problem is when I need to save the file, I have to calculate the affine to map the now denser voxels in ijk space to reference xyz space. How do I do that?
First, my thought is to use the old affine and calculate the new affine.
For example, if volume V has a shape of 256 x 256 x 20
voxels with 0.5 x 0.5 x 3
voxel size and interpolated into volume U 256 x 256 x 120
voxels with 0.5 x 0.5 x 0.5
voxelsize.
The old affine will do [255 255 19]OA = [X Y Z]
and the new affine should do [255 255 119]NA = [X Y Z]
and we know AX=B X=inverse(A)B
.
So the new affine should be inverse([255 255 119])[X Y Z]
.
However, the inverse matrix only exists for a square matrix. There will be no such thing of inverse([255 255 119])
.
And it seems there is no set_voxel_size
function in python-nibabel matlab-nifti-toolbox and so. How does that a case?
How do I change the voxel size explicitly?
Upvotes: 1
Views: 2545
Reputation: 19310
I am facing a similar problem at the moment. To solve it, I create a nifti header from scratch with 0.5 mm isotropic voxels and the desired shape. You can use header.set_zooms()
to set the voxel size in mm.
import nibabel as nib
import numpy as np
hdr = nib.Nifti1Header()
hdr.set_data_shape((256, 256, 120))
hdr.set_zooms((0.5, 0.5, 0.5)) # set voxel size
hdr.set_xyzt_units(2) # millimeters
dst_aff = hdr.get_best_affine()
src_aff = np.eye(4)
src_aff_inv = np.linalg.inv(src_aff)
transform = np.matmul(src_aff_inv, dst_aff)
Upvotes: 1