vpgl_camera_transform.cxx
Go to the documentation of this file.
1 #include <iostream>
2 #include <limits>
3 #include <utility>
5 //:
6 // \file
7 
8 
9 #ifdef _MSC_VER
10 # include <vcl_msvc_warnings.h>
11 #endif
13 #include <vgl/vgl_box_3d.h>
16 #include <vnl/algo/vnl_lsqr.h>
17 #include <vnl/algo/vnl_qr.h>
19 #include <vnl/vnl_inverse.h>
20 #include <vnl/vnl_quaternion.h>
21 #include <vnl/vnl_trace.h>
22 
23 
24 vpgl_camera_transform_f::vpgl_camera_transform_f(unsigned cnt_residuals, unsigned n_unknowns,
25  const std::vector<vpgl_perspective_camera<double> >& input_cams,
26  std::vector< std::vector< std::pair<vnl_vector_fixed<double, 2>, unsigned> > > cam_ids_img_pts,
27  std::vector<vnl_vector_fixed<double, 4> > pts_3d, bool minimize_R) :
28  vnl_least_squares_function(n_unknowns,cnt_residuals,vnl_least_squares_function::no_gradient),
29  cam_ids_img_pts_(std::move(cam_ids_img_pts)), pts_3d_(std::move(pts_3d)), input_cams_(input_cams), minimize_R_(minimize_R)
30 {
31 
32  for (const auto & input_cam : input_cams) {
33  const vpgl_calibration_matrix<double>& K = input_cam.get_calibration();
34  Ks_.push_back(K);
35  vnl_matrix_fixed<double, 3, 3> R = input_cam.get_rotation().as_matrix();
36  Rs_.push_back(R);
37  //vgl_vector_3d<double> tv = input_cams[i].get_translation();
38  //vnl_vector_fixed<double, 3> tvv(tv.x(), tv.y(), tv.z());
39  vgl_point_3d<double> C = input_cam.get_camera_center();
40  //vnl_vector_fixed<double, 3> tvv(C.x(), C.y(), C.z());
41  //ts_.push_back(tvv);
42  Cs_.push_back(C);
43  }
44 }
45 
46 //: The main function.
47 // Given the parameter vector x, compute the vector of residuals fx.
49 {
50  unsigned dim = get_number_of_unknowns();
51 
52  // compute current cams
53  std::vector<vpgl_perspective_camera<double> > current_cams;
54  if (dim == 6)
55  compute_cams(x, current_cams);
56  else
57  compute_cams_selective(x, current_cams);
58 
59  std::vector<vnl_matrix_fixed<double, 3, 4> > current_cam_Ms;
60  current_cam_Ms.reserve(current_cams.size());
61 for (auto & current_cam : current_cams)
62  current_cam_Ms.push_back(current_cam.get_matrix());
63 
64  // compute the new projections and the residuals
65  unsigned cnt = 0;
66  for (unsigned j = 0; j < cam_ids_img_pts_.size(); j++) {
67  for (unsigned i = 0; i < cam_ids_img_pts_[j].size(); i++) {
68  unsigned cam_id = cam_ids_img_pts_[j][i].second;
69 
70  vnl_vector_fixed<double, 2> img_pt = cam_ids_img_pts_[j][i].first;
71 
72  vnl_vector_fixed<double, 3> current_img_pt = current_cam_Ms[cam_id]*pts_3d_[j];
73 
74  // compute the residual
75  double dif0 = (current_img_pt[0]/current_img_pt[2]) - img_pt[0];
76  double dif1 = (current_img_pt[1]/current_img_pt[2]) - img_pt[1];
77  //fx[cnt] = std::sqrt(dif0*dif0 + dif1*dif1);
78  fx[cnt] = std::abs(dif0);
79  cnt++;
80  fx[cnt] = std::abs(dif1);
81 
82  /*if (cnt == 1 || cnt == 11) {
83  std::cout << " \t\t cam id: " << cam_id << " img_pt: " << img_pt;
84  std::cout << " projected pt: " << current_img_pt[0]/current_img_pt[2] << " " << current_img_pt[1]/current_img_pt[2] << std::endl;
85  std::cout << " \t\t dif0: " << dif0 << " dif1: " << dif1 << " error: " << std::sqrt(dif0*dif0 + dif1*dif1) << std::endl;
86  std::cout << " \t\t 3d pt: " << pts_3d_[j] << std::endl;
87  }*/
88 
89 
90  cnt++;
91  }
92  }
93 }
94 
95 //: Fast conversion of rotation from Rodrigues vector to matrix
97 vpgl_camera_transform_f::rod_to_matrix(double r0, double r1, double r2)
98 {
99  double x2 = r0*r0, y2 = r1*r1, z2 = r2*r2;
100  double m = x2 + y2 + z2;
101  double theta = std::sqrt(m);
102  double s = std::sin(theta) / theta;
103  double c = (1 - std::cos(theta)) / m;
104 
106  R(0,0) = R(1,1) = R(2,2) = 1.0;
107  if (m == 0.0)
108  return R;
109 
110  R(0,0) -= (y2 + z2) * c;
111  R(1,1) -= (x2 + z2) * c;
112  R(2,2) -= (x2 + y2) * c;
113  R(0,1) = R(1,0) = r0*r1*c;
114  R(0,2) = R(2,0) = r0*r2*c;
115  R(1,2) = R(2,1) = r1*r2*c;
116 
117  double t = r0*s;
118  R(1,2) -= t;
119  R(2,1) += t;
120  t = r1*s;
121  R(0,2) += t;
122  R(2,0) -= t;
123  t = r2*s;
124  R(0,1) -= t;
125  R(1,0) += t;
126 
127  return R;
128 }
129 
130 
132 {
133  // current rotation
134  //vnl_vector<double> w(3);
135  //w[0] = x[0]; w[1] = x[1]; w[2] = x[2];
136  //vgl_rotation_3d <double> Rw(w); // create from Rodriguez params
137  //vnl_matrix_fixed<double,3,3> R = Rw.as_matrix();
138  vnl_matrix_fixed<double,3,3> R = rod_to_matrix(x[0], x[1], x[2]);
139 
140  // current t
141  //vnl_vector_fixed<double, 3> t(x[3], x[4], x[5]);
142 
143  // construct the new cameras
144  for (unsigned i = 0; i < Ks_.size(); i++) {
145  //compose rotations
147  vgl_rotation_3d<double> Rtr(Rt);
148 
149  //compute new center
150  vgl_point_3d<double> Cg(Cs_[i].x() + x[3], Cs_[i].y() + x[4], Cs_[i].z() + x[5]);
151 
152  //construct transformed camera
153  vpgl_perspective_camera<double> camt(Ks_[i], Cg, Rtr);
154  output_cams.push_back(camt);
155  }
156 }
157 
159 {
160  if (minimize_R_) { // minimize only R,
161 
162  // current rotation
163  vnl_matrix_fixed<double,3,3> R = rod_to_matrix(x[0], x[1], x[2]);
164 
165  // construct the new cameras
166  for (unsigned i = 0; i < Ks_.size(); i++) {
167  //compose rotations
169  vgl_rotation_3d<double> Rtr(Rt);
170 
171  //construct transformed camera
172  vpgl_perspective_camera<double> camt(Ks_[i], Cs_[i], Rtr);
173  output_cams.push_back(camt);
174 
175  /*if (i==0) {
176  std::cout << "input cam:\n " << input_cams_[i] << std::endl;
177  std::cout << "output cam with x: " << x[0] << " " << x[1] << " " << x[2] << ":\n " << camt << std::endl;
178  }*/
179  }
180  } else { // minimize only t
181  // construct the new cameras
182  for (unsigned i = 0; i < Ks_.size(); i++) {
184 
185  //compute new translation
186  //vnl_vector_fixed<double, 3> tt = ts_[i] + Rs_[i]*t;
187  //vgl_vector_3d<double> ttg(tt[0], tt[1], tt[2]);
188  vgl_point_3d<double> Cg(Cs_[i].x() + x[0], Cs_[i].y() + x[1], Cs_[i].z() + x[2]);
189 
190  //construct transformed camera
191  //vpgl_perspective_camera<double> camt(Ks_[i], Rtr, ttg);
192  vpgl_perspective_camera<double> camt(Ks_[i], Cg, Rtr);
193  output_cams.push_back(camt);
194 
195  /*if (i==0) {
196  std::cout << "input cam:\n " << input_cams_[i] << std::endl;
197  std::cout << "input cam center: " << Cs_[i] << std::endl;
198  std::cout << "output cam with x: " << x[0] << " " << x[1] << " " << x[2] << ":\n " << camt << std::endl;
199  std::cout << "output cam center: " << Cg << std::endl;
200  std::cout << "input output dif: " << (Cs_[i]-Cg).length() << std::endl;
201  }*/
202  }
203  }
204 }
205 
207  const std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > >& cam_ids_img_pts,
208  std::vector<vpgl_perspective_camera<double> >& input_cams_norm,
209  std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > >& cam_ids_norm_img_pts)
210 {
211  // normalize the image points
212  unsigned cnt_residuals = 0;
213  double nx = 0, ny = 0, ns = 0;
214 
215  for (const auto & cam_ids_img_pt : cam_ids_img_pts) {
216  for (unsigned i = 0; i < cam_ids_img_pt.size(); i++) {
217  double x = cam_ids_img_pt[i].first[0];
218  double y = cam_ids_img_pt[i].first[1];
219  nx += x;
220  ny += y;
221  ns += x*x + y*y;
222  cnt_residuals++;
223  }
224  }
225  nx /= cnt_residuals;
226  ny /= cnt_residuals;
227  ns /= cnt_residuals;
228  ns -= nx*nx + ny*ny;
229  ns /= 2;
230  ns = std::sqrt(ns);
231  for (const auto & cam_ids_img_pt : cam_ids_img_pts) {
232  std::vector< std::pair<vnl_vector_fixed<double, 2>, unsigned> > cam_pts;
233  for (unsigned i = 0; i < cam_ids_img_pt.size(); i++) {
234  double x = cam_ids_img_pt[i].first[0];
235  double y = cam_ids_img_pt[i].first[1];
237  new_pt[0] = (x-nx)/ns;
238  new_pt[1] = (y-ny)/ns;
239  std::pair<vnl_vector_fixed<double, 2>, unsigned> pair(new_pt, cam_ids_img_pt[i].second);
240  cam_pts.push_back(pair);
241  }
242  cam_ids_norm_img_pts.push_back(cam_pts);
243  }
244 
245  // normalize the K matrices
246  for (const auto & input_cam : input_cams) {
247  const vpgl_calibration_matrix<double>& Ki = input_cam.get_calibration();
248 
249  vnl_vector<double> K_vals(5,0.0);
250  K_vals[0] = Ki.focal_length()*Ki.x_scale();
251  K_vals[1] = Ki.y_scale() / Ki.x_scale();
252  K_vals[2] = Ki.principal_point().x();
253  K_vals[3] = Ki.principal_point().y();
254  K_vals[4] = Ki.skew();
255 
256  vpgl_calibration_matrix<double> Knew(K_vals[0]/ns,
257  vgl_point_2d<double>((K_vals[2]-nx)/ns,(K_vals[3]-ny)/ns),
258  1.0,
259  K_vals[1],
260  K_vals[4]);
261 
262  vpgl_perspective_camera<double> cnew(Knew, input_cam.get_rotation(), input_cam.get_translation());
263  input_cams_norm.push_back(cnew);
264  }
265 
266 }
267 
268 //: compute the fixed transformation as R and t
270  const std::vector< std::vector< std::pair<vnl_vector_fixed<double, 2>, unsigned> > >& cam_ids_img_pts,
271  const std::vector<vnl_vector_fixed<double, 4> >& pts_3d,
272  std::vector<vpgl_perspective_camera<double> >& output_cams)
273 {
274  // find the number of residuals
275  unsigned cnt_residuals = 0;
276  for (const auto & cam_ids_img_pt : cam_ids_img_pts) {
277  for (unsigned i = 0; i < cam_ids_img_pt.size(); i++) {
278  cnt_residuals++;
279  }
280  }
281  std::cout << "number of residuals: " << cnt_residuals << std::endl;
282 
283  // normalize the image points
284  std::vector<vpgl_perspective_camera<double> > input_cams_norm;
285  std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > > cam_ids_norm_img_pts;
286  normalize_img_pts(input_cams, cam_ids_img_pts, input_cams_norm, cam_ids_norm_img_pts);
287 
288  // setup the minimization problem
289 
290  //unsigned n_unknowns = 6; // if 6, minimize both R and t params
291  unsigned n_unknowns = 3; // if 3 minimize only R or t params (depends on stepsizes, set stepsize negative to discard)
292 
293  vpgl_camera_transform_f f(cnt_residuals*2, n_unknowns, input_cams_norm, cam_ids_norm_img_pts, pts_3d);
294 
295  vnl_levenberg_marquardt minimizer(f);
296  //minimizer.set_x_tolerance(1e-16);
297  //minimizer.set_f_tolerance(1.0);
298  //minimizer.set_g_tolerance(1e-3);
299  minimizer.set_trace(true);
300  //minimizer.set_max_iterations(50);
301 
302  // setup initial parameters, rodriguez vector is (0,0,0) for identity rotation, also set translation to 0,0,0
303  vnl_vector<double> x(n_unknowns, 0.0);
304 
305  //std::cout << "initial params: " << x << std::endl;
306  minimizer.minimize(x);
307  //std::cout << "end_error: " << minimizer.get_end_error() << " end params: " << x << std::endl;
308 
309  std::vector<vpgl_perspective_camera<double> > output_cams_denorm;
310  if (n_unknowns == 6)
311  f.compute_cams(x, output_cams_denorm);
312  else
313  f.compute_cams_selective(x, output_cams_denorm);
314 
315  // denormalize output_cams
316  for (unsigned i = 0; i < output_cams_denorm.size(); i++) {
317  vpgl_calibration_matrix<double> K = input_cams[i].get_calibration();
318  vpgl_perspective_camera<double> cnew(K, output_cams_denorm[i].get_rotation(), output_cams_denorm[i].get_translation());
319 
320  output_cams.push_back(cnew);
321  }
322 
323  return true;
324 }
325 
326 //: sample offsets for camera centers in a box with the given dimensions (e.g. plus/minus dim_x) in meters
327 std::vector<vnl_vector_fixed<double, 3> > vpgl_camera_transform::sample_centers(double dim_x, double dim_y, double dim_z, double step)
328 {
329  std::vector<vnl_vector_fixed<double, 3> > out;
330  for (double z = -dim_z; z <= dim_z; z+=step)
331  for (double x = -dim_x; x <= dim_x; x+=step)
332  for (double y = -dim_y; y <= dim_y; y+=step) {
334  out.push_back(o);
335  }
336  return out;
337 }
338 
339 //: compute the fixed transformation by sampling centers in a given box and then optimizing for rotation
341  const std::vector< std::vector< std::pair<vnl_vector_fixed<double, 2>, unsigned> > >& cam_ids_img_pts,
342  const std::vector<vnl_vector_fixed<double, 4> >& pts_3d,
343  std::vector<vpgl_perspective_camera<double> >& output_cams)
344 {
345  // find the number of residuals
346  unsigned cnt_residuals = 0;
347  for (const auto & cam_ids_img_pt : cam_ids_img_pts) {
348  for (unsigned i = 0; i < cam_ids_img_pt.size(); i++) {
349  cnt_residuals++;
350  }
351  }
352  std::cout << "number of residuals: " << cnt_residuals << std::endl;
353 
354  // normalize the image points
355  std::vector<vpgl_perspective_camera<double> > input_cams_norm;
356  std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > > cam_ids_norm_img_pts;
357  normalize_img_pts(input_cams, cam_ids_img_pts, input_cams_norm, cam_ids_norm_img_pts);
358 
359  // setup the minimization problems
360  double dim_x = 20.0, dim_y = 20.0, dim_z = 12.0; // offsets around the original cam center in meters
361  double step = 1.0;
362  std::vector<vnl_vector_fixed<double, 3> > offsets = sample_centers(dim_x, dim_y, dim_z, step);
363 
364  double error_min = 1000000000.0;
365  output_cams = input_cams;
366  vnl_vector_fixed<double, 3> offset_min;
367  for (unsigned i = 0; i < offsets.size(); i++) {
368  if (i%500 == 0) std::cout << i << " ";
369 
370  std::vector<vpgl_perspective_camera<double> > input_cams_norm_off;
371  for (auto & j : input_cams_norm) {
372  const vpgl_calibration_matrix<double>& K = j.get_calibration();
373  const vgl_rotation_3d<double>& R = j.get_rotation();
374  vgl_point_3d<double> C = j.get_camera_center();
375  vgl_point_3d<double> Cnew(C.x() + offsets[i][0], C.y() + offsets[i][1], C.z() + offsets[i][2]);
376  vpgl_perspective_camera<double> cnew(K, Cnew, R);
377  input_cams_norm_off.push_back(cnew);
378  }
379 
380  unsigned n_unknowns = 3; // if 3 minimize only R or t params (depends on stepsizes, set stepsize negative to discard)
381  vpgl_camera_transform_f f(cnt_residuals*2, n_unknowns, input_cams_norm_off, cam_ids_norm_img_pts, pts_3d);
382 
383  vnl_levenberg_marquardt minimizer(f);
384  //minimizer.set_trace(true);
385 
386  // setup initial parameters, rodriguez vector is (0,0,0) for identity rotation, also set translation to 0,0,0
387  vnl_vector<double> x(n_unknowns, 0.0);
388 
389  //std::cout << "initial params: " << x << std::endl;
390  minimizer.minimize(x);
391  double enderror = minimizer.get_end_error();
392  //std::cout << "end_error: " << enderror << " end params: " << x << std::endl;
393 
394  std::vector<vpgl_perspective_camera<double> > output_cams_denorm;
395  f.compute_cams_selective(x, output_cams_denorm);
396 
397  if (enderror < error_min) {
398  std::cout << " setting output cams for offset: " << offsets[i] << " with min error: " << error_min << std::endl;
399  error_min = enderror;
400  offset_min = offsets[i];
401  // denormalize output_cams
402  for (unsigned j = 0; j < output_cams_denorm.size(); j++) {
403  vpgl_calibration_matrix<double> K = input_cams[j].get_calibration();
404  vpgl_perspective_camera<double> cnew(K, output_cams_denorm[j].get_rotation(), output_cams_denorm[j].get_translation());
405  output_cams[j] = cnew;
406  }
407  }
408  }
409  std::cout << " final error min: " << error_min << " final offset: " << offset_min << " tried: " << offsets.size() << " offsets!\n";
410  return true;
411 }
412 
413 
415  const std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > >& cam_ids_img_pts,
416  const std::vector<vnl_vector_fixed<double, 4> >& pts_3d,
417  std::vector<vpgl_perspective_camera<double> >& output_cams)
418 {
419  // find the number of residuals
420  unsigned cnt_residuals = 0;
421  for (const auto & cam_ids_img_pt : cam_ids_img_pts) {
422  for (unsigned i = 0; i < cam_ids_img_pt.size(); i++) {
423  cnt_residuals++;
424  }
425  }
426  std::cout << "number of residuals: " << cnt_residuals << std::endl;
427 
428  // normalize the image points
429  std::vector<vpgl_perspective_camera<double> > input_cams_norm;
430  std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > > cam_ids_norm_img_pts;
431  normalize_img_pts(input_cams, cam_ids_img_pts, input_cams_norm, cam_ids_norm_img_pts);
432 
433  //////////////////////////////////////////////////////////////////////////////////////////////
434  // compute X_cam (get rid of K matrix)
435  //////////////////////////////////////////////////////////////////////////////////////////////
436  std::vector<vnl_matrix_fixed<double, 3, 3> > input_cam_K_invs;
437  for (auto & i : input_cams_norm) {
438  const vpgl_calibration_matrix<double>& K = i.get_calibration();
441  input_cam_K_invs.push_back(Kinv);
442  }
443 
444  std::vector< std::vector < std::pair<vnl_vector_fixed<double, 3>, unsigned> > > cam_ids_norm_cam_pts;
445  for (auto & cam_ids_norm_img_pt : cam_ids_norm_img_pts) {
446  std::vector < std::pair<vnl_vector_fixed<double, 3>, unsigned> > cam_pts;
447  for (unsigned i = 0; i < cam_ids_norm_img_pt.size(); i++) {
449  pt[0] = cam_ids_norm_img_pt[i].first[0];
450  pt[1] = cam_ids_norm_img_pt[i].first[1];
451  pt[2] = 1.0;
453  cam_pt = input_cam_K_invs[cam_ids_norm_img_pt[i].second]*pt;
454  std::pair<vnl_vector_fixed<double, 3>, unsigned> pair(cam_pt, cam_ids_norm_img_pt[i].second);
455  cam_pts.push_back(pair);
456  }
457  cam_ids_norm_cam_pts.push_back(cam_pts);
458  }
459  ///////////////////////////////////////////////////////////////////////////////////////////////
460 
461  ////////////////////////////////////////////////////////////////////////
462  // setup the problem Ax = b
463  ////////////////////////////////////////////////////////////////////////
464  // two equations per correspondence
465  unsigned m = cnt_residuals*2;
466  // there are 12 unknowns in R matrix and t vector
467  unsigned n = 12;
469  // setup rows of A and b
470  unsigned cnt = 0;
471  for (unsigned j = 0; j < cam_ids_norm_cam_pts.size(); j++) {
472  double X = pts_3d[j][0], Y = pts_3d[j][1], Z = pts_3d[j][2];
473 
474  for (auto & i : cam_ids_norm_cam_pts[j]) {
475  vnl_vector_fixed<double, 3> pt = i.first;
476  double x = pt[0]; double y = pt[1]; double z = pt[2];
477  double a = x/z; double b = y/z;
478 
479  vnl_matrix_fixed<double, 3, 3> R = input_cams_norm[i.second].get_rotation().as_matrix();
480  double r1 = R[0][0], r2 = R[0][1], r3 = R[0][2];
481  double r4 = R[1][0], r5 = R[1][1], r6 = R[1][2];
482  double r7 = R[2][0], r8 = R[2][1], r9 = R[2][2];
483  vgl_vector_3d<double> t = input_cams_norm[i.second].get_translation();
484  double t1 = t.x(), t2 = t.y(), t3 = t.z();
485 
486  A(cnt, 0) = r7*X*a-r1*X; A(cnt, 1) = r7*Y*a-r1*Y; A(cnt, 2) = r7*Z*a-r1*Z;
487  A(cnt, 3) = r8*X*a-r2*X; A(cnt, 4) = r8*Y*a-r2*Y; A(cnt, 5) = r8*Z*a-r2*Z;
488  A(cnt, 6) = r9*X*a-r3*X; A(cnt, 7) = r9*Y*a-r3*Y; A(cnt, 8) = r9*Z*a-r3*Z;
489  A(cnt, 9) = r7*a-r1; A(cnt, 10) = r8*a-r2; A(cnt, 11) = r9*a-r3;
490  B[cnt] = t1 - t3*a;
491  cnt++;
492 
493  A(cnt, 0) = r7*X*b-r4*X; A(cnt, 1) = r7*Y*b-r4*Y; A(cnt, 2) = r7*Z*b-r4*Z;
494  A(cnt, 3) = r8*X*b-r5*X; A(cnt, 4) = r8*Y*b-r5*Y; A(cnt, 5) = r8*Z*b-r5*Z;
495  A(cnt, 6) = r9*X*b-r6*X; A(cnt, 7) = r9*Y*b-r6*Y; A(cnt, 8) = r9*Z*b-r6*Z;
496  A(cnt, 9) = r7*b-r4; A(cnt, 10) = r8*b-r5; A(cnt, 11) = r9*b-r6;
497  B[cnt] = t2 - t3*b;
498  cnt++;
499  }
500  }
501 
503  vnl_vector<double> unknowns(n, 0.0);
504  unknowns[0] = 1; unknowns[4] = 1; unknowns[8] = 1;
505  vnl_lsqr lsqr(ls); lsqr.minimize(unknowns);
506  std::cout << "unknowns: " << unknowns << std::endl;
507 
509  R_fixed[0][0] = unknowns[0]; R_fixed[0][1] = unknowns[1]; R_fixed[0][2] = unknowns[2];
510  R_fixed[1][0] = unknowns[3]; R_fixed[1][1] = unknowns[4]; R_fixed[1][2] = unknowns[5];
511  R_fixed[2][0] = unknowns[6]; R_fixed[2][1] = unknowns[7]; R_fixed[2][2] = unknowns[8];
512 
513  std::cout << " R_fixed: " << R_fixed << std::endl; std::cout << " det of R_fixed: " << vnl_det(R_fixed) << std::endl;
514 
515  //vnl_matrix_fixed<double, 3, 3> R_fixed_norm;
516  //normalize_to_rotation_matrix(R_fixed, R_fixed_norm);
517 
518  //std::cout << " R_fixed_norm: " << R_fixed_norm << std::endl; std::cout << " det of R_fixed_norm: " << vnl_det(R_fixed_norm) << std::endl;
519 
520  vnl_vector_fixed<double, 3> t_fixed(unknowns[9], unknowns[10], unknowns[11]);
521  std::cout << " t_fixed: " << t_fixed << std::endl;
522  /////////////////////////////////////////////////////////////////////////
523 
524  // denormalize and compute R and t
525  for (const auto & input_cam : input_cams) {
526  const vpgl_calibration_matrix<double>& K = input_cam.get_calibration();
527  vnl_matrix_fixed<double, 3, 3> R = input_cam.get_rotation().as_matrix();
528  vgl_vector_3d<double> t = input_cam.get_translation();
530  tv[0] = t.x(); tv[1] = t.y(); tv[2] = t.z();
531 
532  //vnl_matrix_fixed<double, 3, 3> R_new = R*R_fixed_norm;
533  vnl_matrix_fixed<double, 3, 3> R_new = R*R_fixed;
534  vnl_vector_fixed<double, 3> t_new = R*t_fixed + tv;
535 
536  vgl_rotation_3d<double> R_newr(R_new);
537  vgl_vector_3d<double> t_newv(t_new[0], t_new[1], t_new[2]);
538 
539  vpgl_perspective_camera<double> cnew(K, R_newr, t_newv);
540  output_cams.push_back(cnew);
541 
542  std::cout << " old center: " << input_cam.get_camera_center() << " new center: " << cnew.get_camera_center();
543  std::cout << " move by: " << (input_cam.get_camera_center()-cnew.get_camera_center()).length() << std::endl;
544  }
545 
546  return true;
547 }
548 
549 
551  const std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > >& cam_ids_img_pts,
552  const std::vector<vnl_vector_fixed<double, 4> >& pts_3d,
553  std::vector<vpgl_perspective_camera<double> >& output_cams)
554 {
555  // find the number of residuals
556  unsigned cnt_residuals = 0;
557  for (const auto & cam_ids_img_pt : cam_ids_img_pts) {
558  for (unsigned i = 0; i < cam_ids_img_pt.size(); i++) {
559  cnt_residuals++;
560  }
561  }
562  std::cout << "number of residuals: " << cnt_residuals << std::endl;
563 
564  // normalize the image points
565  std::vector<vpgl_perspective_camera<double> > input_cams_norm;
566  std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > > cam_ids_norm_img_pts;
567  normalize_img_pts(input_cams, cam_ids_img_pts, input_cams_norm, cam_ids_norm_img_pts);
568 
569  //////////////////////////////////////////////////////////////////////////////////////////////
570  // compute X_cam (get rid of K matrix)
571  //////////////////////////////////////////////////////////////////////////////////////////////
572  std::vector<vnl_matrix_fixed<double, 3, 3> > input_cam_K_invs;
573  for (auto & i : input_cams_norm) {
574  const vpgl_calibration_matrix<double>& K = i.get_calibration();
577  input_cam_K_invs.push_back(Kinv);
578  }
579 
580  std::vector< std::vector < std::pair<vnl_vector_fixed<double, 3>, unsigned> > > cam_ids_norm_cam_pts;
581  for (auto & cam_ids_norm_img_pt : cam_ids_norm_img_pts) {
582  std::vector < std::pair<vnl_vector_fixed<double, 3>, unsigned> > cam_pts;
583  for (unsigned i = 0; i < cam_ids_norm_img_pt.size(); i++) {
585  pt[0] = cam_ids_norm_img_pt[i].first[0];
586  pt[1] = cam_ids_norm_img_pt[i].first[1];
587  pt[2] = 1.0;
589  cam_pt = input_cam_K_invs[cam_ids_norm_img_pt[i].second]*pt;
590  std::pair<vnl_vector_fixed<double, 3>, unsigned> pair(cam_pt, cam_ids_norm_img_pt[i].second);
591  cam_pts.push_back(pair);
592  }
593  cam_ids_norm_cam_pts.push_back(cam_pts);
594  }
595  ///////////////////////////////////////////////////////////////////////////////////////////////
596 
597  ////////////////////////////////////////////////////////////////////////
598  // setup the problem Ax = b
599  ////////////////////////////////////////////////////////////////////////
600  // two equations per correspondence
601  unsigned m = cnt_residuals*2;
602  // there are 3 unknowns in t vector
603  unsigned n = 3;
605  // setup rows of A and b
606  unsigned cnt = 0;
607  for (unsigned j = 0; j < cam_ids_norm_cam_pts.size(); j++) {
608  double X = pts_3d[j][0], Y = pts_3d[j][1], Z = pts_3d[j][2];
609 
610  for (auto & i : cam_ids_norm_cam_pts[j]) {
611  vnl_vector_fixed<double, 3> pt = i.first;
612  double x = pt[0]; double y = pt[1]; double z = pt[2];
613  double a = x/z; double b = y/z;
614 
615  vnl_matrix_fixed<double, 3, 3> R = input_cams_norm[i.second].get_rotation().as_matrix();
616  double r1 = R[0][0], r2 = R[0][1], r3 = R[0][2];
617  double r4 = R[1][0], r5 = R[1][1], r6 = R[1][2];
618  double r7 = R[2][0], r8 = R[2][1], r9 = R[2][2];
619  vgl_vector_3d<double> t = input_cams_norm[i.second].get_translation();
620  double t1 = t.x(), t2 = t.y();
621 
622  A(cnt, 0) = r7*a-r1;
623  A(cnt, 1) = r8*a-r2;
624  A(cnt, 2) = r9*a-r3;
625 
626  B[cnt] = r1*X + r2*Y + r3*Z + t1 - r7*X*a - r8*Y*a - r9*Z*a;
627  cnt++;
628 
629  A(cnt, 0) = r7*b-r4;
630  A(cnt, 1) = r8*b-r5;
631  A(cnt, 2) = r9*b-r6;
632  B[cnt] = r4*X + r5*Y + r6*Z + t2 - r7*X*b - r8*Y*b - r9*Z*b;
633  cnt++;
634  }
635  }
636 
638  vnl_vector<double> unknowns(n, 0.0);
639  vnl_lsqr lsqr(ls); lsqr.minimize(unknowns);
640  std::cout << "unknowns: " << unknowns << std::endl;
641 
642  vnl_vector_fixed<double, 3> t_fixed(unknowns[0], unknowns[1], unknowns[2]);
643  std::cout << " t_fixed: " << t_fixed << std::endl;
644  /////////////////////////////////////////////////////////////////////////
645 
646  // denormalize and compute R and t
647  for (const auto & input_cam : input_cams) {
648  const vpgl_calibration_matrix<double>& K = input_cam.get_calibration();
649  const vgl_rotation_3d<double>& R = input_cam.get_rotation();
650  vgl_vector_3d<double> t = input_cam.get_translation();
652  tv[0] = t.x(); tv[1] = t.y(); tv[2] = t.z();
653 
654  vnl_vector_fixed<double, 3> t_new = R*t_fixed + tv;
655  vgl_vector_3d<double> t_newv(t_new[0], t_new[1], t_new[2]);
656 
657  vpgl_perspective_camera<double> cnew(K, R, t_newv);
658 
659  std::cout << " old center: " << input_cam.get_camera_center() << " new center: " << cnew.get_camera_center();
660  std::cout << " move by: " << (input_cam.get_camera_center()-cnew.get_camera_center()).length() << std::endl;
661 
662  output_cams.push_back(cnew);
663  }
664 
665  return true;
666 }
667 
669 {
670  vnl_matrix<double> temp = R.transpose()*R; // this is symmetric
671 
672  vnl_matrix<double> Dreal(3,3,0.0), Vreal(3,3,0.0);
673  vnl_vector<double> D(3, 0.0);
674 
675  // find square root of temp using eigendecomposition
676  if (!vnl_symmetric_eigensystem_compute(temp, Vreal, D)) {
677  std::cerr << "In vpgl_camera_transform::normalize_to_rotation_matrix() -- cannot compute eigendecomposition!\n";
678  return false;
679  }
680  for (unsigned i = 0; i < 3; i++) {
681  if (std::abs(D[i]) < std::numeric_limits<double>::epsilon())
682  D[i] = 1.0;
683  Dreal[i][i] = 1.0/std::sqrt(D[i]);
684  }
685  std::cout << "D real:\n " << Dreal << std::endl;
686  std::cout << "V real:\n " << Vreal << std::endl;
687 
688  vnl_matrix<double> out;
689  out = Vreal*Dreal*Vreal.transpose();
690  std::cout << "( (R^t*R)^(1/2) )^-1:\n " << out << std::endl;
691  out = R*out;
692 
693  for (unsigned i = 0; i < 3; i++)
694  for (unsigned j = 0; j < 3; j++)
695  R_norm[i][j] = out[i][j];
696 
697  return true;
698 }
699 
700 // use quaternions
702 {
704  std::cout << "initial q: " << q << std::endl;
706  std::cout << "norm q: " << q_n << std::endl;
707  vgl_rotation_3d<double> Rn(q_n);
708  R_norm = Rn.as_matrix();
709  return true;
710 }
711 
713  const std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > >& cam_ids_img_pts,
714  const std::vector<vnl_vector_fixed<double, 4> >& pts_3d,
715  std::vector<vpgl_perspective_camera<double> >& output_cams)
716 {
717  // find the number of residuals
718  unsigned cnt_residuals = 0;
719  for (const auto & cam_ids_img_pt : cam_ids_img_pts) {
720  for (unsigned i = 0; i < cam_ids_img_pt.size(); i++) {
721  cnt_residuals++;
722  }
723  }
724  std::cout << "number of residuals: " << cnt_residuals << std::endl;
725 
726  // normalize the image points
727  std::vector<vpgl_perspective_camera<double> > input_cams_norm;
728  std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > > cam_ids_norm_img_pts;
729  normalize_img_pts(input_cams, cam_ids_img_pts, input_cams_norm, cam_ids_norm_img_pts);
730 
731  //////////////////////////////////////////////////////////////////////////////////////////////
732  // compute X_cam (get rid of K matrix)
733  //////////////////////////////////////////////////////////////////////////////////////////////
734  std::vector<vnl_matrix_fixed<double, 3, 3> > input_cam_K_invs;
735  for (auto & i : input_cams_norm) {
736  const vpgl_calibration_matrix<double>& K = i.get_calibration();
739  input_cam_K_invs.push_back(Kinv);
740  }
741 
742  std::vector< std::vector < std::pair<vnl_vector_fixed<double, 3>, unsigned> > > cam_ids_norm_cam_pts;
743  for (auto & cam_ids_norm_img_pt : cam_ids_norm_img_pts) {
744  std::vector < std::pair<vnl_vector_fixed<double, 3>, unsigned> > cam_pts;
745  for (unsigned i = 0; i < cam_ids_norm_img_pt.size(); i++) {
747  pt[0] = cam_ids_norm_img_pt[i].first[0];
748  pt[1] = cam_ids_norm_img_pt[i].first[1];
749  pt[2] = 1.0;
751  cam_pt = input_cam_K_invs[cam_ids_norm_img_pt[i].second]*pt;
752  std::pair<vnl_vector_fixed<double, 3>, unsigned> pair(cam_pt, cam_ids_norm_img_pt[i].second);
753  cam_pts.push_back(pair);
754  }
755  cam_ids_norm_cam_pts.push_back(cam_pts);
756  }
757  ///////////////////////////////////////////////////////////////////////////////////////////////
758 
759  ////////////////////////////////////////////////////////////////////////
760  // setup the problem Ax = b
761  ////////////////////////////////////////////////////////////////////////
762  // two equations per correspondence
763  unsigned m = cnt_residuals*2;
764  // there are 9 unknowns in R matrix
765  unsigned n = 9;
767  //vnl_matrix<double> A(m,n);
769  // setup rows of A and b
770  unsigned cnt = 0;
771  for (unsigned j = 0; j < cam_ids_norm_cam_pts.size(); j++) {
772  double X = pts_3d[j][0], Y = pts_3d[j][1], Z = pts_3d[j][2];
773 
774  for (auto & i : cam_ids_norm_cam_pts[j]) {
775  vnl_vector_fixed<double, 3> pt = i.first;
776  double x = pt[0]; double y = pt[1]; double z = pt[2];
777  double a = x/z; double b = y/z;
778 
779  vnl_matrix_fixed<double, 3, 3> R = input_cams_norm[i.second].get_rotation().as_matrix();
780  double r1 = R[0][0], r2 = R[0][1], r3 = R[0][2];
781  double r4 = R[1][0], r5 = R[1][1], r6 = R[1][2];
782  double r7 = R[2][0], r8 = R[2][1], r9 = R[2][2];
783  vgl_vector_3d<double> t = input_cams_norm[i.second].get_translation();
784  double t1 = t.x(), t2 = t.y(), t3 = t.z();
785 
786  A(cnt, 0) = r7*X*a-r1*X; A(cnt, 1) = r7*Y*a-r1*Y; A(cnt, 2) = r7*Z*a-r1*Z;
787  A(cnt, 3) = r8*X*a-r2*X; A(cnt, 4) = r8*Y*a-r2*Y; A(cnt, 5) = r8*Z*a-r2*Z;
788  A(cnt, 6) = r9*X*a-r3*X; A(cnt, 7) = r9*Y*a-r3*Y; A(cnt, 8) = r9*Z*a-r3*Z;
789  B[cnt] = t1 - t3*a;
790  cnt++;
791 
792  A(cnt, 0) = r7*X*b-r4*X; A(cnt, 1) = r7*Y*b-r4*Y; A(cnt, 2) = r7*Z*b-r4*Z;
793  A(cnt, 3) = r8*X*b-r5*X; A(cnt, 4) = r8*Y*b-r5*Y; A(cnt, 5) = r8*Z*b-r5*Z;
794  A(cnt, 6) = r9*X*b-r6*X; A(cnt, 7) = r9*Y*b-r6*Y; A(cnt, 8) = r9*Z*b-r6*Z;
795  B[cnt] = t2 - t3*b;
796  cnt++;
797  }
798  }
799  vnl_vector<double> unknowns(n, 0.0);
800 
802  unknowns[0] = 1; unknowns[4] = 1; unknowns[8] = 1;
803  vnl_lsqr lsqr(ls); lsqr.minimize(unknowns);
804  /*vnl_qr<double> ls(A);
805  unknowns = ls.solve(B);*/
806  std::cout << "unknowns: " << unknowns << std::endl;
807 
809  R_fixed[0][0] = unknowns[0]; R_fixed[0][1] = unknowns[1]; R_fixed[0][2] = unknowns[2];
810  R_fixed[1][0] = unknowns[3]; R_fixed[1][1] = unknowns[4]; R_fixed[1][2] = unknowns[5];
811  R_fixed[2][0] = unknowns[6]; R_fixed[2][1] = unknowns[7]; R_fixed[2][2] = unknowns[8];
812 
813  std::cout << " R_fixed: " << R_fixed << std::endl; std::cout << " det of R_fixed: " << vnl_det(R_fixed) << std::endl;
814 
815  vnl_matrix_fixed<double, 3, 3> R_fixed_norm;
816  normalize_to_rotation_matrix(R_fixed, R_fixed_norm);
817  //normalize_to_rotation_matrix_q(R_fixed, R_fixed_norm);
818 
819  std::cout << " R_fixed_norm: " << R_fixed_norm << std::endl; std::cout << " det of R_fixed_norm: " << vnl_det(R_fixed_norm) << std::endl;
820 
821  /////////////////////////////////////////////////////////////////////////
822 
823  // denormalize and compute R and t
824  for (const auto & input_cam : input_cams) {
825  const vpgl_calibration_matrix<double>& K = input_cam.get_calibration();
826  vnl_matrix_fixed<double, 3, 3> R = input_cam.get_rotation().as_matrix();
827  vgl_vector_3d<double> t = input_cam.get_translation();
829  tv[0] = t.x(); tv[1] = t.y(); tv[2] = t.z();
830 
831 
832  vnl_matrix_fixed<double, 3, 3> R_new = R*R_fixed_norm;
833  //vnl_matrix_fixed<double, 3, 3> R_new = R*R_fixed;
834 
835  vgl_rotation_3d<double> R_newr(R_new);
836 
837  vpgl_perspective_camera<double> cnew(K, input_cam.get_camera_center(), R_newr);
838  output_cams.push_back(cnew);
839 
840  std::cout << " old center: " << input_cam.get_camera_center() << " new center: " << cnew.get_camera_center();
841  std::cout << " move by: " << (input_cam.get_camera_center()-cnew.get_camera_center()).length() << std::endl;
842  std::cout << " old t: " << input_cam.get_translation() << " new t: " << cnew.get_translation() << std::endl;
843  }
844 
845  return true;
846 }
847 
848 //: apply fixeld transformation
851  std::vector<vpgl_perspective_camera<double> >& output_cams)
852 {
853  for (const auto & input_cam : input_cams) {
854  const vpgl_calibration_matrix<double>& K = input_cam.get_calibration();
855  vnl_matrix_fixed<double, 3, 3> R = input_cam.get_rotation().as_matrix();
856  vgl_vector_3d<double> t = input_cam.get_translation();
858  tv[0] = t.x(); tv[1] = t.y(); tv[2] = t.z();
859 
860 
861  vnl_matrix_fixed<double, 3, 3> R_new = R_fixed*R;
862 
863  vgl_rotation_3d<double> R_newr(R_new);
864 
865  vgl_point_3d<double> cent(input_cam.get_camera_center().x() + t_fixed.x(),
866  input_cam.get_camera_center().x() + t_fixed.y(),
867  input_cam.get_camera_center().x() + t_fixed.z());
868 
869  vpgl_perspective_camera<double> cnew(K, cent, R_newr);
870  output_cams.push_back(cnew);
871 
872  std::cout << " old center: " << input_cam.get_camera_center() << " new center: " << cnew.get_camera_center();
873  std::cout << " move by: " << (input_cam.get_camera_center()-cnew.get_camera_center()).length() << std::endl;
874  std::cout << " old t: " << input_cam.get_translation() << " new t: " << cnew.get_translation() << std::endl;
875  }
876 
877 }
878 
879 //: normalize the points using the inverse of the K matrix
880 void vpgl_camera_transform::K_normalize_img_pts(const std::vector<vpgl_perspective_camera<double> >& input_cams, vnl_matrix_fixed<double, 3, 3> const& input_correspondence_covariance,
881  const std::vector< std::vector < std::pair<vnl_vector_fixed<double, 2>, unsigned> > >& cam_ids_img_pts,
882  std::vector< std::vector < std::pair< std::pair<vnl_vector_fixed<double, 3>, vnl_matrix_fixed<double, 3, 3> >, unsigned> > >& cam_ids_img_pts_norm)
883 {
884  //////////////////////////////////////////////////////////////////////////////////////////////
885  // compute X_cam (get rid of K matrix)
886  //////////////////////////////////////////////////////////////////////////////////////////////
887  std::vector<vnl_matrix_fixed<double, 3, 3> > input_cam_K_invs;
888  for (const auto & input_cam : input_cams) {
889  const vpgl_calibration_matrix<double>& K = input_cam.get_calibration();
892  input_cam_K_invs.push_back(Kinv);
893  }
894 
895  //std::vector< std::vector < std::pair<vnl_vector_fixed<double, 3>, unsigned> > > cam_ids_norm_cam_pts;
896  for (const auto & cam_ids_img_pt : cam_ids_img_pts) {
897  std::vector < std::pair< std::pair<vnl_vector_fixed<double, 3>, vnl_matrix_fixed<double, 3, 3> >, unsigned> > cam_pts;
898  for (unsigned i = 0; i < cam_ids_img_pt.size(); i++) {
900  pt[0] = cam_ids_img_pt[i].first[0];
901  pt[1] = cam_ids_img_pt[i].first[1];
902  pt[2] = 1.0;
904  cam_pt = input_cam_K_invs[cam_ids_img_pt[i].second]*pt;
905  //std::pair<vnl_vector_fixed<double, 3>, unsigned> pair(cam_pt, cam_ids_img_pts[j][i].second);
906 
907  // also compute the covariance matrix of the normalized point using error propagation
908  vnl_matrix_fixed<double, 3, 3> KinvT = input_cam_K_invs[cam_ids_img_pt[i].second].transpose();
909  vnl_matrix_fixed<double, 3, 3> temp = input_correspondence_covariance*KinvT;
910  vnl_matrix_fixed<double, 3, 3> correspondence_covariance = input_cam_K_invs[cam_ids_img_pt[i].second]*temp;
911 
912  std::pair<vnl_vector_fixed<double, 3>, vnl_matrix_fixed<double, 3, 3> > pair(cam_pt, correspondence_covariance);
913  std::pair< std::pair<vnl_vector_fixed<double, 3>, vnl_matrix_fixed<double, 3, 3> >, unsigned> pair2(pair, cam_ids_img_pt[i].second);
914 
915  cam_pts.push_back(pair2);
916  }
917  cam_ids_img_pts_norm.push_back(cam_pts);
918  }
919  ///////////////////////////////////////////////////////////////////////////////////////////////
920 
921 }
922 
923 //: pass the ids of cams in the input_cams vector, this method computes the variance between these two using their image correspondences
924 bool vpgl_camera_transform::compute_covariance(unsigned cam_i, unsigned cam_j, const std::vector<vpgl_perspective_camera<double> >& input_cams,
925  const std::vector< std::vector < std::pair< std::pair<vnl_vector_fixed<double, 3>, vnl_matrix_fixed<double, 3, 3> >, unsigned> > >& cam_ids_img_pts,
926  vnl_matrix_fixed<double, 3, 3>& rot_variance)
927 {
928  vgl_rotation_3d<double> R = vpgl_persp_cam_relative_orientation(input_cams[cam_i], input_cams[cam_j]);
930  vgl_vector_3d<double> h = vpgl_persp_cam_base_line_vector(input_cams[cam_i], input_cams[cam_j]);
931  vnl_vector_fixed<double, 3> hv(h.x(), h.y(), h.z());
932 
933  std::vector<vnl_vector_fixed<double, 3> > cam_i_pts;
934  std::vector<vnl_matrix_fixed<double, 3, 3> > cam_i_pts_cov;
935  std::vector<vnl_vector_fixed<double, 3> > cam_j_pts;
936  std::vector<vnl_matrix_fixed<double, 3, 3> > cam_j_pts_cov;
937 
938  // for each 3d point
939  for (const auto & cam_ids_img_pt : cam_ids_img_pts)
940  // for each frame
941  for (unsigned i = 0; i < cam_ids_img_pt.size(); i++) {
942  //std::cout << "pt: " << cam_ids_img_pts[j][i].first.first << " from cam: " << cam_ids_img_pts[j][i].second << std::endl;
943  if (cam_ids_img_pt[i].second == cam_i) {
944  cam_i_pts.push_back(cam_ids_img_pt[i].first.first);
945  cam_i_pts_cov.push_back(cam_ids_img_pt[i].first.second);
946  } if (cam_ids_img_pt[i].second == cam_j) {
947  cam_j_pts.push_back(cam_ids_img_pt[i].first.first);
948  cam_j_pts_cov.push_back(cam_ids_img_pt[i].first.second);
949  }
950  }
951 
952  if (cam_i_pts.size() != cam_j_pts.size())
953  return false;
954 
955  rot_variance.fill(0.0);
956 
957  for (unsigned i = 0; i < cam_i_pts.size(); i++) {
958  //std::cout << cam_i_pts[i] << " corresponds to " << cam_j_pts[i] << std::endl;
959 
960  // compute b vector for this correspondences b = (x,Rx')h - (h,Rx')x
961  vnl_vector_fixed<double, 3> temp = Rm*(cam_j_pts[i]);
962  double prod = dot_product(cam_i_pts[i],temp);
963  vnl_vector_fixed<double, 3> hv_new = prod*hv;
964 
965  double prod2 = dot_product(hv,temp);
966  vnl_vector_fixed<double, 3> hv_new2 = prod2*cam_i_pts[i];
967 
968  vnl_vector_fixed<double, 3> b = hv_new - hv_new2;
969  std::cout << " \t b: " << b << std::endl;
970 
972  std::cout << " \t bb: \n" << bb << std::endl;
973 
974  vnl_vector<double> term11 = vnl_cross_3d(hv, temp);
975  vnl_vector<double> term12 = cam_i_pts_cov[i]*term11;
976  double t1 = dot_product(term11, term12);
977 
978  vnl_vector<double> term21 = vnl_cross_3d(hv, cam_i_pts[i]);
979  vnl_matrix_fixed<double, 3, 3> term22_temp = cam_j_pts_cov[i]*Rm.transpose();
980  vnl_matrix_fixed<double, 3, 3> term22_m = Rm*term22_temp;
981  vnl_vector<double> term22 = term22_m*term21;
982  double t2 = dot_product(term21, term22);
983 
985  hvM(0,0) = 0.0; hvM(0,1) = -hv[2]; hvM(0,2) = hv[1];
986  hvM(1,0) = hv[2]; hvM(1,1) = 0.0; hvM(1,2) = -hv[0];
987  hvM(2,0) = -hv[1]; hvM(2,1) = hv[0]; hvM(2,2) = 0.0;
988 
989  vnl_matrix_fixed<double, 3, 3> term31 = hvM*Rm;
990  vnl_matrix_fixed<double, 3, 3> term32 = cam_i_pts_cov[i]*term31;
991  vnl_matrix_fixed<double, 3, 3> term33 = term31*cam_j_pts_cov[i];
992  vnl_matrix_fixed<double, 3, 3> term34 = term32.transpose()*term33;
993  double t3 = vnl_trace(term34); // term34[0][0] + term34[1][1] + term34[2][2]; // trace
994 
995  double weight = 1.0/(t1 + t2 + t3);
996  std::cout << " t1: " << t1 << " t2: " << t2 << " t3: " << t3 << " weight: " << weight << std::endl;
997 
998  rot_variance += weight*bb;
999  }
1000 
1001  return true;
1002 }
vgl_point_2d< T > principal_point() const
vnl_vector< T > vnl_cross_3d(const vnl_vector< T > &v1, const vnl_vector< T > &v2)
vnl_matrix_fixed< T, 3, 3 > as_matrix() const
static bool compute_initial_transformation_R(const std::vector< vpgl_perspective_camera< double > > &input_cams, const std::vector< std::vector< std::pair< vnl_vector_fixed< double, 2 >, unsigned > > > &cam_ids_img_pts, const std::vector< vnl_vector_fixed< double, 4 > > &pts_3d, std::vector< vpgl_perspective_camera< double > > &output_cams)
virtual void compute_cams(vnl_vector< double > const &x, std::vector< vpgl_perspective_camera< double > > &output_cams)
vnl_matrix< double > transpose() const
virtual void compute_cams_selective(vnl_vector< double > const &x, std::vector< vpgl_perspective_camera< double > > &output_cams)
static void K_normalize_img_pts(const std::vector< vpgl_perspective_camera< double > > &input_cams, vnl_matrix_fixed< double, 3, 3 > const &input_correspondence_covariance, const std::vector< std::vector< std::pair< vnl_vector_fixed< double, 2 >, unsigned > > > &cam_ids_img_pts, std::vector< std::vector< std::pair< std::pair< vnl_vector_fixed< double, 3 >, vnl_matrix_fixed< double, 3, 3 > >, unsigned > > > &cam_ids_img_pts_norm)
normalize the points using the inverse of the K matrix.
#define m
double get_end_error() const
unsigned int size() const
const vnl_matrix< T > as_matrix() const
T vnl_trace(vnl_matrix< T > const &M)
unsigned int get_number_of_unknowns() const
std::vector< vnl_vector_fixed< double, 4 > > pts_3d_
static bool normalize_to_rotation_matrix(const vnl_matrix_fixed< double, 3, 3 > &R, vnl_matrix_fixed< double, 3, 3 > &R_norm)
static bool compute_covariance(unsigned i, unsigned j, const std::vector< vpgl_perspective_camera< double > > &input_cams, const std::vector< std::vector< std::pair< std::pair< vnl_vector_fixed< double, 3 >, vnl_matrix_fixed< double, 3, 3 > >, unsigned > > > &cam_ids_img_pts, vnl_matrix_fixed< double, 3, 3 > &rot_variance)
pass the ids of cams in the input_cams vector, this method computes the variance between these two us...
Type & z()
void f(vnl_vector< double > const &x, vnl_vector< double > &fx) override
The main function.
static bool normalize_to_rotation_matrix_q(const vnl_matrix_fixed< double, 3, 3 > &R, vnl_matrix_fixed< double, 3, 3 > &R_norm)
std::vector< vnl_matrix_fixed< double, 3, 3 > > Rs_
vnl_matrix_fixed< T, 1, 1 > vnl_inverse(vnl_matrix_fixed< T, 1, 1 > const &m)
Several routines for computing different kinds of cameras from world-point correspondences.
static std::vector< vnl_vector_fixed< double, 3 > > sample_centers(double dim_x, double dim_y, double dim_z, double step)
sample offsets for camera centers in a box with the given dimensions (e.g. plus/minus dim_x) in meter...
VNL_EXPORT T vnl_det(T const *row0, T const *row1)
virtual vnl_matrix_fixed< double, 3, 3 > rod_to_matrix(double r0, double r1, double r2)
Calculate the Jacobian, given the parameter vector x using forward differencing.
T y() const
static bool compute_initial_transformation_t(const std::vector< vpgl_perspective_camera< double > > &input_cams, const std::vector< std::vector< std::pair< vnl_vector_fixed< double, 2 >, unsigned > > > &cam_ids_img_pts, const std::vector< vnl_vector_fixed< double, 4 > > &pts_3d, std::vector< vpgl_perspective_camera< double > > &output_cams)
vgl_vector_3d< T > vpgl_persp_cam_base_line_vector(const vpgl_perspective_camera< T > &cam1, const vpgl_perspective_camera< T > &cam2)
vpgl_camera_transform_f(unsigned cnt_residuals, unsigned n_unknowns, const std::vector< vpgl_perspective_camera< double > > &input_cams, std::vector< std::vector< std::pair< vnl_vector_fixed< double, 2 >, unsigned > > > cam_ids_img_pts, std::vector< vnl_vector_fixed< double, 4 > > pts_3d, bool minimize_R=true)
Constructor. The source image is mapped to the destination frame by dt. nbins is the number of histog...
Type & y()
vgl_rotation_3d< T > vpgl_persp_cam_relative_orientation(const vpgl_perspective_camera< T > &cam1, const vpgl_perspective_camera< T > &cam2)
compute rotation such that principal_vector1 = R*principal_vector2.
vnl_matrix_fixed< T, num_cols, num_rows > transpose() const
static void normalize_img_pts(const std::vector< vpgl_perspective_camera< double > > &input_cams, const std::vector< std::vector< std::pair< vnl_vector_fixed< double, 2 >, unsigned > > > &cam_ids_img_pts, std::vector< vpgl_perspective_camera< double > > &input_cams_norm, std::vector< std::vector< std::pair< vnl_vector_fixed< double, 2 >, unsigned > > > &cam_ids_img_pts_norm)
std::vector< vgl_point_3d< double > > Cs_
vnl_matrix_fixed< T, 3, 3 > get_matrix() const
Get the calibration matrix.
The cost function to be used by a Lev-Marq minimization routine, compute the residuals for each corre...
const vgl_point_3d< T > & get_camera_center() const
vnl_matrix_fixed & fill(T)
T x() const
static bool compute_fixed_transformation(const std::vector< vpgl_perspective_camera< double > > &input_cams, const std::vector< std::vector< std::pair< vnl_vector_fixed< double, 2 >, unsigned > > > &cam_ids_img_pts, const std::vector< vnl_vector_fixed< double, 4 > > &pts_3d, std::vector< vpgl_perspective_camera< double > > &output_cams)
compute the fixed transformation as R and camera center.
T z() const
Type & x()
This class implements the perspective camera class as described in Hartley & Zisserman as a finite ca...
std::vector< vpgl_calibration_matrix< double > > Ks_
static bool compute_fixed_transformation_sample(const std::vector< vpgl_perspective_camera< double > > &input_cams, const std::vector< std::vector< std::pair< vnl_vector_fixed< double, 2 >, unsigned > > > &cam_ids_img_pts, const std::vector< vnl_vector_fixed< double, 4 > > &pts_3d, std::vector< vpgl_perspective_camera< double > > &output_cams)
compute the fixed transformation by sampling centers in a given box and then optimizing for rotation.
T dot_product(v const &a, v const &b)
static void apply_fixed_transformation(const std::vector< vpgl_perspective_camera< double > > &input_cams, vnl_matrix_fixed< double, 3, 3 > &R, vgl_point_3d< double > &t, std::vector< vpgl_perspective_camera< double > > &output_cams)
apply fixeld transformation – R_new = R*R_old.
vnl_vector_fixed< T, n > & normalize()
double length(v const &a)
VNL_EXPORT vnl_matrix_fixed< T, m, n > outer_product(vnl_vector_fixed< T, m > const &a, vnl_vector_fixed< T, n > const &b)
bool minimize(vnl_vector< double > &x)
bool vnl_symmetric_eigensystem_compute(vnl_matrix< T > const &A, vnl_matrix< T > &V, vnl_vector< T > &D)
Type & y()
Type & x()
std::vector< std::vector< std::pair< vnl_vector_fixed< double, 2 >, unsigned > > > cam_ids_img_pts_
Methods for computing a fixed transformation that moves and orients a camera so that given 3-d points...
int minimize(vnl_vector< double > &x)
void set_trace(bool on)
static bool compute_initial_transformation(const std::vector< vpgl_perspective_camera< double > > &input_cams, const std::vector< std::vector< std::pair< vnl_vector_fixed< double, 2 >, unsigned > > > &cam_ids_img_pts, const std::vector< vnl_vector_fixed< double, 4 > > &pts_3d, std::vector< vpgl_perspective_camera< double > > &output_cams)