38 #include <visp3/vision/vpHomography.h>
39 #include <visp3/core/vpColVector.h>
40 #include <visp3/core/vpRansac.h>
42 #include <visp3/core/vpImage.h>
43 #include <visp3/core/vpDisplay.h>
44 #include <visp3/core/vpMeterPixelConversion.h>
53 #ifndef DOXYGEN_SHOULD_SKIP_THIS
55 bool iscolinear(
double *x1,
double *x2,
double *x3);
59 iscolinear(
double *x1,
double *x2,
double *x3)
80 vpHomography::degenerateConfiguration(
vpColVector &x,
unsigned int *ind,
81 double threshold_area)
86 for (i=1 ; i < 4 ; i++)
88 if (ind[i]==ind[j])
return true ;
90 unsigned int n = x.
getRows()/4 ;
96 for(i = 0 ; i < 4 ; i++)
98 pb[i][0] = x[2*ind[i]] ;
99 pb[i][1] = x[2*ind[i]+1] ;
102 pa[i][0] = x[2*n+2*ind[i]] ;
103 pa[i][1] = x[2*n+2*ind[i]+1] ;
109 double area012 = (-pa[j][0]*pa[i][1] + pa[k][0]*pa[i][1] +
110 pa[i][0]*pa[j][1] - pa[k][0]*pa[j][1] +
111 -pa[i][0]*pa[k][1] + pa[1][j]*pa[k][1]);
114 double area013 = (-pa[j][0]*pa[i][1] + pa[k][0]*pa[i][1] +
115 pa[i][0]*pa[j][1] - pa[k][0]*pa[j][1] +
116 -pa[i][0]*pa[k][1] + pa[1][j]*pa[k][1]);
119 double area023 = (-pa[j][0]*pa[i][1] + pa[k][0]*pa[i][1] +
120 pa[i][0]*pa[j][1] - pa[k][0]*pa[j][1] +
121 -pa[i][0]*pa[k][1] + pa[1][j]*pa[k][1]);
124 double area123 = (-pa[j][0]*pa[i][1] + pa[k][0]*pa[i][1] +
125 pa[i][0]*pa[j][1] - pa[k][0]*pa[j][1] +
126 -pa[i][0]*pa[k][1] + pa[1][j]*pa[k][1]);
128 double sum_area = area012 + area013 + area023 + area123;
130 return ((sum_area < threshold_area) ||
131 (iscolinear(pa[0],pa[1],pa[2]) ||
132 iscolinear(pa[0],pa[1],pa[3]) ||
133 iscolinear(pa[0],pa[2],pa[3]) ||
134 iscolinear(pa[1],pa[2],pa[3]) ||
135 iscolinear(pb[0],pb[1],pb[2]) ||
136 iscolinear(pb[0],pb[1],pb[3]) ||
137 iscolinear(pb[0],pb[2],pb[3]) ||
138 iscolinear(pb[1],pb[2],pb[3])));
153 vpHomography::degenerateConfiguration(
vpColVector &x,
unsigned int *ind)
155 for (
unsigned int i = 1; i < 4 ; i++)
156 for (
unsigned int j = 0 ;j < i ; j++)
157 if (ind[i] == ind[j])
return true ;
159 unsigned int n = x.
getRows()/4;
162 unsigned int n2 = 2 * n;
163 for(
unsigned int i = 0; i < 4 ;i++)
165 unsigned int ind2 = 2 * ind[i];
167 pb[i][1] = x[ind2+1];
170 pa[i][0] = x[n2+ind2] ;
171 pa[i][1] = x[n2+ind2+1] ;
174 return ( iscolinear(pa[0],pa[1],pa[2]) ||
175 iscolinear(pa[0],pa[1],pa[3]) ||
176 iscolinear(pa[0],pa[2],pa[3]) ||
177 iscolinear(pa[1],pa[2],pa[3]) ||
178 iscolinear(pb[0],pb[1],pb[2]) ||
179 iscolinear(pb[0],pb[1],pb[3]) ||
180 iscolinear(pb[0],pb[2],pb[3]) ||
181 iscolinear(pb[1],pb[2],pb[3]));
184 vpHomography::degenerateConfiguration(
const std::vector<double> &xb,
const std::vector<double> &yb,
185 const std::vector<double> &xa,
const std::vector<double> &ya)
187 unsigned int n = (
unsigned int)xb.
size();
191 std::vector<vpColVector> pa(n), pb(n);
192 for (
unsigned i=0; i<n;i++) {
203 for (
unsigned int i = 0; i < n-2; i++) {
204 for (
unsigned int j = i+1; j < n-1; j++) {
205 for (
unsigned int k = j+1; k < n ; k++)
207 if (isColinear(pa[i], pa[j], pa[k])) {
210 if (isColinear(pb[i], pb[j], pb[k])){
222 unsigned int n = x.
getRows()/4 ;
223 std::vector<double> xa(4), xb(4);
224 std::vector<double> ya(4), yb(4);
225 unsigned int n2 = n * 2;
226 for(
unsigned int i=0 ; i < 4 ; i++)
228 unsigned int ind2 = 2 * ind[i];
233 ya[i] = x[n2+ind2+1] ;
246 for (
unsigned int i=0 ; i <9 ; i++)
258 unsigned int n = x.
getRows()/4 ;
259 unsigned int n2 = n * 2;
266 for(
unsigned int i=0 ; i < n ; i++)
268 unsigned int i2 = 2 * i;
275 pa[i][0] = x[n2+i2] ;
276 pa[i][1] = x[n2+i2+1] ;
282 for (
unsigned int i=0 ; i <9 ; i++)
292 for (
unsigned int i=0 ; i <n ; i++)
296 d[i] = sqrt((pa[i] - Hpb ).sumSquare()) ;
304 #endif //#ifndef DOXYGEN_SHOULD_SKIP_THIS
308 vpHomography::initRansac(
unsigned int n,
309 double *xb,
double *yb,
310 double *xa,
double *ya,
314 unsigned int n2 = n * 2;
315 for (
unsigned int i=0 ; i < n ; i++)
317 unsigned int i2 = 2 * i;
352 const std::vector<double> &xa,
const std::vector<double> &ya,
354 std::vector<bool> &inliers,
356 unsigned int nbInliersConsensus,
360 unsigned int n = (
unsigned int)xb.size();
361 if (yb.size() != n || xa.size() != n || ya.size() != n)
363 "Bad dimension for robust homography estimation"));
369 vpUniRand random((
const long)time(NULL)) ;
371 std::vector<unsigned int> best_consensus;
372 std::vector<unsigned int> cur_consensus;
373 std::vector<unsigned int> cur_outliers;
374 std::vector<unsigned int> cur_randoms;
376 std::vector<unsigned int> rand_ind;
378 unsigned int nbMinRandom = 4 ;
379 unsigned int ransacMaxTrials = 1000;
380 unsigned int maxDegenerateIter = 1000;
382 unsigned int nbTrials = 0;
383 unsigned int nbDegenerateIter = 0;
384 unsigned int nbInliers = 0;
386 bool foundSolution =
false;
388 std::vector<double> xa_rand(nbMinRandom);
389 std::vector<double> ya_rand(nbMinRandom);
390 std::vector<double> xb_rand(nbMinRandom);
391 std::vector<double> yb_rand(nbMinRandom);
393 if (inliers.size() != n)
396 while (nbTrials < ransacMaxTrials && nbInliers < nbInliersConsensus)
398 cur_outliers.clear();
401 bool degenerate =
true;
402 while(degenerate ==
true){
403 std::vector<bool> usedPt(n,
false);
406 for(
unsigned int i = 0; i < nbMinRandom; i++)
409 unsigned int r = (
unsigned int)ceil(random()*n) -1;
411 r = (
unsigned int)ceil(random()*n) -1;
414 rand_ind.push_back(r);
423 if (! vpHomography::degenerateConfiguration(xb_rand, yb_rand, xa_rand, ya_rand)) {
434 if (nbDegenerateIter > maxDegenerateIter){
445 for (
unsigned int i=0 ; i < nbMinRandom ; i++) {
446 a[0] = xa_rand[i] ; a[1] = ya_rand[i] ; a[2] = 1 ;
447 b[0] = xb_rand[i] ; b[1] = yb_rand[i] ; b[2] = 1 ;
449 c = aHb*b; c /= c[2] ;
450 r += (a-c).sumSquare() ;
455 r = sqrt(r/nbMinRandom);
459 unsigned int nbInliersCur = 0;
460 for (
unsigned int i = 0; i < n ; i++)
462 a[0] = xa[i] ; a[1] = ya[i] ; a[2] = 1 ;
463 b[0] = xb[i] ; b[1] = yb[i] ; b[2] = 1 ;
465 c = aHb*b ; c /= c[2] ;
466 double error = sqrt((a-c).sumSquare()) ;
467 if(error <= threshold){
469 cur_consensus.push_back(i);
473 cur_outliers.push_back(i);
478 if(nbInliersCur > nbInliers)
480 foundSolution =
true;
481 best_consensus = cur_consensus;
482 nbInliers = nbInliersCur;
485 cur_consensus.clear();
489 if(nbTrials >= ransacMaxTrials){
490 vpERROR_TRACE(
"Ransac reached the maximum number of trials");
491 foundSolution =
true;
496 if(nbInliers >= nbInliersConsensus)
498 std::vector<double> xa_best(best_consensus.size());
499 std::vector<double> ya_best(best_consensus.size());
500 std::vector<double> xb_best(best_consensus.size());
501 std::vector<double> yb_best(best_consensus.size());
503 for(
unsigned i = 0 ; i < best_consensus.size(); i++)
505 xa_best[i] = xa[best_consensus[i]];
506 ya_best[i] = ya[best_consensus[i]];
507 xb_best[i] = xb[best_consensus[i]];
508 yb_best[i] = yb[best_consensus[i]];
516 for (
unsigned int i=0 ; i < best_consensus.size() ; i++) {
517 a[0] = xa_best[i] ; a[1] = ya_best[i] ; a[2] = 1 ;
518 b[0] = xb_best[i] ; b[1] = yb_best[i] ; b[2] = 1 ;
520 c = aHb*b ; c /= c[2] ;
521 residual += (a-c).sumSquare() ;
524 residual = sqrt(residual/best_consensus.size());
Implementation of a matrix and operations on matrices.
static vpColVector cross(const vpColVector &a, const vpColVector &b)
error that can be emited by ViSP classes.
Type * data
Address of the first element of the data array.
unsigned int size() const
Return the number of elements of the 2D array.
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)
Implementation of an homography and operations on homographies.
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)
unsigned int getRows() const
Return the number of rows of the 2D array.
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)
Implementation of column vector and the associated operations.
Class for generating random numbers with uniform probability density.
void resize(const unsigned int i, const bool flagNullify=true)