vpgl_affine_rectification.cxx
Go to the documentation of this file.
1 #include <iostream>
2 #include <limits>
4 //:
5 // \file
6 
7 
8 #include <vnl/algo/vnl_svd.h>
9 #ifdef _MSC_VER
10 # include <vcl_msvc_warnings.h>
11 #endif
12 #include <vnl/algo/vnl_lsqr.h>
15 #include <vgl/vgl_box_3d.h>
16 
18  const std::vector< vgl_point_3d<double> >& world_pts)
19 {
20  vpgl_affine_camera<double> aff_camera;
21  vpgl_affine_camera_compute::compute(image_pts, world_pts, aff_camera);
22  vgl_box_3d<double> bbox;
23  for (const auto & world_pt : world_pts)
24  bbox.add(world_pt);
25 
26  // use the constructor with matrix to compute the camera direction properly
27  auto* out_camera = new vpgl_affine_camera<double>(aff_camera.get_matrix());
28  out_camera->set_viewing_distance(10.0*bbox.height());
29  return out_camera;
30 }
31 
32 
33 //:Extract the fundamental matrix from affine cameras
35  const vpgl_affine_camera<double>* cam2,
37 {
40  vnl_vector_fixed<double,4> C1; C1[0] = C.x(); C1[1] = C.y(); C1[2] = C.z(); C1[3] = C.w();
41 
43 
44  vnl_vector_fixed<double,3> e2 = M2*C1;
45 
47  e2M[0][0] = 0; e2M[0][1] = -e2[2]; e2M[0][2] = e2[1];
48  e2M[1][0] = e2[2]; e2M[1][1] = 0; e2M[1][2] = -e2[0];
49  e2M[2][0] = -e2[1]; e2M[2][1] = e2[0]; e2M[2][2] = 0;
50 
51  // find pseudo inverse of the first camera
52  vnl_svd<double> temp(M1*M1.transpose()); // use svd to find inverse of M1*M1.transpose()
53  vnl_matrix_fixed<double, 4,3> M1inv = M1.transpose()*temp.inverse();
54 
56  FAM = e2M*M2*M1inv;
57  FA.set_matrix(FAM);
58 
59  // check for zero elements
60  /*if (std::abs(FA.get_matrix()[0][0]) > 10*std::numeric_limits<double>::epsilon() ||
61  std::abs(FA.get_matrix()[0][1]) > 10*std::numeric_limits<double>::epsilon() ||
62  std::abs(FA.get_matrix()[1][0]) > 10*std::numeric_limits<double>::epsilon() ||
63  std::abs(FA.get_matrix()[1][1]) > 10*std::numeric_limits<double>::epsilon()) {
64  std::cerr << "In vpgl_affine_rectification::compute_affine_f() -- the computed matrix is not an affine fundamental matrix! the input cameras may have not been affine cameras!\n";
65  return false;
66  }*/
67 
68  return true;
69 }
70 
71 //: compute the rectification homographies using the affine fundamental matrix
72 // image correspondences need to be passed to find homographies
73 // (if cameras are known, one can use known points in 3d in the observed scene, project them using the cameras and pass the image points to this routine)
75  const std::vector<vnl_vector_fixed<double, 3> >& img_p1,
76  const std::vector<vnl_vector_fixed<double, 3> >& img_p2,
79 {
81  vnl_vector_fixed<double, 2> e1; e1[0] = -FAM[2][1]; e1[1] = FAM[2][0]; e1[2] = 0;
82  vnl_vector_fixed<double, 2> e2; e2[0] = -FAM[1][2]; e2[1] = FAM[0][2]; e2[2] = 0;
83 
84  double e1l = e1.magnitude();
85  double e2l = e2.magnitude();
86 
87  H1.set_identity();
88  H2.set_identity();
89 
90  // rotation of the left image so that epipolar lines become parallel
91  H1[0][0] = e1[0]/e1l; H1[0][1] = e1[1]/e1l;
92  H1[1][0] = -e1[1]/e1l; H1[1][1] = e1[0]/e1l;
93 
94  // rotation of the right image so that epipolar lines become parallel
95  H2[0][0] = e2[0]/e2l; H2[0][1] = e2[1]/e2l;
96  H2[1][0] = -e2[1]/e2l; H2[1][1] = e2[0]/e2l;
97 
98  auto m = static_cast<unsigned int>(img_p1.size());
99  if (m != img_p2.size()) {
100  std::cerr << " In vpgl_affine_rectification::compute_rectification() -- img_p1 and img_p2 do not have equal size!\n";
101  return false;
102  }
103 
104  // find a scaling and offset for the Y axis
106  // setup rows of A and b
107  for (unsigned i = 0; i < m; i++) {
108  vnl_vector_fixed<double, 3> p1rot = H1*img_p1[i];
109  vnl_vector_fixed<double, 3> p2rot = H2*img_p2[i];
110  A(i,0) = p2rot[1]; A(i,1) = 1;
111  b[i] = p1rot[1];
112  }
113 
115  vnl_vector<double> scaling(2); scaling[0]=scaling[1]=0.0;
116  vnl_lsqr lsqr(ls); lsqr.minimize(scaling);
117  std::cout << "scaling: " << scaling << std::endl;
118 
119  H2[0][0] = scaling[0]*H2[0][0]; H2[0][1] = scaling[0]*H2[0][1];
120  H2[1][0] = scaling[0]*H2[1][0]; H2[1][1] = scaling[0]*H2[1][1];
121 
122  H2[1][2] = scaling[1];
123 
124  // find scaling, skew and offset for X
126  for (unsigned i = 0; i < m; i++) {
127  vnl_vector_fixed<double, 3> p1rot = H1*img_p1[i];
128  vnl_vector_fixed<double, 3> p2rot = H2*img_p2[i];
129  AA(i,0) = p2rot[0]; AA(i,1) = p2rot[1]; AA(i,2) = p2rot[2];
130  b[i] = p1rot[0];
131  }
133  vnl_vector<double> shear(3); shear[0]=shear[1]=shear[2]=0.0;
134  vnl_lsqr lsqr2(ls2); lsqr2.minimize(shear);
135  std::cout << "shear: " << shear << std::endl;
136 
138  interm[0][1] = -shear[1] / 2.0;
139  H1 = interm*H1; // affine_left = interm * affine_left;
140 
141  interm.set_identity();
142  interm[0][0] = shear[0];
143  interm[0][1] = shear[1] / 2.0;
144  interm[0][2] = shear[2];
145  H2 = interm*H2; // affine_right = interm * affine_right;
146 
147  return true;
148 }
abs_t magnitude() const
Methods for computing an affine fundamental matrix, FA using a pair of affine cameras and using FA to...
#define m
void add(vgl_point_3d< Type > const &p)
Type z() const
static bool compute_rectification(const vpgl_affine_fundamental_matrix< double > &FA, const std::vector< vnl_vector_fixed< double, 3 > > &img_p1, const std::vector< vnl_vector_fixed< double, 3 > > &img_p2, vnl_matrix_fixed< double, 3, 3 > &H1, vnl_matrix_fixed< double, 3, 3 > &H2)
compute the rectification homographies using the affine fundamental matrix.
Several routines for computing different kinds of cameras from world-point correspondences.
vnl_matrix_fixed & set_identity()
vnl_matrix_fixed< T, num_cols, num_rows > transpose() const
Type w() const
vgl_homg_point_3d< T > camera_center() const override
Find the 3d coordinates of the center of the camera. Will be an ideal point with the sense of the ray...
Type height() const
static bool compute(const std::vector< vgl_point_2d< double > > &image_pts, const std::vector< vgl_point_3d< double > > &world_pts, vpgl_affine_camera< double > &camera)
Compute from two sets of corresponding points.
const vnl_matrix_fixed< T, 3, 4 > & get_matrix() const
Return a copy of the camera matrix.
static bool compute_affine_f(const vpgl_affine_camera< double > *cam1, const vpgl_affine_camera< double > *cam2, vpgl_affine_fundamental_matrix< double > &FA)
extract the fundamental matrix from a pair of affine cameras.
void set_viewing_distance(T dist)
set a finite viewing distance to allow the methods below to return finite objects.
Type y() const
const vnl_matrix_fixed< T, 3, 3 > & get_matrix() const
Get a copy of the FM in vnl form.
Type x() const
static vpgl_affine_camera< double > * compute_affine_cam(const std::vector< vgl_point_2d< double > > &image_pts, const std::vector< vgl_point_3d< double > > &world_pts)
int minimize(vnl_vector< double > &x)
void set_matrix(const vpgl_proj_camera< T > &cr, const vpgl_proj_camera< T > &cl)