mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
405 lines
12 KiB
405 lines
12 KiB
/*M/////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. |
|
// |
|
// By downloading, copying, installing or using the software you agree to this license. |
|
// If you do not agree to this license, do not download, install, |
|
// copy or use the software. |
|
// |
|
// This file originates from the openFABMAP project: |
|
// [http://code.google.com/p/openfabmap/] |
|
// |
|
// For published work which uses all or part of OpenFABMAP, please cite: |
|
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6224843] |
|
// |
|
// Original Algorithm by Mark Cummins and Paul Newman: |
|
// [http://ijr.sagepub.com/content/27/6/647.short] |
|
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942] |
|
// [http://ijr.sagepub.com/content/30/9/1100.abstract] |
|
// |
|
// License Agreement |
|
// |
|
// Copyright (C) 2012 Arren Glover [aj.glover@qut.edu.au] and |
|
// Will Maddern [w.maddern@qut.edu.au], all rights reserved. |
|
// |
|
// |
|
// Redistribution and use in source and binary forms, with or without modification, |
|
// are permitted provided that the following conditions are met: |
|
// |
|
// * Redistribution's of source code must retain the above copyright notice, |
|
// this list of conditions and the following disclaimer. |
|
// |
|
// * Redistribution's in binary form must reproduce the above copyright notice, |
|
// this list of conditions and the following disclaimer in the documentation |
|
// and/or other materials provided with the distribution. |
|
// |
|
// * The name of the copyright holders may not be used to endorse or promote products |
|
// derived from this software without specific prior written permission. |
|
// |
|
// This software is provided by the copyright holders and contributors "as is" and |
|
// any express or implied warranties, including, but not limited to, the implied |
|
// warranties of merchantability and fitness for a particular purpose are disclaimed. |
|
// In no event shall the Intel Corporation or contributors be liable for any direct, |
|
// indirect, incidental, special, exemplary, or consequential damages |
|
// (including, but not limited to, procurement of substitute goods or services; |
|
// loss of use, data, or profits; or business interruption) however caused |
|
// and on any theory of liability, whether in contract, strict liability, |
|
// or tort (including negligence or otherwise) arising in any way out of |
|
// the use of this software, even if advised of the possibility of such damage. |
|
// |
|
//M*/ |
|
|
|
#ifndef __OPENCV_OPENFABMAP_H_ |
|
#define __OPENCV_OPENFABMAP_H_ |
|
|
|
#include "opencv2/core/core.hpp" |
|
#include "opencv2/features2d/features2d.hpp" |
|
|
|
#include <vector> |
|
#include <list> |
|
#include <map> |
|
#include <set> |
|
#include <valarray> |
|
|
|
namespace cv { |
|
|
|
namespace of2 { |
|
|
|
using std::list; |
|
using std::map; |
|
using std::multiset; |
|
|
|
/* |
|
Return data format of a FABMAP compare call |
|
*/ |
|
struct CV_EXPORTS IMatch { |
|
|
|
IMatch() : |
|
queryIdx(-1), imgIdx(-1), likelihood(-DBL_MAX), match(-DBL_MAX) { |
|
} |
|
IMatch(int _queryIdx, int _imgIdx, double _likelihood, double _match) : |
|
queryIdx(_queryIdx), imgIdx(_imgIdx), likelihood(_likelihood), match( |
|
_match) { |
|
} |
|
|
|
int queryIdx; //query index |
|
int imgIdx; //test index |
|
|
|
double likelihood; //raw loglikelihood |
|
double match; //normalised probability |
|
|
|
bool operator<(const IMatch& m) const { |
|
return match < m.match; |
|
} |
|
|
|
}; |
|
|
|
/* |
|
Base FabMap class. Each FabMap method inherits from this class. |
|
*/ |
|
class CV_EXPORTS FabMap { |
|
public: |
|
|
|
//FabMap options |
|
enum { |
|
MEAN_FIELD = 1, |
|
SAMPLED = 2, |
|
NAIVE_BAYES = 4, |
|
CHOW_LIU = 8, |
|
MOTION_MODEL = 16 |
|
}; |
|
|
|
FabMap(const Mat& clTree, double PzGe, double PzGNe, int flags, |
|
int numSamples = 0); |
|
virtual ~FabMap(); |
|
|
|
//methods to add training data for sampling method |
|
virtual void addTraining(const Mat& queryImgDescriptor); |
|
virtual void addTraining(const vector<Mat>& queryImgDescriptors); |
|
|
|
//methods to add to the test data |
|
virtual void add(const Mat& queryImgDescriptor); |
|
virtual void add(const vector<Mat>& queryImgDescriptors); |
|
|
|
//accessors |
|
const vector<Mat>& getTrainingImgDescriptors() const; |
|
const vector<Mat>& getTestImgDescriptors() const; |
|
|
|
//Main FabMap image comparison |
|
void compare(const Mat& queryImgDescriptor, |
|
vector<IMatch>& matches, bool addQuery = false, |
|
const Mat& mask = Mat()); |
|
void compare(const Mat& queryImgDescriptor, |
|
const Mat& testImgDescriptors, vector<IMatch>& matches, |
|
const Mat& mask = Mat()); |
|
void compare(const Mat& queryImgDescriptor, |
|
const vector<Mat>& testImgDescriptors, |
|
vector<IMatch>& matches, const Mat& mask = Mat()); |
|
void compare(const vector<Mat>& queryImgDescriptors, vector< |
|
IMatch>& matches, bool addQuery = false, const Mat& mask = |
|
Mat()); |
|
void compare(const vector<Mat>& queryImgDescriptors, |
|
const vector<Mat>& testImgDescriptors, |
|
vector<IMatch>& matches, const Mat& mask = Mat()); |
|
|
|
protected: |
|
|
|
void compareImgDescriptor(const Mat& queryImgDescriptor, |
|
int queryIndex, const vector<Mat>& testImgDescriptors, |
|
vector<IMatch>& matches); |
|
|
|
void addImgDescriptor(const Mat& queryImgDescriptor); |
|
|
|
//the getLikelihoods method is overwritten for each different FabMap |
|
//method. |
|
virtual void getLikelihoods(const Mat& queryImgDescriptor, |
|
const vector<Mat>& testImgDescriptors, |
|
vector<IMatch>& matches); |
|
virtual double getNewPlaceLikelihood(const Mat& queryImgDescriptor); |
|
|
|
//turn likelihoods into probabilities (also add in motion model if used) |
|
void normaliseDistribution(vector<IMatch>& matches); |
|
|
|
//Chow-Liu Tree |
|
int pq(int q); |
|
double Pzq(int q, bool zq); |
|
double PzqGzpq(int q, bool zq, bool zpq); |
|
|
|
//FAB-MAP Core |
|
double PzqGeq(bool zq, bool eq); |
|
double PeqGL(int q, bool Lzq, bool eq); |
|
double PzqGL(int q, bool zq, bool zpq, bool Lzq); |
|
double PzqGzpqL(int q, bool zq, bool zpq, bool Lzq); |
|
double (FabMap::*PzGL)(int q, bool zq, bool zpq, bool Lzq); |
|
|
|
//data |
|
Mat clTree; |
|
vector<Mat> trainingImgDescriptors; |
|
vector<Mat> testImgDescriptors; |
|
vector<IMatch> priorMatches; |
|
|
|
//parameters |
|
double PzGe; |
|
double PzGNe; |
|
double Pnew; |
|
|
|
double mBias; |
|
double sFactor; |
|
|
|
int flags; |
|
int numSamples; |
|
|
|
}; |
|
|
|
/* |
|
The original FAB-MAP algorithm, developed based on: |
|
http://ijr.sagepub.com/content/27/6/647.short |
|
*/ |
|
class CV_EXPORTS FabMap1: public FabMap { |
|
public: |
|
FabMap1(const Mat& clTree, double PzGe, double PzGNe, int flags, |
|
int numSamples = 0); |
|
virtual ~FabMap1(); |
|
protected: |
|
|
|
//FabMap1 implementation of likelihood comparison |
|
void getLikelihoods(const Mat& queryImgDescriptor, const vector< |
|
Mat>& testImgDescriptors, vector<IMatch>& matches); |
|
}; |
|
|
|
/* |
|
A computationally faster version of the original FAB-MAP algorithm. A look- |
|
up-table is used to precompute many of the reoccuring calculations |
|
*/ |
|
class CV_EXPORTS FabMapLUT: public FabMap { |
|
public: |
|
FabMapLUT(const Mat& clTree, double PzGe, double PzGNe, |
|
int flags, int numSamples = 0, int precision = 6); |
|
virtual ~FabMapLUT(); |
|
protected: |
|
|
|
//FabMap look-up-table implementation of the likelihood comparison |
|
void getLikelihoods(const Mat& queryImgDescriptor, const vector< |
|
Mat>& testImgDescriptors, vector<IMatch>& matches); |
|
|
|
//precomputed data |
|
int (*table)[8]; |
|
|
|
//data precision |
|
int precision; |
|
}; |
|
|
|
/* |
|
The Accelerated FAB-MAP algorithm, developed based on: |
|
http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942 |
|
*/ |
|
class CV_EXPORTS FabMapFBO: public FabMap { |
|
public: |
|
FabMapFBO(const Mat& clTree, double PzGe, double PzGNe, int flags, |
|
int numSamples = 0, double rejectionThreshold = 1e-8, double PsGd = |
|
1e-8, int bisectionStart = 512, int bisectionIts = 9); |
|
virtual ~FabMapFBO(); |
|
|
|
protected: |
|
|
|
//FabMap Fast Bail-out implementation of the likelihood comparison |
|
void getLikelihoods(const Mat& queryImgDescriptor, const vector< |
|
Mat>& testImgDescriptors, vector<IMatch>& matches); |
|
|
|
//stucture used to determine word comparison order |
|
struct WordStats { |
|
WordStats() : |
|
q(0), info(0), V(0), M(0) { |
|
} |
|
|
|
WordStats(int _q, double _info) : |
|
q(_q), info(_info), V(0), M(0) { |
|
} |
|
|
|
int q; |
|
double info; |
|
mutable double V; |
|
mutable double M; |
|
|
|
bool operator<(const WordStats& w) const { |
|
return info < w.info; |
|
} |
|
|
|
}; |
|
|
|
//private fast bail-out necessary functions |
|
void setWordStatistics(const Mat& queryImgDescriptor, multiset<WordStats>& wordData); |
|
double limitbisection(double v, double m); |
|
double bennettInequality(double v, double m, double delta); |
|
static bool compInfo(const WordStats& first, const WordStats& second); |
|
|
|
//parameters |
|
double PsGd; |
|
double rejectionThreshold; |
|
int bisectionStart; |
|
int bisectionIts; |
|
}; |
|
|
|
/* |
|
The FAB-MAP2.0 algorithm, developed based on: |
|
http://ijr.sagepub.com/content/30/9/1100.abstract |
|
*/ |
|
class CV_EXPORTS FabMap2: public FabMap { |
|
public: |
|
|
|
FabMap2(const Mat& clTree, double PzGe, double PzGNe, int flags); |
|
virtual ~FabMap2(); |
|
|
|
//FabMap2 builds the inverted index and requires an additional training/test |
|
//add function |
|
void addTraining(const Mat& queryImgDescriptors) { |
|
FabMap::addTraining(queryImgDescriptors); |
|
} |
|
void addTraining(const vector<Mat>& queryImgDescriptors); |
|
|
|
void add(const Mat& queryImgDescriptors) { |
|
FabMap::add(queryImgDescriptors); |
|
} |
|
void add(const vector<Mat>& queryImgDescriptors); |
|
|
|
protected: |
|
|
|
//FabMap2 implementation of the likelihood comparison |
|
void getLikelihoods(const Mat& queryImgDescriptor, const vector< |
|
Mat>& testImgDescriptors, vector<IMatch>& matches); |
|
double getNewPlaceLikelihood(const Mat& queryImgDescriptor); |
|
|
|
//the likelihood function using the inverted index |
|
void getIndexLikelihoods(const Mat& queryImgDescriptor, vector< |
|
double>& defaults, map<int, vector<int> >& invertedMap, |
|
vector<IMatch>& matches); |
|
void addToIndex(const Mat& queryImgDescriptor, |
|
vector<double>& defaults, |
|
map<int, vector<int> >& invertedMap); |
|
|
|
//data |
|
vector<double> d1, d2, d3, d4; |
|
vector<vector<int> > children; |
|
|
|
// TODO: inverted map a vector? |
|
|
|
vector<double> trainingDefaults; |
|
map<int, vector<int> > trainingInvertedMap; |
|
|
|
vector<double> testDefaults; |
|
map<int, vector<int> > testInvertedMap; |
|
|
|
}; |
|
/* |
|
A Chow-Liu tree is required by FAB-MAP. The Chow-Liu tree provides an |
|
estimate of the full distribution of visual words using a minimum spanning |
|
tree. The tree is generated through training data. |
|
*/ |
|
class CV_EXPORTS ChowLiuTree { |
|
public: |
|
ChowLiuTree(); |
|
virtual ~ChowLiuTree(); |
|
|
|
//add data to the chow-liu tree before calling make |
|
void add(const Mat& imgDescriptor); |
|
void add(const vector<Mat>& imgDescriptors); |
|
|
|
const vector<Mat>& getImgDescriptors() const; |
|
|
|
Mat make(double infoThreshold = 0.0); |
|
|
|
private: |
|
vector<Mat> imgDescriptors; |
|
Mat mergedImgDescriptors; |
|
|
|
typedef struct info { |
|
float score; |
|
short word1; |
|
short word2; |
|
} info; |
|
|
|
//probabilities extracted from mergedImgDescriptors |
|
double P(int a, bool za); |
|
double JP(int a, bool za, int b, bool zb); //a & b |
|
double CP(int a, bool za, int b, bool zb); // a | b |
|
|
|
//calculating mutual information of all edges |
|
void createBaseEdges(list<info>& edges, double infoThreshold); |
|
double calcMutInfo(int word1, int word2); |
|
static bool sortInfoScores(const info& first, const info& second); |
|
|
|
//selecting minimum spanning egdges with maximum information |
|
bool reduceEdgesToMinSpan(list<info>& edges); |
|
|
|
//building the tree sctructure |
|
Mat buildTree(int root_word, list<info> &edges); |
|
void recAddToTree(Mat &cltree, int q, int pq, |
|
list<info> &remaining_edges); |
|
vector<int> extractChildren(list<info> &remaining_edges, int q); |
|
|
|
}; |
|
|
|
/* |
|
A custom vocabulary training method based on: |
|
http://www.springerlink.com/content/d1h6j8x552532003/ |
|
*/ |
|
class CV_EXPORTS BOWMSCTrainer: public BOWTrainer { |
|
public: |
|
BOWMSCTrainer(double clusterSize = 0.4); |
|
virtual ~BOWMSCTrainer(); |
|
|
|
// Returns trained vocabulary (i.e. cluster centers). |
|
virtual Mat cluster() const; |
|
virtual Mat cluster(const Mat& descriptors) const; |
|
|
|
protected: |
|
|
|
double clusterSize; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif /* OPENFABMAP_H_ */
|
|
|