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