00001 #ifndef RANSAC_TEMPLATE_HPP
00002 #define RANSAC_TEMPLATE_HPP
00003
00004 #include <float.h>
00005 #include <vector>
00006 #include <cmath>
00007
00008 #include "kernel/jafarException.hpp"
00009
00011 #include "jmath/randomIntTmplt.hpp"
00012
00013 #define PROBABILITY_GOOD_MODEL 0.90
00014 #define TOO_SMALL_MODEL_CHANGE 0.10
00015
00016 namespace jafar {
00018 namespace model3d {
00059 template <class ModelType>
00060 class RANSAC
00061 {
00062 public:
00063
00072 RANSAC();
00073
00077 RANSAC(unsigned int sample_length);
00078
00079 virtual ~RANSAC();
00080
00081
00088 void initialize(unsigned int sample_length);
00089
00117 int Algorithm(double inlying_data_fraction,
00118 ModelType& model,
00119 std::vector<bool>& inliers,
00120 unsigned int& nModelInlierNumber,
00121 double& dbModelScore);
00122
00129 virtual void fitSampleModel(std::vector<unsigned int>&sample_data_indices,
00130 ModelType& model)=0;
00131
00162 virtual
00163 bool evaluateModel(const ModelType& model,
00164 std::vector<bool>& inlier,
00165 unsigned int& unInlierNumber,
00166 double& evaluate_score);
00167
00173 virtual
00174 double distance(const ModelType& model, unsigned int unIndex)=0;
00175
00176
00186 virtual bool isDegenerate(std::vector<unsigned int>& sample_data_indices)
00187 { return false; }
00188
00195 virtual
00196 bool generateSample(std::vector<unsigned int>& sample_data_indices);
00197
00205 bool generateRandomSample(std::vector<unsigned int>& sampletable);
00206
00207
00208
00209
00216 inline void setMaxIterationNumber(unsigned int unMaxIterationNumber)
00217 { m_unMaxIterationNumber = unMaxIterationNumber; }
00218
00233 void fixIterationNumber(unsigned int uiIterationNumber)
00234 { m_unFixedIterationNumber = uiIterationNumber; }
00235
00237 void setInlierNumberThreshold(unsigned int unInlierNumberThreshold)
00238 {m_unInlierNumberThreshold = unInlierNumberThreshold;}
00239
00241 unsigned int getInlierNumberThreshold()
00242 {return m_unInlierNumberThreshold;}
00243
00247 void setInlierDistanceThreshold (double dbInlierDistanceThreshold)
00248 { m_dbInlierDistanceThreshold = dbInlierDistanceThreshold;}
00249
00253 double getInlierDistanceThreshold ()
00254 { return m_dbInlierDistanceThreshold;}
00255
00257 void setModelErrorThreshold(double dbModelErrorThreshold)
00258 { m_dbModelErrorThreshold = dbModelErrorThreshold;}
00259
00261 double getModelErrorThreshold()
00262 { return m_dbModelErrorThreshold;}
00263
00264 protected:
00266 unsigned int m_unDataLength;
00267
00271 unsigned int m_unSampleLength;
00272
00273 jafar::jmath::RandomUIntVect* m_pRandomUIntVect;
00274
00280 unsigned int m_unMaxIterationNumber;
00281
00289 unsigned int m_unFixedIterationNumber;
00290
00298 double m_dbProbabilityOfGoodModel;
00299
00307 double m_dbInlierDistanceThreshold;
00308
00315 unsigned int m_unInlierNumberThreshold;
00316
00320 double m_dbModelErrorThreshold;
00321
00322
00323 private:
00324 static int ComputeIterationNumber(double inlying_data_fraction,
00325 double desired_prob_good,
00326 unsigned int sample_length);
00327 };
00328
00329
00330
00331
00332
00333
00334
00335 template <class ModelType>
00336 RANSAC<ModelType>::RANSAC()
00337 {
00338 m_dbProbabilityOfGoodModel = PROBABILITY_GOOD_MODEL;
00339 m_unSampleLength=m_unDataLength=m_unMaxIterationNumber=0;
00340 m_unFixedIterationNumber = 0;
00341 m_pRandomUIntVect = NULL;
00342
00343 srand(time(NULL));
00344 }
00345
00346 template <class ModelType>
00347 RANSAC<ModelType>::RANSAC(unsigned int sample_length)
00348 {
00349 m_dbProbabilityOfGoodModel = PROBABILITY_GOOD_MODEL;
00350 initialize(sample_length);
00351 m_unDataLength = 0;
00352 m_pRandomUIntVect = NULL;
00353
00354 srand(time(NULL));
00355 }
00356
00357 template <class ModelType>
00358 void RANSAC<ModelType>::initialize(unsigned int sample_length)
00359 {
00360 m_unSampleLength = sample_length;
00361 m_unMaxIterationNumber = 0;
00362 m_unFixedIterationNumber = 0;
00363
00364 srand(time(NULL));
00365
00366
00367 }
00368
00369 template <class ModelType>
00370 RANSAC<ModelType>::~RANSAC()
00371 {
00372 if (m_pRandomUIntVect != NULL) {
00373 delete m_pRandomUIntVect;
00374 m_pRandomUIntVect = NULL;
00375 }
00376 }
00377
00378 template <class ModelType>
00379 int RANSAC<ModelType>::Algorithm(double inlying_data_fraction,
00380 ModelType& model,
00381 std::vector<bool>& inliers,
00382 unsigned int& nModelInlierNumber,
00383 double& dbModelScore)
00384 {
00385 JFR_PRECOND(m_unDataLength!=0,
00386 "m_unDataLength should be set in derived class first.. use initialize");
00387
00388 if (inlying_data_fraction>1.0 || inlying_data_fraction<0.0){
00389 JFR_RUN_TIME("invalid value : inlying_data_fraction must be between 0 and 1 ");
00390 }
00391
00392 if (m_unDataLength < m_unSampleLength) {
00393 JFR_RUN_TIME("Algorithm: m_unDataLength < m_unSampleLength !");
00394 }
00395
00396
00397 ModelType curModel;
00398
00399 double dbCurScore;
00400
00401 unsigned int nCurInlierNumber;
00402
00403 std::vector<bool> curInliers(m_unDataLength, false);
00404
00405
00406 std::vector<unsigned int> sample_data_indices;
00407
00408
00409 bool bGoodModel;
00410
00411 bool bGotModel;
00412
00413
00414 bool theBestFlag;
00415
00416 int iteration_number;
00417 int nIterationIndex;
00418
00419
00420 nModelInlierNumber = 0;
00421 dbModelScore = DBL_MAX;
00422 bGotModel = false;
00423
00424
00425
00426 if (m_unFixedIterationNumber>0) {
00427
00428
00429 iteration_number = m_unFixedIterationNumber;
00430 }
00431 else {
00432
00433 iteration_number = ComputeIterationNumber(inlying_data_fraction,
00434 m_dbProbabilityOfGoodModel,
00435 m_unSampleLength);
00436 }
00437
00438
00439
00440 if (m_unMaxIterationNumber != 0 &&
00441 (unsigned)iteration_number > m_unMaxIterationNumber) {
00442 iteration_number = m_unMaxIterationNumber;
00443 }
00444
00445
00446 for (nIterationIndex = 0; nIterationIndex < iteration_number;
00447 nIterationIndex++) {
00448
00449
00450 if (! generateSample(sample_data_indices)) {
00451
00452
00453 continue;
00454 }
00455
00456
00457 if ( isDegenerate(sample_data_indices)){
00458
00459
00460 continue;
00461 }
00462
00463
00464 fitSampleModel(sample_data_indices, curModel);
00465 if (bGotModel)
00466 nCurInlierNumber = nModelInlierNumber;
00467
00468 dbCurScore = DBL_MAX;
00469 bGoodModel = evaluateModel(curModel,
00470 curInliers,
00471 nCurInlierNumber,
00472 dbCurScore);
00473
00474
00475
00476
00477
00478
00479
00480 theBestFlag = false;
00481 if (bGoodModel) {
00482 if (!bGotModel) {
00483 bGotModel = true;
00484 theBestFlag = true;
00485 }
00486 else {
00487 if (nCurInlierNumber > nModelInlierNumber ||
00488 (nCurInlierNumber == nModelInlierNumber &&
00489 dbCurScore < dbModelScore))
00490 theBestFlag = true;
00491 }
00492
00493 if (theBestFlag) {
00494
00495 nModelInlierNumber = nCurInlierNumber;
00496 dbModelScore = dbCurScore;
00497 inliers = curInliers;
00498 model = curModel;
00499 }
00500 }
00501 }
00502
00503 if (!bGotModel) {
00504
00505
00506 nIterationIndex = -2;
00507 }
00508
00509 return nIterationIndex;
00510 }
00511
00512
00513 template <class ModelType>
00514 bool RANSAC<ModelType>::
00515 evaluateModel(const ModelType& model,
00516 std::vector<bool>& inlier,
00517 unsigned int& unInlierNumber,
00518 double& dbScore)
00519 {
00520 bool bGoodModel = false;
00521 inlier.clear();
00522 inlier.resize(m_unDataLength);
00523
00524 unsigned int nCurInlierNumber = 0;
00525 dbScore = 0.0;
00526 double dbDistance;
00527
00528 for (unsigned int i=0; i<m_unDataLength; i++){
00529 dbDistance = distance(model,i);
00530 inlier[i] = (dbDistance < m_dbInlierDistanceThreshold);
00531 if (inlier[i]) {
00532 nCurInlierNumber++;
00533 dbScore += dbDistance;
00534 }
00535 }
00536 if (nCurInlierNumber!=0) {
00537 dbScore /= nCurInlierNumber;
00538 }
00539 else {
00540 dbScore=DBL_MAX;
00541 bGoodModel=false;
00542 }
00543 unInlierNumber = nCurInlierNumber;
00544
00545
00546
00547
00548 bGoodModel = (unInlierNumber > m_unInlierNumberThreshold)
00549 && (dbScore < m_dbModelErrorThreshold);
00550
00551 return bGoodModel;
00552 }
00553
00554
00555 template <class ModelType>
00556 bool RANSAC<ModelType>::
00557 generateSample(std::vector<unsigned int>& sample_data_indices)
00558 {
00559 return generateRandomSample(sample_data_indices);
00560 }
00561
00562 template <class ModelType>
00563 bool RANSAC<ModelType>::
00564 generateRandomSample(std::vector<unsigned int>& sample_data_indices)
00565 {
00566 if (m_unSampleLength==0){
00567
00568 return false;
00569 }
00570 if (m_unSampleLength>=m_unDataLength){
00571
00572 return false;
00573 }
00574 JFR_PRECOND(m_pRandomUIntVect!=NULL,
00575 "NULL pointer:must use new to create it \
00576 when knowing the data size ");
00577
00578 sample_data_indices = m_pRandomUIntVect->getDifferent();
00579
00580 return true;
00581 }
00582
00583
00584 template <class ModelType>
00585 int RANSAC<ModelType>::
00586 ComputeIterationNumber(double inlying_data_fraction,
00587 double desired_prob_good,
00588 unsigned int sample_length)
00589 {
00590
00591
00592
00593 if (inlying_data_fraction == 1.0)
00594 return 1;
00595
00596
00597 return int(log (1.0 - desired_prob_good) /
00598 log (1.0 - pow (inlying_data_fraction,
00599 (double) sample_length)));
00600 }
00601
00602
00603 }
00604 }
00605
00606 #endif // RANSAC_TEMPLATE_HPP
00607
00608