bazar  1.3.1
CamAugmentation.cpp
Go to the documentation of this file.
1 #include <assert.h>
2 #include <cv.h>
3 #include <highgui.h>
4 #include "CamAugmentation.h"
6 
19 extern void twomat_gradian (
20  double fx,
21  double fy,
22  double cx,
23  double cy,
24  double R_matrix[3][3],
25  double Rx,
26  double Ry,
27  double Rz,
28  CvMat *R_jacobian,
29  double S_matrix[3][3],
30  double Sx,
31  double Sy,
32  double Sz,
33  CvMat *S_jacobian,
34  double p[3],
35  double cgret[24],
36  double uv[2] );
37 
45 extern void showmatrix_ch(CvMat &M);
46 
53 extern void showmatrix(CvMat &M);
54 
62 extern void showmatrix(CvMat &M,const char *header);
63 
71 extern void showmatrix(const char *header,CvMat &M);
72 
78 extern void showmatrix_file(CvMat &M,FILE *stream);
79 
81  v_homography_r_t = cvCreateMat( 3, 4, CV_64FC1 );
82  v_homography_r_t_jacobian = cvCreateMat( 3, 9, CV_64FC1 );
83 }
84 
86  ClearAll();
87  cvReleaseMat(&v_homography_r_t);
88  cvReleaseMat(&v_homography_r_t_jacobian);
89 }
90 
91 void CamAugmentation::ReleaseOptimalCameraStructure(){
92  for( int i = 0; i < (int)s_optimal.v_camera_c.size(); i++ ) cvReleaseMat(&s_optimal.v_camera_c[i]);
93  s_optimal.v_camera_c.clear();
94  for( int i = 0; i < (int)s_optimal.v_camera_r_t.size(); i++ ) cvReleaseMat(&s_optimal.v_camera_r_t[i]);
95  s_optimal.v_camera_r_t.clear();
96  for( int i = 0; i < (int)s_optimal.v_camera_r_t_jacobian.size(); i++ ) cvReleaseMat(&s_optimal.v_camera_r_t_jacobian[i]);
97  s_optimal.v_camera_r_t_jacobian.clear();
98 }
99 
101  for( int i = 0; i < (int)v_homography.size(); i++ )
102  delete v_homography[i];
103  v_homography.clear();
104  ReleaseOptimalCameraStructure();
105  v_opt_param.clear();
106 }
107 
108 bool CamAugmentation::LoadOptimalStructureFromFile( char* cam_c_file, char *cam_rt_file ){
109  FILE *stream;
110 
111  // Load camera calibration matrices into optimal structure:
112  if( (stream = fopen( cam_c_file, "r+t" )) != NULL ){
113  int num,width,height;
114  while( fscanf( stream, "no: %i\nwidth: %i\nheight: %i\n", &num, &width, &height ) != EOF ){
115  float h;
116  CvMat* m = cvCreateMat( 3, 3, CV_64FC1 );
117  for(int i=0; i < 3; i++)
118  for(int j=0; j < 3; j++) {
119  fscanf( stream, "%f", &h );
120  cvmSet(m,i,j,h);
121  }
122  fscanf( stream, "\n" );
123  s_optimal.v_camera_width.push_back( width );
124  s_optimal.v_camera_height.push_back( height );
125  s_optimal.v_camera_c.push_back( m );
126  printf( "Calibration matrix %i loaded!\n", num );
127  }
128  fclose( stream );
129  } else {
130  printf( "WARNING: Could not load matrices from file %s.", cam_c_file );
131  return false;
132  }
133 
134  // Load camera rotation-translation matrices into optimal structure:
135  if( (stream = fopen( cam_rt_file, "r+t" )) != NULL ){
136  int num,width,height;
137  while( fscanf( stream, "no: %i\nwidth: %i\nheight: %i\n", &num, &width, &height ) != EOF ){
138  float h;
139  CvMat* m = cvCreateMat( 3, 4, CV_64FC1 );
140  for(int i=0; i < 3; i++)
141  for(int j=0; j < 4; j++) {
142  fscanf( stream, "%f", &h );
143  cvmSet(m,i,j,h);
144  }
145  fscanf( stream, "\n" );
146  s_optimal.v_camera_r_t.push_back( m );
147 
148  // Create jacobian:
149  CvMat* R = cvCreateMat( 3, 3, CV_64FC1 );
150  CvMat* r = cvCreateMat( 3, 1, CV_64FC1 );
151  CvMat* j = cvCreateMat( 3, 9, CV_64FC1 );
153  cvRodrigues2( R, r, j );
154  s_optimal.v_camera_r_t_jacobian.push_back( j );
155  printf( "Rotation-Translation matrix %i loaded and jacobian created!\n", num );
156  }
157  fclose( stream );
158  } else {
159  printf( "WARNING: Could not load matrices from file %s.", cam_rt_file );
160  return false;
161  }
162  return true;
163 }
164 
166  // Create new, empty homography structure:
167  s_struct_homography *s_homography = new s_struct_homography();
168 
169  // Push the homography to the vector:
170  v_homography.push_back( s_homography );
171 }
172 
173 void CamAugmentation::AddHomography( std::vector<CamCalibration::s_struct_points> p, CvMat* ready ){
174  // Create new, empty homography structure:
175  s_struct_homography *s_homography = new s_struct_homography();
176 
177  // Copy points and homography:
178  s_homography->v_point = p;
179  s_homography->m_homography = new homography();
180  cvCopy(ready, s_homography->m_homography);
181 
182  // Push the homography to the vector:
183  v_homography.push_back( s_homography );
184 }
185 
186 CvMat* CamAugmentation::InverseCalibrationMatrix( CvMat *in ){
187  if( cvmGet( in, 1, 1 ) != 0 ){
188  CvMat* out = cvCreateMat( 3, 3, CV_64FC1 );
189  double tau = cvmGet( in, 0, 0 )/cvmGet( in, 1, 1 );
190  double f = cvmGet( in, 1, 1 );
191  double u0 = cvmGet( in, 0, 2 );
192  double v0 = cvmGet( in, 1, 2 );
193  cvmSet( out, 0, 0, 1.00/(tau*f) );
194  cvmSet( out, 0, 1, 0.00 );
195  cvmSet( out, 0, 2, -(u0)/(tau*f) );
196  cvmSet( out, 1, 0, 0.00 );
197  cvmSet( out, 1, 1, 1.00/f );
198  cvmSet( out, 1, 2, -(v0)/f );
199  cvmSet( out, 2, 0, 0.00 );
200  cvmSet( out, 2, 1, 0.00 );
201  cvmSet( out, 2, 2, 1.00 );
202  return out;
203  } else
204  return NULL;
205 }
206 
207 bool CamAugmentation::CreateHomographyRotationTranslationMatrix( int c ){
208  int i;
209 
210  // Get pointer to homography:
211  CvMat* m_homography = v_homography[c]->m_homography;
212 
213  if( m_homography ){
214 
215  // Vectors holding columns of H and R:
216  double a_H1[3];
217  CvMat m_H1 = cvMat( 3, 1, CV_64FC1, a_H1 );
218  for( i = 0; i < 3; i++ ) cvmSet( &m_H1, i, 0, cvmGet( m_homography, i, 0 ) );
219 
220  double a_H2[3];
221  CvMat m_H2 = cvMat( 3, 1, CV_64FC1, a_H2 );
222  for( i = 0; i < 3; i++ ) cvmSet( &m_H2, i, 0, cvmGet( m_homography, i, 1 ) );
223 
224  double a_H3[3];
225  CvMat m_H3 = cvMat( 3, 1, CV_64FC1, a_H3 );
226  for( i = 0; i < 3; i++ ) cvmSet( &m_H3, i, 0, cvmGet( m_homography, i, 2 ) );
227 
228  double a_CinvH1[3];
229  CvMat m_CinvH1 = cvMat( 3, 1, CV_64FC1, a_CinvH1 );
230 
231  double a_R1[3];
232  CvMat m_R1 = cvMat( 3, 1, CV_64FC1, a_R1 );
233 
234  double a_R2[3];
235  CvMat m_R2 = cvMat( 3, 1, CV_64FC1, a_R2 );
236 
237  double a_R3[3];
238  CvMat m_R3 = cvMat( 3, 1, CV_64FC1, a_R3 );
239 
240  // The rotation matrix:
241  double a_R[9];
242  CvMat m_R = cvMat( 3, 3, CV_64FC1, a_R );
243 
244  // The translation vector:
245  double a_T[3];
246  CvMat m_T = cvMat( 3, 1, CV_64FC1, a_T );
247 
249  // Create inverse calibration matrix:
250  CvMat* m_Cinv = InverseCalibrationMatrix( s_optimal.v_camera_c[c] );
251 
252  // Create norming factor lambda:
253  cvGEMM( m_Cinv, &m_H1, 1, NULL, 0, &m_CinvH1, 0 );
254 
255  // Search next orthonormal matrix:
256  if( cvNorm( &m_CinvH1, NULL, CV_L2, NULL ) != 0 ){
257  double lambda = 1.00/cvNorm( &m_CinvH1, NULL, CV_L2, NULL );
258 
259  // Create normalized R1 & R2:
260  cvGEMM( m_Cinv, &m_H1, lambda, NULL, 0, &m_R1, 0 );
261  cvGEMM( m_Cinv, &m_H2, lambda, NULL, 0, &m_R2, 0 );
262 
263  // Get R3 orthonormal to R1 and R2:
264  cvCrossProduct( &m_R1, &m_R2, &m_R3 );
265 
266  // Put the rotation column vectors in the rotation matrix:
267  for( i = 0; i < 3; i++ ){
268  cvmSet( &m_R, i, 0, cvmGet( &m_R1, i, 0 ) );
269  cvmSet( &m_R, i, 1, cvmGet( &m_R2, i, 0 ) );
270  cvmSet( &m_R, i, 2, cvmGet( &m_R3, i, 0 ) );
271  }
272 
273  // Calculate Translation Vector T (- because of its definition):
274  cvGEMM( m_Cinv, &m_H3, -lambda, NULL, 0, &m_T, 0 );
275 
276  // Transformation of R into - in Frobenius sense - next orthonormal matrix:
277  double a_W[9]; CvMat m_W = cvMat( 3, 3, CV_64FC1, a_W );
278  double a_U[9]; CvMat m_U = cvMat( 3, 3, CV_64FC1, a_U );
279  double a_Vt[9]; CvMat m_Vt = cvMat( 3, 3, CV_64FC1, a_Vt );
280  cvSVD( &m_R, &m_W, &m_U, &m_Vt, CV_SVD_MODIFY_A | CV_SVD_V_T );
281  cvMatMul( &m_U, &m_Vt, &m_R );
282 
283 
284  // Put the rotation matrix and the translation vector together:
285  double a_view_to_cam[12];
286  CvMat m_view_to_cam = cvMat( 3, 4, CV_64FC1, a_view_to_cam );
287  CamCalibration::ComposeRotationTranslationTo3x4Matrix( &m_view_to_cam, &m_R, &m_T );
288 
289  // Transfer to global reference coordinate system:
290  double a_cam_inv[12];
291  CvMat m_cam_inv = cvMat( 3, 4, CV_64FC1, a_cam_inv );
292  CamCalibration::Mat3x4Inverse( s_optimal.v_camera_r_t[c], &m_cam_inv );
293  CamCalibration::Mat3x4Mul( &m_cam_inv, &m_view_to_cam, v_homography_r_t );
294 
295  return true;
296  }
297  }
298  return false;
299 }
300 
301 bool CamAugmentation::EstimateHomographyRT(){
302 
303  // Search for first existing homography:
304  for( int c = 0; c < (int)v_homography.size(); c++ ){
305 
306  // If homography and corresponding camera exists, yipiee:
307  if( v_homography[c]->m_homography && (int)s_optimal.v_camera_c.size() > c ){
308  return CreateHomographyRotationTranslationMatrix( c );
309  }
310  }
311  return false;
312 }
313 
314 int CamAugmentation::GetObservationNumber(){
315  int num = 0;
316  for( int c = 0; c < (int)v_homography.size(); c++ ){
317  num += (int)v_homography[c]->v_point.size();
318  }
319  return num*2; //TODO: ohne 2 mit neuem LM-optimizer!
320 }
321 
322 void CamAugmentation::updateCB( double *params, void **user_data ){
323  CamAugmentation *cam = (CamAugmentation*) user_data[0];
324 
325  // Pass parameters to global parameter array:
326  int parameter_number = 6;
327  for( int i = 0; i < parameter_number; i++ )
328  cam->v_opt_param[i] = params[i];
329 
330  // Update the structure:
331  cam->SetParameterSet();
332 }
333 
334 void CamAugmentation::GetParameterSet(){
335 
336  // Clear old vector:
337  v_opt_param.clear();
338 
339  double a_R[9]; CvMat m_R = cvMat( 3, 3, CV_64FC1, a_R );
340  double a_r[3]; CvMat m_r = cvMat( 3, 1, CV_64FC1, a_r );
341  double a_T[3]; CvMat m_T = cvMat( 3, 1, CV_64FC1, a_T );
342 
343  // Pack Homography RT matrix:
344  CamCalibration::ExtractRotationTranslationFrom3x4Matrix( v_homography_r_t, &m_R, &m_T);
345  v_opt_param.push_back( -cvmGet( &m_T, 0, 0 ) );
346  v_opt_param.push_back( -cvmGet( &m_T, 1, 0 ) );
347  v_opt_param.push_back( -cvmGet( &m_T, 2, 0 ) );
348  cvRodrigues2( &m_R, &m_r, v_homography_r_t_jacobian );
349  v_opt_param.push_back( cvmGet( &m_r, 0, 0 ) );
350  v_opt_param.push_back( cvmGet( &m_r, 1, 0 ) );
351  v_opt_param.push_back( cvmGet( &m_r, 2, 0 ) );
352 }
353 
354 void CamAugmentation::SetParameterSet(){
355 
356  double a_R[9]; CvMat m_R = cvMat( 3, 3, CV_64FC1, a_R );
357  double a_r[3]; CvMat m_r = cvMat( 3, 1, CV_64FC1, a_r );
358  double a_T[3]; CvMat m_T = cvMat( 3, 1, CV_64FC1, a_T );
359 
360  // Unpack Homography RT matrix:
361  cvmSet( &m_T, 0, 0, -v_opt_param[0] );
362  cvmSet( &m_T, 1, 0, -v_opt_param[1] );
363  cvmSet( &m_T, 2, 0, -v_opt_param[2] );
364  cvmSet( &m_r, 0, 0, v_opt_param[3] );
365  cvmSet( &m_r, 1, 0, v_opt_param[4] );
366  cvmSet( &m_r, 2, 0, v_opt_param[5] );
367  cvRodrigues2( &m_r, &m_R, v_homography_r_t_jacobian );
368  CamCalibration::ComposeRotationTranslationTo3x4Matrix( v_homography_r_t, &m_R, &m_T);
369 }
370 
372 {
373  double target[2];
374  int cam;
375  int point;
377  b = target;
378  }
379  virtual int get_nb_measures() const { return 2; };
380  virtual void eval_func(const double *params, double *f, double *J, void **user_data) const;
381 };
382 
383 //void CamAugmentation::projFunc( double *x, double *params, int na, double *f, double *grad, int *ind, LsqData *Data ){
384 void PoseObs::eval_func(const double *params, double *f, double *J, void **user_data) const {
385  CamAugmentation *cam = (CamAugmentation*) *user_data;
386 
387  // Unpack arguments:
388  int c = this->cam;
389 
390  // Project the point (CRTp) and set f:
391  double a_p[4]; double a_p3[3]; double a_p4[3];
392  double a_RT[12]; CvMat m_RT = cvMat( 3, 4, CV_64FC1, a_RT );
393  a_p[0] = cam->v_homography[c]->v_point[point].x; a_p[2] = 0;
394  a_p[1] = cam->v_homography[c]->v_point[point].y; a_p[3] = 1;
395  CvMat m_p = cvMat( 4, 1, CV_64FC1, a_p ); // plane point (flat)
396  CvMat m_p3 = cvMat( 3, 1, CV_64FC1, a_p3 ); // eye point 2
397  CvMat m_p4 = cvMat( 3, 1, CV_64FC1, a_p4 ); // image point
398  CamCalibration::Mat3x4Mul( cam->s_optimal.v_camera_r_t[c], cam->v_homography_r_t, &m_RT );
399  cvMatMul( &m_RT, &m_p, &m_p3 );
400  cvMatMul( cam->s_optimal.v_camera_c[c], &m_p3, &m_p4 );
402  f[0] = cvmGet( &m_p4, 0, 0 );
403  f[1] = cvmGet( &m_p4, 1, 0 );
404 
405  int gc = 0;
406  if( J ){
407 
408  double *grad0 = J;
409  double *grad1 = J+6;
410  double a_R1[9]; CvMat m_R1 = cvMat( 3, 3, CV_64FC1, a_R1 );
411  double a_T1[3]; CvMat m_T1 = cvMat( 3, 1, CV_64FC1, a_T1 );
412  double a_R2[9]; CvMat m_R2 = cvMat( 3, 3, CV_64FC1, a_R2 );
413  double a_T2[3]; CvMat m_T2 = cvMat( 3, 1, CV_64FC1, a_T2 );
414  CamCalibration::ExtractRotationTranslationFrom3x4Matrix( cam->s_optimal.v_camera_r_t[c], &m_R1, &m_T1 );
415  CamCalibration::ExtractRotationTranslationFrom3x4Matrix( cam->v_homography_r_t, &m_R2, &m_T2 );
416 
417  double R1[3][3];
418  for( int i = 0; i < 3; i++ )
419  for( int j = 0; j < 3; j++ )
420  R1[i][j] = cvmGet( &m_R1, i, j );
421 
422  double R2[3][3];
423  for( int i = 0; i < 3; i++ )
424  for( int j = 0; j < 3; j++ )
425  R2[i][j] = cvmGet( &m_R2, i, j );
426 
427  double cgret[24];
428  double uv[2];
429 
430  twomat_gradian ( cvmGet( cam->s_optimal.v_camera_c[c], 0, 0 ),
431  cvmGet( cam->s_optimal.v_camera_c[c], 1, 1 ),
432  cvmGet( cam->s_optimal.v_camera_c[c], 0, 2 ),
433  cvmGet( cam->s_optimal.v_camera_c[c], 1, 2 ),
434  R1,
435  -cvmGet( &m_T1, 0, 0 ),
436  -cvmGet( &m_T1, 1, 0 ),
437  -cvmGet( &m_T1, 2, 0 ),
438  cam->s_optimal.v_camera_r_t_jacobian[c],
439  R2,
440  -cvmGet( &m_T2, 0, 0 ),
441  -cvmGet( &m_T2, 1, 0 ),
442  -cvmGet( &m_T2, 2, 0 ),
443  cam->v_homography_r_t_jacobian,
444  a_p,
445  cgret, uv );
446 
447  gc=0;
448  for( int i = 0; i < 3; i++ )
449  grad0[gc++] = cgret[6+i+3];
450  for( int i = 0; i < 3; i++ )
451  grad0[gc++] = cgret[6+i];
452  gc=0;
453  for( int i = 0; i < 3; i++ )
454  grad1[gc++] = cgret[12+6+i+3];
455  for( int i = 0; i < 3; i++ )
456  grad1[gc++] = cgret[12+6+i];
457  }
458 }
459 
460 bool CamAugmentation::OptimizeCurrentView( int iter, double eps ){
461 
462  // Get number parameters and observations:
463  int parameter_number = 6;
464  int observation_number = GetObservationNumber();
465 
466  ls_minimizer2 minimizer(parameter_number);
467  minimizer.set_user_data(0, this);
468  minimizer.set_state_change_callback(updateCB);
469  minimizer.lm_set_max_iterations(iter);
470 
471  // Feed with initial parameters:
472  GetParameterSet();
473  //FillLsqParams( lsqData, &v_opt_param[0], 0, 0 );
474 
475  // Add the observations for ...
476  int test = 0;
477  for( int c = 0; c < (int)v_homography.size(); c++ ) // ... cameras
478  if( v_homography[c]->m_homography ){
479  int points = (int)v_homography[c]->v_point.size();
480  for( int point = 0; point < points; point++ ){ // ... points
481  PoseObs *o = new PoseObs();
482  o->cam = c;
483  o->point = point;
484  o->target[0] = v_homography[c]->v_point[point].u;
485  o->target[1] = v_homography[c]->v_point[point].v;
486  minimizer.add_observation(o, true, false);
487  }
488  }
489 
490  minimizer.minimize_using_levenberg_marquardt_from(&v_opt_param[0]);
491 
492  void *ptr = this;
493  updateCB(minimizer.state, &ptr);
494 
495  return true;
496 }
497 
498 bool CamAugmentation::Accomodate( int iter, double eps ){
499  if( EstimateHomographyRT() ){
500  return OptimizeCurrentView( iter, eps );
501  } else
502  return false;
503 }
504 
506  for( int i = 0; i < (int)v_homography.size(); i++ )
507  delete v_homography[i];
508  v_homography.clear();
509 }
510 
512 
513  // If enough cameras mounted (calibrated):
514  if( s_optimal.v_camera_c.size() > (unsigned)c ){
515 
516  // If all necessary matrices exist:
517  if( s_optimal.v_camera_c[c] && s_optimal.v_camera_r_t[c] && v_homography_r_t ){
518  CvMat* m_proj = cvCreateMat( 3, 4, CV_64FC1 );
519  cvMatMul( s_optimal.v_camera_c[c], s_optimal.v_camera_r_t[c], m_proj );
520  CamCalibration::Mat3x4Mul( m_proj, v_homography_r_t, m_proj );
521  return m_proj;
522  } else
523  return NULL;
524  } else
525  return NULL;
526 }
527 
529 
530  // If enough cameras mounted (calibrated):
531  if( s_optimal.v_camera_c.size() > (unsigned)c ){
532 
533  // If all necessary matrices exist:
534  if( s_optimal.v_camera_c[c] && s_optimal.v_camera_r_t[c] ){
535  CvMat* m_proj = cvCreateMat( 3, 4, CV_64FC1 );
536  cvMatMul( s_optimal.v_camera_c[c], s_optimal.v_camera_r_t[c], m_proj );
537  return m_proj;
538  } else
539  return NULL;
540  } else
541  return NULL;
542 }
543 
545 
546  // If enough cameras mounted (calibrated):
547  if( s_optimal.v_camera_c.size() > (unsigned)c ){
548 
549  if(s_optimal.v_camera_r_t[c])
550  return cvCloneMat(s_optimal.v_camera_r_t[c]);
551  else
552  return NULL;
553  } else
554  return NULL;
555 }
556 
558  if (v_homography_r_t)
559  return cvCloneMat(v_homography_r_t);
560  return 0;
561 }