ViSP  2.10.0
vpRansac.h
1 /****************************************************************************
2  *
3  * $Id: vpRansac.h 4574 2014-01-09 08:48:51Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Ransac robust algorithm.
36  *
37  * Authors:
38  * Eric Marchand
39  *
40  *****************************************************************************/
41 
42 
49 #ifndef vpRANSAC_HH
50 #define vpRANSAC_HH
51 
52 
53 
54 #include <visp/vpNoise.h> // random number generation
55 #include <visp/vpDebug.h> // debug and trace
56 #include <visp/vpColVector.h>
57 #include <visp/vpMath.h>
58 #include <ctime>
78 template <class vpTransformation>
79 class vpRansac
80 {
81 public:
82  static bool ransac(unsigned int npts,
83  vpColVector &x,
84  unsigned int s, double t,
85  vpColVector &model,
86  vpColVector &inliers,
87  int consensus = 1000,
88  double areaThreshold = 0.0,
89  const int maxNbumbersOfTrials = 10000);
90 };
91 
122 template <class vpTransformation>
123 bool
125  unsigned int s, double t,
126  vpColVector &M,
127  vpColVector &inliers,
128  int consensus,
129  double /* areaThreshold */,
130  const int maxNbumbersOfTrials)
131 {
132  /* bool isplanar; */
133  /* if (s == 4) isplanar = true; */
134  /* else isplanar = false; */
135 
136  double eps = 1e-6 ;
137  double p = 0.99; // Desired probability of choosing at least one sample
138  // free from outliers
139 
140  int maxTrials = maxNbumbersOfTrials; // Maximum number of trials before we give up.
141  int maxDataTrials = 1000; // Max number of attempts to select a non-degenerate
142  // data set.
143 
144  if (s<4)
145  s = 4;
146 
147  // Sentinel value allowing detection of solution failure.
148  bool solutionFind = false ;
149  vpColVector bestM ;
150  int trialcount = 0;
151  int bestscore = -1;
152  double N = 1; // Dummy initialisation for number of trials.
153 
154  vpUniRand random((const long)time(NULL)) ;
155  vpColVector bestinliers ;
156  unsigned int *ind = new unsigned int [s] ;
157  int numiter = 0;
158  int ninliers = 0;
159  double residual = 0.0;
160  while(( N > trialcount) && (consensus > bestscore))
161  {
162  // Select at random s datapoints to form a trial model, M.
163  // In selecting these points we have to check that they are not in
164  // a degenerate configuration.
165 
166  bool degenerate = true;
167  int count = 1;
168 
169  while ( degenerate == true)
170  {
171  // Generate s random indicies in the range 1..npts
172  for (unsigned int i=0 ; i < s ; i++)
173  ind[i] = (unsigned int)ceil(random()*npts) -1;
174 
175  // Test that these points are not a degenerate configuration.
176  degenerate = vpTransformation::degenerateConfiguration(x,ind) ;
177  // degenerate = feval(degenfn, x(:,ind));
178 
179  // Safeguard against being stuck in this loop forever
180  count = count + 1;
181 
182  if (count > maxDataTrials) {
183  delete [] ind;
184  vpERROR_TRACE("Unable to select a nondegenerate data set");
185  throw(vpException(vpException::fatalError, "Unable to select a nondegenerate data set"));
186  //return false; //Useless after a throw() function
187  }
188  }
189  // Fit model to this random selection of data points.
190  vpTransformation::computeTransformation(x,ind, M);
191 
192  vpColVector d ;
193  // Evaluate distances between points and model.
194  vpTransformation::computeResidual(x, M, d) ;
195 
196  // Find the indices of points that are inliers to this model.
197  residual = 0.0;
198  ninliers =0 ;
199  for (unsigned int i=0 ; i < npts ; i++)
200  {
201  double resid = fabs(d[i]);
202  if (resid < t)
203  {
204  inliers[i] = 1 ;
205  ninliers++ ;
206  residual += fabs(d[i]);
207  }
208  else inliers[i] = 0;
209  }
210 
211  if (ninliers > bestscore) // Largest set of inliers so far...
212  {
213  bestscore = ninliers; // Record data for this model
214  bestinliers = inliers;
215  bestM = M;
216  solutionFind = true ;
217 
218  // Update estimate of N, the number of trials to ensure we pick,
219  // with probability p, a data set with no outliers.
220 
221  double fracinliers = (double)ninliers / (double)npts;
222 
223  double pNoOutliers = 1 - pow(fracinliers,static_cast<int>(s));
224 
225  pNoOutliers = vpMath::maximum(eps, pNoOutliers); // Avoid division by -Inf
226  pNoOutliers = vpMath::minimum(1-eps, pNoOutliers);// Avoid division by 0.
227  N = (log(1-p)/log(pNoOutliers));
228  }
229 
230  trialcount = trialcount+1;
231  // Safeguard against being stuck in this loop forever
232  if (trialcount > maxTrials)
233  {
234  vpTRACE("ransac reached the maximum number of %d trials", maxTrials);
235  break ;
236  }
237  numiter++;
238  }
239 
240  if (solutionFind==true) // We got a solution
241  {
242  M = bestM;
243  inliers = bestinliers;
244  }
245  else
246  {
247  vpTRACE("ransac was unable to find a useful solution");
248  M = 0;
249  }
250 
251  if(ninliers > 0)
252  residual /= ninliers;
253  delete [] ind;
254 
255  return true;
256 }
257 
258 
259 #endif
#define vpERROR_TRACE
Definition: vpDebug.h:395
#define vpTRACE
Definition: vpDebug.h:418
error that can be emited by ViSP classes.
Definition: vpException.h:76
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
static Type minimum(const Type &a, const Type &b)
Definition: vpMath.h:148
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
static bool ransac(unsigned int npts, vpColVector &x, unsigned int s, double t, vpColVector &model, vpColVector &inliers, int consensus=1000, double areaThreshold=0.0, const int maxNbumbersOfTrials=10000)
RANSAC - Robustly fits a model to data with the RANSAC algorithm.
Definition: vpRansac.h:124
This class is a generic implementation of the Ransac algorithm. It cannot be used alone...
Definition: vpRansac.h:79
Class for generating random numbers with uniform probability density.
Definition: vpNoise.h:68