NifTK  16.4.1 - 0798f20
CMIC's Translational Medical Imaging Platform
itkSuperEllipseFit.h
Go to the documentation of this file.
1 /*=============================================================================
2 
3  NifTK: A software platform for medical image computing.
4 
5  Copyright (c) University College London (UCL). All rights reserved.
6 
7  This software is distributed WITHOUT ANY WARRANTY; without even
8  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9  PURPOSE.
10 
11  See LICENSE.txt in the top level directory for details.
12 
13  =============================================================================*/
14 
15 #ifndef __itkSuperEllipseFit_h
16 #define __itkSuperEllipseFit_h
17 
18 #include <itkMultipleValuedCostFunction.h>
19 #include <itkLevenbergMarquardtOptimizer.h>
20 
21 #include <vnl/vnl_vector.h>
22 #include <vnl/vnl_matrix.h>
23 #include <vnl/vnl_math.h>
24 
25 #include <itkArray.h>
26 #include <itkArray2D.h>
27 
28 #include <deque>
29 
30 namespace itk {
31 
32 typedef vnl_matrix<double> MatrixType;
33 typedef vnl_vector<double> VectorType;
34 
35 
36 #if 0
37 
38 class ITK_EXPORT Index2D : public itk::Index< 2 >
39 {
40  Index2D() {
41  this->m_Index[0] = 0.;
42  this->m_Index[1] = 0.;
43  }
44 
45  Index2D operator=(const Index2D &newIndex) {
46 
47  for ( unsigned int i = 0; i < Dimension; i++ )
48  {
49  m_Index[i] = newIndex.m_Index[i];
50  }
51  return *this;
52  }
53 }
54 
55 #endif
56 
57 
58 // --------------------------------------------------------------------------
59 // SuperEllipseFitMetric
60 // --------------------------------------------------------------------------
61 
62 class ITK_EXPORT SuperEllipseFitMetric : public MultipleValuedCostFunction
63 {
64 public:
65 
67 
68  typedef MultipleValuedCostFunction Superclass;
69  typedef SmartPointer<Self> Pointer;
70  typedef SmartPointer<const Self> ConstPointer;
71 
72  itkNewMacro( Self );
73 
74  enum { NumberOfParameters = 5 };
75 
76  typedef Superclass::ParametersType ParametersType;
77  typedef Superclass::DerivativeType DerivativeType;
78  typedef Superclass::MeasureType MeasureType;
79 
80  typedef itk::Index< 2 > Index2D;
81 
82  typedef std::deque< Index2D > DataType;
83 
85  {
86  }
87 
88  void SetData( DataType &inputData )
89  {
90  m_NumberOfDataPoints = inputData.size();
91 
92  m_Measure.SetSize( m_NumberOfDataPoints );
93  m_Derivative.SetSize( NumberOfParameters, m_NumberOfDataPoints );
94 
95  m_Data = inputData;
96  }
97 
98  MeasureType GetValue( const ParametersType &parameters ) const override
99  {
100  unsigned int i;
101 
102  double A = parameters[0];
103  double B = parameters[1];
104  double C = parameters[2];
105  double D = parameters[3];
106  double E = parameters[4];
107 
108  double x;
109  double y;
110 
111  unsigned int iPoint = 0;
112 
113  std::deque< Index2D >::const_iterator itData = m_Data.begin();
114 
115  while ( itData != m_Data.end() )
116  {
117  x = (*itData)[0];
118  y = (*itData)[1];
119 
120  m_Measure[ iPoint ] = A*x*x + B*y*y + C*x + D*y + E;
121 
122  ++itData;
123  iPoint++;
124  }
125 
126  return m_Measure;
127  }
128 
129  void GetDerivative( const ParametersType &parameters,
130  DerivativeType &derivative ) const override
131  {
132  unsigned int iPoint = 0;
133 
134  double x;
135  double y;
136 
137  std::deque< Index2D >::const_iterator itData = m_Data.begin();
138 
139  while ( itData != m_Data.end() )
140  {
141  x = (*itData)[0];
142  y = (*itData)[1];
143 
144  m_Derivative[0][iPoint] = x*x;
145  m_Derivative[1][iPoint] = y*y;
146  m_Derivative[2][iPoint] = x;
147  m_Derivative[3][iPoint] = y;
148  m_Derivative[4][iPoint] = 1.0;
149  }
150 
151  derivative = m_Derivative;
152 
153  ++itData;
154  iPoint++;
155  }
156 
157  unsigned int GetNumberOfParameters(void) const override
158  {
159  return NumberOfParameters;
160  }
161 
162  unsigned int GetNumberOfValues(void) const override
163  {
164  return m_NumberOfDataPoints;
165  }
166 
167 
168 protected:
169 
170  DataType m_Data;
171 
172 
173 private:
174 
175  unsigned int m_NumberOfDataPoints;
176 
177  mutable MeasureType m_Measure;
178  mutable DerivativeType m_Derivative;
179 
180 };
181 
182 
183 
184 // --------------------------------------------------------------------------
185 // CommandIterationUpdateSuperEllipseFit
186 // --------------------------------------------------------------------------
187 
189 {
190  public:
192  typedef Command Superclass;
193  typedef SmartPointer<Self> Pointer;
194  itkNewMacro( Self );
195  protected:
197  {
198  m_IterationNumber=0;
199  }
200  public:
201  typedef LevenbergMarquardtOptimizer OptimizerType;
202  typedef const OptimizerType *OptimizerPointer;
203 
204  void Execute(Object *caller, const EventObject & event) override
205  {
206  Execute( (const Object *)caller, event);
207  }
208 
209  void Execute(const Object * object, const EventObject & event) override
210  {
211  std::cout << "Observer::Execute() " << std::endl;
212  OptimizerPointer optimizer =
213  dynamic_cast< OptimizerPointer >( object );
214  if( m_FunctionEvent.CheckEvent( &event ) )
215  {
216  std::cout << m_IterationNumber++ << " ";
217  std::cout << optimizer->GetCachedValue() << " ";
218  std::cout << optimizer->GetCachedCurrentPosition() << std::endl;
219  }
220  else if( m_GradientEvent.CheckEvent( &event ) )
221  {
222  std::cout << "Gradient " << optimizer->GetCachedDerivative() << " ";
223  }
224 
225  }
226  private:
227  unsigned long m_IterationNumber;
228 
229  FunctionEvaluationIterationEvent m_FunctionEvent;
230  GradientEvaluationIterationEvent m_GradientEvent;
231 };
232 
233 
234 // --------------------------------------------------------------------------
235 // SuperEllipseFit()
236 // --------------------------------------------------------------------------
237 
239  bool useGradient = true,
240  double fTolerance = 1e-2,
241  double gTolerance = 1e-2,
242  double xTolerance = 1e-5,
243  double epsilonFunction = 1e-9,
244  int maxIterations = 200 )
245 {
246  std::cout << "Levenberg Marquardt optimisation \n \n";
247 
248  typedef LevenbergMarquardtOptimizer OptimizerType;
249 
250  typedef OptimizerType::InternalOptimizerType vnlOptimizerType;
251 
252  // Declaration of a itkOptimizer
253  OptimizerType::Pointer optimizer = OptimizerType::New();
254 
255  // Declaration of the CostFunction adaptor
257 
258  costFunction->SetData( data );
259 
260  typedef SuperEllipseFitMetric::ParametersType ParametersType;
261  ParametersType parameters( SuperEllipseFitMetric::NumberOfParameters );
262 
263  parameters.Fill( 0.0 );
264  costFunction->GetValue(parameters);
265 
266  std::cout << "Number of Values = " << costFunction->GetNumberOfValues() << "\n";
267 
268  try
269  {
270  optimizer->SetCostFunction( costFunction.GetPointer() );
271  }
272  catch( ExceptionObject & e )
273  {
274  std::cout << "Exception thrown ! " << std::endl;
275  std::cout << "An error ocurred during Optimization" << std::endl;
276  std::cout << e << std::endl;
277  return EXIT_FAILURE;
278  }
279 
280  // this following call is equivalent to invoke: costFunction->SetUseGradient( useGradient );
281  optimizer->GetUseCostFunctionGradient();
282  optimizer->UseCostFunctionGradientOn();
283  optimizer->UseCostFunctionGradientOff();
284  optimizer->SetUseCostFunctionGradient( useGradient );
285 
286 
287  vnlOptimizerType * vnlOptimizer = optimizer->GetOptimizer();
288 
289  vnlOptimizer->set_f_tolerance( fTolerance );
290  vnlOptimizer->set_g_tolerance( gTolerance );
291  vnlOptimizer->set_x_tolerance( xTolerance );
292  vnlOptimizer->set_epsilon_function( epsilonFunction );
293  vnlOptimizer->set_max_function_evals( maxIterations );
294 
295  // We start not so far from the solution
296  typedef SuperEllipseFitMetric::ParametersType ParametersType;
297  ParametersType initialValue( SuperEllipseFitMetric::NumberOfParameters );
298 
299  initialValue[0] = 10;
300  initialValue[1] = 20;
301  initialValue[2] = 100;
302  initialValue[3] = 200;
303  initialValue[4] = 1;
304 
305  OptimizerType::ParametersType currentValue(SuperEllipseFitMetric::NumberOfParameters);
306 
307  currentValue = initialValue;
308 
309  optimizer->SetInitialPosition( currentValue );
310 
313  optimizer->AddObserver( IterationEvent(), observer );
314  optimizer->AddObserver( FunctionEvaluationIterationEvent(), observer );
315 
316  try
317  {
318  optimizer->StartOptimization();
319  }
320  catch( ExceptionObject & e )
321  {
322  std::cerr << "Exception thrown ! " << std::endl;
323  std::cerr << "An error ocurred during Optimization" << std::endl;
324  std::cerr << "Location = " << e.GetLocation() << std::endl;
325  std::cerr << "Description = " << e.GetDescription() << std::endl;
326  return EXIT_FAILURE;
327  }
328 
329 
330  // Error codes taken from vxl/vnl/vnl_nonlinear_minimizer.h
331  std::cout << "End condition = ";
332  switch( vnlOptimizer->get_failure_code() )
333  {
334  case vnl_nonlinear_minimizer::ERROR_FAILURE:
335  std::cout << " Error Failure"; break;
336  case vnl_nonlinear_minimizer::ERROR_DODGY_INPUT:
337  std::cout << " Error Dogy Input"; break;
338  case vnl_nonlinear_minimizer::CONVERGED_FTOL:
339  std::cout << " Converged F Tolerance"; break;
340  case vnl_nonlinear_minimizer::CONVERGED_XTOL:
341  std::cout << " Converged X Tolerance"; break;
342  case vnl_nonlinear_minimizer::CONVERGED_XFTOL:
343  std::cout << " Converged XF Tolerance"; break;
344  case vnl_nonlinear_minimizer::CONVERGED_GTOL:
345  std::cout << " Converged G Tolerance"; break;
346  case vnl_nonlinear_minimizer::FAILED_TOO_MANY_ITERATIONS:
347  std::cout << " Too many iterations "; break;
348  case vnl_nonlinear_minimizer::FAILED_FTOL_TOO_SMALL:
349  std::cout << " Failed F Tolerance too small "; break;
350  case vnl_nonlinear_minimizer::FAILED_XTOL_TOO_SMALL:
351  std::cout << " Failed X Tolerance too small "; break;
352  case vnl_nonlinear_minimizer::FAILED_GTOL_TOO_SMALL:
353  std::cout << " Failed G Tolerance too small "; break;
354  case vnl_nonlinear_minimizer::FAILED_USER_REQUEST:
355  std::cout << " Failed user request "; break;
356  }
357  std::cout << std::endl;
358  std::cout << "Number of iters = " << vnlOptimizer->get_num_iterations() << std::endl;
359  std::cout << "Number of evals = " << vnlOptimizer->get_num_evaluations() << std::endl;
360  std::cout << std::endl;
361 
362 
363  OptimizerType::ParametersType finalPosition;
364  finalPosition = optimizer->GetCurrentPosition();
365 
366  std::cout << "Solution = (";
367  std::cout << finalPosition[0] << "," ;
368  std::cout << finalPosition[1] << "," ;
369  std::cout << finalPosition[2] << "," ;
370  std::cout << finalPosition[3] << "," ;
371  std::cout << finalPosition[4] << ")" << std::endl;
372 
373  return EXIT_SUCCESS;
374 };
375 
376 } // end namespace itk
377 
378 #endif
379 
380 
std::deque< Index2D > DataType
Definition: itkSuperEllipseFit.h:82
int SuperEllipseFit(SuperEllipseFitMetric::DataType &data, bool useGradient=true, double fTolerance=1e-2, double gTolerance=1e-2, double xTolerance=1e-5, double epsilonFunction=1e-9, int maxIterations=200)
Definition: itkSuperEllipseFit.h:238
SmartPointer< Self > Pointer
Definition: itkSuperEllipseFit.h:193
MeasureType GetValue(const ParametersType &parameters) const override
Definition: itkSuperEllipseFit.h:98
LevenbergMarquardtOptimizer OptimizerType
Definition: itkSuperEllipseFit.h:201
itk::Index< 2 > Index2D
Definition: itkSuperEllipseFit.h:80
DataType m_Data
Definition: itkSuperEllipseFit.h:170
unsigned int GetNumberOfParameters(void) const override
Definition: itkSuperEllipseFit.h:157
SmartPointer< Self > Pointer
Definition: itkSuperEllipseFit.h:69
CommandIterationUpdateSuperEllipseFit()
Definition: itkSuperEllipseFit.h:196
MultipleValuedCostFunction Superclass
Definition: itkSuperEllipseFit.h:68
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1236
CommandIterationUpdateSuperEllipseFit Self
Definition: itkSuperEllipseFit.h:191
Definition: niftkITKAffineResampleImage.cxx:74
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1363
vnl_matrix< double > MatrixType
Definition: itkSuperEllipseFit.h:32
Definition: itkSuperEllipseFit.h:62
vnl_vector< double > VectorType
Definition: itkSuperEllipseFit.h:33
Superclass::DerivativeType DerivativeType
Definition: itkSuperEllipseFit.h:77
SmartPointer< const Self > ConstPointer
Definition: itkSuperEllipseFit.h:70
SuperEllipseFitMetric(void)
Definition: itkSuperEllipseFit.h:84
Definition: itkSuperEllipseFit.h:74
Definition: itkSuperEllipseFit.h:188
Command Superclass
Definition: itkSuperEllipseFit.h:192
Superclass::MeasureType MeasureType
Definition: itkSuperEllipseFit.h:78
void SetData(DataType &inputData)
Definition: itkSuperEllipseFit.h:88
void Execute(Object *caller, const EventObject &event) override
Definition: itkSuperEllipseFit.h:204
GLint GLint GLint GLint GLint x
Definition: glew.h:1236
Superclass::ParametersType ParametersType
Definition: itkSuperEllipseFit.h:76
SuperEllipseFitMetric Self
Definition: itkSuperEllipseFit.h:66
void Execute(const Object *object, const EventObject &event) override
Definition: itkSuperEllipseFit.h:209
const OptimizerType * OptimizerPointer
Definition: itkSuperEllipseFit.h:202
const unsigned int Dimension
Definition: niftkBreastDCEandADC.cxx:89
cl_event event
Definition: glew.h:3231
unsigned int GetNumberOfValues(void) const override
Definition: itkSuperEllipseFit.h:162
void GetDerivative(const ParametersType &parameters, DerivativeType &derivative) const override
Definition: itkSuperEllipseFit.h:129