ITK  5.4.0
Insight Toolkit
Examples/RegistrationITKv4/IterativeClosestPoint1.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
*
* https://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.
*
*=========================================================================*/
// Software Guide : BeginLatex
//
// This example illustrates how to perform Iterative Closest Point (ICP)
// registration in ITK. The main class featured in this section is the
// \doxygen{EuclideanDistancePointMetric}.
//
// Software Guide : EndLatex
// Software Guide : BeginLatex
//
// The first step is to include the relevant headers.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
// Software Guide : EndCodeSnippet
#include <iostream>
#include <fstream>
class CommandIterationUpdate : public itk::Command
{
public:
using Self = CommandIterationUpdate;
itkNewMacro(Self);
protected:
CommandIterationUpdate() = default;
public:
using OptimizerType = itk::LevenbergMarquardtOptimizer;
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 = dynamic_cast<OptimizerPointer>(object);
if (optimizer == nullptr)
{
itkExceptionMacro("Could not cast optimizer.");
}
if (!itk::IterationEvent().CheckEvent(&event))
{
return;
}
std::cout << "Value = " << optimizer->GetCachedValue() << std::endl;
std::cout << "Position = " << optimizer->GetCachedCurrentPosition();
std::cout << std::endl << std::endl;
}
};
int
main(int argc, char * argv[])
{
if (argc < 3)
{
std::cerr << "Arguments Missing. " << std::endl;
std::cerr
<< "Usage: IterativeClosestPoint1 fixedPointsFile movingPointsFile "
<< std::endl;
return EXIT_FAILURE;
}
// Software Guide : BeginLatex
//
// Next, define the necessary types for the fixed and moving pointsets and
// point containers.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
constexpr unsigned int Dimension = 2;
using PointSetType = itk::PointSet<float, Dimension>;
auto fixedPointSet = PointSetType::New();
auto movingPointSet = PointSetType::New();
using PointsContainer = PointSetType::PointsContainer;
auto fixedPointContainer = PointsContainer::New();
auto movingPointContainer = PointsContainer::New();
PointType fixedPoint;
PointType movingPoint;
// Software Guide : EndCodeSnippet
// Read the file containing coordinates of fixed points.
std::ifstream fixedFile;
fixedFile.open(argv[1]);
if (fixedFile.fail())
{
std::cerr << "Error opening points file with name : " << std::endl;
std::cerr << argv[1] << std::endl;
return EXIT_FAILURE;
}
unsigned int pointId = 0;
fixedFile >> fixedPoint;
while (!fixedFile.eof())
{
fixedPointContainer->InsertElement(pointId, fixedPoint);
fixedFile >> fixedPoint;
pointId++;
}
fixedPointSet->SetPoints(fixedPointContainer);
std::cout << "Number of fixed Points = "
<< fixedPointSet->GetNumberOfPoints() << std::endl;
// Read the file containing coordinates of moving points.
std::ifstream movingFile;
movingFile.open(argv[2]);
if (movingFile.fail())
{
std::cerr << "Error opening points file with name : " << std::endl;
std::cerr << argv[2] << std::endl;
return EXIT_FAILURE;
}
pointId = 0;
movingFile >> movingPoint;
while (!movingFile.eof())
{
movingPointContainer->InsertElement(pointId, movingPoint);
movingFile >> movingPoint;
pointId++;
}
movingPointSet->SetPoints(movingPointContainer);
std::cout << "Number of moving Points = "
<< movingPointSet->GetNumberOfPoints() << std::endl;
// Software Guide : BeginLatex
//
// After the points are read in from files, set up the metric type.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
using MetricType =
auto metric = MetricType::New();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Now, setup the transform, optimizers, and registration method using the
// point set types defined earlier.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
auto transform = TransformType::New();
// Optimizer Type
using OptimizerType = itk::LevenbergMarquardtOptimizer;
auto optimizer = OptimizerType::New();
optimizer->SetUseCostFunctionGradient(false);
// Registration Method
using RegistrationType =
auto registration = RegistrationType::New();
// Scale the translation components of the Transform in the Optimizer
OptimizerType::ScalesType scales(transform->GetNumberOfParameters());
scales.Fill(0.01);
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Next we setup the convergence criteria, and other properties required
// by the optimizer.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
unsigned long numberOfIterations = 100;
double gradientTolerance = 1e-5; // convergence criterion
double valueTolerance = 1e-5; // convergence criterion
double epsilonFunction = 1e-6; // convergence criterion
optimizer->SetScales(scales);
optimizer->SetNumberOfIterations(numberOfIterations);
optimizer->SetValueTolerance(valueTolerance);
optimizer->SetGradientTolerance(gradientTolerance);
optimizer->SetEpsilonFunction(epsilonFunction);
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// In this case we start from an identity transform, but in reality the user
// will usually be able to provide a better guess than this.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
transform->SetIdentity();
// Software Guide : EndCodeSnippet
registration->SetInitialTransformParameters(transform->GetParameters());
// Software Guide : BeginLatex
//
// Finally, connect all the components required for the registration, and an
// observer.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
registration->SetMetric(metric);
registration->SetOptimizer(optimizer);
registration->SetTransform(transform);
registration->SetFixedPointSet(fixedPointSet);
registration->SetMovingPointSet(movingPointSet);
// Connect an observer
auto observer = CommandIterationUpdate::New();
optimizer->AddObserver(itk::IterationEvent(), observer);
// Software Guide : EndCodeSnippet
try
{
registration->Update();
}
catch (const itk::ExceptionObject & e)
{
std::cerr << e << std::endl;
return EXIT_FAILURE;
}
std::cout << "Solution = " << transform->GetParameters() << std::endl;
return EXIT_SUCCESS;
}
Pointer
SmartPointer< Self > Pointer
Definition: itkAddImageFilter.h:93
itk::PointSet
A superclass of the N-dimensional mesh structure; supports point (geometric coordinate and attribute)...
Definition: itkPointSet.h:82
itkLevenbergMarquardtOptimizer.h
itk::EuclideanDistancePointMetric
Computes the minimum distance between a moving point-set and a fixed point-set. A vector of minimum c...
Definition: itkEuclideanDistancePointMetric.h:47
itk::GTest::TypedefsAndConstructors::Dimension2::PointType
ImageBaseType::PointType PointType
Definition: itkGTestTypedefsAndConstructors.h:51
itkPointSetToPointSetRegistrationMethod.h
itk::SmartPointer< Self >
itkTranslationTransform.h
itk::Command
Superclass for callback/observer methods.
Definition: itkCommand.h:45
itkEuclideanDistancePointMetric.h
itk::Command
class ITK_FORWARD_EXPORT Command
Definition: itkObject.h:42
itk::TranslationTransform
Translation transformation of a vector space (e.g. space coordinates)
Definition: itkTranslationTransform.h:43
itk::Command::Execute
virtual void Execute(Object *caller, const EventObject &event)=0
itk::Object
Base class for most ITK classes.
Definition: itkObject.h:61
itk::Math::e
static constexpr double e
Definition: itkMath.h:56
itk::EventObject
Abstraction of the Events used to communicating among filters and with GUIs.
Definition: itkEventObject.h:57
New
static Pointer New()
AddImageFilter
Definition: itkAddImageFilter.h:81
itk::GTest::TypedefsAndConstructors::Dimension2::Dimension
constexpr unsigned int Dimension
Definition: itkGTestTypedefsAndConstructors.h:44
itk::PointSetToPointSetRegistrationMethod
Base class for PointSet to PointSet Registration Methods.
Definition: itkPointSetToPointSetRegistrationMethod.h:66
Superclass
BinaryGeneratorImageFilter< TInputImage1, TInputImage2, TOutputImage > Superclass
Definition: itkAddImageFilter.h:90
itk::LevenbergMarquardtOptimizer
Wrap of the vnl_levenberg_marquardt algorithm.
Definition: itkLevenbergMarquardtOptimizer.h:38