Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
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
39
40//#define DEBUG_Homographie 0
41
42/* ---------------------------------------------------------------------- */
43/* --- STATIC ------------------------------------------------------------ */
44/* ------------------------------------------------------------------------ */
45const 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
87
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
675void 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
1295END_VISP_NAMESPACE
Implementation of column vector and the associated operations.
vpRowVector t() const
void resize(unsigned int i, bool flagNullify=true)
Implementation of an homography and operations on homographies.
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:175
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.