best way to apply composite transforms in sitk

I am trying to apply several transforms to an image, i.e. align a set of 2d image to the same space, when I apply the transforms it doesn’t appear to work even though the figures I generate before this operation appear to register correctly between the fixed and moving image.

basically I iterate through multiple pairs of images where the key value pair here is the (i, k), i is the fixed image and k is the moving image, and the value is the registration metric, following the approach implemented in poSSUm, creating a weighted directed graph.

then I need to compose the transformations between a reference image (I am using the first image for now, so 0) and the moving image (j). I use the shortest path between the reference index and the jth imag to get a reversed list of transforms to create a composite transform. however when done, this does not actually create a registered image as would have expected.

I tried using flatten transform, as I noticed that at earlier steps that after the initial k to i registration generates composite, transform and multi-transform information, but it appears either way, only the last transform from the composite is applied, but I am not 100% sure about that.

Its possible I messing up the directed graph, or don’t fully understand the composite transform.

I did see some comments about how the transform generated by the registration doesn’t include the initialization transform… but that seems confusing as when create resampled images comparing i to k the registration looks fine, but the composite doesn’t appear to work.

I need to update this snippet with the latest changes

  for j in range(n_rows):
    # j is the moving image
    trans_list = _calculate_composite(G, reference_index, j)
    # Instanciate composite transform which will handle all the partial
    # transformations.
    composite_transform = sitk.Transform(2, sitk.sitkEuler)
    # Fill the composite transformation with the partial transformations:
    for transform in trans_list:

    reg_key = (reference_index, j)
    if (reg_key in reg_n.keys()):
      f_sitk, t_sitk = read_tiff_image(reg_n[reg_key], page_index=4)
      new_image = resample_rgb(composite_transform,
      resample_image =  os.path.join(top_dir, resample_dir, "resample_affine_{0}.png".format(j))
      writer = sitk.ImageFileWriter()

1 Like

Hello @kayarre,

There are several places where things can go wrong, and it is hard to identify what is the issue given the complicated workflow you present.

Let’s start with the simplest possible error, I assume the transformations you obtain via registration are self contained. That is, there is no missing portion belonging to an initialization transformation, for details see this Jupyter notebook section titled version 1.1.

Given the assumption above, the composite transformation has stack semantics, last added-first applied, so you may be adding your transformations into the composite transform in an incorrect order. Possibly try in reverse order:

for transform in reversed(trans_list):

If this isn’t the issue, please provide a minimal example illustrating the issue so that we can pinpoint the error.

1 Like

I tried reversing the order, but it only rotated the image the other direction. meaning, the first way rotated the image counter clock wise to much and the reverse rotated the image clock wise to much.

Lets start with something like 3 images.
I register image 2 to image 1 with a Moments initialization transformation. save the output transform. trans_2_1.h5

I register image 3 to image 2 with a Moments initialization transformation. save the output transform. trans_3_2.h5

how would I read those transforms and stack them to get image 2 mapped to 1, and image 3 mapped to image 1?

T_32(T_21(Image 3)) ?

When I export the resulting images using the transforms and do a checkerboard comparision for image 2 to 1, and image 3 to 2, the results look correct. but when I use the resulting transforms from transforms read from disk the images subsequently don’t match.

It should be T_21(T_32(Image 3)).

1 Like