bazar  1.3.1
CamCalibration.cpp
Go to the documentation of this file.
1 #include <assert.h>
2 #include <cv.h>
3 #include <highgui.h>
4 #include "CamCalibration.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 
80 int imin(int a, int b) {
81  return (a<b ? a:b);
82 }
83 
85  m_CH = NULL;
86  srand( (unsigned)time(NULL) );
87  printf("Welcome to AMCC!\n");
88  printf("================\n\n");
89 }
90 
92  ClearAll();
93 }
94 
96  if( m_CH ) cvReleaseMat( &m_CH );
97  for( int i = 0; i < (int)v_camera.size(); i++ )
98  delete v_camera[i];
99  v_camera.clear();
100  ReleaseOptimalCameraStructure();
101  v_opt_param.clear();
102  if( m_CH ) cvReleaseMat( &m_CH ); m_CH = NULL;
103 }
104 
105 void CamCalibration::AddCamera( int width, int height ){
106  v_camera.push_back( new s_struct_camera( width, height ) );
107 }
108 
110  // Check if camera is allocated:
111  if( (int)v_camera.size() <= c ){
112  printf("ERROR: Homography has not been added: Camera %i does not exist!\n",c);
113  return false;
114  }
115 
116  // Create new, empty homography structure:
117  s_struct_homography *s_homography = new s_struct_homography();
118 
119  // Push the homography to the vector:
120  v_camera[c]->v_homography.push_back( s_homography );
121 
122  return true;
123 }
124 
125 bool CamCalibration::AddHomography( int c, std::vector<CamCalibration::s_struct_points> p, CvMat* ready ){
126  // Check if camera is allocated:
127  if( (int)v_camera.size() <= c ){
128  printf("ERROR: Homography has not been added because Camera %i doesn't exist!\n",c);
129  return false;
130  }
131 
132  // Create new homography structure:
133  s_struct_homography *s_homography = new s_struct_homography();
134 
135  // Allocate space:
136  s_homography->s_plane_object->px = new double[p.size()];
137  s_homography->s_plane_object->py = new double[p.size()];
138 
139  // Store m_pp and (px,py) in structure:
140  for( unsigned i = 0; i < p.size(); i++ ){
141  // printf("%f %f %f %f\n", p[i].x, p[i].y, p[i].u, p[i].v);
142  s_homography->s_plane_object->px[i] = p[i].x;
143  s_homography->s_plane_object->py[i] = p[i].y;
144  CvMat *plane_point = cvCreateMat( 3, 1, CV_64FC1 );
145  cvmSet( plane_point, 0, 0, p[i].u );
146  cvmSet( plane_point, 1, 0, p[i].v );
147  cvmSet( plane_point, 2, 0, 1 );
148  s_homography->s_plane_object->v_m_pp.push_back( plane_point );
149  }
150 
151  // Tell point number:
152  s_homography->s_plane_object->p = p.size();
153 
154  // Push the homography to the vector:
155  v_camera[c]->v_homography.push_back( s_homography );
156 
157  // Create homography from m_pp and (px,py) in structure:
158  CreateWorldPlaneHomography( c, (int)v_camera[c]->v_homography.size()-1, ready );
159  return true;
160 }
161 
163  FILE *stream;
164  char buffer[1000];
165  int length;
166  if( (stream = fopen( file_name, "w+t" )) != NULL ){
167  for( int c = 0; c < (int)v_camera.size(); c++ ){
168  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ ){
169  if( v_camera[c]->v_homography[h]->m_homography ){
170  // Camera & Homography & Point number:
171  s_struct_plane* s_plane_object = v_camera[c]->v_homography[h]->s_plane_object;
172  int p = (*s_plane_object).p;
173  length = sprintf(buffer,"%i %i %i %i %i\n",c,h,p,v_camera[c]->w,v_camera[c]->h);
174  fwrite( buffer, sizeof(char), length, stream );
175  // Points:
176  for( int i = 0; i < p; i++ ){
177  double x = (*s_plane_object).px[i];
178  double y = (*s_plane_object).py[i];
179  double u = cvmGet( (*s_plane_object).v_m_pp[i], 0, 0 );
180  double v = cvmGet( (*s_plane_object).v_m_pp[i], 1, 0 );
181  length = sprintf(buffer,"%f %f %f %f\n",x,y,u,v);
182  fwrite( buffer, sizeof(char), length, stream );
183  }
184  // Homography:
185  homography *m_homography = v_camera[c]->v_homography[h]->m_homography;
186  for(int i=0; i < 3; i++) {
187  for(int j=0; j < 3; j++) {
188  length = sprintf(buffer,"%f ",m_homography->cvmGet(i,j));
189  fwrite( buffer, sizeof(char), length, stream );
190  }
191  length = sprintf(buffer,"\n");
192  fwrite( buffer, sizeof(char), length, stream );
193  }
194  } else {
195  length = sprintf(buffer,"%i %i 0 %i %i\n",c,h,v_camera[c]->w,v_camera[c]->h);
196  fwrite( buffer, sizeof(char), length, stream );
197  }
198  }
199  }
200  printf("\n----------------------------\n");
201  printf("Homographies stored to file!\n");
202  printf("----------------------------\n\n");
203  fclose( stream );
204  return true;
205  } else
206  return false;
207 }
208 
210  FILE *stream;
211  int curr_cam = -1;
212  if( (stream = fopen( file_name, "r+t" )) != NULL ){
213  int c,h,p,iw,ih;
214  c=-1;h=-1;p=-1;iw=-1;ih=-1;
215  while( fscanf( stream, "%i %i %i %i %i\n", &c, &h, &p, &iw, &ih ) != EOF ){
216  if( c != curr_cam ){
217  curr_cam = c;
218  AddCamera( iw, ih );
219  }
220  if( p > 0 ){
221  float x,y,u,v;
222  std::vector<CamCalibration::s_struct_points> points;
223  for( int i = 0; i < p; i++ ){
224  fscanf( stream, "%f %f %f %f\n", &x, &y, &u, &v );
225  points.push_back( CamCalibration::s_struct_points(u,v,x,y) );
226  }
227  // Homography:
228  homography* m_homography = new homography();
229  float h;
230  for(int i=0; i < 3; i++)
231  for(int j=0; j < 3; j++) {
232  fscanf( stream, "%f", &h );
233  m_homography->cvmSet(i,j,h);
234  }
235  AddHomography( c, points, m_homography );
236  } else
237  AddHomography( c );
238  }
239  fclose( stream );
240  return true;
241  } else
242  return false;
243 }
244 
245 std::vector<CamCalibration::s_struct_solution> CamCalibration::GetRandomSolution( int num ){
246  std::vector<s_struct_solution> current_solution;
247  do {
248  // Get random c and h:
249  int c,h;
250  while ((int)v_camera.size() <= (c = rand()/(RAND_MAX/(int)v_camera.size())) );
251  while ((int)v_camera[0]->v_homography.size() <= (h = rand()/(RAND_MAX/(int)v_camera[0]->v_homography.size())) );
252 
253  // Check if there is a connection:
254  if( v_camera[c]->v_homography[h]->m_homography ){
255 
256  // Check if it is already in the vector:
257  bool in_vector = false;
258  for( int i = 0; i < (int)current_solution.size(); i++ )
259  if( current_solution[i].c == c && current_solution[i].h == h )
260  in_vector = true;
261 
262  // If not already in vector, add element:
263  if( !in_vector )
264  current_solution.push_back(s_struct_solution(c,h));
265  }
266  } while( (int)current_solution.size() < num );
267  return current_solution;
268 }
269 
270 double CamCalibration::GetScreenDistance( int c, int h1, int h2 ){
271  // Initialze measure point, projected points & homographies:
272  double a_w[] = { 0, 0, 1 }; CvMat m_w = cvMat( 3, 1, CV_64FC1, a_w );
273  double a_p1[3]; CvMat m_p1 = cvMat( 3, 1, CV_64FC1, a_p1 );
274  double a_p2[3]; CvMat m_p2 = cvMat( 3, 1, CV_64FC1, a_p2 );
275  double a_h1[9]; CvMat m_h1 = cvMat( 3, 3, CV_64FC1, a_h1 );
276  double a_h2[9]; CvMat m_h2 = cvMat( 3, 3, CV_64FC1, a_h2 );
277 
278  // Copy homographies to matrices:
279  for( int i = 0; i < 3; i++ )
280  for( int j = 0; j < 3; j++ ){
281  cvmSet( &m_h1, i, j, cvmGet( v_camera[c]->v_homography[h1]->m_homography, i, j ) );
282  cvmSet( &m_h2, i, j, cvmGet( v_camera[c]->v_homography[h2]->m_homography, i, j ) );
283  }
284 
285  // Project points using the homographies:
286  cvMatMul( &m_h1, &m_w, &m_p1 ); HomogenousNormalizeVector( &m_p1 );
287  cvMatMul( &m_h2, &m_w, &m_p2 ); HomogenousNormalizeVector( &m_p2 );
288 
289  // Return euclidean distance:
290  return sqrt( pow(cvmGet(&m_p1,0,0)-cvmGet(&m_p2,0,0),2) +
291  pow(cvmGet(&m_p1,1,0)-cvmGet(&m_p2,1,0),2) );
292 }
293 
294 double CamCalibration::GetSolutionQuality( std::vector<s_struct_solution> solution, double p_PreFilter_a, double p_PreFilter_b, double p_PreFilter_c ){
296  // Q1 - Number of points:
297  int overall_points = 0;
298  for( int c = 0; c < (int)v_camera.size(); c++ )
299  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
300  if( v_camera[c]->v_homography[h]->m_homography )
301  overall_points += v_camera[c]->v_homography[h]->s_plane_object->p;
302 
303  int solution_points = 0;
304  for( int i = 0; i < (int)solution.size(); i++ )
305  solution_points += v_camera[solution[i].c]->v_homography[solution[i].h]->s_plane_object->p;
306 
307  //TODO: Should be max_points instead of overall_points here:
308  double q1 = (double)solution_points/(double)overall_points;
309 
311  // Q2 - Number of connections:
312  int overall_connections = (int)v_camera.size()*(int)v_camera[0]->v_homography.size();
313  int solution_connections = 0;
314  for( int h = 0; h < (int)v_camera[0]->v_homography.size(); h++ ){
315  int current_connections = 0;
316  for( int i = 0; i < (int)solution.size(); i++ )
317  if( solution[i].h == h )
318  current_connections++;
319 
320  solution_connections += (int)pow((double)current_connections,2.);
321  }
322  double q2 = (double)solution_connections/(double)overall_connections;
323 
325  // Q3 - Distances:
326  double overall_distances = 0;
327  double solution_distances = 0;
328  for( int c = 0; c < (int)v_camera.size(); c++ ){
329  int hom_cam_num = 0;
330  for( int i = 0; i < (int)solution.size(); i++ )
331  if( solution[i].c == c )
332  hom_cam_num++;
333 
334  double overall_cam_distances = pow((double)hom_cam_num,2.)*sqrt(pow((double)v_camera[c]->w,2.)+pow((double)v_camera[c]->h,2.));
335  double solution_cam_distances = 0;
336  for( int i = 0; i < (int)solution.size(); i++ )
337  if( solution[i].c == c )
338  for( int j = 0; j < (int)solution.size(); j++ )
339  if( solution[j].c == c )
340  solution_cam_distances += GetScreenDistance(c,solution[i].h,solution[j].h);
341 
342  overall_distances += overall_cam_distances;
343  solution_distances += solution_cam_distances;
344  }
345 
346  double q3 = solution_distances/overall_distances;
347  return p_PreFilter_a*q1+p_PreFilter_b*q2+p_PreFilter_c*q3;
348 }
349 
350 // Greedy filter:
351 bool CamCalibration::FilterBestHomographiesGreedyMethod( int num ){
352  int cnt = 0;
353  printf( "INFO: Starting pre-filtering process, greedy method...\n" );
354  for( int h = 0; h < (int)v_camera[0]->v_homography.size(); h++ )
355  for( int c = 0; c < (int)v_camera.size(); c++ )
356  if( v_camera[c]->v_homography[h]->m_homography ){
357  if( cnt >= num ){
358  DeleteWorldPlaneHomography(c,h);
359  printf( "INFO: View %i of camera %i has been deleted!\n", h, c );
360  }
361  cnt++;
362  }
363 
364  if( cnt < num )
365  printf( "WARNING: Only %i homographies available instead of the requested %i ones!\n", cnt, num );
366 
367  printf( "INFO: Pre-filtering process finished\n" );
368  return true;
369 }
370 
371 static void fill_random(int array[],int size)
372 {
373  for (int i=0; i<size; ++i) {
374  array[i]=i;
375  }
376  for (int i=0; i<size; ++i) {
377  int n = (size*rand())/RAND_MAX;
378  if (n==i) continue;
379  if (n<0) n=0;
380  if (n>=size) n=size-1;
381  int tmp = array[i];
382  array[i] = array[n];
383  array[n] = tmp;
384  }
385 }
386 
387 // Padding filter:
388 bool CamCalibration::FilterBestHomographiesFillingMethod( int num, double p_PreFilter_a ){
389  double ratio = p_PreFilter_a; // Ratio of individual and group homographies
390  int cam = (int)v_camera.size();
391  int min = (int)floor((double)num/((double)cam*ratio));
392  int cnt = 0;
393  int totalHom = 0;
394 
395  // 1. PHASE - retain individual cam homographies:
396  for( int c = 0; c < cam; c++ ){
397  int hnum = 0;
398  for( unsigned h = 0; h < v_camera[c]->v_homography.size(); h++ )
399  if (v_camera[c]->v_homography[h]->m_homography) {
400  v_camera[c]->v_homography[h]->b_discard=true;
401  totalHom++;
402  }
403  printf("Camera %d: %d homographies\n", c, totalHom);
404 
405  for( int i = 0; i < min; i++ ){
406  int pmax = 0;
407  int hmax = 0;
408  // Find discarded homography with most inliers:
409  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
410  if( v_camera[c]->v_homography[h]->m_homography &&
411  v_camera[c]->v_homography[h]->s_plane_object->p > pmax &&
412  v_camera[c]->v_homography[h]->b_discard ){
413  pmax = (int)v_camera[c]->v_homography[h]->s_plane_object->p;
414  hmax = h;
415  }
416  // Set this homography to "not discarded":
417  if( pmax > 0 ){
418  //printf("individuals: %i %i\n",c,hmax);
419  v_camera[c]->v_homography[hmax]->b_discard = false;
420  cnt++; hnum++;
421  }
422  }
423  // You will need at least 3 individual homographies for calibration:
424  if( hnum < 2 ){
425  printf( "ERROR: Could not detect >= 2 homographies for camera %i\n", c );
426  return false;
427  }
428  }
429 
430  int *random_h = new int [v_camera[0]->v_homography.size()];
431  fill_random(random_h,v_camera[0]->v_homography.size());
432  // 2. PHASE - fill with group cam homographies:
433  for( int i = cam; i > 0; i-- ){
434  for( int _h = 0; _h < (int)v_camera[0]->v_homography.size(); _h++ ){
435  int h = random_h[_h];
436  int con = 0;
437  for( int c = 0; c < cam; c++ )
438  if( v_camera[c]->v_homography[h]->m_homography )
439  con++;
440  if( con == i )
441  for( int c2 = 0; c2 < cam; c2++ ){
442  if( v_camera[c2]->v_homography[h]->m_homography ){
443  if( v_camera[c2]->v_homography[h]->b_discard ){
444  v_camera[c2]->v_homography[h]->b_discard = false;
445  cnt++;
446  //printf("multi: %i %i\n",c2,h);
447  }
448  }
449  if( cnt >= num )
450  break;
451  }
452  if( cnt >= num )
453  break;
454  }
455  if( cnt >= num )
456  break;
457  }
458 
459  // Phase 2.5: try every possible pair, just in case we missed some.
460  for( int i = 0; i < cam; i++ ){
461  for( int j = 0; j < cam; j++ ){
462  int taken=0;
463  int missed=0;
464  for( int h = 0; h < (int)v_camera[0]->v_homography.size(); h++ ) {
465  if (v_camera[i]->v_homography[h]->m_homography
466  && v_camera[j]->v_homography[h]->m_homography) {
467  if (!v_camera[i]->v_homography[h]->b_discard
468  && !v_camera[j]->v_homography[h]->b_discard)
469  taken++;
470  else
471  missed++;
472  }
473  }
474  if (taken > 5 || missed ==0) continue;
475  int required = imin(missed,5);
476  for( int h = 0; h < (int)v_camera[0]->v_homography.size(); h++ ) {
477  if (v_camera[i]->v_homography[h]->m_homography
478  && v_camera[j]->v_homography[h]->m_homography) {
479  if (v_camera[i]->v_homography[h]->b_discard
480  || v_camera[j]->v_homography[h]->b_discard)
481  {
482  v_camera[i]->v_homography[h]->b_discard=false;
483  v_camera[j]->v_homography[h]->b_discard=false;
484  if (--required==0) break;
485  }
486  }
487  }
488  }
489  }
490 
491  // 3. PHASE - discard unused homographies:
492  for( int c = 0; c < cam; c++ )
493  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
494  if( v_camera[c]->v_homography[h]->m_homography &&
495  v_camera[c]->v_homography[h]->b_discard )
496  DeleteWorldPlaneHomography(c,h);
497 
498  // ensure we did not intensionally drop connectivity
499  for( int h = 0; h < (int)v_camera[0]->v_homography.size(); h++ ) {
500  bool taken=false;
501  for( int c = 0; c < cam; c++ ) {
502  taken = taken || (v_camera[c]->v_homography[h]->m_homography &&
503  !v_camera[c]->v_homography[h]->b_discard);
504  }
505  if (taken)
506  for( int c = 0; c < cam; c++ ) {
507  if (v_camera[c]->v_homography[h]->m_homography && v_camera[c]->v_homography[h]->b_discard) {
508  v_camera[c]->v_homography[h]->b_discard=false;
509  cnt++;
510  }
511  }
512  }
513 
514  // Return true only if homography number is sufficient:
515  if( cnt >= num ) {
516  printf( "Selected %d homographies out of %d. Minimum was: %d\n", cnt, totalHom, num );
517  return true;
518  } else {
519  printf( "ERROR: Only %i homographies available instead of the requested %i ones!\n", cnt, num );
520  return false;
521  }
522 }
523 
524 bool CamCalibration::FilterBestHomographiesRandomMethod( int num, int p_Solutions, double p_PreFilter_a, double p_PreFilter_b, double p_PreFilter_c ){
525 
526  int hom_num = 0;
527 
528  // 1. PHASE - count all homographies:
529  for( int c = 0; c < (int)v_camera.size(); c++ )
530  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
531  if( v_camera[c]->v_homography[h]->m_homography )
532  hom_num++;
533 
534  // If not enough homographies available, print error message:
535  if( num > hom_num ){
536  printf( "ERROR: Only %i homographies available instead of the requested %i ones!\n", hom_num, num );
537  return false;
538  } else
539  printf( "Filtering %i homographies out of %i ones ...\n", num, hom_num );
540 
541  // 2. PHASE - create random solutions and take best one:
542  std::vector<s_struct_solution> best_solution;
543  double best_quality = 0;
544  for( int i = 0; i < p_Solutions; i++ ){
545  std::vector<s_struct_solution> current_solution = GetRandomSolution( num );
546  printf("Solution %i, ",i);
547 
548  double current_quality = GetSolutionQuality( current_solution, p_PreFilter_a, p_PreFilter_b, p_PreFilter_c );
549  printf("quality: %f",current_quality);
550  if( current_quality > best_quality ){
551  best_solution = current_solution;
552  best_quality = current_quality;
553  }
554  printf("best: %f",best_quality);
555  printf("\n");
556  }
557 
558  // 3. PHASE - filter best Solutions:
559  int deleted = 0;
560  for( int c = 0; c < (int)v_camera.size(); c++ )
561  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
562  if( v_camera[c]->v_homography[h]->m_homography ){
563  bool del_hom = true;
564 
565  // Search in best solution if homography is there:
566  for( int i = 0; i < (int)best_solution.size(); i++ )
567  if( c == best_solution[i].c && h == best_solution[i].h )
568  del_hom = false;
569 
570  if( del_hom ){
571  DeleteWorldPlaneHomography(c,h);
572  deleted++;
573  }
574  }
575 
576  return true;
577 }
578 
579 bool CamCalibration::Calibrate( int p_HomographyNum, int p_PreFilter, int p_Solutions, double p_PreFilter_a, double p_PreFilter_b, double p_PreFilter_c,
580  double p_InitialGuess_a, double p_InitialGuess_b, double p_InitialGuess_c,
581  int p_Iterations, double p_Epsilon, double p_PostFilter ){
582 
583  // Starting values for statistics:
584  stat_HomographyNum = p_HomographyNum;
585  stat_ExpStartTime = time(0);
586 
587  bool filter_ok;
588  switch( p_PreFilter ){
589  case 0: filter_ok = FilterBestHomographiesGreedyMethod ( p_HomographyNum ); break;
590  case 1: filter_ok = FilterBestHomographiesFillingMethod( p_HomographyNum, p_PreFilter_a ); break;
591  case 2: filter_ok = FilterBestHomographiesRandomMethod ( p_HomographyNum, p_Solutions, p_PreFilter_a, p_PreFilter_b, p_PreFilter_c ); break;
592  default: filter_ok = FilterBestHomographiesFillingMethod( p_HomographyNum, p_PreFilter_a ); break;
593  }
594 
595  if( !filter_ok ){
596  printf("ERROR: Homography filtering process failed!\n");
597  return false;
598  }
599 
600  // Perform initial guess:
601  for( int c = 0; c < (int)v_camera.size(); c++ ){
602  if( !ExtractIntrinsicParameters( c, p_InitialGuess_a, p_InitialGuess_b, p_InitialGuess_c ) ){
603  printf("ERROR: Extraction of intrinsic parameters of camera %i failed!\n",c);
604  return false;
605  }
606  CreateEstimatedCalibrationMatrixFromEstimatedIntrinsicParameters( c );
607  CreateEstimatedInverseCalibrationMatrixFromEstimatedIntrinsicParameters( c );
608  CreateAllRotationTranslationMatrices( c );
609  }
610 
611  // Do optimization:
612  if( OptimizeCalibrationByMinimalParameterMethod( p_Iterations, p_Epsilon, p_PostFilter ) ){
613  return true;
614  } else
615  return false;
616 }
617 
618 void CamCalibration::PrintStatisticToFile(){
619  FILE * stat;
620  stat = fopen( "stat.txt", "a" );
621  fprintf( stat, "%i %ld", stat_HomographyNum, time(0)-stat_ExpStartTime);
622  for( int i = 0; i < (int)v_camera.size(); i++ )
623  for( int j = 0; j < 4; j++ )
624  fprintf( stat, " %f", v_opt_param[i*4+j] );
625  fprintf( stat, "\n" );
626  printf("Statistic has successfully been saved!\n");
627  fclose( stat );
628 }
629 
630 void CamCalibration::CreateAllRotationTranslationMatrices( int c ){
631  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
632  if( v_camera[c]->v_homography[h]->m_homography )
633  CreateRotationTranslationMatrixFromInverseCalibrationMatrixAndHomography( c, h );
634 }
635 
636 CvMat* CamCalibration::GetM( enum matrix_desc desc, int c, int h ){
637  switch( desc ){
638  case m_calibration: return v_camera[c]->m_calibration_matrix;
639  case m_rot_trans : return v_camera[c]->m_rot_trans_matrix;
640  case m_estim_calib: return v_camera[c]->m_estim_calib_matrix;
641  case m_estinvcalib: return v_camera[c]->m_estinvcalib_matrix;
642  case m_estim_r_t : return v_camera[c]->v_homography[h]->m_estim_r_t_matrix;
643  case m_jacobian : return v_camera[c]->v_homography[h]->m_jacobian_matrix;\
644  default : return NULL;
645  }
646 }
647 
648 double CamCalibration::GetRandomValue( double min, double max ){
649  double delta = max - min;
650  double value = (double)rand()/(double)RAND_MAX;
651  return min + delta*value;
652 }
653 
654 // Box-Muller method:
655 void CamCalibration::AddGaussianNoise( CvMat* mat, double noise ){
656  double u1 = GetRandomValue( 0, 1 );
657  double u2 = GetRandomValue( 0, 1 );
658  cvmSet( mat, 0, 0, cvmGet( mat, 0, 0 ) + noise*sqrt(-2.00*log(u1))*cos(2*M_PI*u2) );
659  cvmSet( mat, 1, 0, cvmGet( mat, 1, 0 ) + noise*sqrt(-2.00*log(u1))*sin(2*M_PI*u2) );
660 }
661 
663  if( cvGetDimSize( mat, 0 ) > 1 ){
664  double d = cvmGet( mat, cvGetDimSize( mat, 0 )-1, 0 );
665  if( d != 0 )
666  for( int i = 0; i < cvGetDimSize( mat, 0 ); i++ )
667  cvmSet( mat, i, 0, cvmGet( mat, i, 0 )/d );
668  } else {
669  double d = cvmGet( mat, 0, cvGetDimSize( mat, 1 )-1 );
670  if( d != 0 )
671  for( int i = 0; i < cvGetDimSize( mat, 1 ); i++ )
672  cvmSet( mat, 0, i, cvmGet( mat, 0, i )/d );
673  }
674 }
675 
676 void CamCalibration::SetIntrinsicParam( int c, double f, double a, double u, double v ){
677  v_camera[c]->s_intrinsic.focal = f;
678  v_camera[c]->s_intrinsic.aspect = a;
679  v_camera[c]->s_intrinsic.u0 = u;
680  v_camera[c]->s_intrinsic.v0 = v;
681 }
682 
683 void CamCalibration::SetPlaneObject( int c, int h, int p, double px[], double py[],
684  double rx, double ry, double rz, double tx, double ty, double tz ){
685  // Get pointer:
686  s_struct_plane* s_plane_object = v_camera[c]->v_homography[h]->s_plane_object;
687 
688  // Delete old data if necessary:
689  if( (*s_plane_object).px ) delete (*s_plane_object).px;
690  if( (*s_plane_object).py ) delete (*s_plane_object).py;
691  if( (*s_plane_object).v_m_wp.size() > 0 ){
692  for( int i = 0; i < (int)(*s_plane_object).v_m_wp.size(); i++ )
693  cvReleaseMat( &(*s_plane_object).v_m_wp[i] );
694  (*s_plane_object).v_m_wp.clear();
695  }
696  if( (*s_plane_object).v_m_pp.size() > 0 ){
697  for( int i = 0; i < (*s_plane_object).p; i++ )
698  cvReleaseMat( &(*s_plane_object).v_m_pp[i] );
699  (*s_plane_object).v_m_pp.clear();
700  }
701 
702  // Create new sized data structures:
703  (*s_plane_object).px = new double[p];
704  (*s_plane_object).py = new double[p];
705  for( int i = 0; i < p; i++ ){
706  (*s_plane_object).v_m_wp.push_back(cvCreateMat( 4, 1, CV_64FC1 ));
707  (*s_plane_object).v_m_pp.push_back(cvCreateMat( 3, 1, CV_64FC1 ));
708  }
709 
710  // Set plane number:
711  (*s_plane_object).p = p;
712 
713  // Set x/y coordinates on plane:
714  for( int i = 0; i < p; i++ ){
715  (*s_plane_object).px[i] = px[i];
716  (*s_plane_object).py[i] = py[i];
717  }
718 
719  // Set rotation translation:
720  (*s_plane_object).rx = rx;
721  (*s_plane_object).ry = ry;
722  (*s_plane_object).rz = rz;
723  (*s_plane_object).tx = tx;
724  (*s_plane_object).ty = ty;
725  (*s_plane_object).tz = tz;
726 }
727 
728 void CamCalibration::Translate3DVector( CvMat* v, double x, double y, double z ){
729  double a_T[] = { 1, 0, 0, -x,
730  0, 1, 0, -y,
731  0, 0, 1, -z,
732  0, 0, 0, 1 };
733  CvMat m_T = cvMat( 4, 4, CV_64FC1, a_T );
734  cvMatMul( &m_T, v, v );
735 }
736 
737 void CamCalibration::Rotate3DVector( CvMat* v, double x, double y, double z ){
738  x *= 2*M_PI/360.00;
739  y *= 2*M_PI/360.00;
740  z *= 2*M_PI/360.00;
741  double a_Rx[] = { 1, 0, 0, 0,
742  0, cos(x), -sin(x), 0,
743  0, sin(x), cos(x), 0,
744  0, 0, 0, 1 };
745  double a_Ry[] = { cos(y), 0, -sin(y), 0,
746  0, 1, 0, 0,
747  sin(y), 0, cos(y), 0,
748  0, 0, 0, 1 };
749  double a_Rz[] = { cos(z), -sin(z), 0, 0,
750  sin(z), cos(z), 0, 0,
751  0, 0, 1, 0,
752  0, 0, 0, 1 };
753  CvMat m_Rx = cvMat( 4, 4, CV_64FC1, a_Rx );
754  CvMat m_Ry = cvMat( 4, 4, CV_64FC1, a_Ry );
755  CvMat m_Rz = cvMat( 4, 4, CV_64FC1, a_Rz );
756  cvMatMul( &m_Rx, v, v );
757  cvMatMul( &m_Ry, v, v );
758  cvMatMul( &m_Rz, v, v );
759 }
760 
761 void CamCalibration::ExtractRotationTranslationFrom3x4Matrix( CvMat* RotTrans , CvMat* Rot, CvMat*Trans ){
762  if( Rot != NULL ){
763  cvmSet( Rot, 0, 0, cvmGet( RotTrans, 0, 0 ) );
764  cvmSet( Rot, 0, 1, cvmGet( RotTrans, 0, 1 ) );
765  cvmSet( Rot, 0, 2, cvmGet( RotTrans, 0, 2 ) );
766  cvmSet( Rot, 1, 0, cvmGet( RotTrans, 1, 0 ) );
767  cvmSet( Rot, 1, 1, cvmGet( RotTrans, 1, 1 ) );
768  cvmSet( Rot, 1, 2, cvmGet( RotTrans, 1, 2 ) );
769  cvmSet( Rot, 2, 0, cvmGet( RotTrans, 2, 0 ) );
770  cvmSet( Rot, 2, 1, cvmGet( RotTrans, 2, 1 ) );
771  cvmSet( Rot, 2, 2, cvmGet( RotTrans, 2, 2 ) );
772  }
773  if( Trans != NULL ){
774  cvmSet( Trans, 0, 0, -cvmGet( RotTrans, 0, 3 ) );
775  cvmSet( Trans, 1, 0, -cvmGet( RotTrans, 1, 3 ) );
776  cvmSet( Trans, 2, 0, -cvmGet( RotTrans, 2, 3 ) );
777  }
778 }
779 
780 void CamCalibration::ComposeRotationTranslationTo3x4Matrix( CvMat* RotTrans , CvMat* Rot, CvMat*Trans ){
781  cvmSet( RotTrans, 0, 0, cvmGet( Rot, 0, 0 ) );
782  cvmSet( RotTrans, 0, 1, cvmGet( Rot, 0, 1 ) );
783  cvmSet( RotTrans, 0, 2, cvmGet( Rot, 0, 2 ) );
784  cvmSet( RotTrans, 1, 0, cvmGet( Rot, 1, 0 ) );
785  cvmSet( RotTrans, 1, 1, cvmGet( Rot, 1, 1 ) );
786  cvmSet( RotTrans, 1, 2, cvmGet( Rot, 1, 2 ) );
787  cvmSet( RotTrans, 2, 0, cvmGet( Rot, 2, 0 ) );
788  cvmSet( RotTrans, 2, 1, cvmGet( Rot, 2, 1 ) );
789  cvmSet( RotTrans, 2, 2, cvmGet( Rot, 2, 2 ) );
790  cvmSet( RotTrans, 0, 3, -cvmGet( Trans, 0, 0 ) );
791  cvmSet( RotTrans, 1, 3, -cvmGet( Trans, 1, 0 ) );
792  cvmSet( RotTrans, 2, 3, -cvmGet( Trans, 2, 0 ) );
793 }
794 
795 void CamCalibration::Mat3x4ToMat4x4( CvMat* m_A, CvMat* m_B ){
796  for( int i = 0; i < 3; i++ )
797  for( int j = 0; j < 4; j++ )
798  cvmSet( m_B, i, j, cvmGet( m_A, i, j ) );
799  cvmSet( m_B, 3, 0, 0 );
800  cvmSet( m_B, 3, 1, 0 );
801  cvmSet( m_B, 3, 2, 0 );
802  cvmSet( m_B, 3, 3, 1 );
803 }
804 
805 void CamCalibration::Mat4x4ToMat3x4( CvMat* m_A, CvMat* m_B ){
806  for( int i = 0; i < 3; i++ )
807  for( int j = 0; j < 4; j++ )
808  cvmSet( m_B, i, j, cvmGet( m_A, i, j ) );
809 }
810 
811 void CamCalibration::Mat3x4Mul( CvMat* m_A, CvMat* m_B, CvMat* m_C ){
812  double a_A2[16]; CvMat m_A2 = cvMat( 4, 4, CV_64FC1, a_A2 );
813  double a_B2[16]; CvMat m_B2 = cvMat( 4, 4, CV_64FC1, a_B2 );
814  double a_C2[16]; CvMat m_C2 = cvMat( 4, 4, CV_64FC1, a_C2 );
815  Mat3x4ToMat4x4( m_A, &m_A2 );
816  Mat3x4ToMat4x4( m_B, &m_B2 );
817  cvMatMul( &m_A2, &m_B2, &m_C2 );
818  Mat4x4ToMat3x4( &m_C2, m_C );
819 }
820 
821 void CamCalibration::Mat3x4Inverse( CvMat* m_A, CvMat* m_B ){
822  double a_R[9]; CvMat m_R = cvMat( 3, 3, CV_64FC1, a_R );
823  double a_T[3]; CvMat m_T = cvMat( 3, 1, CV_64FC1, a_T );
824  ExtractRotationTranslationFrom3x4Matrix( m_A, &m_R, &m_T );
825  cvTranspose( &m_R, &m_R );
826  cvGEMM( &m_R, &m_T, -1.00, NULL, +1.00, &m_T, 0 );
827  ComposeRotationTranslationTo3x4Matrix( m_B, &m_R, &m_T );
828 }
829 
830 void CamCalibration::CreatePlaneObjectWorldPoints( int c, int h ){
831  s_struct_plane* s_plane_object = v_camera[c]->v_homography[h]->s_plane_object;
832  for( int i = 0; i < (*s_plane_object).p; i++ ){
833 
834  // Create Point in plane Z=0:
835  cvmSet( (*s_plane_object).v_m_wp[i], 0, 0, (*s_plane_object).px[i] );
836  cvmSet( (*s_plane_object).v_m_wp[i], 1, 0, (*s_plane_object).py[i] );
837  cvmSet( (*s_plane_object).v_m_wp[i], 2, 0, 0.0 );
838  cvmSet( (*s_plane_object).v_m_wp[i], 3, 0, 1.0 );
839 
840  // Translate and Rotate the Point to its World Position:
841  Rotate3DVector ( (*s_plane_object).v_m_wp[i],
842  (*s_plane_object).rx,
843  (*s_plane_object).ry,
844  (*s_plane_object).rz );
845 
846  Translate3DVector( (*s_plane_object).v_m_wp[i],
847  (*s_plane_object).tx,
848  (*s_plane_object).ty,
849  (*s_plane_object).tz );
850  }
851 }
852 
853 void CamCalibration::CreatePlaneObjectPlanePoints( int c, int h, double noise ){
854  s_struct_plane* s_plane_object = v_camera[c]->v_homography[h]->s_plane_object;
855  for( int i = 0; i < (*s_plane_object).p; i++ ){
856  double a_P[12]; CvMat m_P = cvMat( 3, 4, CV_64FC1, a_P );
857  cvMatMul( GetM(m_calibration,c,h), GetM(m_rot_trans,c,h), &m_P );
858  cvMatMul( &m_P, (*s_plane_object).v_m_wp[i], (*s_plane_object).v_m_pp[i] );
859  HomogenousNormalizeVector( (*s_plane_object).v_m_pp[i] );
860  AddGaussianNoise( (*s_plane_object).v_m_pp[i], noise );
861  }
862 }
863 
864 void CamCalibration::CreateWorldPlaneHomography( int c, int h, CvMat *ready ){
865  s_struct_plane* s_plane_object = v_camera[c]->v_homography[h]->s_plane_object;
866 
867  homography* m_homography = v_camera[c]->v_homography[h]->m_homography = new homography();
868  if (ready){
869  cvCopy(ready, m_homography);
870  } else {
871  m_homography->set_match_number( (*s_plane_object).p );
872 
873  for( int i = 0; i < (*s_plane_object).p; i++ ){
874  HomogenousNormalizeVector( (*s_plane_object).v_m_pp[i] );
875  m_homography->add_match( (float)(*s_plane_object).px[i],
876  (float)(*s_plane_object).py[i],
877  (float)cvmGet( (*s_plane_object).v_m_pp[i], 0, 0 ),
878  (float)cvmGet( (*s_plane_object).v_m_pp[i], 1, 0 ) );
879  }
880  m_homography->estimate();
881  m_homography->release_matches();
882  }
883 }
884 
885 double CamCalibration::VectorAngle( CvMat* v1, CvMat* v2, CvMat* v3, CvMat* v4 ){
886  double x1 = cvmGet( v2, 0, 0 ) - cvmGet( v1, 0, 0 );
887  double y1 = cvmGet( v2, 1, 0 ) - cvmGet( v1, 1, 0 );
888  double x2 = cvmGet( v4, 0, 0 ) - cvmGet( v3, 0, 0 );
889  double y2 = cvmGet( v4, 1, 0 ) - cvmGet( v3, 1, 0 );
890  double a = x1*x2+y1*y2;
891  double b = sqrt(pow(x1,2)+pow(y1,2)) * sqrt(pow(x2,2)+pow(y2,2));
892  if( b != 0 )
893  return acos(a/b);
894  else
895  return 0;
896 }
897 
898 double CamCalibration::PointDistance( CvMat* v1, CvMat* v2 ){
899  double x = cvmGet( v2, 0, 0 ) - cvmGet( v1, 0, 0 );
900  double y = cvmGet( v2, 1, 0 ) - cvmGet( v1, 1, 0 );
901  return sqrt(pow(x,2)+pow(y,2));
902 }
903 
904 void CamCalibration::DeleteWorldPlaneHomography( int c, int h ){
905  delete v_camera[c]->v_homography[h]->m_homography;
906  v_camera[c]->v_homography[h]->m_homography = NULL;
907 }
908 
909 bool CamCalibration::HomographySingular( int c, int h, double p_InitialGuess_a, double p_InitialGuess_b, double p_InitialGuess_c ){
910 
911  // Initialze 4 standard measure points:
912  double a_w1[] = { -1, -1, 1 }; CvMat m_w1 = cvMat( 3, 1, CV_64FC1, a_w1 );
913  double a_w2[] = { -1, 1, 1 }; CvMat m_w2 = cvMat( 3, 1, CV_64FC1, a_w2 );
914  double a_w3[] = { 1, 1, 1 }; CvMat m_w3 = cvMat( 3, 1, CV_64FC1, a_w3 );
915  double a_w4[] = { 1, -1, 1 }; CvMat m_w4 = cvMat( 3, 1, CV_64FC1, a_w4 );
916  double a_p1[3]; CvMat m_p1 = cvMat( 3, 1, CV_64FC1, a_p1 );
917  double a_p2[3]; CvMat m_p2 = cvMat( 3, 1, CV_64FC1, a_p2 );
918  double a_p3[3]; CvMat m_p3 = cvMat( 3, 1, CV_64FC1, a_p3 );
919  double a_p4[3]; CvMat m_p4 = cvMat( 3, 1, CV_64FC1, a_p4 );
920  double a_h[9]; CvMat m_h = cvMat( 3, 3, CV_64FC1, a_h );
921 
922  // Copy homography to matrix:
923  for( int i = 0; i < 3; i++ )
924  for( int j = 0; j < 3; j++ )
925  cvmSet( &m_h, i, j, cvmGet( v_camera[c]->v_homography[h]->m_homography, i, j ) );
926 
927  // Project points using the homography:
928  cvMatMul( &m_h, &m_w1, &m_p1 ); HomogenousNormalizeVector( &m_p1 );
929  cvMatMul( &m_h, &m_w2, &m_p2 ); HomogenousNormalizeVector( &m_p2 );
930  cvMatMul( &m_h, &m_w3, &m_p3 ); HomogenousNormalizeVector( &m_p3 );
931  cvMatMul( &m_h, &m_w4, &m_p4 ); HomogenousNormalizeVector( &m_p4 );
932 
933  // Check for correct angles:
934  double a1 = VectorAngle( &m_p1, &m_p4, &m_p1, &m_p2 );
935  double a2 = VectorAngle( &m_p2, &m_p3, &m_p2, &m_p1 );
936  double a3 = VectorAngle( &m_p3, &m_p4, &m_p3, &m_p2 );
937  double a4 = VectorAngle( &m_p4, &m_p1, &m_p4, &m_p3 );
938  double e1 = p_InitialGuess_a;
939  double e2 = p_InitialGuess_b;
940  if( a1 < e2 || (a1 > (M_PI/2.00) - e1 && a1 < (M_PI/2.00) + e1) || a1 > M_PI - e2 ||
941  a2 < e2 || (a2 > (M_PI/2.00) - e1 && a2 < (M_PI/2.00) + e1) || a2 > M_PI - e2 ||
942  a3 < e2 || (a3 > (M_PI/2.00) - e1 && a3 < (M_PI/2.00) + e1) || a3 > M_PI - e2 ||
943  a4 < e2 || (a4 > (M_PI/2.00) - e1 && a4 < (M_PI/2.00) + e1) || a4 > M_PI - e2 ){
944  return true;
945  }
946 
947  // Check for correct distances:
948  double d1 = PointDistance( &m_p1, &m_p2 );
949  double d2 = PointDistance( &m_p2, &m_p3 );
950  double d3 = PointDistance( &m_p3, &m_p4 );
951  double d4 = PointDistance( &m_p4, &m_p1 );
952  double d5 = (d1+d2+d3+d4)/4.00;
953  double e3 = p_InitialGuess_c;
954  if( d1 < d5*e3 || d2 < d5*e3 || d3 < d5*e3 || d4 < d5*e3 ){
955  return true;
956  }
957 
958  return false;
959 }
960 
961 double CamCalibration::GetFrobeniusDistance( int c, int h1, int h2 ){
962 
963  // First normalize to get comparable values:
964  double na = 0;
965  double nb = 0;
966  for( int i = 0; i < 3; i++ )
967  for( int j = 0; j < 3; j++ ){
968  na += pow(cvmGet( v_camera[c]->v_homography[h1]->m_homography, i, j ),2);
969  nb += pow(cvmGet( v_camera[c]->v_homography[h2]->m_homography, i, j ),2);
970  }
971  na /= 10000.00;
972  nb /= 10000.00;
973 
974  // Then build Frobenius norm:
975  double sum = 0;
976  for( int i = 0; i < 3; i++ )
977  for( int j = 0; j < 3; j++ ){
978  double a = cvmGet( v_camera[c]->v_homography[h1]->m_homography, i, j )/na;
979  double b = cvmGet( v_camera[c]->v_homography[h2]->m_homography, i, j )/nb;
980  sum += pow( a - b, 2 );
981  }
982  return sum;
983 }
984 
985 bool CamCalibration::GetDistalHomographiesForCalibration( int c, int *h1, int *h2 ){
986  double dist = 0;
987  for( int i = 0; i < (int)v_camera[c]->v_homography.size(); i++ )
988  for( int j = 0; j < (int)v_camera[c]->v_homography.size(); j++ )
989  if( v_camera[c]->v_homography[i]->m_homography &&
990  v_camera[c]->v_homography[j]->m_homography ){
991  double dnew = GetFrobeniusDistance( c, i, j );
992  if( dnew > dist ){
993  dist = dnew;
994  *h1 = i;
995  *h2 = j;
996  }
997  }
998 
999  if( dist > 0 )
1000  return true;
1001  else
1002  return false;
1003 }
1004 
1005 bool CamCalibration::ExtractIntrinsicParameters( int c, double p_InitialGuess_a, double p_InitialGuess_b, double p_InitialGuess_c ){
1006  int homs = 0;
1007  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
1008  if( v_camera[c]->v_homography[h]->m_homography )
1009  if( !HomographySingular( c, h, p_InitialGuess_a, p_InitialGuess_b, p_InitialGuess_c ) )
1010  homs++;
1011 
1012  // Check if enough homographies to calculate intrinsic parameters:
1013  if( homs < 2 ){
1014  printf( "ERROR: Could not extract intrinsic parameters of camera %i\n", c );
1015  printf( " because there are fewer than 2 views available!\n" );
1016  return false;
1017  }
1018 
1019  int rows_of_a = 2*homs;
1020  CvMat* m_A = cvCreateMat( rows_of_a, 4, CV_64FC1 );
1021  CvMat* m_X = cvCreateMat( 4, 1, CV_64FC1 );
1022  CvMat* m_B = cvCreateMat( rows_of_a, 1, CV_64FC1 );
1023 
1024  homs = 0;
1025  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
1026  if( v_camera[c]->v_homography[h]->m_homography )
1027  if( !HomographySingular( c, h, p_InitialGuess_a, p_InitialGuess_b, p_InitialGuess_c ) ){
1028 
1029  // Get pointer:
1030  homography* m_homography = v_camera[c]->v_homography[h]->m_homography;
1031 
1032  double v_h11 = m_homography->cvmGet( 0, 0 );
1033  double v_h12 = m_homography->cvmGet( 0, 1 );
1034  double v_h21 = m_homography->cvmGet( 1, 0 );
1035  double v_h22 = m_homography->cvmGet( 1, 1 );
1036  double v_h31 = m_homography->cvmGet( 2, 0 );
1037  double v_h32 = m_homography->cvmGet( 2, 1 );
1038 
1039  // First row:
1040  cvmSet( m_A, homs*2, 0, (pow(v_h21,2)-pow(v_h22,2) ));
1041  cvmSet( m_A, homs*2, 1, 2*( v_h11*v_h31-v_h12*v_h32 ));
1042  cvmSet( m_A, homs*2, 2, 2*( v_h21*v_h31-v_h22*v_h32 ));
1043  cvmSet( m_A, homs*2, 3, (pow(v_h31,2)-pow(v_h32,2) ));
1044  cvmSet( m_B, homs*2, 0, (pow(v_h12,2)-pow(v_h11,2) ));
1045 
1046  // Second row:
1047  cvmSet( m_A, homs*2+1, 0, (v_h22*v_h21 ) );
1048  cvmSet( m_A, homs*2+1, 1, (v_h11*v_h32 + v_h12*v_h31 ));
1049  cvmSet( m_A, homs*2+1, 2, (v_h32*v_h21 + v_h22*v_h31 ));
1050  cvmSet( m_A, homs*2+1, 3, (v_h32*v_h31) );
1051  cvmSet( m_B, homs*2+1, 0, (-v_h11*v_h12) );
1052 
1053  homs++;
1054  }
1055 
1056  // Solve least squares
1057  cvSolve( m_A, m_B, m_X, CV_SVD );
1058 
1059  // Grab omegas out of X
1060  double v_w22 = cvmGet( m_X, 0, 0 );
1061  double v_w13 = cvmGet( m_X, 1, 0 );
1062  double v_w23 = cvmGet( m_X, 2, 0 );
1063  double v_w33 = cvmGet( m_X, 3, 0 );
1064 
1065  // Release temporary matices:
1066  cvReleaseMat( &m_A );
1067  cvReleaseMat( &m_X );
1068  cvReleaseMat( &m_B );
1069 
1070  // Set the estimated intrinsic parameters if possible:
1071  double f2 = (v_w22*v_w33-v_w22*pow(v_w13,2)-pow(v_w23,2))/pow(v_w22,2);
1072  double a2 = v_w22;
1073  if( a2 < 0 || f2 < 0 ){
1074  printf("ERROR: Intrinsic parameters of camera %i could not be estimated (complex values)!\n",c);
1075  return false;
1076  }
1077 
1078  // Assign results:
1079  v_camera[c]->s_estim_int.focal = sqrt(f2);
1080  v_camera[c]->s_estim_int.aspect = sqrt(a2);
1081  v_camera[c]->s_estim_int.u0 = -v_w13;
1082  v_camera[c]->s_estim_int.v0 = -v_w23/v_w22;
1083 
1084  printf( "Estimated camera %i (%03d views): %f %f %f %f\n", c, homs,
1085  v_camera[c]->s_estim_int.focal, v_camera[c]->s_estim_int.aspect,
1086  v_camera[c]->s_estim_int.u0, v_camera[c]->s_estim_int.v0 );
1087 
1088  return true;
1089 }
1090 
1091 /*
1092 void CamCalibration::ExtractIntrinsicParameters( int c, int h1, int h2 ){
1093 int rows_of_a = 2*2;
1094 
1095 CvMat* m_A = cvCreateMat( rows_of_a, 4, CV_64FC1 );
1096 CvMat* m_X = cvCreateMat( 4, 1, CV_64FC1 );
1097 CvMat* m_B = cvCreateMat( rows_of_a, 1, CV_64FC1 );
1098 
1099 for( int h = 0; h < 2; h++ ){
1100 // Get the homography number (of first or second):
1101 int hom = h1;
1102 if( h == 1 ) hom = h2;
1103 
1104 // Get pointer:
1105 homography* m_homography = v_camera[c]->v_homography[hom]->m_homography;
1106 
1107 double v_h11 = m_homography->cvmGet( 0, 0 );
1108 double v_h12 = m_homography->cvmGet( 0, 1 );
1109 double v_h21 = m_homography->cvmGet( 1, 0 );
1110 double v_h22 = m_homography->cvmGet( 1, 1 );
1111 double v_h31 = m_homography->cvmGet( 2, 0 );
1112 double v_h32 = m_homography->cvmGet( 2, 1 );
1113 
1114 // First row:
1115 cvmSet( m_A, h*2, 0, (pow(v_h21,2)-pow(v_h22,2)));
1116 cvmSet( m_A, h*2, 1, 2*( v_h11*v_h31-v_h12*v_h32 ));
1117 cvmSet( m_A, h*2, 2, 2*( v_h21*v_h31-v_h22*v_h32 ));
1118 cvmSet( m_A, h*2, 3, (pow(v_h31,2)-pow(v_h32,2) ));
1119 cvmSet( m_B, h*2, 0, (pow(v_h12,2)-pow(v_h11,2) ));
1120 
1121 // Second row:
1122 cvmSet( m_A, h*2+1, 0, (v_h22*v_h21 ) );
1123 cvmSet( m_A, h*2+1, 1, (v_h11*v_h32 + v_h12*v_h31 ));
1124 cvmSet( m_A, h*2+1, 2, (v_h32*v_h21 + v_h22*v_h31 ));
1125 cvmSet( m_A, h*2+1, 3, (v_h32*v_h31) );
1126 cvmSet( m_B, h*2+1, 0, (-v_h11*v_h12) );
1127 }
1128 
1129 // Solve least squares
1130 cvSolve( m_A, m_B, m_X, CV_SVD );
1131 
1132 // Grab omegas out of X
1133 double v_w22 = cvmGet( m_X, 0, 0 );
1134 double v_w13 = cvmGet( m_X, 1, 0 );
1135 double v_w23 = cvmGet( m_X, 2, 0 );
1136 double v_w33 = cvmGet( m_X, 3, 0 );
1137 
1138 // Set the estimated intrinsic parameters if possible:
1139 double f2 = (v_w22*v_w33-v_w22*pow(v_w13,2)-pow(v_w23,2))/pow(v_w22,2);
1140 double a2 = v_w22;
1141 if( a2 < 0 || f2 < 0 ){
1142 printf("ERROR: Intrinsic parameters of camera %i could not be estimated (complex values)!\n",c);
1143 return false; // complex value
1144 }
1145 v_camera[c]->s_estim_int.focal = sqrt(f2);
1146 v_camera[c]->s_estim_int.aspect = sqrt(a2);
1147 v_camera[c]->s_estim_int.u0 = -v_w13;
1148 v_camera[c]->s_estim_int.v0 = -v_w23/v_w22;
1149 
1150 // Realease temporary matices:
1151 cvReleaseMat( &m_A );
1152 cvReleaseMat( &m_X );
1153 cvReleaseMat( &m_B );
1154 }*/
1155 
1156 /*
1157 bool CamCalibration::ExtractIntrinsicParameters( int c ){
1158 
1159 int homs = 0;
1160 for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
1161 if( v_camera[c]->v_homography[h]->m_homography )
1162 homs++;
1163 
1164 // Check if enough homographies to calculate intrinsic parameters:
1165 if( homs < 2 ){
1166 printf( "ERROR: Could not extract intrinsic parameters of camera %i\n", c );
1167 printf( " because there are fewer than 2 views available!\n" );
1168 return false;
1169 }
1170 
1171 int rows_of_a = 2*homs;
1172 CvMat* m_A = cvCreateMat( rows_of_a, 5, CV_64FC1 );
1173 CvMat* m_ATA = cvCreateMat( 5, 5, CV_64FC1 );
1174 CvMat* m_EVA = cvCreateMat( 5, 1, CV_64FC1 );
1175 CvMat* m_EVE = cvCreateMat( 5, 5, CV_64FC1 );
1176 
1177 homs = 0;
1178 for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
1179 if( v_camera[c]->v_homography[h]->m_homography ){
1180 // Get pointer:
1181 homography* m_homography = v_camera[c]->v_homography[h]->m_homography;
1182 
1183 double v_h11 = m_homography->cvmGet( 0, 0 );
1184 double v_h12 = m_homography->cvmGet( 0, 1 );
1185 double v_h21 = m_homography->cvmGet( 1, 0 );
1186 double v_h22 = m_homography->cvmGet( 1, 1 );
1187 double v_h31 = m_homography->cvmGet( 2, 0 );
1188 double v_h32 = m_homography->cvmGet( 2, 1 );
1189 
1190 // First row:
1191 cvmSet( m_A, homs*2, 0, pow(v_h11,2)-pow(v_h12,2) );
1192 cvmSet( m_A, homs*2, 1, pow(v_h21,2)-pow(v_h22,2) );
1193 cvmSet( m_A, homs*2, 2, 2*( v_h11*v_h31-v_h12*v_h32 ) );
1194 cvmSet( m_A, homs*2, 3, 2*( v_h21*v_h31-v_h22*v_h32 ) );
1195 cvmSet( m_A, homs*2, 4, pow(v_h31,2)-pow(v_h32,2) );
1196 
1197 // Second row:
1198 cvmSet( m_A, homs*2+1, 0, v_h11*v_h12 );
1199 cvmSet( m_A, homs*2+1, 1, v_h22*v_h21 );
1200 cvmSet( m_A, homs*2+1, 2, v_h11*v_h32 + v_h12*v_h31 );
1201 cvmSet( m_A, homs*2+1, 3, v_h32*v_h21 + v_h22*v_h31 );
1202 cvmSet( m_A, homs*2+1, 4, v_h32*v_h31 );
1203 
1204 homs++;
1205 }
1206 
1207 // Get Eigenvectors:
1208 cvGEMM( m_A, m_A, 1, NULL, 0, m_ATA, CV_GEMM_A_T );
1209 cvEigenVV( m_ATA, m_EVE, m_EVA, DBL_EPSILON );
1210 
1211 
1212 // Grab omegas out of X
1213 double v_w11 = cvmGet( m_EVE, 4, 0 );
1214 double v_w22 = cvmGet( m_EVE, 4, 1 );
1215 double v_w13 = cvmGet( m_EVE, 4, 2 );
1216 double v_w23 = cvmGet( m_EVE, 4, 3 );
1217 double v_w33 = cvmGet( m_EVE, 4, 4 );
1218 
1219 // Set the estimated intrinsic parameters if possible:
1220 double f2 = (v_w11*v_w22*v_w33-v_w22*pow(v_w13,2)-v_w11*pow(v_w23,2))/(v_w11*pow(v_w22,2));
1221 double a2 = v_w22/v_w11;
1222 if( a2 < 0 || f2 < 0 ){
1223 printf("ERROR: Intrinsic parameters of camera %i could not be estimated (complex values)!\n",c);
1224 return false; // complex value
1225 }
1226 
1227 v_camera[c]->s_estim_int.focal = sqrt(f2);
1228 v_camera[c]->s_estim_int.aspect = sqrt(a2);
1229 v_camera[c]->s_estim_int.u0 = -v_w13/v_w11;
1230 v_camera[c]->s_estim_int.v0 = -v_w23/v_w22;
1231 
1232 // Realease temporary matices:
1233 cvReleaseMat( &m_EVE );
1234 cvReleaseMat( &m_EVA );
1235 cvReleaseMat( &m_ATA );
1236 cvReleaseMat( &m_A );
1237 
1238 printf( "%f %f %f %f\n", v_camera[c]->s_estim_int.focal, v_camera[c]->s_estim_int.aspect, v_camera[c]->s_estim_int.u0, v_camera[c]->s_estim_int.v0 );
1239 if( c == 4)
1240 return false;
1241 
1242 return true;
1243 }*/
1244 
1245 void CamCalibration::CreateCalibrationMatrixFromIntrinsicParameters( int c ){
1246  cvmSet( GetM(m_calibration,c,0), 0, 0, v_camera[c]->s_intrinsic.aspect*v_camera[c]->s_intrinsic.focal );
1247  cvmSet( GetM(m_calibration,c,0), 0, 1, 0.00 );
1248  cvmSet( GetM(m_calibration,c,0), 0, 2, v_camera[c]->s_intrinsic.u0 );
1249  cvmSet( GetM(m_calibration,c,0), 1, 0, 0.00 );
1250  cvmSet( GetM(m_calibration,c,0), 1, 1, v_camera[c]->s_intrinsic.focal );
1251  cvmSet( GetM(m_calibration,c,0), 1, 2, v_camera[c]->s_intrinsic.v0 );
1252  cvmSet( GetM(m_calibration,c,0), 2, 0, 0.00 );
1253  cvmSet( GetM(m_calibration,c,0), 2, 1, 0.00 );
1254  cvmSet( GetM(m_calibration,c,0), 2, 2, 1.00 );
1255 }
1256 
1257 void CamCalibration::CreateEstimatedCalibrationMatrixFromEstimatedIntrinsicParameters( int c ){
1258  cvmSet( GetM(m_estim_calib,c,0), 0, 0, v_camera[c]->s_estim_int.aspect*v_camera[c]->s_estim_int.focal );
1259  cvmSet( GetM(m_estim_calib,c,0), 0, 1, 0.00 );
1260  cvmSet( GetM(m_estim_calib,c,0), 0, 2, v_camera[c]->s_estim_int.u0 );
1261  cvmSet( GetM(m_estim_calib,c,0), 1, 0, 0.00 );
1262  cvmSet( GetM(m_estim_calib,c,0), 1, 1, v_camera[c]->s_estim_int.focal );
1263  cvmSet( GetM(m_estim_calib,c,0), 1, 2, v_camera[c]->s_estim_int.v0 );
1264  cvmSet( GetM(m_estim_calib,c,0), 2, 0, 0.00 );
1265  cvmSet( GetM(m_estim_calib,c,0), 2, 1, 0.00 );
1266  cvmSet( GetM(m_estim_calib,c,0), 2, 2, 1.00 );
1267 }
1268 
1269 void CamCalibration::CreateEstimatedInverseCalibrationMatrixFromEstimatedIntrinsicParameters( int c ){
1270  double tau = v_camera[c]->s_estim_int.aspect;
1271  double f = v_camera[c]->s_estim_int.focal;
1272  cvmSet( GetM(m_estinvcalib,c,0), 0, 0, 1.00/(tau*f) );
1273  cvmSet( GetM(m_estinvcalib,c,0), 0, 1, 0.00 );
1274  cvmSet( GetM(m_estinvcalib,c,0), 0, 2, -(v_camera[c]->s_estim_int.u0)/(tau*f) );
1275  cvmSet( GetM(m_estinvcalib,c,0), 1, 0, 0.00 );
1276  cvmSet( GetM(m_estinvcalib,c,0), 1, 1, 1.00/f );
1277  cvmSet( GetM(m_estinvcalib,c,0), 1, 2, -(v_camera[c]->s_estim_int.v0)/f );
1278  cvmSet( GetM(m_estinvcalib,c,0), 2, 0, 0.00 );
1279  cvmSet( GetM(m_estinvcalib,c,0), 2, 1, 0.00 );
1280  cvmSet( GetM(m_estinvcalib,c,0), 2, 2, 1.00 );
1281 }
1282 
1283 void CamCalibration::CreateRotationTranslationMatrixFromInverseCalibrationMatrixAndHomography( int c, int h ){
1284  int i;
1285 
1286  // Get pointer to homography:
1287  homography* m_homography = v_camera[c]->v_homography[h]->m_homography;
1288 
1289  if( m_homography ){
1290 
1291  // Vectors holding columns of H and R:
1292  double a_H1[3];
1293  CvMat m_H1 = cvMat( 3, 1, CV_64FC1, a_H1 );
1294  for( i = 0; i < 3; i++ ) cvmSet( &m_H1, i, 0, cvmGet( m_homography, i, 0 ) );
1295 
1296  double a_H2[3];
1297  CvMat m_H2 = cvMat( 3, 1, CV_64FC1, a_H2 );
1298  for( i = 0; i < 3; i++ ) cvmSet( &m_H2, i, 0, cvmGet( m_homography, i, 1 ) );
1299 
1300  double a_H3[3];
1301  CvMat m_H3 = cvMat( 3, 1, CV_64FC1, a_H3 );
1302  for( i = 0; i < 3; i++ ) cvmSet( &m_H3, i, 0, cvmGet( m_homography, i, 2 ) );
1303 
1304  double a_CinvH1[3];
1305  CvMat m_CinvH1 = cvMat( 3, 1, CV_64FC1, a_CinvH1 );
1306 
1307  double a_R1[3];
1308  CvMat m_R1 = cvMat( 3, 1, CV_64FC1, a_R1 );
1309 
1310  double a_R2[3];
1311  CvMat m_R2 = cvMat( 3, 1, CV_64FC1, a_R2 );
1312 
1313  double a_R3[3];
1314  CvMat m_R3 = cvMat( 3, 1, CV_64FC1, a_R3 );
1315 
1316  // The rotation matrix:
1317  double a_R[9];
1318  CvMat m_R = cvMat( 3, 3, CV_64FC1, a_R );
1319 
1320  // The translation vector:
1321  double a_T[3];
1322  CvMat m_T = cvMat( 3, 1, CV_64FC1, a_T );
1323 
1325  // Create norming factor lambda:
1326  cvGEMM( GetM(m_estinvcalib,c,0), &m_H1, 1, NULL, 0, &m_CinvH1, 0 );
1327 
1328  // Search next orthonormal matrix:
1329  if( cvNorm( &m_CinvH1, NULL, CV_L2, NULL ) != 0 ){
1330  double lambda = 1.00/cvNorm( &m_CinvH1, NULL, CV_L2, NULL );
1331 
1332  // Create normalized R1 & R2:
1333  cvGEMM( GetM(m_estinvcalib,c,0), &m_H1, lambda, NULL, 0, &m_R1, 0 );
1334  cvGEMM( GetM(m_estinvcalib,c,0), &m_H2, lambda, NULL, 0, &m_R2, 0 );
1335 
1336  // Get R3 orthonormal to R1 and R2:
1337  cvCrossProduct( &m_R1, &m_R2, &m_R3 );
1338 
1339  // Put the rotation column vectors in the rotation matrix:
1340  for( i = 0; i < 3; i++ ){
1341  cvmSet( &m_R, i, 0, cvmGet( &m_R1, i, 0 ) );
1342  cvmSet( &m_R, i, 1, cvmGet( &m_R2, i, 0 ) );
1343  cvmSet( &m_R, i, 2, cvmGet( &m_R3, i, 0 ) );
1344  }
1345 
1346  // Calculate Translation Vector T (- because of its definition):
1347  cvGEMM( GetM(m_estinvcalib,c,0), &m_H3, -lambda, NULL, 0, &m_T, 0 );
1348 
1349  // Transformation of R into - in Frobenius sense - next orthonormal matrix:
1350  double a_W[9]; CvMat m_W = cvMat( 3, 3, CV_64FC1, a_W );
1351  double a_U[9]; CvMat m_U = cvMat( 3, 3, CV_64FC1, a_U );
1352  double a_Vt[9]; CvMat m_Vt = cvMat( 3, 3, CV_64FC1, a_Vt );
1353  cvSVD( &m_R, &m_W, &m_U, &m_Vt, CV_SVD_MODIFY_A | CV_SVD_V_T );
1354  cvMatMul( &m_U, &m_Vt, &m_R );
1355 
1356  // Put the rotation matrix and the translation vector together:
1357  ComposeRotationTranslationTo3x4Matrix( GetM(m_estim_r_t,c,h), &m_R, &m_T );
1358  }
1359  }
1360 }
1361 
1362 void CamCalibration::CreateRotationTranslationIdentityMatrix( int c ){
1363  for( int i=0; i<3; i++ )
1364  for( int j=0; j<4; j++ )
1365  cvmSet( GetM(m_rot_trans,c,0), i, j, 0.0 );
1366  cvmSet( GetM(m_rot_trans,c,0), 0, 0, 1.0 );
1367  cvmSet( GetM(m_rot_trans,c,1), 1, 1, 1.0 );
1368  cvmSet( GetM(m_rot_trans,c,2), 2, 2, 1.0 );
1369 }
1370 
1371 void CamCalibration::CreateRotationTranslationMatrix( int c, double rx, double ry, double rz,
1372  double tx, double ty, double tz ){
1373  rx *= 2*M_PI/360.00;
1374  ry *= 2*M_PI/360.00;
1375  rz *= 2*M_PI/360.00;
1376  double a_R[] = { 1, 0, 0,
1377  0, 1, 0,
1378  0, 0, 1 };
1379  double a_Rx[] = { 1, 0, 0,
1380  0, cos(rx), -sin(rx),
1381  0, sin(rx), cos(rx) };
1382  double a_Ry[] = { cos(ry), 0, -sin(ry),
1383  0, 1, 0,
1384  sin(ry), 0, cos(ry) };
1385  double a_Rz[] = { cos(rz), -sin(rz), 0,
1386  sin(rz), cos(rz), 0,
1387  0, 0, 1 };
1388  CvMat m_R = cvMat( 3, 3, CV_64FC1, a_R );
1389  CvMat m_Rx = cvMat( 3, 3, CV_64FC1, a_Rx );
1390  CvMat m_Ry = cvMat( 3, 3, CV_64FC1, a_Ry );
1391  CvMat m_Rz = cvMat( 3, 3, CV_64FC1, a_Rz );
1392  cvMatMul( &m_Rx, &m_R, &m_R );
1393  cvMatMul( &m_Ry, &m_R, &m_R );
1394  cvMatMul( &m_Rz, &m_R, &m_R );
1395 
1396  for( int i = 0; i < 3; i++ )
1397  for( int j = 0; j < 3; j++ )
1398  cvmSet( GetM(m_rot_trans,c,0), i, j, cvmGet( &m_R, i, j ) );
1399 
1400  cvmSet( GetM(m_rot_trans,c,0), 0, 3, -tx );
1401  cvmSet( GetM(m_rot_trans,c,0), 1, 3, -ty );
1402  cvmSet( GetM(m_rot_trans,c,0), 2, 3, -tz );
1403 }
1404 
1405 void CamCalibration::CreateEstimated3ChainMatrixRT( int h1, int c2, int h2, int c1 ){
1406  double a_RTinv[12]; CvMat m_RTinv = cvMat( 3, 4, CV_64FC1, a_RTinv );
1407  CvMat *m_RT11 = v_camera[c1]->v_homography[h1]->m_estim_r_t_matrix;
1408  CvMat *m_RT12 = v_camera[c1]->v_homography[h2]->m_estim_r_t_matrix;
1409  CvMat *m_RT21 = v_camera[c2]->v_homography[h1]->m_estim_r_t_matrix;
1410  CvMat *m_RT22 = v_camera[c2]->v_homography[h2]->m_estim_r_t_matrix;
1411  Mat3x4Inverse( m_RT22, &m_RTinv );
1412  Mat3x4Mul( m_RT21, &m_RTinv, m_RT11 );
1413  Mat3x4Mul( m_RT11, m_RT12, m_RT11 );
1414 }
1415 
1416 void CamCalibration::CreateEstimatedOptimalHomographyMatrixRT( int h1, int c1, int h2 ){
1417  double a_RTinv[12]; CvMat m_RTinv = cvMat( 3, 4, CV_64FC1, a_RTinv );
1418  CvMat *m_RT11 = v_camera[c1]->v_homography[h1]->m_estim_r_t_matrix;
1419  CvMat *m_RT12 = v_camera[c1]->v_homography[h2]->m_estim_r_t_matrix;
1420  Mat3x4Inverse( m_RT12, &m_RTinv );
1421  s_optimal.v_homography_r_t[h1] = cvCreateMat( 3, 4, CV_64FC1 );
1422  Mat3x4Mul( &m_RTinv, m_RT11, s_optimal.v_homography_r_t[h1] );
1423 }
1424 
1425 void CamCalibration::CreateEstimatedOptimalCameraMatrixC( int c ){
1426  s_optimal.v_camera_c[c] = cvCloneMat( v_camera[c]->m_estim_calib_matrix );
1427 }
1428 
1429 void CamCalibration::CreateEstimatedOptimalCameraMatrixRT( int c, int h ){
1430  s_optimal.v_camera_r_t[c] = cvCloneMat( v_camera[c]->v_homography[h]->m_estim_r_t_matrix );
1431 }
1432 
1433 bool CamCalibration::CreateMatrixCH(){
1434 
1435  // Release old CV matrix:
1436  if( m_CH )
1437  cvReleaseMat( &m_CH );
1438 
1439  m_CH = cvCreateMat( v_camera.size(), v_camera[0]->v_homography.size(), CV_64FC1 );
1440  s_optimal.c_max = -1; s_optimal.h_max = -1;
1441 
1442  // Search for all existing connections:
1443  int cnt = 0;
1444  for( int c = 0; c < (int)v_camera.size(); c++ )
1445  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ ){
1446  cvmSet( m_CH, c, h, v_camera[c]->v_homography[h]->m_homography ? 1 : 0 );
1447  if( v_camera[c]->v_homography[h]->m_homography )
1448  cnt++;
1449  }
1450 
1451  printf("\nOriginal connection matrix (connections: %i):\n",cnt);
1452  showmatrix_ch(*m_CH);
1453 
1454  // Find plane with most camera connections:
1455  int cmax = -1; int hmax = -1; int max = -1;
1456  for( int h = 0; h < (int)v_camera[0]->v_homography.size(); h++ ){
1457  int i = 0;
1458  for( int c = 0; c < (int)v_camera.size(); c++ )
1459  if( cvmGet( m_CH, c, h ) == 1 )
1460  i++;
1461  if( i > max ){
1462  max = i;
1463  hmax = h;
1464  }
1465  }
1466 
1467  // Find camera inside plane with most plane connections:
1468  max = -1;
1469  for( int c = 0; c < (int)v_camera.size(); c++ ){
1470  if( cvmGet( m_CH, c, hmax ) == 1 ){
1471  int i = 0;
1472  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
1473  if( cvmGet( m_CH, c, h ) == 1 )
1474  i++;
1475  if( i > max ){
1476  max = i;
1477  cmax = c;
1478  }
1479  }
1480  }
1481 
1482  // If no maximum row or column found return false:
1483  if( cmax == -1 || hmax == -1 ){
1484  cvReleaseMat( &m_CH );
1485  m_CH = NULL;
1486  if( cmax == -1 )
1487  printf("ERROR: Camera with maximal plane connections could not be estimated!\n");
1488  else
1489  printf("ERROR: Plane with maximal camera connections could not be estimated!\n");
1490  return false;
1491  }
1492 
1493  bool big_briged;
1494  do{
1495  big_briged = false;
1496  for( int c1 = 0; c1 < (int)v_camera.size(); c1++ ){
1497  for( int h1 = 0; h1 < (int)v_camera[c1]->v_homography.size(); h1++ ){
1498  if( cvmGet( m_CH, c1, h1 ) == 0 ){
1499  bool briged = false;
1500  for( int c2 = 0; c2 < (int)v_camera.size(); c2++ ){
1501  for( int h2 = 0; h2 < (int)v_camera[c2]->v_homography.size(); h2++ ){
1502  if( (cvmGet( m_CH, c1, h2 ) == 1 || cvmGet( m_CH, c1, h2 ) == 2) &&
1503  (cvmGet( m_CH, c2, h1 ) == 1 || cvmGet( m_CH, c2, h1 ) == 2) &&
1504  (cvmGet( m_CH, c2, h2 ) == 1 || cvmGet( m_CH, c2, h2 ) == 2) &&
1505  c1 != c2 && h1 != h2 ){
1506 
1507  briged = true;
1508  big_briged = true;
1509  cvmSet( m_CH, c1, h1, 1 );
1510  CreateEstimated3ChainMatrixRT( h1, c2, h2, c1 );
1511  }
1512  if( briged ) break;
1513  }
1514  if( briged ) break;
1515  }
1516  }
1517  }
1518  }
1519  } while( big_briged );
1520 
1521  s_optimal.c_max = cmax;
1522  s_optimal.h_max = hmax;
1523 
1524  printf("\nNew connection matrix (cmax: %i, hmax: %i, connections: %i):\n",cmax,hmax,cnt);
1525  showmatrix_ch(*m_CH);
1526 
1527  // Check if all cameras are connected:
1528  for( int c = 0; c < (int)v_camera.size(); c++ ){
1529  if( cvmGet( m_CH, c, hmax ) == 0 ){
1530  printf("ERROR: Not enough links to connect camera %i to main camera %i!\n",c,cmax);
1531  return false;
1532  }
1533  }
1534 
1535  return true;
1536 }
1537 
1538 void CamCalibration::ReleaseOptimalCameraStructure(){
1539  for( int i = 0; i < (int)s_optimal.v_camera_c.size(); i++ ) cvReleaseMat(&s_optimal.v_camera_c[i]);
1540  s_optimal.v_camera_c.clear();
1541  for( int i = 0; i < (int)s_optimal.v_camera_r_t.size(); i++ ) cvReleaseMat(&s_optimal.v_camera_r_t[i]);
1542  s_optimal.v_camera_r_t.clear();
1543  for( int i = 0; i < (int)s_optimal.v_camera_r_t_jacobian.size(); i++ ) cvReleaseMat(&s_optimal.v_camera_r_t_jacobian[i]);
1544  s_optimal.v_camera_r_t_jacobian.clear();
1545  for( int i = 0; i < (int)s_optimal.v_homography_r_t.size(); i++ ) cvReleaseMat(&s_optimal.v_homography_r_t[i]);
1546  s_optimal.v_homography_r_t.clear();
1547  for( int i = 0; i < (int)s_optimal.v_homography_r_t_jacobian.size(); i++ ) cvReleaseMat(&s_optimal.v_homography_r_t_jacobian[i]);
1548  s_optimal.v_homography_r_t_jacobian.clear();
1549 }
1550 
1551 bool CamCalibration::CreateOptimalCameraStructure(){
1552  ReleaseOptimalCameraStructure();
1553 
1554  if( !CreateMatrixCH() ){
1555  printf("ERROR: Connection matrix could not be constructed!\n");
1556  return false;
1557  }
1558 
1559  // Create all camera & calibration matrices:
1560  for( int c = 0; c < m_CH->height; c++ ){
1561  s_optimal.v_camera_r_t.push_back( NULL );
1562  CreateEstimatedOptimalCameraMatrixRT( c, s_optimal.h_max );
1563  s_optimal.v_camera_c.push_back( NULL );
1564  CreateEstimatedOptimalCameraMatrixC( c );
1565  s_optimal.v_camera_r_t_jacobian.push_back( cvCreateMat( 3, 9, CV_64FC1 ) );
1566  }
1567 
1568  // Create all possible plane matrices (others = NULL):
1569  for( int h = 0; h < m_CH->width; h++ ){
1570  s_optimal.v_homography_r_t.push_back( NULL );
1571  if( cvmGet( m_CH, s_optimal.c_max, h ) == 1 || cvmGet( m_CH, s_optimal.c_max, h ) == 2 )
1572  CreateEstimatedOptimalHomographyMatrixRT( h, s_optimal.c_max, s_optimal.h_max );
1573  s_optimal.v_homography_r_t_jacobian.push_back( cvCreateMat( 3, 9, CV_64FC1 ) );
1574  }
1575 
1576  return true;
1577 }
1578 
1580 {
1581  double target[2];
1582  int cam;
1583  int hom;
1584  int point;
1585  static int parameterNumber;
1587  b = target;
1588  }
1589  virtual int get_nb_measures() const { return 2; };
1590  virtual void eval_func(const double *params, double *f, double *J, void **user_data) const;
1591 };
1592 
1594 
1595 void CamCalibration::updateCB( double *params , void **user_data){
1596  CamCalibration *cam = (CamCalibration*) *user_data;
1597 
1598  // Pass parameters to global parameter array:
1599  int parameter_number = cam->GetParameterNumber();
1600  for( int i = 0; i < parameter_number; i++ )
1601  cam->v_opt_param[i] = params[i];
1602 
1603  // Update the optimization structure:
1604  cam->SetParameterSetToOptimalStructure();
1605  cam->PrintOptimizedResultErrors(params);
1606 }
1607 
1608 //void CamCalibration::projFunc( double *x, double *params, int na, double *f, double *grad, int *ind, LsqData *Data ){
1609 void ProjObs::eval_func(const double *params, double *f, double *J, void **user_data) const {
1610  CamCalibration *cam = (CamCalibration*) *user_data;
1611 
1612  // Unpack arguments:
1613  int c = this->cam;
1614  int h = hom;
1615 
1616  double *grad0 = J;
1617  double *grad1 = J+parameterNumber;
1618 
1619  // Project the point (CRTp) and set f:
1620  double a_p[4]; double a_p3[3]; double a_p4[3];
1621  double a_RT[12]; CvMat m_RT = cvMat( 3, 4, CV_64FC1, a_RT );
1622  a_p[0] = cam->v_camera[c]->v_homography[h]->s_plane_object->px[point]; a_p[2] = 0;
1623  a_p[1] = cam->v_camera[c]->v_homography[h]->s_plane_object->py[point]; a_p[3] = 1;
1624  CvMat m_p = cvMat( 4, 1, CV_64FC1, a_p ); // plane point (flat)
1625  CvMat m_p3 = cvMat( 3, 1, CV_64FC1, a_p3 ); // eye point 2
1626  CvMat m_p4 = cvMat( 3, 1, CV_64FC1, a_p4 ); // image point
1627  cam->Mat3x4Mul( cam->s_optimal.v_camera_r_t[c], cam->s_optimal.v_homography_r_t[h], &m_RT );
1628  cvMatMul( &m_RT, &m_p, &m_p3 );
1629  cvMatMul( cam->s_optimal.v_camera_c[c], &m_p3, &m_p4 );
1630  cam->HomogenousNormalizeVector( &m_p4 );
1631  f[0] = cvmGet( &m_p4, 0, 0 );
1632  f[1] = cvmGet( &m_p4, 1, 0 );
1633 
1634  int gc = 0;
1635  if( J ){
1636 
1637  // Gradient of camera calibration parameters:
1638  for( int g_c = 0; g_c < (int)cam->s_optimal.v_camera_c.size(); g_c++ ){
1639  if( g_c == c ){
1640  grad0[gc] = cvmGet(&m_p3,0,0)/cvmGet(&m_p3,2,0);
1641  grad0[gc+1] = 0;
1642  grad0[gc+2] = 1;
1643  grad0[gc+3] = 0;
1644  grad1[gc] = 0;
1645  grad1[gc+1] = cvmGet(&m_p3,1,0)/cvmGet(&m_p3,2,0);
1646  grad1[gc+2] = 0;
1647  grad1[gc+3] = 1;
1648  } else {
1649  grad0[gc] = 0;
1650  grad0[gc+1] = 0;
1651  grad0[gc+2] = 0;
1652  grad0[gc+3] = 0;
1653  grad1[gc] = 0;
1654  grad1[gc+1] = 0;
1655  grad1[gc+2] = 0;
1656  grad1[gc+3] = 0;
1657  }
1658  gc+=4;
1659  }
1660 
1661  double a_R1[9]; CvMat m_R1 = cvMat( 3, 3, CV_64FC1, a_R1 );
1662  double a_T1[3]; CvMat m_T1 = cvMat( 3, 1, CV_64FC1, a_T1 );
1663  double a_R2[9]; CvMat m_R2 = cvMat( 3, 3, CV_64FC1, a_R2 );
1664  double a_T2[3]; CvMat m_T2 = cvMat( 3, 1, CV_64FC1, a_T2 );
1665  cam->ExtractRotationTranslationFrom3x4Matrix( cam->s_optimal.v_camera_r_t[c], &m_R1, &m_T1 );
1666  cam->ExtractRotationTranslationFrom3x4Matrix( cam->s_optimal.v_homography_r_t[h], &m_R2, &m_T2 );
1667 
1668  double R1[3][3];
1669  for( int i = 0; i < 3; i++ )
1670  for( int j = 0; j < 3; j++ )
1671  R1[i][j] = cvmGet( &m_R1, i, j );
1672 
1673  double R2[3][3];
1674  for( int i = 0; i < 3; i++ )
1675  for( int j = 0; j < 3; j++ )
1676  R2[i][j] = cvmGet( &m_R2, i, j );
1677 
1678  double cgret[24];
1679  double uv[2];
1680 
1681  twomat_gradian ( params[c*4+0],
1682  params[c*4+1],
1683  params[c*4+2],
1684  params[c*4+3],
1685  R1,
1686  -cvmGet( &m_T1, 0, 0 ),
1687  -cvmGet( &m_T1, 1, 0 ),
1688  -cvmGet( &m_T1, 2, 0 ),
1689  cam->s_optimal.v_camera_r_t_jacobian[c],
1690  R2,
1691  -cvmGet( &m_T2, 0, 0 ),
1692  -cvmGet( &m_T2, 1, 0 ),
1693  -cvmGet( &m_T2, 2, 0 ),
1694  cam->s_optimal.v_homography_r_t_jacobian[h],
1695  a_p,
1696  cgret, uv );
1697 
1698  // Gradient of camera RT matrices:
1699  for( int g_c = 0; g_c < (int)cam->s_optimal.v_camera_r_t.size(); g_c++ ){
1700  if( g_c == c ){
1701  for( int i = 0; i < 3; i++ )
1702  grad0[gc+i] = cgret[i+3];
1703  for( int i = 0; i < 3; i++ )
1704  grad0[gc+3+i] = cgret[i];
1705  for( int i = 0; i < 3; i++ )
1706  grad1[gc+i] = cgret[12+i+3];
1707  for( int i = 0; i < 3; i++ )
1708  grad1[gc+3+i] = cgret[12+i];
1709  } else {
1710  for( int i = 0; i < 6; i++ ) {
1711  grad0[gc+i] = 0;
1712  grad1[gc+i] = 0;
1713  }
1714  }
1715  gc+=6;
1716  }
1717 
1718  // Gradient of homography RT matrices:
1719  for( int g_h = 0; g_h < (int)cam->s_optimal.v_homography_r_t.size(); g_h++ ){
1720 
1721  // If not plane itself (Identity) and plane is connected to main plane:
1722  if( g_h != cam->s_optimal.h_max && cvmGet( cam->m_CH, cam->s_optimal.c_max, g_h ) == 1 ){
1723  if( g_h == h ){
1724  for( int i = 0; i < 3; i++ )
1725  grad0[gc+i] = cgret[6+i+3];
1726  for( int i = 0; i < 3; i++ )
1727  grad0[gc+i+3] = cgret[6+i];
1728  for( int i = 0; i < 3; i++ )
1729  grad1[gc+i] = cgret[12+6+i+3];
1730  for( int i = 0; i < 3; i++ )
1731  grad1[gc+i+3] = cgret[12+6+i];
1732  } else {
1733  for( int i = 0; i < 6; i++ ) {
1734  grad0[gc+i] = 0;
1735  grad1[gc+i] = 0;
1736  }
1737  }
1738  gc+=6;
1739  }
1740  }
1741  }
1742 }
1743 
1744 int CamCalibration::GetParameterNumber(){
1745  int i = 0;
1746 
1747  for( int c = 0; c < (int)s_optimal.v_camera_r_t.size(); c++ )
1748  i+=6;
1749 
1750  for( int h = 0; h < (int)s_optimal.v_homography_r_t.size(); h++ )
1751  // If connection found and not plane itself (Identity)
1752  if( h != s_optimal.h_max && cvmGet( m_CH, s_optimal.c_max, h ) == 1 /*|| cvmGet( m_CH, s_optimal.c_max, h ) == 2)*/ )
1753  i+=6;
1754 
1755  return 4*(int)s_optimal.v_camera_r_t.size()+i;
1756 }
1757 
1758 int CamCalibration::GetObservationNumber(){
1759  int i = 0;
1760  for( int c = 0; c < (int)v_camera.size(); c++ )
1761  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ )
1762  if( v_camera[c]->v_homography[h]->m_homography )
1763  i += v_camera[c]->v_homography[h]->s_plane_object->p*2;
1764  return i;
1765 }
1766 
1767 void CamCalibration::GetParameterSetFromOptimalStructure(){
1768  // Clear old vector:
1769  v_opt_param.clear();
1770 
1771  // Pack camera calibration parameters:
1772  for( int c = 0; c < (int)s_optimal.v_camera_c.size(); c++ ){
1773  v_opt_param.push_back( cvmGet( s_optimal.v_camera_c[c], 0, 0 ) ); // f
1774  v_opt_param.push_back( cvmGet( s_optimal.v_camera_c[c], 1, 1 ) ); // g
1775  v_opt_param.push_back( cvmGet( s_optimal.v_camera_c[c], 0, 2 ) ); // u0
1776  v_opt_param.push_back( cvmGet( s_optimal.v_camera_c[c], 1, 2 ) ); // v0
1777  }
1778 
1779  double a_R[9]; CvMat m_R = cvMat( 3, 3, CV_64FC1, a_R );
1780  double a_r[3]; CvMat m_r = cvMat( 3, 1, CV_64FC1, a_r );
1781  double a_T[3]; CvMat m_T = cvMat( 3, 1, CV_64FC1, a_T );
1782 
1783  // Pack Camera RT matrices:
1784  for( int c = 0; c < (int)s_optimal.v_camera_r_t.size(); c++ ){
1785  ExtractRotationTranslationFrom3x4Matrix( s_optimal.v_camera_r_t[c], &m_R, &m_T);
1786  v_opt_param.push_back( -cvmGet( &m_T, 0, 0 ) );
1787  v_opt_param.push_back( -cvmGet( &m_T, 1, 0 ) );
1788  v_opt_param.push_back( -cvmGet( &m_T, 2, 0 ) );
1789  cvRodrigues2( &m_R, &m_r, 0 );
1790  v_opt_param.push_back( cvmGet( &m_r, 0, 0 ) );
1791  v_opt_param.push_back( cvmGet( &m_r, 1, 0 ) );
1792  v_opt_param.push_back( cvmGet( &m_r, 2, 0 ) );
1793  }
1794 
1795  // Pack Homography RT matrices:
1796  for( int h = 0; h < (int)s_optimal.v_homography_r_t.size(); h++ ){
1797  // Pack to arguments if not reference plane itself (Identity)
1798  if( h != s_optimal.h_max && cvmGet( m_CH, s_optimal.c_max, h ) == 1 ){
1799  ExtractRotationTranslationFrom3x4Matrix( s_optimal.v_homography_r_t[h], &m_R, &m_T);
1800  v_opt_param.push_back( -cvmGet( &m_T, 0, 0 ) );
1801  v_opt_param.push_back( -cvmGet( &m_T, 1, 0 ) );
1802  v_opt_param.push_back( -cvmGet( &m_T, 2, 0 ) );
1803  cvRodrigues2( &m_R, &m_r, 0 );
1804  v_opt_param.push_back( cvmGet( &m_r, 0, 0 ) );
1805  v_opt_param.push_back( cvmGet( &m_r, 1, 0 ) );
1806  v_opt_param.push_back( cvmGet( &m_r, 2, 0 ) );
1807  }
1808  }
1809 }
1810 
1811 static CvPoint cvPoint(double a, double b)
1812 {
1813  return cvPoint((int)a, (int)b);
1814 }
1815 
1816 void CamCalibration::SetParameterSetToOptimalStructure(){
1817  int i = 0;
1818 
1819  // Unpack camera calibration parameters:
1820  for( int c = 0; c < (int)s_optimal.v_camera_c.size(); c++ ){
1821  cvmSet( s_optimal.v_camera_c[c], 0, 0, v_opt_param[i++] ); // f
1822  cvmSet( s_optimal.v_camera_c[c], 1, 1, v_opt_param[i++] ); // g
1823  cvmSet( s_optimal.v_camera_c[c], 0, 2, v_opt_param[i++] ); // u0
1824  cvmSet( s_optimal.v_camera_c[c], 1, 2, v_opt_param[i++] ); // v0
1825  }
1826 
1827  double a_R[9]; CvMat m_R = cvMat( 3, 3, CV_64FC1, a_R );
1828  double a_r[3]; CvMat m_r = cvMat( 3, 1, CV_64FC1, a_r );
1829  double a_T[3]; CvMat m_T = cvMat( 3, 1, CV_64FC1, a_T );
1830 
1831  // Unpack Camera RT matrices:
1832  for( int c = 0; c < (int)s_optimal.v_camera_r_t.size(); c++ ){
1833  cvmSet( &m_T, 0, 0, -v_opt_param[i++] );
1834  cvmSet( &m_T, 1, 0, -v_opt_param[i++] );
1835  cvmSet( &m_T, 2, 0, -v_opt_param[i++] );
1836  cvmSet( &m_r, 0, 0, v_opt_param[i++] );
1837  cvmSet( &m_r, 1, 0, v_opt_param[i++] );
1838  cvmSet( &m_r, 2, 0, v_opt_param[i++] );
1839  cvRodrigues2( &m_r, &m_R, s_optimal.v_camera_r_t_jacobian[c] );
1840  ComposeRotationTranslationTo3x4Matrix( s_optimal.v_camera_r_t[c], &m_R, &m_T);
1841  }
1842 
1843  // Unpack Homography RT matrices:
1844  for( int h = 0; h < (int)s_optimal.v_homography_r_t.size(); h++ ){
1845  // Pack to arguments if not plane itself (Identity)
1846  if( h != s_optimal.h_max && (cvmGet( m_CH, s_optimal.c_max, h ) == 1 || cvmGet( m_CH, s_optimal.c_max, h ) == 1) ){
1847  cvmSet( &m_T, 0, 0, -v_opt_param[i++] );
1848  cvmSet( &m_T, 1, 0, -v_opt_param[i++] );
1849  cvmSet( &m_T, 2, 0, -v_opt_param[i++] );
1850  cvmSet( &m_r, 0, 0, v_opt_param[i++] );
1851  cvmSet( &m_r, 1, 0, v_opt_param[i++] );
1852  cvmSet( &m_r, 2, 0, v_opt_param[i++] );
1853  cvRodrigues2( &m_r, &m_R, s_optimal.v_homography_r_t_jacobian[h] );
1854  ComposeRotationTranslationTo3x4Matrix( s_optimal.v_homography_r_t[h], &m_R, &m_T);
1855  }
1856  }
1857 }
1858 
1860  char file_name[200];
1861  IplImage * image[5]; // TODO: flexibel!!
1862  int cnt = 0;
1863  for( int h = 0; h < (int)v_camera[0]->v_homography.size(); h++ ){
1864  for( int c = 0; c < (int)v_camera.size(); c++ ){
1865  if( cvmGet( m_CH, c, h ) == 1 ){
1866  sprintf(file_name,"E:\\andreas_camcal_16_12_2005\\cam%02d%04d.bmp",c+1,h+2048); //TODO: 2048!!!!!
1867  if( image[c] = cvLoadImage( file_name, 1 ) ){
1868  // Draw box:
1869  FILE * boxfile;
1870  if( (boxfile = fopen( "box.txt", "r+t" )) != NULL ){
1871  for( int j = 0; j < 6; j++ ){
1872  double p[4][2];
1873  for( int i = 0; (i < 4 && j < 2) || i < 2; i++ ){
1874  double a_p[4]; double a_p3[3]; double a_p4[3];
1875  double a_RT[12]; CvMat m_RT = cvMat( 3, 4, CV_64FC1, a_RT );
1876  float x, y, z;
1877  fscanf( boxfile, "%f %f %f\n", &x, &y, &z );
1878  a_p[0] = x; a_p[1] = y; a_p[2] = z; a_p[3] = 1;
1879  CvMat m_p = cvMat( 4, 1, CV_64FC1, a_p ); // plane point (flat)
1880  CvMat m_p3 = cvMat( 3, 1, CV_64FC1, a_p3 ); // eye point 2
1881  CvMat m_p4 = cvMat( 3, 1, CV_64FC1, a_p4 ); // image point
1882  Mat3x4Mul( s_optimal.v_camera_r_t[c], s_optimal.v_homography_r_t[h], &m_RT );
1883  cvMatMul( &m_RT, &m_p, &m_p3 );
1884  cvMatMul( s_optimal.v_camera_c[c], &m_p3, &m_p4 );
1885  HomogenousNormalizeVector( &m_p4 );
1886  p[i][0] = cvmGet( &m_p4, 0, 0 );
1887  p[i][1] = cvmGet( &m_p4, 1, 0 );
1888  }
1889  CvScalar color = CV_RGB ( 0,0,0 );
1890  if( j == 0 ) color = CV_RGB ( 255,200,0 );
1891  if( j >= 1 ) color = CV_RGB ( 155,100,0 );
1892  cvLine( image[c], cvPoint( p[0][0],p[0][1] ), cvPoint( p[1][0],p[1][1] ), color,4,CV_AA,0 );
1893  if( j < 2 ){
1894  cvLine( image[c], cvPoint( p[1][0],p[1][1] ), cvPoint( p[2][0],p[2][1] ), color,4,CV_AA,0 );
1895  cvLine( image[c], cvPoint( p[2][0],p[2][1] ), cvPoint( p[3][0],p[3][1] ), color,4,CV_AA,0 );
1896  cvLine( image[c], cvPoint( p[3][0],p[3][1] ), cvPoint( p[0][0],p[0][1] ), color,4,CV_AA,0 );
1897  }
1898  }
1899  fclose(boxfile);
1900  }
1901  }
1902  }
1903  }
1904  if( cvmGet( m_CH, 0, h ) == 1 &&
1905  cvmGet( m_CH, 1, h ) == 1 &&
1906  cvmGet( m_CH, 2, h ) == 1 &&
1907  cvmGet( m_CH, 3, h ) == 1 &&
1908  cvmGet( m_CH, 4, h ) == 1 ){ //TODO: 0 (alle testen!) intelligenter!!!
1909  // Save image:
1910  IplImage *im = cvCreateImage(cvSize(980,480), IPL_DEPTH_8U, 3);
1911  cvSetImageROI(im, cvRect(0,0,320,240)); cvResize(image[0], im, CV_INTER_LINEAR );
1912  cvSetImageROI(im, cvRect(320,0,320,240)); cvResize(image[1], im, CV_INTER_LINEAR );
1913  cvSetImageROI(im, cvRect(640,0,320,240)); cvResize(image[2], im, CV_INTER_LINEAR );
1914  cvSetImageROI(im, cvRect(0,240,320,240)); cvResize(image[3], im, CV_INTER_LINEAR );
1915  cvSetImageROI(im, cvRect(320,240,320,240)); cvResize(image[4], im, CV_INTER_LINEAR );
1916  cvResetImageROI(im);
1917  cvLine( im, cvPoint( 0,240 ), cvPoint( 980,240 ), CV_RGB ( 255,255,255 ),2,CV_AA,0 );
1918  cvLine( im, cvPoint( 320,0 ), cvPoint( 320,480 ), CV_RGB ( 255,255,255 ),2,CV_AA,0 );
1919  cvLine( im, cvPoint( 640,0 ), cvPoint( 640,480 ), CV_RGB ( 255,255,255 ),2,CV_AA,0 );
1920  sprintf(file_name,"__cam%04d_%04d.bmp",cnt,h);
1921  cvSaveImage( file_name, im );
1922  cvReleaseImage( &image[0] ); //TODO!
1923  cvReleaseImage( &image[1] ); //TODO!
1924  cvReleaseImage( &image[2] ); //TODO!
1925  cvReleaseImage( &image[3] ); //TODO!
1926  cvReleaseImage( &image[4] ); //TODO!
1927  cvReleaseImage( &im ); //TODO!
1928  printf("File __cam%04d.bmp written!\n",cnt);
1929  cnt++;
1930  }
1931  }
1932 }
1933 
1934 /*
1935 void CamCalibration::PlotPointsToImagesAfterOptimization(){
1936 char file_name[200];
1937 IplImage * image1;
1938 for( int c = 0; c < (int)v_camera.size(); c++ ) // ... cameras
1939 for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ ) // ... homographies
1940 if( cvmGet( m_CH, c, h ) == 1 ){
1941 sprintf(file_name,"E:\\andreas_camcal_16_12_2005\\cam%02d%04d.bmp",c+1,h+2048);
1942 image1 = cvLoadImage( file_name, 1 );
1943 int points = v_camera[c]->v_homography[h]->s_plane_object->p;
1944 for( int point = 0; point < points; point++ ){
1945 s_struct_plane* s_plane_object = v_camera[c]->v_homography[h]->s_plane_object;
1946 HomogenousNormalizeVector( (*s_plane_object).v_m_pp[point] );
1947 double u1 = cvmGet( (*s_plane_object).v_m_pp[point], 0, 0 );
1948 double v1 = cvmGet( (*s_plane_object).v_m_pp[point], 1, 0 );
1949 double a_p[4]; double a_p3[3]; double a_p4[3];
1950 double a_RT[12]; CvMat m_RT = cvMat( 3, 4, CV_64FC1, a_RT );
1951 a_p[0] = v_camera[c]->v_homography[h]->s_plane_object->px[point]; a_p[2] = 0;
1952 a_p[1] = v_camera[c]->v_homography[h]->s_plane_object->py[point]; a_p[3] = 1;
1953 
1954 // In the new system (u2 - rot):
1955 CvMat m_p = cvMat( 4, 1, CV_64FC1, a_p ); // plane point (flat)
1956 CvMat m_p3 = cvMat( 3, 1, CV_64FC1, a_p3 ); // eye point 2
1957 CvMat m_p4 = cvMat( 3, 1, CV_64FC1, a_p4 ); // image point
1958 Mat3x4Mul( s_optimal.v_camera_r_t[c], s_optimal.v_homography_r_t[h], &m_RT );
1959 cvMatMul( &m_RT, &m_p, &m_p3 );
1960 cvMatMul( s_optimal.v_camera_c[c], &m_p3, &m_p4 );
1961 HomogenousNormalizeVector( &m_p4 );
1962 double u2 = cvmGet( &m_p4, 0, 0 );
1963 double v2 = cvmGet( &m_p4, 1, 0 );
1964 
1965 // In the old system (u4 - hellblau):
1966 cvMatMul( v_camera[c]->v_homography[h]->m_estim_r_t_matrix, &m_p, &m_p3 );
1967 cvMatMul( v_camera[c]->m_estim_calib_matrix, &m_p3, &m_p4 );
1968 HomogenousNormalizeVector( &m_p4 );
1969 double u4 = cvmGet( &m_p4, 0, 0 );
1970 double v4 = cvmGet( &m_p4, 1, 0 );
1971 
1972 double u3;
1973 double v3;
1974 v_camera[c]->v_homography[h]->m_homography->transform_point(
1975 v_camera[c]->v_homography[h]->s_plane_object->px[point],
1976 v_camera[c]->v_homography[h]->s_plane_object->py[point],
1977 &u3,&v3 );
1978 
1979 // Originalmessung gruen:
1980 cvCircle( image1, cvPoint( u1,v1 ), 1, CV_RGB ( 1,255,1 ), 1, CV_AA, 0 );
1981 
1982 // Original Homography gelb:
1983 cvLine( image1, cvPoint( u1,v1 ), cvPoint( u3,v3 ), CV_RGB ( 255,255,1 ),1,CV_AA,0 );
1984 cvCircle( image1, cvPoint( u3,v3 ), 1, CV_RGB ( 255,255,1 ), 1, CV_AA, 0 );
1985 
1986 // Altes System hellblau:
1987 cvCircle( image1, cvPoint( u4,v4 ), 1, CV_RGB ( 1,255,255 ), 2, CV_AA, 0 );
1988 cvLine( image1, cvPoint( u1,v1 ), cvPoint( u4,v4 ), CV_RGB ( 1,255,255 ),2,CV_AA,0 );
1989 
1990 // Endresultat rot:
1991 cvCircle( image1, cvPoint( u2,v2 ), 1, CV_RGB ( 255,1,1 ), 1, CV_AA, 0 );
1992 cvLine( image1, cvPoint( u1,v1 ), cvPoint( u2,v2 ), CV_RGB ( 255,1,1 ),1,CV_AA,0 );
1993 }
1994 
1996 // Draw box:
1997 FILE * boxfile;
1998 if( (boxfile = fopen( "box.txt", "r+t" )) != NULL ){
1999 for( int j = 0; j < 6; j++ ){
2000 double p[4][2];
2001 for( int i = 0; (i < 4 && j < 2) || i < 2; i++ ){
2002 double a_p[4]; double a_p3[3]; double a_p4[3];
2003 double a_RT[12]; CvMat m_RT = cvMat( 3, 4, CV_64FC1, a_RT );
2004 float x, y, z;
2005 fscanf( boxfile, "%f %f %f\n", &x, &y, &z );
2006 a_p[0] = x; a_p[1] = y; a_p[2] = z; a_p[3] = 1;
2007 CvMat m_p = cvMat( 4, 1, CV_64FC1, a_p ); // plane point (flat)
2008 CvMat m_p3 = cvMat( 3, 1, CV_64FC1, a_p3 ); // eye point 2
2009 CvMat m_p4 = cvMat( 3, 1, CV_64FC1, a_p4 ); // image point
2010 Mat3x4Mul( s_optimal.v_camera_r_t[c], s_optimal.v_homography_r_t[h], &m_RT );
2011 cvMatMul( &m_RT, &m_p, &m_p3 );
2012 cvMatMul( s_optimal.v_camera_c[c], &m_p3, &m_p4 );
2013 HomogenousNormalizeVector( &m_p4 );
2014 p[i][0] = cvmGet( &m_p4, 0, 0 );
2015 p[i][1] = cvmGet( &m_p4, 1, 0 );
2016 }
2017 CvScalar color;
2018 if( j == 0 ) color = CV_RGB ( 255,255,255 );
2019 if( j >= 1 ) color = CV_RGB ( 155,155,155 );
2020 cvLine( image1, cvPoint( p[0][0],p[0][1] ), cvPoint( p[1][0],p[1][1] ), color,1,CV_AA,0 );
2021 if( j < 2 ){
2022 cvLine( image1, cvPoint( p[1][0],p[1][1] ), cvPoint( p[2][0],p[2][1] ), color,1,CV_AA,0 );
2023 cvLine( image1, cvPoint( p[2][0],p[2][1] ), cvPoint( p[3][0],p[3][1] ), color,1,CV_AA,0 );
2024 cvLine( image1, cvPoint( p[3][0],p[3][1] ), cvPoint( p[0][0],p[0][1] ), color,1,CV_AA,0 );
2025 }
2026 //printf("lines drawn %f %f %f %f\n",p[0][0],p[0][1],p[1][0],p[1][1]);
2027 }
2028 fclose(boxfile);
2029 }
2030 
2031 // Save image:
2032 sprintf(file_name,"__cam%02d%04d.bmp",c,h);
2033 printf("Image %s saved!\n",file_name);
2034 cvSaveImage( file_name, image1 );
2035 }
2036 }*/
2037 
2038 
2039 void CamCalibration::PrintOptimizedResultErrors( double *params){
2040  CamCalibration *cam = this;
2041 
2042  double total_error_opt = 0;
2043  double total_error_org = 0;
2044  double chi_error_opt = 0;
2045  double chi_error_org = 0;
2046  float error_opt[50000];
2047  float error_org[50000];
2048  float error_gra[10][3000];
2049  int obs = 0;
2050 
2051  // Calculate errors:
2052  for( int c = 0; c < (int)cam->v_camera.size(); c++ ) // ... cameras
2053  for( int h = 0; h < (int)cam->v_camera[c]->v_homography.size(); h++ ){ // ... homographies
2054  error_gra[c][h] = 0;
2055  if( cam->v_camera[c]->v_homography[h]->m_homography ){
2056  int points = cam->v_camera[c]->v_homography[h]->s_plane_object->p;
2057  for( int point = 0; point < points; point++ ){
2058 
2059  // Original point on the screen:
2060  cam->HomogenousNormalizeVector( cam->v_camera[c]->v_homography[h]->s_plane_object->v_m_pp[point] );
2061  double u1 = cvmGet( cam->v_camera[c]->v_homography[h]->s_plane_object->v_m_pp[point], 0, 0 );
2062  double v1 = cvmGet( cam->v_camera[c]->v_homography[h]->s_plane_object->v_m_pp[point], 1, 0 );
2063 
2064  // Projected point on the screen:
2065  double a_p[4]; double a_p3[3]; double a_p4[3];
2066  double a_RT[12]; CvMat m_RT = cvMat( 3, 4, CV_64FC1, a_RT );
2067  a_p[0] = cam->v_camera[c]->v_homography[h]->s_plane_object->px[point]; a_p[2] = 0;
2068  a_p[1] = cam->v_camera[c]->v_homography[h]->s_plane_object->py[point]; a_p[3] = 1;
2069  CvMat m_p = cvMat( 4, 1, CV_64FC1, a_p ); // plane point (flat)
2070  CvMat m_p3 = cvMat( 3, 1, CV_64FC1, a_p3 ); // eye point 2
2071  CvMat m_p4 = cvMat( 3, 1, CV_64FC1, a_p4 ); // image point
2072  cam->Mat3x4Mul( cam->s_optimal.v_camera_r_t[c], cam->s_optimal.v_homography_r_t[h], &m_RT );
2073  cvMatMul( &m_RT, &m_p, &m_p3 );
2074  cvMatMul( cam->s_optimal.v_camera_c[c], &m_p3, &m_p4 );
2075  cam->HomogenousNormalizeVector( &m_p4 );
2076  double u2 = cvmGet( &m_p4, 0, 0 );
2077  double v2 = cvmGet( &m_p4, 1, 0 );
2078 
2079  // Projected points with original homography:
2080  double u3,v3;
2081  cam->v_camera[c]->v_homography[h]->m_homography->transform_point(
2082  cam->v_camera[c]->v_homography[h]->s_plane_object->px[point],
2083  cam->v_camera[c]->v_homography[h]->s_plane_object->py[point],
2084  &u3,&v3 );
2085 
2086  // Calculate error:
2087  double current_error_opt = sqrt( pow(u1-u2,2) + pow(v1-v2,2) );
2088  double current_error_org = sqrt( pow(u1-u3,2) + pow(v1-v3,2) );
2089  chi_error_opt += pow(u1-u2,2) + pow(v1-v2,2);
2090  chi_error_org += pow(u1-u3,2) + pow(v1-v3,2);
2091  error_opt[obs] = (float)current_error_opt;
2092  total_error_opt += current_error_opt;
2093  error_org[obs] = (float)current_error_org;
2094  total_error_org += current_error_org;
2095  obs++;
2096 
2097  // For error graphic:
2098  error_gra[c][h] += (float)( current_error_opt/(double)points );
2099  }
2100  }
2101  }
2102 
2103  // Print results to screen if more than one observation has been found:
2104  if( obs > 0 ){
2105  chi_error_opt /= (double)obs * 2.0;
2106  chi_error_org /= (double)obs * 2.0;
2107  double avg_error_opt = total_error_opt / (double)obs;
2108  double avg_error_org = total_error_org / (double)obs;
2109  double std_dev_opt = 0;
2110  double std_dev_org = 0;
2111  double max_error_opt = 0;
2112  double max_error_org = 0;
2113  double min_error_opt = total_error_opt;
2114  double min_error_org = total_error_org;
2115  for( int j = 0; j < obs; j++ ){
2116  if( error_opt[j] > max_error_opt ) max_error_opt = error_opt[j];
2117  if( error_org[j] > max_error_org ) max_error_org = error_org[j];
2118  if( error_opt[j] < min_error_opt ) min_error_opt = error_opt[j];
2119  if( error_org[j] < min_error_org ) min_error_org = error_org[j];
2120  std_dev_opt += pow( error_opt[j]-avg_error_opt, 2 );
2121  std_dev_org += pow( error_org[j]-avg_error_org, 2 );
2122  }
2123  std_dev_opt = sqrt(std_dev_opt/(double)obs);
2124  std_dev_org = sqrt(std_dev_org/(double)obs);
2125 
2126  // Plot cameras:
2127  printf("\n Focal Aspect u_0 v_0 Hnum\n");
2128  for( int c = 0; c < (int)cam->v_camera.size(); c++ )
2129  if( params[c*4+1] != 0 ){
2130  int hom = 0;
2131  for( int h = 0; h < (int)cam->v_camera[c]->v_homography.size(); h++ )
2132  if( cam->v_camera[c]->v_homography[h]->m_homography )
2133  hom++;
2134  printf( "Camera %02d: %8.3f %8.3f %8.3f %8.3f %5d\n",
2135  c,
2136  params[c*4+1], params[c*4]/params[c*4+1] , params[c*4+2], params[c*4+3],
2137  hom );
2138  }
2139 
2140  // Plot Errors:
2141  printf("\n Optimal Original\n");
2142  printf("Maximal error in observations: %8.3f %8.3f\n", max_error_opt, max_error_org );
2143  printf("Minimal error in observations: %8.3f %8.3f\n", min_error_opt, min_error_org );
2144  printf("Average error in observations: %8.3f %8.3f\n", avg_error_opt, avg_error_org );
2145  printf("Chi^2 error in observations: %8.3f %8.3f\n", chi_error_opt, chi_error_org );
2146  printf("Standard deviation of error: %8.3f %8.3f\n", std_dev_opt, std_dev_org );
2147  printf("Number of observations: %8i %8i\n", obs, obs);
2148 
2149  // Init error histogram graphic:
2150  int width = 1024; //TODO: Hier groesse aus Parametern!
2151  int height = 768;
2152  IplImage *im = cvCreateImage( cvSize( width, height ), IPL_DEPTH_8U, 3 );
2153  CvFont font;
2154  cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 1, 1, 0, 2, 8 );
2155 
2156  // Get maximal error for scaling:
2157  double max_error = 0;
2158  for( int c = 0; c < (int)cam->v_camera.size(); c++ ) // ... cameras
2159  for( int h = (int)cam->v_camera[c]->v_homography.size()-1; h >= 0 ; h-- ) // ... homographies
2160  if( cam->v_camera[c]->v_homography[h]->m_homography )
2161  if( error_gra[c][h] > max_error )
2162  max_error = error_gra[c][h];
2163  max_error *= 1.2;
2164 
2165  // Draw background:
2166  double cut_error = 1; //TODO: Hier Parameter wert!
2167  int y_cut = (int)((double)height-(double)height*cut_error/max_error);
2168  cvRectangle( im, cvPoint( 0, 0 ), cvPoint( width, y_cut ), CV_RGB ( 100,100,100 ), CV_FILLED, 8, 0 );
2169  cvRectangle( im, cvPoint( 0, y_cut ), cvPoint( width, height ), CV_RGB ( 0, 0, 0 ), CV_FILLED, 8, 0 );
2170 
2171  // Draw error histogram:
2172  char info[200];
2173  for( int c = 0; c < (int)cam->v_camera.size(); c++ ) // ... cameras
2174  for( int h = (int)cam->v_camera[c]->v_homography.size()-1; h >= 0 ; h-- ) // ... homographies
2175  if( cam->v_camera[c]->v_homography[h]->m_homography ){
2176  int x = (int)((double)width*(double)h/(double)cam->v_camera[c]->v_homography.size());
2177  int y = (int)((double)height-(double)height*error_gra[c][h]/max_error);
2178  cvLine( im, cvPoint( x,y ), cvPoint( x,height ), CV_RGB ( 255,255,255 ), 2, CV_AA, 0 );
2179  cvCircle( im, cvPoint( x,y ), 2, CV_RGB ( 255,200,0 ), 2, CV_AA, 0 );
2180  if( error_gra[c][h]/max_error > 0.3 ){
2181  sprintf( info, "%i", h );
2182  cvPutText( im, info, cvPoint( x+1,y-1 ), &font, CV_RGB ( 255,200,0 ) );
2183  }
2184  }
2185 
2186  // Titles:
2187  sprintf( info, "%.3f", max_error );
2188  cvPutText( im, info, cvPoint( 10,30 ), &font, CV_RGB ( 255,0,0 ) );
2189  sprintf( info, "%.3f", 0 );
2190  cvPutText( im, info, cvPoint( 10,height-10 ), &font, CV_RGB ( 255,0,0 ) );
2191  if( cut_error > 0.1*max_error && cut_error < 0.9*max_error ){
2192  sprintf( info, "%.3f", cut_error );
2193  cvPutText( im, info, cvPoint( 10,y_cut-5 ), &font, CV_RGB ( 255,0,0 ) );
2194  }
2195  sprintf( info, "Maximal Camera Error in Pixel over homographies", 0 );
2196  cvPutText( im, info, cvPoint( 150,30 ), &font, CV_RGB ( 200,255,100 ) );
2197 
2198  /*
2199  // Print errorgraphic to file:
2200  char file_name[200];
2201  sprintf( file_name, "error_graphic_%02d.jpg", cam->errorgraphic_counter++ );
2202  cvSaveImage( file_name, im );
2203  */
2204  IplImage *im2 = cvCreateImage(cvSize(800,600), IPL_DEPTH_8U, 3); //TODO: Hier echte groesse von parametern!
2205  cvResize(im, im2, CV_INTER_LINEAR );
2206  cvShowImage( "Error Histogram", im2 );
2207  cvWaitKey(10);
2208  cvReleaseImage( &im );
2209  cvReleaseImage( &im2 );
2210  //printf( "File error_graphic_%02d.jpg successfully stored!\n\n", cam->errorgraphic_counter );
2211  printf( "==================================================\n" );
2212  } else {
2213  printf("\n\n---------- Calibration results: ----------\n");
2214  printf("ERROR: No observations found!\n\n");
2215  }
2216 }
2217 
2218 bool CamCalibration::FilterHomographiesAfterOptimization( double p_PostFilter ){
2219  bool filtered = false;
2220  printf( "INFO: Starting post-filtering process...\n" );
2221 
2222  // Post filter homographies:
2223  for( int c = 0; c < (int)v_camera.size(); c++ ) // ... cameras
2224  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ ){ // ... homographies
2225  if( v_camera[c]->v_homography[h]->m_homography ){
2226  int points = v_camera[c]->v_homography[h]->s_plane_object->p;
2227  double error = 0;
2228  for( int point = 0; point < points; point++ ){
2229 
2230  // Original point on the screen:
2231  HomogenousNormalizeVector( v_camera[c]->v_homography[h]->s_plane_object->v_m_pp[point] );
2232  double u1 = cvmGet( v_camera[c]->v_homography[h]->s_plane_object->v_m_pp[point], 0, 0 );
2233  double v1 = cvmGet( v_camera[c]->v_homography[h]->s_plane_object->v_m_pp[point], 1, 0 );
2234 
2235  // Projected point on the screen:
2236  double a_p[4]; double a_p3[3]; double a_p4[3];
2237  double a_RT[12]; CvMat m_RT = cvMat( 3, 4, CV_64FC1, a_RT );
2238  a_p[0] = v_camera[c]->v_homography[h]->s_plane_object->px[point]; a_p[2] = 0;
2239  a_p[1] = v_camera[c]->v_homography[h]->s_plane_object->py[point]; a_p[3] = 1;
2240  CvMat m_p = cvMat( 4, 1, CV_64FC1, a_p ); // plane point (flat)
2241  CvMat m_p3 = cvMat( 3, 1, CV_64FC1, a_p3 ); // eye point 2
2242  CvMat m_p4 = cvMat( 3, 1, CV_64FC1, a_p4 ); // image point
2243  Mat3x4Mul( s_optimal.v_camera_r_t[c], s_optimal.v_homography_r_t[h], &m_RT );
2244  cvMatMul( &m_RT, &m_p, &m_p3 );
2245  cvMatMul( s_optimal.v_camera_c[c], &m_p3, &m_p4 );
2246  HomogenousNormalizeVector( &m_p4 );
2247  double u2 = cvmGet( &m_p4, 0, 0 );
2248  double v2 = cvmGet( &m_p4, 1, 0 );
2249 
2250  // Calculate error:
2251  double current_error_opt = sqrt( pow(u1-u2,2) + pow(v1-v2,2) );
2252  error += current_error_opt/(double)points;
2253  }
2254  if( error > p_PostFilter ){
2255  for( int c2 = 0; c2 < (int)v_camera.size(); c2++ ){
2256  DeleteWorldPlaneHomography( c2, h );
2257  cvmSet( m_CH, c2, h, 0 );
2258  cvReleaseMat( &s_optimal.v_homography_r_t[h] );
2259  cvReleaseMat( &s_optimal.v_homography_r_t_jacobian[h] );
2260  }
2261  printf( "INFO: View %i has been deleted for all cameras!\n", h );
2262  filtered = true;
2263  }
2264  }
2265  }
2266 
2267  if( !filtered )
2268  printf( "INFO: Nothing filtered!\n" );
2269 
2270  // Return true if at least one homography has been filtered:
2271  printf( "INFO: Post-filtering process finished.\n\n" );
2272  return filtered;
2273 }
2274 
2275 bool CamCalibration::OptimizeCalibrationByMinimalParameterMethod( int iter, double eps, double p_PostFilter ){
2276 
2277  // Create optimal camera structure for the first time:
2278  if( !CreateOptimalCameraStructure() ){
2279  printf("ERROR: Optial camera structure estimation failed!\n");
2280  return false;
2281  }
2282 
2283  // Reset counter for error histogram and create an output window:
2284  errorgraphic_counter = 0;
2285  cvNamedWindow( "Error Histogram", CV_WINDOW_AUTOSIZE );
2286  cvWaitKey(10);
2287 
2288  // Start calibration:
2289  //double post_filter_offset = 20;
2290  do {
2291 
2292  // Get number parameters and observations:
2293  int parameter_number = GetParameterNumber();
2294  /* int observation_number = GetObservationNumber(); */
2295 
2296  ls_minimizer2 minimizer(parameter_number);
2297  minimizer.set_state_change_callback(updateCB);
2298  minimizer.set_user_data(0, this);
2299  minimizer.lm_set_max_iterations(iter);
2300  //minimizer.set_verbose_level(3);
2301  ProjObs::parameterNumber = parameter_number;
2302 
2303  // Feed with initial parameters:
2304  GetParameterSetFromOptimalStructure();
2305 
2306  /*
2307  LsqData *lsqData = AllocateLsqData( parameter_number, observation_number );
2308  SetLsqGlobals( lsqData, iter, eps, GAUSS_JORDAN, updateCB, true );
2309  LsqObs *obs = AllocateLsqObs( lsqData, sizeof(LsqObs), observation_number, 4 );
2310  lsqData->slot1 = this;
2311 
2312  // Feed with initial parameters:
2313  GetParameterSetFromOptimalStructure();
2314  FillLsqParams( lsqData, &v_opt_param[0], 0, 0 );
2315  lsqData->Dsp.F = PrintOptimizedResultErrors;
2316  */
2317 
2318  // Add the observations for ...
2319  for( int c = 0; c < (int)v_camera.size(); c++ ) // ... cameras
2320  for( int h = 0; h < (int)v_camera[c]->v_homography.size(); h++ ) // ... homographies
2321  if( v_camera[c]->v_homography[h]->m_homography ){
2322  int points = v_camera[c]->v_homography[h]->s_plane_object->p;
2323  for( int point = 0; point < points; point++ ) { // ... points
2324 
2325  // Add homography number and point:
2326  ProjObs *o = new ProjObs();
2327  o->cam = c;
2328  o->hom = h;
2329  o->point = point;
2330 
2331  // Add screen plane point (reference!):
2332  s_struct_plane* s_plane_object = v_camera[c]->v_homography[h]->s_plane_object;
2333  HomogenousNormalizeVector( (*s_plane_object).v_m_pp[point] );
2334  o->target[0] = cvmGet( (*s_plane_object).v_m_pp[point], 0, 0 );
2335  o->target[1] = cvmGet( (*s_plane_object).v_m_pp[point], 1, 0 );
2336 
2337  minimizer.add_observation(o, true, false);
2338  }
2339  }
2340 
2341  minimizer.minimize_using_levenberg_marquardt_from(&v_opt_param[0]);
2342  void *ptr=this;
2343  updateCB( minimizer.state, &ptr);
2344 
2345  // post filter offset in test phase! remove, please!
2346  //if( post_filter_offset > 1 )
2347  // post_filter_offset -= 10;
2348 
2349  // Redo calibration if at least one homography was post-filtered:
2350  } while( FilterHomographiesAfterOptimization( p_PostFilter/*+post_filter_offset*/ ) );
2351 
2352  // Destroy histogram output window:
2353  cvDestroyAllWindows();
2354  return true;
2355 }
2356 
2358 {
2359  FILE *stream;
2360 
2361  // Print cameras intrinsic matrix to file:
2362  if( (stream = fopen( "camera_c.txt", "w+t" )) != NULL ){
2363  for( int c = 0; c < (int)s_optimal.v_camera_c.size(); c++ ){
2364  fprintf( stream, "no: %i\n", c );
2365  fprintf( stream, "width: %i\n", v_camera[c]->w );
2366  fprintf( stream, "height: %i\n", v_camera[c]->h );
2367  showmatrix_file( *s_optimal.v_camera_c[c], stream );
2368  }
2369  fclose( stream );
2370  }
2371 
2372  // Print cameras extrinsic matrix to file:
2373  if( (stream = fopen( "camera_r_t.txt", "w+t" )) != NULL ){
2374  for( int c = 0; c < (int)s_optimal.v_camera_c.size(); c++ ){
2375  fprintf( stream, "no: %i\n", c );
2376  fprintf( stream, "width: %i\n", v_camera[c]->w );
2377  fprintf( stream, "height: %i\n", v_camera[c]->h );
2378  showmatrix_file( *s_optimal.v_camera_r_t[c], stream );
2379  }
2380  fclose( stream );
2381  }
2382 
2383  // Print views to file:
2384  if( (stream = fopen( "view_r_t.txt", "w+t" )) != NULL ){
2385  for( int h = 0; h < (int)s_optimal.v_homography_r_t.size(); h++ ){
2386  if( s_optimal.v_homography_r_t[h] ){
2387  fprintf( stream, "no: %i\n", h );
2388  showmatrix_file( *s_optimal.v_homography_r_t[h], stream );
2389  }
2390  }
2391  fclose( stream );
2392  }
2393 }
2394 
2395 void CamCalibration::PrintOptimizedResultsToFile2( char* file_descriptor, bool create_png, char* sequence_descriptor,
2396  char* png_descriptor, int c_start, int h_start )
2397 {
2398  FILE *stream;
2399  char file_name[200];
2400  char image_in[200];
2401  char image_out[200];
2402 
2403  // Print files (and copy images to new location):
2404  for( int c = 0; c < (int)s_optimal.v_camera_c.size(); c++ ){
2405  for( int h = 0; h < (int)s_optimal.v_homography_r_t.size(); h++ ){
2406  if( cvmGet( m_CH, c, h ) == 1 ){
2407  sprintf( file_name, file_descriptor, c, h );
2408  if( (stream = fopen( file_name, "w+t" )) != NULL ){
2409  double a_proj[12];
2410  CvMat m_proj = cvMat( 3, 4, CV_64FC1, a_proj );
2411  cvMatMul( s_optimal.v_camera_c[c], s_optimal.v_camera_r_t[c], &m_proj );
2412  Mat3x4Mul( &m_proj, s_optimal.v_homography_r_t[h], &m_proj );
2413  showmatrix_file( m_proj, stream );
2414  fclose( stream );
2415  }
2416  }/*
2417  if( create_png ){
2418  // Image:
2419  sprintf(image_in,sequence_descriptor,c_start+c,h_start+h);
2420  sprintf(image_out,png_descriptor,c,h);
2421  IplImage * myimage = cvLoadImage( image_in, 0 );
2422  cvSaveImage( image_out, myimage );
2423  printf("Print to file: %i %i \n",c,h);
2424  }*/
2425  }
2426  }
2427 }