Visual Servoing Platform  version 3.0.0
vpHomographyExtract.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  * Homography transformation.
32  *
33  * Authors:
34  * Eric Marchand
35  *
36  *****************************************************************************/
37 
38 #include <visp3/vision/vpHomography.h>
39 #include <visp3/core/vpMath.h>
40 #include <math.h>
41 
42 //#define DEBUG_Homographie 0
43 
44 /* ---------------------------------------------------------------------- */
45 /* --- STATIC ------------------------------------------------------------ */
46 /* ------------------------------------------------------------------------ */
47 const double vpHomography::sing_threshold = 0.0001;
48 
62  vpColVector &n)
63 {
64 
65 
66  vpColVector nd(3) ;
67  nd[0]=0;nd[1]=0;nd[2]=1;
68 
69  computeDisplacement(*this,aRb,atb,n);
70 
71 }
72 
94  vpRotationMatrix &aRb,
96  vpColVector &n)
97 {
98  computeDisplacement(*this,nd, aRb,atb,n);
99 }
100 
101 #ifndef DOXYGEN_SHOULD_SKIP_THIS
102 
125 void
127  const vpColVector &nd,
128  vpRotationMatrix &aRb,
129  vpTranslationVector &atb,
130  vpColVector &n)
131 {
132  /**** Declarations des variables ****/
133 
134  vpMatrix aRbint(3,3) ;
135  vpColVector svTemp(3), sv(3);
136  vpMatrix mX(3,2) ;
137  vpColVector aTbp(3), normaleEstimee(3);
138  double distanceFictive;
139  double sinusTheta, cosinusTheta, signeSinus= 1;
140  double cosinusDesireeEstimee, cosinusAncien;
141  double s, determinantU, determinantV;
142  unsigned int i, j, k, w;
143  unsigned int vOrdre[3];
144 
145  //vpColVector normaleDesiree(3) ;
146  //normaleDesiree[0]=0;normaleDesiree[1]=0;normaleDesiree[2]=1;
147  vpColVector normaleDesiree(nd);
148 
149  /**** Corps de la focntion ****/
150 #ifdef DEBUG_Homographie
151  printf ("debut : Homographie_EstimationDeplacementCamera\n");
152 #endif
153 
154  /* Allocation des matrices */
155  vpMatrix mTempU(3,3) ;
156  vpMatrix mTempV(3,3) ;
157  vpMatrix mU(3,3) ;
158  vpMatrix mV(3,3) ;
159  vpMatrix aRbp(3,3) ;
160 
161 
162  vpMatrix mH(3,3) ;
163  for (i=0 ; i < 3 ; i++)
164  for (j=0 ; j < 3 ; j++) mH[i][j] = aHb[i][j];
165 
166  /* Preparation au calcul de la SVD */
167  mTempU = mH ;
168 
169  /*****
170  Remarque : mTempU, svTemp et mTempV sont modifies par svd
171  Il est necessaire apres de les trier dans l'ordre decroissant
172  des valeurs singulieres
173  *****/
174  mTempU.svd(svTemp,mTempV) ;
175 
176  /* On va mettre les valeurs singulieres en ordre decroissant : */
177 
178  /* Determination de l'ordre des valeurs */
179  if (svTemp[0] >= svTemp[1]) {
180  if (svTemp[0] >= svTemp[2]) {
181  if (svTemp[1] > svTemp[2]) {
182  vOrdre[0] = 0; vOrdre[1] = 1; vOrdre[2] = 2;
183  } else {
184  vOrdre[0] = 0; vOrdre[1] = 2; vOrdre[2] = 1;
185  }
186  } else {
187  vOrdre[0] = 2; vOrdre[1] = 0; vOrdre[2] = 1;
188  }
189  } else {
190  if (svTemp[1] >= svTemp[2]){
191  if (svTemp[0] > svTemp[2])
192  { vOrdre[0] = 1; vOrdre[1] = 0; vOrdre[2] = 2; }
193  else
194  { vOrdre[0] = 1; vOrdre[1] = 2; vOrdre[2] = 0; }
195  } else {
196  vOrdre[0] = 2; vOrdre[1] = 1; vOrdre[2] = 0;
197  }
198  }
199  /*****
200  Tri decroissant des matrices U, V, sv
201  en fonction des valeurs singulieres car
202  hypothese : sv[0]>=sv[1]>=sv[2]>=0
203  *****/
204 
205 
206  for (i = 0; i < 3; i++) {
207  sv[i] = svTemp[vOrdre[i]];
208  for (j = 0; j < 3; j++) {
209  mU[i][j] = mTempU[i][vOrdre[j]];
210  mV[i][j] = mTempV[i][vOrdre[j]];
211  }
212  }
213 
214 #ifdef DEBUG_Homographie
215  printf("U : \n") ; std::cout << mU << std::endl ;
216  printf("V : \n") ; std::cout << mV << std::endl ;
217  printf("Valeurs singulieres : ") ; std::cout << sv.t() ;
218 #endif
219 
220  /* A verifier si necessaire!!! */
221  determinantV = mV.det();
222  determinantU = mU.det();
223 
224  s = determinantU * determinantV;
225 
226 #ifdef DEBUG_Homographie
227  printf ("s = det(U) * det(V) = %f * %f = %f\n",determinantU,determinantV,s);
228 #endif
229  if (s < 0) mV *=-1 ;
230 
231 
232  /* d' = d2 */
233  distanceFictive = sv[1];
234 #ifdef DEBUG_Homographie
235  printf ("d = %f\n",distanceFictive);
236 #endif
237  n.resize(3) ;
238 
239  if (((sv[0] - sv[1]) < sing_threshold) && (sv[0] - sv[2]) < sing_threshold)
240  {
241  //#ifdef DEBUG_Homographie
242  // printf ("\nPure rotation\n");
243  //#endif
244  /*****
245  Cas ou le deplacement est une rotation pure
246  et la normale reste indefini
247  sv[0] = sv[1]= sv[2]
248  *****/
249  aTbp[0] = 0;
250  aTbp[1] = 0;
251  aTbp[2] = 0;
252 
253  n[0] = normaleDesiree[0];
254  n[1] = normaleDesiree[1];
255  n[2] = normaleDesiree[2];
256  }
257  else
258  {
259 #ifdef DEBUG_Homographie
260  printf("\nCas general\n");
261 #endif
262  /* Cas general */
263 
264  /*****
265  test pour determiner quelle est la bonne solution on teste
266  d'abord quelle solution est plus proche de la perpendiculaire
267  au plan de la cible constuction de la normale n
268  *****/
269 
270  /*****
271  Calcul de la normale au plan : n' = [ esp1*x1 , x2=0 , esp3*x3 ]
272  dans l'ordre : cas (esp1=+1, esp3=+1) et (esp1=-1, esp3=+1)
273  *****/
274  mX[0][0] = sqrt ((sv[0] * sv[0] - sv[1] * sv[1])
275  / (sv[0] * sv[0] - sv[2] * sv[2]));
276  mX[1][0] = 0.0;
277  mX[2][0] = sqrt ((sv[1] * sv[1] - sv[2] * sv[2])
278  / (sv[0] * sv[0] - sv[2] * sv[2]));
279 
280  mX[0][1] = -mX[0][0];
281  mX[1][1] = mX[1][0];
282  mX[2][1] = mX[2][0];
283 
284  /* Il y a 4 solutions pour n : 2 par cas => n1, -n1, n2, -n2 */
285  cosinusAncien = 0.0;
286  for (w = 0; w < 2; w++) { /* Pour les 2 cas */
287  for (k = 0; k < 2; k++) { /* Pour le signe */
288 
289  /* Calcul de la normale estimee : n = V.n' */
290  for (i = 0; i < 3; i++) {
291  normaleEstimee[i] = 0.0;
292  for (j = 0; j < 3; j++) {
293  normaleEstimee[i] += (2.0 * k - 1.0) * mV[i][j] * mX[j][w];
294  }
295  }
296 
297 
298  /* Calcul du cosinus de l'angle entre la normale reelle et desire */
299  cosinusDesireeEstimee = 0.0;
300  for (i = 0; i < 3; i++)
301  cosinusDesireeEstimee += normaleEstimee[i] * normaleDesiree[i];
302 
303  /*****
304  Si la solution est meilleur
305  Remarque : On ne teste pas le cas oppose (cos<0)
306  *****/
307  if (cosinusDesireeEstimee > cosinusAncien)
308  {
309  cosinusAncien = cosinusDesireeEstimee;
310 
311  /* Affectation de la normale qui est retourner */
312  for (j = 0; j < 3; j++)
313  n[j] = normaleEstimee[j];
314 
315  /* Construction du vecteur t'= +/- (d1-d3).[x1, 0, -x3] */
316  aTbp[0] = (2.0 * k - 1.0) * (sv[0] - sv[2]) * mX[0][w];
317  aTbp[1] = (2.0 * k - 1.0) * (sv[0] - sv[2]) * mX[1][w];
318  aTbp[2] = -(2.0 * k - 1.0) * (sv[0] - sv[2]) * mX[2][w];
319 
320  /* si c'est la deuxieme solution */
321  if (w == 1)
322  signeSinus = -1; /* car esp1*esp3 = -1 */
323  else
324  signeSinus = 1;
325  } /* fin if (cosinusDesireeEstimee > cosinusAncien) */
326  } /* fin k */
327  } /* fin w */
328  } /* fin else */
329 
330 
331  /* Calcul du vecteur de translation qui est retourner : t = (U * t') / d */
332  for (i = 0; i < 3; i++) {
333  atb[i] = 0.0;
334  for (j = 0; j < 3; j++) {
335  atb[i] += mU[i][j] * aTbp[j];
336  }
337  atb[i] /= distanceFictive;
338  }
339 
340 
341 #ifdef DEBUG_Homographie
342  printf("t' : ") ; std::cout << aTbp.t() ;
343  printf("t/d : ") ; std::cout << atb.t() ;
344  printf("n : ") ; std::cout << n.t() ;
345 #endif
346 
347 
348  /* Calcul de la matrice de rotation R */
349 
350  /*****
351  Calcul du sinus(theta) et du cosinus(theta)
352  Remarque : sinus(theta) pourra changer de signe en fonction
353  de la solution retenue (cf. ci-dessous)
354  *****/
355  sinusTheta = signeSinus*sqrt((sv[0]*sv[0] -sv[1]*sv[1])
356  *(sv[1]*sv[1] -sv[2]*sv[2]))
357  / ((sv[0] + sv[2]) * sv[1]);
358 
359  cosinusTheta = ( sv[1] * sv[1] + sv[0] * sv[2] ) / ((sv[0] + sv[2]) * sv[1]);
360 
361  /* construction de la matrice de rotation R' */
362  aRbp[0][0] = cosinusTheta; aRbp[0][1] = 0; aRbp[0][2] = -sinusTheta;
363  aRbp[1][0] = 0; aRbp[1][1] = 1; aRbp[1][2] = 0;
364  aRbp[2][0] = sinusTheta; aRbp[2][1] = 0; aRbp[2][2] = cosinusTheta;
365 
366 
367 
368  /* multiplication Rint = U R' */
369  for (i = 0; i < 3; i++) {
370  for (j = 0; j < 3; j++) {
371  aRbint[i][j] = 0.0;
372  for (k = 0; k < 3; k++) {
373  aRbint[i][j] += mU[i][k] * aRbp[k][j];
374  }
375  }
376  }
377 
378  /* multiplication R = Rint . V^T */
379  for (i = 0; i < 3; i++) {
380  for (j = 0; j < 3; j++) {
381  aRb[i][j] = 0.0;
382  for (k = 0; k < 3; k++) {
383  aRb[i][j] += aRbint[i][k] * mV[j][k];
384  }
385  }
386  }
387  /*transpose_carre(aRb,3); */
388 #ifdef DEBUG_Homographie
389  printf("R : %d\n",aRb.isARotationMatrix() ) ; std::cout << aRb << std::endl ;
390 #endif
391 
392 }
393 
412 void
414  vpRotationMatrix &aRb,
415  vpTranslationVector &atb,
416  vpColVector &n)
417 {
418  /**** Declarations des variables ****/
419 
420  vpMatrix aRbint(3,3) ;
421  vpColVector svTemp(3), sv(3);
422  vpMatrix mX(3,2) ;
423  vpColVector aTbp(3), normaleEstimee(3);
424  double distanceFictive;
425  double sinusTheta, cosinusTheta, signeSinus= 1;
426  double cosinusDesireeEstimee, cosinusAncien;
427  double s, determinantU, determinantV;
428  unsigned int i, j, k, w;
429  unsigned int vOrdre[3];
430 
431  vpColVector normaleDesiree(3) ;
432  normaleDesiree[0]=0;normaleDesiree[1]=0;normaleDesiree[2]=1;
433 
434  /**** Corps de la focntion ****/
435 #ifdef DEBUG_Homographie
436  printf ("debut : Homographie_EstimationDeplacementCamera\n");
437 #endif
438 
439  /* Allocation des matrices */
440  vpMatrix mTempU(3,3) ;
441  vpMatrix mTempV(3,3) ;
442  vpMatrix mU(3,3) ;
443  vpMatrix mV(3,3) ;
444  vpMatrix aRbp(3,3) ;
445 
446 
447  vpMatrix mH(3,3) ;
448  for (i=0 ; i < 3 ; i++)
449  for (j=0 ; j < 3 ; j++) mH[i][j] = aHb[i][j];
450 
451  /* Preparation au calcul de la SVD */
452  mTempU = mH ;
453 
454  /*****
455  Remarque : mTempU, svTemp et mTempV sont modifies par svd
456  Il est necessaire apres de les trier dans l'ordre decroissant
457  des valeurs singulieres
458  *****/
459  mTempU.svd(svTemp,mTempV) ;
460 
461  /* On va mettre les valeurs singulieres en ordre decroissant : */
462 
463  /* Determination de l'ordre des valeurs */
464  if (svTemp[0] >= svTemp[1]) {
465  if (svTemp[0] >= svTemp[2]) {
466  if (svTemp[1] > svTemp[2]) {
467  vOrdre[0] = 0; vOrdre[1] = 1; vOrdre[2] = 2;
468  } else {
469  vOrdre[0] = 0; vOrdre[1] = 2; vOrdre[2] = 1;
470  }
471  } else {
472  vOrdre[0] = 2; vOrdre[1] = 0; vOrdre[2] = 1;
473  }
474  } else {
475  if (svTemp[1] >= svTemp[2]){
476  if (svTemp[0] > svTemp[2])
477  { vOrdre[0] = 1; vOrdre[1] = 0; vOrdre[2] = 2; }
478  else
479  { vOrdre[0] = 1; vOrdre[1] = 2; vOrdre[2] = 0; }
480  } else {
481  vOrdre[0] = 2; vOrdre[1] = 1; vOrdre[2] = 0;
482  }
483  }
484  /*****
485  Tri decroissant des matrices U, V, sv
486  en fonction des valeurs singulieres car
487  hypothese : sv[0]>=sv[1]>=sv[2]>=0
488  *****/
489 
490 
491  for (i = 0; i < 3; i++) {
492  sv[i] = svTemp[vOrdre[i]];
493  for (j = 0; j < 3; j++) {
494  mU[i][j] = mTempU[i][vOrdre[j]];
495  mV[i][j] = mTempV[i][vOrdre[j]];
496  }
497  }
498 
499 #ifdef DEBUG_Homographie
500  printf("U : \n") ; std::cout << mU << std::endl ;
501  printf("V : \n") ; std::cout << mV << std::endl ;
502  printf("Valeurs singulieres : ") ; std::cout << sv.t() ;
503 #endif
504 
505  /* A verifier si necessaire!!! */
506  determinantV = mV.det();
507  determinantU = mU.det();
508 
509  s = determinantU * determinantV;
510 
511 #ifdef DEBUG_Homographie
512  printf ("s = det(U) * det(V) = %f * %f = %f\n",determinantU,determinantV,s);
513 #endif
514  if (s < 0) mV *=-1 ;
515 
516 
517  /* d' = d2 */
518  distanceFictive = sv[1];
519 #ifdef DEBUG_Homographie
520  printf ("d = %f\n",distanceFictive);
521 #endif
522  n.resize(3) ;
523 
524  if (((sv[0] - sv[1]) < sing_threshold) && (sv[0] - sv[2]) < sing_threshold)
525  {
526  //#ifdef DEBUG_Homographie
527  // printf ("\nPure rotation\n");
528  //#endif
529  /*****
530  Cas ou le deplacement est une rotation pure
531  et la normale reste indefini
532  sv[0] = sv[1]= sv[2]
533  *****/
534  aTbp[0] = 0;
535  aTbp[1] = 0;
536  aTbp[2] = 0;
537 
538  n[0] = normaleDesiree[0];
539  n[1] = normaleDesiree[1];
540  n[2] = normaleDesiree[2];
541  }
542  else
543  {
544 #ifdef DEBUG_Homographie
545  printf("\nCas general\n");
546 #endif
547  /* Cas general */
548 
549  /*****
550  test pour determiner quelle est la bonne solution on teste
551  d'abord quelle solution est plus proche de la perpendiculaire
552  au plan de la cible constuction de la normale n
553  *****/
554 
555  /*****
556  Calcul de la normale au plan : n' = [ esp1*x1 , x2=0 , esp3*x3 ]
557  dans l'ordre : cas (esp1=+1, esp3=+1) et (esp1=-1, esp3=+1)
558  *****/
559  mX[0][0] = sqrt ((sv[0] * sv[0] - sv[1] * sv[1])
560  / (sv[0] * sv[0] - sv[2] * sv[2]));
561  mX[1][0] = 0.0;
562  mX[2][0] = sqrt ((sv[1] * sv[1] - sv[2] * sv[2])
563  / (sv[0] * sv[0] - sv[2] * sv[2]));
564 
565  mX[0][1] = -mX[0][0];
566  mX[1][1] = mX[1][0];
567  mX[2][1] = mX[2][0];
568 
569  /* Il y a 4 solutions pour n : 2 par cas => n1, -n1, n2, -n2 */
570  cosinusAncien = 0.0;
571  for (w = 0; w < 2; w++) { /* Pour les 2 cas */
572  for (k = 0; k < 2; k++) { /* Pour le signe */
573 
574  /* Calcul de la normale estimee : n = V.n' */
575  for (i = 0; i < 3; i++) {
576  normaleEstimee[i] = 0.0;
577  for (j = 0; j < 3; j++) {
578  normaleEstimee[i] += (2.0 * k - 1.0) * mV[i][j] * mX[j][w];
579  }
580  }
581 
582 
583  /* Calcul du cosinus de l'angle entre la normale reelle et desire */
584  cosinusDesireeEstimee = 0.0;
585  for (i = 0; i < 3; i++)
586  cosinusDesireeEstimee += normaleEstimee[i] * normaleDesiree[i];
587 
588  /*****
589  Si la solution est meilleur
590  Remarque : On ne teste pas le cas oppose (cos<0)
591  *****/
592  if (cosinusDesireeEstimee > cosinusAncien)
593  {
594  cosinusAncien = cosinusDesireeEstimee;
595 
596  /* Affectation de la normale qui est retourner */
597  for (j = 0; j < 3; j++)
598  n[j] = normaleEstimee[j];
599 
600  /* Construction du vecteur t'= +/- (d1-d3).[x1, 0, -x3] */
601  aTbp[0] = (2.0 * k - 1.0) * (sv[0] - sv[2]) * mX[0][w];
602  aTbp[1] = (2.0 * k - 1.0) * (sv[0] - sv[2]) * mX[1][w];
603  aTbp[2] = -(2.0 * k - 1.0) * (sv[0] - sv[2]) * mX[2][w];
604 
605  /* si c'est la deuxieme solution */
606  if (w == 1)
607  signeSinus = -1; /* car esp1*esp3 = -1 */
608  else
609  signeSinus = 1;
610  } /* fin if (cosinusDesireeEstimee > cosinusAncien) */
611  } /* fin k */
612  } /* fin w */
613  } /* fin else */
614 
615 
616  /* Calcul du vecteur de translation qui est retourner : t = (U * t') / d */
617  for (i = 0; i < 3; i++) {
618  atb[i] = 0.0;
619  for (j = 0; j < 3; j++) {
620  atb[i] += mU[i][j] * aTbp[j];
621  }
622  atb[i] /= distanceFictive;
623  }
624 
625 
626 #ifdef DEBUG_Homographie
627  printf("t' : ") ; std::cout << aTbp.t() ;
628  printf("t/d : ") ; std::cout << atb.t() ;
629  printf("n : ") ; std::cout << n.t() ;
630 #endif
631 
632 
633  /* Calcul de la matrice de rotation R */
634 
635  /*****
636  Calcul du sinus(theta) et du cosinus(theta)
637  Remarque : sinus(theta) pourra changer de signe en fonction
638  de la solution retenue (cf. ci-dessous)
639  *****/
640  sinusTheta = signeSinus*sqrt((sv[0]*sv[0] -sv[1]*sv[1])
641  *(sv[1]*sv[1] -sv[2]*sv[2]))
642  / ((sv[0] + sv[2]) * sv[1]);
643 
644  cosinusTheta = ( sv[1] * sv[1] + sv[0] * sv[2] ) / ((sv[0] + sv[2]) * sv[1]);
645 
646  /* construction de la matrice de rotation R' */
647  aRbp[0][0] = cosinusTheta; aRbp[0][1] = 0; aRbp[0][2] = -sinusTheta;
648  aRbp[1][0] = 0; aRbp[1][1] = 1; aRbp[1][2] = 0;
649  aRbp[2][0] = sinusTheta; aRbp[2][1] = 0; aRbp[2][2] = cosinusTheta;
650 
651 
652 
653  /* multiplication Rint = U R' */
654  for (i = 0; i < 3; i++) {
655  for (j = 0; j < 3; j++) {
656  aRbint[i][j] = 0.0;
657  for (k = 0; k < 3; k++) {
658  aRbint[i][j] += mU[i][k] * aRbp[k][j];
659  }
660  }
661  }
662 
663  /* multiplication R = Rint . V^T */
664  for (i = 0; i < 3; i++) {
665  for (j = 0; j < 3; j++) {
666  aRb[i][j] = 0.0;
667  for (k = 0; k < 3; k++) {
668  aRb[i][j] += aRbint[i][k] * mV[j][k];
669  }
670  }
671  }
672  /*transpose_carre(aRb,3); */
673 #ifdef DEBUG_Homographie
674  printf("R : %d\n",aRb.isARotationMatrix() ) ; std::cout << aRb << std::endl ;
675 #endif
676 
677 }
678 
680  const double x,
681  const double y,
682  std::list<vpRotationMatrix> & vR,
683  std::list<vpTranslationVector> & vT,
684  std::list<vpColVector> & vN)
685 {
686 
687 #ifdef DEBUG_Homographie
688  printf ("debut : Homographie_EstimationDeplacementCamera\n");
689 #endif
690 
691  vR.clear();
692  vT.clear();
693  vN.clear();
694 
695  /**** Declarations des variables ****/
696  int cas1 =1, cas2=2, cas3=3, cas4=4;
697  int cas =0;
698  bool norm1ok=false, norm2ok = false,norm3ok=false,norm4ok =false;
699 
700  double tmp,determinantU,determinantV,s,distanceFictive;
701  vpMatrix mTempU(3,3),mTempV(3,3),U(3,3),V(3,3);
702 
703  vpRotationMatrix Rprim1,R1;
704  vpRotationMatrix Rprim2,R2;
705  vpRotationMatrix Rprim3,R3;
706  vpRotationMatrix Rprim4,R4;
707  vpTranslationVector Tprim1, T1;
708  vpTranslationVector Tprim2, T2;
709  vpTranslationVector Tprim3, T3;
710  vpTranslationVector Tprim4, T4;
711  vpColVector Nprim1(3), N1(3);
712  vpColVector Nprim2(3), N2(3);
713  vpColVector Nprim3(3), N3(3);
714  vpColVector Nprim4(3), N4(3);
715 
716  vpColVector svTemp(3),sv(3);
717  unsigned int vOrdre[3];
718  vpColVector vTp(3);
719 
720 
721  /* Preparation au calcul de la SVD */
722  mTempU = H.convert();
723 
724  /*****
725  Remarque : mTempU, svTemp et mTempV sont modifies par svd
726  Il est necessaire apres de les trier dans l'ordre decroissant
727  des valeurs singulieres
728  *****/
729 
730  // cette fonction ne renvoit pas d'erreur
731  mTempU.svd(svTemp, mTempV);
732 
733  /* On va mettre les valeurs singulieres en ordre decroissant : */
734  /* Determination de l'ordre des valeurs */
735  if (svTemp[0] >= svTemp[1]) {
736  if (svTemp[0] >= svTemp[2])
737  {
738  if (svTemp[1] > svTemp[2])
739  {
740  vOrdre[0] = 0; vOrdre[1] = 1; vOrdre[2] = 2;
741  }
742  else
743  {
744  vOrdre[0] = 0; vOrdre[1] = 2; vOrdre[2] = 1;
745  }
746  }
747  else
748  {
749  vOrdre[0] = 2; vOrdre[1] = 0; vOrdre[2] = 1;
750  }
751  } else {
752  if (svTemp[1] >= svTemp[2]){
753  if (svTemp[0] > svTemp[2]) {
754  vOrdre[0] = 1; vOrdre[1] = 0; vOrdre[2] = 2;
755  } else {
756  vOrdre[0] = 1; vOrdre[1] = 2; vOrdre[2] = 0;
757  }
758  } else {
759  vOrdre[0] = 2; vOrdre[1] = 1; vOrdre[2] = 0;
760  }
761  }
762  /*****
763  Tri decroissant des matrices U, V, sv
764  en fonction des valeurs singulieres car
765  hypothese : sv[0]>=sv[1]>=sv[2]>=0
766  *****/
767  for (unsigned int i = 0; i < 3; i++) {
768  sv[i] = svTemp[vOrdre[i]];
769  for (unsigned int j = 0; j < 3; j++) {
770  U[i][j] = mTempU[i][vOrdre[j]];
771  V[i][j] = mTempV[i][vOrdre[j]];
772  }
773  }
774 
775 #ifdef DEBUG_Homographie
776  printf("U : \n") ; Affiche(U) ;
777  printf("V : \n") ; affiche(V) ;
778  printf("Valeurs singulieres : ") ; affiche(sv);
779 #endif
780 
781  // calcul du determinant de U et V
782  determinantU = U[0][0] * (U[1][1]*U[2][2] - U[1][2]*U[2][1]) +
783  U[0][1] * (U[1][2]*U[2][0] - U[1][0]*U[2][2]) +
784  U[0][2] * (U[1][0]*U[2][1] - U[1][1]*U[2][0]);
785 
786  determinantV = V[0][0] * (V[1][1]*V[2][2] - V[1][2]*V[2][1]) +
787  V[0][1] * (V[1][2]*V[2][0] - V[1][0]*V[2][2]) +
788  V[0][2] * (V[1][0]*V[2][1] - V[1][1]*V[2][0]);
789 
790  s = determinantU * determinantV;
791 
792 #ifdef DEBUG_Homographie
793  printf ("s = det(U) * det(V) = %f * %f = %f\n",determinantU,determinantV,s);
794 #endif
795 
796  // deux cas sont a traiter :
797  // distance Fictive = sv[1]
798  // distance fictive = -sv[1]
799 
800  // pour savoir quelle est le bon signe,
801  // on utilise le point qui appartient au plan
802  // la contrainte est :
803  // (h_31x_1 + h_32x_2 + h_33)/d > 0
804  // et d = sd'
805 
806  tmp = H[2][0]*x + H[2][1]*y + H[2][2] ;
807 
808  if ((tmp/(sv[1] *s)) > 0)
809  distanceFictive = sv[1];
810  else
811  distanceFictive = -sv[1];
812 
813  // il faut ensuite considerer l'ordre de multiplicite de chaque variable
814  // 1er cas : d1<>d2<>d3
815  // 2eme cas : d1=d2 <> d3
816  // 3eme cas : d1 <>d2 =d3
817  // 4eme cas : d1 =d2=d3
818 
819  if ((sv[0] - sv[1]) < sing_threshold)
820  {
821  if ((sv[1] - sv[2]) < sing_threshold)
822  cas = cas4;
823  else
824  cas = cas2;
825  }
826  else
827  {
828  if ((sv[1] - sv[2]) < sing_threshold)
829  cas = cas3;
830  else
831  cas = cas1;
832  }
833 
834  Nprim1 = 0.0; Nprim2 = 0.0; Nprim3 = 0.0; Nprim4 = 0.0;
835 
836  // on filtre ensuite les diff'erentes normales possibles
837  // condition : nm/d > 0
838  // avec d = sd'
839  // et n = Vn'
840 
841  // les quatres cas sont : ++, +-, -+ , --
842  // dans tous les cas, Normale[1] = 0;
843  Nprim1[1] = 0.0;
844  Nprim2[1] = 0.0;
845  Nprim3[1] = 0.0;
846  Nprim4[1] = 0.0;
847 
848  // on calcule les quatres cas de normale
849 
850  if (cas == cas1)
851  {
852  // quatre normales sont possibles
853  Nprim1[0] = sqrt((sv[0] * sv[0] - sv[1] * sv[1] )/
854  (sv[0] * sv[0] - sv[2] * sv[2] ));
855 
856  Nprim1[2] = sqrt((sv[1] * sv[1] - sv[2] * sv[2] )/
857  (sv[0] * sv[0] - sv[2] * sv[2] ));
858 
859  Nprim2[0] = Nprim1[0]; Nprim2[2] = - Nprim1[2];
860  Nprim3[0] = - Nprim1[0]; Nprim3[2] = Nprim1[2];
861  Nprim4[0] = - Nprim1[0]; Nprim4[2] = - Nprim1[2];
862  }
863  if (cas == cas2)
864  {
865  // 2 normales sont possibles
866  // x3 = +-1
867  Nprim1[2] = 1;
868  Nprim2[2] = -1;
869  }
870 
871  if (cas == cas3)
872  {
873  // 2 normales sont possibles
874  // x1 = +-1
875  Nprim1[0] = 1;
876  Nprim2[0] = -1;
877  }
878  // si on est dans le cas 4,
879  // on considere que x reste indefini
880 
881  // on peut maintenant filtrer les solutions avec la contrainte
882  // n^tm / d > 0
883  // attention, il faut travailler avec la bonne normale,
884  // soit Ni et non pas Nprimi
885  if (cas == cas1)
886  {
887  N1 = V *Nprim1;
888 
889  tmp = N1[0] * x + N1[1] * y + N1[2];
890  tmp/= (distanceFictive *s);
891  norm1ok = (tmp>0);
892 
893  N2 = V *Nprim2;
894  tmp = N2[0] * x + N2[1] *y+ N2[2];
895  tmp/= (distanceFictive*s);
896  norm2ok = (tmp>0);
897 
898  N3 = V *Nprim3;
899  tmp = N3[0] * x + N3[1]*y+ N3[2];
900  tmp/= (distanceFictive*s);
901  norm3ok = (tmp>0);
902 
903  N4 = V *Nprim4;
904  tmp = N4[0] * x + N4[1] * y + N4[2];
905  tmp/= (distanceFictive*s);
906  norm4ok = (tmp>0);
907  }
908 
909  if (cas == cas2)
910  {
911  N1 = V *Nprim1;
912  tmp = N1[0] * x + N1[1] * y + N1[2];
913  tmp/= (distanceFictive*s);
914  norm1ok = (tmp>0);
915 
916  N2 = V *Nprim2;
917  tmp = N2[0] * x + N2[1] * y + N2[2];
918  tmp/= (distanceFictive*s);
919  norm2ok = (tmp>0);
920  }
921 
922  if (cas == cas3)
923  {
924  N1 = V *Nprim1;
925  tmp = N1[0] * x + N1[1] * y + N1[2];
926  tmp/= (distanceFictive*s);
927  norm1ok = (tmp>0);
928 
929  N2 = V *Nprim2;
930  tmp = N2[0] * x + N2[1] * y + N2[2];
931  tmp/= (distanceFictive*s);
932  norm2ok = (tmp>0);
933  }
934 
935  // on a donc maintenant les differents cas possibles
936  // on peut ensuite remonter aux deplacements
937  // on separe encore les cas 1,2,3
938  // la, deux choix se posent suivant le signe de d
939  if (distanceFictive>0)
940  {
941  if (cas == cas1)
942  {
943  if (norm1ok)
944  {
945 
946  //cos theta
947  Rprim1[0][0] = (vpMath::sqr(sv[1]) + sv[0] * sv[2]) /
948  ((sv[0] + sv[2]) * sv[1]);
949 
950  Rprim1[2][2] = Rprim1[0][0];
951 
952  // sin theta
953  Rprim1[2][0] = (sqrt((vpMath::sqr(sv[0]) - vpMath::sqr(sv[1])) *
954  (vpMath::sqr(sv[1]) - vpMath::sqr(sv[2]))))
955  / ((sv[0] + sv[2]) * sv[1]);
956 
957  Rprim1[0][2] = -Rprim1[2][0];
958 
959  Rprim1[1][1] =1.0;
960 
961  Tprim1[0] = Nprim1[0];
962  Tprim1[1] = 0.0;
963  Tprim1[2] = -Nprim1[2];
964 
965  Tprim1*=(sv[0] - sv[2]);
966 
967  }
968 
969  if (norm2ok)
970  {
971 
972  //cos theta
973  Rprim2[0][0] = (vpMath::sqr(sv[1]) + sv[0] * sv[2]) /
974  ((sv[0] + sv[2]) * sv[1]);
975 
976  Rprim2[2][2] = Rprim2[0][0];
977 
978  // sin theta
979  Rprim2[2][0] = -(sqrt((vpMath::sqr(sv[0]) - vpMath::sqr(sv[1])) *
980  (vpMath::sqr(sv[1]) - vpMath::sqr(sv[2]))))
981  / ((sv[0] + sv[2]) * sv[1]);
982 
983  Rprim2[0][2] = -Rprim2[2][0];
984 
985  Rprim2[1][1] =1.0;
986 
987  Tprim2[0] = Nprim2[0];
988  Tprim2[1] = 0.0;
989  Tprim2[2] = -Nprim2[2];
990 
991  Tprim2*=(sv[0] - sv[2]);
992 
993  }
994 
995  if (norm3ok)
996  {
997 
998  //cos theta
999  Rprim3[0][0] = (vpMath::sqr(sv[1]) + sv[0] * sv[2]) /
1000  ((sv[0] + sv[2]) * sv[1]);
1001 
1002  Rprim3[2][2] = Rprim3[0][0];
1003 
1004  // sin theta
1005  Rprim3[2][0] = -(sqrt((vpMath::sqr(sv[0]) - vpMath::sqr(sv[1])) *
1006  (vpMath::sqr(sv[1]) - vpMath::sqr(sv[2]))))
1007  / ((sv[0] + sv[2]) * sv[1]);
1008 
1009  Rprim3[0][2] = -Rprim3[2][0];
1010 
1011  Rprim3[1][1] =1.0;
1012 
1013  Tprim3[0] = Nprim3[0];
1014  Tprim3[1] = 0.0;
1015  Tprim3[2] = -Nprim3[2];
1016 
1017  Tprim3*=(sv[0] - sv[2]);
1018 
1019  }
1020 
1021  if (norm4ok)
1022  {
1023 
1024  //cos theta
1025  Rprim4[0][0] = (vpMath::sqr(sv[1]) + sv[0] * sv[2])/
1026  ((sv[0] + sv[2]) * sv[1]);
1027 
1028  Rprim4[2][2] = Rprim4[0][0];
1029 
1030  // sin theta
1031  Rprim4[2][0] = (sqrt((vpMath::sqr(sv[0]) - vpMath::sqr(sv[1])) *
1032  (vpMath::sqr(sv[1]) - vpMath::sqr(sv[2]))))
1033  / ((sv[0] + sv[2]) * sv[1]);
1034 
1035  Rprim4[0][2] = -Rprim4[2][0];
1036 
1037  Rprim4[1][1] =1.0;
1038 
1039  Tprim4[0] = Nprim4[0];
1040  Tprim4[1] = 0.0;
1041  Tprim4[2] = -Nprim4[2];
1042 
1043  Tprim4*=(sv[0] - sv[2]);
1044 
1045  }
1046  }
1047 
1048  if (cas == cas2)
1049  {
1050  // 2 normales sont potentiellement candidates
1051 
1052  if (norm1ok)
1053  {
1054  Rprim1.eye();
1055 
1056  Tprim1 = Nprim1[0];
1057  Tprim1*= (sv[2] - sv[0]);
1058  }
1059 
1060  if (norm2ok)
1061  {
1062  Rprim2.eye();
1063 
1064  Tprim2 = Nprim2[1];
1065  Tprim2*= (sv[2] - sv[0]);
1066  }
1067  }
1068  if (cas == cas3)
1069  {
1070  if (norm1ok)
1071  {
1072  Rprim1.eye();
1073 
1074  Tprim1 = Nprim1[0];
1075  Tprim1*= (sv[0] - sv[1]);
1076  }
1077 
1078  if (norm2ok)
1079  {
1080  Rprim2.eye();
1081 
1082  Tprim2 = Nprim2[1];
1083  Tprim2*= (sv[0] - sv[1]);
1084  }
1085  }
1086  if (cas == cas4)
1087  {
1088  // on ne connait pas la normale dans ce cas la
1089  Rprim1.eye();
1090  Tprim1 = 0.0;
1091  }
1092  }
1093 
1094  if (distanceFictive <0)
1095  {
1096 
1097  if (cas == cas1)
1098  {
1099  if (norm1ok)
1100  {
1101 
1102 
1103  //cos theta
1104  Rprim1[0][0] = ( sv[0] * sv[2] - vpMath::sqr(sv[1])) /
1105  ((sv[0] - sv[2]) * sv[1]);
1106 
1107  Rprim1[2][2] = -Rprim1[0][0];
1108 
1109  // sin theta
1110  Rprim1[2][0] = (sqrt((vpMath::sqr(sv[0]) - vpMath::sqr(sv[1])) *
1111  (vpMath::sqr(sv[1]) - vpMath::sqr(sv[2]))))
1112  / ((sv[0] - sv[2]) * sv[1]);
1113 
1114  Rprim1[0][2] = Rprim1[2][0];
1115 
1116  Rprim1[1][1] = -1.0;
1117 
1118  Tprim1[0] = Nprim1[0];
1119  Tprim1[1] = 0.0;
1120  Tprim1[2] = Nprim1[2];
1121 
1122  Tprim1*=(sv[0] + sv[2]);
1123 
1124  }
1125 
1126  if (norm2ok)
1127  {
1128 
1129  //cos theta
1130  Rprim2[0][0] = (sv[0] * sv[2] - vpMath::sqr(sv[1])) /
1131  ((sv[0] - sv[2]) * sv[1]);
1132 
1133  Rprim2[2][2] = -Rprim2[0][0];
1134 
1135  // sin theta
1136  Rprim2[2][0] = -(sqrt((vpMath::sqr(sv[0]) - vpMath::sqr(sv[1])) *
1137  (vpMath::sqr(sv[1]) - vpMath::sqr(sv[2]))))
1138  / ((sv[0] - sv[2]) * sv[1]);
1139 
1140  Rprim2[0][2] = Rprim2[2][0];
1141 
1142  Rprim2[1][1] = - 1.0;
1143 
1144  Tprim2[0] = Nprim2[0];
1145  Tprim2[1] = 0.0;
1146  Tprim2[2] = Nprim2[2];
1147 
1148  Tprim2*=(sv[0] + sv[2]);
1149 
1150  }
1151 
1152  if (norm3ok)
1153  {
1154 
1155  //cos theta
1156  Rprim3[0][0] = ( sv[0] * sv[2] - vpMath::sqr(sv[1])) /
1157  ((sv[0] - sv[2]) * sv[1]);
1158 
1159  Rprim3[2][2] = -Rprim3[0][0];
1160 
1161  // sin theta
1162  Rprim3[2][0] = -(sqrt((vpMath::sqr(sv[0]) - vpMath::sqr(sv[1])) *
1163  (vpMath::sqr(sv[1]) - vpMath::sqr(sv[2]))))
1164  / ((sv[0] - sv[2]) * sv[1]);
1165 
1166  Rprim3[0][2] = Rprim3[2][0];
1167 
1168  Rprim3[1][1] = -1.0;
1169 
1170  Tprim3[0] = Nprim3[0];
1171  Tprim3[1] = 0.0;
1172  Tprim3[2] = Nprim3[2];
1173 
1174  Tprim3*=(sv[0] + sv[2]);
1175 
1176  }
1177 
1178  if (norm4ok)
1179  {
1180  //cos theta
1181  Rprim4[0][0] = ( sv[0] * sv[2]-vpMath::sqr(sv[1]))/((sv[0] - sv[2]) * sv[1]);
1182 
1183  Rprim4[2][2] = -Rprim4[0][0];
1184 
1185  // sin theta
1186  Rprim4[2][0] = (sqrt((vpMath::sqr(sv[0]) - vpMath::sqr(sv[1])) *
1187  (vpMath::sqr(sv[1]) - vpMath::sqr(sv[2]))))
1188  / ((sv[0] - sv[2]) * sv[1]);
1189 
1190  Rprim4[0][2] = Rprim4[2][0];
1191 
1192  Rprim4[1][1] = - 1.0;
1193 
1194  Tprim4[0] = Nprim4[0];
1195  Tprim4[1] = 0.0;
1196  Tprim4[2] = Nprim4[2];
1197 
1198  Tprim4*=(sv[0] + sv[2]);
1199  }
1200  }
1201  if (cas == cas2)
1202  {
1203  // 2 normales sont potentiellement candidates
1204 
1205  if (norm1ok)
1206  {
1207  Rprim1.eye();
1208  Rprim1[0][0] = -1;
1209  Rprim1[1][1] = -1;
1210 
1211  Tprim1 = Nprim1[0];
1212  Tprim1*= (sv[2] + sv[0]);
1213  }
1214 
1215  if (norm2ok)
1216  {
1217  Rprim2.eye();
1218  Rprim2[0][0] = -1;
1219  Rprim2[1][1] = -1;
1220 
1221  Tprim2 = Nprim2[1];
1222  Tprim2*= (sv[2] + sv[0]);
1223  }
1224  }
1225  if (cas == cas3)
1226  {
1227  if (norm1ok)
1228  {
1229  Rprim1.eye();
1230  Rprim1[2][2] = -1;
1231  Rprim1[1][1] = -1;
1232 
1233  Tprim1 = Nprim1[0];
1234  Tprim1*= (sv[2] + sv[0]);
1235  }
1236 
1237  if (norm2ok)
1238  {
1239  Rprim2.eye();
1240  Rprim2[2][2] = -1;
1241  Rprim2[1][1] = -1;
1242 
1243  Tprim2 = Nprim2[1];
1244  Tprim2*= (sv[0] + sv[2]);
1245  }
1246  }
1247 
1248  // ON NE CONSIDERE PAS LE CAS NUMERO 4
1249  }
1250  // tous les Rprim et Tprim sont calcules
1251  // on peut maintenant recuperer la
1252  // rotation, et la translation
1253  // IL Y A JUSTE LE CAS D<0 ET CAS 4 QU'ON NE TRAITE PAS
1254  if ((distanceFictive>0) || (cas != cas4))
1255  {
1256  // on controle juste si les normales sont ok
1257 
1258  if (norm1ok)
1259  {
1260  R1 = s * U * Rprim1 * V.t();
1261  T1 = U * Tprim1;
1262  T1 /= (distanceFictive *s);
1263  N1 = V *Nprim1;
1264 
1265  // je rajoute le resultat
1266  vR.push_back(R1);
1267  vT.push_back(T1);
1268  vN.push_back(N1);
1269  }
1270  if (norm2ok)
1271  {
1272  R2 = s * U * Rprim2 * V.t();
1273  T2 = U * Tprim2;
1274  T2 /= (distanceFictive *s);
1275  N2 = V *Nprim2;
1276 
1277  // je rajoute le resultat
1278  vR.push_back(R2);
1279  vT.push_back(T2);
1280  vN.push_back(N2);
1281  }
1282  if (norm3ok)
1283  {
1284  R3 = s * U * Rprim3 * V.t();
1285  T3 = U * Tprim3;
1286  T3 /= (distanceFictive *s);
1287  N3 = V *Nprim3;
1288  // je rajoute le resultat
1289  vR.push_back(R3);
1290  vT.push_back(T3);
1291  vN.push_back(N3);
1292  }
1293  if (norm4ok)
1294  {
1295  R4 = s * U * Rprim4 * V.t();
1296  T4 = U * Tprim4;
1297  T4 /= (distanceFictive *s);
1298  N4 = V *Nprim4;
1299 
1300  // je rajoute le resultat
1301  vR.push_back(R4);
1302  vT.push_back(T4);
1303  vN.push_back(N4);
1304  }
1305  }
1306  else
1307  {
1308  std::cout << "On tombe dans le cas particulier ou le mouvement n'est pas estimable!" << std::endl;
1309  }
1310 
1311  // on peut ensuite afficher les resultats...
1312  /* std::cout << "Analyse des resultats : "<< std::endl; */
1313  /* if (cas==cas1) */
1314  /* std::cout << "On est dans le cas 1" << std::endl; */
1315  /* if (cas==cas2) */
1316  /* std::cout << "On est dans le cas 2" << std::endl; */
1317  /* if (cas==cas3) */
1318  /* std::cout << "On est dans le cas 3" << std::endl; */
1319  /* if (cas==cas4) */
1320  /* std::cout << "On est dans le cas 4" << std::endl; */
1321 
1322  /* if (distanceFictive < 0) */
1323  /* std::cout << "d'<0" << std::endl; */
1324  /* else */
1325  /* std::cout << "d'>0" << std::endl; */
1326 
1327 #ifdef DEBUG_Homographie
1328  printf("fin : Homographie_EstimationDeplacementCamera\n");
1329 #endif
1330 }
1331 #endif //#ifndef DOXYGEN_SHOULD_SKIP_THIS
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:92
vpRotationMatrix t() const
void computeDisplacement(vpRotationMatrix &aRb, vpTranslationVector &atb, vpColVector &n)
bool isARotationMatrix() const
Implementation of a rotation matrix and operations on such kind of matrices.
Implementation of an homography and operations on homographies.
Definition: vpHomography.h:179
void svd(vpColVector &w, vpMatrix &v)
Definition: vpMatrix.cpp:1646
static double sqr(double x)
Definition: vpMath.h:110
vpRowVector t() const
vpRowVector t() const
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
vpMatrix convert() const
Class that consider the case of a translation vector.
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:217