include/opencv2/contrib/openfabmap.hpp
Go to the documentation of this file.
00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 // This file originates from the openFABMAP project:
00010 // [http://code.google.com/p/openfabmap/]
00011 //
00012 // For published work which uses all or part of OpenFABMAP, please cite:
00013 // [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6224843]
00014 //
00015 // Original Algorithm by Mark Cummins and Paul Newman:
00016 // [http://ijr.sagepub.com/content/27/6/647.short]
00017 // [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942]
00018 // [http://ijr.sagepub.com/content/30/9/1100.abstract]
00019 //
00020 //                           License Agreement
00021 //
00022 // Copyright (C) 2012 Arren Glover [aj.glover@qut.edu.au] and
00023 //                    Will Maddern [w.maddern@qut.edu.au], all rights reserved.
00024 //
00025 //
00026 // Redistribution and use in source and binary forms, with or without modification,
00027 // are permitted provided that the following conditions are met:
00028 //
00029 //   * Redistribution's of source code must retain the above copyright notice,
00030 //     this list of conditions and the following disclaimer.
00031 //
00032 //   * Redistribution's in binary form must reproduce the above copyright notice,
00033 //     this list of conditions and the following disclaimer in the documentation
00034 //     and/or other materials provided with the distribution.
00035 //
00036 //   * The name of the copyright holders may not be used to endorse or promote products
00037 //     derived from this software without specific prior written permission.
00038 //
00039 // This software is provided by the copyright holders and contributors "as is" and
00040 // any express or implied warranties, including, but not limited to, the implied
00041 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00042 // In no event shall the Intel Corporation or contributors be liable for any direct,
00043 // indirect, incidental, special, exemplary, or consequential damages
00044 // (including, but not limited to, procurement of substitute goods or services;
00045 // loss of use, data, or profits; or business interruption) however caused
00046 // and on any theory of liability, whether in contract, strict liability,
00047 // or tort (including negligence or otherwise) arising in any way out of
00048 // the use of this software, even if advised of the possibility of such damage.
00049 //
00050 //M*/
00051 
00052 #ifndef __OPENCV_OPENFABMAP_H_
00053 #define __OPENCV_OPENFABMAP_H_
00054 
00055 #include "opencv2/core/core.hpp"
00056 #include "opencv2/features2d/features2d.hpp"
00057 
00058 #include <vector>
00059 #include <list>
00060 #include <map>
00061 #include <set>
00062 #include <valarray>
00063 
00064 namespace cv {
00065 
00066 namespace of2 {
00067 
00068 using std::list;
00069 using std::map;
00070 using std::multiset;
00071 
00072 /*
00073     Return data format of a FABMAP compare call
00074 */
00075 struct CV_EXPORTS IMatch {
00076 
00077     IMatch() :
00078         queryIdx(-1), imgIdx(-1), likelihood(-DBL_MAX), match(-DBL_MAX) {
00079     }
00080     IMatch(int _queryIdx, int _imgIdx, double _likelihood, double _match) :
00081         queryIdx(_queryIdx), imgIdx(_imgIdx), likelihood(_likelihood), match(
00082                 _match) {
00083     }
00084 
00085     int queryIdx;    //query index
00086     int imgIdx;      //test index
00087 
00088     double likelihood;  //raw loglikelihood
00089     double match;      //normalised probability
00090 
00091     bool operator<(const IMatch& m) const {
00092         return match < m.match;
00093     }
00094 
00095 };
00096 
00097 /*
00098     Base FabMap class. Each FabMap method inherits from this class.
00099 */
00100 class CV_EXPORTS FabMap {
00101 public:
00102 
00103     //FabMap options
00104     enum {
00105         MEAN_FIELD = 1,
00106         SAMPLED = 2,
00107         NAIVE_BAYES = 4,
00108         CHOW_LIU = 8,
00109         MOTION_MODEL = 16
00110     };
00111 
00112     FabMap(const Mat& clTree, double PzGe, double PzGNe, int flags,
00113             int numSamples = 0);
00114     virtual ~FabMap();
00115 
00116     //methods to add training data for sampling method
00117     virtual void addTraining(const Mat& queryImgDescriptor);
00118     virtual void addTraining(const vector<Mat>& queryImgDescriptors);
00119 
00120     //methods to add to the test data
00121     virtual void add(const Mat& queryImgDescriptor);
00122     virtual void add(const vector<Mat>& queryImgDescriptors);
00123 
00124     //accessors
00125     const vector<Mat>& getTrainingImgDescriptors() const;
00126     const vector<Mat>& getTestImgDescriptors() const;
00127 
00128     //Main FabMap image comparison
00129     void compare(const Mat& queryImgDescriptor,
00130             vector<IMatch>& matches, bool addQuery = false,
00131             const Mat& mask = Mat());
00132     void compare(const Mat& queryImgDescriptor,
00133             const Mat& testImgDescriptors, vector<IMatch>& matches,
00134             const Mat& mask = Mat());
00135     void compare(const Mat& queryImgDescriptor,
00136             const vector<Mat>& testImgDescriptors,
00137             vector<IMatch>& matches, const Mat& mask = Mat());
00138     void compare(const vector<Mat>& queryImgDescriptors, vector<
00139             IMatch>& matches, bool addQuery = false, const Mat& mask =
00140             Mat());
00141     void compare(const vector<Mat>& queryImgDescriptors,
00142             const vector<Mat>& testImgDescriptors,
00143             vector<IMatch>& matches, const Mat& mask = Mat());
00144 
00145 protected:
00146 
00147     void compareImgDescriptor(const Mat& queryImgDescriptor,
00148             int queryIndex, const vector<Mat>& testImgDescriptors,
00149             vector<IMatch>& matches);
00150 
00151     void addImgDescriptor(const Mat& queryImgDescriptor);
00152 
00153     //the getLikelihoods method is overwritten for each different FabMap
00154     //method.
00155     virtual void getLikelihoods(const Mat& queryImgDescriptor,
00156             const vector<Mat>& testImgDescriptors,
00157             vector<IMatch>& matches);
00158     virtual double getNewPlaceLikelihood(const Mat& queryImgDescriptor);
00159 
00160     //turn likelihoods into probabilities (also add in motion model if used)
00161     void normaliseDistribution(vector<IMatch>& matches);
00162 
00163     //Chow-Liu Tree
00164     int pq(int q);
00165     double Pzq(int q, bool zq);
00166     double PzqGzpq(int q, bool zq, bool zpq);
00167 
00168     //FAB-MAP Core
00169     double PzqGeq(bool zq, bool eq);
00170     double PeqGL(int q, bool Lzq, bool eq);
00171     double PzqGL(int q, bool zq, bool zpq, bool Lzq);
00172     double PzqGzpqL(int q, bool zq, bool zpq, bool Lzq);
00173     double (FabMap::*PzGL)(int q, bool zq, bool zpq, bool Lzq);
00174 
00175     //data
00176     Mat clTree;
00177     vector<Mat> trainingImgDescriptors;
00178     vector<Mat> testImgDescriptors;
00179     vector<IMatch> priorMatches;
00180 
00181     //parameters
00182     double PzGe;
00183     double PzGNe;
00184     double Pnew;
00185 
00186     double mBias;
00187     double sFactor;
00188 
00189     int flags;
00190     int numSamples;
00191 
00192 };
00193 
00194 /*
00195     The original FAB-MAP algorithm, developed based on:
00196     http://ijr.sagepub.com/content/27/6/647.short
00197 */
00198 class CV_EXPORTS FabMap1: public FabMap {
00199 public:
00200     FabMap1(const Mat& clTree, double PzGe, double PzGNe, int flags,
00201             int numSamples = 0);
00202     virtual ~FabMap1();
00203 protected:
00204 
00205     //FabMap1 implementation of likelihood comparison
00206     void getLikelihoods(const Mat& queryImgDescriptor, const vector<
00207             Mat>& testImgDescriptors, vector<IMatch>& matches);
00208 };
00209 
00210 /*
00211     A computationally faster version of the original FAB-MAP algorithm. A look-
00212     up-table is used to precompute many of the reoccuring calculations
00213 */
00214 class CV_EXPORTS FabMapLUT: public FabMap {
00215 public:
00216     FabMapLUT(const Mat& clTree, double PzGe, double PzGNe,
00217             int flags, int numSamples = 0, int precision = 6);
00218     virtual ~FabMapLUT();
00219 protected:
00220 
00221     //FabMap look-up-table implementation of the likelihood comparison
00222     void getLikelihoods(const Mat& queryImgDescriptor, const vector<
00223             Mat>& testImgDescriptors, vector<IMatch>& matches);
00224 
00225     //precomputed data
00226     int (*table)[8];
00227 
00228     //data precision
00229     int precision;
00230 };
00231 
00232 /*
00233     The Accelerated FAB-MAP algorithm, developed based on:
00234     http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942
00235 */
00236 class CV_EXPORTS FabMapFBO: public FabMap {
00237 public:
00238     FabMapFBO(const Mat& clTree, double PzGe, double PzGNe, int flags,
00239             int numSamples = 0, double rejectionThreshold = 1e-8, double PsGd =
00240                     1e-8, int bisectionStart = 512, int bisectionIts = 9);
00241     virtual ~FabMapFBO();
00242 
00243 protected:
00244 
00245     //FabMap Fast Bail-out implementation of the likelihood comparison
00246     void getLikelihoods(const Mat& queryImgDescriptor, const vector<
00247             Mat>& testImgDescriptors, vector<IMatch>& matches);
00248 
00249     //stucture used to determine word comparison order
00250     struct WordStats {
00251         WordStats() :
00252             q(0), info(0), V(0), M(0) {
00253         }
00254 
00255         WordStats(int _q, double _info) :
00256             q(_q), info(_info), V(0), M(0) {
00257         }
00258 
00259         int q;
00260         double info;
00261         mutable double V;
00262         mutable double M;
00263 
00264         bool operator<(const WordStats& w) const {
00265             return info < w.info;
00266         }
00267 
00268     };
00269 
00270     //private fast bail-out necessary functions
00271     void setWordStatistics(const Mat& queryImgDescriptor, multiset<WordStats>& wordData);
00272     double limitbisection(double v, double m);
00273     double bennettInequality(double v, double m, double delta);
00274     static bool compInfo(const WordStats& first, const WordStats& second);
00275 
00276     //parameters
00277     double PsGd;
00278     double rejectionThreshold;
00279     int bisectionStart;
00280     int bisectionIts;
00281 };
00282 
00283 /*
00284     The FAB-MAP2.0 algorithm, developed based on:
00285     http://ijr.sagepub.com/content/30/9/1100.abstract
00286 */
00287 class CV_EXPORTS FabMap2: public FabMap {
00288 public:
00289 
00290     FabMap2(const Mat& clTree, double PzGe, double PzGNe, int flags);
00291     virtual ~FabMap2();
00292 
00293     //FabMap2 builds the inverted index and requires an additional training/test
00294     //add function
00295     void addTraining(const Mat& queryImgDescriptors) {
00296         FabMap::addTraining(queryImgDescriptors);
00297     }
00298     void addTraining(const vector<Mat>& queryImgDescriptors);
00299 
00300     void add(const Mat& queryImgDescriptors) {
00301         FabMap::add(queryImgDescriptors);
00302     }
00303     void add(const vector<Mat>& queryImgDescriptors);
00304 
00305 protected:
00306 
00307     //FabMap2 implementation of the likelihood comparison
00308     void getLikelihoods(const Mat& queryImgDescriptor, const vector<
00309             Mat>& testImgDescriptors, vector<IMatch>& matches);
00310     double getNewPlaceLikelihood(const Mat& queryImgDescriptor);
00311 
00312     //the likelihood function using the inverted index
00313     void getIndexLikelihoods(const Mat& queryImgDescriptor, vector<
00314                              double>& defaults, map<int, vector<int> >& invertedMap,
00315             vector<IMatch>& matches);
00316     void addToIndex(const Mat& queryImgDescriptor,
00317             vector<double>& defaults,
00318             map<int, vector<int> >& invertedMap);
00319 
00320     //data
00321     vector<double> d1, d2, d3, d4;
00322     vector<vector<int> > children;
00323 
00324     // TODO: inverted map a vector?
00325 
00326     vector<double> trainingDefaults;
00327     map<int, vector<int> > trainingInvertedMap;
00328 
00329     vector<double> testDefaults;
00330     map<int, vector<int> > testInvertedMap;
00331 
00332 };
00333 /*
00334     A Chow-Liu tree is required by FAB-MAP. The Chow-Liu tree provides an
00335     estimate of the full distribution of visual words using a minimum spanning
00336     tree. The tree is generated through training data.
00337 */
00338 class CV_EXPORTS ChowLiuTree {
00339 public:
00340     ChowLiuTree();
00341     virtual ~ChowLiuTree();
00342 
00343     //add data to the chow-liu tree before calling make
00344     void add(const Mat& imgDescriptor);
00345     void add(const vector<Mat>& imgDescriptors);
00346 
00347     const vector<Mat>& getImgDescriptors() const;
00348 
00349     Mat make(double infoThreshold = 0.0);
00350 
00351 private:
00352     vector<Mat> imgDescriptors;
00353     Mat mergedImgDescriptors;
00354 
00355     typedef struct info {
00356         float score;
00357         short word1;
00358         short word2;
00359     } info;
00360 
00361     //probabilities extracted from mergedImgDescriptors
00362     double P(int a, bool za);
00363     double JP(int a, bool za, int b, bool zb); //a & b
00364     double CP(int a, bool za, int b, bool zb); // a | b
00365 
00366     //calculating mutual information of all edges
00367     void createBaseEdges(list<info>& edges, double infoThreshold);
00368     double calcMutInfo(int word1, int word2);
00369     static bool sortInfoScores(const info& first, const info& second);
00370 
00371     //selecting minimum spanning egdges with maximum information
00372     bool reduceEdgesToMinSpan(list<info>& edges);
00373 
00374     //building the tree sctructure
00375     Mat buildTree(int root_word, list<info> &edges);
00376     void recAddToTree(Mat &cltree, int q, int pq,
00377         list<info> &remaining_edges);
00378     vector<int> extractChildren(list<info> &remaining_edges, int q);
00379 
00380 };
00381 
00382 /*
00383     A custom vocabulary training method based on:
00384     http://www.springerlink.com/content/d1h6j8x552532003/
00385 */
00386 class CV_EXPORTS BOWMSCTrainer: public BOWTrainer {
00387 public:
00388     BOWMSCTrainer(double clusterSize = 0.4);
00389     virtual ~BOWMSCTrainer();
00390 
00391     // Returns trained vocabulary (i.e. cluster centers).
00392     virtual Mat cluster() const;
00393     virtual Mat cluster(const Mat& descriptors) const;
00394 
00395 protected:
00396 
00397     double clusterSize;
00398 
00399 };
00400 
00401 }
00402 
00403 }
00404 
00405 #endif /* OPENFABMAP_H_ */