Extremely slow (compared to SimpleITK - Elastix)
Hi,
I am trying to use Elastix in python. I went with itk-elastix first as its the most maintained version that can be easily installed. However, it seems to be having some sort of issues. Im using python 3.9 and the example outline and parameter file from: https://github.com/InsightSoftwareConsortium/ITKElastix/blob/main/examples/ITK_Example03_Masked_3D_Registration.ipynb
When I run this code using SimpleElastix (https://pypi.org/project/SimpleITK-SimpleElastix/), I get a registration in ~5seconds. When I do it with itk-elastix it ran overnight and didnt complete. Both were installed in a fresh python 3.9 environment using pip. itk elastix is version 5.4.0 and sitk elastix is 2.0.0. Simple code is below.
I also tried other parameter files (e.g., default rigid in both versions) and it has the same result.
ITK ELASTIX:
path_param_file = 'parameters.3D.NC.affine.ASGD.001.txt'
fixed_image = itk.imread(path_fixed_image, itk.F)
moving_image = itk.imread(path_moving_image, itk.F)
parameter_object = itk.ParameterObject.New()
parameter_object.AddParameterFile(path_param_file)
parameter_object.SetParameter(0, "WriteResultImage", "true")
elastix_object = itk.ElastixRegistrationMethod.New(fixed_image, moving_image)
elastix_object.SetParameterObject(parameter_object)
elastix_object.SetLogToConsole(True)
elastix_object.UpdateLargestPossibleRegion()
result_image = elastix_object.GetOutput()
result_transform_parameters = elastix_object.GetTransformParameterObject()
SITK ELASTIX:
path_param_file = 'parameters.3D.NC.affine.ASGD.001.txt'
fixed_image = sitk.ReadImage(path_fixed_image)
moving_image = sitk.ReadImage(path_moving_image)
selx = sitk.ElastixImageFilter()
selx.SetMovingImage(moving_image)
selx.SetFixedImage(fixed_image)
parameter_map = sitk.ReadParameterFile(path_param_file)
# parameter_map = sitk.GetDefaultParameterMap("rigid")
selx.SetParameterMap(parameter_map)
# Specify the output directory
selx.SetOutputDirectory(out_path)
# Execute registration
selx.Execute()
# Extract Image
registered_image = selx.GetResultImage()
What version are you using? I remember some slowdowns happening with some versions, and crashes with others (see #265). Later versions should have taken care of that. Is that right, @thewtex?
itk elastix is version 5.4.0 and sitk elastix is 2.0.0. Both on python 3.9
Yes, this is unexpected behavior.
@gattia do you observe the behavior on the referenced example? Or just your own data / code?
I only tried on my own data - I did briefly try seeing if it was a datatype issue by changing the data type in itk elastix, but that didnt seem to fix it in any way. I can try with the example data and report back.
@gattia thanks -- it would be helpful to know if the example notebook also has the same behavior.
Hello @gattia,
Is this issue reproducible with the latest Python package, itk-elastix 0.22.0?
Sorry for the long delays here. I tried out the new version, and I got the same results. Then, I tried the example and it worked fine. Then, I tried to dig into what the root cause was. I noticed two differences.
- I used the class instead of function based approach.
- I set
elastix_object.SetLogToConsole(True)(it was False in the example)
Turns out, it's setting log_to_console to True that causes the error - whether in the functional or class-based usage of the registration. And for reference, the SimpleElastix one just prints to console by default - so you see all of the outputs as its registering and it doesnt have the slow down.
Apologies for the delay - I hope this is helpful.
Anthony.
Class-based, log to console, slow/doesnt solve:
path_param_file = 'parameters.3D.NC.affine.ASGD.001.tx'
fixed_image = itk.imread(path_fixed_image, itk.F)
moving_image = itk.imread(path_moving_image, itk.F)
parameter_object = itk.ParameterObject.New()
parameter_object.AddParameterFile(path_param_file)
parameter_object.SetParameter(0, "WriteResultImage", "true")
elastix_object = itk.ElastixRegistrationMethod.New(fixed_image, moving_image)
elastix_object.SetParameterObject(parameter_object)
elastix_object.SetLogToConsole(True)
elastix_object.UpdateLargestPossibleRegion()
result_image = elastix_object.GetOutput()
result_transform_parameters = elastix_object.GetTransformParameterObject()
Function-based, log to console, slow/doesnt solve:
path_param_file = 'parameters.3D.NC.affine.ASGD.001.tx'
fixed_image = itk.imread(path_fixed_image, itk.F)
moving_image = itk.imread(path_moving_image, itk.F)
parameter_object = itk.ParameterObject.New()
parameter_object.AddParameterFile(path_param_file)
parameter_object.SetParameter(0, "WriteResultImage", "true")
# Call registration function
result_image, result_transform_parameters = itk.elastix_registration_method(
fixed_image, moving_image,
parameter_object=parameter_object,
log_to_console=True
)
Class-based, don't log, fast:
path_param_file = 'parameters.3D.NC.affine.ASGD.001.tx'
fixed_image = itk.imread(path_fixed_image, itk.F)
moving_image = itk.imread(path_moving_image, itk.F)
parameter_object = itk.ParameterObject.New()
parameter_object.AddParameterFile(path_param_file)
parameter_object.SetParameter(0, "WriteResultImage", "true")
elastix_object = itk.ElastixRegistrationMethod.New(fixed_image, moving_image)
elastix_object.SetParameterObject(parameter_object)
elastix_object.SetLogToConsole(False)
elastix_object.UpdateLargestPossibleRegion()
result_image = elastix_object.GetOutput()
result_transform_parameters = elastix_object.GetTransformParameterObject()
Function-based, don't log, fast:
path_param_file = 'parameters.3D.NC.affine.ASGD.001.tx'
fixed_image = itk.imread(path_fixed_image, itk.F)
moving_image = itk.imread(path_moving_image, itk.F)
parameter_object = itk.ParameterObject.New()
parameter_object.AddParameterFile(path_param_file)
parameter_object.SetParameter(0, "WriteResultImage", "true")
# Call registration function
result_image, result_transform_parameters = itk.elastix_registration_method(
fixed_image, moving_image,
parameter_object=parameter_object,
log_to_console=False
)
@gattia that is very helpful, thank you!
@N-Dekker what do you think?