SLIP  1.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
levenberg_marquardt.hpp
Go to the documentation of this file.
1 /*
2  * Copyright(c):
3  * Signal Image and Communications (SIC) Department
4  * http://www.sic.sp2mi.univ-poitiers.fr/
5  * - University of Poitiers, France http://www.univ-poitiers.fr
6  * - XLIM Institute UMR CNRS 7252 http://www.xlim.fr/
7  *
8  * and
9  *
10  * D2 Fluid, Thermic and Combustion
11  * - University of Poitiers, France http://www.univ-poitiers.fr
12  * - PPRIME Institute - UPR CNRS 3346 http://www.pprime.fr
13  * - ISAE-ENSMA http://www.ensma.fr
14  *
15  * Contributor(s):
16  * The SLIP team,
17  * Benoit Tremblais <tremblais_AT_sic.univ-poitiers.fr>,
18  * Laurent David <laurent.david_AT_lea.univ-poitiers.fr>,
19  * Ludovic Chatellier <ludovic.chatellier_AT_univ-poitiers.fr>,
20  * Lionel Thomas <lionel.thomas_AT_univ-poitiers.fr>,
21  * Denis Arrivault <arrivault_AT_sic.univ-poitiers.fr>,
22  * Julien Dombre <julien.dombre_AT_univ-poitiers.fr>.
23  *
24  * Description:
25  * The Simple Library of Image Processing (SLIP) is a new image processing
26  * library. It is written in the C++ language following as much as possible
27  * the ISO/ANSI C++ standard. It is consequently compatible with any system
28  * satisfying the ANSI C++ complience. It works on different Unix , Linux ,
29  * Mircrosoft Windows and Mac OS X plateforms. SLIP is a research library that
30  * was created by the Signal, Image and Communications (SIC) departement of
31  * the XLIM, UMR 7252 CNRS Institute in collaboration with the Fluids, Thermic
32  * and Combustion departement of the P', UPR 3346 CNRS Institute of the
33  * University of Poitiers.
34  *
35  * The SLIP Library source code has been registered to the APP (French Agency
36  * for the Protection of Programs) by the University of Poitiers and CNRS,
37  * under registration number IDDN.FR.001.300034.000.S.P.2010.000.21000.
38 
39  * http://www.sic.sp2mi.univ-poitiers.fr/slip/
40  *
41  * This software is governed by the CeCILL-C license under French law and
42  * abiding by the rules of distribution of free software. You can use,
43  * modify and/ or redistribute the software under the terms of the CeCILL-C
44  * license as circulated by CEA, CNRS and INRIA at the following URL
45  * http://www.cecill.info.
46  * As a counterpart to the access to the source code and rights to copy,
47  * modify and redistribute granted by the license, users are provided only
48  * with a limited warranty and the software's author, the holder of the
49  * economic rights, and the successive licensors have only limited
50  * liability.
51  *
52  * In this respect, the user's attention is drawn to the risks associated
53  * with loading, using, modifying and/or developing or reproducing the
54  * software by the user in light of its specific status of free software,
55  * that may mean that it is complicated to manipulate, and that also
56  * therefore means that it is reserved for developers and experienced
57  * professionals having in-depth computer knowledge. Users are therefore
58  * encouraged to load and test the software's suitability as regards their
59  * requirements in conditions enabling the security of their systems and/or
60  * data to be ensured and, more generally, to use and operate it in the
61  * same conditions as regards security.
62  *
63  * The fact that you are presently reading this means that you have had
64  * knowledge of the CeCILL-C license and that you accept its terms.
65  */
66 
67 
68 
75 #ifndef SLIP_LEVENBERG_MARQUARDT_HPP
76 #define SLIP_LEVENBERG_MARQUARDT_HPP
77 
78 #include "Vector3d.hpp"
79 #include "KVector.hpp"
80 #include "Matrix.hpp"
81 #include "linear_algebra.hpp"
82 
83 
84 namespace slip
85 {
86 
95 template <typename Type>
96 struct funLM_bp : public std::unary_function <slip::Vector<Type>,slip::Vector<Type> >
97 {
98  typedef funLM_bp<Type> self;
105  funLM_bp(const slip::Vector<Type>& Data) :
106  data_(Data),
107  r_(slip::Vector<Type>(2))
108  {}
109  slip::Vector<Type>& operator() (const slip::Vector<Type>& pt) // define the function
110  {
111  Type u = data_[21];
112  Type v = data_[22];
113  Type X = pt[0];
114  Type Y = pt[1];
115  Type Z =data_[23];
116  Type den = (data_[6]*X + data_[7]*Y + data_[8]*Z + data_[11]);
117  Type xd = (data_[0]*X + data_[1]*Y + data_[2]*Z + data_[9])/den;
118  Type yd = (data_[3]*X + data_[4]*Y + data_[5]*Z + data_[10])/den;
119  Type R1 = data_[14];
120  Type R2 = data_[15];
121  Type R3 = data_[16];
122  Type D1 = data_[17];
123  Type D2 = data_[18];
124  Type P1 = data_[19];
125  Type P2 = data_[20];
126  Type x_p = xd-data_[12];
127  Type y_p = yd-data_[13];
128  Type x_p2 = x_p*x_p;
129  Type y_p2 = y_p*y_p;
130  Type two_x_p_y_p = static_cast<Type>(2.0) * x_p*y_p;
131  Type rhoi2 = x_p2+y_p2;
132  Type rhoi2_2 = rhoi2*rhoi2;
133  Type rhoi2_3 = rhoi2_2*rhoi2;
134  Type three = static_cast<Type>(3.0);
135  Type rad = (R1*rhoi2 + R2*rhoi2_2 + R3*rhoi2_3);
136  xd = xd + x_p*rad + D1*two_x_p_y_p + D2*(three*x_p2 + y_p2) + P1*rhoi2;
137  yd = yd + y_p*rad + D2*two_x_p_y_p + D1*(three*y_p2 + x_p2) + P2*rhoi2;
138 
139  r_[0] = u-xd;
140  r_[1] = v-yd;
141 
142  return r_;
143 }
146 };
147 
148 
149 
155 template <typename Type>
156 struct funLM_DLT : public std::unary_function <slip::Vector<Type>,slip::Vector<Type> > // parameter : Vector, return a double
157 {
158 
159  typedef funLM_DLT<Type> self;
160 
162  data_(Data), // initialize function with given data
163  N_((Data.size()-19)/5),
164  _2N_(2*N_),
165  _3N_(3*N_),
166  _4N_(4*N_),
167  _5N_(5*N_),
168  _5N_p_7_(_5N_ + 7),
169  _5N_p_19_(_5N_ + 19),
170  M_(slip::Vector<Type>(12)),
171  r_(slip::Vector<Type>(2*N_))
172  {
174  }
175 
176 
177  slip::Vector<Type>& operator() (const slip::Vector<Type>& p) // define the function
178  {
179  Type R1 = p[2]*data_[_5N_];
180  Type R2 = p[3]*data_[_5N_+1];
181  Type R3 = p[4]*data_[_5N_+2];
182  Type D1 = p[5]*data_[_5N_+3];
183  Type D2 = p[6]*data_[_5N_+4];
184  Type P1 = p[7]*data_[_5N_+5];
185  Type P2 = p[8]*data_[_5N_+6];
186 
187  Type U0 = p[0];
188  Type V0 = p[1];
189  Type two = static_cast<Type>(2.0);
190  Type three = static_cast<Type>(3.0);
191 
192  for(std::size_t i=0, k = 0; i < N_; ++i,k+=2)
193  {
194  Type u = data_(i);
195  Type v = data_(N_+i);
196  Type X = data_(_2N_+i);
197  Type Y = data_(_3N_+i);
198  Type Z = data_(_4N_+i);
199  Type den = (M_[6]*X + M_[7]*Y + M_[8]*Z + M_[11]);
200  Type xr = (M_[0]*X + M_[1]*Y + M_[2]*Z + M_[9] )/den;
201  Type yr = (M_[3]*X + M_[4]*Y + M_[5]*Z + M_[10])/den;
202 
203  Type xr_p = xr-U0;
204  Type yr_p = yr-V0;
205  Type xr_p2 = xr_p * xr_p;
206  Type yr_p2 = yr_p * yr_p;
207  Type two_xr_p_yr_p = two * xr_p * yr_p;
208  Type rhoi2 = xr_p2 + yr_p2;
209  Type rhoi22 = rhoi2 * rhoi2;
210  Type rhoi222 = rhoi22 * rhoi2;
211  Type R123 = (R1*rhoi2 + R2*rhoi22 + R3*rhoi222);
212  Type xd = xr + xr_p*R123 + D1*two_xr_p_yr_p + D2*(yr_p2 + three*xr_p2) + P1*rhoi2;
213  Type yd = yr + yr_p*R123 + D2*two_xr_p_yr_p + D1*(xr_p2 + three*yr_p2) + P2*rhoi2;
214  r_[k] = u - xd;
215  r_[k+1] = v - yd;
216  }
217  return r_;
218  }
219 
220 
222  std::size_t N_;
223  std::size_t _2N_;
224  std::size_t _3N_;
225  std::size_t _4N_;
226  std::size_t _5N_;
227  std::size_t _5N_p_7_;
228  std::size_t _5N_p_19_;
231 };
232 
233 
241 template <typename T,typename RandomAccessIterator>
242 T LM_chi2(RandomAccessIterator first, RandomAccessIterator last)
243 {
244  T chisq = T();
245  const T N = static_cast<T>(last-first);
246  for(; first != last; ++first)
247  {
248  chisq += (*first * *first)/N;
249  }
250  return chisq;
251 }
252 
253 
327 template<typename Function,
328  typename Real,
329  typename DerivativeFunction>
330 void marquardt (Function& fun,
331  DerivativeFunction& df,
332  slip::Vector<Real> &par,
334  Real& calchi2,
335  const int maxiter = 10000,
336  const Real eps = static_cast<Real>(1e-6))
337 {
338 
339  //const int maxiter = 10000;
340  const std::size_t N = r.size();
341  const std::size_t npar = par.size();
342 
343  slip::Vector<Real> par2(npar);
344  slip::Vector<Real> delta(npar);
345  slip::Vector<Real> b(npar);
346  // double tmp;
347  slip::Matrix<Real> aprime(npar,npar);
348  //std::cout<<"npar = "<<npar<<" N = "<<N<<std::endl;
349  slip::Matrix<Real> A(npar,N);
350 
351 
352  //const Real eps = static_cast<Real>(1e-6);
353  Real lamfac = static_cast<Real>(2.0);
354  Real two = static_cast<Real>(2.0);
355  Real minus_two = - two;
356  Real zero = static_cast<Real>(0.0);
357  Real lambda = static_cast<Real>(0.5);
358  bool done = 0;
359  int decrease = 0;
360  int niter = 1;
361 
362  //value for the initial fit
363  r = fun(par);
364  //compute jacobian
365  df(par.begin(),par.end(),A); /* A= matrix jacobien transpose */
366 
367  //compute chi^2
368  Real chisq = LM_chi2<Real>(r.begin(),r.end());
369 
370 //initial matrices; curvature matrix H and b
371  slip::Matrix<Real> AAt(npar,npar);
373 
374  for(std::size_t i = 0; i < npar; ++i)
375  {
376  b[i] = zero;
377  for(std::size_t k=0; k < N; ++k)
378  {
379  b[i] += minus_two*A[i][k]*r[k] ;
380  }
381  }
382 
383 //Main Loop
384  while(!done)
385  {
386  /* Set up a' */
387  for (std::size_t k = 0; k < npar; ++k)
388  {
389  for (std::size_t i = 0; i < npar; ++i)
390  {
391  aprime[i][k] = two * AAt[i][k];
392  }
393  aprime[k][k] = (two*AAt[k][k] + lambda);
394  }
395  /* Solve Matrix Equation: a'.delta = b */
396  slip::lu_solve(aprime,delta,b);
397 
398  /* Increment parameters in work space and evaluate new chisq */
399  for (std::size_t i = 0; i < npar; ++i)
400  {
401  par2[i] = par[i] + delta[i];
402  }
403  r = fun(par2);
404 
405  //compute chisq2
406  Real chisq2 = LM_chi2<Real>(r.begin(),r.end());
407 
408  if (chisq2 <= chisq)
409  {
410  decrease = 1;
411  if (chisq == chisq2)
412  {
413  done = 1;
414  }
415  if (fabs(((chisq - chisq2)/chisq)) < eps && decrease )
416  {
417  done = 1;
418  }
419  std::copy(par2.begin(),par2.end(),par.begin());
420 
421  if (!done)
422  {
423  // new Hessien and b
424  df(par.begin(),par.end(),A);
426  for(std::size_t i = 0; i < npar; ++i)
427  {
428  b[i] = zero;
429  for(std::size_t k = 0; k < N; ++k)
430  {
431  b[i] += minus_two* A[i][k] * r[k] ;
432  }
433  }
434  chisq = chisq2;
435  lambda = lambda / lamfac;
436  decrease = 1;
437  }
438  }
439  else
440  {
441  decrease = 0;
442  lambda = two*lambda;
443  }
444 
445  if (niter > maxiter)
446  {
447  done = 1;
448  }
449  niter++;
450  }
451 
452  calchi2 = LM_chi2<Real>(r.begin(),r.end());
453 }
454 
460 template <typename Function,
461  typename Type>
463 {
464 
465  LMDerivFunctor(const Function& fun,
466  const int N,
467  const int npar):
468  fun_(fun),
469  N_(N),
470  npar_(npar),
471  p_inf_(slip::Vector<Type>(npar)),
472  p_sup_(slip::Vector<Type>(npar)),
473  rinf_(slip::Vector<Type>(N,static_cast<Type>(0.0))),
474  rsup_(slip::Vector<Type>(N,static_cast<Type>(0.0))),
475  delta_(0.001),
476  delta2_(0.002)
477  {}
478 
479  LMDerivFunctor(const Function& fun,
480  const int N,
481  const int npar,
482  const Type& delta):
483  fun_(fun),
484  N_(N),
485  npar_(npar),
486  p_inf_(slip::Vector<Type>(npar)),
487  p_sup_(slip::Vector<Type>(npar)),
488  rinf_(slip::Vector<Type>(N,static_cast<Type>(0.0))),
489  rsup_(slip::Vector<Type>(N,static_cast<Type>(0.0))),
490  delta_(delta),
491  delta2_(static_cast<Type>(2.0)*delta)
492  {}
493 
494 
495  template <typename RandomAccessIterator>
496  void operator()(RandomAccessIterator p_first,
497  RandomAccessIterator p_last,
499  {
500  assert(static_cast<int>(p_last-p_first)==npar_);
501 
502  std::copy(p_first,p_last,p_sup_.begin());
503  std::copy(p_first,p_last,p_inf_.begin());
504  typename slip::Vector<Type>::iterator it_p_inf = p_inf_.begin();
505  typename slip::Vector<Type>::iterator it_p_sup = p_sup_.begin();
506 
507  for(int k =0; p_first != p_last; ++k,++p_first, ++it_p_inf,++it_p_sup)
508  {
509  Type pk = *p_first;
510  *it_p_inf = pk - delta_;
511  *it_p_sup = pk + delta_;
512  rsup_ = fun_(p_sup_);
513  rinf_ = fun_(p_inf_);
514  for (int i = 0; i < N_ ; ++i)
515  {
516  A[k][i] =(rsup_[i] - rinf_[i]) / delta2_;
517  }
518  *it_p_inf = pk;
519  *it_p_sup = pk;
520  }
521  }
522 
523  //attributes
524  Function fun_;
525  int N_;
526  int npar_;
531  Type delta_;
532  Type delta2_;
533 };
534 
535 
536 
537 }//slip::
538 
539 #endif // SLIP_LEVENBERG_MARQUARDT_HPP
LMDerivFunctor(const Function &fun, const int N, const int npar, const Type &delta)
void lu_solve(const Matrix LU, const std::size_t nr, const std::size_t nc, const Vector1 &Indx, const std::size_t nv1, const Vector2 &B, const std::size_t nv2, Vector3 &X, const std::size_t nv3)
Solve Linear Equation using LU decomposition.
void matrix_matrixt_multiplies(RandomAccessIterator2d1 M1_up, RandomAccessIterator2d1 M1_bot, RandomAccessIterator2d2 Res_up, RandomAccessIterator2d2 Res_bot)
Computes the multiplication of a matrix with its transposate A^T .
slip::Vector< Type > & operator()(const slip::Vector< Type > &pt)
iterator end()
Returns a read/write iterator that points one past the last element in the Vector. Iteration is done in ordinary element order.
Definition: Vector.hpp:1481
slip::Vector< Type > data_
generic derivative functor
Provides common linear algebra algorithms.
T LM_chi2(RandomAccessIterator first, RandomAccessIterator last)
Computes Chi2 for Lebvenberg Marquardt algorithm.
slip::Vector< Type > p_sup_
Function to compute the backprojection of the 3d world point corresponding to the backprojection of a...
void marquardt(Function &fun, DerivativeFunction &df, slip::Vector< Real > &par, slip::Vector< Real > &r, Real &calchi2, const int maxiter=10000, const Real eps=static_cast< Real >(1e-6))
Optimization of function using the Levenberg-Marquardt algorithm.
funLM_DLT(const slip::Vector< Type > &Data)
slip::Vector< Type > rinf_
Provides a class to manipulate static and generic vectors.
pointer iterator
Definition: Vector.hpp:169
size_type size() const
Returns the number of elements in the Vector.
Definition: Vector.hpp:1743
void copy(_II first, _II last, _OI output_first)
Copy algorithm optimized for slip iterators.
Definition: copy_ext.hpp:177
LMDerivFunctor(const Function &fun, const int N, const int npar)
Provides a class to manipulate 3d Vector.
slip::Vector< Type > r_
slip::Vector< Type > r_
slip::Vector< Type > data_
Numerical matrix class. This container statisfies the BidirectionnalContainer concepts of the STL...
slip::Vector< Type > rsup_
slip::Vector< Type > & operator()(const slip::Vector< Type > &p)
void operator()(RandomAccessIterator p_first, RandomAccessIterator p_last, slip::Matrix< Type > &A)
Function to compute the camera model of distortion using the Levenberg-Marquadt algorithm.
Provides a class to manipulate Numerical Matrix.
slip::Vector< Type > M_
funLM_bp(const slip::Vector< Type > &Data)
Function to compute the backprojection of the 3d world point corresponding to the backprojection of a...
slip::Vector< Type > p_inf_
iterator begin()
Returns a read/write iterator that points to the first element in the Vector. Iteration is done in or...
Definition: Vector.hpp:1474