19 #include <visp/vpHomography.h>
20 #include <visp/vpColVector.h>
21 #include <visp/vpRansac.h>
23 #include <visp/vpImage.h>
24 #include <visp/vpDisplay.h>
25 #include <visp/vpMeterPixelConversion.h>
34 #ifndef DOXYGEN_SHOULD_SKIP_THIS
36 bool iscolinear(
double *x1,
double *x2,
double *x3);
40 iscolinear(
double *x1,
double *x2,
double *x3)
61 vpHomography::degenerateConfiguration(
vpColVector &x,
unsigned int *ind,
62 double threshold_area)
67 for (i=1 ; i < 4 ; i++)
69 if (ind[i]==ind[j])
return true ;
71 unsigned int n = x.
getRows()/4 ;
77 for(i = 0 ; i < 4 ; i++)
79 pb[i][0] = x[2*ind[i]] ;
80 pb[i][1] = x[2*ind[i]+1] ;
83 pa[i][0] = x[2*n+2*ind[i]] ;
84 pa[i][1] = x[2*n+2*ind[i]+1] ;
90 double area012 = (-pa[j][0]*pa[i][1] + pa[k][0]*pa[i][1] +
91 pa[i][0]*pa[j][1] - pa[k][0]*pa[j][1] +
92 -pa[i][0]*pa[k][1] + pa[1][j]*pa[k][1]);
95 double area013 = (-pa[j][0]*pa[i][1] + pa[k][0]*pa[i][1] +
96 pa[i][0]*pa[j][1] - pa[k][0]*pa[j][1] +
97 -pa[i][0]*pa[k][1] + pa[1][j]*pa[k][1]);
100 double area023 = (-pa[j][0]*pa[i][1] + pa[k][0]*pa[i][1] +
101 pa[i][0]*pa[j][1] - pa[k][0]*pa[j][1] +
102 -pa[i][0]*pa[k][1] + pa[1][j]*pa[k][1]);
105 double area123 = (-pa[j][0]*pa[i][1] + pa[k][0]*pa[i][1] +
106 pa[i][0]*pa[j][1] - pa[k][0]*pa[j][1] +
107 -pa[i][0]*pa[k][1] + pa[1][j]*pa[k][1]);
109 double sum_area = area012 + area013 + area023 + area123;
111 return ((sum_area < threshold_area) ||
112 (iscolinear(pa[0],pa[1],pa[2]) ||
113 iscolinear(pa[0],pa[1],pa[3]) ||
114 iscolinear(pa[0],pa[2],pa[3]) ||
115 iscolinear(pa[1],pa[2],pa[3]) ||
116 iscolinear(pb[0],pb[1],pb[2]) ||
117 iscolinear(pb[0],pb[1],pb[3]) ||
118 iscolinear(pb[0],pb[2],pb[3]) ||
119 iscolinear(pb[1],pb[2],pb[3])));
134 vpHomography::degenerateConfiguration(
vpColVector &x,
unsigned int *ind)
136 for (
unsigned int i = 1; i < 4 ; i++)
137 for (
unsigned int j = 0 ;j < i ; j++)
138 if (ind[i] == ind[j])
return true ;
140 unsigned int n = x.
getRows()/4;
143 unsigned int n2 = 2 * n;
145 for(
unsigned int i = 0; i < 4 ;i++)
149 pb[i][1] = x[ind2+1];
152 pa[i][0] = x[n2+ind2] ;
153 pa[i][1] = x[n2+ind2+1] ;
156 return ( iscolinear(pa[0],pa[1],pa[2]) ||
157 iscolinear(pa[0],pa[1],pa[3]) ||
158 iscolinear(pa[0],pa[2],pa[3]) ||
159 iscolinear(pa[1],pa[2],pa[3]) ||
160 iscolinear(pb[0],pb[1],pb[2]) ||
161 iscolinear(pb[0],pb[1],pb[3]) ||
162 iscolinear(pb[0],pb[2],pb[3]) ||
163 iscolinear(pb[1],pb[2],pb[3]));
166 vpHomography::degenerateConfiguration(
const std::vector<double> &xb,
const std::vector<double> &yb,
167 const std::vector<double> &xa,
const std::vector<double> &ya)
169 unsigned int n = (
unsigned int)xb.
size();
173 std::vector<vpColVector> pa(n), pb(n);
174 for (
unsigned i=0; i<n;i++) {
185 for (
unsigned int i = 0; i < n-2; i++) {
186 for (
unsigned int j = i+1; j < n-1; j++) {
187 for (
unsigned int k = j+1; k < n ; k++)
189 if (isColinear(pa[i], pa[j], pa[k])) {
192 if (isColinear(pb[i], pb[j], pb[k])){
205 unsigned int n = x.
getRows()/4 ;
206 std::vector<double> xa(4), xb(4);
207 std::vector<double> ya(4), yb(4);
208 unsigned int n2 = n * 2;
210 for(i=0 ; i < 4 ; i++)
217 ya[i] = x[n2+ind2+1] ;
230 for (i=0 ; i <9 ; i++)
243 unsigned int n = x.
getRows()/4 ;
244 unsigned int n2 = n * 2;
252 for( i=0 ; i < n ; i++)
261 pa[i][0] = x[n2+i2] ;
262 pa[i][1] = x[n2+i2+1] ;
268 for (i=0 ; i <9 ; i++)
278 for (i=0 ; i <n ; i++)
282 d[i] = sqrt((pa[i] - Hpb ).sumSquare()) ;
290 #endif //#ifndef DOXYGEN_SHOULD_SKIP_THIS
294 vpHomography::initRansac(
unsigned int n,
295 double *xb,
double *yb,
296 double *xa,
double *ya,
300 unsigned int n2 = n * 2;
302 for (
unsigned int i=0 ; i < n ; i++)
312 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
320 double *xb,
double *yb,
321 double *xa,
double *ya ,
328 vpHomography::initRansac(n, xb, yb, xa, ya, x) ;
338 for (
unsigned int i = 0 ;i < 9 ;i++)
380 double *xb,
double *yb,
381 double *xa,
double *ya ,
387 double areaThreshold)
390 vpHomography::initRansac(n, xb, yb, xa, ya, x);
399 for (
unsigned int i = 0 ;i < 9 ;i++)
407 #endif //#ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
436 const std::vector<double> &xa,
const std::vector<double> &ya,
438 std::vector<bool> &inliers,
440 unsigned int nbInliersConsensus,
444 unsigned int n = (
unsigned int)xb.size();
445 if (yb.size() != n || xa.size() != n || ya.size() != n)
447 "Bad dimension for robust homography estimation"));
453 vpUniRand random((
const long)time(NULL)) ;
455 std::vector<unsigned int> best_consensus;
456 std::vector<unsigned int> cur_consensus;
457 std::vector<unsigned int> cur_outliers;
458 std::vector<unsigned int> cur_randoms;
460 std::vector<unsigned int> rand_ind;
462 unsigned int nbMinRandom = 4 ;
463 unsigned int ransacMaxTrials = 1000;
464 unsigned int maxDegenerateIter = 1000;
466 unsigned int nbTrials = 0;
467 unsigned int nbDegenerateIter = 0;
468 unsigned int nbInliers = 0;
470 bool foundSolution =
false;
472 std::vector<double> xa_rand(nbMinRandom);
473 std::vector<double> ya_rand(nbMinRandom);
474 std::vector<double> xb_rand(nbMinRandom);
475 std::vector<double> yb_rand(nbMinRandom);
477 if (inliers.size() != n)
480 while (nbTrials < ransacMaxTrials && nbInliers < nbInliersConsensus)
482 cur_outliers.clear();
485 bool degenerate =
true;
486 while(degenerate ==
true){
487 std::vector<bool> usedPt(n,
false);
490 for(
unsigned int i = 0; i < nbMinRandom; i++)
493 unsigned int r = (
unsigned int)ceil(random()*n) -1;
495 r = (
unsigned int)ceil(random()*n) -1;
498 rand_ind.push_back(r);
507 if (! vpHomography::degenerateConfiguration(xb_rand, yb_rand, xa_rand, ya_rand)) {
518 if (nbDegenerateIter > maxDegenerateIter){
529 for (
unsigned int i=0 ; i < nbMinRandom ; i++) {
530 a[0] = xa_rand[i] ; a[1] = ya_rand[i] ; a[2] = 1 ;
531 b[0] = xb_rand[i] ; b[1] = yb_rand[i] ; b[2] = 1 ;
533 c = aHb*b; c /= c[2] ;
534 r += (a-c).sumSquare() ;
539 r = sqrt(r/nbMinRandom);
543 unsigned int nbInliersCur = 0;
544 for (
unsigned int i = 0; i < n ; i++)
546 a[0] = xa[i] ; a[1] = ya[i] ; a[2] = 1 ;
547 b[0] = xb[i] ; b[1] = yb[i] ; b[2] = 1 ;
549 c = aHb*b ; c /= c[2] ;
550 double error = sqrt((a-c).sumSquare()) ;
551 if(error <= threshold){
553 cur_consensus.push_back(i);
557 cur_outliers.push_back(i);
562 if(nbInliersCur > nbInliers)
564 foundSolution =
true;
565 best_consensus = cur_consensus;
566 nbInliers = nbInliersCur;
569 cur_consensus.clear();
573 if(nbTrials >= ransacMaxTrials){
574 vpERROR_TRACE(
"Ransac reached the maximum number of trials");
575 foundSolution =
true;
580 if(nbInliers >= nbInliersConsensus)
582 std::vector<double> xa_best(best_consensus.size());
583 std::vector<double> ya_best(best_consensus.size());
584 std::vector<double> xb_best(best_consensus.size());
585 std::vector<double> yb_best(best_consensus.size());
587 for(
unsigned i = 0 ; i < best_consensus.size(); i++)
589 xa_best[i] = xa[best_consensus[i]];
590 ya_best[i] = ya[best_consensus[i]];
591 xb_best[i] = xb[best_consensus[i]];
592 yb_best[i] = yb[best_consensus[i]];
600 for (
unsigned int i=0 ; i < best_consensus.size() ; i++) {
601 a[0] = xa_best[i] ; a[1] = ya_best[i] ; a[2] = 1 ;
602 b[0] = xb_best[i] ; b[1] = yb_best[i] ; b[2] = 1 ;
604 c = aHb*b ; c /= c[2] ;
605 residual += (a-c).sumSquare() ;
608 residual = sqrt(residual/best_consensus.size());
Definition of the vpMatrix class.
static vpColVector cross(const vpColVector &a, const vpColVector &b)
error that can be emited by ViSP classes.
static void HLM(const std::vector< double > &xb, const std::vector< double > &yb, const std::vector< double > &xa, const std::vector< double > &ya, bool isplanar, vpHomography &aHb)
unsigned int size() const
This class aims to compute the homography wrt.two images.
static bool ransac(const std::vector< double > &xb, const std::vector< double > &yb, const std::vector< double > &xa, const std::vector< double > &ya, vpHomography &aHb, std::vector< bool > &inliers, double &residual, unsigned int nbInliersConsensus, double threshold, bool normalization=true)
static void DLT(const std::vector< double > &xb, const std::vector< double > &yb, const std::vector< double > &xa, const std::vector< double > &ya, vpHomography &aHb, bool normalization=true)
Class that provides a data structure for the column vectors as well as a set of operations on these v...
static bool ransac(unsigned int npts, vpColVector &x, unsigned int s, double t, vpColVector &model, vpColVector &inliers, int consensus=1000, double areaThreshold=0.0, const int maxNbumbersOfTrials=10000)
RANSAC - Robustly fits a model to data with the RANSAC algorithm.
Class for generating random numbers with uniform probability density.
unsigned int getRows() const
Return the number of rows of the matrix.
void resize(const unsigned int i, const bool flagNullify=true)