00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef QVRANSAC_H
00022 #define QVRANSAC_H
00023
00024 #include <iostream>
00025 #include <QMap>
00026
00027 #include <qvmath.h>
00028
00122 template <typename Element, typename Model> class QVRANSAC
00123 {
00124 protected:
00125 int sampleSetSize, minInliers, iteration;
00126
00127
00128 QList< Element > elements;
00129 bool continueCondition;
00130
00131
00132 QList<Element> bestInliers;
00133 Model bestModel;
00134
00135 virtual bool init()
00136 {
00137
00138 if (elements.size() < sampleSetSize)
00139 return continueCondition = false;
00140 else
00141 return continueCondition = true;
00142 }
00143
00144
00145 virtual const QList< Element > getNewTentativeInliersSet()
00146 {
00147 QList< Element > result;
00148
00149 for (int i = 0; i < this->sampleSetSize; i++)
00150 result.append(this->elements.at( RANDOM(0, this->elements.size()-1) ));
00151
00152 return result;
00153 }
00154
00155 public:
00162 QVRANSAC(const int sampleSetSize, const int minInliers):sampleSetSize(sampleSetSize), minInliers(minInliers) { }
00163
00171 virtual const bool fit(const QList<Element> &elementList, Model &model) = 0;
00172
00180 virtual const bool test(const Model &model, const Element &element, const QList<Element> &bestInliers) = 0;
00181
00187 void addElement(const Element &element) { elements.append(element); }
00188
00194 const Model & getBestModel() const { return bestModel; }
00195
00201 const QList<Element> & getBestInliers() const { return bestInliers; }
00202
00208 const int getIterations() const { return iteration; }
00209
00217 const bool iterate(const int maxIterations)
00218 {
00219 if (!init())
00220 return false;
00221
00222 iteration = 0;
00223
00224 while(continueCondition && (iteration++) < maxIterations)
00225 {
00226
00227 Model tentativeModel;
00228
00229
00230 if (!fit(getNewTentativeInliersSet(), tentativeModel))
00231 continue;
00232
00233
00234 QList<Element> inliersSet;
00235 foreach (Element element, elements)
00236 if (test(tentativeModel, element, inliersSet))
00237 inliersSet.append(element);
00238
00239
00240 if (inliersSet.size() >= minInliers )
00241 {
00242 fit(inliersSet, tentativeModel);
00243 bestModel = tentativeModel;
00244 bestInliers = inliersSet;
00245 return true;
00246 }
00247 }
00248
00249 return false;
00250 }
00251 };
00252
00276 template <typename Element, typename Model> class QVPROSAC: public QVRANSAC<Element, Model>
00277 {
00278 protected:
00279 QMap<double, Element > elementsMap;
00280
00281 #ifndef DOXYGEN_IGNORE_THIS
00282 virtual const QList< Element > getNewTentativeInliersSet()
00283 {
00284 const int maxSize = 2* log(this->getIterations()) / log(2);
00285 QList< Element > result;
00286
00287 for (int i = 0; i < this->sampleSetSize; i++)
00288 result.append(this->elements.at( RANDOM(0, MAX(this->sampleSetSize, maxSize-1)) ));
00289
00290 return result;
00291 }
00292
00293 bool init()
00294 {
00295 const QList<double> preferenceList = elementsMap.uniqueKeys();
00296 for (int i = 0; i < preferenceList.size(); i++)
00297 this->elements += elementsMap.values(preferenceList.at(i));
00298
00299 return QVRANSAC<Element, Model>::init();
00300 }
00301 #endif
00302
00303 public:
00310 QVPROSAC(const int sampleSetSize, const int minInliers): QVRANSAC<Element, Model>(sampleSetSize, minInliers) { }
00311
00319 void addElement(const Element &element, const double preference = 0)
00320 { elementsMap.insertMulti(preference, element); }
00321 };
00322
00323 #endif