After image registrations it is often useful to apply the transformation as found by the registration to another image. Maybe you want to apply the transformation to an original (larger) image to gain resolution. Or maybe you need the transformation to apply it to a label image (segmentation). The itk.resample_image_filter
function will resample an image given a sampling grid, a spatial transformation, and an interpolation function.
A spatial transformation is defined as a mapping from the fixed image domain to the moving image domain. More information on the precise definition of the transform can be found in the Elastix Manual or the ITK Software Guide.
As an alternative, see the transformix example.
import itk
from itkwidgets import compare, checkerboard
# Import Images
fixed_image = itk.imread('data/CT_2D_head_fixed.mha', itk.F)
moving_image = itk.imread('data/CT_2D_head_moving.mha', itk.F)
# Import Default Parameter Maps
parameter_object = itk.ParameterObject.New()
parameter_map_rigid = parameter_object.GetDefaultParameterMap('rigid')
parameter_object.AddParameterMap(parameter_map_rigid)
parameter_map_affine = parameter_object.GetDefaultParameterMap('affine')
parameter_object.AddParameterMap(parameter_map_affine)
Registration with the registration function...
# Call registration function
result_image_elx, result_transform_parameters = itk.elastix_registration_method(
fixed_image, moving_image,
parameter_object=parameter_object)
Convert the Elastix ParameterMap to ITK Transform's.
euler_transform = itk.Euler2DTransform[itk.D].New()
pm0 = result_transform_parameters.GetParameterMap(0)
center = [float(p) for p in pm0['CenterOfRotationPoint']]
fixed_parameters = itk.OptimizerParameters[itk.D](len(center))
for i, p in enumerate(center):
fixed_parameters[i] = p
euler_transform.SetFixedParameters(fixed_parameters)
elx_parameters = [float(p) for p in pm0['TransformParameters']]
itk_parameters = itk.OptimizerParameters[itk.D](len(elx_parameters))
for i, p in enumerate(elx_parameters):
itk_parameters[i] = p
euler_transform.SetParameters(itk_parameters)
dimension = moving_image.GetImageDimension()
affine_transform = itk.AffineTransform[itk.D, dimension].New()
pm1 = result_transform_parameters.GetParameterMap(1)
center = [float(p) for p in pm1['CenterOfRotationPoint']]
fixed_parameters = itk.OptimizerParameters[itk.D](len(center))
for i, p in enumerate(center):
fixed_parameters[i] = p
affine_transform.SetFixedParameters(fixed_parameters)
elx_parameters = [float(p) for p in pm1['TransformParameters']]
itk_parameters = itk.OptimizerParameters[itk.D](len(elx_parameters))
for i, p in enumerate(elx_parameters):
itk_parameters[i] = p
affine_transform.SetParameters(itk_parameters)
# When creating the composite transform for itk,
# take into account that elastix uses T2(T1(x)) while itk does this the other way around.
# So to get the correct composite transform, add the last transform in elastix first in itk.
composite_transform = itk.CompositeTransform[itk.D, dimension].New()
composite_transform.AddTransform(affine_transform)
composite_transform.AddTransform(euler_transform)
result_image_itk = itk.resample_image_filter(moving_image,
transform=composite_transform,
use_reference_image=True,
reference_image=fixed_image)
The results of the image transform can be visualized with widgets from the itkwidget library such as the checkerboard and compare widgets.
checkerboard(fixed_image, result_image_itk, pattern=5)
VBox(children=(Viewer(annotations=False, interpolation=False, rendered_image=<itk.itkImagePython.itkImageF2; p…
compare(result_image_elx, result_image_itk, link_cmap=True)
AppLayout(children=(HBox(children=(Label(value='Link:'), Checkbox(value=True, description='cmap'), Checkbox(va…