Visual Servoing Platform  version 3.0.0
vpRobust.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 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 
84 void vpRobust::resize(unsigned int n_data){
85 
86  if(n_data!=size){
87  normres.resize(n_data);
88  sorted_normres.resize(n_data);
89  sorted_residues.resize(n_data);
90  size=n_data;
91  }
92 
93 }
94 
95 // ===================================================================
131 // ===================================================================
133  const vpColVector &residues,
134  vpColVector &weights)
135 {
136 
137  double med=0; // median
138  double normmedian=0; // Normalized median
139  double sigma=0;// Standard Deviation
140 
141  // resize vector only if the size of residue vector has changed
142  unsigned int n_data = residues.getRows();
143  resize(n_data);
144 
145  sorted_residues = residues;
146 
147  unsigned int ind_med = (unsigned int)(ceil(n_data/2.0))-1;
148 
149  // Calculate median
150  med = select(sorted_residues, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
151  //residualMedian = med ;
152 
153  // Normalize residues
154  for(unsigned int i=0; i<n_data; i++)
155  {
156  normres[i] = (fabs(residues[i]- med));
157  sorted_normres[i] = (fabs(sorted_residues[i]- med));
158 
159  }
160 
161  // Calculate MAD
162  normmedian = select(sorted_normres, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
163  //normalizedResidualMedian = normmedian ;
164  // 1.48 keeps scale estimate consistent for a normal probability dist.
165  sigma = 1.4826*normmedian; // median Absolute Deviation
166 
167  // Set a minimum threshold for sigma
168  // (when sigma reaches the level of noise in the image)
169  if(sigma < NoiseThreshold)
170  {
171  sigma= NoiseThreshold;
172  }
173 
174  switch (method)
175  {
176  case TUKEY :
177  {
178  psiTukey(sigma, normres,weights);
179 
180  vpCDEBUG(2) << "Tukey's function computed" << std::endl;
181  break ;
182 
183  }
184  case CAUCHY :
185  {
186  psiCauchy(sigma, normres,weights);
187  break ;
188  }
189  /* case MCLURE :
190  {
191  psiMcLure(sigma, normres);
192  break ;
193  }*/
194  case HUBER :
195  {
196  psiHuber(sigma, normres,weights);
197  break ;
198  }
199  }
200 }
201 
202 
203 
205  const vpColVector &residues,
206  const vpColVector& all_residues,
207  vpColVector &weights)
208 {
209 
210 
211  double normmedian=0; // Normalized median
212  double sigma=0;// Standard Deviation
213 
214  unsigned int n_all_data = all_residues.getRows();
215  vpColVector all_normres(n_all_data);
216 
217  // compute median with the residues vector, return all_normres which are the normalized all_residues vector.
218  normmedian = computeNormalizedMedian(all_normres,residues,all_residues,weights);
219 
220 
221  // 1.48 keeps scale estimate consistent for a normal probability dist.
222  sigma = 1.4826*normmedian; // Median Absolute Deviation
223 
224  // Set a minimum threshold for sigma
225  // (when sigma reaches the level of noise in the image)
226  if(sigma < NoiseThreshold)
227  {
228  sigma= NoiseThreshold;
229  }
230 
231 
232  switch (method)
233  {
234  case TUKEY :
235  {
236  psiTukey(sigma, all_normres,weights);
237 
238  vpCDEBUG(2) << "Tukey's function computed" << std::endl;
239  break ;
240 
241  }
242  case CAUCHY :
243  {
244  psiCauchy(sigma, all_normres,weights);
245  break ;
246  }
247  /* case MCLURE :
248  {
249  psiMcLure(sigma, all_normres);
250  break ;
251  }*/
252  case HUBER :
253  {
254  psiHuber(sigma, all_normres,weights);
255  break ;
256  }
257 
258 
259  };
260 }
261 
262 
263 
264 double vpRobust::computeNormalizedMedian(vpColVector &all_normres,
265  const vpColVector &residues,
266  const vpColVector &all_residues,
267  const vpColVector & weights
268  )
269 {
270  double med=0;
271  double normmedian=0;
272 
273  unsigned int n_all_data = all_residues.getRows();
274  unsigned int n_data = residues.getRows();
275 
276  // resize vector only if the size of residue vector has changed
277  resize(n_data);
278 
279  sorted_residues = residues;
280  vpColVector no_null_weight_residues;
281  no_null_weight_residues.resize(n_data);
282 
283  //all_normres.resize(n_all_data); // Normalized Residue
284  //vpColVector sorted_normres(n_data); // Normalized Residue
285  //vpColVector sorted_residues = residues;
286  //vpColVector sorted_residues;
287 
288 
289  unsigned int index =0;
290  for(unsigned int j=0;j<n_data;j++)
291  {
292  //if(weights[j]!=0)
293  if(std::fabs(weights[j]) > std::numeric_limits<double>::epsilon())
294  {
295  no_null_weight_residues[index]=residues[j];
296  index++;
297  }
298  }
299  sorted_residues.resize(index);
300  memcpy(sorted_residues.data,no_null_weight_residues.data,index*sizeof(double));
301  n_data=index;
302 
303  vpCDEBUG(2) << "vpRobust MEstimator reached. No. data = " << n_data
304  << std::endl;
305 
306  // Calculate Median
307  // Be careful to not use the rejected residues for the
308  // calculation.
309 
310  unsigned int ind_med = (unsigned int)(ceil(n_data/2.0))-1;
311  med = select(sorted_residues, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
312 
313  unsigned int i;
314  // Normalize residues
315  for(i=0; i<n_all_data; i++)
316  {
317  all_normres[i] = (fabs(all_residues[i]- med));
318  }
319 
320  for(i=0; i<n_data; i++)
321  {
322  sorted_normres[i] = (fabs(sorted_residues[i]- med));
323  }
324  // MAD calculated only on first iteration
325 
326  //normmedian = Median(normres, weights);
327  //normmedian = Median(normres);
328  normmedian = select(sorted_normres, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
329 
330  return normmedian;
331 }
332 
333 // ===================================================================
341 // ===================================================================
344 {
345 
346  double med=0; // Median
347  double normmedian=0; // Normalized Median
348  double sigma=0; // Standard Deviation
349 
350  unsigned int n_data = residues.getRows();
351  vpColVector norm_res(n_data); // Normalized Residue
352  vpColVector w(n_data);
353 
354  vpCDEBUG(2) << "vpRobust MEstimator reached. No. data = " << n_data
355  << std::endl;
356 
357  // Calculate Median
358  unsigned int ind_med = (unsigned int)(ceil(n_data/2.0))-1;
359  med = select(residues, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
360 
361  // Normalize residues
362  for(unsigned int i=0; i<n_data; i++)
363  norm_res[i] = (fabs(residues[i]- med));
364 
365  // Check for various methods.
366  // For Huber compute Simultaneous scale estimate
367  // For Others use MAD calculated on first iteration
368  if(it==0)
369  {
370  normmedian = select(norm_res, 0, (int)n_data-1, (int)ind_med/*(int)n_data/2*/);
371  // 1.48 keeps scale estimate consistent for a normal probability dist.
372  sigma = 1.4826*normmedian; // Median Absolute Deviation
373  }
374  else
375  {
376  // compute simultaneous scale estimate
377  sigma = simultscale(residues);
378  }
379 
380  // Set a minimum threshold for sigma
381  // (when sigma reaches the level of noise in the image)
382  if(sigma < NoiseThreshold)
383  {
384  sigma= NoiseThreshold;
385  }
386 
387  vpCDEBUG(2) << "MAD and C computed" << std::endl;
388 
389  psiHuber(sigma, norm_res,w);
390 
391  sig_prev = sigma;
392 
393  return w;
394 }
395 
396 double
397 vpRobust::scale(vpRobustEstimatorType method, vpColVector &x)
398 {
399  unsigned int p = 6; //Number of parameters to be estimated.
400  unsigned int n = x.getRows();
401  double sigma2=0;
402  /* long */ double Expectation=0;
403  /* long */ double Sum_chi=0;
404  /* long*/ double chiTmp =0;
405 
406  for(unsigned int i=0; i<n; i++)
407  {
408 
409  chiTmp = constrainedChi(method, x[i]);
410  Expectation += chiTmp*(1-erf(chiTmp));
411  Sum_chi += chiTmp;
412 
413 #ifdef VP_DEBUG
414 #if VP_DEBUG_MODE == 3
415  {
416  std::cout << "erf = " << 1-erf(chiTmp) << std::endl;
417  std::cout << "x[i] = " << x[i] <<std::endl;
418  std::cout << "chi = " << chiTmp << std::endl;
419  std::cout << "Sum chi = " << chiTmp*vpMath::sqr(sig_prev) << std::endl;
420  std::cout << "Expectation = " << chiTmp*(1-erf(chiTmp)) << std::endl;
421  //getchar();
422  }
423 #endif
424 #endif
425  }
426 
427 
428  sigma2 = Sum_chi*vpMath::sqr(sig_prev)/((n-p)*Expectation);
429 
430 #ifdef VP_DEBUG
431 #if VP_DEBUG_MODE == 3
432  {
433  std::cout << "Expectation = " << Expectation << std::endl;
434  std::cout << "Sum chi = " << Sum_chi << std::endl;
435  std::cout << "sig_prev" << sig_prev << std::endl;
436  std::cout << "sig_out" << sqrt(fabs(sigma2)) << std::endl;
437  }
438 #endif
439 #endif
440 
441  return sqrt(fabs(sigma2));
442 
443 }
444 
445 
446 double
447 vpRobust::simultscale(vpColVector &x)
448 {
449  unsigned int p = 6; //Number of parameters to be estimated.
450  unsigned int n = x.getRows();
451  double sigma2=0;
452  /* long */ double Expectation=0;
453  /* long */ double Sum_chi=0;
454  /* long */ double chiTmp =0;
455 
456  for(unsigned int i=0; i<n; i++)
457  {
458 
459  chiTmp = simult_chi_huber(x[i]);
460  Expectation += chiTmp*(1-erf(chiTmp));
461  Sum_chi += chiTmp;
462 
463 #ifdef VP_DEBUG
464 #if VP_DEBUG_MODE == 3
465  {
466  std::cout << "erf = " << 1-erf(chiTmp) << std::endl;
467  std::cout << "x[i] = " << x[i] <<std::endl;
468  std::cout << "chi = " << chiTmp << std::endl;
469  std::cout << "Sum chi = " << chiTmp*vpMath::sqr(sig_prev) << std::endl;
470  std::cout << "Expectation = " << chiTmp*(1-erf(chiTmp)) << std::endl;
471  //getchar();
472  }
473 #endif
474 #endif
475  }
476 
477 
478  sigma2 = Sum_chi*vpMath::sqr(sig_prev)/((n-p)*Expectation);
479 
480 #ifdef VP_DEBUG
481 #if VP_DEBUG_MODE == 3
482  {
483  std::cout << "Expectation = " << Expectation << std::endl;
484  std::cout << "Sum chi = " << Sum_chi << std::endl;
485  std::cout << "sig_prev" << sig_prev << std::endl;
486  std::cout << "sig_out" << sqrt(fabs(sigma2)) << std::endl;
487  }
488 #endif
489 #endif
490 
491  return sqrt(fabs(sigma2));
492 
493 }
494 
495 double
496 vpRobust::constrainedChi(vpRobustEstimatorType method, double x)
497 {
498  switch (method)
499  {
500  case TUKEY :
501  return constrainedChiTukey(x);
502  case CAUCHY :
503  return constrainedChiCauchy(x);
504  case HUBER :
505  return constrainedChiHuber(x);
506  };
507 
508  return -1;
509 
510 }
511 
512 
513 double
514 vpRobust::constrainedChiTukey(double x)
515 {
516  double sct=0;
517  double a=4.7;
518  double s=sig_prev;
519  //double epsillon=0.5;
520 
521  if(fabs(x) <= 4.7*sig_prev)
522  {
523  //sct = (vpMath::sqr(s*a-x)*vpMath::sqr(s*a+x)*vpMath::sqr(x))/(s*vpMath::sqr(vpMath::sqr(a*vpMath::sqr(s))));
525  }
526  else
527  sct = -1/s;
528 
529  return sct;
530 }
531 
532 
533 double
534 vpRobust::constrainedChiCauchy(double x)
535 {
536  double sct = 0;
537  //double u = x/sig_prev;
538  double s = sig_prev;
539  double b = 2.3849;
540 
541  sct = -1*(vpMath::sqr(x)*b)/(s*(vpMath::sqr(s*b)+vpMath::sqr(x)));
542 
543  return sct;
544 }
545 
546 double
547 vpRobust::constrainedChiHuber(double x)
548 {
549  double sct=0;
550  double u = x/sig_prev;
551  double c = 1.2107; //1.345;
552 
553  if(fabs(u) <= c)
554  sct = vpMath::sqr(u);
555  else
556  sct = vpMath::sqr(c);
557 
558  return sct;
559 }
560 
561 double
562 vpRobust::simult_chi_huber(double x)
563 {
564  double sct=0;
565  double u = x/sig_prev;
566  double c = 1.2107; //1.345;
567 
568  if(fabs(u) <= c)
569  {
570  //sct = 0.5*vpMath::sqr(u);
571  sct = vpMath::sqr(u);
572  }
573  else
574  {
575  //sct = 0.5*vpMath::sqr(c);
576  sct = vpMath::sqr(c);
577  }
578 
579  return sct;
580 }
581 
590 void vpRobust::psiTukey(double sig, vpColVector &x, vpColVector & weights)
591 {
592 
593  unsigned int n_data = x.getRows();
594  double cst_const = vpCST*4.6851;
595 
596  for(unsigned int i=0; i<n_data; i++)
597  {
598  //if(sig==0 && weights[i]!=0)
599  if(std::fabs(sig) <= std::numeric_limits<double>::epsilon() && std::fabs(weights[i]) > std::numeric_limits<double>::epsilon())
600  {
601  weights[i]=1;
602  continue;
603  }
604 
605  double xi_sig = x[i]/sig;
606 
607  //if((fabs(xi_sig)<=(cst_const)) && weights[i]!=0)
608  if((std::fabs(xi_sig)<=(cst_const)) && std::fabs(weights[i]) > std::numeric_limits<double>::epsilon())
609  {
610  weights[i] = vpMath::sqr(1-vpMath::sqr(xi_sig/cst_const));
611  //w[i] = vpMath::sqr(1-vpMath::sqr(x[i]/sig/4.7));
612  }
613  else
614  {
615  //Outlier - could resize list of points tracked here?
616  weights[i] = 0;
617  }
618  }
619 }
620 
628 void vpRobust::psiHuber(double sig, vpColVector &x, vpColVector &weights)
629 {
630  double c = 1.2107; //1.345;
631  unsigned int n_data = x.getRows();
632 
633  for(unsigned int i=0; i<n_data; i++)
634  {
635  //if(weights[i]!=0)
636  if(std::fabs(weights[i]) > std::numeric_limits<double>::epsilon())
637  {
638  double xi_sig = x[i]/sig;
639  if(fabs(xi_sig)<=c)
640  weights[i] = 1;
641  else
642  weights[i] = c/fabs(xi_sig);
643  }
644  }
645 }
646 
655 void vpRobust::psiCauchy(double sig, vpColVector &x, vpColVector &weights)
656 {
657  unsigned int n_data = x.getRows();
658  double const_sig = 2.3849*sig;
659 
660  //Calculate Cauchy's equation
661  for(unsigned int i=0; i<n_data; i++)
662  {
663  weights[i] = 1/(1+vpMath::sqr(x[i]/(const_sig)));
664 
665  // If one coordinate is an outlier the other is too!
666  // w[i] < 0.01 is a threshold to be set
667  /*if(w[i] < 0.01)
668  {
669  if(i%2 == 0)
670  {
671  w[i+1] = w[i];
672  i++;
673  }
674  else
675  w[i-1] = w[i];
676  }*/
677  }
678 }
679 
680 
688 void vpRobust::psiMcLure(double sig, vpColVector &r,vpColVector &weights)
689 {
690  unsigned int n_data = r.getRows();
691 
692  //McLure's function
693  for(unsigned int i=0; i<n_data; i++)
694  {
695  weights[i] = 1/(vpMath::sqr(1+vpMath::sqr(r[i]/sig)));
696  //w[i] = 2*mad/vpMath::sqr((mad+r[i]*r[i]));//odobez
697 
698  // If one coordinate is an outlier the other is too!
699  // w[i] < 0.01 is a threshold to be set
700  /*if(w[i] < 0.01)
701  {
702  if(i%2 == 0)
703  {
704  w[i+1] = w[i];
705  i++;
706  }
707  else
708  w[i-1] = w[i];
709  }*/
710  }
711 }
712 
713 
720 int
721 vpRobust::partition(vpColVector &a, int l, int r)
722 {
723  int i = l-1;
724  int j = r;
725  double v = a[(unsigned int)r];
726 
727  for (;;)
728  {
729  while (a[(unsigned int)++i] < v) ;
730  while (v < a[(unsigned int)--j]) if (j == l) break;
731  if (i >= j) break;
732  exch(a[(unsigned int)i], a[(unsigned int)j]);
733  }
734  exch(a[(unsigned int)i], a[(unsigned int)r]);
735  return i;
736 }
737 
745 double
746 vpRobust::select(vpColVector &a, int l, int r, int k)
747 {
748  while (r > l)
749  {
750  int i = partition(a, l, r);
751  if (i >= k) r = i-1;
752  if (i <= k) l = i+1;
753  }
754  return a[(unsigned int)k];
755 }
756 
757 
758 double
759 vpRobust::erf(double x)
760 {
761  return x < 0.0 ? -gammp(0.5,x*x) : gammp(0.5,x*x);
762 }
763 
764 double
765 vpRobust::gammp(double a, double x)
766 {
767  double gamser=0.,gammcf=0.,gln;
768 
769  if (x < 0.0 || a <= 0.0)
770  std::cout << "Invalid arguments in routine GAMMP";
771  if (x < (a+1.0))
772  {
773  gser(&gamser,a,x,&gln);
774  return gamser;
775  }
776  else
777  {
778  gcf(&gammcf,a,x,&gln);
779  return 1.0-gammcf;
780  }
781 }
782 
783 void
784 vpRobust::gser(double *gamser, double a, double x, double *gln)
785 {
786  double sum,del,ap;
787 
788  *gln=gammln(a);
789  if (x <= 0.0)
790  {
791  if (x < 0.0)
792  std::cout << "x less than 0 in routine GSER";
793  *gamser=0.0;
794  return;
795  }
796  else
797  {
798  ap=a;
799  del=sum=1.0/a;
800  for (int n=1; n<=vpITMAX; n++)
801  {
802  ap += 1.0;
803  del *= x/ap;
804  sum += del;
805  if (fabs(del) < fabs(sum)*vpEPS)
806  {
807  *gamser=sum*exp(-x+a*log(x)-(*gln));
808  return;
809  }
810  }
811  std::cout << "a too large, vpITMAX too small in routine GSER";
812  return;
813  }
814 }
815 
816 void
817 vpRobust::gcf(double *gammcf, double a, double x, double *gln)
818 {
819  double gold=0.0,g,fac=1.0,b1=1.0;
820  double b0=0.0,anf,ana,an,a1,a0=1.0;
821 
822  *gln=gammln(a);
823  a1=x;
824  for (int n=1; n<=vpITMAX; n++)
825  {
826  an=(double) n;
827  ana=an-a;
828  a0=(a1+a0*ana)*fac;
829  b0=(b1+b0*ana)*fac;
830  anf=an*fac;
831  a1=x*a0+anf*a1;
832  b1=x*b0+anf*b1;
833  //if (a1)
834  if (std::fabs(a1) > std::numeric_limits<double>::epsilon())
835  {
836  fac=1.0/a1;
837  g=b1*fac;
838  if (fabs((g-gold)/g) < vpEPS)
839  {
840  *gammcf=exp(-x+a*log(x)-(*gln))*g;
841  return;
842  }
843  gold=g;
844  }
845  }
846  std::cout << "a too large, vpITMAX too small in routine GCF";
847 }
848 
849 double
850 vpRobust::gammln(double xx)
851 {
852  double x,tmp,ser;
853  static double cof[6]={76.18009173,-86.50532033,24.01409822,
854  -1.231739516,0.120858003e-2,-0.536382e-5};
855 
856  x=xx-1.0;
857  tmp=x+5.5;
858  tmp -= (x+0.5)*log(tmp);
859  ser=1.0;
860  for (int j=0; j<=5; j++)
861  {
862  x += 1.0;
863  ser += cof[j]/x;
864  }
865  return -tmp+log(2.50662827465*ser);
866 }
867 
868 
869 
870 // double
871 // vpRobust::median(const vpColVector &v)
872 // {
873 // int i,j;
874 // int inf, sup;
875 // int n = v.getRows() ;
876 // vpColVector infsup(n) ;
877 // vpColVector eq(n) ;
878 //
879 // for (i=0;i<n;i++)
880 // {
881 // // We compute the number of elements superior to the current value (sup)
882 // // the number of elements inferior (inf) to the current value and
883 // // the number of elements equal to the current value (eq)
884 // inf = sup = 0;
885 // for (j=0;j<n;j++)
886 // {
887 // if (i != j)
888 // {
889 // if (v[i] <= v[j]) inf++;
890 // if (v[i] >= v[j]) sup++;
891 // if (v[i] == v[j]) eq[i]++;
892 // }
893 // }
894 // // We compute then difference between inf and sup
895 // // the median should be for |inf-sup| = 0 (1 if an even number of element)
896 // // which means that there are the same number of element in the array
897 // // that are greater and smaller that this value.
898 // infsup[i] = abs(inf-sup);
899 // }
900 //
901 // // seek for the smaller value of |inf-sup| (should be 0 or 1)
902 // int imin = 0 ; // index of the median in the array
903 // //double eqmax = 0 ; // count of equal values
904 // // min cannot be greater than the number of element
905 // double min = n;
906 //
907 // // number of medians
908 // int mediancount = 0;
909 // // array of medians
910 // int *medianindex = new int[n];
911 //
912 // for (i=0; i<n; i++)
913 // {
914 // if(infsup[i] < min)
915 // {
916 // min = infsup[i];
917 // imin = i ;
918 //
919 // //reset count of median values
920 // mediancount=0;
921 // medianindex[mediancount]=i;
922 // }
923 // else if(infsup[i]==min) //If there is another median
924 // {
925 // mediancount++;
926 // medianindex[mediancount]=i;
927 // }
928 // }
929 //
930 // // Choose smalest data to be the median
931 // /*for(i=0; i<mediancount+1; i++)
932 // {
933 // //Choose the value with the greatest count
934 // if(eq[medianindex[i]] > eqmax)
935 // {
936 // eqmax = eq[medianindex[i]];
937 // imin = medianindex[i];
938 // }
939 // //If we have identical counts
940 // // Choose smalest data to be the median
941 // //if(v[medianindex[i]] < v[imin])
942 // // imin = medianindex[i];
943 // }*/
944 //
945 // // return the median
946 // delete []medianindex;
947 // return(v[imin]);
948 // }
949 //
950 // // Calculate median only for the residues which have
951 // // not be rejected. i.e. weight=0
952 // double
953 // vpRobust::median(const vpColVector &v, vpColVector &weights)
954 // {
955 // int i,j;
956 // int inf, sup;
957 // int n = v.getRows() ;
958 // vpColVector infsup(n) ;
959 // vpColVector eq(n) ;
960 //
961 // for (i=0;i<n;i++)
962 // {
963 // if(weights[i]!=0)
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 (weights[j]!=0 && 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 //
986 // // seek for the smaller value of |inf-sup| (should be 0 or 1)
987 // int imin = 0 ; // index of the median in the array
988 // //double eqmax = 0 ; // count of equal values
989 // // min cannot be greater than the number of element
990 // double min = n;
991 //
992 // for (i=0; i<n; i++)
993 // {
994 // if(weights[i]!=0)
995 // {
996 // if(infsup[i] < min)
997 // {
998 // min = infsup[i];
999 // imin = i ;
1000 // }
1001 // }
1002 // }
1003 //
1004 // // return the median
1005 // return(v[imin]);
1006 // }
1007 
1008 
1009 #undef vpITMAX
1010 #undef vpEPS
1011 #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:132
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:84
vpColVector simultMEstimator(vpColVector &residues)
Simult Mestimator.
Definition: vpRobust.cpp:343
static double sqr(double x)
Definition: vpMath.h:110
#define vpCDEBUG(level)
Definition: vpDebug.h:502
unsigned int getRows() const
Return the number of rows of the 2D array.
Definition: vpArray2D.h:152
vpRobust(unsigned int n_data)
Default Constructor.
Definition: vpRobust.cpp:68
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
void resize(unsigned int n_data)
Resize containers for sort methods.
Definition: vpRobust.cpp:84
vpRobustEstimatorType
Enumeration of influence functions.
Definition: vpRobust.h:64
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:217