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 QVector<int> indexes;
00148 indexes.reserve(this->sampleSetSize);
00149
00150 for (int i = 0; i < this->sampleSetSize; i++)
00151 {
00152 int index = RANDOM(0, this->elements.size()-1);
00153
00154 while( indexes.contains(index) )
00155 index = RANDOM(0, this->elements.size()-1);
00156
00157
00158 indexes << index;
00159 }
00160
00161 QList< Element > result;
00162 result.reserve(indexes.count());
00163 foreach(int index, indexes)
00164 result << this->elements.at( index );
00165
00166 return result;
00167 }
00168
00169 public:
00176 QVRANSAC(const int sampleSetSize, const int minInliers):sampleSetSize(sampleSetSize), minInliers(minInliers) { }
00177
00185 virtual bool fit(const QList<Element> &elementList, Model &model) = 0;
00186
00194 virtual bool test(const Model &model, const Element &element) = 0;
00195
00201 void addElement(const Element &element) { elements.append(element); }
00202
00208 const Model & getBestModel() const { return bestModel; }
00209
00215 const QList<Element> & getBestInliers() const { return bestInliers; }
00216
00222 int getIterations() const { return iteration; }
00223
00231 bool iterate(const int maxIterations)
00232 {
00233 if (!init())
00234 return false;
00235
00236 iteration = 0;
00237
00238 while(continueCondition && (iteration++) < maxIterations)
00239 {
00240
00241 Model tentativeModel;
00242
00243
00244 if (!fit(getNewTentativeInliersSet(), tentativeModel))
00245 continue;
00246
00247
00248 QList<Element> inliersSet;
00249 foreach (Element element, elements)
00250 if (test(tentativeModel, element))
00251 inliersSet.append(element);
00252
00253
00254 if (inliersSet.size() >= minInliers )
00255 {
00256 fit(inliersSet, tentativeModel);
00257 bestModel = tentativeModel;
00258 bestInliers = inliersSet;
00259 return true;
00260 }
00261 }
00262
00263 return false;
00264 }
00265 };
00266
00290 template <typename Element, typename Model> class QVPROSAC: public QVRANSAC<Element, Model>
00291 {
00292 protected:
00293 QMap<double, Element > elementsMap;
00294
00295 #ifndef DOXYGEN_IGNORE_THIS
00296 virtual const QList< Element > getNewTentativeInliersSet()
00297 {
00298 const int maxSize = 2* log(this->getIterations()) / log(2);
00299 QList< Element > result;
00300
00301 for (int i = 0; i < this->sampleSetSize; i++)
00302 result.append(this->elements.at( RANDOM(0, MAX(this->sampleSetSize, maxSize-1)) ));
00303
00304 return result;
00305 }
00306
00307 bool init()
00308 {
00309 const QList<double> preferenceList = elementsMap.uniqueKeys();
00310 for (int i = 0; i < preferenceList.size(); i++)
00311 this->elements += elementsMap.values(preferenceList.at(i));
00312
00313 return QVRANSAC<Element, Model>::init();
00314 }
00315 #endif
00316
00317 public:
00324 QVPROSAC(const int sampleSetSize, const int minInliers): QVRANSAC<Element, Model>(sampleSetSize, minInliers) { }
00325
00333 void addElement(const Element &element, const double preference = 0)
00334 { elementsMap.insertMulti(preference, element); }
00335 };
00336
00337 #endif