Register two binary Images of different size and resolution

Hello everyone,

I am currently working on project, where i want to register 2 images of different modality. One image is a MALDI image with a low resolution (5um). The other image is an fluorescence image of the same section but with a much higher resolution (0.4 um). My goal is to find a good registration.
I already spend weeks to understand Elastix and all its functionality but I am still bemused.

Hopefully someone had the same struggle I have and can help me fixing my problems.

Hello @Flo_Van_Wickeren,

It is hard to guess why the registration is failing without more details. From what you provided we only know that you are registering microscopy images. Some common pitfalls:

  1. Registration initialization - initial transformation parameter values are too far from the correct values and the optimization converges to a local minimum.
  2. Transformation type - when there is a large global transformation combined with local deformations, using only a deformation transformation (theoretically correct) will not work. Actually this is an instance of (1). Instead estimate an initial global transformation and then estimate the deformation transformation on top of that.
  3. Numerical stability issues. By default ITK reads images and converts sizes to mm. When working with microscopy this can introduce computational instabilities (your images have a spacing of 0.005x0.005 and 0.0004x0.0004). As we do not know how the images were read into memory you should check to see what image.GetSpacing() returns (0.005 or 5), avoid the tiny spacing.

Thank you @zivy for your reply.
These are the pictures I want to perfrom a co-registration on.
Here are some informations about the pictures, produced by SimpleITK:
Fluorescence_Picture (used as fixed image):
size: (3441, 3771)
spacing: (0.000334, 0.000334)
Origin: (0.0, 0.0)
Direction: (1.0, 0.0, 0.0, 1.0)
Min: 0.0
Max: 204.4250030517578
Mean: 10.537444104225761
MALDI image (used as moving image):
size: (200, 203)
spacing: (0.005, 0.005)
Origin: (0.0, 0.0)
Direction: (1.0, 0.0, 0.0, 1.0)
Min: 0.0
Max: 65535.0
Mean: 2781.27815270936

Do process both of these images, I thought maybe a binarisation would be good. So I performed sitk.OtsuThreshold on both images.

To perform the registration i used the following code:

# Set the initial moving transform
initial_transform = sitk.CenteredTransformInitializer(FixedImage_bin, MovingImage_bin, sitk.Euler2DTransform(), sitk.CenteredTransformInitializerFilter.GEOMETRY)
# Set the registration method
registration_method = sitk.ImageRegistrationMethod()
registration_method.SetOptimizerAsGradientDescent(learningRate=0.1, numberOfIterations=500, convergenceMinimumValue=1e-6, convergenceWindowSize=10)
registration_method.SetInitialTransform(initial_transform, inPlace=False)
# Run the registration
final_transform = registration_method.Execute(FixedImage, MovingImage)

Are there any suggestions, where I have to change something. Or is the used code completly useless for my approach?

You mentioned in the topic subject that you want to register binary images. Automatic intensity-based registration methods generally struggle with directly registering binary images, slightly better alignment may not lead to slightly better objective function value.

You can easily fix this, by registering not the binary images, but instead registering distance maps computed from the binary images. You can use signed Maurer distance. It can even be used for deformable registration.


Thanks for that hint @lassoan.
However, what you would suggest to register both of these images if you would start from the beginning. I am asking because it is very hard to adapt the workflows from the notebooks and example to my specific problem.

Hello @Flo_Van_Wickeren,

Something is wrong with the fluorescence image you provided, its spacing doesn’t match what you specified (1.0 instead of 0.000334):

import SimpleITK as sitk

def print_image_information(image, title):
  print(f"Information for {title}:")    
  print(f"\tSize: {image.GetSize()}")
  print(f"\tSpacing: {image.GetSpacing()}")
  print(f"\tPhysical size: {[sz*spc for sz,spc in zip(image.GetSize(), image.GetSpacing())]}")
  print(f"\tNumber of channels: {image.GetNumberOfComponentsPerPixel()}")

maldi = sitk.ReadImage("MALDI_Picture.ome.tif")
fluo = sitk.ReadImage("fluo_image_cells.tif")

print_image_information(maldi, "MALDI")
print_image_information(fluo, "Fluorescence")

To register the two images, register the DAPI channel from the fluorescence image (extract it using VectorIndexSelectionCast) to the MALDI image. Also, because the information is sparse, use a mask during the registration (SetMetricFixedMask).

Finally, some SimpleITK based code that may be of interest:


Thanks for that feedback @zivy.
Yes you are right! The spacing of the fluorescence image is not set to the correct value in the loaded picture due to the fact, that I got this picture from a colleague who just send it as a jpg. To set it up right, I change the spacing in my python scripts.
Until now i tried various combinations of different paramteres for the registration but nothing really works. Is it maybe possible that someone can look through my code and give me some advise how I can overcome my problems?