PICCANTE  0.4
The hottest HDR imaging library!
camera_matrix.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_COMPUTER_VISION_CAMERA_MARTIX_HPP
19 #define PIC_COMPUTER_VISION_CAMERA_MARTIX_HPP
20 
21 #include <vector>
22 #include <random>
23 #include <stdlib.h>
24 
25 #include "../base.hpp"
26 
27 #include "../util/math.hpp"
28 #include "../util/eigen_util.hpp"
29 
30 #ifndef PIC_DISABLE_EIGEN
31 
32 #ifndef PIC_EIGEN_NOT_BUNDLED
33  #include "../externals/Eigen/Dense"
34  #include "../externals/Eigen/SVD"
35  #include "../externals/Eigen/Geometry"
36  #include "../externals/Eigen/Geometry"
37  #include "../externals/Eigen/QR"
38 #else
39  #include <Eigen/Dense>
40  #include <Eigen/SVD>
41  #include <Eigen/Geometry>
42  #include <Eigen/QR>
43 #endif
44 
45 #endif
46 
47 namespace pic {
48 
49 #ifndef PIC_DISABLE_EIGEN
50 
56 PIC_INLINE Eigen::Vector3d computeEpipole(Eigen::Matrix3d &F)
57 {
58  Eigen::JacobiSVD< Eigen::Matrix3d > svdF(F, Eigen::ComputeFullV);
59  Eigen::Matrix3d V = svdF.matrixV();
60 
61  Eigen::Vector3d e;
62 
63  e[0] = V(0, 2);
64  e[1] = V(1, 2);
65  e[2] = V(2, 2);
66 
67  return e;
68 }
69 
76 PIC_INLINE Eigen::Matrix34d getCameraMatrixFromHomography(Eigen::Matrix3d &H, Eigen::Matrix3d &K)
77 {
78  Eigen::Matrix34d m;
79  m.setZero();
80 
81  Eigen::Matrix3d K_inv = K.inverse();
82 
83  Eigen::Matrix3d H_p = K_inv * H;
84 
85  Eigen::Vector3d r_0(H_p(0, 0), H_p(1, 0), H_p(2, 0));
86  Eigen::Vector3d r_1(H_p(0, 1), H_p(1, 1), H_p(2, 1));
87 
88  r_0.normalize();
89  r_1.normalize();
90  Eigen::Vector3d r_2 = r_0.cross(r_1);
91 
92  Eigen::Vector3d t(H_p(0, 2), H_p(1, 2), H_p(2, 2));
93 
94  m(0, 0) = r_0[0];
95  m(1, 0) = r_0[1];
96  m(2, 0) = r_0[2];
97 
98  m(0, 1) = r_1[0];
99  m(1, 1) = r_1[1];
100  m(2, 1) = r_1[2];
101 
102  m(0, 2) = r_2[0];
103  m(1, 2) = r_2[1];
104  m(2, 2) = r_2[2];
105 
106  m(0 , 3) = t[0];
107  m(1 , 3) = t[1];
108  m(2 , 3) = t[2];
109 
110  return K * m;
111 }
112 
118 PIC_INLINE Eigen::Matrix34d getCameraMatrixIdentity(Eigen::Matrix3d &K)
119 {
120  Eigen::Matrix34d m;
121  m.setIdentity();
122  return K * m;
123 }
124 
132 PIC_INLINE Eigen::Matrix34d getCameraMatrix(Eigen::Matrix3d &K, Eigen::Matrix3d &R, Eigen::Vector3d &t)
133 {
134  Eigen::Matrix34d m;
135 
136  m(0, 0) = R(0, 0);
137  m(1, 0) = R(1, 0);
138  m(2, 0) = R(2, 0);
139 
140  m(0, 1) = R(0, 1);
141  m(1, 1) = R(1, 1);
142  m(2, 1) = R(2, 1);
143 
144  m(0, 2) = R(0, 2);
145  m(1, 2) = R(1, 2);
146  m(2, 2) = R(2, 2);
147 
148  m(0, 3) = t[0];
149  m(1, 3) = t[1];
150  m(2, 3) = t[2];
151 
152  return K * m;
153 }
154 
162 PIC_INLINE void decomposeCameraMatrix(Eigen::Matrix34d &P,
163  Eigen::Matrix3d &K,
164  Eigen::Matrix3d &R,
165  Eigen::Vector3d &t)
166 {
167  Eigen::Matrix3d matrix = P.block<3, 3>(0, 0).inverse();
168 
169 
170  //QR decomposition
171  Eigen::HouseholderQR<Eigen::Matrix3d> qr(matrix.rows(), matrix.cols());
172  qr.compute(matrix);
173 
174  Eigen::Matrix3d Q = qr.householderQ();
175  Eigen::Matrix3d U = qr.matrixQR().triangularView<Eigen::Upper>();
176 
177  auto U_d = getDiagonalFromMatrix(U);
178  Eigen::Vector3d d = U_d;
179  for(int i = 0; i < 3; i++) {
180  if(d[i] != 0.0) {
181  d[i] = U_d[i] > 0.0 ? 1.0 : -1.0;
182  }
183  }
184  auto D = DiagonalMatrix(d);
185 
186  Q = Q * D;
187  U = D * U;
188 
189  //compute K, R, and t
190  auto Q_t = Eigen::Transpose< Eigen::Matrix3d >(Q);
191  auto s = Q.determinant();
192 
193  R = s * Q_t;
194  t = s * U * P.col(3);
195 
196  if(U(2, 2) > 0.0) {
197  U /= U(2, 2);
198  }
199 
200  K = U.inverse();
201 }
202 
210 PIC_INLINE Eigen::Vector2i cameraMatrixProject(Eigen::Matrix34d &M, Eigen::Vector4d &p)
211 {
212  Eigen::Vector3d proj = M * p;
213  proj[0] /= proj[2];
214  proj[1] /= proj[2];
215 
216  return Eigen::Vector2i(int(proj[0]), int(proj[1]));
217 }
218 
226 PIC_INLINE Eigen::Vector2i cameraMatrixProject(Eigen::Matrix34d &M, Eigen::Vector3d &p)
227 {
228  Eigen::Vector4d p4d(p[0], p[1], p[2], 1.0);
229  return cameraMatrixProject(M, p4d);
230 }
231 
243 PIC_INLINE Eigen::Vector2i cameraMatrixProjection(Eigen::Matrix34d &M, Eigen::Vector3d &p, double cx, double cy, double fx, double fy, double lambda)
244 {
245  Eigen::Vector4d p_t = Eigen::Vector4d(p[0], p[1], p[2], 1.0);
246  Eigen::Vector2i out;
247  Eigen::Vector3d proj = M * p_t;
248  proj[0] /= proj[2];
249  proj[1] /= proj[2];
250 
251  double x_cx = (proj[0] - cx);
252  double y_cy = (proj[1] - cy);
253 
254  double dx = x_cx / fx;
255  double dy = y_cy / fy;
256  double rho_sq = dx * dx + dy * dy;
257 
258  double factor = 1.0 / (1.0 + rho_sq * lambda);
259 
260  proj[0] = x_cx * factor + cx;
261  proj[1] = y_cy * factor + cy;
262 
263  out[0] = int(proj[0]);
264  out[1] = int(proj[1]);
265 
266  return out;
267 }
268 
274 PIC_INLINE Eigen::Vector3d getOpticalCenter(Eigen::Matrix34d &P)
275 {
276  Eigen::Matrix3d Q = P.block<3, 3>(0, 0);
277  auto Q_inv = Q.inverse();
278  return - Q_inv * P.col(3);
279 }
280 
294 PIC_INLINE void cameraRectify(Eigen::Matrix3d &K0, Eigen::Matrix3d &R0, Eigen::Vector3d &t0,
295  Eigen::Matrix3d &K1, Eigen::Matrix3d &R1, Eigen::Vector3d &t1,
296  Eigen::Matrix34d &P0_out, Eigen::Matrix34d &P1_out,
297  Eigen::Matrix3d &T0, Eigen::Matrix3d &T1)
298 {
299  auto P0_in = getCameraMatrix(K0, R0, t0);
300  auto P1_in = getCameraMatrix(K1, R1, t1);
301 
302  /*
303  auto K0_i = K0.inverse();
304  auto K1_i = K1.inverse();
305 
306  auto R0_t = Eigen::Transpose< Eigen::Matrix3d >(R0);
307  auto R1_t = Eigen::Transpose< Eigen::Matrix3d >(R1);
308  auto c0 = -R0_t * K0_i * P0t.col(3);
309  auto c1 = -R1_t * K1_i * P1t.col(3);
310  */
311 
312  //compute optical centers
313 
314  auto c0 = getOpticalCenter(P0_in);
315  auto c1 = getOpticalCenter(P1_in);
316 
317  //compute new rotation matrix
318  Eigen::Vector3d x_axis = c1 - c0;
319  Eigen::Vector3d tmp = R1.row(2);
320  Eigen::Vector3d y_axis = tmp.cross(x_axis);
321  Eigen::Vector3d z_axis = x_axis.cross(y_axis);
322 
323  x_axis.normalize();
324  y_axis.normalize();
325  z_axis.normalize();
326 
327  Eigen::Matrix3d R;
328 
329  R(0, 0) = x_axis[0];
330  R(0, 1) = x_axis[1];
331  R(0, 2) = x_axis[2];
332 
333  R(1, 0) = y_axis[0];
334  R(1, 1) = y_axis[1];
335  R(1, 2) = y_axis[2];
336 
337  R(2, 0) = z_axis[0];
338  R(2, 1) = z_axis[1];
339  R(2, 2) = z_axis[2];
340 
341  //new camera matrices
342  Eigen::Matrix3d K;
343  K.setZero();
344  K(0, 0) = K0(0, 0);
345  K(1, 1) = K0(1, 1);
346  K(0, 2) = (K0(0, 2) + K1(0, 2)) * 0.5;
347  K(1, 2) = (K0(1, 2) + K1(1, 2)) * 0.5;
348  K(2, 2) = 1.0;
349 
350  Eigen::Vector3d t0n = -R * c0;
351  P0_out = getCameraMatrix(K, R, t0n);
352 
353  Eigen::Vector3d t1n = -R * c1;
354  P1_out = getCameraMatrix(K, R, t1n);
355 
356  //transformations
357  auto Q0o = P0_in.block<3, 3>(0, 0);
358  auto Q0n = P0_out.block<3, 3>(0, 0);
359  T0 = Q0n * Q0o.inverse();
360 
361  auto Q1o = P1_in.block<3, 3>(0, 0);
362  auto Q1n = P1_out.block<3, 3>(0, 0);
363  T1 = Q1n * Q1o.inverse();
364 }
365 
375 PIC_INLINE void cameraRectify(Eigen::Matrix34d &P0_in, Eigen::Matrix34d &P1_in,
376  Eigen::Matrix34d &P0_out, Eigen::Matrix34d &P1_out,
377  Eigen::Matrix3d &T0, Eigen::Matrix3d &T1)
378 {
379  Eigen::Matrix3d K0, K1, R0, R1;
380  Eigen::Vector3d t0, t1;
381 
382  decomposeCameraMatrix(P0_in, K0, R0, t0);
383 
384  decomposeCameraMatrix(P1_in, K1, R1, t1);
385 
386  cameraRectify(K0, R0, t0,
387  K1, R1, t1,
388  P0_out, P1_out,
389  T0, T1);
390 }
391 
392 #endif // PIC_DISABLE_EIGEN
393 
394 } // end namespace pic
395 
396 #endif // PIC_COMPUTER_VISION_CAMERA_MARTIX_HPP
PIC_INLINE Eigen::Matrix34d getCameraMatrixIdentity(Eigen::Matrix3d &K)
getCameraMatrixIdentity
Definition: camera_matrix.hpp:118
PIC_INLINE Eigen::Vector3d getDiagonalFromMatrix(Eigen::Matrix3d &mat)
getDiagonalFromMatrix
Definition: eigen_util.hpp:130
PIC_INLINE Eigen::Matrix34d getCameraMatrix(Eigen::Matrix3d &K, Eigen::Matrix3d &R, Eigen::Vector3d &t)
getCameraMatrix
Definition: camera_matrix.hpp:132
PIC_INLINE Eigen::Vector2i cameraMatrixProjection(Eigen::Matrix34d &M, Eigen::Vector3d &p, double cx, double cy, double fx, double fy, double lambda)
cameraMatrixProjection
Definition: camera_matrix.hpp:243
PIC_INLINE Eigen::Vector2i cameraMatrixProject(Eigen::Matrix34d &M, Eigen::Vector4d &p)
cameraMatrixProject projects a point, p, using the camera matrix, M.
Definition: camera_matrix.hpp:210
PIC_INLINE Eigen::Vector3d computeEpipole(Eigen::Matrix3d &F)
computeEpipole computes the epipole of a fundamental matrix F.
Definition: camera_matrix.hpp:56
#define PIC_INLINE
Definition: base.hpp:33
PIC_INLINE Eigen::Vector3d getOpticalCenter(Eigen::Matrix34d &P)
getOpticalCenter
Definition: camera_matrix.hpp:274
PIC_INLINE Eigen::Matrix3d DiagonalMatrix(Eigen::Vector3d D)
DiagonalMatrix creates a diagonal matrix.
Definition: eigen_util.hpp:113
PIC_INLINE void decomposeCameraMatrix(Eigen::Matrix34d &P, Eigen::Matrix3d &K, Eigen::Matrix3d &R, Eigen::Vector3d &t)
decomposeCameraMatrix
Definition: camera_matrix.hpp:162
PIC_INLINE void cameraRectify(Eigen::Matrix3d &K0, Eigen::Matrix3d &R0, Eigen::Vector3d &t0, Eigen::Matrix3d &K1, Eigen::Matrix3d &R1, Eigen::Vector3d &t1, Eigen::Matrix34d &P0_out, Eigen::Matrix34d &P1_out, Eigen::Matrix3d &T0, Eigen::Matrix3d &T1)
cameraRectify
Definition: camera_matrix.hpp:294
Definition: bilateral_separation.hpp:25
PIC_INLINE Eigen::Matrix34d getCameraMatrixFromHomography(Eigen::Matrix3d &H, Eigen::Matrix3d &K)
getCameraMatrixFromHomography
Definition: camera_matrix.hpp:76