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 <qvdefines.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> inliersSet, bestInliers;
00133 Model maybeModel, consensusModel, 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 > getNextMaybeInliersSet()
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) = 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 const QList<Element> maybeInliers = getNextMaybeInliersSet();
00230
00231
00232 if (!fit(maybeInliers, maybeModel))
00233 continue;
00234
00235
00236 inliersSet.clear();
00237
00238 foreach (Element element, elements)
00239 if (test(maybeModel, element))
00240 inliersSet.append(element);
00241
00242
00243 fit(inliersSet, consensusModel);
00244
00245 if (inliersSet.size() >= minInliers && inliersSet.size() > bestInliers.size() )
00246 {
00247 bestModel = consensusModel;
00248 bestInliers = inliersSet;
00249 return true;
00250 }
00251 }
00252 return (inliersSet.size() >= minInliers);
00253 }
00254 };
00255
00279 template <typename Element, typename Model> class QVPROSAC: public QVRANSAC<Element, Model>
00280 {
00281 protected:
00282 QMap<double, Element > elementsMap;
00283
00284 #ifndef DOXYGEN_IGNORE_THIS
00285 virtual const QList< Element > getNextMaybeInliersSet()
00286 {
00287 const int maxSize = 2* log(this->getIterations()) / log(2);
00288 QList< Element > result;
00289
00290 for (int i = 0; i < this->sampleSetSize; i++)
00291 result.append(this->elements.at( RANDOM(0, MAX(this->sampleSetSize, maxSize-1)) ));
00292
00293 return result;
00294 }
00295
00296 bool init()
00297 {
00298 const QList<double> preferenceList = elementsMap.uniqueKeys();
00299 for (int i = 0; i < preferenceList.size(); i++)
00300 this->elements += elementsMap.values(preferenceList.at(i));
00301
00302 return QVRANSAC<Element, Model>::init();
00303 }
00304 #endif
00305
00306 public:
00313 QVPROSAC(const int sampleSetSize, const int minInliers): QVRANSAC<Element, Model>(sampleSetSize, minInliers) { }
00314
00322 void addElement(const Element &element, const double preference = 0)
00323 { elementsMap.insertMulti(preference, element); }
00324 };
00325
00326 #endif