00001 /* 00002 Copyright (C) 2010 - 2014 Christoph Haenisch 00003 00004 Chair of Medical Engineering (mediTEC) 00005 RWTH Aachen University 00006 Pauwelsstr. 20 00007 52074 Aachen 00008 Germany 00009 00010 See license.txt for more information. 00011 00012 Version 0.1.0 (2012-03-23) 00013 */ 00014 00019 #ifndef RANSAC_HPP_1147104378 00020 #define RANSAC_HPP_1147104378 00021 00022 00023 #include <cstddef> 00024 #include <cmath> 00025 #include <limits> 00026 #include <vector> 00027 #include <set> 00028 00029 #include "Coordinate.hpp" 00030 #include "ErrorObj.hpp" 00031 00032 00033 namespace TRTK 00034 { 00035 00036 00185 template <class T, class DataType = Coordinate<T> > 00186 class Ransac 00187 { 00188 public: 00189 00190 class Model 00191 { 00192 public: 00193 virtual void compute() = 0; 00194 virtual T getDeviation(const DataType & datum) const = 0; 00195 virtual unsigned getMinimumNumberOfItems() const = 0; 00196 virtual T getRMSE() const = 0; 00197 virtual void setData(const std::vector<DataType> & data) = 0; 00198 }; 00199 00200 enum Algorithm 00201 { 00202 RANSAC, 00203 RANSAC_BIGGEST_CONSESUS_SET, 00204 RANSAC_SMALLEST_RMSE 00205 }; 00206 00207 enum Error 00208 { 00209 NO_DATA_AVAILABLE, 00210 NO_MODEL_AVAILABLE, 00211 NOT_ENOUGH_DATA_POINTS, 00212 UNKNOWN_ALGORITHM, 00213 UNKNOWN_ERROR 00214 }; 00215 00216 Ransac(); 00217 virtual ~Ransac(); 00218 00219 unsigned compute(); 00220 00221 void setAlgorithm(Algorithm algorithm = RANSAC); 00222 void setData(const std::vector<DataType> & data); 00223 void setErrorTolerance(T error_tolerance); 00224 void setMinimumSetSize(unsigned threshold); 00225 void setModel(Model & model); 00226 void setProbability(T probability); 00227 void setThreshold(unsigned threshold); 00228 void setTrials(unsigned number); 00229 00230 protected: 00231 const std::vector<DataType> * data; 00232 Model * model; 00233 00234 T error_tolerance; 00235 unsigned threshold; 00236 unsigned trials; 00237 T probability; // Probability that any selected data point of a minimal subset of data is within the error tolerance of the model. 00238 unsigned minimumSetSize; 00239 00240 unsigned (Ransac::*algorithm)(); 00241 00242 unsigned algorithmRansac(); 00243 unsigned algorithmRansacBiggestConsensusSet(); 00244 unsigned algorithmRansacSmallestRmse(); 00245 }; 00246 00247 00248 template <class T, class DataType> 00249 Ransac<T, DataType>::Ransac() : 00250 data(NULL), 00251 model(NULL), 00252 error_tolerance(0), 00253 threshold(0), 00254 trials(0), 00255 probability(0.2), 00256 minimumSetSize(0), 00257 algorithm(&Ransac::algorithmRansac) 00258 { 00259 } 00260 00261 00262 template <class T, class DataType> 00263 Ransac<T, DataType>::~Ransac() 00264 { 00265 } 00266 00267 00278 template <class T, class DataType> 00279 unsigned Ransac<T, DataType>::algorithmRansac() 00280 { 00281 using namespace std; 00282 using namespace Tools; 00283 00284 const unsigned maximum_number_of_items = data->size(); 00285 const unsigned minimum_number_of_items = model->getMinimumNumberOfItems(); 00286 00287 vector<DataType> initial_data_set(minimum_number_of_items); 00288 vector<DataType> consensus_set; 00289 vector<DataType> best_consensus_set; 00290 00291 // For each trial... 00292 00293 for (unsigned i = 0; i < trials; ++i) 00294 { 00295 // Randomly select items from the data set and use them 00296 // as an initial data set for the model fitting. 00297 00298 set<int> indices; 00299 00300 for (unsigned j = 0; j < minimum_number_of_items; ++j) 00301 { 00302 // Avoid using the same data point several times. 00303 00304 unsigned index = rand(0u, maximum_number_of_items - 1);; 00305 00306 while (indices.find(index) != indices.end()) 00307 { 00308 index = rand(0u, maximum_number_of_items - 1); 00309 } 00310 00311 indices.insert(index); 00312 00313 // Store the randomly selected data point. 00314 00315 initial_data_set[j] = (*data)[index]; 00316 } 00317 00318 // Estimate a model from the initial data set. 00319 00320 model->setData(initial_data_set); 00321 model->compute(); 00322 00323 // Construct a new consensus set and add those items from the 00324 // original data set which lie within some error tolerance. 00325 00326 consensus_set.clear(); 00327 consensus_set.reserve(maximum_number_of_items); 00328 00329 for (unsigned j = 0; j < maximum_number_of_items; ++j) 00330 { 00331 if (model->getDeviation((*data)[j]) < error_tolerance) 00332 { 00333 consensus_set.push_back((*data)[j]); 00334 } 00335 } 00336 00337 if (consensus_set.size() <= minimum_number_of_items) 00338 { 00339 // Actually, this should never happen! 00340 // But you never know... 00341 00342 consensus_set = initial_data_set; 00343 } 00344 00345 // If the size of the consensus set is greater than the given 00346 // threshold, then compute a new model from this set and exit. 00347 00348 if (consensus_set.size() > threshold) 00349 { 00350 model->setData(consensus_set); 00351 model->compute(); 00352 00353 return consensus_set.size(); 00354 } 00355 00356 // The size of the consensus set is *not* greater than the given 00357 // threshold, so randomly select a new subset. Save the old 00358 // consensus set in case no better one is found. 00359 00360 if (best_consensus_set.size() < consensus_set.size()) 00361 { 00362 best_consensus_set = consensus_set; 00363 } 00364 } 00365 00366 // Use the consensus set to compute a new model. 00367 00368 model->setData(best_consensus_set); 00369 model->compute(); 00370 00371 return best_consensus_set.size(); 00372 } 00373 00374 00382 template <class T, class DataType> 00383 unsigned Ransac<T, DataType>::algorithmRansacBiggestConsensusSet() 00384 { 00385 using namespace std; 00386 using namespace Tools; 00387 00388 const unsigned maximum_number_of_items = data->size(); 00389 const unsigned minimum_number_of_items = model->getMinimumNumberOfItems(); 00390 00391 vector<DataType> initial_data_set(minimum_number_of_items); 00392 vector<DataType> consensus_set; 00393 vector<DataType> best_consensus_set; 00394 00395 // For each trial... 00396 00397 for (unsigned i = 0; i < trials; ++i) 00398 { 00399 // Randomly select items from the data set and use them 00400 // as an initial data set for the model fitting. 00401 00402 set<int> indices; 00403 00404 for (unsigned j = 0; j < minimum_number_of_items; ++j) 00405 { 00406 // Avoid using the same data point several times. 00407 00408 unsigned index = rand(0u, maximum_number_of_items - 1);; 00409 00410 while (indices.find(index) != indices.end()) 00411 { 00412 index = rand(0u, maximum_number_of_items - 1); 00413 } 00414 00415 indices.insert(index); 00416 00417 // Store the randomly selected data point. 00418 00419 initial_data_set[j] = (*data)[index]; 00420 } 00421 00422 // Estimate a model from the initial data set. 00423 00424 model->setData(initial_data_set); 00425 model->compute(); 00426 00427 // Construct a new consensus set and add those items from the 00428 // original data set which lie within some error tolerance. 00429 00430 consensus_set.clear(); 00431 consensus_set.reserve(maximum_number_of_items); 00432 00433 for (unsigned j = 0; j < maximum_number_of_items; ++j) 00434 { 00435 if (model->getDeviation((*data)[j]) < error_tolerance) 00436 { 00437 consensus_set.push_back((*data)[j]); 00438 } 00439 } 00440 00441 if (consensus_set.size() <= minimum_number_of_items) 00442 { 00443 // Actually, this should never happen! 00444 // But you never know... 00445 00446 consensus_set = initial_data_set; 00447 } 00448 00449 // Randomly select a new subset. Save the old consensus set 00450 // in case no better one is found. 00451 00452 if (best_consensus_set.size() < consensus_set.size()) 00453 { 00454 best_consensus_set = consensus_set; 00455 } 00456 } 00457 00458 // Use the biggest consensus set to compute a new model. 00459 00460 model->setData(best_consensus_set); 00461 model->compute(); 00462 00463 return best_consensus_set.size(); 00464 } 00465 00466 00476 template <class T, class DataType> 00477 unsigned Ransac<T, DataType>::algorithmRansacSmallestRmse() 00478 { 00479 using namespace std; 00480 using namespace Tools; 00481 00482 const unsigned maximum_number_of_items = data->size(); 00483 const unsigned minimum_number_of_items = model->getMinimumNumberOfItems(); 00484 00485 vector<DataType> initial_data_set(minimum_number_of_items); 00486 vector<DataType> consensus_set; 00487 vector<DataType> best_consensus_set; 00488 00489 T rmse = numeric_limits<T>::max(); 00490 00491 // For each trial... 00492 00493 for (unsigned i = 0; i < trials; ++i) 00494 { 00495 // Randomly select items from the data set and use them 00496 // as an initial data set for the model fitting. 00497 00498 set<int> indices; 00499 00500 for (unsigned j = 0; j < minimum_number_of_items; ++j) 00501 { 00502 // Avoid using the same data point several times. 00503 00504 unsigned index = rand(0u, maximum_number_of_items - 1);; 00505 00506 while (indices.find(index) != indices.end()) 00507 { 00508 index = rand(0u, maximum_number_of_items - 1); 00509 } 00510 00511 indices.insert(index); 00512 00513 // Store the randomly selected data point. 00514 00515 initial_data_set[j] = (*data)[index]; 00516 } 00517 00518 // Estimate a model from the initial data set. 00519 00520 model->setData(initial_data_set); 00521 model->compute(); 00522 00523 // Construct a new consensus set and add those items from the 00524 // original data set which lie within some error tolerance. 00525 00526 consensus_set.clear(); 00527 consensus_set.reserve(maximum_number_of_items); 00528 00529 for (unsigned j = 0; j < maximum_number_of_items; ++j) 00530 { 00531 if (model->getDeviation((*data)[j]) < error_tolerance) 00532 { 00533 consensus_set.push_back((*data)[j]); 00534 } 00535 } 00536 00537 if (consensus_set.size() <= minimum_number_of_items) 00538 { 00539 // Actually, this should never happen! 00540 // But you never know... 00541 00542 consensus_set = initial_data_set; 00543 } 00544 00545 // Compute the model with the current consensus set. 00546 00547 model->setData(consensus_set); 00548 model->compute(); 00549 00550 T rmse_current_model = model->getRMSE(); 00551 00552 // Randomly select a new subset. Save the old consensus set 00553 // in case no better one is found. 00554 00555 if (rmse_current_model < rmse && consensus_set.size() >= minimumSetSize) 00556 { 00557 best_consensus_set = consensus_set; 00558 } 00559 } 00560 00561 // Use the biggest consensus set to compute a new model. 00562 00563 if (best_consensus_set.size() > minimum_number_of_items) 00564 { 00565 model->setData(best_consensus_set); 00566 model->compute(); 00567 00568 return best_consensus_set.size(); 00569 } 00570 else 00571 { 00572 return 0; 00573 } 00574 } 00575 00576 00602 template <class T, class DataType> 00603 unsigned Ransac<T, DataType>::compute() 00604 { 00605 // Checking some assumptions. 00606 00607 if (!model) 00608 { 00609 ErrorObj error; 00610 error.setClassName("Ransac"); 00611 error.setFunctionName("compute"); 00612 error.setErrorMessage("Regression model was not set."); 00613 error.setErrorCode(NO_MODEL_AVAILABLE); 00614 throw error; 00615 } 00616 00617 if (!data) 00618 { 00619 ErrorObj error; 00620 error.setClassName("Ransac"); 00621 error.setFunctionName("compute"); 00622 error.setErrorMessage("No data available."); 00623 error.setErrorCode(NO_DATA_AVAILABLE); 00624 throw error; 00625 } 00626 00627 if (data->size() < model->getMinimumNumberOfItems()) 00628 { 00629 ErrorObj error; 00630 error.setClassName("Ransac"); 00631 error.setFunctionName("compute"); 00632 error.setErrorMessage("Not enough data points to compute the model."); 00633 error.setErrorCode(NOT_ENOUGH_DATA_POINTS); 00634 throw error; 00635 } 00636 00637 using namespace std; 00638 00639 // Compute the maximum number of attempts (trials) to find a consensus 00640 // set if not given. See the paper of Fischler and Bolles. 00641 00642 unsigned trials_backup = trials; 00643 00644 if (trials == 0) 00645 { 00646 int n = model->getMinimumNumberOfItems(); 00647 trials = unsigned(ceil(3.0 * pow(probability, -T(n)))); 00648 } 00649 00650 // If no threshold is given, set it to 8/10 of the size of "data". 00651 00652 unsigned threshold_backup = threshold; 00653 00654 if (threshold == 0) 00655 { 00656 threshold = unsigned(ceil(0.8 * data->size())); 00657 } 00658 00659 // If the minimum set size is greater than the size of "data" shrink 00660 // it to #data - model->getMinimumNumberOfItems(). 00661 00662 unsigned minimumSetSize_backup = minimumSetSize; 00663 00664 if (minimumSetSize > data->size() && data->size() > model->getMinimumNumberOfItems()) 00665 { 00666 minimumSetSize = data->size() - model->getMinimumNumberOfItems(); 00667 } 00668 00669 // Start the computation. 00670 00671 unsigned number_of_items_used = (this->*algorithm)(); 00672 00673 // Restore the changed variables. 00674 00675 minimumSetSize = minimumSetSize_backup; 00676 threshold = threshold_backup; 00677 trials = trials_backup; 00678 00679 return number_of_items_used; 00680 } 00681 00682 00685 template <class T, class DataType> 00686 void Ransac<T, DataType>::setAlgorithm(Algorithm algorithm) 00687 { 00688 switch(algorithm) 00689 { 00690 case RANSAC: 00691 { 00692 this->algorithm = &Ransac::algorithmRansac; 00693 break; 00694 } 00695 00696 case RANSAC_BIGGEST_CONSESUS_SET: 00697 { 00698 this->algorithm = &Ransac::algorithmRansacBiggestConsensusSet; 00699 break; 00700 } 00701 00702 case RANSAC_SMALLEST_RMSE: 00703 { 00704 this->algorithm = &Ransac::algorithmRansacSmallestRmse; 00705 break; 00706 } 00707 00708 default: 00709 { 00710 ErrorObj error; 00711 error.setClassName("Ransac"); 00712 error.setFunctionName("setAlgorithm"); 00713 error.setErrorMessage("Unknown algorithm."); 00714 error.setErrorCode(UNKNOWN_ALGORITHM); 00715 throw error; 00716 } 00717 } 00718 } 00719 00720 00723 template <class T, class DataType> 00724 void Ransac<T, DataType>::setData(const std::vector<DataType> & data) 00725 { 00726 this->data = &data; 00727 } 00728 00729 00737 template <class T, class DataType> 00738 void Ransac<T, DataType>::setErrorTolerance(T error_tolerance) 00739 { 00740 this->error_tolerance = error_tolerance; 00741 } 00742 00743 00746 template <class T, class DataType> 00747 void Ransac<T, DataType>::setMinimumSetSize(unsigned size) 00748 { 00749 minimumSetSize = size; 00750 } 00751 00752 00755 template <class T, class DataType> 00756 void Ransac<T, DataType>::setModel(Model & model) 00757 { 00758 this->model = &model; 00759 } 00760 00761 00768 template <class T, class DataType> 00769 void Ransac<T, DataType>::setProbability(T probability) 00770 { 00771 this->probability = probability; 00772 } 00773 00774 00783 template <class T, class DataType> 00784 void Ransac<T, DataType>::setThreshold(unsigned threshold) 00785 { 00786 this->threshold = threshold; 00787 } 00788 00789 00792 template <class T, class DataType> 00793 void Ransac<T, DataType>::setTrials(unsigned number) 00794 { 00795 trials = number; 00796 } 00797 00798 00799 } // namespace TRTK 00800 00801 00802 #endif // RANSAC_HPP_1147104378
Documentation generated by Doxygen