Need help understanding codes from sitk notebook

I need help understanding some codes lines from sitk notebook (63_Registration_Initialization), link here.

I will (1) show the codes that I am using, (2) then ask my specific questions. I have so many questions (I apologise in advance!), and that’s mainly because I don’t want to blindly apply the codes without understanding them. I have changed some parameters from the original notebook, but the final registration is off by few slices/frames.

  1. The codes that I am using for registration:
def multires_registration(fixed_image, moving_image, initial_transform):
    registration_method = sitk.ImageRegistrationMethod()
    registration_method.SetMetricAsMattesMutualInformation(numberOfHistogramBins=50)
    registration_method.SetMetricSamplingStrategy(registration_method.RANDOM)
    registration_method.SetMetricSamplingPercentage(0.5)
    registration_method.SetInterpolator(sitk.sitkLinear)
    registration_method.SetOptimizerAsGradientDescent(
        learningRate=1.0,
        numberOfIterations=100,
        estimateLearningRate=registration_method.Once,
    )
    registration_method.SetOptimizerScalesFromPhysicalShift()
    registration_method.SetInitialTransform(initial_transform, inPlace=False)
    registration_method.SetShrinkFactorsPerLevel(shrinkFactors=[1, 1, 1])
    registration_method.SetSmoothingSigmasPerLevel(smoothingSigmas=[1, 1, 1])
    registration_method.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn()

    final_transform = registration_method.Execute(fixed_image, moving_image)
    print(f"Final metric value: {registration_method.GetMetricValue()}")
    print(
        f"Optimizer's stopping condition, {registration_method.GetOptimizerStopConditionDescription()}"
    )
    return (final_transform, registration_method.GetMetricValue())

# --------     Setting up initial transform ----------------------------
initial_transform = sitk.CenteredTransformInitializer(
    fixed_image,
    moving_image,
    sitk.Euler3DTransform(),
    sitk.CenteredTransformInitializerFilter.MOMENTS,
)
registration_method = sitk.ImageRegistrationMethod()
registration_method.SetMetricAsMattesMutualInformation(numberOfHistogramBins=50)
registration_method.SetMetricSamplingStrategy(registration_method.RANDOM)
registration_method.SetMetricSamplingPercentage(0.5)
registration_method.SetInterpolator(sitk.sitkLinear)
# The order of parameters for the Euler3DTransform is [angle_x, angle_y, angle_z, t_x, t_y, t_z]. The parameter
# sampling grid is centered on the initial_transform parameter values, that are all zero for the rotations. Given
# the number of steps and their length and optimizer scales we have:
# angle_x = 0
# angle_y = -pi, 0, pi
# angle_z = -pi, 0, pi
registration_method.SetOptimizerAsExhaustive(
    numberOfSteps=[0, 1, 1, 0, 0, 0], stepLength=np.pi
)
registration_method.SetOptimizerScales([1, 1, 1, 1, 1, 1])

# Perform the registration in-place so that the initial_transform is modified.
registration_method.SetInitialTransform(initial_transform, inPlace=True)
registration_method.Execute(fixed_image, moving_image)

print("best initial transformation is: " + str(initial_transform.GetParameters()))

#  --------   Calculate final transform 
final_transform, _ = multires_registration(fixed_image, moving_image, initial_transform)
  1. My questions:
    (1) I don’t get registration_method.SetOptimizerAsExhaustive(numberOfSteps=[0, 1, 1, 0, 0, 0], stepLength=np.pi) in setting up the initial transform. Can someone explain what does this do specifically? I don’t get the explanation given in the notebook. What are the 6 parameters in the numberOfSteps related to?

(2) Similarly to above, I don’t know registration_method.SetOptimizerScales([1, 1, 1, 1, 1, 1]). What is meant by “Scales” in registration?

(3) In setting up initial transform, there is registration_method.SetInitialTransform(initial_transform, inPlace=True). On the other hand, it appears again in multires_registration function, but with inPlace=False. Why?

(4) In multires_registration function, there is SetShrinkFactorsPerLevel(shrinkFactors=[1, 1, 1]). What does it do? What are the 3 parameters?

And what is SetSmoothingSigmasPerLevel(smoothingSigmas=[1, 1, 1])? Is it related to some sort of interpolation when shrinking is done?

Hello @Learner,

Welcome to ITK/SimpleITK!

When using the Exhaustive optimization approach we place a grid in the transformation parameter space and evaluate the similarity metric for all transformations defined by the grid.

The grid is defined by the numberOfSteps, stepLength parameters and the SetOptimizerScales method. If i is the transformation parameter index (for example, i==2 for Euler3DTransform, angle_x, angle_y, angle_z, t_x, t_y, t_z, means we are dealing with angle_z).

The grid in parameter space is defined as follows
[initial_transform.GetParameters()[i] - optimizer_scales[i] \cdot stepLength \cdot numberOfSteps[i],…,
initial_transform.GetParameters(),…,
initial_transform.GetParameters()+optimizer_scales[i] \cdot stepLength \cdot numberOfSteps[i]]

With respect to the remaining questions, please see the SimpleITK online Tutorial. The videos may be a bit outdated, but they mostly match the current toolkit status. If after going through the tutorial you still have questions, post them on the forum and we’ll do our best to help you.

3 Likes