src/qvdta/qvsampleconsensus.h

00001 /*
00002  *      Copyright (C) 2007. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
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                 // To use after initialization
00127                 QList< Element > elements;
00128                 bool continueCondition;
00129 
00130                 // To return to the user.
00131                 QList<Element> inliersSet, bestInliers;
00132                 Model maybeModel, consensusModel, bestModel;
00133 
00134                 #ifndef DOXYGEN_IGNORE_THIS
00135                 virtual bool init()
00136                         {
00137                         // Check if there are enough in-liners to work.
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                                 // Get feasible maybe model, and maybe inliers set.
00228                                 const QList<Element> maybeInliers = getNextMaybeInliersSet();
00229                 
00230                                 // If no feasible model was found, return the continue condition.
00231                                 if (!fit(maybeInliers, maybeModel))
00232                                         continue;
00233                 
00234                                 // Else, get consensus set.
00235                                 inliersSet.clear();
00236                 
00237                                 foreach (Element element, elements)
00238                                         if (test(maybeModel, element))
00239                                                 inliersSet.append(element);
00240                 
00241                                 // Get consensus model.
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

Generated on Thu Jul 17 17:23:27 2008 for QVision by  doxygen 1.5.3