Hugin trunk 0.1
Loading...
Searching...
No Matches
ransac.h
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
28#ifndef _RANSAC_H_
29#define _RANSAC_H_
30
31#include <set>
32#include <vector>
33#include <stdlib.h>
34#include <cstring>
35#include <math.h>
36#include <ctime>
37
38#include "hugin_config.h"
39#include <random>
40#include <functional>
41
42//#include "ParameterEsitmator.h"
43
44//#define DEBUG_RANSAC
45
75class Ransac {
76
77public:
94 template<class Estimator, class S, class T>
95 static std::vector<const T*> compute(S & parameters,
96 std::vector<int> & inliers,
98 const std::vector<T> &data,
101
102
125 template<class Estimator, class S, class T>
126 static std::vector<const T*> compute(S &parameters,
127 const Estimator & paramEstimator ,
128 const std::vector<T> &data);
129
130private:
131
135 static unsigned int choose(unsigned int n, unsigned int m);
136
137 template<class Estimator, class T>
138 static void computeAllChoices(const Estimator & paramEstimator,
139 const std::vector<T> &data,
140 int numForEstimate,
141 short *bestVotes, short *curVotes,
142 int &numVotesForBest, int startIndex,
143 int n, int k, int arrIndex, int *arr);
144
145
146 template<class Estimator, class T, class S>
147 static void estimate(const Estimator & paramEstimator, const std::vector<T> &data,
148 int numForEstimate,
149 short *bestVotes, short *curVotes,
150 int &numVotesForBest, int *arr);
151
153 {
154 private:
156 public:
159
160 bool operator()(const int *arr1, const int *arr2) const
161 {
162 for(int i=0; i<m_length; i++)
163 if(arr1[i] < arr2[i])
164 return true;
165 return false;
166 }
167 };
168
169};
170
171
172/*******************************RanSac Implementation*************************/
173
174template<class Estimator, class S, class T>
175std::vector<const T *> Ransac::compute(S &parameters,
176 std::vector<int> & inliers,
178 const std::vector<T> &data,
181{
182 unsigned int numDataObjects = (int) data.size();
183 unsigned int numForEstimate = paramEstimator.numForEstimate();
184 //there are less data objects than the minimum required for an exact fit, or
185 //all the data is outliers?
187 return std::vector<const T*>();
188
189 std::vector<const T *> exactEstimateData;
190 std::vector<const T *> leastSquaresEstimateData;
193 short *bestVotes = new short[numDataObjects]; //one if data[i] agrees with the best model, otherwise zero
194 short *curVotes = new short[numDataObjects]; //one if data[i] agrees with the current model, otherwise zero
195 short *notChosen = new short[numDataObjects]; //not zero if data[i] is NOT chosen for computing the exact fit, otherwise zero
197 std::set<int *, SubSetIndexComparator > chosenSubSets(subSetIndexComparator);
198 int *curSubSetIndexes;
199 // double outlierPercentage = maximalOutlierPercentage;
201 double denominator = log(1- pow((double)(1.0-maximalOutlierPercentage), (double)(numForEstimate)));
202 int allTries = choose(numDataObjects,numForEstimate);
203
204 //parameters.clear();
205
206
207 numVotesForBest = 0; //initalize with 0 so that the first computation which gives any type of fit will be set to best
208
209 // intialize random generator
211 std::mt19937 rng(static_cast<unsigned int>(std::time(0)));
212 std::uniform_int_distribution<> distribIndex(0, maxIndex);
213 auto randIndex=std::bind(distribIndex, rng);
214
215// srand((unsigned)time(NULL)); //seed random number generator
217
218 //there are cases when the probablistic number of tries is greater than all possible sub-sets
220
221 for(i=0; i<numTries; i++) {
222 //randomly select data for exact model fit ('numForEstimate' objects).
223 memset(notChosen,'1',numDataObjects*sizeof(short));
224 curSubSetIndexes = new int[numForEstimate];
225
226 exactEstimateData.clear();
227
229 for(l=0; l<(int)numForEstimate; l++) {
230 //selectedIndex is in [0,maxIndex]
231 unsigned int selectedIndex = randIndex();
232// unsigned int selectedIndex = (unsigned int)(((float)rand()/(float)RAND_MAX)*maxIndex + 0.5);
233 for(j=-1,k=0; k<(int)numDataObjects && j<(int)selectedIndex; k++) {
234 if(notChosen[k])
235 j++;
236 }
237 k--;
238 exactEstimateData.push_back(&(data[k]));
239 notChosen[k] = 0;
240 maxIndex--;
241 }
242 //get the indexes of the chosen objects so we can check that this sub-set hasn't been
243 //chosen already
244 for(l=0, j=0; j<(int)numDataObjects; j++) {
245 if(!notChosen[j]) {
246 curSubSetIndexes[l] = j+1;
247 l++;
248 }
249 }
250
251 //check that the sub set just chosen is unique
252 std::pair< std::set<int *, SubSetIndexComparator >::iterator, bool > res = chosenSubSets.insert(curSubSetIndexes);
253
254 if(res.second == true) { //first time we chose this sub set
255 //use the selected data for an exact model parameter fit
257 //selected data is a singular configuration (e.g. three colinear points for
258 //a circle fit)
259 continue;
260 //see how many agree on this estimate
261 numVotesForCur = 0;
262 memset(curVotes,'\0',numDataObjects*sizeof(short));
263 for(j=0; j<(int)numDataObjects; j++) {
264 if(paramEstimator.agree(exactEstimateParameters, data[j])) {
265 curVotes[j] = 1;
267 }
268 }
269 // debug output
270 #ifdef DEBUG_RANSAC
271 std::cerr << "RANSAC iter " << i << ": inliers: " << numVotesForCur << " parameters:";
272 for (int jj=0; jj < exactEstimateParameters.size(); jj++)
273 std::cerr << " " << exactEstimateParameters[jj];
274 std::cerr << std::endl;
275 #endif
276
279 memcpy(bestVotes,curVotes, numDataObjects*sizeof(short));
281 }
282 /*
283 //update the estimate of outliers and the number of iterations we need
284 outlierPercentage = 1 - (double)numVotesForCur/(double)numDataObjects;
285 if(outlierPercentage < maximalOutlierPercentage) {
286 maximalOutlierPercentage = outlierPercentage;
287 denominator = log(1- pow((double)(1.0-maximalOutlierPercentage), (double)(numForEstimate)));
288 numTries = (int)(numerator/denominator + 0.5);
289 //there are cases when the probablistic number of tries is greater than all possible sub-sets
290 numTries = numTries<allTries ? numTries : allTries;
291 }
292 */
293 }
294 else { //this sub set already appeared, don't count this iteration
295 delete [] curSubSetIndexes;
296 i--;
297 }
298 }
299
300 //release the memory
301 std::set<int *, SubSetIndexComparator >::iterator it = chosenSubSets.begin();
302 std::set<int *, SubSetIndexComparator >::iterator chosenSubSetsEnd = chosenSubSets.end();
303 while(it!=chosenSubSetsEnd) {
304 delete [] (*it);
305 it++;
306 }
307 chosenSubSets.clear();
308
309 //compute the least squares estimate using the largest sub set
310 if(numVotesForBest > 0) {
311 for(j=0; j<(int)numDataObjects; j++) {
312 if(bestVotes[j]) {
313 leastSquaresEstimateData.push_back(&(data[j]));
314 inliers.push_back(j);
315 }
316 }
318 }
319 delete [] bestVotes;
320 delete [] curVotes;
321 delete [] notChosen;
322
324}
325/*****************************************************************************/
326template<class Estimator, class S, class T>
327std::vector<const T*> Ransac::compute(S &parameters,
329 const std::vector<T> &data)
330{
331 unsigned int numForEstimate = paramEstimator.numForEstimate();
332 std::vector<T *> leastSquaresEstimateData;
333 int numDataObjects = data.size();
334 int numVotesForBest = 0;
335 int *arr = new int[numForEstimate];
336 short *curVotes = new short[numDataObjects]; //one if data[i] agrees with the current model, otherwise zero
337 short *bestVotes = new short[numDataObjects]; //one if data[i] agrees with the best model, otherwise zero
338
339 //parameters.clear();
340
341 //there are less data objects than the minimum required for an exact fit
342 if(numDataObjects < numForEstimate)
343 return 0;
344
345 computeAllChoices(paramEstimator,data,numForEstimate,
346 bestVotes, curVotes, numVotesForBest, 0, data.size(), numForEstimate, 0, arr);
347
348 //compute the least squares estimate using the largest sub set
349 if(numVotesForBest > 0) {
350 for(int j=0; j<numDataObjects; j++) {
351 if(bestVotes[j])
352 leastSquaresEstimateData.push_back(&(data[j]));
353 }
355 }
356
357 delete [] arr;
358 delete [] bestVotes;
359 delete [] curVotes;
360
362}
363/*****************************************************************************/
364template<class Estimator, class T>
365void Ransac::computeAllChoices(const Estimator &paramEstimator, const std::vector<T> &data,
366 int numForEstimate,short *bestVotes, short *curVotes,
367 int &numVotesForBest, int startIndex, int n, int k,
368 int arrIndex, int *arr)
369{
370 //we have a new choice of indexes
371 if(k==0) {
372 estimate(paramEstimator, data, numForEstimate, bestVotes, curVotes, numVotesForBest, arr);
373 return;
374 }
375
376 //continue to recursivly generate the choice of indexes
377 int endIndex = n-k;
378 for(int i=startIndex; i<=endIndex; i++) {
379 arr[arrIndex] = i;
381 i+1, n, k-1, arrIndex+1, arr);
382 }
383
384}
385/*****************************************************************************/
386template<class Estimator, class T, class S>
387void Ransac::estimate(const Estimator & paramEstimator, const std::vector<T> &data,
388 int numForEstimate, short *bestVotes, short *curVotes,
389 int &numVotesForBest, int *arr)
390{
391 std::vector<T *> exactEstimateData;
392 std::vector<S> exactEstimateParameters;
393 int numDataObjects;
394 int numVotesForCur;//initalize with -1 so that the first computation will be set to best
395 int j;
396
397 numDataObjects = data.size();
398 memset(curVotes,'\0',numDataObjects*sizeof(short));
400
401 for(j=0; j<numForEstimate; j++)
402 exactEstimateData.push_back(&(data[arr[j]]));
404 //singular data configuration
405 if(exactEstimateParameters.empty())
406 return;
407
408 for(j=0; j<numDataObjects; j++) {
409 if(paramEstimator.agree(exactEstimateParameters, data[j])) {
410 curVotes[j] = 1;
412 }
413 }
416 memcpy(bestVotes,curVotes, numDataObjects*sizeof(short));
417 }
418}
419/*****************************************************************************/
420inline unsigned int Ransac::choose(unsigned int n, unsigned int m)
421{
423 if((n-m) > m) {
424 numeratorStart = n-m+1;
425 denominatorEnd = m;
426 }
427 else {
428 numeratorStart = m+1;
429 denominatorEnd = n-m;
430 }
431
432 unsigned int i;
433 for(i=numeratorStart, numerator=1; i<=n; i++)
434 numerator*=i;
435 for(i=1, denominator=1; i<=denominatorEnd; i++)
436 denominator*=i;
437 return numerator/denominator;
438
439}
440
441
442#endif //_RANSAC_H_
bool operator()(const int *arr1, const int *arr2) const
Definition ransac.h:160
SubSetIndexComparator(int arrayLength)
Definition ransac.h:157
This class implements the Random Sample Consensus (RanSac) framework, a framework for robust paramete...
Definition ransac.h:75
static void estimate(const Estimator &paramEstimator, const std::vector< T > &data, int numForEstimate, short *bestVotes, short *curVotes, int &numVotesForBest, int *arr)
Definition ransac.h:387
static unsigned int choose(unsigned int n, unsigned int m)
Compute n choose m [ n!/(m!*(n-m)!)].
Definition ransac.h:420
static void computeAllChoices(const Estimator &paramEstimator, const std::vector< T > &data, int numForEstimate, short *bestVotes, short *curVotes, int &numVotesForBest, int startIndex, int n, int k, int arrIndex, int *arr)
Definition ransac.h:365
static std::vector< const T * > compute(S &parameters, std::vector< int > &inliers, const Estimator &paramEstimator, const std::vector< T > &data, double desiredProbabilityForNoOutliers, double maximalOutlierPercentage)
Estimate the model parameters using the RanSac framework.
Definition ransac.h:175
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41