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 #include <qvcore/qvdefines.h>
00027
00121 template <typename Element, typename Model> class QVRANSAC
00122 {
00123 protected:
00124 int sampleSetSize, minInliers, iteration;
00125
00126
00127 QList< Element > elements;
00128 bool continueCondition;
00129
00130
00131 QList<Element> inliersSet, bestInliers;
00132 Model maybeModel, consensusModel, bestModel;
00133
00134 #ifndef DOXYGEN_IGNORE_THIS
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 > getNextMaybeInliersSet()
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 #endif
00155
00156 public:
00163 QVRANSAC(const int sampleSetSize, const int minInliers):sampleSetSize(sampleSetSize), minInliers(minInliers) { }
00164
00172 virtual const bool fit(const QList<Element> &elementList, Model &model) = 0;
00173
00181 virtual const bool test(const Model &model, const Element &element) = 0;
00182
00188 void addElement(const Element &element) { elements.append(element); }
00189
00195 const Model & getBestModel() const { return bestModel; }
00196
00202 const QList<Element> & getBestInliers() const { return bestInliers; }
00203
00209 const int getIterations() const { return iteration; }
00210
00218 const bool iterate(const int maxIterations)
00219 {
00220 if (!init())
00221 return false;
00222
00223 iteration = 0;
00224
00225 while(continueCondition && (iteration++) < maxIterations)
00226 {
00227
00228 const QList<Element> maybeInliers = getNextMaybeInliersSet();
00229
00230
00231 if (!fit(maybeInliers, maybeModel))
00232 continue;
00233
00234
00235 inliersSet.clear();
00236
00237 foreach (Element element, elements)
00238 if (test(maybeModel, element))
00239 inliersSet.append(element);
00240
00241
00242 fit(inliersSet, consensusModel);
00243
00244 if (inliersSet.size() >= minInliers && inliersSet.size() > bestInliers.size() )
00245 {
00246 bestModel = consensusModel;
00247 bestInliers = inliersSet;
00248 return true;
00249 }
00250 }
00251 return (inliersSet.size() >= minInliers);
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 > getNextMaybeInliersSet()
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