ViSP  2.6.2
vpRansac.h
1 /****************************************************************************
2  *
3  * $Id: vpRansac.h 3530 2012-01-03 10:52:12Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2012 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>
92 template <class vpTransformation>
93 class vpRansac
94 {
95 public:
96  static bool ransac(unsigned int npts,
97  vpColVector &x,
98  unsigned int s, double t,
99  vpColVector &model,
100  vpColVector &inliers,
101  int consensus = 1000,
102  double areaThreshold = 0.0,
103  const int maxNbumbersOfTrials = 10000);
104 };
105 
136 template <class vpTransformation>
137 bool
139  unsigned int s, double t,
140  vpColVector &M,
141  vpColVector &inliers,
142  int consensus,
143  double /* areaThreshold */,
144  const int maxNbumbersOfTrials
145  )
146 {
147 
148 
149 /* bool isplanar; */
150 /* if (s == 4) isplanar = true; */
151 /* else isplanar = false; */
152 
153  double eps = 1e-6 ;
154  double p = 0.99; // Desired probability of choosing at least one sample
155  // free from outliers
156 
157  int maxTrials = maxNbumbersOfTrials; // Maximum number of trials before we give up.
158  int maxDataTrials = 1000; // Max number of attempts to select a non-degenerate
159  // data set.
160 
161  // Sentinel value allowing detection of solution failure.
162  bool solutionFind = false ;
163  vpColVector bestM ;
164  int trialcount = 0;
165  int bestscore = -1;
166  double N = 1; // Dummy initialisation for number of trials.
167 
168  vpUniRand random((const long)time(NULL)) ;
169  vpColVector bestinliers ;
170  unsigned int *ind = new unsigned int [s] ;
171  int numiter = 0;
172  int ninliers = 0;
173  double residual = 0.0;
174  while(( N > trialcount) && (consensus > bestscore))
175  {
176  // Select at random s datapoints to form a trial model, M.
177  // In selecting these points we have to check that they are not in
178  // a degenerate configuration.
179 
180  bool degenerate = true;
181  int count = 1;
182 
183  while ( degenerate == true)
184  {
185  // Generate s random indicies in the range 1..npts
186  for (unsigned int i=0 ; i < s ; i++)
187  ind[i] = (unsigned int)ceil(random()*npts) -1;
188 
189  // Test that these points are not a degenerate configuration.
190  degenerate = vpTransformation::degenerateConfiguration(x,ind) ;
191  // degenerate = feval(degenfn, x(:,ind));
192 
193  // Safeguard against being stuck in this loop forever
194  count = count + 1;
195 
196  if (count > maxDataTrials) {
197  delete [] ind;
198  vpERROR_TRACE("Unable to select a nondegenerate data set");
199  throw(vpException(vpException::fatalError, "Unable to select a nondegenerate data set"));
200  //return false; //Useless after a throw() function
201  }
202  }
203  // Fit model to this random selection of data points.
204  vpTransformation::computeTransformation(x,ind, M);
205 
206  vpColVector d ;
207  // Evaluate distances between points and model.
208  vpTransformation::computeResidual(x, M, d) ;
209 
210  // Find the indices of points that are inliers to this model.
211  residual = 0.0;
212  ninliers =0 ;
213  for (unsigned int i=0 ; i < npts ; i++)
214  {
215  double resid = fabs(d[i]);
216  if (resid < t)
217  {
218  inliers[i] = 1 ;
219  ninliers++ ;
220  residual += fabs(d[i]);
221  }
222  else inliers[i] = 0;
223  }
224 
225  if (ninliers > bestscore) // Largest set of inliers so far...
226  {
227  bestscore = ninliers; // Record data for this model
228  bestinliers = inliers;
229  bestM = M;
230  solutionFind = true ;
231 
232  // Update estimate of N, the number of trials to ensure we pick,
233  // with probability p, a data set with no outliers.
234 
235  double fracinliers = (double)ninliers / (double)npts;
236 
237  double pNoOutliers = 1 - pow(fracinliers,static_cast<int>(s));
238 
239  pNoOutliers = vpMath::maximum(eps, pNoOutliers); // Avoid division by -Inf
240  pNoOutliers = vpMath::minimum(1-eps, pNoOutliers);// Avoid division by 0.
241  N = (log(1-p)/log(pNoOutliers));
242  }
243 
244  trialcount = trialcount+1;
245  // Safeguard against being stuck in this loop forever
246  if (trialcount > maxTrials)
247  {
248  vpTRACE("ransac reached the maximum number of %d trials", maxTrials);
249  break ;
250  }
251  numiter++;
252  }
253 
254  if (solutionFind==true) // We got a solution
255  {
256  M = bestM;
257  inliers = bestinliers;
258  }
259  else
260  {
261  vpTRACE("ransac was unable to find a useful solution");
262  M = 0;
263  }
264 
265  if(ninliers > 0)
266  residual /= ninliers;
267  delete [] ind;
268 
269  return true;
270 }
271 
272 
273 #endif
#define vpERROR_TRACE
Definition: vpDebug.h:379
#define vpTRACE
Definition: vpDebug.h:401
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:138
This class is a generic implementation of the Ransac algorithm. It cannot be used alone...
Definition: vpRansac.h:93
Class for generating random numbers with uniform probability density.
Definition: vpNoise.h:72