Hello, All. I am trying to register vertebra in spine CT and MRI.
The average size of the vertebra MRI is (200-300, 100-200, 15).
The average number of intensity in MRI is around 500. Which is calculated by this.
min_max = np.percentile(new_scan_array.flatten(),[2,98]) num_bins = int(min_max-min_max)
The average size of the vertebra CT is (200-300, 100-200, 30-50).
THe average number of intensity in CT is around 1000.
Here are two examples of how the crop MRI and CT looks like. (The examples shown are T2-weighted, I have also tried with T1-weighted)
For Initialization, I have used the centorid of the interested vertebra. (The centroids are marked manually in the whole spine scan, and when I cropped the CT and MRI, I maintained the relative position of all vertebrae by resetting the origin.)
initial_transform = sitk.LandmarkBasedTransformInitializer(sitk.VersorRigid3DTransform(), fixed_image_points_flat, moving_image_points_flat)
Here is the visualization of the initialization:
Then I set up the registration method:
registration_method = sitk.ImageRegistrationMethod() # Similarity metric settings. registration_method.SetMetricAsMattesMutualInformation(numberOfHistogramBins=1000) # registration_method.SetMetricAsANTSNeighborhoodCorrelation(radius=20) registration_method.SetMetricSamplingStrategy(registration_method.NONE) # registration_method.SetMetricSamplingPercentage(0.1) registration_method.SetInterpolator(sitk.sitkLinear) # Optimizer settings. registration_method.SetOptimizerAsGradientDescent(learningRate=1, numberOfIterations=100, convergenceMinimumValue=1e-6, convergenceWindowSize=10) # registration_method.SetOptimizerAsRegularStepGradientDescent(learningRate=1,minStep = 1e-6, relaxationFactor = 0.9, # numberOfIterations=100) registration_method.SetOptimizerScalesFromPhysicalShift() # Setup for the multi-resolution framework. registration_method.SetShrinkFactorsPerLevel(shrinkFactors = [4,2,1]) registration_method.SetSmoothingSigmasPerLevel(smoothingSigmas=[2,1,0]) registration_method.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn()
I used MattesMutualInformation and GradientDescent, I set the numberOfHistogramBins to 1000 because the number of intensity values is around 1000. (Please correct me if my intuition is wrong here.)
The numberOfIteration I tired is 100 or 200.
Here are the curves of the metric value:
And here is the final registration result:
As you can see, vertebra 9 is registered well while vertebra 19 is not so good. I want the algorithm to be robust to every vertebra, so do you have any ideas for the method or parameters that I have used? It would be very nice of you to provide some practical advice. If there is more needed to be seen, please inform me.
By the way, I have also tried with the ITK_reigstration_v4 method.
optimized_transform = sitk.VersorRigid3DTransform() registration_method.SetMovingInitialTransform(initial_transform) registration_method.SetInitialTransform(optimized_transform, inPlace=False) final_transform_v4 = registration_method.Execute(fixed_image, moving_image) final_transform_v4.AddTransform(initial_transform)
But it didn’t work at all, the result made no sense.