ViSP  2.8.0
vpHomographyDLT.cpp
1 /****************************************************************************
2  *
3  * $Id: vpHomographyDLT.cpp 4317 2013-07-17 09:40:17Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Homography estimation.
36  *
37  * Authors:
38  * Eric Marchand
39  *
40  *****************************************************************************/
41 
42 
50 #include <visp/vpHomography.h>
51 #include <visp/vpMatrixException.h>
52 
53 #include <cmath> // std::fabs
54 #include <limits> // numeric_limits
55 
56 void
58  double *x, double *y,
59  double *xn, double *yn,
60  double &xg, double &yg,
61  double &coef)
62 {
63  unsigned int i;
64  xg = 0 ;
65  yg = 0 ;
66 
67  for (i =0 ; i < n ; i++)
68  {
69  xg += x[i] ;
70  yg += y[i] ;
71  }
72  xg /= n ;
73  yg /= n ;
74 
75  //Changement d'origine : le centre de gravité doit correspondre
76  // à l'origine des coordonnées
77  double distance=0;
78  for(i=0; i<n;i++)
79  {
80  double xni=x[i]-xg;
81  double yni=y[i]-yg;
82  xn[i] = xni ;
83  yn[i] = yni ;
84  distance+=sqrt(vpMath::sqr(xni)+vpMath::sqr(yni));
85  }//for translation sur tous les points
86 
87  //Changement d'échelle
88  distance/=n;
89  //calcul du coef de changement d'échelle
90  //if(distance ==0)
91  if(std::fabs(distance) <= std::numeric_limits<double>::epsilon())
92  coef=1;
93  else
94  coef=sqrt(2.0)/distance;
95 
96  for(i=0; i<n;i++)
97  {
98  xn[i] *= coef;
99  yn[i] *= coef;
100  }
101 
102 }
103 
104 //---------------------------------------------------------------------------------------
105 
106 void
108  vpHomography &aHb,
109  double xg1, double yg1, double coef1,
110  double xg2, double yg2, double coef2 )
111 {
112 
113  //calcul des transformations à appliquer sur M_norm pour obtenir M
114  //en fonction des deux normalisations effectuées au début sur
115  //les points: aHb = T2^ aHbn T1
116  vpMatrix T1(3,3);
117  vpMatrix T2(3,3);
118  vpMatrix T2T(3,3);
119 
120  T1.setIdentity();
121  T2.setIdentity();
122  T2T.setIdentity();
123 
124  T1[0][0]=T1[1][1]=coef1;
125  T1[0][2]=-coef1*xg1 ;
126  T1[1][2]=-coef1*yg1 ;
127 
128  T2[0][0]=T2[1][1]=coef2;
129  T2[0][2]=-coef2*xg2 ;
130  T2[1][2]=-coef2*yg2 ;
131 
132 
133  T2T=T2.pseudoInverse(1e-16) ;
134 
135  vpMatrix maHb=T2T*(vpMatrix)aHbn*T1;
136 
137  for (unsigned int i=0 ; i < 3 ; i++)
138  for (unsigned int j=0 ; j < 3 ; j++) aHb[i][j] = maHb[i][j] ;
139 
140 }
141 
142 
158 void
160  double *xb, double *yb,
161  double *xa, double *ya ,
162  vpHomography &aHb)
163 {
164  try{
165  //initialise les données initiales
166  // code_retour =InitialData(n, p1,p2);
167 
168  // normalize points
169  double *xbn;
170  double *ybn;
171  xbn = new double [n];
172  ybn = new double [n];
173 
174  double xg1, yg1, coef1 ;
176  xb,yb,
177  xbn,ybn,
178  xg1, yg1,coef1);
179 
180  double *xan;
181  double *yan;
182  xan = new double [n];
183  yan = new double [n];
184 
185  double xg2, yg2, coef2 ;
187  xa,ya,
188  xan,yan,
189  xg2, yg2,coef2);
190 
191  vpHomography aHbn ;
192  //compute the homography using the DLT from normalized data
193  vpHomography::DLT(n,xbn,ybn,xan,yan,aHbn);
194 
195  //H dénormalisée
196  vpHomography::HartleyDenormalization(aHbn,aHb,xg1,yg1,coef1,xg2,yg2, coef2);
197 
198  delete [] xbn;
199  delete [] ybn;
200  delete [] xan;
201  delete [] yan;
202 
203  }
204  catch(...)
205  {
206  vpTRACE(" ") ;
207  throw ;
208  }
209 }
210 
211 
269 void vpHomography::DLT(unsigned int n,
270  double *xb, double *yb,
271  double *xa, double *ya ,
272  vpHomography &aHb)
273 {
274 
275  // 4 point are required
276  if(n<4)
277  {
278  vpTRACE("there must be at least 4 points in the both images\n") ;
279  throw ;
280  }
281 
282  try{
283  vpMatrix A(2*n,9);
284  vpColVector h(9);
285  vpColVector D(9);
286  vpMatrix V(9,9);
287  unsigned int i, j;
288 
289  // We need here to compute the SVD on a (n*2)*9 matrix (where n is
290  // the number of points). if n == 4, the matrix has more columns
291  // than rows. This kind of matrix is not supported by GSL for
292  // SVD. The solution is to add an extra line with zeros
293  if (n == 4)
294  A.resize(2*n+1,9);
295 
296  // build matrix A
297  for(i=0; i<n;i++)
298  {
299 
300  A[2*i][0]=0;
301  A[2*i][1]=0;
302  A[2*i][2]=0;
303  A[2*i][3]=-xb[i] ;
304  A[2*i][4]=-yb[i] ;
305  A[2*i][5]=-1;
306  A[2*i][6]=xb[i]*ya[i] ;
307  A[2*i][7]=yb[i]*ya[i];
308  A[2*i][8]=ya[i];
309 
310 
311  A[2*i+1][0]=xb[i] ;
312  A[2*i+1][1]=yb[i] ;
313  A[2*i+1][2]=1;
314  A[2*i+1][3]=0;
315  A[2*i+1][4]=0;
316  A[2*i+1][5]=0;
317  A[2*i+1][6]=-xb[i]*xa[i];
318  A[2*i+1][7]=-yb[i]*xa[i];
319  A[2*i+1][8]=-xa[i] ;
320  }
321 
322  // Add an extra line with zero.
323  if (n == 4) {
324  for (int i=0; i < 9; i ++) {
325  A[2*n][i] = 0;
326  }
327  }
328 
329  // solve Ah = 0
330  // SVD Decomposition A = UDV^T (destructive wrt A)
331  A.svd(D,V);
332 
333  // on en profite pour effectuer un controle sur le rang de la matrice :
334  // pas plus de 2 valeurs singulières quasi=0
335  int rank=0;
336  for(i = 0; i<9;i++) if(D[i]>1e-7) rank++;
337  if(rank <7)
338  {
339  vpTRACE(" Rank is : %d, should be 8", rank);
341  "\n\t\t Matrix rank is deficient")) ;
342  }
343  //h = is the column of V associated with the smallest singular value of A
344 
345  // since we are not sure that the svd implemented sort the
346  // singular value... we seek for the smallest
347  double smallestSv = 1e30 ;
348  unsigned int indexSmallestSv = 0 ;
349  for (i=0 ; i < 9 ; i++)
350  if ((D[i] < smallestSv) ){ smallestSv = D[i] ;indexSmallestSv = i ; }
351 
352 
353  h=V.column(indexSmallestSv+1);
354 
355  // build the homography
356  for(i =0;i<3;i++)
357  {
358  for(j=0;j<3;j++)
359  aHb[i][j]=h[3*i+j];
360  }
361 
362  }
363  catch(vpMatrixException me)
364  {
365  vpTRACE("Matrix Exception ") ;
366  throw(me) ;
367  }
368  catch(vpException me)
369  {
370  vpERROR_TRACE("caught another error") ;
371  std::cout <<std::endl << me << std::endl ;
372  throw(me) ;
373  }
374 
375 }
Definition of the vpMatrix class.
Definition: vpMatrix.h:96
void resize(const unsigned int nrows, const unsigned int ncols, const bool nullify=true)
Definition: vpMatrix.cpp:174
#define vpERROR_TRACE
Definition: vpDebug.h:379
#define vpTRACE
Definition: vpDebug.h:401
error that can be emited by ViSP classes.
Definition: vpException.h:75
static void HartleyDenormalization(vpHomography &aHbn, vpHomography &aHb, double xg1, double yg1, double coef1, double xg2, double yg2, double coef2)
vpMatrix()
Basic constructor.
Definition: vpMatrix.cpp:111
vpColVector column(const unsigned int j)
Column extraction.
Definition: vpMatrix.cpp:2240
This class aims to compute the homography wrt.two images.
Definition: vpHomography.h:173
void setIdentity(const double &val=1.0)
Definition: vpMatrix.cpp:1110
void svd(vpColVector &w, vpMatrix &v)
Definition: vpMatrix.cpp:1702
static double sqr(double x)
Definition: vpMath.h:106
static void DLT(unsigned int n, double *xb, double *yb, double *xa, double *ya, vpHomography &aHb)
Computes the homography matrix wrt. the data using the DLT (Direct Linear Transform) algorithm...
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
error that can be emited by the vpMatrix class and its derivates
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1812
static void HartleyDLT(unsigned int n, double *xb, double *yb, double *xa, double *ya, vpHomography &aHb)
Computes the homography matrix using the DLT (Direct Linear Transform) algorithm on normalized data...
static void HartleyNormalization(unsigned int n, double *x, double *y, double *xn, double *yn, double &xg, double &yg, double &coef)