14 #include "itkIndent.h" 15 #include "itkEuler3DTransform.h" 16 #include "itkVersorRigid3DTransform.h" 17 #include "itkEuclideanDistancePointMetric.h" 18 #include "itkLevenbergMarquardtOptimizer.h" 19 #include "itkPointSet.h" 20 #include "itkPointSetToPointSetRegistrationMethod.h" 25 m_ErrorMean(-1.0), m_ErrorStdDev(-1.0), m_ErrorRMS(-1.0), m_ErrorMin(-1.0), m_ErrorMax(-1.0), m_ErrorAbsMax(-1.0),
26 m_SourcePoints(), m_TargetPoints(), m_LandmarkTransformInitializer(nullptr), m_LandmarkTransform(nullptr),
27 m_QuatLandmarkTransform(nullptr), m_QuatTransform(nullptr), m_Errors(), m_UseICPInitialization(false)
55 itkExceptionMacro(
"Landmark correspondence finding failed.");
61 itkExceptionMacro(
"Cannot initialize Filter, number of input datas does not equal number of output datas.");
72 TransformInitializerType::LandmarkPointType lPoint;
74 for (mitk::PointSet::PointsContainer::ConstIterator it = mitkSourcePointSet->GetPointSet()->GetPoints()->Begin();
75 it != mitkSourcePointSet->GetPointSet()->GetPoints()->End(); ++it)
77 mitk::FillVector3D(lPoint, it->Value().GetElement(0), it->Value().GetElement(1), it->Value().GetElement(2));
83 itkExceptionMacro(
"SourcePointSet must contain at least 3 points");
94 TransformInitializerType::LandmarkPointType lPoint;
95 for (mitk::PointSet::PointsContainer::ConstIterator it = mitkTargetPointSet->GetPointSet()->GetPoints()->Begin();
96 it != mitkTargetPointSet->GetPointSet()->GetPoints()->End(); ++it)
98 mitk::FillVector3D(lPoint, it->Value().GetElement(0), it->Value().GetElement(1), it->Value().GetElement(2));
104 itkExceptionMacro(
"TargetPointSet must contain at least 3 points");
156 for (std::vector<mitk::ScalarType>::size_type i = 0; i < vector.size(); i++)
172 for (std::vector<mitk::ScalarType>::size_type i = 0; i < vector.size(); i++)
175 if(vector.size() > 1)
176 m_ErrorStdDev = sqrt(m_ErrorStdDev / (vector.size() - 1.0));
185 TransformInitializerType::LandmarkPointType lPointIn, lPointOut;
188 for (
unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i)
200 output->
Graft(input);
207 lPointIn[0] = tempCoordinate[0];
208 lPointIn[1] = tempCoordinate[1];
209 lPointIn[2] = tempCoordinate[2];
213 tempCoordinate[0] = lPointOut[0];
214 tempCoordinate[1] = lPointOut[1];
215 tempCoordinate[2] = lPointOut[2];
220 vnl_quaternion<double>
const vnlQuatIn(quatIn.x(), quatIn.y(), quatIn.z(), quatIn.r());
243 Superclass::PrintSelf(os, indent);
245 os << indent << this->GetNameOfClass() <<
":\n";
246 os << indent <<
m_SourcePoints.size() <<
" SourcePoints exist: \n";
247 itk::Indent nextIndent = indent.GetNextIndent();
251 os << nextIndent <<
"Point " << i++ <<
": [";
252 os << it->GetElement(0);
253 for (
unsigned int i = 1; i < TransformInitializerType::LandmarkPointType::GetPointDimension(); ++i)
255 os <<
", " << it->GetElement(i);
260 os << indent <<
m_TargetPoints.size() <<
" TargetPoints exist: \n";
264 os << nextIndent <<
"Point " << i++ <<
": [";
265 os << it->GetElement(0);
266 for (
unsigned int i = 1; i < TransformInitializerType::LandmarkPointType::GetPointDimension(); ++i)
268 os <<
", " << it->GetElement(i);
272 os << indent <<
"Landmarktransform initialized: " << this->
IsInitialized() <<
"\n";
275 os << indent <<
"Registration error statistics:\n";
276 os << nextIndent <<
"FRE: " << this->
GetFRE() <<
"\n";
277 os << nextIndent <<
"FRE std.dev.: " << this->
GetFREStdDev() <<
"\n";
278 os << nextIndent <<
"FRE RMS: " << this->
GetRMSError() <<
"\n";
279 os << nextIndent <<
"Minimum registration error: " << this->
GetMinError() <<
"\n";
280 os << nextIndent <<
"Maximum registration error: " << this->
GetMaxError() <<
"\n";
281 os << nextIndent <<
"Absolute Maximum registration error: " << this->
GetAbsMaxError() <<
"\n";
293 if (sources.size() < 6 || targets.size() < 6)
298 typedef itk::PointSet<mitk::ScalarType, 3>
PointSetType;
300 typedef itk::EuclideanDistancePointMetric< PointSetType, PointSetType> MetricType;
301 typedef itk::VersorRigid3DTransform< double > TransformType;
302 typedef itk::PointSetToPointSetRegistrationMethod< PointSetType, PointSetType >
RegistrationType;
305 PointSetType::Pointer sourcePointSet = PointSetType::New();
307 for (LandmarkPointContainer::const_iterator it = sources.begin(); it != sources.end(); ++it)
309 PointSetType::PointType doublePoint;
311 sourcePointSet->SetPoint(i++, doublePoint );
315 PointSetType::Pointer targetPointSet = PointSetType::New();
316 for (LandmarkPointContainer::const_iterator it = targets.begin(); it != targets.end(); ++it)
318 PointSetType::PointType doublePoint;
320 targetPointSet->SetPoint(i++, doublePoint );
323 TransformType::Pointer transform = TransformType::New();
324 transform->SetIdentity();
326 itk::LevenbergMarquardtOptimizer::Pointer optimizer = itk::LevenbergMarquardtOptimizer::New();
327 optimizer->SetUseCostFunctionGradient(
false);
329 RegistrationType::Pointer registration = RegistrationType::New();
332 itk::LevenbergMarquardtOptimizer::ScalesType scales(transform->GetNumberOfParameters());
333 const double translationScale = 5000;
334 const double rotationScale = 1.0;
335 scales[0] = 1.0 / rotationScale;
336 scales[1] = 1.0 / rotationScale;
337 scales[2] = 1.0 / rotationScale;
338 scales[3] = 1.0 / translationScale;
339 scales[4] = 1.0 / translationScale;
340 scales[5] = 1.0 / translationScale;
342 unsigned long numberOfIterations = 80000;
343 double gradientTolerance = 1e-10;
344 double valueTolerance = 1e-10;
345 double epsilonFunction = 1e-10;
346 optimizer->SetScales( scales );
347 optimizer->SetNumberOfIterations( numberOfIterations );
348 optimizer->SetValueTolerance( valueTolerance );
349 optimizer->SetGradientTolerance( gradientTolerance );
350 optimizer->SetEpsilonFunction( epsilonFunction );
353 registration->SetInitialTransformParameters( transform->GetParameters() );
357 MetricType::Pointer metric = MetricType::New();
359 registration->SetMetric( metric );
360 registration->SetOptimizer( optimizer );
361 registration->SetTransform( transform );
362 registration->SetFixedPointSet( targetPointSet );
363 registration->SetMovingPointSet( sourcePointSet );
368 registration->Update();
370 catch( itk::ExceptionObject & e )
372 MITK_INFO <<
"Exception caught during ICP optimization: " << e;
376 MITK_INFO <<
"ICP successful: Solution = " << transform->GetParameters() << std::endl;
377 MITK_INFO <<
"Metric value: " << metric->GetValue(transform->GetParameters());
382 for (LandmarkPointContainer::const_iterator targetsIt = targets.begin(); targetsIt != targets.end(); ++targetsIt)
385 LandmarkPointContainer::iterator minDistanceIterator = sources.end();
386 for (LandmarkPointContainer::iterator sourcesIt = sources.begin(); sourcesIt != sources.end(); ++sourcesIt)
388 TransformInitializerType::LandmarkPointType transformedSource = transform->TransformPoint(*sourcesIt);
389 double dist = targetsIt->EuclideanDistanceTo(transformedSource);
390 MITK_INFO <<
"target: " << *targetsIt <<
", source: " << *sourcesIt <<
", transformed source: " << transformedSource <<
", dist: " << dist;
391 if (dist < minDistance )
393 minDistanceIterator = sourcesIt;
397 if (minDistanceIterator == sources.end())
399 MITK_INFO <<
"minimum distance point is: " << *minDistanceIterator <<
" (dist: " << targetsIt->EuclideanDistanceTo(transform->TransformPoint(*minDistanceIterator)) <<
", minDist: " << minDistance <<
")";
400 sortedSources.push_back(*minDistanceIterator);
401 sources.erase(minDistanceIterator);
404 sources = sortedSources;
420 TransformInitializerType::LandmarkPointType curData;
422 for (LandmarkPointContainer::size_type index = 0; index < sources.size(); index++)
425 m_Errors.push_back(curData.EuclideanDistanceTo(targets.at(index)));
430 catch (std::exception& e)
434 itkExceptionMacro(
"Initializing landmark-transform failed\n. " << e.what());
NavigationData * GetOutput(void)
return the output (output with id 0) of the filter
NavigationDataToNavigationDataFilter is the base class of all filters that receive NavigationDatas as...
DataCollection - Class to facilitate loading/accessing structured data.
virtual void SetDataValid(bool _arg)
sets the dataValid flag of the NavigationData object indicating if the object contains valid data ...
mitk::Quaternion OrientationType
Type that holds the orientation part of the tracking data.
virtual PositionType GetPosition() const
returns position of the NavigationData object
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
const NavigationData * GetInput(void) const
Get the input of this filter.
virtual void SetOrientation(OrientationType _arg)
sets the orientation of the NavigationData object
virtual void SetPosition(PositionType _arg)
sets the position of the NavigationData object
void itk2vtk(const Tin &in, Tout &out)
void Graft(const DataObject *data) override
Graft the data and information from one NavigationData to another.
void CreateOutputsForAllInputs()
Create an output for each input.
virtual OrientationType GetOrientation() const
returns the orientation of the NavigationData object
virtual bool IsDataValid() const
returns true if the object contains valid data
::map::core::RegistrationBase RegistrationType