Image Registration Method 4

Overview

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

Example Run

Running the Python code with the following inputs:

main('BrainProtonDensitySliceBorder20.png', 'BrainProtonDensitySliceShifted13x17y.png', 'displaceMeth4.hdf5')

produces the text and images below.

Output Text

Text Output (click triangle to collapse)
  0 =   -0.33742 : (0.8883551991522953, 0.4591568796599763)
  1 =   -0.35088 : (1.7268176481128081, 1.004116255836898)
  2 =   -0.36229 : (2.4187469173877156, 1.7260815502387081)
  3 =   -0.37514 : (3.3203576953706744, 2.158629819250346)
  4 =   -0.38488 : (3.9693971620112545, 2.9193845568254146)
  5 =   -0.39582 : (4.580401367036123, 3.711011906935255)
  6 =   -0.40560 : (4.982807469043353, 4.626473172673651)
  7 =   -0.41584 : (5.724526806050685, 5.297183561074937)
  8 =   -0.42722 : (6.3011461810254055, 6.114196471868739)
  9 =   -0.43198 : (6.879495374940256, 6.929985788970921)
 10 =   -0.44823 : (7.679696390998657, 7.529717673982133)
 11 =   -0.47282 : (8.372140895644197, 8.251188815460566)
 12 =   -0.50020 : (9.027329551231393, 9.006654119488385)
 13 =   -0.51452 : (9.406946086345647, 9.931798046814208)
 14 =   -0.54356 : (9.854355564205843, 10.826127269819287)
 15 =   -0.57008 : (10.264665927853011, 11.738073214206194)
 16 =   -0.60484 : (10.776763753895718, 12.597000345319383)
 17 =   -0.65100 : (11.404217723671293, 13.37565400119783)
 18 =   -0.70046 : (11.871902871940648, 14.25954913190524)
 19 =   -0.77212 : (12.347454971019081, 15.139236690679432)
 20 =   -0.86938 : (12.764835887967642, 16.0479683178209)
 21 =   -1.04948 : (13.05232647713824, 17.005751780373025)
 22 =   -1.41999 : (12.554720245893066, 16.95688421826918)
 23 =   -1.23275 : (12.803933391805609, 16.97670360030731)
 24 =   -1.35483 : (13.053245682820764, 16.99523415747041)
 25 =   -1.41953 : (12.928734542524285, 17.00627842938261)
 26 =   -1.41252 : (12.990848387738, 16.99934155452668)
 27 =   -1.42587 : (13.05330474421836, 16.9970062739872)
 28 =   -1.41959 : (13.022106487167733, 16.998803843736308)
 29 =   -1.42511 : (12.99088273126701, 17.000084299691075)
 30 =   -1.42589 : (13.006454996306088, 16.99880165143347)
 31 =   -1.42614 : (12.998831820095416, 17.000511136944098)
 32 =   -1.42621 : (13.002653505928967, 16.999702739484835)
 33 =   -1.42621 : (13.00646513960582, 16.99884819997377)
 34 =   -1.42614 : (13.004549764853339, 16.99923034761956)
-------
itk::simple::TranslationTransform
 TranslationTransform (0x57bbc6fdbe80)
   RTTI typeinfo:   itk::TranslationTransform<double, 2u>
   Reference Count: 2
   Modified Time: 13969
   Debug: Off
   Object Name: 
   Observers: 
     none
   Offset: [13.0045, 16.9992]

Optimizer stop condition: RegularStepGradientDescentOptimizerv4: Step too small after 35 iterations. Current step (0.000976562) is less than minimum step (0.001).
 Iteration: 36
 Metric value: -1.426184883438515

Input Images

_images/ImageRegistrationMethod4_fixed.png

Fixed Image

_images/ImageRegistrationMethod4_moving.png

Moving Image

Output Image

_images/ImageRegistrationMethod4_composition.png

Composition Image

Code

using System;
using itk.simple;

namespace itk.simple.examples
{
    class IterationUpdate : Command
    {
        private ImageRegistrationMethod m_Method;

        public IterationUpdate(ImageRegistrationMethod m)
        {
            m_Method = m;
        }

        public override void Execute()
        {
            VectorDouble pos = m_Method.GetOptimizerPosition();
            Console.Write("{0,3} = {1,10:F5} : [",
                         m_Method.GetOptimizerIteration(),
                         m_Method.GetMetricValue());
            for (int i = 0; i < pos.Count; i++)
            {
                if (i > 0) Console.Write(", ");
                Console.Write("{0:F5}", pos[i]);
            }
            Console.WriteLine("]");
        }
    }

    class ImageRegistrationMethod4
    {
        static void Main(string[] args)
        {
            if (args.Length < 3)
            {
                Console.WriteLine("Usage: ImageRegistrationMethod4 <fixedImageFile> <movingImageFile> <outputTransformFile> [numberOfBins] [samplingPercentage]");
                return;
            }

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

            uint numberOfBins = 24;
            double samplingPercentage = 0.10;

            if (args.Length > 3)
            {
                numberOfBins = uint.Parse(args[3]);
            }
            if (args.Length > 4)
            {
                samplingPercentage = double.Parse(args[4]);
            }

            ImageRegistrationMethod R = new ImageRegistrationMethod();
            R.SetMetricAsMattesMutualInformation(numberOfBins);
            R.SetMetricSamplingPercentage(samplingPercentage);
            R.SetMetricSamplingStrategy(ImageRegistrationMethod.MetricSamplingStrategyType.RANDOM);
            R.SetOptimizerAsRegularStepGradientDescent(1.0, 0.001, 200);
            R.SetInitialTransform(new TranslationTransform(fixedImage.GetDimension()));
            R.SetInterpolator(InterpolatorEnum.sitkLinear);

            IterationUpdate cmd = new IterationUpdate(R);
            R.AddCommand(EventEnum.sitkIterationEvent, cmd);

            Transform outTx = R.Execute(fixedImage, movingImage);

            Console.WriteLine("-------");
            Console.WriteLine(outTx.ToString());
            Console.WriteLine("Optimizer stop condition: " + R.GetOptimizerStopConditionDescription());
            Console.WriteLine(" Iteration: " + R.GetOptimizerIteration());
            Console.WriteLine(" Metric value: " + R.GetMetricValue());

            SimpleITK.WriteTransform(outTx, args[2]);

            ResampleImageFilter resampler = new ResampleImageFilter();
            resampler.SetReferenceImage(fixedImage);
            resampler.SetInterpolator(InterpolatorEnum.sitkLinear);
            resampler.SetDefaultPixelValue(100);
            resampler.SetTransform(outTx);

            Image output = resampler.Execute(movingImage);
            Image simg1 = SimpleITK.Cast(SimpleITK.RescaleIntensity(fixedImage), PixelIDValueEnum.sitkUInt8);
            Image simg2 = SimpleITK.Cast(SimpleITK.RescaleIntensity(output), PixelIDValueEnum.sitkUInt8);
            Image cimg = SimpleITK.Compose(simg1, simg2, SimpleITK.Divide(SimpleITK.Add(simg1, simg2), 2));

            // Show the composition image if SITK_NOSHOW environment variable is not set
            if (Environment.GetEnvironmentVariable("SITK_NOSHOW") == null)
            {
                SimpleITK.Show(cimg, "ImageRegistration4 Composition");
            }
        }
    }
}