Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpRobust.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * M-Estimator and various influence function.
32  *
33  * Authors:
34  * Andrew Comport
35  * Jean Laneurit
36  *
37  *****************************************************************************/
38 
46 #include <visp3/core/vpDebug.h>
47 #include <visp3/core/vpColVector.h>
48 #include <visp3/core/vpMath.h>
49 
50 #include <visp3/core/vpRobust.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <stdlib.h>
54 #include <cmath> // std::fabs
55 #include <limits> // numeric_limits
56 
57 #define vpITMAX 100
58 #define vpEPS 3.0e-7
59 #define vpCST 1
60 
61 
62 // ===================================================================
68 vpRobust::vpRobust(unsigned int n_data)
69  : normres(), sorted_normres(), sorted_residues(), NoiseThreshold(0.0017), sig_prev(0), it(0), swap(0), size(n_data)
70 {
71  vpCDEBUG(2) << "vpRobust constructor reached" << std::endl;
72 
73  normres.resize(n_data);
74  sorted_normres.resize(n_data);
75  sorted_residues.resize(n_data);
76  // NoiseThreshold=0.0017; //Can not be more accurate than 1 pixel
77 }
78 
83  : normres(), sorted_normres(), sorted_residues(), NoiseThreshold(0.0017), sig_prev(0), it(0), swap(0), size(0)
84 {
85 }
86 
91 {
92  *this = other;
93 }
94 
99 {
100  normres = other.normres;
101  sorted_normres = other.sorted_normres;
102  sorted_residues = other.sorted_residues;
103  NoiseThreshold = other.NoiseThreshold;
104  sig_prev = other.sig_prev;
105  it = other.it;
106  swap = other.swap;
107  size = other.size;
108  return *this;
109 }
110 
111 #ifdef VISP_HAVE_CPP11_COMPATIBILITY
112 
116 {
117  normres = std::move(other.normres);
118  sorted_normres = std::move(other.sorted_normres);
119  sorted_residues = std::move(other.sorted_residues);
120  NoiseThreshold = std::move(other.NoiseThreshold);
121  sig_prev = std::move(other.sig_prev);
122  it = std::move(other.it);
123  swap = std::move(other.swap);
124  size = std::move(other.size);
125  return *this;
126 }
127 #endif
128 
134 void vpRobust::resize(unsigned int n_data){
135 
136  if(n_data!=size){
137  normres.resize(n_data);
138  sorted_normres.resize(n_data);
139  sorted_residues.resize(n_data);
140  size=n_data;
141  }
142 
143 }
144 
145 // ===================================================================
181 // ===================================================================
183  const vpColVector &residues,
184  vpColVector &weights)
185 {
186 
187  double med=0; // median
188  double normmedian=0; // Normalized median
189  double sigma=0;// Standard Deviation
190 
191  // resize vector only if the size of residue vector has changed
192  unsigned int n_data = residues.getRows();
193  resize(n_data);
194 
195  sorted_residues = residues;
196 
197  unsigned int ind_med = (unsigned int)(ceil(n_data/2.0))-1;
198 
199  // Calculate median
200  med = select(sorted_residues, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
201  //residualMedian = med ;
202 
203  // Normalize residues
204  for(unsigned int i=0; i<n_data; i++)
205  {
206  normres[i] = (fabs(residues[i]- med));
207  sorted_normres[i] = (fabs(sorted_residues[i]- med));
208 
209  }
210 
211  // Calculate MAD
212  normmedian = select(sorted_normres, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
213  //normalizedResidualMedian = normmedian ;
214  // 1.48 keeps scale estimate consistent for a normal probability dist.
215  sigma = 1.4826*normmedian; // median Absolute Deviation
216 
217  // Set a minimum threshold for sigma
218  // (when sigma reaches the level of noise in the image)
219  if(sigma < NoiseThreshold)
220  {
221  sigma= NoiseThreshold;
222  }
223 
224  switch (method)
225  {
226  case TUKEY :
227  {
228  psiTukey(sigma, normres,weights);
229 
230  vpCDEBUG(2) << "Tukey's function computed" << std::endl;
231  break ;
232 
233  }
234  case CAUCHY :
235  {
236  psiCauchy(sigma, normres,weights);
237  break ;
238  }
239  /* case MCLURE :
240  {
241  psiMcLure(sigma, normres);
242  break ;
243  }*/
244  case HUBER :
245  {
246  psiHuber(sigma, normres,weights);
247  break ;
248  }
249  }
250 }
251 
252 
253 
255  const vpColVector &residues,
256  const vpColVector& all_residues,
257  vpColVector &weights)
258 {
259 
260 
261  double normmedian=0; // Normalized median
262  double sigma=0;// Standard Deviation
263 
264  unsigned int n_all_data = all_residues.getRows();
265  vpColVector all_normres(n_all_data);
266 
267  // compute median with the residues vector, return all_normres which are the normalized all_residues vector.
268  normmedian = computeNormalizedMedian(all_normres,residues,all_residues,weights);
269 
270 
271  // 1.48 keeps scale estimate consistent for a normal probability dist.
272  sigma = 1.4826*normmedian; // Median Absolute Deviation
273 
274  // Set a minimum threshold for sigma
275  // (when sigma reaches the level of noise in the image)
276  if(sigma < NoiseThreshold)
277  {
278  sigma= NoiseThreshold;
279  }
280 
281 
282  switch (method)
283  {
284  case TUKEY :
285  {
286  psiTukey(sigma, all_normres,weights);
287 
288  vpCDEBUG(2) << "Tukey's function computed" << std::endl;
289  break ;
290 
291  }
292  case CAUCHY :
293  {
294  psiCauchy(sigma, all_normres,weights);
295  break ;
296  }
297  /* case MCLURE :
298  {
299  psiMcLure(sigma, all_normres);
300  break ;
301  }*/
302  case HUBER :
303  {
304  psiHuber(sigma, all_normres,weights);
305  break ;
306  }
307 
308 
309  };
310 }
311 
312 
313 
314 double vpRobust::computeNormalizedMedian(vpColVector &all_normres,
315  const vpColVector &residues,
316  const vpColVector &all_residues,
317  const vpColVector & weights
318  )
319 {
320  double med=0;
321  double normmedian=0;
322 
323  unsigned int n_all_data = all_residues.getRows();
324  unsigned int n_data = residues.getRows();
325 
326  // resize vector only if the size of residue vector has changed
327  resize(n_data);
328 
329  sorted_residues = residues;
330  vpColVector no_null_weight_residues;
331  no_null_weight_residues.resize(n_data);
332 
333  //all_normres.resize(n_all_data); // Normalized Residue
334  //vpColVector sorted_normres(n_data); // Normalized Residue
335  //vpColVector sorted_residues = residues;
336  //vpColVector sorted_residues;
337 
338 
339  unsigned int index =0;
340  for(unsigned int j=0;j<n_data;j++)
341  {
342  //if(weights[j]!=0)
343  if(std::fabs(weights[j]) > std::numeric_limits<double>::epsilon())
344  {
345  no_null_weight_residues[index]=residues[j];
346  index++;
347  }
348  }
349  sorted_residues.resize(index);
350  memcpy(sorted_residues.data,no_null_weight_residues.data,index*sizeof(double));
351  n_data=index;
352 
353  vpCDEBUG(2) << "vpRobust MEstimator reached. No. data = " << n_data
354  << std::endl;
355 
356  // Calculate Median
357  // Be careful to not use the rejected residues for the
358  // calculation.
359 
360  unsigned int ind_med = (unsigned int)(ceil(n_data/2.0))-1;
361  med = select(sorted_residues, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
362 
363  unsigned int i;
364  // Normalize residues
365  for(i=0; i<n_all_data; i++)
366  {
367  all_normres[i] = (fabs(all_residues[i]- med));
368  }
369 
370  for(i=0; i<n_data; i++)
371  {
372  sorted_normres[i] = (fabs(sorted_residues[i]- med));
373  }
374  // MAD calculated only on first iteration
375 
376  //normmedian = Median(normres, weights);
377  //normmedian = Median(normres);
378  normmedian = select(sorted_normres, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
379 
380  return normmedian;
381 }
382 
383 // ===================================================================
391 // ===================================================================
394 {
395 
396  double med=0; // Median
397  double sigma=0; // Standard Deviation
398 
399  unsigned int n_data = residues.getRows();
400  vpColVector norm_res(n_data); // Normalized Residue
401  vpColVector w(n_data);
402 
403  vpCDEBUG(2) << "vpRobust MEstimator reached. No. data = " << n_data
404  << std::endl;
405 
406  // Calculate Median
407  unsigned int ind_med = (unsigned int)(ceil(n_data/2.0))-1;
408  med = select(residues, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
409 
410  // Normalize residues
411  for(unsigned int i=0; i<n_data; i++)
412  norm_res[i] = (fabs(residues[i]- med));
413 
414  // Check for various methods.
415  // For Huber compute Simultaneous scale estimate
416  // For Others use MAD calculated on first iteration
417  if(it==0)
418  {
419  double normmedian = select(norm_res, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/); // Normalized Median
420  // 1.48 keeps scale estimate consistent for a normal probability dist.
421  sigma = 1.4826*normmedian; // Median Absolute Deviation
422  }
423  else
424  {
425  // compute simultaneous scale estimate
426  sigma = simultscale(residues);
427  }
428 
429  // Set a minimum threshold for sigma
430  // (when sigma reaches the level of noise in the image)
431  if(sigma < NoiseThreshold)
432  {
433  sigma= NoiseThreshold;
434  }
435 
436  vpCDEBUG(2) << "MAD and C computed" << std::endl;
437 
438  psiHuber(sigma, norm_res,w);
439 
440  sig_prev = sigma;
441 
442  return w;
443 }
444 
445 double
446 vpRobust::scale(vpRobustEstimatorType method, vpColVector &x)
447 {
448  unsigned int p = 6; //Number of parameters to be estimated.
449  unsigned int n = x.getRows();
450  double sigma2=0;
451  /* long */ double Expectation=0;
452  /* long */ double Sum_chi=0;
453 
454  for(unsigned int i=0; i<n; i++)
455  {
456  double chiTmp = constrainedChi(method, x[i]);
457 #if defined(VISP_HAVE_FUNC_STD_ERFC)
458  Expectation += chiTmp*std::erfc(chiTmp);
459 #elif defined(VISP_HAVE_FUNC_ERFC)
460  Expectation += chiTmp*erfc(chiTmp);
461 #else
462  Expectation += chiTmp*(1-erf(chiTmp));
463 #endif
464 
465  Sum_chi += chiTmp;
466 
467 #ifdef VP_DEBUG
468 #if VP_DEBUG_MODE == 3
469  {
470 #if defined(VISP_HAVE_FUNC_STD_ERFC)
471  std::cout << "erf = " << std::erfc(chiTmp) << std::endl;
472 #elif defined(VISP_HAVE_FUNC_ERFC)
473  std::cout << "erf = " << erfc(chiTmp) << std::endl;
474 #else
475  std::cout << "erf = " << (1-erf(chiTmp)) << std::endl;
476 #endif
477  std::cout << "x[i] = " << x[i] <<std::endl;
478  std::cout << "chi = " << chiTmp << std::endl;
479  std::cout << "Sum chi = " << chiTmp*vpMath::sqr(sig_prev) << std::endl;
480 #if defined(VISP_HAVE_FUNC_STD_ERFC)
481  std::cout << "Expectation = " << chiTmp*std::erfc(chiTmp) << std::endl;
482 #elif defined(VISP_HAVE_FUNC_ERFC)
483  std::cout << "Expectation = " << chiTmp*erfc(chiTmp) << std::endl;
484 #else
485  std::cout << "Expectation = " << chiTmp*(1-erf(chiTmp)) << std::endl;
486 #endif
487  //getchar();
488  }
489 #endif
490 #endif
491  }
492 
493 
494  sigma2 = Sum_chi*vpMath::sqr(sig_prev)/((n-p)*Expectation);
495 
496 #ifdef VP_DEBUG
497 #if VP_DEBUG_MODE == 3
498  {
499  std::cout << "Expectation = " << Expectation << std::endl;
500  std::cout << "Sum chi = " << Sum_chi << std::endl;
501  std::cout << "sig_prev" << sig_prev << std::endl;
502  std::cout << "sig_out" << sqrt(fabs(sigma2)) << std::endl;
503  }
504 #endif
505 #endif
506 
507  return sqrt(fabs(sigma2));
508 
509 }
510 
511 
512 double
513 vpRobust::simultscale(vpColVector &x)
514 {
515  unsigned int p = 6; //Number of parameters to be estimated.
516  unsigned int n = x.getRows();
517  double sigma2=0;
518  /* long */ double Expectation=0;
519  /* long */ double Sum_chi=0;
520 
521  for(unsigned int i=0; i<n; i++)
522  {
523 
524  double chiTmp = simult_chi_huber(x[i]);
525 #if defined(VISP_HAVE_FUNC_STD_ERFC)
526  Expectation += chiTmp*std::erfc(chiTmp);
527 #elif defined(VISP_HAVE_FUNC_ERFC)
528  Expectation += chiTmp*erfc(chiTmp);
529 #else
530  Expectation += chiTmp*(1-erf(chiTmp));
531 #endif
532  Sum_chi += chiTmp;
533 
534 #ifdef VP_DEBUG
535 #if VP_DEBUG_MODE == 3
536  {
537 #if defined(VISP_HAVE_FUNC_STD_ERFC)
538  std::cout << "erf = " << std::erfc(chiTmp) << std::endl;
539 #elif defined(VISP_HAVE_FUNC_ERFC)
540  std::cout << "erf = " << erfc(chiTmp) << std::endl;
541 #else
542  std::cout << "erf = " << (1-erf(chiTmp)) << std::endl;
543 #endif
544  std::cout << "x[i] = " << x[i] <<std::endl;
545  std::cout << "chi = " << chiTmp << std::endl;
546  std::cout << "Sum chi = " << chiTmp*vpMath::sqr(sig_prev) << std::endl;
547 #if defined(VISP_HAVE_FUNC_STD_ERFC)
548  std::cout << "Expectation = " << chiTmp*std::erfc(chiTmp) << std::endl;
549 #elif defined(VISP_HAVE_FUNC_ERFC)
550  std::cout << "Expectation = " << chiTmp*erfc(chiTmp) << std::endl;
551 #else
552  std::cout << "Expectation = " << chiTmp*(1-erf(chiTmp)) << std::endl;
553 #endif
554  //getchar();
555  }
556 #endif
557 #endif
558  }
559 
560 
561  sigma2 = Sum_chi*vpMath::sqr(sig_prev)/((n-p)*Expectation);
562 
563 #ifdef VP_DEBUG
564 #if VP_DEBUG_MODE == 3
565  {
566  std::cout << "Expectation = " << Expectation << std::endl;
567  std::cout << "Sum chi = " << Sum_chi << std::endl;
568  std::cout << "sig_prev" << sig_prev << std::endl;
569  std::cout << "sig_out" << sqrt(fabs(sigma2)) << std::endl;
570  }
571 #endif
572 #endif
573 
574  return sqrt(fabs(sigma2));
575 
576 }
577 
578 double
579 vpRobust::constrainedChi(vpRobustEstimatorType method, double x)
580 {
581  switch (method)
582  {
583  case TUKEY :
584  return constrainedChiTukey(x);
585  case CAUCHY :
586  return constrainedChiCauchy(x);
587  case HUBER :
588  return constrainedChiHuber(x);
589  };
590 
591  return -1;
592 
593 }
594 
595 
596 double
597 vpRobust::constrainedChiTukey(double x)
598 {
599  double sct=0;
600  double s=sig_prev;
601  //double epsillon=0.5;
602 
603  if(fabs(x) <= 4.7*sig_prev)
604  {
605  double a=4.7;
606  //sct = (vpMath::sqr(s*a-x)*vpMath::sqr(s*a+x)*vpMath::sqr(x))/(s*vpMath::sqr(vpMath::sqr(a*vpMath::sqr(s))));
608  }
609  else
610  sct = -1/s;
611 
612  return sct;
613 }
614 
615 
616 double
617 vpRobust::constrainedChiCauchy(double x)
618 {
619  double sct = 0;
620  //double u = x/sig_prev;
621  double s = sig_prev;
622  double b = 2.3849;
623 
624  sct = -1*(vpMath::sqr(x)*b)/(s*(vpMath::sqr(s*b)+vpMath::sqr(x)));
625 
626  return sct;
627 }
628 
629 double
630 vpRobust::constrainedChiHuber(double x)
631 {
632  double sct=0;
633  double u = x/sig_prev;
634  double c = 1.2107; //1.345;
635 
636  if(fabs(u) <= c)
637  sct = vpMath::sqr(u);
638  else
639  sct = vpMath::sqr(c);
640 
641  return sct;
642 }
643 
644 double
645 vpRobust::simult_chi_huber(double x)
646 {
647  double sct=0;
648  double u = x/sig_prev;
649  double c = 1.2107; //1.345;
650 
651  if(fabs(u) <= c)
652  {
653  //sct = 0.5*vpMath::sqr(u);
654  sct = vpMath::sqr(u);
655  }
656  else
657  {
658  //sct = 0.5*vpMath::sqr(c);
659  sct = vpMath::sqr(c);
660  }
661 
662  return sct;
663 }
664 
673 void vpRobust::psiTukey(double sig, vpColVector &x, vpColVector & weights)
674 {
675 
676  unsigned int n_data = x.getRows();
677  double cst_const = vpCST*4.6851;
678 
679  for(unsigned int i=0; i<n_data; i++)
680  {
681  //if(sig==0 && weights[i]!=0)
682  if(std::fabs(sig) <= std::numeric_limits<double>::epsilon() && std::fabs(weights[i]) > std::numeric_limits<double>::epsilon())
683  {
684  weights[i]=1;
685  continue;
686  }
687 
688  double xi_sig = x[i]/sig;
689 
690  //if((fabs(xi_sig)<=(cst_const)) && weights[i]!=0)
691  if((std::fabs(xi_sig)<=(cst_const)) && std::fabs(weights[i]) > std::numeric_limits<double>::epsilon())
692  {
693  weights[i] = vpMath::sqr(1-vpMath::sqr(xi_sig/cst_const));
694  //w[i] = vpMath::sqr(1-vpMath::sqr(x[i]/sig/4.7));
695  }
696  else
697  {
698  //Outlier - could resize list of points tracked here?
699  weights[i] = 0;
700  }
701  }
702 }
703 
711 void vpRobust::psiHuber(double sig, vpColVector &x, vpColVector &weights)
712 {
713  double c = 1.2107; //1.345;
714  unsigned int n_data = x.getRows();
715 
716  for(unsigned int i=0; i<n_data; i++)
717  {
718  //if(weights[i]!=0)
719  if(std::fabs(weights[i]) > std::numeric_limits<double>::epsilon())
720  {
721  double xi_sig = x[i]/sig;
722  if(fabs(xi_sig)<=c)
723  weights[i] = 1;
724  else
725  weights[i] = c/fabs(xi_sig);
726  }
727  }
728 }
729 
738 void vpRobust::psiCauchy(double sig, vpColVector &x, vpColVector &weights)
739 {
740  unsigned int n_data = x.getRows();
741  double const_sig = 2.3849*sig;
742 
743  //Calculate Cauchy's equation
744  for(unsigned int i=0; i<n_data; i++)
745  {
746  weights[i] = 1/(1+vpMath::sqr(x[i]/(const_sig)));
747 
748  // If one coordinate is an outlier the other is too!
749  // w[i] < 0.01 is a threshold to be set
750  /*if(w[i] < 0.01)
751  {
752  if(i%2 == 0)
753  {
754  w[i+1] = w[i];
755  i++;
756  }
757  else
758  w[i-1] = w[i];
759  }*/
760  }
761 }
762 
763 
771 void vpRobust::psiMcLure(double sig, vpColVector &r,vpColVector &weights)
772 {
773  unsigned int n_data = r.getRows();
774 
775  //McLure's function
776  for(unsigned int i=0; i<n_data; i++)
777  {
778  weights[i] = 1/(vpMath::sqr(1+vpMath::sqr(r[i]/sig)));
779  //w[i] = 2*mad/vpMath::sqr((mad+r[i]*r[i]));//odobez
780 
781  // If one coordinate is an outlier the other is too!
782  // w[i] < 0.01 is a threshold to be set
783  /*if(w[i] < 0.01)
784  {
785  if(i%2 == 0)
786  {
787  w[i+1] = w[i];
788  i++;
789  }
790  else
791  w[i-1] = w[i];
792  }*/
793  }
794 }
795 
796 
803 int
804 vpRobust::partition(vpColVector &a, int l, int r)
805 {
806  int i = l-1;
807  int j = r;
808  double v = a[(unsigned int)r];
809 
810  for (;;)
811  {
812  while (a[(unsigned int)++i] < v) ;
813  while (v < a[(unsigned int)--j]) if (j == l) break;
814  if (i >= j) break;
815  exch(a[(unsigned int)i], a[(unsigned int)j]);
816  }
817  exch(a[(unsigned int)i], a[(unsigned int)r]);
818  return i;
819 }
820 
828 double
829 vpRobust::select(vpColVector &a, int l, int r, int k)
830 {
831  while (r > l)
832  {
833  int i = partition(a, l, r);
834  if (i >= k) r = i-1;
835  if (i <= k) l = i+1;
836  }
837  return a[(unsigned int)k];
838 }
839 
840 
841 #if !defined(VISP_HAVE_FUNC_ERFC) && !defined(VISP_HAVE_FUNC_STD_ERFC)
842 double
843 vpRobust::erf(double x)
844 {
845  return x < 0.0 ? -gammp(0.5,x*x) : gammp(0.5,x*x);
846 }
847 
848 double
849 vpRobust::gammp(double a, double x)
850 {
851  double gamser=0.,gammcf=0.,gln;
852 
853  if (x < 0.0 || a <= 0.0)
854  std::cout << "Invalid arguments in routine GAMMP";
855  if (x < (a+1.0))
856  {
857  gser(&gamser,a,x,&gln);
858  return gamser;
859  }
860  else
861  {
862  gcf(&gammcf,a,x,&gln);
863  return 1.0-gammcf;
864  }
865 }
866 
867 void
868 vpRobust::gser(double *gamser, double a, double x, double *gln)
869 {
870  *gln=gammln(a);
871  if (x <= 0.0)
872  {
873  if (x < 0.0)
874  std::cout << "x less than 0 in routine GSER";
875  *gamser=0.0;
876  return;
877  }
878  else
879  {
880  double ap=a;
881  double sum=1.0/a;
882  double del = sum;
883  for (int n=1; n<=vpITMAX; n++)
884  {
885  ap += 1.0;
886  del *= x/ap;
887  sum += del;
888  if (fabs(del) < fabs(sum)*vpEPS)
889  {
890  *gamser=sum*exp(-x+a*log(x)-(*gln));
891  return;
892  }
893  }
894  std::cout << "a too large, vpITMAX too small in routine GSER";
895  return;
896  }
897 }
898 
899 void
900 vpRobust::gcf(double *gammcf, double a, double x, double *gln)
901 {
902  double gold=0.0,g,fac=1.0,b1=1.0;
903  double b0=0.0,a1,a0=1.0;
904 
905  *gln=gammln(a);
906  a1=x;
907  for (int n=1; n<=vpITMAX; n++)
908  {
909  double an=(double) n;
910  double ana=an-a;
911  a0=(a1+a0*ana)*fac;
912  b0=(b1+b0*ana)*fac;
913  double anf=an*fac;
914  a1=x*a0+anf*a1;
915  b1=x*b0+anf*b1;
916  //if (a1)
917  if (std::fabs(a1) > std::numeric_limits<double>::epsilon())
918  {
919  fac=1.0/a1;
920  g=b1*fac;
921  if (fabs((g-gold)/g) < vpEPS)
922  {
923  *gammcf=exp(-x+a*log(x)-(*gln))*g;
924  return;
925  }
926  gold=g;
927  }
928  }
929  std::cout << "a too large, vpITMAX too small in routine GCF";
930 }
931 
932 double
933 vpRobust::gammln(double xx)
934 {
935  double x,tmp,ser;
936  static double cof[6]={76.18009173,-86.50532033,24.01409822,
937  -1.231739516,0.120858003e-2,-0.536382e-5};
938 
939  x=xx-1.0;
940  tmp=x+5.5;
941  tmp -= (x+0.5)*log(tmp);
942  ser=1.0;
943  for (int j=0; j<=5; j++)
944  {
945  x += 1.0;
946  ser += cof[j]/x;
947  }
948  return -tmp+log(2.50662827465*ser);
949 }
950 #endif
951 
952 
953 
954 // double
955 // vpRobust::median(const vpColVector &v)
956 // {
957 // int i,j;
958 // int inf, sup;
959 // int n = v.getRows() ;
960 // vpColVector infsup(n) ;
961 // vpColVector eq(n) ;
962 //
963 // for (i=0;i<n;i++)
964 // {
965 // // We compute the number of elements superior to the current value (sup)
966 // // the number of elements inferior (inf) to the current value and
967 // // the number of elements equal to the current value (eq)
968 // inf = sup = 0;
969 // for (j=0;j<n;j++)
970 // {
971 // if (i != j)
972 // {
973 // if (v[i] <= v[j]) inf++;
974 // if (v[i] >= v[j]) sup++;
975 // if (v[i] == v[j]) eq[i]++;
976 // }
977 // }
978 // // We compute then difference between inf and sup
979 // // the median should be for |inf-sup| = 0 (1 if an even number of element)
980 // // which means that there are the same number of element in the array
981 // // that are greater and smaller that this value.
982 // infsup[i] = abs(inf-sup);
983 // }
984 //
985 // // seek for the smaller value of |inf-sup| (should be 0 or 1)
986 // int imin = 0 ; // index of the median in the array
987 // //double eqmax = 0 ; // count of equal values
988 // // min cannot be greater than the number of element
989 // double min = n;
990 //
991 // // number of medians
992 // int mediancount = 0;
993 // // array of medians
994 // int *medianindex = new int[n];
995 //
996 // for (i=0; i<n; i++)
997 // {
998 // if(infsup[i] < min)
999 // {
1000 // min = infsup[i];
1001 // imin = i ;
1002 //
1003 // //reset count of median values
1004 // mediancount=0;
1005 // medianindex[mediancount]=i;
1006 // }
1007 // else if(infsup[i]==min) //If there is another median
1008 // {
1009 // mediancount++;
1010 // medianindex[mediancount]=i;
1011 // }
1012 // }
1013 //
1014 // // Choose smalest data to be the median
1015 // /*for(i=0; i<mediancount+1; i++)
1016 // {
1017 // //Choose the value with the greatest count
1018 // if(eq[medianindex[i]] > eqmax)
1019 // {
1020 // eqmax = eq[medianindex[i]];
1021 // imin = medianindex[i];
1022 // }
1023 // //If we have identical counts
1024 // // Choose smalest data to be the median
1025 // //if(v[medianindex[i]] < v[imin])
1026 // // imin = medianindex[i];
1027 // }*/
1028 //
1029 // // return the median
1030 // delete []medianindex;
1031 // return(v[imin]);
1032 // }
1033 //
1034 // // Calculate median only for the residues which have
1035 // // not be rejected. i.e. weight=0
1036 // double
1037 // vpRobust::median(const vpColVector &v, vpColVector &weights)
1038 // {
1039 // int i,j;
1040 // int inf, sup;
1041 // int n = v.getRows() ;
1042 // vpColVector infsup(n) ;
1043 // vpColVector eq(n) ;
1044 //
1045 // for (i=0;i<n;i++)
1046 // {
1047 // if(weights[i]!=0)
1048 // {
1049 // // We compute the number of elements superior to the current value (sup)
1050 // // the number of elements inferior (inf) to the current value and
1051 // // the number of elements equal to the current value (eq)
1052 // inf = sup = 0;
1053 // for (j=0;j<n;j++)
1054 // {
1055 // if (weights[j]!=0 && i!=j)
1056 // {
1057 // if (v[i] <= v[j]) inf++;
1058 // if (v[i] >= v[j]) sup++;
1059 // if (v[i] == v[j]) eq[i]++;
1060 // }
1061 // }
1062 // // We compute then difference between inf and sup
1063 // // the median should be for |inf-sup| = 0 (1 if an even number of element)
1064 // // which means that there are the same number of element in the array
1065 // // that are greater and smaller that this value.
1066 // infsup[i] = abs(inf-sup);
1067 // }
1068 // }
1069 //
1070 // // seek for the smaller value of |inf-sup| (should be 0 or 1)
1071 // int imin = 0 ; // index of the median in the array
1072 // //double eqmax = 0 ; // count of equal values
1073 // // min cannot be greater than the number of element
1074 // double min = n;
1075 //
1076 // for (i=0; i<n; i++)
1077 // {
1078 // if(weights[i]!=0)
1079 // {
1080 // if(infsup[i] < min)
1081 // {
1082 // min = infsup[i];
1083 // imin = i ;
1084 // }
1085 // }
1086 // }
1087 //
1088 // // return the median
1089 // return(v[imin]);
1090 // }
1091 
1092 
1093 #undef vpITMAX
1094 #undef vpEPS
1095 #undef vpCST
void MEstimator(const vpRobustEstimatorType method, const vpColVector &residues, vpColVector &weights)
Compute the weights according a residue vector and a PsiFunction.
Definition: vpRobust.cpp:182
vpRobust()
Definition: vpRobust.cpp:82
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:84
vpColVector simultMEstimator(vpColVector &residues)
Simult Mestimator.
Definition: vpRobust.cpp:393
static double sqr(double x)
Definition: vpMath.h:110
#define vpCDEBUG(level)
Definition: vpDebug.h:502
vpRobust & operator=(const vpRobust &other)
Definition: vpRobust.cpp:98
unsigned int getRows() const
Return the number of rows of the 2D array.
Definition: vpArray2D.h:152
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
Contains an M-Estimator and various influence function.
Definition: vpRobust.h:60
void resize(unsigned int n_data)
Resize containers for sort methods.
Definition: vpRobust.cpp:134
vpRobustEstimatorType
Enumeration of influence functions.
Definition: vpRobust.h:65
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:225