00001
00002
00003
00004
00005
00006 #ifndef JMATH_RANSAC_HPP
00007 #define JMATH_RANSAC_HPP
00008 #include "jmath/uniform_random.hpp"
00009
00010 namespace jafar {
00011 namespace jmath {
00012 template <typename NUMTYPE = double>
00016 class RANSAC {
00017 public:
00018
00020 typedef void (*RANSAC_fit_functor)(const ublas::matrix<NUMTYPE> &data,
00021 const std::vector<size_t> &indices,
00022 ublas::vector< ublas::matrix<NUMTYPE> > &fit_models);
00023
00025 typedef void (*RANSAC_distance_functor)(const ublas::matrix<NUMTYPE> &data,
00026 const ublas::vector< ublas::matrix<NUMTYPE> > & test_models,
00027 NUMTYPE distance_threshold,
00028 unsigned int & best_model_index,
00029 std::vector<size_t>& inlier_indices );
00030
00032 typedef bool (*RANSAC_degenerate_functor)(const ublas::matrix<NUMTYPE> &data,
00033 const std::vector<size_t> &indices );
00034
00044 static bool execute(const ublas::matrix<NUMTYPE> &data,
00045 RANSAC_fit_functor fit_func,
00046 RANSAC_distance_functor dist_func,
00047 RANSAC_degenerate_functor degen_func,
00048 const NUMTYPE distance_threshold,
00049 const unsigned int min_size_samples_to_fit,
00050 std::vector<size_t> &out_best_inliers,
00051 ublas::matrix<NUMTYPE> &out_best_model,
00052 const NUMTYPE prob_good_sample = 0.999,
00053 const size_t max_iter = 200000)
00054 {
00055 JFR_ASSERT(min_size_samples_to_fit>=1,
00056 "minimum size of samples to fit must be greater than 0")
00057 const size_t D = data.size1();
00058 const size_t nb_pts = data.size2();
00059
00060 JFR_ASSERT(D>=1, "data diemension must be greater than 0");
00061 JFR_ASSERT(nb_pts>1, "number of data points must be at least 2");
00062
00063 const size_t maxDataTrials = 100;
00064
00065 out_best_model.resize(0,0);
00066
00067 size_t trialcount = 0;
00068 size_t bestscore = 0;
00069 size_t N = 1;
00070
00071 std::vector<size_t> ind( min_size_samples_to_fit );
00072
00073 while (N > trialcount) {
00074
00075
00076
00077 bool degenerate=true;
00078 size_t count = 1;
00079 ublas::vector< ublas::matrix<NUMTYPE> > MODELS;
00080
00081 while (degenerate) {
00082
00083 ind.resize( min_size_samples_to_fit );
00084
00085 random::uniform_fill((unsigned int)0, (unsigned int)nb_pts-1, ind);
00086
00087
00088 degenerate = degen_func(data, ind);
00089
00090 if (!degenerate) {
00091
00092
00093 fit_func(data,ind,MODELS);
00094
00095
00096
00097
00098
00099 degenerate = MODELS.empty();
00100 }
00101
00102
00103 if (++count > maxDataTrials) {
00104 JFR_DEBUG("unable to select a nondegenerate data set")
00105 }
00106 }
00107 JFR_DEBUG("found a non degenerate data set")
00108
00109
00110
00111
00112
00113
00114 unsigned int best_model_index = -1;
00115 std::vector<size_t> inliers;
00116 if (!degenerate) {
00117 dist_func(data,MODELS, distance_threshold, best_model_index, inliers);
00118
00119
00120 }
00121 JFR_DEBUG("best model index "<<best_model_index)
00122
00123 const size_t ninliers = inliers.size();
00124 JFR_DEBUG("nb inliers "<<ninliers)
00125 if (ninliers > bestscore ) {
00126 bestscore = ninliers;
00127 out_best_model.resize(MODELS[best_model_index].size1(), MODELS[best_model_index].size2());
00128 out_best_model = MODELS[best_model_index];
00129 out_best_inliers = inliers;
00130
00131
00132
00133 NUMTYPE fracinliers = ninliers/static_cast<NUMTYPE>(nb_pts);
00134 NUMTYPE pNoOutliers = 1 - pow(fracinliers,static_cast<NUMTYPE>(min_size_samples_to_fit));
00135
00136 pNoOutliers = std::max( std::numeric_limits<NUMTYPE>::epsilon(), pNoOutliers);
00137 pNoOutliers = std::min(1.0 - std::numeric_limits<NUMTYPE>::epsilon() , pNoOutliers);
00138
00139 N = log(1-prob_good_sample)/log(pNoOutliers);
00140 JFR_DEBUG("iter #"<<(unsigned)trialcount<<" Estimated number of iters: "<<(unsigned)N<<" pNoOutliers = "<<pNoOutliers<<" #inliers: "<<(unsigned)ninliers)
00141 }
00142
00143 ++trialcount;
00144
00145 JFR_DEBUG("trial "<<(unsigned int)trialcount<<" out of "<<(unsigned int)ceil(static_cast<double>(N)))
00146
00147
00148 if (trialcount > max_iter) {
00149 JFR_DEBUG("Warning: maximum number of trials ("<<max_iter<<") reached")
00150 break;
00151 }
00152 }
00153
00154 if (out_best_model.size1()>0) {
00155 JFR_DEBUG("Finished in "<<(unsigned)trialcount<<" iterations")
00156 return true;
00157 }
00158 else {
00159 JFR_DEBUG("Warning: Finished without any proper solution.")
00160 return false;
00161 }
00162 }
00163 };
00165 typedef RANSAC<double> ransac;
00166
00167 }
00168 }
00169
00170 #endif