ViSP  2.6.2
vpHomographyDLT.cpp
1 /****************************************************************************
2  *
3  * $Id: vpHomographyDLT.cpp 3530 2012-01-03 10:52:12Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2012 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 
52 #include <cmath> // std::fabs
53 #include <limits> // numeric_limits
54 
55 void
56 vpHomography::HartleyNormalization(unsigned int n,
57  double *x, double *y,
58  double *xn, double *yn,
59  double &xg, double &yg,
60  double &coef)
61 {
62  unsigned int i;
63  xg = 0 ;
64  yg = 0 ;
65 
66  for (i =0 ; i < n ; i++)
67  {
68  xg += x[i] ;
69  yg += y[i] ;
70  }
71  xg /= n ;
72  yg /= n ;
73 
74  //Changement d'origine : le centre de gravité doit correspondre
75  // à l'origine des coordonnées
76  double distance=0;
77  for(i=0; i<n;i++)
78  {
79  double xni=x[i]-xg;
80  double yni=y[i]-yg;
81  xn[i] = xni ;
82  yn[i] = yni ;
83  distance+=sqrt(vpMath::sqr(xni)+vpMath::sqr(yni));
84  }//for translation sur tous les points
85 
86  //Changement d'échelle
87  distance/=n;
88  //calcul du coef de changement d'échelle
89  //if(distance ==0)
90  if(std::fabs(distance) <= std::numeric_limits<double>::epsilon())
91  coef=1;
92  else
93  coef=sqrt(2.0)/distance;
94 
95  for(i=0; i<n;i++)
96  {
97  xn[i] *= coef;
98  yn[i] *= coef;
99  }
100 
101 }
102 
103 //---------------------------------------------------------------------------------------
104 
105 void
106 vpHomography::HartleyDenormalization(vpHomography &aHbn,
107  vpHomography &aHb,
108  double xg1, double yg1, double coef1,
109  double xg2, double yg2, double coef2 )
110 {
111 
112  //calcul des transformations à appliquer sur M_norm pour obtenir M
113  //en fonction des deux normalisations effectuées au début sur
114  //les points: aHb = T2^ aHbn T1
115  vpMatrix T1(3,3);
116  vpMatrix T2(3,3);
117  vpMatrix T2T(3,3);
118 
119  T1.setIdentity();
120  T2.setIdentity();
121  T2T.setIdentity();
122 
123  T1[0][0]=T1[1][1]=coef1;
124  T1[0][2]=-coef1*xg1 ;
125  T1[1][2]=-coef1*yg1 ;
126 
127  T2[0][0]=T2[1][1]=coef2;
128  T2[0][2]=-coef2*xg2 ;
129  T2[1][2]=-coef2*yg2 ;
130 
131 
132  T2T=T2.pseudoInverse(1e-16) ;
133 
134  vpMatrix maHb=T2T*(vpMatrix)aHbn*T1;
135 
136  for (unsigned int i=0 ; i < 3 ; i++)
137  for (unsigned int j=0 ; j < 3 ; j++) aHb[i][j] = maHb[i][j] ;
138 
139 }
140 
141 
153 void
155  double *xb, double *yb,
156  double *xa, double *ya ,
157  vpHomography &aHb)
158 {
159  try{
160  //initialise les données initiales
161  // code_retour =InitialData(n, p1,p2);
162 
163  // normalize points
164  double *xbn;
165  double *ybn;
166  xbn = new double [n];
167  ybn = new double [n];
168 
169  double xg1, yg1, coef1 ;
170  vpHomography::HartleyNormalization(n,
171  xb,yb,
172  xbn,ybn,
173  xg1, yg1,coef1);
174 
175  double *xan;
176  double *yan;
177  xan = new double [n];
178  yan = new double [n];
179 
180  double xg2, yg2, coef2 ;
181  vpHomography::HartleyNormalization(n,
182  xa,ya,
183  xan,yan,
184  xg2, yg2,coef2);
185 
186  vpHomography aHbn ;
187  //compute the homography using the DLT from normalized data
188  vpHomography::DLT(n,xbn,ybn,xan,yan,aHbn);
189 
190  //H dénormalisée
191  vpHomography::HartleyDenormalization(aHbn,aHb,xg1,yg1,coef1,xg2,yg2, coef2);
192 
193  delete [] xbn;
194  delete [] ybn;
195  delete [] xan;
196  delete [] yan;
197 
198  }
199  catch(...)
200  {
201  vpTRACE(" ") ;
202  throw ;
203  }
204 }
205 
206 
262 void vpHomography::DLT(unsigned int n,
263  double *xb, double *yb,
264  double *xa, double *ya ,
265  vpHomography &aHb)
266 {
267 
268  // 4 point are required
269  if(n<4)
270  {
271  vpTRACE("there must be at least 4 points in the both images\n") ;
272  throw ;
273  }
274 
275  try{
276  vpMatrix A(2*n,9);
277  vpColVector h(9);
278  vpColVector D(9);
279  vpMatrix V(9,9);
280  unsigned int i, j;
281 
282  // We need here to compute the SVD on a (n*2)*9 matrix (where n is
283  // the number of points). if n == 4, the matrix has more columns
284  // than rows. This kind of matrix is not supported by GSL for
285  // SVD. The solution is to add an extra line with zeros
286  if (n == 4)
287  A.resize(2*n+1,9);
288 
289  // build matrix A
290  for(i=0; i<n;i++)
291  {
292 
293  A[2*i][0]=0;
294  A[2*i][1]=0;
295  A[2*i][2]=0;
296  A[2*i][3]=-xb[i] ;
297  A[2*i][4]=-yb[i] ;
298  A[2*i][5]=-1;
299  A[2*i][6]=xb[i]*ya[i] ;
300  A[2*i][7]=yb[i]*ya[i];
301  A[2*i][8]=ya[i];
302 
303 
304  A[2*i+1][0]=xb[i] ;
305  A[2*i+1][1]=yb[i] ;
306  A[2*i+1][2]=1;
307  A[2*i+1][3]=0;
308  A[2*i+1][4]=0;
309  A[2*i+1][5]=0;
310  A[2*i+1][6]=-xb[i]*xa[i];
311  A[2*i+1][7]=-yb[i]*xa[i];
312  A[2*i+1][8]=-xa[i] ;
313  }
314 
315  // Add an extra line with zero.
316  if (n == 4) {
317  for (int i=0; i < 9; i ++) {
318  A[2*n][i] = 0;
319  }
320  }
321 
322  // solve Ah = 0
323  // SVD Decomposition A = UDV^T (destructive wrt A)
324  A.svd(D,V);
325 
326  // on en profite pour effectuer un controle sur le rang de la matrice :
327  // pas plus de 2 valeurs singulières quasi=0
328  int rank=0;
329  for(i = 0; i<9;i++) if(D[i]>1e-7) rank++;
330  if(rank <7)
331  {
332  vpTRACE(" le rang est de : %d, shoud be 8", rank);
333  throw ;
334  }
335  //h = is the column of V associated with the smallest singular value of A
336 
337  // since we are not sure that the svd implemented sort the
338  // singular value... we seek for the smallest
339  double smallestSv = 1e30 ;
340  unsigned int indexSmallestSv = 0 ;
341  for (i=0 ; i < 9 ; i++)
342  if ((D[i] < smallestSv) ){ smallestSv = D[i] ;indexSmallestSv = i ; }
343 
344 
345  h=V.column(indexSmallestSv+1);
346 
347  // build the homography
348  for(i =0;i<3;i++)
349  {
350  for(j=0;j<3;j++)
351  aHb[i][j]=h[3*i+j];
352  }
353 
354  }
355  catch(...)
356  {
357  vpTRACE(" ") ;
358  throw ;
359  }
360 }
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 vpTRACE
Definition: vpDebug.h:401
vpMatrix()
Basic constructor.
Definition: vpMatrix.cpp:111
vpColVector column(const unsigned int j)
Column extraction.
Definition: vpMatrix.cpp:2238
This class aims to compute the homography wrt.two images.
Definition: vpHomography.h:174
void svd(vpColVector &w, vpMatrix &v)
Definition: vpMatrix.cpp:1700
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
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...