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 #ifndef DOXYGEN_IGNORE_THIS
00136 virtual bool init()
00137 {
00138
00139 if (elements.size() < sampleSetSize)
00140 return continueCondition = false;
00141 else
00142 return continueCondition = true;
00143 }
00144
00145
00146 virtual const QList< Element > getNewTentativeInliersSet()
00147 {
00148 QList< Element > result;
00149
00150 for (int i = 0; i < this->sampleSetSize; i++)
00151 result.append(this->elements.at( RANDOM(0, this->elements.size()-1) ));
00152
00153 return result;
00154 }
00155 #endif
00156
00157 public:
00164 QVRANSAC(const int sampleSetSize, const int minInliers):sampleSetSize(sampleSetSize), minInliers(minInliers) { }
00165
00173 virtual const bool fit(const QList<Element> &elementList, Model &model) = 0;
00174
00182 virtual const bool test(const Model &model, const Element &element, const QList<Element> &bestInliers) = 0;
00183
00189 void addElement(const Element &element) { elements.append(element); }
00190
00196 const Model & getBestModel() const { return bestModel; }
00197
00203 const QList<Element> & getBestInliers() const { return bestInliers; }
00204
00210 const int getIterations() const { return iteration; }
00211
00219 const bool iterate(const int maxIterations)
00220 {
00221 if (!init())
00222 return false;
00223
00224 iteration = 0;
00225
00226 while(continueCondition && (iteration++) < maxIterations)
00227 {
00228
00229 Model tentativeModel;
00230
00231
00232 if (!fit(getNewTentativeInliersSet(), tentativeModel))
00233 continue;
00234
00235
00236 QList<Element> inliersSet;
00237 foreach (Element element, elements)
00238 if (test(tentativeModel, element, inliersSet))
00239 inliersSet.append(element);
00240
00241
00242 if (inliersSet.size() >= minInliers )
00243 {
00244 fit(inliersSet, tentativeModel);
00245 bestModel = tentativeModel;
00246 bestInliers = inliersSet;
00247 return true;
00248 }
00249 }
00250
00251 return false;
00252 }
00253 };
00254
00278 template <typename Element, typename Model> class QVPROSAC: public QVRANSAC<Element, Model>
00279 {
00280 protected:
00281 QMap<double, Element > elementsMap;
00282
00283 #ifndef DOXYGEN_IGNORE_THIS
00284 virtual const QList< Element > getNewTentativeInliersSet()
00285 {
00286 const int maxSize = 2* log(this->getIterations()) / log(2);
00287 QList< Element > result;
00288
00289 for (int i = 0; i < this->sampleSetSize; i++)
00290 result.append(this->elements.at( RANDOM(0, MAX(this->sampleSetSize, maxSize-1)) ));
00291
00292 return result;
00293 }
00294
00295 bool init()
00296 {
00297 const QList<double> preferenceList = elementsMap.uniqueKeys();
00298 for (int i = 0; i < preferenceList.size(); i++)
00299 this->elements += elementsMap.values(preferenceList.at(i));
00300
00301 return QVRANSAC<Element, Model>::init();
00302 }
00303 #endif
00304
00305 public:
00312 QVPROSAC(const int sampleSetSize, const int minInliers): QVRANSAC<Element, Model>(sampleSetSize, minInliers) { }
00313
00321 void addElement(const Element &element, const double preference = 0)
00322 { elementsMap.insertMulti(preference, element); }
00323 };
00324
00325 #endif