Berkeley SfM
fundamental_matrix_ransac_problem.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: David Fridovich-Keil ( dfk@eecs.berkeley.edu )
35  * Erik Nelson ( eanelson@eecs.berkeley.edu )
36  */
37 
38 ///////////////////////////////////////////////////////////////////////////////
39 //
40 // This class defines the FundamentalMatrixRansacModel class, which
41 // is derived from the abstract base class RansacModel.
42 //
43 ///////////////////////////////////////////////////////////////////////////////
44 
45 #include <iostream>
46 
47 #include <algorithm>
48 #include <Eigen/Core>
49 #include <gflags/gflags.h>
50 #include <vector>
51 
52 #include "ransac_problem.h"
54 #include "../math/random_generator.h"
55 #include "../geometry/eight_point_algorithm_solver.h"
56 #include "../geometry/fundamental_matrix_solver_options.h"
57 
58 namespace bsfm {
59 
60 // ------------ FundamentalMatrixRansacModel methods ------------ //
61 
62 // Default constructor.
64  : F_(Matrix3d::Identity()), error_(0.0) {}
65 
67  const Matrix3d& F)
68  : F_(F), error_(0.0) {}
69 
70 // Destructor.
72 
73 // Return model error.
75  return error_;
76 }
77 
78 // Evaluate model on a single data element and update error.
80  const FeatureMatch& data_point,
81  double error_tolerance) {
82  const double error = EvaluateEpipolarCondition(data_point);
83 
84  // Test squared error against the provided tolerance.
85  if (error * error < error_tolerance) {
86  return true;
87  }
88  return false;
89 }
90 
92  const FeatureMatch& match) const {
93  // Construct vectors for 2D keypoints in match.
94  Vector3d kp1, kp2;
95  kp1 << match.feature1_.u_, match.feature1_.v_, 1;
96  kp2 << match.feature2_.u_, match.feature2_.v_, 1;
97 
98  // Compute deviation from the epipolar condition.
99  const double epipolar_condition = kp2.transpose() * F_ * kp1;
100  return epipolar_condition;
101 }
102 
103 // ------------ FundamentalMatrixRansacProblem methods ------------ //
104 
105 // RansacProblem constructor.
107 
108 // RansacProblem destructor.
110 
111 // Subsample the data.
113  unsigned int num_samples) {
114  // Randomly shuffle the entire dataset and take the first elements.
115  std::random_shuffle(data_.begin(), data_.end());
116 
117  // Make sure we don't over step.
118 
119  if (static_cast<size_t>(num_samples) > data_.size()) {
120  VLOG(1) << "Requested more RANSAC data samples than are available. "
121  "Returning all data.";
122  num_samples = data_.size();
123  }
124 
125  // Get samples.
126  std::vector<FeatureMatch> samples(
127  data_.begin(), data_.begin() + static_cast<size_t>(num_samples));
128 
129  return samples;
130 }
131 
132 // Return all data that was not sampled.
134  unsigned int num_sampled_previously) const {
135  // In Sample(), the data was shuffled and we took the first
136  // 'num_sampled_previously' elements. Here, take the remaining elements.
137  if (num_sampled_previously >= data_.size()) {
138  VLOG(1) << "No remaining RANSAC data to sample.";
139  return std::vector<FeatureMatch>();
140  }
141 
142  return std::vector<FeatureMatch>(
143  data_.begin() + num_sampled_previously, data_.end());
144 }
145 
146 // Fit a model to the provided data using the 8-point algorithm.
148  const std::vector<FeatureMatch>& input_data) const {
149  // Create an empty fundamental matrix.
150  Matrix3d F;
151 
152  // Run the 8-point algorithm with default options.
155  solver.SetOptions(options);
156 
157  if (solver.ComputeFundamentalMatrix(input_data, F)) {
158  // Create a new RansacModel using the computed fundamental matrix.
159  FundamentalMatrixRansacModel model_out(F);
160 
161  // Record sum of squared error over all matches.
162  model_out.error_ = 0.0;
163  for (const auto& feature_match : input_data) {
164  const double error = model_out.EvaluateEpipolarCondition(feature_match);
165  model_out.error_ += error * error;
166  }
167 
168  return model_out;
169  }
170  // Set a large error - we didn't find a model that fits the data.
171  FundamentalMatrixRansacModel model_out(Matrix3d::Identity());
172  model_out.error_ = std::numeric_limits<double>::infinity();
173  return model_out;
174 }
175 
176 } //\namespace bsfm
double v_
Definition: feature.h:62
virtual std::vector< FeatureMatch > RemainingData(unsigned int num_sampled_previously) const
virtual std::vector< FeatureMatch > SampleData(unsigned int num_samples)
double EvaluateEpipolarCondition(const FeatureMatch &match) const
double u_
Definition: feature.h:62
virtual bool IsGoodFit(const FeatureMatch &data_point, double error_tolerance)
virtual bool ComputeFundamentalMatrix(const FeatureMatchList &matched_features, Matrix3d &fundamental_matrix) const
Definition: camera.cpp:50
virtual void SetOptions(const FundamentalMatrixSolverOptions &options)
virtual FundamentalMatrixRansacModel FitModel(const std::vector< FeatureMatch > &input_data) const