AliceVision
Photogrammetric Computer Vision Framework
tijsAndXis_From_xi_Ri.hpp
1 // This file is part of the AliceVision project.
2 // Copyright (c) 2016 AliceVision contributors.
3 // Copyright (c) 2012 openMVG contributors.
4 // This Source Code Form is subject to the terms of the Mozilla Public License,
5 // v. 2.0. If a copy of the MPL was not distributed with this file,
6 // You can obtain one at https://mozilla.org/MPL/2.0/.
7 
8 #ifndef ALICEVISION_LINFINITY_COMPUTER_VISION_TRANSLATIONANDSTRUCTUREFrom_xi_RI_H_
9 #define ALICEVISION_LINFINITY_COMPUTER_VISION_TRANSLATIONANDSTRUCTUREFrom_xi_RI_H_
10 
11 #include "aliceVision/numeric/numeric.hpp"
12 #include "aliceVision/linearProgramming/ISolver.hpp"
13 #include <fstream>
14 #include <utility>
15 #include <vector>
16 
17 #ifdef _MSC_VER
18  #pragma warning(once : 4267) // warning C4267: 'argument' : conversion from 'size_t' to 'const int', possible loss of data
19 #endif
20 
21 //--
22 //- Implementation of algorithm from Paper titled :
23 //- [1] "Multiple-View Geometry under the L_\infty Norm."
24 //- Author : Fredrik Kahl, Richard Hartley.
25 //- Date : 9 sept 2008.
26 
27 //- [2] "Multiple View Geometry and the L_\infty -norm"
28 //- Author : Fredrik Kahl
29 //- ICCV 2005.
30 //--
31 
32 namespace aliceVision {
33 namespace lInfinityCV {
34 
35 using namespace linearProgramming;
36 
37 //-- Estimate the translation and the structure
38 // from image points coordinates and camera rotations.
39 // - Estimation of Ci from Ri and xij
40 // [1] -> 6.1 Cameras with Known Rotation
41 //
42 // - This implementation Use L1 norm instead of the L2 norm of
43 // the paper, it allows to use standard standard LP
44 // (simplex) instead of using SOCP (second order cone programming).
45 // Implementation by Pierre Moulon
46 //
47 
49 inline void EncodeTiXi(const Mat& M, // Scene representation
50  const std::vector<Mat3>& Ri,
51  double sigma, // Start upper bound
52  sRMat& A,
53  Vec& C,
54  std::vector<LPConstraints::eLP_SIGN>& vec_sign,
55  std::vector<double>& vec_costs,
56  std::vector<std::pair<double, double>>& vec_bounds)
57 {
58  // Build Constraint matrix.
59  const size_t Ncam = (size_t)M.row(3).maxCoeff() + 1;
60  const size_t N3D = (size_t)M.row(2).maxCoeff() + 1;
61  const size_t Nobs = M.cols();
62 
63  assert(Ncam == Ri.size());
64 
65  A.resize(5 * Nobs, 3 * (N3D + Ncam));
66 
67  C.resize(5 * Nobs, 1);
68  C.fill(0.0);
69  vec_sign.resize(5 * Nobs + 3);
70 
71  const size_t transStart = 0;
72  const size_t pointStart = transStart + 3 * Ncam;
73 #define TVAR(i, el) (0 + 3 * (i) + (el))
74 #define XVAR(j, el) (pointStart + 3 * (j) + (el))
75 
76  // By default set free variable:
77  vec_bounds = std::vector<std::pair<double, double>>(3 * (N3D + Ncam));
78  fill(vec_bounds.begin(), vec_bounds.end(), std::make_pair((double)-1e+30, (double)1e+30));
79  // Fix the translation ambiguity. (set first cam at (0,0,0))
80  vec_bounds[0] = vec_bounds[1] = vec_bounds[2] = std::make_pair(0, 0);
81 
82  size_t rowPos = 0;
83  // Add the cheirality conditions (R_i*X_j + T_i)_3 >= 1
84  for (size_t k = 0; k < Nobs; ++k)
85  {
86  const size_t indexPt3D = M(2, k);
87  const size_t indexCam = M(3, k);
88  const Mat3& R = Ri[indexCam];
89 
90  A.coeffRef(rowPos, XVAR(indexPt3D, 0)) = R(2, 0);
91  A.coeffRef(rowPos, XVAR(indexPt3D, 1)) = R(2, 1);
92  A.coeffRef(rowPos, XVAR(indexPt3D, 2)) = R(2, 2);
93  A.coeffRef(rowPos, TVAR(indexCam, 2)) = 1.0;
94  C(rowPos) = 1.0;
95  vec_sign[rowPos] = LPConstraints::LP_GREATER_OR_EQUAL;
96  ++rowPos;
97 
98  const Vec2 pt = M.block<2, 1>(0, k);
99  const double u = pt(0);
100  const double v = pt(1);
101 
102  // x-residual =>
103  // (R_i*X_j + T_i)_1 / (R_i*X_j + T_i)_3 - u >= -sigma
104  // (R_i*X_j + T_i)_1 - u * (R_i*X_j + T_i)_3 + sigma (R_i*X_j + T_i)_3 >= 0.0
105  // R_i_3 * (sigma-u) + R_i_1 + t_i_1 + t_i_3 * (sigma-u) >= 0
106 
107  A.coeffRef(rowPos, XVAR(indexPt3D, 0)) = R(0, 0) + (sigma - u) * R(2, 0);
108  A.coeffRef(rowPos, XVAR(indexPt3D, 1)) = R(0, 1) + (sigma - u) * R(2, 1);
109  A.coeffRef(rowPos, XVAR(indexPt3D, 2)) = R(0, 2) + (sigma - u) * R(2, 2);
110  A.coeffRef(rowPos, TVAR(indexCam, 0)) = 1.0;
111  A.coeffRef(rowPos, TVAR(indexCam, 2)) = sigma - u;
112  C(rowPos) = 0.0;
113  vec_sign[rowPos] = LPConstraints::LP_GREATER_OR_EQUAL;
114  ++rowPos;
115 
116  A.coeffRef(rowPos, XVAR(indexPt3D, 0)) = R(0, 0) - (sigma + u) * R(2, 0);
117  A.coeffRef(rowPos, XVAR(indexPt3D, 1)) = R(0, 1) - (sigma + u) * R(2, 1);
118  A.coeffRef(rowPos, XVAR(indexPt3D, 2)) = R(0, 2) - (sigma + u) * R(2, 2);
119  A.coeffRef(rowPos, TVAR(indexCam, 0)) = 1.0;
120  A.coeffRef(rowPos, TVAR(indexCam, 2)) = -(sigma + u);
121  C(rowPos) = 0.0;
122  vec_sign[rowPos] = LPConstraints::LP_LESS_OR_EQUAL;
123  ++rowPos;
124 
125  // y-residual =>
126  // (R_i*X_j + T_i)_2 / (R_i*X_j + T_i)_3 - v >= -sigma
127  // (R_i*X_j + T_i)_2 - v * (R_i*X_j + T_i)_3 + sigma (R_i*X_j + T_i)_3 >= 0.0
128  // R_i_3 * (sigma-v) + R_i_2 + t_i_2 + t_i_3 * (sigma-v) >= 0
129  A.coeffRef(rowPos, XVAR(indexPt3D, 0)) = R(1, 0) + (sigma - v) * R(2, 0);
130  A.coeffRef(rowPos, XVAR(indexPt3D, 1)) = R(1, 1) + (sigma - v) * R(2, 1);
131  A.coeffRef(rowPos, XVAR(indexPt3D, 2)) = R(1, 2) + (sigma - v) * R(2, 2);
132  A.coeffRef(rowPos, TVAR(indexCam, 1)) = 1.0;
133  A.coeffRef(rowPos, TVAR(indexCam, 2)) = sigma - v;
134  C(rowPos) = 0.0;
135  vec_sign[rowPos] = LPConstraints::LP_GREATER_OR_EQUAL;
136  ++rowPos;
137 
138  A.coeffRef(rowPos, XVAR(indexPt3D, 0)) = R(1, 0) - (sigma + v) * R(2, 0);
139  A.coeffRef(rowPos, XVAR(indexPt3D, 1)) = R(1, 1) - (sigma + v) * R(2, 1);
140  A.coeffRef(rowPos, XVAR(indexPt3D, 2)) = R(1, 2) - (sigma + v) * R(2, 2);
141  A.coeffRef(rowPos, TVAR(indexCam, 1)) = 1.0;
142  A.coeffRef(rowPos, TVAR(indexCam, 2)) = -(sigma + v);
143  C(rowPos) = 0.0;
144  vec_sign[rowPos] = LPConstraints::LP_LESS_OR_EQUAL;
145  ++rowPos;
146  }
147 #undef TVAR
148 #undef XVAR
149 }
150 
157 
159 {
160  Translation_Structure_L1_ConstraintBuilder(const std::vector<Mat3>& vec_Ri, const Mat& M)
161  {
162  _M = M;
163  _vec_Ri = vec_Ri;
164  }
165 
168  bool Build(double gamma, LPConstraintsSparse& constraint)
169  {
170  EncodeTiXi(_M,
171  _vec_Ri,
172  gamma,
173  constraint._constraintMat,
174  constraint._Cst_objective,
175  constraint._vec_sign,
176  constraint._vec_cost,
177  constraint._vec_bounds);
178 
179  //-- Setup additional information about the Linear Program constraint
180  // We look for nb translations and nb 3D points.
181  const size_t N3D = (size_t)_M.row(2).maxCoeff() + 1;
182  const size_t Ncam = (size_t)_M.row(3).maxCoeff() + 1;
183 
184  constraint._nbParams = (Ncam + N3D) * 3;
185 
186  return true;
187  }
188 
189  std::vector<Mat3> _vec_Ri; // Rotation matrix
190  Mat _M; // M contains (X,Y,index3dPoint, indexCam)^T
191 };
192 
193 } // namespace lInfinityCV
194 } // namespace aliceVision
195 
196 #endif // ALICEVISION_LINFINITY_COMPUTER_VISION_TRANSLATIONANDSTRUCTUREFrom_xi_RI_H_
aliceVision
Definition: checkerDetector.cpp:32
aliceVision::linearProgramming::LPConstraintsSparse
Definition: ISolver.hpp:54
aliceVision::lInfinityCV::Translation_Structure_L1_ConstraintBuilder::Build
bool Build(double gamma, LPConstraintsSparse &constraint)
Definition: tijsAndXis_From_xi_Ri.hpp:168
aliceVision::lInfinityCV::Translation_Structure_L1_ConstraintBuilder
Definition: tijsAndXis_From_xi_Ri.hpp:158