Main MRPT website > C++ reference for MRPT 1.9.9
ransac.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "base-precomp.h" // Precompiled headers
11 
12 #include <mrpt/math/ransac.h>
13 #include <mrpt/random.h>
14 
15 using namespace mrpt;
16 using namespace mrpt::utils;
17 using namespace mrpt::random;
18 using namespace mrpt::math;
19 using namespace std;
20 
21 /*---------------------------------------------------------------
22  ransac generic implementation
23  ---------------------------------------------------------------*/
24 template <typename NUMTYPE>
27  const TRansacFitFunctor& fit_func, const TRansacDistanceFunctor& dist_func,
28  const TRansacDegenerateFunctor& degen_func, const double distanceThreshold,
29  const unsigned int minimumSizeSamplesToFit,
30  mrpt::vector_size_t& out_best_inliers,
31  CMatrixTemplateNumeric<NUMTYPE>& out_best_model, const double p,
32  const size_t maxIter) const
33 {
35 
36  ASSERT_(minimumSizeSamplesToFit >= 1)
37 
38  // Highly inspired on http://www.csse.uwa.edu.au/~pk/
39 
40  const size_t D = size(data, 1); // dimensionality
41  const size_t Npts = size(data, 2);
42 
43  ASSERT_(D >= 1);
44  ASSERT_(Npts > 1);
45 
46  const size_t maxDataTrials =
47  100; // Maximum number of attempts to select a non-degenerate data set.
48 
49  out_best_model.setSize(
50  0, 0); // Sentinel value allowing detection of solution failure.
51  out_best_inliers.clear();
52 
53  size_t trialcount = 0;
54  size_t bestscore = std::string::npos; // npos will mean "none"
55  size_t N = 1; // Dummy initialisation for number of trials.
56 
57  vector_size_t ind(minimumSizeSamplesToFit);
58 
59  while (N > trialcount)
60  {
61  // Select at random s datapoints to form a trial model, M.
62  // In selecting these points we have to check that they are not in
63  // a degenerate configuration.
64  bool degenerate = true;
65  size_t count = 1;
66  std::vector<CMatrixTemplateNumeric<NUMTYPE>> MODELS;
67 
68  while (degenerate)
69  {
70  // Generate s random indicies in the range 1..npts
71  ind.resize(minimumSizeSamplesToFit);
72 
73  // The +0.99... is due to the floor rounding afterwards when
74  // converting from random double samples to size_t
75  getRandomGenerator().drawUniformVector(ind, 0.0, Npts - 1 + 0.999999);
76 
77  // Test that these points are not a degenerate configuration.
78  degenerate = degen_func(data, ind);
79 
80  if (!degenerate)
81  {
82  // Fit model to this random selection of data points.
83  // Note that M may represent a set of models that fit the data
84  fit_func(data, ind, MODELS);
85 
86  // Depending on your problem it might be that the only way you
87  // can determine whether a data set is degenerate or not is to
88  // try to fit a model and see if it succeeds. If it fails we
89  // reset degenerate to true.
90  degenerate = MODELS.empty();
91  }
92 
93  // Safeguard against being stuck in this loop forever
94  if (++count > maxDataTrials)
95  {
96  MRPT_LOG_WARN("Unable to select a nondegenerate data set");
97  break;
98  }
99  }
100 
101  // Once we are out here we should have some kind of model...
102  // Evaluate distances between points and model returning the indices
103  // of elements in x that are inliers. Additionally, if M is a cell
104  // array of possible models 'distfn' will return the model that has
105  // the most inliers. After this call M will be a non-cell objec
106  // representing only one model.
107  unsigned int bestModelIdx = 1000;
108  mrpt::vector_size_t inliers;
109  if (!degenerate)
110  {
111  dist_func(
112  data, MODELS, NUMTYPE(distanceThreshold), bestModelIdx,
113  inliers);
114  ASSERT_(bestModelIdx < MODELS.size());
115  }
116 
117  // Find the number of inliers to this model.
118  const size_t ninliers = inliers.size();
119  bool update_estim_num_iters =
120  (trialcount == 0); // Always update on the first iteration,
121  // regardless of the result (even for
122  // ninliers=0)
123 
124  if (ninliers > bestscore ||
125  (bestscore == std::string::npos && ninliers != 0))
126  {
127  bestscore = ninliers; // Record data for this model
128 
129  out_best_model = MODELS[bestModelIdx];
130  out_best_inliers = inliers;
131  update_estim_num_iters = true;
132  }
133 
134  if (update_estim_num_iters)
135  {
136  // Update estimate of N, the number of trials to ensure we pick,
137  // with probability p, a data set with no outliers.
138  double fracinliers = ninliers / static_cast<double>(Npts);
139  double pNoOutliers =
140  1 -
141  pow(fracinliers, static_cast<double>(minimumSizeSamplesToFit));
142 
143  pNoOutliers = std::max(
144  std::numeric_limits<double>::epsilon(),
145  pNoOutliers); // Avoid division by -Inf
146  pNoOutliers = std::min(
147  1.0 - std::numeric_limits<double>::epsilon(),
148  pNoOutliers); // Avoid division by 0.
149  // Number of
150  N = static_cast<size_t>(log(1 - p) / log(pNoOutliers));
152  format(
153  "Iter #%u Estimated number of iters: %u pNoOutliers = %f "
154  "#inliers: %u\n",
155  (unsigned)trialcount, (unsigned)N, pNoOutliers,
156  (unsigned)ninliers));
157  }
158 
159  ++trialcount;
160 
162  format(
163  "trial %u out of %u \r", (unsigned int)trialcount,
164  (unsigned int)ceil(static_cast<double>(N))));
165 
166  // Safeguard against being stuck in this loop forever
167  if (trialcount > maxIter)
168  {
170  format(
171  "Warning: maximum number of trials (%u) reached\n",
172  (unsigned)maxIter));
173  break;
174  }
175  }
176 
177  if (size(out_best_model, 1) > 0)
178  { // We got a solution
180  format("Finished in %u iterations.\n", (unsigned)trialcount));
181  return true;
182  }
183  else
184  {
185  MRPT_LOG_WARN("Finished without any proper solution!");
186  return false;
187  }
188 
189  MRPT_END
190 }
191 
192 // Template instantiation:
195 
196 #ifdef HAVE_LONG_DOUBLE
198 #endif
A namespace of pseudo-random numbers genrators of diferent distributions.
GLuint GLuint GLsizei count
Definition: glext.h:3528
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
#define min(a, b)
std::function< bool(const CMatrixTemplateNumeric< NUMTYPE > &allData, const mrpt::vector_size_t &useIndices)> TRansacDegenerateFunctor
The type of the function passed to mrpt::math::ransac - See the documentation for that method for mor...
Definition: ransac.h:54
STL namespace.
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
#define MRPT_END
#define MRPT_LOG_WARN(_STRING)
#define MRPT_LOG_INFO(_STRING)
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
#define MRPT_LOG_DEBUG(_STRING)
std::function< void(const CMatrixTemplateNumeric< NUMTYPE > &allData, const mrpt::vector_size_t &useIndices, std::vector< CMatrixTemplateNumeric< NUMTYPE > > &fitModels)> TRansacFitFunctor
The type of the function passed to mrpt::math::ransac - See the documentation for that method for mor...
Definition: ransac.h:40
#define MRPT_START
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::function< void(const CMatrixTemplateNumeric< NUMTYPE > &allData, const std::vector< CMatrixTemplateNumeric< NUMTYPE > > &testModels, const NUMTYPE distanceThreshold, unsigned int &out_bestModelIndex, mrpt::vector_size_t &out_inlierIndices)> TRansacDistanceFunctor
The type of the function passed to mrpt::math::ransac - See the documentation for that method for mor...
Definition: ransac.h:48
#define ASSERT_(f)
std::vector< size_t > vector_size_t
Definition: types_simple.h:26
GLsizeiptr size
Definition: glext.h:3923
A generic RANSAC implementation with models as matrices.
Definition: ransac.h:31
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
void drawUniformVector(VEC &v, const double unif_min=0, const double unif_max=1)
Fills the given vector with independent, uniformly distributed samples.
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3546
GLfloat GLfloat p
Definition: glext.h:6305
std::vector< size_t > vector_size_t



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019