Hello everyone,
I am a bit confused about the registration results I got from performing a rigid alignment between a CT and a PET (of the same subject, which makes it even more confusing for me). I can run it once and get a proper alignment, but it might be off on the next run.
I think the best way to find the problem is to share the code:
def rigid(fixed_image, moving_image, aligned_image=None):
# Define the registration method
registration_method = SimpleITK.ImageRegistrationMethod()
registration_method.SetInterpolator(SimpleITK.sitkLinear)
# Inital alignment of the images
initial_transform = SimpleITK.CenteredTransformInitializer(fixed_image, moving_image,
SimpleITK.Euler3DTransform(),
SimpleITK.CenteredTransformInitializerFilter.GEOMETRY)
registration_method.SetInitialTransform(initial_transform, inPlace=True)
# Only to check the inital alignment
if aligned_image is not None:
aligned_image_parent_directory = os.path.dirname(aligned_image)
centered_image_path = os.path.join(aligned_image_parent_directory, 'rigid_centered_image.nii.gz')
centered_resampled_image = SimpleITK.Resample(moving_image, fixed_image, initial_transform, SimpleITK.sitkLinear)
SimpleITK.WriteImage(centered_resampled_image, centered_image_path)
# Similarity metric settings
registration_method.SetMetricAsMattesMutualInformation(numberOfHistogramBins=50)
registration_method.SetMetricSamplingStrategy(registration_method.EachIteration)
registration_method.SetMetricSamplingPercentage(0.01)
# Optimizer settings
registration_method.SetOptimizerAsGradientDescent(learningRate=2.0,
numberOfIterations=200,
convergenceMinimumValue=1e-6,
convergenceWindowSize=10)
registration_method.SetOptimizerScalesFromPhysicalShift()
# Multi-resolution framework settings
registration_method.SetShrinkFactorsPerLevel(shrinkFactors=[4, 2, 1])
registration_method.SetSmoothingSigmasPerLevel(smoothingSigmas=[2, 1, 0])
registration_method.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn()
final_transform = registration_method.Execute(fixed_image, moving_image)
# Always check the reason optimization terminated.
print('Final metric value: {0}'.format(registration_method.GetMetricValue()))
print('Optimizer\'s stopping condition, {0}'.format(registration_method.GetOptimizerStopConditionDescription()))
if aligned_image is not None:
resampled_image = SimpleITK.Resample(moving_image, fixed_image, final_transform)
SimpleITK.WriteImage(resampled_image, aligned_image)
return final_transform
Sometimes, the registration stops around iteration 9 and around iteration 37.
The initial alignment looks alignment after the initial transform always looks good, so that works fine.
I read through the registration notebooks (6* series) and tried to replicate everything as closely as possible, but obviously, there is something that I am missing and/or not understanding. Maybe you can hint me towards a specific section of the notebooks.
I don’t understand why I receive alternating results. I also tried it with affine registration, but there the optimizer reached the maximum number of iterations (200). So most likely, the problem might the optimizer that I set and the parameters for it. I also tried it with registration_method.Random
first because I thought that the error might stem from there.
Any apparent mistakes in the code or the approach? I really appreciate any help you can provide.