Image Registration Method BSpline 2
If you are not familiar with the SimpleITK registration framework we recommend that you read the registration overview before continuing with the example.
Overview
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()
{
Console.Write(String.Format("{0,3}", m_Method.GetOptimizerIteration()));
Console.WriteLine(String.Format(" = {0,10:F5}", m_Method.GetMetricValue()));
Console.WriteLine(String.Format("\t#: {0}", m_Method.GetOptimizerPosition().Count));
}
}
class MultiResolutionIterationUpdate : Command
{
private ImageRegistrationMethod m_Method;
public MultiResolutionIterationUpdate(ImageRegistrationMethod m)
{
m_Method = m;
}
public override void Execute()
{
Console.WriteLine("--------- Resolution Changing ---------");
}
}
class ImageRegistrationMethodBSpline2
{
static void Main(string[] args)
{
if (args.Length < 3)
{
Console.WriteLine("Usage: {0} <fixedImageFile> <movingImageFile> <outputTransformFile>",
System.AppDomain.CurrentDomain.FriendlyName);
return;
}
Image fixedImage = SimpleITK.ReadImage(args[0], PixelIDValueEnum.sitkFloat32);
Image movingImage = SimpleITK.ReadImage(args[1], PixelIDValueEnum.sitkFloat32);
VectorUInt32 transformDomainMeshSize = new VectorUInt32();
for (uint i = 0; i < movingImage.GetDimension(); i++)
{
transformDomainMeshSize.Add(10);
}
Transform tx = SimpleITK.BSplineTransformInitializer(fixedImage, transformDomainMeshSize);
Console.WriteLine("Initial Parameters:");
VectorDouble initialParams = tx.GetParameters();
Console.Write(String.Format("[{0:F5}", initialParams[0]));
for (int i = 1; i < initialParams.Count; i++)
{
Console.Write(String.Format(", {0:F5}", initialParams[i]));
}
Console.WriteLine("]");
ImageRegistrationMethod R = new ImageRegistrationMethod();
R.SetMetricAsMattesMutualInformation(50);
double learningRate = 5.0;
uint numberOfIterations = 100;
double convergenceMinimumValue = 1e-4;
uint convergenceWindowSize = 5;
R.SetOptimizerAsGradientDescentLineSearch(learningRate, numberOfIterations, convergenceMinimumValue, convergenceWindowSize);
R.SetOptimizerScalesFromPhysicalShift();
R.SetInitialTransform(tx);
R.SetInterpolator(InterpolatorEnum.sitkLinear);
VectorUInt32 shrinkFactors = new VectorUInt32();
shrinkFactors.Add(6); shrinkFactors.Add(2); shrinkFactors.Add(1);
R.SetShrinkFactorsPerLevel(shrinkFactors);
VectorDouble smoothingSigmas = new VectorDouble();
smoothingSigmas.Add(6); smoothingSigmas.Add(2); smoothingSigmas.Add(1);
R.SetSmoothingSigmasPerLevel(smoothingSigmas);
IterationUpdate cmd1 = new IterationUpdate(R);
R.AddCommand(EventEnum.sitkIterationEvent, cmd1);
MultiResolutionIterationUpdate cmd2 = new MultiResolutionIterationUpdate(R);
R.AddCommand(EventEnum.sitkMultiResolutionIterationEvent, cmd2);
Transform outTx = R.Execute(fixedImage, movingImage);
Console.WriteLine("-------");
Console.WriteLine(outTx.ToString());
Console.WriteLine(String.Format("Optimizer stop condition: {0}", R.GetOptimizerStopConditionDescription()));
Console.WriteLine(String.Format(" Iteration: {0}", R.GetOptimizerIteration()));
Console.WriteLine(String.Format(" Metric value: {0}", R.GetMetricValue()));
SimpleITK.WriteTransform(outTx, args[2]);
if (Environment.GetEnvironmentVariable("SITK_NOSHOW") == null)
{
ResampleImageFilter resampler = new ResampleImageFilter();
resampler.SetReferenceImage(fixedImage);
resampler.SetInterpolator(InterpolatorEnum.sitkLinear);
resampler.SetDefaultPixelValue(100);
resampler.SetTransform(outTx);
Image outputImage = resampler.Execute(movingImage);
Image simg1 = SimpleITK.Cast(SimpleITK.RescaleIntensity(fixedImage), PixelIDValueEnum.sitkUInt8);
Image simg2 = SimpleITK.Cast(SimpleITK.RescaleIntensity(outputImage), PixelIDValueEnum.sitkUInt8);
Image cimg = SimpleITK.Compose(simg1, simg2, SimpleITK.Divide(SimpleITK.Add(simg1, simg2), 2.0));
SimpleITK.Show(cimg, "ImageRegistrationMethodBSpline2 Composition");
}
}
}
}
#include <SimpleITK.h>
#include <iostream>
#include <stdlib.h>
#include <iomanip>
namespace sitk = itk::simple;
class IterationUpdate
{
public:
IterationUpdate(const sitk::ImageRegistrationMethod & m)
: m_Method(m)
{}
void
Execute()
{
std::cout << std::setw(3) << m_Method.GetOptimizerIteration();
std::cout << " = " << std::setw(10) << std::setprecision(5) << m_Method.GetMetricValue() << std::endl;
std::cout << "\t#: " << m_Method.GetOptimizerPosition().size() << std::endl;
}
private:
const sitk::ImageRegistrationMethod & m_Method;
};
int
main(int argc, char * argv[])
{
if (argc < 4)
{
std::cerr << "Usage: " << argv[0] << " <fixedImageFile> <movingImageFile> <outputTransformFile>" << std::endl;
return 1;
}
sitk::Image fixed = sitk::ReadImage(argv[1], sitk::sitkFloat32);
sitk::Image moving = sitk::ReadImage(argv[2], sitk::sitkFloat32);
std::vector<unsigned int> transformDomainMeshSize(moving.GetDimension(), 10);
sitk::Transform tx = sitk::BSplineTransformInitializer(fixed, transformDomainMeshSize);
std::cout << "Initial Parameters:" << std::endl;
std::vector<double> initialParams = tx.GetParameters();
std::cout << "[";
std::cout << std::setprecision(5) << std::fixed << initialParams[0];
for (size_t i = 1; i < initialParams.size(); i++)
{
std::cout << ", " << std::setprecision(5) << std::fixed << initialParams[i];
}
std::cout << "]" << std::endl;
sitk::ImageRegistrationMethod R;
R.SetMetricAsMattesMutualInformation(50);
double learningRate = 5.0;
unsigned int numberOfIterations = 100;
double convergenceMinimumValue = 1e-4;
unsigned int convergenceWindowSize = 5;
R.SetOptimizerAsGradientDescentLineSearch(
learningRate, numberOfIterations, convergenceMinimumValue, convergenceWindowSize);
R.SetOptimizerScalesFromPhysicalShift();
R.SetInitialTransform(tx);
R.SetInterpolator(sitk::sitkLinear);
R.SetShrinkFactorsPerLevel(std::vector<unsigned int>{ 6, 2, 1 });
R.SetSmoothingSigmasPerLevel(std::vector<double>{ 6.0, 2.0, 1.0 });
IterationUpdate cmd1(R);
R.AddCommand(sitk::sitkIterationEvent, [&cmd1]() { cmd1.Execute(); });
R.AddCommand(sitk::sitkMultiResolutionIterationEvent,
[]() { std::cout << "--------- Resolution Changing ---------" << std::endl; });
sitk::Transform outTx = R.Execute(fixed, moving);
std::cout << "-------" << std::endl;
std::cout << outTx.ToString() << std::endl;
std::cout << "Optimizer stop condition: " << R.GetOptimizerStopConditionDescription() << std::endl;
std::cout << " Iteration: " << R.GetOptimizerIteration() << std::endl;
std::cout << " Metric value: " << R.GetMetricValue() << std::endl;
sitk::WriteTransform(outTx, argv[3]);
if (getenv("SITK_NOSHOW") == NULL)
{
sitk::ResampleImageFilter resampler;
resampler.SetReferenceImage(fixed);
resampler.SetInterpolator(sitk::sitkLinear);
resampler.SetDefaultPixelValue(100);
resampler.SetTransform(outTx);
sitk::Image out = resampler.Execute(moving);
sitk::Image simg1 = sitk::Cast(sitk::RescaleIntensity(fixed), sitk::sitkUInt8);
sitk::Image simg2 = sitk::Cast(sitk::RescaleIntensity(out), sitk::sitkUInt8);
sitk::Image cimg = sitk::Compose(simg1, simg2, sitk::Divide(sitk::Add(simg1, simg2), 2.0));
sitk::Show(cimg, "ImageRegistrationMethodBSpline2 Composition");
}
return 0;
}
import org.itk.simple.*;
class IterationUpdate extends Command {
private ImageRegistrationMethod method;
public IterationUpdate(ImageRegistrationMethod m) {
method = m;
}
public void execute() {
System.out.printf("%3d", method.getOptimizerIteration());
System.out.printf(" = %10.5f%n", method.getMetricValue());
System.out.println("\t#: " + method.getOptimizerPosition().size());
}
}
class MultiResolutionIterationUpdate extends Command {
private ImageRegistrationMethod method;
public MultiResolutionIterationUpdate(ImageRegistrationMethod m) {
method = m;
}
public void execute() {
System.out.println("--------- Resolution Changing ---------");
}
}
class ImageRegistrationMethodBSpline2 {
public static void main(String[] args) {
if (args.length < 3) {
System.out.println("Usage: ImageRegistrationMethodBSpline2 <fixedImageFile> <movingImageFile> <outputTransformFile>");
return;
}
Image fixedImage = SimpleITK.readImage(args[0], PixelIDValueEnum.sitkFloat32);
Image movingImage = SimpleITK.readImage(args[1], PixelIDValueEnum.sitkFloat32);
// Create transform domain mesh size vector
VectorUInt32 transformDomainMeshSize = new VectorUInt32();
for (int i = 0; i < movingImage.getDimension(); i++) {
transformDomainMeshSize.add(10L);
}
Transform tx = SimpleITK.bSplineTransformInitializer(fixedImage, transformDomainMeshSize);
System.out.println("Initial Parameters:");
VectorDouble initialParams = tx.getParameters();
System.out.print("[");
System.out.printf("%.5f", initialParams.get(0));
for (int i = 1; i < initialParams.size(); i++) {
System.out.printf(", %.5f", initialParams.get(i));
}
System.out.println("]");
ImageRegistrationMethod R = new ImageRegistrationMethod();
R.setMetricAsMattesMutualInformation(50);
double learningRate = 5.0;
int numberOfIterations = 100;
double convergenceMinimumValue = 1e-4;
int convergenceWindowSize = 5;
R.setOptimizerAsGradientDescentLineSearch(learningRate, numberOfIterations, convergenceMinimumValue, convergenceWindowSize);
R.setOptimizerScalesFromPhysicalShift();
R.setInitialTransform(tx);
R.setInterpolator(InterpolatorEnum.sitkLinear);
VectorUInt32 shrinkFactors = new VectorUInt32();
shrinkFactors.add(6L); shrinkFactors.add(2L); shrinkFactors.add(1L);
R.setShrinkFactorsPerLevel(shrinkFactors);
VectorDouble smoothingSigmas = new VectorDouble();
smoothingSigmas.add(6.0); smoothingSigmas.add(2.0); smoothingSigmas.add(1.0);
R.setSmoothingSigmasPerLevel(smoothingSigmas);
IterationUpdate cmd1 = new IterationUpdate(R);
R.addCommand(EventEnum.sitkIterationEvent, cmd1);
MultiResolutionIterationUpdate cmd2 = new MultiResolutionIterationUpdate(R);
R.addCommand(EventEnum.sitkMultiResolutionIterationEvent, cmd2);
Transform outTx = R.execute(fixedImage, movingImage);
System.out.println("-------");
System.out.println(outTx.toString());
System.out.println("Optimizer stop condition: " + R.getOptimizerStopConditionDescription());
System.out.println(" Iteration: " + R.getOptimizerIteration());
System.out.println(" Metric value: " + R.getMetricValue());
SimpleITK.writeTransform(outTx, args[2]);
if (System.getenv("SITK_NOSHOW") == null) {
ResampleImageFilter resampler = new ResampleImageFilter();
resampler.setReferenceImage(fixedImage);
resampler.setInterpolator(InterpolatorEnum.sitkLinear);
resampler.setDefaultPixelValue(100);
resampler.setTransform(outTx);
Image outputImage = resampler.execute(movingImage);
Image simg1 = SimpleITK.cast(SimpleITK.rescaleIntensity(fixedImage), PixelIDValueEnum.sitkUInt8);
Image simg2 = SimpleITK.cast(SimpleITK.rescaleIntensity(outputImage), PixelIDValueEnum.sitkUInt8);
Image cimg = SimpleITK.compose(simg1, simg2, SimpleITK.divide(SimpleITK.add(simg1, simg2), 2.0));
SimpleITK.show(cimg, "ImageRegistrationMethodBSpline2 Composition");
}
}
}
#!/usr/bin/env python
""" A SimpleITK example demonstrating image registration using the
BSplineTransform and the MattesMutualInformation metric. """
import sys
import os
import SimpleITK as sitk
def command_iteration(method):
""" Callback invoked each iteration. """
print(f"{method.GetOptimizerIteration():3} " + f"= {method.GetMetricValue():10.5f}")
print("\t#: ", len(method.GetOptimizerPosition()))
def command_multi_iteration(_):
""" Callback invoked at the end of each multi-resolution iteration. """
print("--------- Resolution Changing ---------")
if len(sys.argv) < 4:
print(
"Usage:",
sys.argv[0],
"<fixedImageFilter> <movingImageFile>",
"<outputTransformFile>",
)
sys.exit(1)
fixed = sitk.ReadImage(sys.argv[1], sitk.sitkFloat32)
moving = sitk.ReadImage(sys.argv[2], sitk.sitkFloat32)
transformDomainMeshSize = [10] * moving.GetDimension()
tx = sitk.BSplineTransformInitializer(fixed, transformDomainMeshSize)
print("Initial Parameters:")
print(tx.GetParameters())
R = sitk.ImageRegistrationMethod()
R.SetMetricAsMattesMutualInformation(50)
R.SetOptimizerAsGradientDescentLineSearch(
5.0, 100, convergenceMinimumValue=1e-4, convergenceWindowSize=5
)
R.SetOptimizerScalesFromPhysicalShift()
R.SetInitialTransform(tx)
R.SetInterpolator(sitk.sitkLinear)
R.SetShrinkFactorsPerLevel([6, 2, 1])
R.SetSmoothingSigmasPerLevel([6, 2, 1])
R.AddCommand(sitk.sitkIterationEvent, lambda: command_iteration(R))
R.AddCommand(sitk.sitkMultiResolutionIterationEvent, lambda: command_multi_iteration(R))
outTx = R.Execute(fixed, moving)
print("-------")
print(outTx)
print(f"Optimizer stop condition: {R.GetOptimizerStopConditionDescription()}")
print(f" Iteration: {R.GetOptimizerIteration()}")
print(f" Metric value: {R.GetMetricValue()}")
sitk.WriteTransform(outTx, sys.argv[3])
if "SITK_NOSHOW" not in os.environ:
resampler = sitk.ResampleImageFilter()
resampler.SetReferenceImage(fixed)
resampler.SetInterpolator(sitk.sitkLinear)
resampler.SetDefaultPixelValue(100)
resampler.SetTransform(outTx)
out = resampler.Execute(moving)
simg1 = sitk.Cast(sitk.RescaleIntensity(fixed), sitk.sitkUInt8)
simg2 = sitk.Cast(sitk.RescaleIntensity(out), sitk.sitkUInt8)
cimg = sitk.Compose(simg1, simg2, simg1 // 2.0 + simg2 // 2.0)
sitk.Show(cimg, "ImageRegistration1 Composition")
# Run with:
#
# Rscript --vanilla ImageRegistrationMethodBSpline2.R fixedImageFilter movingImageFile outputTransformFile
#
library(SimpleITK)
commandIteration <- function(method)
{
msg <- paste(method$GetOptimizerIteration(), "=",
method$GetMetricValue(), "\n\t#:",
method$GetOptimizerPosition(), '\n')
cat(msg)
}
commandMultiIteration <- function(method)
{
msg <- paste("--------- Resolution Changing ---------\n")
cat(msg)
}
args <- commandArgs( TRUE )
if (length(args) != 3) {
stop("3 arguments expected - fixedImageFilter, movingImageFile, outputTransformFile")
}
fixed <- ReadImage(args[[1]], 'sitkFloat32')
moving <- ReadImage(args[[2]], 'sitkFloat32')
transformDomainMeshSize <- rep(10, moving$GetDimension())
tx <- BSplineTransformInitializer(fixed, transformDomainMeshSize)
cat("Initial Parameters:\n", tx$GetParameters())
R <- ImageRegistrationMethod()
R$SetMetricAsMattesMutualInformation(50)
R$SetOptimizerAsGradientDescentLineSearch(5.0, 100,
convergenceMinimumValue=1e-4,
convergenceWindowSize=5)
R$SetOptimizerScalesFromPhysicalShift()
R$SetInitialTransform(tx)
R$SetInterpolator('sitkLinear')
R$SetShrinkFactorsPerLevel(c(6,2,1))
R$SetSmoothingSigmasPerLevel(c(6,2,1))
R$AddCommand( 'sitkIterationEvent', function() commandIteration(R) )
R$AddCommand( 'sitkMultiResolutionIterationEvent', function() commandMultiIteration(R) )
outTx <- R$Execute(fixed, moving)
cat("-------\n")
outTx
cat("Optimizer stop condition:", R$GetOptimizerStopConditionDescription(), '\n')
cat(" Iteration:", R$GetOptimizerIteration(), '\n')
cat(" Metric value:", R$GetMetricValue(), '\n')
WriteTransform(outTx, args[[3]])