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