SimpleITK  
ImageRegistrationMethodExhaustive/ImageRegistrationMethodExhaustive.cxx
/*=========================================================================
*
* Copyright NumFOCUS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#include <SimpleITK.h>
#include <iostream>
#include <stdlib.h>
#include <iomanip>
#include <cmath>
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
namespace sitk = itk::simple;
class IterationUpdate : public sitk::Command
{
public:
IterationUpdate(const sitk::ImageRegistrationMethod & m)
: m_Method(m)
{}
void
Execute() override
{
// use sitk's output operator for std::vector etc..
using sitk::operator<<;
if (m_Method.GetOptimizerIteration() == 0)
{
std::cout << "Scales: " << m_Method.GetOptimizerScales() << std::endl;
}
// stash the stream state
std::ios state(NULL);
state.copyfmt(std::cout);
std::cout << std::fixed << std::setfill(' ') << std::setprecision(5);
std::cout << std::setw(3) << m_Method.GetOptimizerIteration();
std::cout << " = " << std::setw(7) << m_Method.GetMetricValue();
std::cout << " : " << m_Method.GetOptimizerPosition() << std::endl;
std::cout.copyfmt(state);
}
private:
};
int
main(int argc, char * argv[])
{
if (argc < 4)
{
std::cout << "Usage: " << argv[0] << " <fixedImageFile> <movingImageFile> <outputTransformFile>" << std::endl;
return 1;
}
sitk::Image fixedImage = sitk::ReadImage(argv[1], sitk::sitkFloat32);
sitk::Image movingImage = sitk::ReadImage(argv[2], sitk::sitkFloat32);
R.SetMetricAsMattesMutualInformation(50); // numberOfHistogramBins
int samplePerAxis = 12;
if (fixedImage.GetDimension() == 2)
{
// Set the number of samples (radius) in each dimension, with a default step size of 1.0
std::vector<unsigned int> exhaustiveSteps = { static_cast<unsigned int>(samplePerAxis / 2), 0, 0 };
R.SetOptimizerAsExhaustive(exhaustiveSteps);
// Utilize the scale to set the step size for each dimension
std::vector<double> scales = { 2.0 * M_PI / samplePerAxis, 1.0, 1.0 };
R.SetOptimizerScales(scales);
}
else if (fixedImage.GetDimension() == 3)
{
std::vector<unsigned int> exhaustiveSteps = { static_cast<unsigned int>(samplePerAxis / 2),
static_cast<unsigned int>(samplePerAxis / 2),
static_cast<unsigned int>(samplePerAxis / 4),
0,
0,
0 };
R.SetOptimizerAsExhaustive(exhaustiveSteps);
std::vector<double> scales = {
2.0 * M_PI / samplePerAxis, 2.0 * M_PI / samplePerAxis, 2.0 * M_PI / samplePerAxis, 1.0, 1.0, 1.0
};
R.SetOptimizerScales(scales);
}
// Initialize the transform with a translation and the center of rotation from the moments of intensity.
tx = sitk::CenteredTransformInitializer(fixedImage, movingImage, tx);
IterationUpdate cmd(R);
sitk::Transform outTx = R.Execute(fixedImage, movingImage);
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") == nullptr)
{
resampler.SetReferenceImage(fixedImage);
resampler.SetDefaultPixelValue(1);
resampler.SetTransform(outTx);
sitk::Image out = resampler.Execute(movingImage);
sitk::Image simg1 = sitk::Cast(sitk::RescaleIntensity(fixedImage), 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));
sitk::Show(cimg, "ImageRegistrationExhaustive Composition");
}
return 0;
}
An implementation of the Command design pattern for callback.
Definition sitkCommand.h:45
virtual void Execute()
A rigid 2D transform with rotation in radians around a fixed center with translation.
A rigid 3D transform with rotation in radians around a fixed center with translation.
An interface method to the modular ITKv4 registration framework.
void SetOptimizerAsExhaustive(const std::vector< unsigned int > &numberOfSteps, double stepLength=1.0)
Set the optimizer to sample the metric at regular steps.
void SetInterpolator(InterpolatorEnum Interpolator)
Set and get the interpolator to use.
Transform Execute(const Image &fixed, const Image &moving)
Optimize the configured registration problem.
void SetMetricAsMattesMutualInformation(unsigned int numberOfHistogramBins=50)
Use the mutual information between two images to be registered using the method of Mattes et al.
std::string GetOptimizerStopConditionDescription() const
void SetOptimizerScales(const std::vector< double > &scales)
Manually set per parameter weighting for the transform parameters.
unsigned int GetOptimizerIteration() const
void SetInitialTransform(const Transform &transform)
Set the initial transform and parameters to optimize.
The Image class for SimpleITK.
Definition sitkImage.h:77
unsigned int GetDimension() const
virtual int AddCommand(itk::simple::EventEnum event, itk::simple::Command &cmd)
Add a Command Object to observer the event.
Resample an image via a coordinate transform.
Image Execute(const Image &image1)
void SetInterpolator(InterpolatorEnum Interpolator)
void SetReferenceImage(const Image &refImage)
void SetDefaultPixelValue(double DefaultPixelValue)
A simplified wrapper around a variety of ITK transforms.
std::string ToString() const
SITKIO_EXPORT Image ReadImage(const PathType &filename, PixelIDValueEnum outputPixelType=sitkUnknown, const std::string &imageIO="")
ReadImage is a procedural interface to the ImageFileReader class which is convenient for most image r...
Image Compose(const std::vector< Image > &images)
ComposeImageFilter combine several scalar images into a multicomponent image.
@ sitkLinear
N-D linear interpolation.
void SITKIO_EXPORT Show(const Image &image, const std::string &title="", const bool debugOn=ProcessObject::GetGlobalDefaultDebug())
@ sitkIterationEvent
Occurs with some algorithms that run for a fixed or undetermined number of iterations.
Definition sitkEvent.h:47
Transform CenteredTransformInitializer(const Image &fixedImage, const Image &movingImage, const Transform &transform, CenteredTransformInitializerFilter::OperationModeType operationMode=itk::simple::CenteredTransformInitializerFilter::MOMENTS)
CenteredTransformInitializer is a helper class intended to initialize the center of rotation and the ...
Image Add(Image &&image1, const Image &image2)
Pixel-wise addition of two images.
Image Divide(Image &&image1, const Image &image2)
Pixel-wise division of two images.
SITKCommon_EXPORT void WriteTransform(const Transform &transform, const PathType &filename)
Image RescaleIntensity(Image &&image1, double outputMinimum=0, double outputMaximum=255)
Applies a linear transformation to the intensity levels of the input Image .
Image Cast(const Image &image, PixelIDValueEnum pixelID)