Berkeley SfM
ransac.h
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 
38 ///////////////////////////////////////////////////////////////////////////////
39 //
40 // This class defines a generic RANSAC solver. The user may define a
41 // RansacProblem derived class, and plug it in here.
42 //
43 ///////////////////////////////////////////////////////////////////////////////
44 
45 
46 #ifndef BSFM_RANSAC_RANSAC_H
47 #define BSFM_RANSAC_RANSAC_H
48 
49 #include <limits>
50 #include <glog/logging.h>
51 
52 #include "ransac_options.h"
53 #include "ransac_problem.h"
54 
55 namespace bsfm {
56 
57 template <typename DataType, typename ModelType>
58 class Ransac {
59  public:
60  Ransac() { }
61  ~Ransac() { }
62 
63  // Set options for the RANSAC solver.
64  inline void SetOptions(const RansacOptions& options);
65 
66  // Run RANSAC using the user's input data (stored in 'problem'). Save the best
67  // model that RANSAC finds after options_.iterations iterations in the
68  // problem. This returns false if RANSAC does not find any solution.
69  inline bool Run(RansacProblem<DataType, ModelType>& problem) const;
70 
71  private:
73 }; //\class Ransac
74 
75 // -------------------- Implementation -------------------- //
76 
77 template <typename DataType, typename ModelType>
79  options_ = options;
80 }
81 
82 template <typename DataType, typename ModelType>
84  RansacProblem<DataType, ModelType>& problem) const {
85  // By default, a valid model has not been found.
86  problem.SetSolutionFound(false);
87 
88  // Set the initial error to something very large.
89  double best_error = std::numeric_limits<double>::infinity();
90 
91  // Proceed for options_.iterations iterations of RANSAC.
92  for (unsigned int iter = 0; iter < options_.iterations; ++iter) {
93  // Sample data points.
94  std::vector<DataType> sampled = problem.SampleData(options_.num_samples);
95 
96  // Fit a model to the sampled data points.
97  ModelType initial_model = problem.FitModel(sampled);
98 
99  // Which of the remaining points are also inliers under this model?
100  std::vector<DataType> unsampled = problem.RemainingData(options_.num_samples);
101  std::vector<DataType> inliers(sampled);
102  for (const auto& not_sampled_data_point : unsampled) {
103  if (initial_model.IsGoodFit(not_sampled_data_point,
104  options_.acceptable_error)) {
105  inliers.push_back(not_sampled_data_point);
106  }
107  }
108 
109  // Check if we have enough inliers to consider this a good model.
110  if (inliers.size() >= options_.minimum_num_inliers) {
111 
112  // Test how good this model is.
113  ModelType better_model = problem.FitModel(inliers);
114 
115  // Is this the best model yet?
116  double this_error = better_model.Error();
117  if (this_error < best_error) {
118  best_error = this_error;
119  problem.SetModel(better_model);
120  problem.SetInliers(inliers);
121  problem.SetSolutionFound(true);
122  }
123  }
124  }
125 
126  // See if RANSAC found a solution.
127  if (!problem.SolutionFound()) {
128  VLOG(1) << "RANSAC failed to find a solution in " << options_.iterations
129  << " iterations.";
130  return false;
131  }
132 
133  return true;
134 }
135 
136 } //\namespace bsfm
137 
138 #endif
virtual void SetSolutionFound(bool solution_found)
void SetOptions(const RansacOptions &options)
Definition: ransac.h:78
virtual std::vector< DataType > RemainingData(unsigned int num_sampled_previously) const =0
virtual void SetInliers(const std::vector< DataType > &inliers)
bool Run(RansacProblem< DataType, ModelType > &problem) const
Definition: ransac.h:83
virtual void SetModel(const ModelType &model)
virtual std::vector< DataType > SampleData(unsigned int num_samples)=0
virtual ModelType FitModel(const std::vector< DataType > &input_data) const =0
Definition: camera.cpp:50
virtual bool SolutionFound()
RansacOptions options_
Definition: ransac.h:72