Note
Go to the end to download the full example code
Affine transforms¶
Display an image and its corners before and after an affine transform
import numpy as np
import scipy.ndimage as ndi
import napari
# Create a random image
image = np.random.random((5, 5))
# Define an affine transform
affine = np.array([[1, -1, 4], [2, 3, 2], [0, 0, 1]])
# Define the corners of the image, including in homogeneous space
corners = np.array([[0, 0], [4, 0], [0, 4], [4, 4]])
corners_h = np.concatenate([corners, np.ones((4, 1))], axis=1)
viewer = napari.Viewer()
# Add the original image and its corners
viewer.add_image(image, name='background', colormap='red', opacity=.5)
viewer.add_points(corners_h[:, :-1], size=0.5, opacity=.5, face_color=[0.8, 0, 0, 0.8], name='bg corners')
# Add another copy of the image, now with a transform, and add its transformed corners
viewer.add_image(image, colormap='blue', opacity=.5, name='moving', affine=affine)
viewer.add_points((corners_h @ affine.T)[:, :-1], size=0.5, opacity=.5, face_color=[0, 0, 0.8, 0.8], name='mv corners')
# Note how the transformed corner points remain at the corners of the transformed image
# Now add the a regridded version of the image transformed with scipy.ndimage.affine_transform
# Note that we have to use the inverse of the affine as scipy does `pull` (or `backward`) resampling,
# transforming the output space to the input to locate data, but napari does `push` (or `forward`) direction,
# transforming input to output.
scipy_affine = ndi.affine_transform(image, np.linalg.inv(affine), output_shape=(10, 25), order=5)
viewer.add_image(scipy_affine, colormap='green', opacity=.5, name='scipy')
# Reset the view
viewer.reset_view()
if __name__ == '__main__':
napari.run()