18 #include "itkIndent.h"
19 #include "itkEuler3DTransform.h"
20 #include "itkVersorRigid3DTransform.h"
21 #include "itkEuclideanDistancePointMetric.h"
22 #include "itkLevenbergMarquardtOptimizer.h"
23 #include "itkPointSet.h"
24 #include "itkPointSetToPointSetRegistrationMethod.h"
29 m_ErrorMean(-1.0), m_ErrorStdDev(-1.0), m_ErrorRMS(-1.0), m_ErrorMin(-1.0), m_ErrorMax(-1.0), m_ErrorAbsMax(-1.0),
30 m_SourcePoints(), m_TargetPoints(), m_LandmarkTransformInitializer(NULL), m_LandmarkTransform(NULL),
31 m_QuatLandmarkTransform(NULL), m_QuatTransform(NULL), m_Errors(), m_UseICPInitialization(false)
46 m_LandmarkTransform = NULL;
47 m_LandmarkTransformInitializer = NULL;
48 m_QuatLandmarkTransform = NULL;
49 m_QuatTransform = NULL;
55 if (m_UseICPInitialization ==
true)
57 if (this->FindCorrespondentLandmarks(sources, targets) ==
false)
59 itkExceptionMacro(
"Landmark correspondence finding failed.");
63 if(m_SourcePoints.size() != m_TargetPoints.size())
65 itkExceptionMacro(
"Cannot initialize Filter, number of input datas does not equal number of output datas.");
68 this->UpdateLandmarkTransform(sources, targets);
74 m_SourcePoints.clear();
76 TransformInitializerType::LandmarkPointType lPoint;
78 for (mitk::PointSet::PointsContainer::ConstIterator it = mitkSourcePointSet->GetPointSet()->GetPoints()->Begin();
79 it != mitkSourcePointSet->GetPointSet()->GetPoints()->End(); ++it)
81 mitk::FillVector3D(lPoint, it->Value().GetElement(0), it->Value().GetElement(1), it->Value().GetElement(2));
82 m_SourcePoints.push_back(lPoint);
85 if (m_SourcePoints.size() < 3)
87 itkExceptionMacro(
"SourcePointSet must contain at least 3 points");
90 if (this->IsInitialized())
91 this->InitializeLandmarkTransform(m_SourcePoints, m_TargetPoints);
97 m_TargetPoints.clear();
98 TransformInitializerType::LandmarkPointType lPoint;
99 for (mitk::PointSet::PointsContainer::ConstIterator it = mitkTargetPointSet->GetPointSet()->GetPoints()->Begin();
100 it != mitkTargetPointSet->GetPointSet()->GetPoints()->End(); ++it)
102 mitk::FillVector3D(lPoint, it->Value().GetElement(0), it->Value().GetElement(1), it->Value().GetElement(2));
103 m_TargetPoints.push_back(lPoint);
106 if (m_TargetPoints.size() < 3)
108 itkExceptionMacro(
"TargetPointSet must contain at least 3 points");
111 if (this->IsInitialized())
112 this->InitializeLandmarkTransform(m_SourcePoints, m_TargetPoints);
124 return m_ErrorStdDev;
148 return m_ErrorAbsMax;
160 for (std::vector<mitk::ScalarType>::size_type i = 0; i < vector.size(); i++)
162 m_ErrorMean += vector[i];
163 m_ErrorRMS += pow(vector[i],2);
164 if(vector[i] < m_ErrorMin)
165 m_ErrorMin = vector[i];
166 if(vector[i] > m_ErrorMax)
167 m_ErrorMax = vector[i];
168 if(fabs(vector[i]) > fabs(m_ErrorAbsMax))
169 m_ErrorAbsMax = vector[i];
171 m_ErrorMean /= vector.size();
172 m_ErrorRMS = sqrt(m_ErrorRMS/vector.size());
176 for (std::vector<mitk::ScalarType>::size_type i = 0; i < vector.size(); i++)
177 m_ErrorStdDev += pow(vector[i] - m_ErrorMean, 2);
179 if(vector.size() > 1)
180 m_ErrorStdDev = sqrt(m_ErrorStdDev / (vector.size() - 1.0));
187 this->CreateOutputsForAllInputs();
189 TransformInitializerType::LandmarkPointType lPointIn, lPointOut;
192 for (
unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i)
204 output->
Graft(input);
206 if (this->IsInitialized() ==
false)
211 lPointIn[0] = tempCoordinate[0];
212 lPointIn[1] = tempCoordinate[1];
213 lPointIn[2] = tempCoordinate[2];
216 lPointOut = m_LandmarkTransform->TransformPoint(lPointIn);
217 tempCoordinate[0] = lPointOut[0];
218 tempCoordinate[1] = lPointOut[1];
219 tempCoordinate[2] = lPointOut[2];
224 vnl_quaternion<double>
const vnlQuatIn(quatIn.x(), quatIn.y(), quatIn.z(), quatIn.r());
225 m_QuatTransform->SetRotation(vnlQuatIn);
227 m_QuatLandmarkTransform->SetMatrix(m_LandmarkTransform->GetMatrix());
229 m_QuatLandmarkTransform->Compose(m_QuatTransform,
true);
231 vnl_quaternion<double> vnlQuatOut = m_QuatLandmarkTransform->GetRotation();
241 return (m_SourcePoints.size() >= 3) && (m_TargetPoints.size() >= 3);
247 Superclass::PrintSelf(os, indent);
249 os << indent << this->GetNameOfClass() <<
":\n";
250 os << indent << m_SourcePoints.size() <<
" SourcePoints exist: \n";
251 itk::Indent nextIndent = indent.GetNextIndent();
253 for (LandmarkPointContainer::const_iterator it = m_SourcePoints.begin(); it != m_SourcePoints.end(); ++it)
255 os << nextIndent <<
"Point " << i++ <<
": [";
256 os << it->GetElement(0);
257 for (
unsigned int i = 1; i < TransformInitializerType::LandmarkPointType::GetPointDimension(); ++i)
259 os <<
", " << it->GetElement(i);
264 os << indent << m_TargetPoints.size() <<
" TargetPoints exist: \n";
266 for (LandmarkPointContainer::const_iterator it = m_TargetPoints.begin(); it != m_TargetPoints.end(); ++it)
268 os << nextIndent <<
"Point " << i++ <<
": [";
269 os << it->GetElement(0);
270 for (
unsigned int i = 1; i < TransformInitializerType::LandmarkPointType::GetPointDimension(); ++i)
272 os <<
", " << it->GetElement(i);
276 os << indent <<
"Landmarktransform initialized: " << this->IsInitialized() <<
"\n";
277 if (this->IsInitialized() ==
true)
278 m_LandmarkTransform->Print(os, nextIndent);
279 os << indent <<
"Registration error statistics:\n";
280 os << nextIndent <<
"FRE: " << this->GetFRE() <<
"\n";
281 os << nextIndent <<
"FRE std.dev.: " << this->GetFREStdDev() <<
"\n";
282 os << nextIndent <<
"FRE RMS: " << this->GetRMSError() <<
"\n";
283 os << nextIndent <<
"Minimum registration error: " << this->GetMinError() <<
"\n";
284 os << nextIndent <<
"Maximum registration error: " << this->GetMaxError() <<
"\n";
285 os << nextIndent <<
"Absolute Maximum registration error: " << this->GetAbsMaxError() <<
"\n";
297 if (sources.size() < 6 || targets.size() < 6)
302 typedef itk::PointSet<mitk::ScalarType, 3>
PointSetType;
305 typedef itk::EuclideanDistancePointMetric< PointSetType, PointSetType> MetricType;
310 typedef itk::VersorRigid3DTransform< double > TransformType;
311 typedef TransformType ParametersType;
312 typedef itk::PointSetToPointSetRegistrationMethod< PointSetType, PointSetType >
RegistrationType;
317 for (LandmarkPointContainer::const_iterator it = sources.begin(); it != sources.end(); ++it)
321 sourcePointSet->SetPoint(i++, doublePoint );
326 for (LandmarkPointContainer::const_iterator it = targets.begin(); it != targets.end(); ++it)
330 targetPointSet->SetPoint(i++, doublePoint );
343 transform->SetIdentity();
347 optimizer->SetUseCostFunctionGradient(
false);
352 itk::LevenbergMarquardtOptimizer::ScalesType scales(transform->GetNumberOfParameters());
353 const double translationScale = 5000;
354 const double rotationScale = 1.0;
355 scales[0] = 1.0 / rotationScale;
356 scales[1] = 1.0 / rotationScale;
357 scales[2] = 1.0 / rotationScale;
358 scales[3] = 1.0 / translationScale;
359 scales[4] = 1.0 / translationScale;
360 scales[5] = 1.0 / translationScale;
362 unsigned long numberOfIterations = 80000;
363 double gradientTolerance = 1e-10;
364 double valueTolerance = 1e-10;
365 double epsilonFunction = 1e-10;
366 optimizer->SetScales( scales );
367 optimizer->SetNumberOfIterations( numberOfIterations );
368 optimizer->SetValueTolerance( valueTolerance );
369 optimizer->SetGradientTolerance( gradientTolerance );
370 optimizer->SetEpsilonFunction( epsilonFunction );
373 registration->SetInitialTransformParameters( transform->GetParameters() );
379 registration->SetMetric( metric );
380 registration->SetOptimizer( optimizer );
381 registration->SetTransform( transform );
382 registration->SetFixedPointSet( targetPointSet );
383 registration->SetMovingPointSet( sourcePointSet );
388 registration->Update();
390 catch( itk::ExceptionObject & e )
392 MITK_INFO <<
"Exception caught during ICP optimization: " << e;
396 MITK_INFO <<
"ICP successful: Solution = " << transform->GetParameters() << std::endl;
397 MITK_INFO <<
"Metric value: " << metric->GetValue(transform->GetParameters());
402 for (LandmarkPointContainer::const_iterator sourcesIt = sources.begin(); sourcesIt != sources.end(); ++sourcesIt)
408 for (LandmarkPointContainer::const_iterator targetsIt = targets.begin(); targetsIt != targets.end(); ++targetsIt)
411 LandmarkPointContainer::iterator minDistanceIterator = sources.end();
412 for (LandmarkPointContainer::iterator sourcesIt = sources.begin(); sourcesIt != sources.end(); ++sourcesIt)
414 TransformInitializerType::LandmarkPointType transformedSource = transform->TransformPoint(*sourcesIt);
415 double dist = targetsIt->EuclideanDistanceTo(transformedSource);
416 MITK_INFO <<
"target: " << *targetsIt <<
", source: " << *sourcesIt <<
", transformed source: " << transformedSource <<
", dist: " << dist;
417 if (dist < minDistance )
419 minDistanceIterator = sourcesIt;
423 if (minDistanceIterator == sources.end())
425 MITK_INFO <<
"minimum distance point is: " << *minDistanceIterator <<
" (dist: " << targetsIt->EuclideanDistanceTo(transform->TransformPoint(*minDistanceIterator)) <<
", minDist: " << minDistance <<
")";
426 sortedSources.push_back(*minDistanceIterator);
427 sources.erase(minDistanceIterator);
430 sources = sortedSources;
440 m_LandmarkTransformInitializer->SetMovingLandmarks(targets);
441 m_LandmarkTransformInitializer->SetFixedLandmarks(sources);
442 m_LandmarkTransform->SetIdentity();
443 m_LandmarkTransformInitializer->InitializeTransform();
446 TransformInitializerType::LandmarkPointType curData;
448 for (LandmarkPointContainer::size_type index = 0; index < sources.size(); index++)
450 curData = m_LandmarkTransform->TransformPoint(sources.at(index));
451 m_Errors.push_back(curData.EuclideanDistanceTo(targets.at(index)));
453 this->AccumulateStatistics(m_Errors);
456 catch (std::exception& e)
459 m_LandmarkTransform->SetIdentity();
460 itkExceptionMacro(
"Initializing landmark-transform failed\n. " << e.what());
itk::SmartPointer< Self > Pointer
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 ...
virtual OrientationType GetOrientation() const
returns the orientation of the NavigationData object
mitk::Quaternion OrientationType
Type that holds the orientation part of the tracking data.
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
virtual void SetOrientation(OrientationType _arg)
sets the orientation of the NavigationData object
virtual bool IsDataValid() const
returns true if the object contains valid data
virtual void SetPosition(PositionType _arg)
sets the position of the NavigationData object
virtual PositionType GetPosition() const
returns position of the NavigationData object
void itk2vtk(const Tin &in, Tout &out)
virtual void Graft(const DataObject *data) override
Graft the data and information from one NavigationData to another.
::map::core::RegistrationBase RegistrationType
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.