Image Registration Optimizer Weights

If you are not familiar with the SimpleITK registration framework we recommend that you read the registration overview before continuing with the example.

Overview

The image registration framework allows us to disable subsets of the transformation parameters so that we can use a lower dimensional transformation. In some cases, if we have some better prior knowledge we can weigh the parameters accordingly (this is much harder to utilize to get a desired effect than disabling parameters).

In this example, we work with a 3D rigid transformation using the Euler parameterization, but we only allow rotation around the z axis. As there is no transformation that represents this subspace of rigid transformations, we use the SetOptimizerWeights method to disable rotations around the x and y axes. The order of the weights in the weights parameter matches the order of parameters returned from the transformation GetParameters method. For the Euler3DTransform the order is [angleX, angleY, angleZ, tx, ty, tz], so our weights vector is [0,0,1,1,1,1].

Code

using System;
using itk.simple;

namespace itk.simple.examples
{
    class ImageRegistrationOptimizerWeights
    {
        static void Main(string[] args)
        {
            if (args.Length < 3)
            {
                Console.WriteLine("Usage: ImageRegistrationOptimizerWeights <fixedImageFile> <movingImageFile> <outputTransformFile>");
                return;
            }

            Image fixedImage = SimpleITK.ReadImage(args[0], PixelIDValueEnum.sitkFloat32);
            Image movingImage = SimpleITK.ReadImage(args[1], PixelIDValueEnum.sitkFloat32);

            // initialization
            Transform transform = SimpleITK.CenteredTransformInitializer(
                fixedImage,
                movingImage,
                new Euler3DTransform(),
                CenteredTransformInitializerFilter.OperationModeType.GEOMETRY);

            // registration
            ImageRegistrationMethod registrationMethod = new ImageRegistrationMethod();
            registrationMethod.SetMetricAsCorrelation();
            registrationMethod.SetMetricSamplingStrategy(ImageRegistrationMethod.MetricSamplingStrategyType.NONE);
            registrationMethod.SetInterpolator(InterpolatorEnum.sitkLinear);
            registrationMethod.SetOptimizerAsGradientDescent(1.0,   // learningRate
                                                             300,   // numberOfIterations
                                                             1e-6,  // convergenceMinimumValue
                                                             10);   // convergenceWindowSize
            registrationMethod.SetOptimizerScalesFromPhysicalShift();
            registrationMethod.SetInitialTransform(transform, true);  // inPlace=true

            // Set optimizer weights: [0, 0, 1, 1, 1, 1] - disable rotation around x and y axes
            VectorDouble weights = new VectorDouble(new double[] { 0, 0, 1, 1, 1, 1 });
            registrationMethod.SetOptimizerWeights(weights);

            registrationMethod.Execute(fixedImage, movingImage);

            Console.WriteLine("-------");
            Console.WriteLine("Final transform parameters: " + transform.GetParameters());
            Console.WriteLine("Optimizer stop condition: " + registrationMethod.GetOptimizerStopConditionDescription());
            Console.WriteLine("Iteration: " + registrationMethod.GetOptimizerIteration());
            Console.WriteLine("Metric value: " + registrationMethod.GetMetricValue());

            SimpleITK.WriteTransform(transform, args[2]);
        }
    }
}