#include <iomanip>
#include <cstdio>
template <class TInput>
class RescaleDynamicRangeFunctor
{
public:
using OutputPixelType = unsigned char;
RescaleDynamicRangeFunctor() = default;
~RescaleDynamicRangeFunctor() = default;
inline OutputPixelType
operator()(const TInput & A)
{
if ((A > 0.0))
{
if (-(30.0 * std::log(A)) > 255)
{
return static_cast<OutputPixelType>(255);
}
}
else
{
return static_cast<OutputPixelType>(255);
}
}
};
namespace
{
class HistogramWriter
{
public:
using InternalPixelType = float;
static constexpr unsigned int Dimension = 2;
using MetricType =
InternalImageType>;
using MetricPointer = MetricType::Pointer;
using HistogramType = MetricType::HistogramType;
using HistogramToEntropyImageFilterType =
using HistogramToImageFilterPointer =
HistogramToEntropyImageFilterType::Pointer;
using OutputImageType = HistogramToEntropyImageFilterType::OutputImageType;
using HistogramFileWriterPointer = HistogramFileWriterType::Pointer;
using OutputPixelType = HistogramToEntropyImageFilterType::OutputPixelType;
HistogramWriter()
: m_Metric(nullptr)
{
this->m_Filter = HistogramToEntropyImageFilterType::New();
this->m_HistogramFileWriter = HistogramFileWriterType::New();
this->m_HistogramFileWriter->SetInput(this->m_Filter->GetOutput());
}
~HistogramWriter() = default;
void
SetMetric(MetricPointer metric)
{
this->m_Metric = metric;
}
MetricPointer
GetMetric() const
{
return this->m_Metric;
}
void
WriteHistogramFile(unsigned int iterationNumber)
{
const std::string outputFileBase = "JointHistogram";
std::ostringstream outputFilename;
outputFilename << outputFileBase << "." << std::setfill('0')
<< std::setw(3) << iterationNumber << "."
<< "mhd";
m_HistogramFileWriter->SetFileName(outputFilename.str());
this->m_Filter->SetInput(this->GetMetric()->GetHistogram());
this->m_Filter->Modified();
try
{
m_Filter->Update();
}
catch (const itk::ExceptionObject & err)
{
std::cerr << "ERROR: ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
}
try
{
m_HistogramFileWriter->Update();
}
catch (const itk::ExceptionObject & excp)
{
std::cerr << "Exception thrown " << excp << std::endl;
}
std::cout << "Joint Histogram file: ";
std::cout << outputFilename.str() << " written" << std::endl;
}
void
WriteHistogramFile(std::string & outputFilename)
{
this->m_Filter->SetInput(this->GetMetric()->GetHistogram());
this->m_Filter->Modified();
using RescaledOutputImageType = itk::Image<unsigned char, Dimension>;
using RescaleDynamicRangeFunctorType =
RescaleDynamicRangeFunctor<OutputPixelType>;
using RescaleDynamicRangeFilterType =
itk::UnaryFunctorImageFilter<OutputImageType,
RescaledOutputImageType,
RescaleDynamicRangeFunctorType>;
auto rescaler = RescaleDynamicRangeFilterType::New();
rescaler->SetInput(m_Filter->GetOutput());
using RescaledWriterType = itk::ImageFileWriter<RescaledOutputImageType>;
auto rescaledWriter = RescaledWriterType::New();
rescaledWriter->SetInput(rescaler->GetOutput());
rescaledWriter->SetFileName(outputFilename);
try
{
m_Filter->Update();
}
catch (const itk::ExceptionObject & err)
{
std::cerr << "ERROR: ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
}
try
{
rescaledWriter->Update();
}
catch (const itk::ExceptionObject & excp)
{
std::cerr << "Exception thrown " << excp << std::endl;
}
std::cout << "Joint Histogram file: " << outputFilename << " written"
<< std::endl;
}
private:
MetricPointer m_Metric;
HistogramToImageFilterPointer m_Filter;
HistogramFileWriterPointer m_HistogramFileWriter;
};
{
public:
using Self = CommandIterationUpdate;
using Pointer = itk::SmartPointer<Self>;
protected:
CommandIterationUpdate() { m_WriteHistogramsAfterEveryIteration = false; }
public:
using OptimizerType = itk::RegularStepGradientDescentOptimizer;
using OptimizerPointer = const OptimizerType *;
void
Execute(itk::Object * caller,
const itk::EventObject & event)
override
{
Execute((
const itk::Object *)caller, event);
}
void
Execute(
const itk::Object *
object,
const itk::EventObject & event)
override
{
auto optimizer = static_cast<OptimizerPointer>(object);
if (!itk::IterationEvent().CheckEvent(&event) || optimizer == nullptr)
{
return;
}
std::cout << optimizer->GetCurrentIteration() << " ";
std::cout << optimizer->GetValue() << " ";
std::cout << optimizer->GetCurrentPosition() << std::endl;
if (optimizer->GetCurrentIteration() == 0)
{
m_JointHistogramWriter.WriteHistogramFile(m_InitialHistogramFile);
}
if (m_WriteHistogramsAfterEveryIteration)
{
m_JointHistogramWriter.WriteHistogramFile(
optimizer->GetCurrentIteration());
}
}
void
SetWriteHistogramsAfterEveryIteration(bool value)
{
m_WriteHistogramsAfterEveryIteration = value;
}
void
SetInitialHistogramFile(const char * filename)
{
m_InitialHistogramFile = filename;
}
HistogramWriter m_JointHistogramWriter;
private:
bool m_WriteHistogramsAfterEveryIteration;
std::string m_InitialHistogramFile;
};
}
int
main(int argc, char * argv[])
{
if (argc < 8)
{
std::cerr << "Missing Parameters " << std::endl;
std::cerr << "Usage: " << argv[0];
std::cerr << " fixedImageFile movingImageFile ";
std::cerr << "outputImagefile WriteJointHistogramsAfterEveryIteration ";
std::cerr << "JointHistogramPriorToRegistrationFile ";
std::cerr << "JointHistogramAfterRegistrationFile ";
std::cerr
<< "NumberOfHistogramBinsForWritingTheMutualInformationHistogramMetric";
std::cerr << std::endl;
return EXIT_FAILURE;
}
using PixelType = unsigned char;
using InternalPixelType = float;
using InterpolatorType =
using RegistrationType =
using MetricType =
InternalImageType>;
auto transform = TransformType::New();
auto optimizer = OptimizerType::New();
auto interpolator = InterpolatorType::New();
auto registration = RegistrationType::New();
auto metric = MetricType::New();
registration->SetOptimizer(optimizer);
registration->SetTransform(transform);
registration->SetInterpolator(interpolator);
const unsigned int numberOfHistogramBins = std::stoi(argv[7]);
MetricType::HistogramType::SizeType histogramSize;
histogramSize.SetSize(2);
histogramSize[0] = numberOfHistogramBins;
histogramSize[1] = numberOfHistogramBins;
metric->SetHistogramSize(histogramSize);
const unsigned int numberOfParameters = transform->GetNumberOfParameters();
using ScalesType = MetricType::ScalesType;
ScalesType scales(numberOfParameters);
scales.Fill(1.0);
metric->SetDerivativeStepLengthScales(scales);
auto observer = CommandIterationUpdate::New();
observer->m_JointHistogramWriter.SetMetric(metric);
registration->SetMetric(metric);
auto fixedImageReader = FixedImageReaderType::New();
auto movingImageReader = MovingImageReaderType::New();
fixedImageReader->SetFileName(argv[1]);
movingImageReader->SetFileName(argv[2]);
using FixedNormalizeFilterType =
using MovingNormalizeFilterType =
auto fixedNormalizer = FixedNormalizeFilterType::New();
auto movingNormalizer = MovingNormalizeFilterType::New();
using GaussianFilterType =
auto fixedSmoother = GaussianFilterType::New();
auto movingSmoother = GaussianFilterType::New();
fixedSmoother->SetVariance(2.0);
movingSmoother->SetVariance(2.0);
fixedNormalizer->SetInput(fixedImageReader->GetOutput());
movingNormalizer->SetInput(movingImageReader->GetOutput());
fixedSmoother->SetInput(fixedNormalizer->GetOutput());
movingSmoother->SetInput(movingNormalizer->GetOutput());
registration->SetFixedImage(fixedSmoother->GetOutput());
registration->SetMovingImage(movingSmoother->GetOutput());
try
{
fixedNormalizer->Update();
}
{
std::cout << "ExceptionObject caught !" << std::endl;
std::cout << err << std::endl;
return EXIT_FAILURE;
}
registration->SetFixedImageRegion(
fixedNormalizer->GetOutput()->GetBufferedRegion());
using ParametersType = RegistrationType::ParametersType;
ParametersType initialParameters(transform->GetNumberOfParameters());
initialParameters[0] = 0.0;
initialParameters[1] = 0.0;
registration->SetInitialTransformParameters(initialParameters);
optimizer->SetMaximumStepLength(4.00);
optimizer->SetMinimumStepLength(0.01);
optimizer->SetRelaxationFactor(0.90);
optimizer->SetNumberOfIterations(200);
optimizer->MaximizeOn();
optimizer->AddObserver(itk::IterationEvent(), observer);
observer->SetInitialHistogramFile(argv[5]);
if (std::stoi(argv[4]))
{
observer->SetWriteHistogramsAfterEveryIteration(true);
}
try
{
registration->Update();
std::cout << "Optimizer stop condition: "
<< registration->GetOptimizer()->GetStopConditionDescription()
<< std::endl;
}
{
std::cout << "ExceptionObject caught !" << std::endl;
std::cout << err << std::endl;
return EXIT_FAILURE;
}
ParametersType finalParameters = registration->GetLastTransformParameters();
const double TranslationAlongX = finalParameters[0];
const double TranslationAlongY = finalParameters[1];
const unsigned int numberOfIterations = optimizer->GetCurrentIteration();
const double bestValue = optimizer->GetValue();
std::cout << "Result = " << std::endl;
std::cout << " Translation X = " << TranslationAlongX << std::endl;
std::cout << " Translation Y = " << TranslationAlongY << std::endl;
std::cout << " Iterations = " << numberOfIterations << std::endl;
std::cout << " Metric value = " << bestValue << std::endl;
std::string histogramAfter(argv[6]);
try
{
observer->m_JointHistogramWriter.WriteHistogramFile(histogramAfter);
}
{
std::cerr << "ERROR: ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
return EXIT_FAILURE;
}
using ResampleFilterType =
auto finalTransform = TransformType::New();
finalTransform->SetParameters(finalParameters);
finalTransform->SetFixedParameters(transform->GetFixedParameters());
auto resample = ResampleFilterType::New();
resample->SetTransform(finalTransform);
resample->SetInput(movingImageReader->GetOutput());
const FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
resample->SetSize(fixedImage->GetLargestPossibleRegion().GetSize());
resample->SetOutputOrigin(fixedImage->GetOrigin());
resample->SetOutputSpacing(fixedImage->GetSpacing());
resample->SetOutputDirection(fixedImage->GetDirection());
resample->SetDefaultPixelValue(100);
using OutputPixelType = unsigned char;
using CastFilterType =
auto writer = WriterType::New();
auto caster = CastFilterType::New();
writer->SetFileName(argv[3]);
caster->SetInput(resample->GetOutput());
writer->SetInput(caster->GetOutput());
try
{
writer->Update();
}
{
std::cerr << "ERROR: ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
}
return EXIT_SUCCESS;
}
Casts input pixels to output pixel type.
Superclass for callback/observer methods.
virtual void Execute(Object *caller, const EventObject &event)=0
Blurs an image by separable convolution with discrete gaussian kernels. This filter performs Gaussian...
Standard exception handling object.
The class takes a histogram as an input and gives the entropy image as the output....
Data source that reads image data from a single file.
Writes image data to a single file.
Base class for Image Registration Methods.
Templated n-dimensional image class.
Linearly interpolate an image at specified positions.
Normalize an image by setting its mean to zero and variance to one.
Implement a gradient descent optimizer.
Resample an image via a coordinate transform.
BinaryGeneratorImageFilter< TInputImage1, TInputImage2, TOutputImage > Superclass
SmartPointer< Self > Pointer
constexpr unsigned int Dimension
TInput TInput TReturn Round(TInput x)
class ITK_FORWARD_EXPORT Command