3D MRI IMAGE REGISTRATION

Hello dear community , i need your help !!!
I applied this registration code on 3D MRI images, but as you can see in the photo, the images are not perfectly aligned.
any solutions ?
image
here is the code

fixed_image_name ='data_t1_ref.hdr'
moving_image_name= 'data_t1_4_inh.hdr'
fixed_image =  sitk.ReadImage(fixed_image_name, sitk.sitkFloat32)
moving_image = sitk.ReadImage(moving_image_name, sitk.sitkFloat32)

initial_transform=sitk.CenteredTransformInitializer(fixed_image,moving_image,sitk.Euler3DTransform(), sitk.CenteredTransformInitializerFilter.GEOMETRY)
moving_resampled = sitk.Resample(moving_image, fixed_image, initial_transform, sitk.sitkLinear, 0.0, moving_image.GetPixelID())
registration_method = sitk.ImageRegistrationMethod()
registration_method.SetMetricAsCorrelation()
registration_method.SetMetricSamplingStrategy(registration_method.RANDOM)
registration_method.SetMetricSamplingPercentage(0.01)
registration_method.SetInterpolator(sitk.sitkLinear)
registration_method.SetOptimizerAsGradientDescent(learningRate=1.0, numberOfIterations=100, convergenceMinimumValue=1e-6, convergenceWindowSize=10)
registration_method.SetOptimizerScalesFromPhysicalShift()
registration_method.SetShrinkFactorsPerLevel(shrinkFactors = [4,2,1])
registration_method.SetSmoothingSigmasPerLevel(smoothingSigmas=[2,1,0])
registration_method.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn()
registration_method.SetInitialTransform(initial_transform, inPlace=False)
final_transform = registration_method.Execute(sitk.Cast(fixed_image, sitk.sitkFloat32), sitk.Cast(moving_image, sitk.sitkFloat32))
moving_resampled = sitk.Resample(moving_image, fixed_image, final_transform, sitk.sitkLinear, 0.0, moving_image.GetPixelID())

Hello @Dodox,

Without additional information it is almost impossible to help you. One thing I highly recommend is always printing the final metric value (which you can compare to the initial value) and the optimizer’s stopping condition:

print('Final metric value: {0}'.format(registration_method.GetMetricValue()))
print('Optimizer\'s stopping condition, {0}'.format(registration_method.GetOptimizerStopConditionDescription()))

That being said, from looking at the code, you set numberOfIterations=100. I highly suspect that you are seeing early termination. By printing the stopping condition you will see if this is the case. If it is, just increase the number of iterations.

This stopping condition is used for two things: (1) setting a small number like 100 for initial evaluation of the registration, to quickly see if the optimization is going in the right direction and then increase the number. (2) to provide a fixed bound on the optimization so that it is terminated and does not continue long after it is close enough to the minimum with oscillations around it.

If this is not the issue, please provide additional details, possibly the plots of the similarity metric during the registration (as in this notebook).

1 Like

hello @zivy

I printed the final metric value but i don’t know how to get the initial value

i added also the plots of the similarity metric during the registration

so when numberOfIterations=100,
Final metric value: -0.8055520260648437
Optimizer’s stopping condition, GradientDescentOptimizerv4Template: Convergence checker passed at iteration 10.
image

and for example when numberOfIterations=1000
Final metric value: -0.9187471229504175
Optimizer’s stopping condition, GradientDescentOptimizerv4Template: Convergence checker passed at iteration 12.
do you need other informations ? please help me :disappointed:
Thank you
image
image

Hello @Dodox,

OK, it looks like my hunch was wrong and it is not early termination due to small number of iterations. One thing that I am not sure of with the image you provided is with respect to the registration errors as it is hard to judge based on the fused images.

As a first step, can you try a manual registration and evaluation of that registration as shown in this notebook section titled Register using manual initialization. I am not sure if the MR images are not 180 degrees from each other as in the images you provided the head is almost spherical (easy to identify gross errors in slices that include the nose/eyes).

In addition to ITK core registration classes, you may also try ITK-based registration tools.

For many years, I though that registration was hard. I had to spend several days to figure out optimization parameters for each new registration problem. With more experience, I got it down to about half day, but it was still a lot of trial and error and kind of an art. Then I discovered Elastix, which almost always got the registration right with the same default initial parameters (either rigid; or rigid+bspline). So, I would highly recommend to try Elastix. You can download command-line tool from their website, use SimpleElastix in Python, or use a very simple visual GUI in 3D Slicer and its SlicerElastix extension.

BrainsFit registration tool in BRAINSTools is specifically developed for brain MRI registration, so it is also expected to work well with default parameters, without any tuning. This is also available in 3D Slicer with a convenient graphical user interface (it is bundled with the default application, the module name is “General registration (BRAINS)”). You can find a number of parameter presets in the registration case library.

1 Like

hello @lassoan @zivy
thanks for your advices, i will try to do all this and i will get back to you as soon as possible