Berkeley SfM
eight_point_algorithm_solver.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, The Regents of the University of California (Regents).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer in the documentation and/or other materials provided
15  * with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Please contact the author(s) of this library if you have any questions.
34  * Authors: Erik Nelson ( eanelson@eecs.berkeley.edu )
35  * David Fridovich-Keil ( dfk@eecs.berkeley.edu )
36  */
37 
39 
40 #include <Eigen/SVD>
41 #include <glog/logging.h>
42 
43 #include "normalization.h"
44 
45 namespace bsfm {
46 
48  const FeatureMatchList& matched_features,
49  Matrix3d& fundamental_matrix) const {
50  // Following: https://www8.cs.umu.se/kurser/TDBD19/VT05/reconstruct-4.pdf
51 
52  // First make sure we even have enough matches to run the eight-point
53  // algorithm.
54  if (matched_features.size() < 8) {
55  VLOG(1) << "Cannot use the eight-point algorithm with less than 8 feature "
56  "matches.";
57  return false;
58  }
59 
60  // Build the A matrix from matched features.
61  MatrixXd A;
62  A.resize(matched_features.size(), 9);
63 
64  // If requested, normalize feature positions prior to computing the A matrix.
65  Matrix3d T1(MatrixXd::Identity(3, 3));
66  Matrix3d T2(MatrixXd::Identity(3, 3));
68  T1 = ComputeNormalization(matched_features, true /*feature set 1*/);
69  T2 = ComputeNormalization(matched_features, false /*feature set 2*/);
70  }
71 
72  // Incrementally add rows to A.
73  for (size_t ii = 0; ii < matched_features.size(); ++ii) {
74  double u1 = matched_features[ii].feature1_.u_;
75  double v1 = matched_features[ii].feature1_.v_;
76  double u2 = matched_features[ii].feature2_.u_;
77  double v2 = matched_features[ii].feature2_.v_;
78 
80  u1 = T1(0, 0) * u1 + T1(0, 2);
81  v1 = T1(1, 1) * v1 + T1(1, 2);
82  u2 = T2(0, 0) * u2 + T2(0, 2);
83  v2 = T2(1, 1) * v2 + T2(1, 2);
84  }
85 
86  A(ii, 0) = u1*u2;
87  A(ii, 1) = v1*u2;
88  A(ii, 2) = u2;
89  A(ii, 3) = u1*v2;
90  A(ii, 4) = v1*v2;
91  A(ii, 5) = v2;
92  A(ii, 6) = u1;
93  A(ii, 7) = v1;
94  A(ii, 8) = 1;
95  }
96 
97  // Get svd(A). Save some time and compute a thin U. We still need a full V.
98  Eigen::JacobiSVD<Eigen::MatrixXd> svd;
99  svd.compute(A, Eigen::ComputeThinU | Eigen::ComputeFullV);
100  if (!svd.computeV()) {
101  VLOG(1) << "Failed to compute a singular value decomposition of A matrix.";
102  return false;
103  }
104 
105  // Get the fundamental matrix elements from the SVD decomposition.
106  const VectorXd f_vec = svd.matrixV().col(8);
107 
108  // Turn the elements of the fundamental matrix into an actual matrix.
109  fundamental_matrix.row(0) = f_vec.topRows(3).transpose();
110  fundamental_matrix.row(1) = f_vec.middleRows(3, 3).transpose();
111  fundamental_matrix.row(2) = f_vec.bottomRows(3).transpose();
112 
113  // If requested, make sure that the computed fundamental matrix has rank 2.
114  // This is step 2 of the eight-point algorithm from the slides.
116  // Get svd(F). We need full U and V to reconstruct the rank deficient F.
117  svd.compute(fundamental_matrix, Eigen::ComputeFullU | Eigen::ComputeFullV);
118  svd.compute(fundamental_matrix);
119  if (!svd.computeU() || !svd.computeV()) {
120  VLOG(1) << "Failed to compute a singular value decomposition of "
121  "fundamental matrix.";
122  return false;
123  }
124 
125  // Build a matrix of the first 8 singular values down the diagonal. Make the
126  // last diagonal entry 0.
127  MatrixXd S_deficient(MatrixXd::Zero(3, 3));
128  S_deficient(0, 0) = svd.singularValues()(0);
129  S_deficient(1, 1) = svd.singularValues()(1);
130  fundamental_matrix = svd.matrixU() * S_deficient * svd.matrixV().transpose();
131  }
132 
133  // If normalization was requested, we need to 'un-normalize' the fundamental
134  // matrix.
136  fundamental_matrix = T2.transpose() * fundamental_matrix * T1;
137  }
138 
139  return true;
140 }
141 
142 } //\namespace bsfm
Matrix3d ComputeNormalization(const FeatureMatchList &matched_features, bool use_feature_set1)
virtual bool ComputeFundamentalMatrix(const FeatureMatchList &matched_features, Matrix3d &fundamental_matrix) const
Definition: camera.cpp:50
std::vector< FeatureMatch > FeatureMatchList
Definition: feature_match.h:99
FundamentalMatrixSolverOptions options_