46 #include <visp3/core/vpDebug.h>
47 #include <visp3/core/vpColVector.h>
48 #include <visp3/core/vpMath.h>
50 #include <visp3/core/vpRobust.h>
69 : normres(), sorted_normres(), sorted_residues(), NoiseThreshold(0.0017), sig_prev(0), it(0), swap(0), size(n_data)
71 vpCDEBUG(2) <<
"vpRobust constructor reached" << std::endl;
74 sorted_normres.
resize(n_data);
75 sorted_residues.
resize(n_data);
83 : normres(), sorted_normres(), sorted_residues(), NoiseThreshold(0.0017), sig_prev(0), it(0), swap(0), size(0)
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;
111 #ifdef VISP_HAVE_CPP11_COMPATIBILITY
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);
138 sorted_normres.
resize(n_data);
139 sorted_residues.
resize(n_data);
192 unsigned int n_data = residues.
getRows();
195 sorted_residues = residues;
197 unsigned int ind_med = (
unsigned int)(ceil(n_data/2.0))-1;
200 med = select(sorted_residues, 0, (
int)n_data-1, (
int)ind_med);
204 for(
unsigned int i=0; i<n_data; i++)
206 normres[i] = (fabs(residues[i]- med));
207 sorted_normres[i] = (fabs(sorted_residues[i]- med));
212 normmedian = select(sorted_normres, 0, (
int)n_data-1, (
int)ind_med);
215 sigma = 1.4826*normmedian;
219 if(sigma < NoiseThreshold)
221 sigma= NoiseThreshold;
228 psiTukey(sigma, normres,weights);
230 vpCDEBUG(2) <<
"Tukey's function computed" << std::endl;
236 psiCauchy(sigma, normres,weights);
246 psiHuber(sigma, normres,weights);
264 unsigned int n_all_data = all_residues.
getRows();
268 normmedian = computeNormalizedMedian(all_normres,residues,all_residues,weights);
272 sigma = 1.4826*normmedian;
276 if(sigma < NoiseThreshold)
278 sigma= NoiseThreshold;
286 psiTukey(sigma, all_normres,weights);
288 vpCDEBUG(2) <<
"Tukey's function computed" << std::endl;
294 psiCauchy(sigma, all_normres,weights);
304 psiHuber(sigma, all_normres,weights);
314 double vpRobust::computeNormalizedMedian(
vpColVector &all_normres,
323 unsigned int n_all_data = all_residues.
getRows();
324 unsigned int n_data = residues.
getRows();
329 sorted_residues = residues;
331 no_null_weight_residues.
resize(n_data);
339 unsigned int index =0;
340 for(
unsigned int j=0;j<n_data;j++)
343 if(std::fabs(weights[j]) > std::numeric_limits<double>::epsilon())
345 no_null_weight_residues[index]=residues[j];
349 sorted_residues.
resize(index);
350 memcpy(sorted_residues.
data,no_null_weight_residues.
data,index*
sizeof(
double));
353 vpCDEBUG(2) <<
"vpRobust MEstimator reached. No. data = " << n_data
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);
365 for(i=0; i<n_all_data; i++)
367 all_normres[i] = (fabs(all_residues[i]- med));
370 for(i=0; i<n_data; i++)
372 sorted_normres[i] = (fabs(sorted_residues[i]- med));
378 normmedian = select(sorted_normres, 0, (
int)n_data-1, (
int)ind_med);
399 unsigned int n_data = residues.
getRows();
403 vpCDEBUG(2) <<
"vpRobust MEstimator reached. No. data = " << n_data
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);
411 for(
unsigned int i=0; i<n_data; i++)
412 norm_res[i] = (fabs(residues[i]- med));
419 double normmedian = select(norm_res, 0, (
int)n_data-1, (
int)ind_med);
421 sigma = 1.4826*normmedian;
426 sigma = simultscale(residues);
431 if(sigma < NoiseThreshold)
433 sigma= NoiseThreshold;
436 vpCDEBUG(2) <<
"MAD and C computed" << std::endl;
438 psiHuber(sigma, norm_res,w);
446 vpRobust::scale(vpRobustEstimatorType method,
vpColVector &x)
451 double Expectation=0;
454 for(
unsigned int i=0; i<n; i++)
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);
462 Expectation += chiTmp*(1-erf(chiTmp));
468 #if VP_DEBUG_MODE == 3
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;
475 std::cout <<
"erf = " << (1-erf(chiTmp)) << std::endl;
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;
485 std::cout <<
"Expectation = " << chiTmp*(1-erf(chiTmp)) << std::endl;
494 sigma2 = Sum_chi*
vpMath::sqr(sig_prev)/((n-p)*Expectation);
497 #if VP_DEBUG_MODE == 3
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;
507 return sqrt(fabs(sigma2));
518 double Expectation=0;
521 for(
unsigned int i=0; i<n; i++)
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);
530 Expectation += chiTmp*(1-erf(chiTmp));
535 #if VP_DEBUG_MODE == 3
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;
542 std::cout <<
"erf = " << (1-erf(chiTmp)) << std::endl;
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;
552 std::cout <<
"Expectation = " << chiTmp*(1-erf(chiTmp)) << std::endl;
561 sigma2 = Sum_chi*
vpMath::sqr(sig_prev)/((n-p)*Expectation);
564 #if VP_DEBUG_MODE == 3
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;
574 return sqrt(fabs(sigma2));
579 vpRobust::constrainedChi(vpRobustEstimatorType method,
double x)
584 return constrainedChiTukey(x);
586 return constrainedChiCauchy(x);
588 return constrainedChiHuber(x);
597 vpRobust::constrainedChiTukey(
double x)
603 if(fabs(x) <= 4.7*sig_prev)
617 vpRobust::constrainedChiCauchy(
double x)
630 vpRobust::constrainedChiHuber(
double x)
633 double u = x/sig_prev;
645 vpRobust::simult_chi_huber(
double x)
648 double u = x/sig_prev;
676 unsigned int n_data = x.
getRows();
677 double cst_const = vpCST*4.6851;
679 for(
unsigned int i=0; i<n_data; i++)
682 if(std::fabs(sig) <= std::numeric_limits<double>::epsilon() && std::fabs(weights[i]) > std::numeric_limits<double>::epsilon())
688 double xi_sig = x[i]/sig;
691 if((std::fabs(xi_sig)<=(cst_const)) && std::fabs(weights[i]) > std::numeric_limits<double>::epsilon())
714 unsigned int n_data = x.
getRows();
716 for(
unsigned int i=0; i<n_data; i++)
719 if(std::fabs(weights[i]) > std::numeric_limits<double>::epsilon())
721 double xi_sig = x[i]/sig;
725 weights[i] = c/fabs(xi_sig);
740 unsigned int n_data = x.
getRows();
741 double const_sig = 2.3849*sig;
744 for(
unsigned int i=0; i<n_data; i++)
773 unsigned int n_data = r.
getRows();
776 for(
unsigned int i=0; i<n_data; i++)
808 double v = a[(
unsigned int)r];
812 while (a[(
unsigned int)++i] < v) ;
813 while (v < a[(
unsigned int)--j])
if (j == l)
break;
815 exch(a[(
unsigned int)i], a[(
unsigned int)j]);
817 exch(a[(
unsigned int)i], a[(
unsigned int)r]);
829 vpRobust::select(
vpColVector &a,
int l,
int r,
int k)
833 int i = partition(a, l, r);
837 return a[(
unsigned int)k];
841 #if !defined(VISP_HAVE_FUNC_ERFC) && !defined(VISP_HAVE_FUNC_STD_ERFC)
843 vpRobust::erf(
double x)
845 return x < 0.0 ? -gammp(0.5,x*x) : gammp(0.5,x*x);
849 vpRobust::gammp(
double a,
double x)
851 double gamser=0.,gammcf=0.,gln;
853 if (x < 0.0 || a <= 0.0)
854 std::cout <<
"Invalid arguments in routine GAMMP";
857 gser(&gamser,a,x,&gln);
862 gcf(&gammcf,a,x,&gln);
868 vpRobust::gser(
double *gamser,
double a,
double x,
double *gln)
874 std::cout <<
"x less than 0 in routine GSER";
883 for (
int n=1; n<=vpITMAX; n++)
888 if (fabs(del) < fabs(sum)*vpEPS)
890 *gamser=sum*exp(-x+a*log(x)-(*gln));
894 std::cout <<
"a too large, vpITMAX too small in routine GSER";
900 vpRobust::gcf(
double *gammcf,
double a,
double x,
double *gln)
902 double gold=0.0,g,fac=1.0,b1=1.0;
903 double b0=0.0,a1,a0=1.0;
907 for (
int n=1; n<=vpITMAX; n++)
909 double an=(double) n;
917 if (std::fabs(a1) > std::numeric_limits<double>::epsilon())
921 if (fabs((g-gold)/g) < vpEPS)
923 *gammcf=exp(-x+a*log(x)-(*gln))*g;
929 std::cout <<
"a too large, vpITMAX too small in routine GCF";
933 vpRobust::gammln(
double xx)
936 static double cof[6]={76.18009173,-86.50532033,24.01409822,
937 -1.231739516,0.120858003e-2,-0.536382e-5};
941 tmp -= (x+0.5)*log(tmp);
943 for (
int j=0; j<=5; j++)
948 return -tmp+log(2.50662827465*ser);
void MEstimator(const vpRobustEstimatorType method, const vpColVector &residues, vpColVector &weights)
Compute the weights according a residue vector and a PsiFunction.
Type * data
Address of the first element of the data array.
vpColVector simultMEstimator(vpColVector &residues)
Simult Mestimator.
static double sqr(double x)
vpRobust & operator=(const vpRobust &other)
unsigned int getRows() const
Return the number of rows of the 2D array.
Implementation of column vector and the associated operations.
Contains an M-Estimator and various influence function.
void resize(unsigned int n_data)
Resize containers for sort methods.
vpRobustEstimatorType
Enumeration of influence functions.
void resize(const unsigned int i, const bool flagNullify=true)