Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpHomographyMalis.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 estimation.
32 */
33
44
45#include <visp3/core/vpDebug.h>
46#include <visp3/core/vpMatrixException.h>
47#include <visp3/vision/vpHomography.h>
48
49#include <cmath> // std::fabs
50
52
53#ifndef DOXYGEN_SHOULD_SKIP_THIS
54namespace
55{
56const double eps = 1e-6;
57
58/**************************************************************************
59 * NOM :
60 * changeFrame
61 *
62 * DESCRIPTION :
63 * Changement de repere Euclidien.
64 *
65 ****************************************************************************
66 * ENTREES :
67 * int pts_ref[4] : Definit quels sont les points de reference, ils ne
68 * seront pas affectes par le changement de repere
69 * int nb_pts : nombre de points a changer de repere
70 * double **pd : La matrice des coordonnees des points desires
71 * double **p : La matrice des coordonnees des points courants
72 *
73 *
74 * SORTIES :
75 *
76 * double **pt_des_nr : La matrice des coordonnees des points desires
77 * dans le nouveau repere.
78 * double **pt_cour_nr : La matrice des coordonnees des points courants
79 * dans le nouveau repere
80 * double **M : ??
81 * double **Mpd : pseudo inverse de M ..
82 *
83 *
84 ****************************************************************************
85 */
86
87void changeFrame(unsigned int *pts_ref, unsigned int nb_pts, vpMatrix &pd, vpMatrix &p, vpMatrix &pnd, vpMatrix &pn,
88 vpMatrix &M, vpMatrix &Mdp);
89void hlm2D(unsigned int nb_pts, vpMatrix &points_des, vpMatrix &points_cour, vpMatrix &H);
90void hlm3D(unsigned int nb_pts, vpMatrix &pd, vpMatrix &p, vpMatrix &H);
91void hlm(unsigned int q_cible, const std::vector<double> &xm, const std::vector<double> &ym,
92 const std::vector<double> &xmi, const std::vector<double> &ymi, vpMatrix &H);
93
94void changeFrame(unsigned int *pts_ref, unsigned int nb_pts, vpMatrix &pd, vpMatrix &p, vpMatrix &pnd, vpMatrix &pn,
95 vpMatrix &M, vpMatrix &Mdp)
96{
97 /* Construction des matrices de changement de repere */
98 vpMatrix Md(3, 3);
99 vpMatrix Mp(3, 3);
100
101 const unsigned int val_3 = 3;
102 for (unsigned int i = 0; i < val_3; ++i) {
103 for (unsigned int j = 0; j < val_3; ++j) {
104 M[j][i] = p[pts_ref[i]][j];
105 Md[j][i] = pd[pts_ref[i]][j];
106 }
107 }
108
109 /*calcul de la pseudo inverse */
110 Mp = M.pseudoInverse(1e-16);
111 Mdp = Md.pseudoInverse(1e-16);
112
113 if (pts_ref[3] > 0) {
114 double lamb_des[3];
115 double lamb_cour[3];
116
117 for (unsigned int i = 0; i < val_3; ++i) {
118 for (unsigned int j = 0; j < val_3; ++j) {
119 lamb_cour[i] = Mp[i][j] * p[pts_ref[3]][j];
120 lamb_des[i] = Mdp[i][j] * pd[pts_ref[3]][j];
121 }
122 }
123
124 for (unsigned int i = 0; i < val_3; ++i) {
125 for (unsigned int j = 0; j < val_3; ++j) {
126 M[i][j] = M[i][j] * lamb_cour[j];
127 Md[i][j] = Md[i][j] * lamb_des[j];
128 }
129 }
130
131 Mdp = Md.pseudoInverse(1e-16);
132 }
133
134 /* changement de repere pour tous les points autres que
135 les trois points de reference */
136
137 unsigned int cont_pts = 0;
138 for (unsigned int k = 0; k < nb_pts; ++k) {
139 if ((pts_ref[0] != k) && (pts_ref[1] != k) && (pts_ref[2] != k)) {
140 for (unsigned int i = 0; i < val_3; ++i) {
141 pn[cont_pts][i] = 0.0;
142 pnd[cont_pts][i] = 0.0;
143 for (unsigned int j = 0; j < val_3; ++j) {
144 pn[cont_pts][i] = pn[cont_pts][i] + (Mp[i][j] * p[k][j]);
145 pnd[cont_pts][i] = pnd[cont_pts][i] + (Mdp[i][j] * pd[k][j]);
146 }
147 }
148 cont_pts = cont_pts + 1;
149 }
150 }
151}
152
153/**************************************************************************
154 * NOM :
155 * Homographie_CrvMafEstHomoPointsCible2D
156 *
157 * DESCRIPTION :
158 * Calcul de l'homographie entre une image courante et une image desiree dans
159 *le cas particulier d'une cible planaire de points (cible pi). Cette
160 *procedure est appellee par "Homographie_CrvMafCalculHomographie".
161 *
162 ****************************************************************************
163 * ENTREES :
164 * int Nb_pts : nombre de points
165 * double **pd : tableau des coordonnees des points desires
166 * couble **p : tableau des coordonnees des points courants
167 *
168 * SORTIES :
169 *
170 * double **H matrice d homographie
171 *
172 ****************************************************************************
173 * AUTEUR : BOSSARD Nicolas. INSA Rennes 5eme annee.
174 *
175 * DATE DE CREATION : 02/12/98
176 *
177 * DATES DE MISE A JOUR :
178 *
179 ****************************************************************************/
180void hlm2D(unsigned int nb_pts, vpMatrix &points_des, vpMatrix &points_cour, vpMatrix &H)
181{
182 double vals_inf;
183 unsigned int contZeros, vect;
184
186 vpMatrix M(3 * nb_pts, 9);
187 vpMatrix V(9, 9);
188 vpColVector sv(9);
189
191 for (unsigned int j = 0; j < nb_pts; ++j) {
192 M[3 * j][0] = 0;
193 M[3 * j][1] = 0;
194 M[3 * j][2] = 0;
195 M[3 * j][3] = -points_des[j][0] * points_cour[j][2];
196 M[3 * j][4] = -points_des[j][1] * points_cour[j][2];
197 M[3 * j][5] = -points_des[j][2] * points_cour[j][2];
198 M[3 * j][6] = points_des[j][0] * points_cour[j][1];
199 M[3 * j][7] = points_des[j][1] * points_cour[j][1];
200 M[3 * j][8] = points_des[j][2] * points_cour[j][1];
201
202 M[(3 * j) + 1][0] = points_des[j][0] * points_cour[j][2];
203 M[(3 * j) + 1][1] = points_des[j][1] * points_cour[j][2];
204 M[(3 * j) + 1][2] = points_des[j][2] * points_cour[j][2];
205 M[(3 * j) + 1][3] = 0;
206 M[(3 * j) + 1][4] = 0;
207 M[(3 * j) + 1][5] = 0;
208 M[(3 * j) + 1][6] = -points_des[j][0] * points_cour[j][0];
209 M[(3 * j) + 1][7] = -points_des[j][1] * points_cour[j][0];
210 M[(3 * j) + 1][8] = -points_des[j][2] * points_cour[j][0];
211
212 M[(3 * j) + 2][0] = -points_des[j][0] * points_cour[j][1];
213 M[(3 * j) + 2][1] = -points_des[j][1] * points_cour[j][1];
214 M[(3 * j) + 2][2] = -points_des[j][2] * points_cour[j][1];
215 M[(3 * j) + 2][3] = points_des[j][0] * points_cour[j][0];
216 M[(3 * j) + 2][4] = points_des[j][1] * points_cour[j][0];
217 M[(3 * j) + 2][5] = points_des[j][2] * points_cour[j][0];
218 M[(3 * j) + 2][6] = 0;
219 M[(3 * j) + 2][7] = 0;
220 M[(3 * j) + 2][8] = 0;
221 }
222
224 M.svd(sv, V);
225
226 /*****
227 La meilleure solution est le vecteur de V associe
228 a la valeur singuliere la plus petite en valeur absolu.
229 Pour cela on parcourt la matrice des valeurs singulieres
230 et on repere la plus petite valeur singuliere, on en profite
231 pour effectuer un controle sur le rang de la matrice : pas plus
232 de 2 valeurs singulieres quasi=0
233 *****/
234 vals_inf = sv[0];
235 vect = 0;
236 contZeros = 0;
237 if (sv[0] < eps) {
238 contZeros = contZeros + 1;
239 }
240 for (unsigned int j = 1; j < 9; ++j) {
241 if (sv[j] < vals_inf) {
242 vals_inf = sv[j];
243 vect = j;
244 }
245 if (sv[j] < eps) {
246 contZeros = contZeros + 1;
247 }
248 }
249
251 if (contZeros > 2) {
252 // vpERROR_TRACE("matrix is rank deficient");
253 throw(vpMatrixException(vpMatrixException::matrixError, "matrix is rank deficient"));
254 }
255
256 H.resize(3, 3);
258 const unsigned int val_3 = 3;
259 for (unsigned int i = 0; i < val_3; ++i) {
260 for (unsigned int j = 0; j < val_3; ++j) {
261 H[i][j] = V[(3 * i) + j][vect];
262 }
263 }
264}
265
266/**************************************************************************
267 * NOM :
268 * Homographie_CrvMafEstHomoPointsC3DEzio
269 *
270 * DESCRIPTION :
271 * Calcul de l'homographie entre une image courante et une image desiree dans
272 *le cas particulier d'une cible non planaire de points (cible pi). Cette
273 *procedure est appellee par "Homographie_CrvMafCalculHomographie".
274 *
275 *
276 ****************************************************************************
277 * ENTREES :
278 * int Nb_pts : nombre de points
279 * double **pd : tableau des coordonnees des points desires
280 * couble **p : tableau des coordonnees des points courants
281 *
282 * SORTIES :
283 *
284 * double **H matrice d'homographie
285 * double epipole[3] epipole
286 *
287 ****************************************************************************
288 **/
289void hlm3D(unsigned int nb_pts, vpMatrix &pd, vpMatrix &p, vpMatrix &H)
290{
291 unsigned int pts_ref[4]; /*** definit lesquels des points de
292 l'image sont les points de reference***/
293
294 vpMatrix M(3, 3);
295 vpMatrix Mdp(3, 3);
296 vpMatrix c(8, 2); // matrice des coeff C
297
298 vpColVector d(8);
299 vpMatrix cp(2, 8); // matrice pseudo-inverse de C
300
301 vpMatrix H_int(3, 3);
302 vpMatrix pn((nb_pts - 3), 3); // points courant nouveau repere
303
304 vpMatrix pnd((nb_pts - 3), 3); // points derives nouveau repere
305
306 /* preparation du changement de repere */
307 /****
308 comme plan de reference on choisit pour le moment
309 arbitrairement le plan contenant les points 1,2,3 du cinq
310 ****/
311 pts_ref[0] = 0;
312 pts_ref[1] = 1;
313 pts_ref[2] = 2;
314 pts_ref[3] = 0;
315
316 /* changement de repere pour tous les points autres que les trois points de
317 * reference */
318
319 changeFrame(pts_ref, nb_pts, pd, p, pnd, pn, M, Mdp);
320
321 unsigned int cont_pts = nb_pts - 3;
322
323 if (cont_pts < 5) {
324 // vpERROR_TRACE(" not enough point to compute the homography ... ");
325 throw(vpMatrixException(vpMatrixException::matrixError, "Not enough point to compute the homography"));
326 }
327
328 unsigned int nc = 7; // nb cols
329
330 /* Allocation matrice CtC */
331 vpMatrix CtC(nc, nc);
332
333 /* Initialisation matrice CtC */
334 for (unsigned int i = 0; i < nc; ++i) {
335 for (unsigned int j = 0; j < nc; ++j) {
336 CtC[i][j] = 0.0;
337 }
338 }
339
340 /* Allocation matrice M */
341 vpColVector C(nc); // Matrice des coefficients
342
343 /* construction de la matrice M des coefficients dans le cas general */
344 /****
345 inconnues du nouveau algorithme
346 x1 = a ; x2 = b ; x3 = c ;
347 x4 = ex ; x5 = ey ; x6 = ez ;
348 qui deviennent apres changement :
349 v1 = x1*x6 ; v2 = x1*x5 ;
350 v3 = x2*x4 ; v4 = x2*x6 ;
351 v5 = x3*x5 ; v6 = x3*x4 ;
352 ****/
353 unsigned int cont = 0;
354 for (unsigned int i = 0; i < (nb_pts - 5); ++i) {
355 for (unsigned int j = i + 1; j < (nb_pts - 4); ++j) {
356 for (unsigned int k = j + 1; k < (nb_pts - 3); ++k) {
357 /* coeff a^2*b */
358 C[0] = (pn[i][2] * pn[j][2] * pn[k][1] * pnd[k][0] //
359 * ((pnd[j][0] * pnd[i][1]) - (pnd[j][1] * pnd[i][0]))) //
360 + (pn[i][2] * pn[k][2] * pn[j][1] * pnd[j][0] //
361 * ((pnd[i][0] * pnd[k][1]) - (pnd[i][1] * pnd[k][0]))) //
362 + (pn[j][2] * pn[k][2] * pn[i][1] * pnd[i][0] //
363 * ((pnd[k][0] * pnd[j][1]) - (pnd[k][1] * pnd[j][0]))); //
364 /* coeff a*b^2 */
365 C[1] = (pn[i][2] * pn[j][2] * pn[k][0] * pnd[k][1] //
366 * ((pnd[i][0] * pnd[j][1]) - (pnd[i][1] * pnd[j][0]))) //
367 + (pn[i][2] * pn[k][2] * pn[j][0] * pnd[j][1] //
368 * ((pnd[k][0] * pnd[i][1]) - (pnd[k][1] * pnd[i][0]))) //
369 + (pn[j][2] * pn[k][2] * pn[i][0] * pnd[i][1] //
370 * ((pnd[j][0] * pnd[k][1]) - (pnd[j][1] * pnd[k][0]))); //
371 /* coeff a^2 */
372 C[2] = (pn[i][1] * pn[k][1] * pn[j][2] * pnd[j][0] //
373 * ((pnd[k][2] * pnd[i][0]) - (pnd[k][0] * pnd[i][2]))) //
374 + (pn[i][1] * pn[j][1] * pn[k][2] * pnd[k][0] //
375 * ((pnd[i][2] * pnd[j][0]) - (pnd[i][0] * pnd[j][2]))) +
376 (pn[j][1] * pn[k][1] * pn[i][2] * pnd[i][0] //
377 * ((pnd[j][2] * pnd[k][0]) - (pnd[j][0] * pnd[k][2]))); //
378
379 /* coeff b^2 */
380 C[3] = (pn[i][0] * pn[j][0] * pn[k][2] * pnd[k][1] //
381 * ((pnd[i][2] * pnd[j][1]) - (pnd[i][1] * pnd[j][2]))) //
382 + (pn[i][0] * pn[k][0] * pn[j][2] * pnd[j][1] //
383 * ((pnd[k][2] * pnd[i][1]) - (pnd[k][1] * pnd[i][2]))) //
384 + (pn[j][0] * pn[k][0] * pn[i][2] * pnd[i][1] //
385 * ((pnd[j][2] * pnd[k][1]) - (pnd[j][1] * pnd[k][2]))); //
386
387 /* coeff a */
388 C[5] = (pn[i][1] * pn[j][1] * pn[k][0] * pnd[k][2] //
389 * ((pnd[i][0] * pnd[j][2]) - (pnd[i][2] * pnd[j][0]))) //
390 + (pn[i][1] * pn[k][1] * pn[j][0] * pnd[j][2] //
391 * ((pnd[k][0] * pnd[i][2]) - (pnd[k][2] * pnd[i][0]))) //
392 + (pn[j][1] * pn[k][1] * pn[i][0] * pnd[i][2] //
393 * ((pnd[j][0] * pnd[k][2]) - (pnd[j][2] * pnd[k][0]))); //
394 /* coeff b */
395 C[6] = (pn[i][0] * pn[j][0] * pn[k][1] * pnd[k][2] //
396 * ((pnd[i][1] * pnd[j][2]) - (pnd[i][2] * pnd[j][1]))) //
397 + (pn[i][0] * pn[k][0] * pn[j][1] * pnd[j][2] //
398 * ((pnd[k][1] * pnd[i][2]) - (pnd[k][2] * pnd[i][1]))) //
399 + (pn[j][0] * pn[k][0] * pn[i][1] * pnd[i][2] //
400 * ((pnd[j][1] * pnd[k][2]) - (pnd[j][2] * pnd[k][1]))); //
401 /* coeff a*b */
402 C[4] = (pn[i][0] * pn[k][1] * pn[j][2] //
403 * ((pnd[k][0] * pnd[j][1] * pnd[i][2]) - (pnd[j][0] * pnd[i][1] * pnd[k][2]))) //
404 + (pn[k][0] * pn[i][1] * pn[j][2] //
405 * ((pnd[j][0] * pnd[k][1] * pnd[i][2]) - (pnd[i][0] * pnd[j][1] * pnd[k][2]))) //
406 + (pn[i][0] * pn[j][1] * pn[k][2] //
407 * ((pnd[k][0] * pnd[i][1] * pnd[j][2]) - (pnd[j][0] * pnd[k][1] * pnd[i][2]))) //
408 + (pn[j][0] * pn[i][1] * pn[k][2] //
409 * ((pnd[i][0] * pnd[k][1] * pnd[j][2]) - (pnd[k][0] * pnd[j][1] * pnd[i][2]))) //
410 + (pn[k][0] * pn[j][1] * pn[i][2] //
411 * ((pnd[j][0] * pnd[i][1] * pnd[k][2]) - (pnd[i][0] * pnd[k][1] * pnd[j][2]))) //
412 + (pn[j][0] * pn[k][1] * pn[i][2] //
413 * ((pnd[i][0] * pnd[j][1] * pnd[k][2]) - (pnd[k][0] * pnd[i][1] * pnd[j][2]))); //
414
415 cont = cont + 1;
416 /* construction de la matrice CtC */
417 for (unsigned int ii = 0; ii < nc; ++ii) {
418 for (unsigned int jj = ii; jj < nc; ++jj) {
419 CtC[ii][jj] = CtC[ii][jj] + (C[ii] * C[jj]);
420 }
421 }
422 }
423 }
424 }
425
426 /* calcul de CtC */
427 for (unsigned int i = 0; i < nc; ++i) {
428 for (unsigned int j = i + 1; j < nc; ++j) {
429 CtC[j][i] = CtC[i][j];
430 }
431 }
432
433 nc = 7; /* nombre de colonnes */
434
435 /* Creation de matrice CtC termine */
436 /* Allocation matrice V */
437 vpMatrix V(nc, nc);
438 /*****
439 Preparation au calcul de la svd (pseudo-inverse)
440 pour obtenir une solution il faut au moins 5 equations independantes
441 donc il faut au moins la mise en correspondence de 3+5 points
442 *****/
443 vpColVector sv(nc); // Vecteur contenant les valeurs singulieres
444
445 CtC.svd(sv, V);
446
447 /*****
448 Il faut un controle sur le rang de la matrice !!
449 La meilleure solution est le vecteur de V associe
450 a la valeur singuliere la plus petite en valeur
451 absolu
452 *****/
453
454 vpColVector svSorted = vpColVector::invSort(sv); // sorted singular value
455
456 /*****
457 Parcours de la matrice ordonnee des valeurs singulieres
458 On note "cont_zeros" le nbre de valeurs quasi= a 0.
459 On note "vect" le rang de la plus petite valeur singliere
460 en valeur absolu
461 *****/
462
463 unsigned int vect = 0;
464 int cont_zeros = 0;
465 cont = 0;
466 for (unsigned int j = 0; j < nc; ++j) {
467 if (std::fabs(sv[j] - svSorted[cont]) <= std::fabs(vpMath::maximum(sv[j], svSorted[cont]))) {
468 vect = j;
469 }
470 if (std::fabs(sv[j] / svSorted[nc - 1]) < eps) {
471 cont_zeros = cont_zeros + 1;
472 }
473 }
474
475 if (cont_zeros > 5) {
476 hlm2D(nb_pts, pd, p, H);
477 }
478 else {
479
480 // estimation de a = 1,b,c ; je cherche le min de somme(i=1:n)
481 // (0.5*(ei)^2)
482 // e1 = V[1][.] * b - V[3][.] = 0 ;
483 // e2 = V[2][.] * c - V[3][.] = 0 ;
484 // e3 = V[2][.] * b - V[3][.] * c = 0 ;
485 // e4 = V[4][.] * b - V[5][.] = 0 ;
486 // e5 = V[4][.] * c - V[6][.] = 0 ;
487 // e6 = V[6][.] * b - V[5][.] * c = 0 ;
488 // e7 = V[7][.] * b - V[8][.] = 0 ;
489 // e8 = V[7][.] * c - V[9][.] = 0 ;
490 d[0] = V[2][vect];
491 d[1] = V[4][vect];
492 d[2] = V[1][vect];
493 d[3] = V[0][vect];
494 d[4] = V[3][vect];
495 d[5] = V[4][vect];
496 d[6] = V[0][vect];
497 d[7] = V[1][vect];
498
499 c[0][0] = V[5][vect];
500 c[0][1] = 0.0;
501 c[1][0] = V[6][vect];
502 c[1][1] = 0.0;
503 c[2][0] = V[3][vect];
504 c[2][1] = 0.0;
505 c[3][0] = V[4][vect];
506 c[3][1] = 0.0;
507 c[4][0] = 0.0;
508 c[4][1] = V[6][vect];
509 c[5][0] = 0.0;
510 c[5][1] = V[5][vect];
511 c[6][0] = 0.0;
512 c[6][1] = V[2][vect];
513 c[7][0] = 0.0;
514 c[7][1] = V[4][vect];
515
517 cp = c.pseudoInverse(1e-6);
518
519 vpColVector H_nr(3), temp; // Homographie diagonale
520 // Multiplication de la matrice H_nr par le vecteur cp
521 temp = cp * d;
522
523 H_nr[0] = temp[0];
524 H_nr[1] = temp[1];
525 H_nr[2] = 1.0;
526
527 vpMatrix T(9, 3);
528 T = 0;
529 T[0][0] = -V[1][vect];
530 T[0][1] = V[0][vect];
531 T[1][0] = V[4][vect];
532 T[1][2] = -V[2][vect];
533 T[2][0] = -V[6][vect];
534 T[2][1] = V[2][vect];
535 T[3][0] = V[6][vect];
536 T[3][2] = -V[0][vect];
537 T[4][0] = -V[3][vect];
538 T[4][1] = V[6][vect];
539 T[5][0] = V[3][vect];
540 T[5][2] = -V[1][vect];
541 T[6][0] = -V[5][vect];
542 T[6][1] = V[4][vect];
543 T[7][0] = V[5][vect];
544 T[7][2] = -V[6][vect];
545 T[8][1] = -V[5][vect];
546 T[8][2] = V[2][vect];
547
548 vpMatrix Hd(3, 3); // diag(gu,gv,gw)
549 const unsigned int val_3 = 3;
550 for (unsigned int i = 0; i < val_3; ++i) {
551 Hd[i][i] = H_nr[i];
552 }
553
554 // H is equal to M diag(gu,gv,gw) M*-1
555 H = M * Hd * Mdp;
556 }
557}
558
559void hlm(unsigned int q_cible, const std::vector<double> &xm, const std::vector<double> &ym,
560 const std::vector<double> &xmi, const std::vector<double> &ymi, vpMatrix &H)
561{
562 unsigned int nbpt = static_cast<unsigned int>(xm.size());
563
564 /****
565 on regarde si il y a au moins un point mais pour l'homographie
566 il faut au moins quatre points
567 ****/
568 vpMatrix pd(nbpt, 3);
569 vpMatrix p(nbpt, 3);
570
571 for (unsigned int i = 0; i < nbpt; ++i) {
572 /****
573 on assigne les points fournies par la structure robot
574 pour la commande globale
575 ****/
576 pd[i][0] = xmi[i];
577 pd[i][1] = ymi[i];
578 pd[i][2] = 1.0;
579 p[i][0] = xm[i];
580 p[i][1] = ym[i];
581 p[i][2] = 1.0;
582 }
583
584 switch (q_cible) {
585 case 1:
586 case 2:
587 /* La cible est planaire de type points */
588
589 hlm2D(nbpt, pd, p, H);
590
591 break;
592 case 3: /* cible non planaire : chateau */
593 /* cible non planaire de type points */
594 hlm3D(nbpt, pd, p, H);
595 break;
596 default:
597 break;
598 } /* fin switch */
599
600} /* fin procedure calcul_homogaphie */
601
602} // end namespace
603#endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
604
605void vpHomography::HLM(const std::vector<double> &xb, const std::vector<double> &yb, const std::vector<double> &xa,
606 const std::vector<double> &ya, bool isplanar, vpHomography &aHb)
607{
608 unsigned int n = static_cast<unsigned int>(xb.size());
609 if ((yb.size() != n) || (xa.size() != n) || (ya.size() != n)) {
610 throw(vpException(vpException::dimensionError, "Bad dimension for HLM shomography estimation"));
611 }
612
613 // 4 point are required
614 if (n < 4) {
615 throw(vpException(vpException::fatalError, "There must be at least 4 matched points"));
616 }
617
618 // The reference plane is the plane build from the 3 first points.
619 unsigned int q_cible;
620 vpMatrix H; // matrice d'homographie en metre
621
622 if (isplanar) {
623 q_cible = 1;
624 }
625 else {
626 q_cible = 3;
627 }
628
629 hlm(q_cible, xa, ya, xb, yb, H);
630
631 aHb = H;
632}
633
634END_VISP_NAMESPACE
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition vpArray2D.h:448
Implementation of column vector and the associated operations.
static vpColVector invSort(const vpColVector &v)
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ dimensionError
Bad dimension.
Definition vpException.h:71
@ fatalError
Fatal error.
Definition vpException.h:72
static void HLM(const std::vector< double > &xb, const std::vector< double > &yb, const std::vector< double > &xa, const std::vector< double > &ya, bool isplanar, vpHomography &aHb)
static Type maximum(const Type &a, const Type &b)
Definition vpMath.h:257
error that can be emitted by the vpMatrix class and its derivatives
@ matrixError
Matrix operation error.
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:175
void svd(vpColVector &w, vpMatrix &V)
vpMatrix pseudoInverse(double svThreshold=1e-6) const