template <class TOptimizer>
{
public:
using Self = IterationCallback;
itkTypeMacro(IterationCallback, Superclass);
itkNewMacro(Self);
using OptimizerType = TOptimizer;
void
SetOptimizer(OptimizerType * optimizer)
{
m_Optimizer = optimizer;
m_Optimizer->AddObserver(itk::IterationEvent(), this);
}
void
{
}
void
{
if (typeid(event) == typeid(itk::StartEvent))
{
std::cout << std::endl << "Position Value";
std::cout << std::endl << std::endl;
}
else if (typeid(event) == typeid(itk::IterationEvent))
{
std::cout << m_Optimizer->GetCurrentIteration() << " ";
std::cout << m_Optimizer->GetValue() << " ";
std::cout << m_Optimizer->GetCurrentPosition() << std::endl;
}
else if (typeid(event) == typeid(itk::EndEvent))
{
std::cout << std::endl << std::endl;
std::cout << "After " << m_Optimizer->GetCurrentIteration();
std::cout << " iterations " << std::endl;
std::cout << "Solution is = " << m_Optimizer->GetCurrentPosition();
std::cout << std::endl;
}
}
protected:
IterationCallback() = default;
};
template <typename TFixedImage, typename TMovingSpatialObject>
class SimpleImageToSpatialObjectMetric
{
public:
using Self = SimpleImageToSpatialObjectMetric;
using Superclass =
using PointListType = std::list<PointType>;
using MovingSpatialObjectType = TMovingSpatialObject;
itkNewMacro(Self);
itkTypeMacro(SimpleImageToSpatialObjectMetric, ImageToSpatialObjectMetric);
static constexpr unsigned int ParametricSpaceDimension = 3;
void
{
if (!this->m_FixedImage)
{
std::cout << "Please set the image before the moving spatial object"
<< std::endl;
return;
}
this->m_MovingSpatialObject = object;
m_PointList.clear();
using myIteratorType =
myIteratorType it(this->m_FixedImage,
this->m_FixedImage->GetBufferedRegion());
while (!it.IsAtEnd())
{
this->m_FixedImage->TransformIndexToPhysicalPoint(it.GetIndex(), point);
if (this->m_MovingSpatialObject->IsInsideInWorldSpace(point, 99999))
{
m_PointList.push_back(point);
}
++it;
}
std::cout << "Number of points in the metric = "
<< static_cast<unsigned long>(m_PointList.size()) << std::endl;
}
void
GetDerivative(
const ParametersType &, DerivativeType &)
const override
{
return;
}
MeasureType
GetValue(
const ParametersType & parameters)
const override
{
double value;
this->m_Transform->SetParameters(parameters);
value = 0;
for (auto it : m_PointList)
{
PointType transformedPoint = this->m_Transform->TransformPoint(it);
if (this->m_Interpolator->IsInsideBuffer(transformedPoint))
{
value += this->m_Interpolator->Evaluate(transformedPoint);
}
}
return value;
}
void
MeasureType & Value,
DerivativeType & Derivative) const override
{
}
private:
PointListType m_PointList;
};
int
main(int argc, char * argv[])
{
if (argc > 1)
{
std::cerr << "Too many parameters " << std::endl;
std::cerr << "Usage: " << argv[0] << std::endl;
}
EllipseType::Pointer ellipse1 = EllipseType::New();
EllipseType::Pointer ellipse2 = EllipseType::New();
EllipseType::Pointer ellipse3 = EllipseType::New();
ellipse1->SetRadiusInObjectSpace(10.0);
ellipse2->SetRadiusInObjectSpace(10.0);
ellipse3->SetRadiusInObjectSpace(10.0);
EllipseType::TransformType::OffsetType offset;
offset[0] = 100.0;
offset[1] = 40.0;
ellipse1->GetModifiableObjectToParentTransform()->SetOffset(offset);
ellipse1->Update();
offset[0] = 40.0;
offset[1] = 150.0;
ellipse2->GetModifiableObjectToParentTransform()->SetOffset(offset);
ellipse2->Update();
offset[0] = 150.0;
offset[1] = 150.0;
ellipse3->GetModifiableObjectToParentTransform()->SetOffset(offset);
ellipse3->Update();
GroupType::Pointer group = GroupType::New();
group->AddChild(ellipse1);
group->AddChild(ellipse2);
group->AddChild(ellipse3);
using SpatialObjectToImageFilterType =
SpatialObjectToImageFilterType::Pointer imageFilter =
SpatialObjectToImageFilterType::New();
imageFilter->SetInput(group);
size[0] = 200;
size[1] = 200;
imageFilter->Update();
using GaussianFilterType =
GaussianFilterType::Pointer gaussianFilter = GaussianFilterType::New();
gaussianFilter->SetInput(imageFilter->GetOutput());
constexpr double variance = 20;
gaussianFilter->SetVariance(variance);
gaussianFilter->Update();
using RegistrationType =
RegistrationType::Pointer registration = RegistrationType::New();
using MetricType = SimpleImageToSpatialObjectMetric<ImageType, GroupType>;
MetricType::Pointer metric = MetricType::New();
using InterpolatorType =
InterpolatorType::Pointer interpolator = InterpolatorType::New();
OptimizerType::Pointer optimizer = OptimizerType::New();
TransformType::Pointer transform = TransformType::New();
generator->Initialize(12345);
optimizer->SetNormalVariateGenerator(generator);
optimizer->Initialize(10);
optimizer->SetMaximumIteration(400);
TransformType::ParametersType parametersScale;
parametersScale.set_size(3);
parametersScale[0] = 1000;
for (unsigned int i = 1; i < 3; i++)
{
parametersScale[i] = 2;
}
optimizer->SetScales(parametersScale);
using IterationCallbackType = IterationCallback<OptimizerType>;
IterationCallbackType::Pointer callback = IterationCallbackType::New();
callback->SetOptimizer(optimizer);
registration->SetFixedImage(gaussianFilter->GetOutput());
registration->SetMovingSpatialObject(group);
registration->SetTransform(transform);
registration->SetInterpolator(interpolator);
registration->SetOptimizer(optimizer);
registration->SetMetric(metric);
TransformType::ParametersType initialParameters(
transform->GetNumberOfParameters());
initialParameters[0] = 0.2;
initialParameters[1] = 7.0;
initialParameters[2] = 6.0;
registration->SetInitialTransformParameters(initialParameters);
std::cout << "Initial Parameters : " << initialParameters << std::endl;
optimizer->MaximizeOn();
try
{
registration->Update();
std::cout << "Optimizer stop condition: "
<< registration->GetOptimizer()->GetStopConditionDescription()
<< std::endl;
}
catch (const itk::ExceptionObject & exp)
{
std::cerr << "Exception caught ! " << std::endl;
std::cerr << exp << std::endl;
}
RegistrationType::ParametersType finalParameters =
registration->GetLastTransformParameters();
std::cout << "Final Solution is : " << finalParameters << std::endl;
return EXIT_SUCCESS;
}