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