"atomic bomb" commit. Reorganized OpenCV directory structure
This commit is contained in:
571
3rdparty/flann/algorithms/autotuned_index.h
vendored
Normal file
571
3rdparty/flann/algorithms/autotuned_index.h
vendored
Normal file
@@ -0,0 +1,571 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef AUTOTUNEDINDEX_H_
|
||||
#define AUTOTUNEDINDEX_H_
|
||||
|
||||
#include "constants.h"
|
||||
#include "nn_index.h"
|
||||
#include "ground_truth.h"
|
||||
#include "index_testing.h"
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
class AutotunedIndex : public NNIndex
|
||||
{
|
||||
NNIndex* bestIndex;
|
||||
IndexParams* bestParams;
|
||||
SearchParams bestSearchParams;
|
||||
|
||||
Matrix<float>* sampledDataset;
|
||||
Matrix<float>* testDataset;
|
||||
Matrix<int>* gt_matches;
|
||||
|
||||
float speedup;
|
||||
|
||||
/**
|
||||
* The dataset used by this index
|
||||
*/
|
||||
const Matrix<float> dataset;
|
||||
|
||||
/**
|
||||
* Index parameters
|
||||
*/
|
||||
const AutotunedIndexParams& params;
|
||||
|
||||
/**
|
||||
* Number of features in the dataset.
|
||||
*/
|
||||
int size_;
|
||||
|
||||
/**
|
||||
* Length of each feature.
|
||||
*/
|
||||
int veclen_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
AutotunedIndex(const Matrix<float>& inputData, const AutotunedIndexParams& params_ = AutotunedIndexParams() ) :
|
||||
dataset(inputData), params(params_)
|
||||
{
|
||||
size_ = dataset.rows;
|
||||
veclen_ = dataset.cols;
|
||||
|
||||
bestIndex = NULL;
|
||||
|
||||
}
|
||||
|
||||
virtual ~AutotunedIndex()
|
||||
{
|
||||
delete bestIndex;
|
||||
delete bestParams;
|
||||
};
|
||||
|
||||
/**
|
||||
Method responsible with building the index.
|
||||
*/
|
||||
virtual void buildIndex()
|
||||
{
|
||||
bestParams = estimateBuildParams();
|
||||
bestIndex = bestParams->createIndex(dataset);
|
||||
bestIndex->buildIndex();
|
||||
speedup = estimateSearchParams(bestSearchParams);
|
||||
}
|
||||
|
||||
/**
|
||||
Saves the index to a stream
|
||||
*/
|
||||
virtual void saveIndex(FILE* stream)
|
||||
{
|
||||
bestIndex->saveIndex(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
Loads the index from a stream
|
||||
*/
|
||||
virtual void loadIndex(FILE* stream)
|
||||
{
|
||||
bestIndex->loadIndex(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
Method that searches for nearest-neighbors
|
||||
*/
|
||||
virtual void findNeighbors(ResultSet& result, const float* vec, const SearchParams& /*searchParams*/)
|
||||
{
|
||||
bestIndex->findNeighbors(result, vec, bestSearchParams);
|
||||
}
|
||||
|
||||
/**
|
||||
Number of features in this index.
|
||||
*/
|
||||
virtual int size() const
|
||||
{
|
||||
return bestIndex->size();
|
||||
}
|
||||
|
||||
/**
|
||||
The length of each vector in this index.
|
||||
*/
|
||||
virtual int veclen() const
|
||||
{
|
||||
return bestIndex->veclen();
|
||||
}
|
||||
|
||||
/**
|
||||
The amount of memory (in bytes) this index uses.
|
||||
*/
|
||||
virtual int usedMemory() const
|
||||
{
|
||||
return bestIndex->usedMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Algorithm name
|
||||
*/
|
||||
virtual flann_algorithm_t getType() const
|
||||
{
|
||||
return bestIndex->getType();
|
||||
}
|
||||
|
||||
/**
|
||||
Estimates the search parameters required in order to get a certain precision.
|
||||
If testset is not given it uses cross-validation.
|
||||
*/
|
||||
// virtual Params estimateSearchParams(float precision, Dataset<float>* testset = NULL)
|
||||
// {
|
||||
// Params params;
|
||||
//
|
||||
// return params;
|
||||
// }
|
||||
private:
|
||||
|
||||
struct CostData {
|
||||
float searchTimeCost;
|
||||
float buildTimeCost;
|
||||
float timeCost;
|
||||
float memoryCost;
|
||||
float totalCost;
|
||||
};
|
||||
|
||||
typedef pair<CostData, KDTreeIndexParams> KDTreeCostData;
|
||||
typedef pair<CostData, KMeansIndexParams> KMeansCostData;
|
||||
|
||||
|
||||
void evaluate_kmeans(CostData& cost, const KMeansIndexParams& kmeans_params)
|
||||
{
|
||||
StartStopTimer t;
|
||||
int checks;
|
||||
const int nn = 1;
|
||||
|
||||
logger.info("KMeansTree using params: max_iterations=%d, branching=%d\n", kmeans_params.iterations, kmeans_params.branching);
|
||||
KMeansIndex kmeans(*sampledDataset, kmeans_params);
|
||||
// measure index build time
|
||||
t.start();
|
||||
kmeans.buildIndex();
|
||||
t.stop();
|
||||
float buildTime = (float)t.value;
|
||||
|
||||
// measure search time
|
||||
float searchTime = test_index_precision(kmeans, *sampledDataset, *testDataset, *gt_matches, params.target_precision, checks, nn);;
|
||||
|
||||
float datasetMemory = (float)(sampledDataset->rows*sampledDataset->cols*sizeof(float));
|
||||
cost.memoryCost = (kmeans.usedMemory()+datasetMemory)/datasetMemory;
|
||||
cost.searchTimeCost = searchTime;
|
||||
cost.buildTimeCost = buildTime;
|
||||
cost.timeCost = (buildTime*params.build_weight+searchTime);
|
||||
logger.info("KMeansTree buildTime=%g, searchTime=%g, timeCost=%g, buildTimeFactor=%g\n",buildTime, searchTime, cost.timeCost, params.build_weight);
|
||||
}
|
||||
|
||||
|
||||
void evaluate_kdtree(CostData& cost, const KDTreeIndexParams& kdtree_params)
|
||||
{
|
||||
StartStopTimer t;
|
||||
int checks;
|
||||
const int nn = 1;
|
||||
|
||||
logger.info("KDTree using params: trees=%d\n",kdtree_params.trees);
|
||||
KDTreeIndex kdtree(*sampledDataset, kdtree_params);
|
||||
|
||||
t.start();
|
||||
kdtree.buildIndex();
|
||||
t.stop();
|
||||
float buildTime = (float)t.value;
|
||||
|
||||
//measure search time
|
||||
float searchTime = test_index_precision(kdtree, *sampledDataset, *testDataset, *gt_matches, params.target_precision, checks, nn);
|
||||
|
||||
float datasetMemory = (float)(sampledDataset->rows*sampledDataset->cols*sizeof(float));
|
||||
cost.memoryCost = (kdtree.usedMemory()+datasetMemory)/datasetMemory;
|
||||
cost.searchTimeCost = searchTime;
|
||||
cost.buildTimeCost = buildTime;
|
||||
cost.timeCost = (buildTime*params.build_weight+searchTime);
|
||||
logger.info("KDTree buildTime=%g, searchTime=%g, timeCost=%g\n",buildTime, searchTime, cost.timeCost);
|
||||
}
|
||||
|
||||
|
||||
// struct KMeansSimpleDownhillFunctor {
|
||||
//
|
||||
// Autotune& autotuner;
|
||||
// KMeansSimpleDownhillFunctor(Autotune& autotuner_) : autotuner(autotuner_) {};
|
||||
//
|
||||
// float operator()(int* params) {
|
||||
//
|
||||
// float maxFloat = numeric_limits<float>::max();
|
||||
//
|
||||
// if (params[0]<2) return maxFloat;
|
||||
// if (params[1]<0) return maxFloat;
|
||||
//
|
||||
// CostData c;
|
||||
// c.params["algorithm"] = KMEANS;
|
||||
// c.params["centers-init"] = CENTERS_RANDOM;
|
||||
// c.params["branching"] = params[0];
|
||||
// c.params["max-iterations"] = params[1];
|
||||
//
|
||||
// autotuner.evaluate_kmeans(c);
|
||||
//
|
||||
// return c.timeCost;
|
||||
//
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// struct KDTreeSimpleDownhillFunctor {
|
||||
//
|
||||
// Autotune& autotuner;
|
||||
// KDTreeSimpleDownhillFunctor(Autotune& autotuner_) : autotuner(autotuner_) {};
|
||||
//
|
||||
// float operator()(int* params) {
|
||||
// float maxFloat = numeric_limits<float>::max();
|
||||
//
|
||||
// if (params[0]<1) return maxFloat;
|
||||
//
|
||||
// CostData c;
|
||||
// c.params["algorithm"] = KDTREE;
|
||||
// c.params["trees"] = params[0];
|
||||
//
|
||||
// autotuner.evaluate_kdtree(c);
|
||||
//
|
||||
// return c.timeCost;
|
||||
//
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
|
||||
KMeansCostData optimizeKMeans()
|
||||
{
|
||||
logger.info("KMEANS, Step 1: Exploring parameter space\n");
|
||||
|
||||
// explore kmeans parameters space using combinations of the parameters below
|
||||
int maxIterations[] = { 1, 5, 10, 15 };
|
||||
int branchingFactors[] = { 16, 32, 64, 128, 256 };
|
||||
|
||||
int kmeansParamSpaceSize = ARRAY_LEN(maxIterations)*ARRAY_LEN(branchingFactors);
|
||||
|
||||
vector<KMeansCostData> kmeansCosts(kmeansParamSpaceSize);
|
||||
|
||||
// CostData* kmeansCosts = new CostData[kmeansParamSpaceSize];
|
||||
|
||||
// evaluate kmeans for all parameter combinations
|
||||
int cnt = 0;
|
||||
for (size_t i=0; i<ARRAY_LEN(maxIterations); ++i) {
|
||||
for (size_t j=0; j<ARRAY_LEN(branchingFactors); ++j) {
|
||||
|
||||
kmeansCosts[cnt].second.centers_init = CENTERS_RANDOM;
|
||||
kmeansCosts[cnt].second.branching = branchingFactors[j];
|
||||
kmeansCosts[cnt].second.iterations = maxIterations[j];
|
||||
|
||||
evaluate_kmeans(kmeansCosts[cnt].first, kmeansCosts[cnt].second);
|
||||
|
||||
int k = cnt;
|
||||
// order by time cost
|
||||
while (k>0 && kmeansCosts[k].first.timeCost < kmeansCosts[k-1].first.timeCost) {
|
||||
swap(kmeansCosts[k],kmeansCosts[k-1]);
|
||||
--k;
|
||||
}
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
|
||||
// logger.info("KMEANS, Step 2: simplex-downhill optimization\n");
|
||||
//
|
||||
// const int n = 2;
|
||||
// // choose initial simplex points as the best parameters so far
|
||||
// int kmeansNMPoints[n*(n+1)];
|
||||
// float kmeansVals[n+1];
|
||||
// for (int i=0;i<n+1;++i) {
|
||||
// kmeansNMPoints[i*n] = (int)kmeansCosts[i].params["branching"];
|
||||
// kmeansNMPoints[i*n+1] = (int)kmeansCosts[i].params["max-iterations"];
|
||||
// kmeansVals[i] = kmeansCosts[i].timeCost;
|
||||
// }
|
||||
// KMeansSimpleDownhillFunctor kmeans_cost_func(*this);
|
||||
// // run optimization
|
||||
// optimizeSimplexDownhill(kmeansNMPoints,n,kmeans_cost_func,kmeansVals);
|
||||
// // store results
|
||||
// for (int i=0;i<n+1;++i) {
|
||||
// kmeansCosts[i].params["branching"] = kmeansNMPoints[i*2];
|
||||
// kmeansCosts[i].params["max-iterations"] = kmeansNMPoints[i*2+1];
|
||||
// kmeansCosts[i].timeCost = kmeansVals[i];
|
||||
// }
|
||||
|
||||
float optTimeCost = kmeansCosts[0].first.timeCost;
|
||||
// recompute total costs factoring in the memory costs
|
||||
for (int i=0;i<kmeansParamSpaceSize;++i) {
|
||||
kmeansCosts[i].first.totalCost = (kmeansCosts[i].first.timeCost/optTimeCost + params.memory_weight * kmeansCosts[i].first.memoryCost);
|
||||
|
||||
int k = i;
|
||||
while (k>0 && kmeansCosts[k].first.totalCost < kmeansCosts[k-1].first.totalCost) {
|
||||
swap(kmeansCosts[k],kmeansCosts[k-1]);
|
||||
k--;
|
||||
}
|
||||
}
|
||||
// display the costs obtained
|
||||
for (int i=0;i<kmeansParamSpaceSize;++i) {
|
||||
logger.info("KMeans, branching=%d, iterations=%d, time_cost=%g[%g] (build=%g, search=%g), memory_cost=%g, cost=%g\n",
|
||||
kmeansCosts[i].second.branching, kmeansCosts[i].second.iterations,
|
||||
kmeansCosts[i].first.timeCost,kmeansCosts[i].first.timeCost/optTimeCost,
|
||||
kmeansCosts[i].first.buildTimeCost, kmeansCosts[i].first.searchTimeCost,
|
||||
kmeansCosts[i].first.memoryCost,kmeansCosts[i].first.totalCost);
|
||||
}
|
||||
|
||||
return kmeansCosts[0];
|
||||
}
|
||||
|
||||
|
||||
KDTreeCostData optimizeKDTree()
|
||||
{
|
||||
|
||||
logger.info("KD-TREE, Step 1: Exploring parameter space\n");
|
||||
|
||||
// explore kd-tree parameters space using the parameters below
|
||||
int testTrees[] = { 1, 4, 8, 16, 32 };
|
||||
|
||||
size_t kdtreeParamSpaceSize = ARRAY_LEN(testTrees);
|
||||
vector<KDTreeCostData> kdtreeCosts(kdtreeParamSpaceSize);
|
||||
|
||||
// evaluate kdtree for all parameter combinations
|
||||
int cnt = 0;
|
||||
for (size_t i=0; i<ARRAY_LEN(testTrees); ++i) {
|
||||
kdtreeCosts[cnt].second.trees = testTrees[i];
|
||||
|
||||
evaluate_kdtree(kdtreeCosts[cnt].first, kdtreeCosts[cnt].second);
|
||||
|
||||
int k = cnt;
|
||||
// order by time cost
|
||||
while (k>0 && kdtreeCosts[k].first.timeCost < kdtreeCosts[k-1].first.timeCost) {
|
||||
swap(kdtreeCosts[k],kdtreeCosts[k-1]);
|
||||
--k;
|
||||
}
|
||||
++cnt;
|
||||
}
|
||||
|
||||
// logger.info("KD-TREE, Step 2: simplex-downhill optimization\n");
|
||||
//
|
||||
// const int n = 1;
|
||||
// // choose initial simplex points as the best parameters so far
|
||||
// int kdtreeNMPoints[n*(n+1)];
|
||||
// float kdtreeVals[n+1];
|
||||
// for (int i=0;i<n+1;++i) {
|
||||
// kdtreeNMPoints[i] = (int)kdtreeCosts[i].params["trees"];
|
||||
// kdtreeVals[i] = kdtreeCosts[i].timeCost;
|
||||
// }
|
||||
// KDTreeSimpleDownhillFunctor kdtree_cost_func(*this);
|
||||
// // run optimization
|
||||
// optimizeSimplexDownhill(kdtreeNMPoints,n,kdtree_cost_func,kdtreeVals);
|
||||
// // store results
|
||||
// for (int i=0;i<n+1;++i) {
|
||||
// kdtreeCosts[i].params["trees"] = kdtreeNMPoints[i];
|
||||
// kdtreeCosts[i].timeCost = kdtreeVals[i];
|
||||
// }
|
||||
|
||||
float optTimeCost = kdtreeCosts[0].first.timeCost;
|
||||
// recompute costs for kd-tree factoring in memory cost
|
||||
for (size_t i=0;i<kdtreeParamSpaceSize;++i) {
|
||||
kdtreeCosts[i].first.totalCost = (kdtreeCosts[i].first.timeCost/optTimeCost + params.memory_weight * kdtreeCosts[i].first.memoryCost);
|
||||
|
||||
int k = i;
|
||||
while (k>0 && kdtreeCosts[k].first.totalCost < kdtreeCosts[k-1].first.totalCost) {
|
||||
swap(kdtreeCosts[k],kdtreeCosts[k-1]);
|
||||
k--;
|
||||
}
|
||||
}
|
||||
// display costs obtained
|
||||
for (size_t i=0;i<kdtreeParamSpaceSize;++i) {
|
||||
logger.info("kd-tree, trees=%d, time_cost=%g[%g] (build=%g, search=%g), memory_cost=%g, cost=%g\n",
|
||||
kdtreeCosts[i].second.trees,kdtreeCosts[i].first.timeCost,kdtreeCosts[i].first.timeCost/optTimeCost,
|
||||
kdtreeCosts[i].first.buildTimeCost, kdtreeCosts[i].first.searchTimeCost,
|
||||
kdtreeCosts[i].first.memoryCost,kdtreeCosts[i].first.totalCost);
|
||||
}
|
||||
|
||||
return kdtreeCosts[0];
|
||||
}
|
||||
|
||||
/**
|
||||
Chooses the best nearest-neighbor algorithm and estimates the optimal
|
||||
parameters to use when building the index (for a given precision).
|
||||
Returns a dictionary with the optimal parameters.
|
||||
*/
|
||||
IndexParams* estimateBuildParams()
|
||||
{
|
||||
int sampleSize = int(params.sample_fraction*dataset.rows);
|
||||
int testSampleSize = min(sampleSize/10, 1000);
|
||||
|
||||
logger.info("Entering autotuning, dataset size: %d, sampleSize: %d, testSampleSize: %d\n",dataset.rows, sampleSize, testSampleSize);
|
||||
|
||||
// For a very small dataset, it makes no sense to build any fancy index, just
|
||||
// use linear search
|
||||
if (testSampleSize<10) {
|
||||
logger.info("Choosing linear, dataset too small\n");
|
||||
return new LinearIndexParams();
|
||||
}
|
||||
|
||||
// We use a fraction of the original dataset to speedup the autotune algorithm
|
||||
sampledDataset = dataset.sample(sampleSize);
|
||||
// We use a cross-validation approach, first we sample a testset from the dataset
|
||||
testDataset = sampledDataset->sample(testSampleSize,true);
|
||||
|
||||
// We compute the ground truth using linear search
|
||||
logger.info("Computing ground truth... \n");
|
||||
gt_matches = new Matrix<int>(testDataset->rows, 1);
|
||||
StartStopTimer t;
|
||||
t.start();
|
||||
compute_ground_truth(*sampledDataset, *testDataset, *gt_matches, 0);
|
||||
t.stop();
|
||||
float bestCost = (float)t.value;
|
||||
IndexParams* bestParams = new LinearIndexParams();
|
||||
|
||||
// Start parameter autotune process
|
||||
logger.info("Autotuning parameters...\n");
|
||||
|
||||
|
||||
KMeansCostData kmeansCost = optimizeKMeans();
|
||||
|
||||
if (kmeansCost.first.totalCost<bestCost) {
|
||||
bestParams = new KMeansIndexParams(kmeansCost.second);
|
||||
bestCost = kmeansCost.first.totalCost;
|
||||
}
|
||||
|
||||
KDTreeCostData kdtreeCost = optimizeKDTree();
|
||||
|
||||
if (kdtreeCost.first.totalCost<bestCost) {
|
||||
bestParams = new KDTreeIndexParams(kdtreeCost.second);
|
||||
bestCost = kdtreeCost.first.totalCost;
|
||||
}
|
||||
|
||||
// free the memory used by the datasets we sampled
|
||||
delete sampledDataset;
|
||||
delete testDataset;
|
||||
delete gt_matches;
|
||||
|
||||
return bestParams;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Estimates the search time parameters needed to get the desired precision.
|
||||
Precondition: the index is built
|
||||
Postcondition: the searchParams will have the optimum params set, also the speedup obtained over linear search.
|
||||
*/
|
||||
float estimateSearchParams(SearchParams& searchParams)
|
||||
{
|
||||
const int nn = 1;
|
||||
const long SAMPLE_COUNT = 1000;
|
||||
|
||||
assert(bestIndex!=NULL); // must have a valid index
|
||||
|
||||
float speedup = 0;
|
||||
|
||||
int samples = min(dataset.rows/10, SAMPLE_COUNT);
|
||||
if (samples>0) {
|
||||
Matrix<float>* testDataset = dataset.sample(samples);
|
||||
|
||||
logger.info("Computing ground truth\n");
|
||||
|
||||
// we need to compute the ground truth first
|
||||
Matrix<int> gt_matches(testDataset->rows,1);
|
||||
StartStopTimer t;
|
||||
t.start();
|
||||
compute_ground_truth(dataset, *testDataset, gt_matches,1);
|
||||
t.stop();
|
||||
float linear = (float)t.value;
|
||||
|
||||
int checks;
|
||||
logger.info("Estimating number of checks\n");
|
||||
|
||||
float searchTime;
|
||||
float cb_index;
|
||||
if (bestIndex->getType() == KMEANS) {
|
||||
|
||||
logger.info("KMeans algorithm, estimating cluster border factor\n");
|
||||
KMeansIndex* kmeans = (KMeansIndex*)bestIndex;
|
||||
float bestSearchTime = -1;
|
||||
float best_cb_index = -1;
|
||||
int best_checks = -1;
|
||||
for (cb_index = 0;cb_index<1.1f; cb_index+=0.2f) {
|
||||
kmeans->set_cb_index(cb_index);
|
||||
searchTime = test_index_precision(*kmeans, dataset, *testDataset, gt_matches, params.target_precision, checks, nn, 1);
|
||||
if (searchTime<bestSearchTime || bestSearchTime == -1) {
|
||||
bestSearchTime = searchTime;
|
||||
best_cb_index = cb_index;
|
||||
best_checks = checks;
|
||||
}
|
||||
}
|
||||
searchTime = bestSearchTime;
|
||||
cb_index = best_cb_index;
|
||||
checks = best_checks;
|
||||
|
||||
kmeans->set_cb_index(best_cb_index);
|
||||
logger.info("Optimum cb_index: %g\n",cb_index);
|
||||
((KMeansIndexParams*)bestParams)->cb_index = cb_index;
|
||||
}
|
||||
else {
|
||||
searchTime = test_index_precision(*bestIndex, dataset, *testDataset, gt_matches, params.target_precision, checks, nn, 1);
|
||||
}
|
||||
|
||||
logger.info("Required number of checks: %d \n",checks);;
|
||||
searchParams.checks = checks;
|
||||
delete testDataset;
|
||||
|
||||
speedup = linear/searchTime;
|
||||
}
|
||||
|
||||
return speedup;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* AUTOTUNEDINDEX_H_ */
|
128
3rdparty/flann/algorithms/composite_index.h
vendored
Normal file
128
3rdparty/flann/algorithms/composite_index.h
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef COMPOSITETREE_H
|
||||
#define COMPOSITETREE_H
|
||||
|
||||
#include "constants.h"
|
||||
#include "nn_index.h"
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
class CompositeIndex : public NNIndex
|
||||
{
|
||||
KMeansIndex* kmeans;
|
||||
KDTreeIndex* kdtree;
|
||||
|
||||
const Matrix<float> dataset;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
CompositeIndex(const Matrix<float>& inputData, const CompositeIndexParams& params = CompositeIndexParams() ) : dataset(inputData)
|
||||
{
|
||||
KDTreeIndexParams kdtree_params(params.trees);
|
||||
KMeansIndexParams kmeans_params(params.branching, params.iterations, params.centers_init, params.cb_index);
|
||||
|
||||
kdtree = new KDTreeIndex(inputData,kdtree_params);
|
||||
kmeans = new KMeansIndex(inputData,kmeans_params);
|
||||
|
||||
}
|
||||
|
||||
virtual ~CompositeIndex()
|
||||
{
|
||||
delete kdtree;
|
||||
delete kmeans;
|
||||
}
|
||||
|
||||
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return COMPOSITE;
|
||||
}
|
||||
|
||||
|
||||
int size() const
|
||||
{
|
||||
return dataset.rows;
|
||||
}
|
||||
|
||||
int veclen() const
|
||||
{
|
||||
return dataset.cols;
|
||||
}
|
||||
|
||||
|
||||
int usedMemory() const
|
||||
{
|
||||
return kmeans->usedMemory()+kdtree->usedMemory();
|
||||
}
|
||||
|
||||
void buildIndex()
|
||||
{
|
||||
logger.info("Building kmeans tree...\n");
|
||||
kmeans->buildIndex();
|
||||
logger.info("Building kdtree tree...\n");
|
||||
kdtree->buildIndex();
|
||||
}
|
||||
|
||||
|
||||
void saveIndex(FILE* /*stream*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loadIndex(FILE* /*stream*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void findNeighbors(ResultSet& result, const float* vec, const SearchParams& searchParams)
|
||||
{
|
||||
kmeans->findNeighbors(result,vec,searchParams);
|
||||
kdtree->findNeighbors(result,vec,searchParams);
|
||||
}
|
||||
|
||||
|
||||
// Params estimateSearchParams(float precision, Dataset<float>* testset = NULL)
|
||||
// {
|
||||
// Params params;
|
||||
//
|
||||
// return params;
|
||||
// }
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //COMPOSITETREE_H
|
51
3rdparty/flann/algorithms/dist.cpp
vendored
Normal file
51
3rdparty/flann/algorithms/dist.cpp
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*************************************************************************/
|
||||
|
||||
#include "dist.h"
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
/** Global variable indicating the distance metric
|
||||
* to be used.
|
||||
*/
|
||||
flann_distance_t flann_distance_type = EUCLIDEAN;
|
||||
|
||||
/**
|
||||
* Zero iterator that emulates a zero feature.
|
||||
*/
|
||||
ZeroIterator<float> zero;
|
||||
|
||||
/**
|
||||
* Order of Minkowski distance to use.
|
||||
*/
|
||||
int flann_minkowski_order;
|
||||
|
||||
}
|
211
3rdparty/flann/algorithms/dist.h
vendored
Normal file
211
3rdparty/flann/algorithms/dist.h
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef DIST_H
|
||||
#define DIST_H
|
||||
|
||||
#include <cmath>
|
||||
using namespace std;
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
/**
|
||||
* Distance function by default set to the custom distance
|
||||
* function. This can be set to a specific distance function
|
||||
* for further efficiency.
|
||||
*/
|
||||
#define flann_dist custom_dist
|
||||
//#define flann_dist euclidean_dist
|
||||
|
||||
|
||||
/**
|
||||
* Compute the squared Euclidean distance between two vectors.
|
||||
*
|
||||
* This is highly optimised, with loop unrolling, as it is one
|
||||
* of the most expensive inner loops.
|
||||
*
|
||||
* The computation of squared root at the end is omitted for
|
||||
* efficiency.
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
double euclidean_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
|
||||
{
|
||||
double distsq = acc;
|
||||
double diff0, diff1, diff2, diff3;
|
||||
Iterator1 lastgroup = last1 - 3;
|
||||
|
||||
/* Process 4 items with each loop for efficiency. */
|
||||
while (first1 < lastgroup) {
|
||||
diff0 = first1[0] - first2[0];
|
||||
diff1 = first1[1] - first2[1];
|
||||
diff2 = first1[2] - first2[2];
|
||||
diff3 = first1[3] - first2[3];
|
||||
distsq += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
|
||||
first1 += 4;
|
||||
first2 += 4;
|
||||
}
|
||||
/* Process last 0-3 pixels. Not needed for standard vector lengths. */
|
||||
while (first1 < last1) {
|
||||
diff0 = *first1++ - *first2++;
|
||||
distsq += diff0 * diff0;
|
||||
}
|
||||
return distsq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the Manhattan (L_1) distance between two vectors.
|
||||
*
|
||||
* This is highly optimised, with loop unrolling, as it is one
|
||||
* of the most expensive inner loops.
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
double manhattan_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
|
||||
{
|
||||
double distsq = acc;
|
||||
double diff0, diff1, diff2, diff3;
|
||||
Iterator1 lastgroup = last1 - 3;
|
||||
|
||||
/* Process 4 items with each loop for efficiency. */
|
||||
while (first1 < lastgroup) {
|
||||
diff0 = fabs(first1[0] - first2[0]);
|
||||
diff1 = fabs(first1[1] - first2[1]);
|
||||
diff2 = fabs(first1[2] - first2[2]);
|
||||
diff3 = fabs(first1[3] - first2[3]);
|
||||
distsq += diff0 + diff1 + diff2 + diff3;
|
||||
first1 += 4;
|
||||
first2 += 4;
|
||||
}
|
||||
/* Process last 0-3 pixels. Not needed for standard vector lengths. */
|
||||
while (first1 < last1) {
|
||||
diff0 = fabs(*first1++ - *first2++);
|
||||
distsq += diff0;
|
||||
}
|
||||
return distsq;
|
||||
}
|
||||
|
||||
|
||||
extern int flann_minkowski_order;
|
||||
/**
|
||||
* Compute the Minkowski (L_p) distance between two vectors.
|
||||
*
|
||||
* This is highly optimised, with loop unrolling, as it is one
|
||||
* of the most expensive inner loops.
|
||||
*
|
||||
* The computation of squared root at the end is omitted for
|
||||
* efficiency.
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
double minkowski_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
|
||||
{
|
||||
double distsq = acc;
|
||||
double diff0, diff1, diff2, diff3;
|
||||
Iterator1 lastgroup = last1 - 3;
|
||||
|
||||
int p = flann_minkowski_order;
|
||||
|
||||
/* Process 4 items with each loop for efficiency. */
|
||||
while (first1 < lastgroup) {
|
||||
diff0 = fabs(first1[0] - first2[0]);
|
||||
diff1 = fabs(first1[1] - first2[1]);
|
||||
diff2 = fabs(first1[2] - first2[2]);
|
||||
diff3 = fabs(first1[3] - first2[3]);
|
||||
distsq += pow(diff0,p) + pow(diff1,p) + pow(diff2,p) + pow(diff3,p);
|
||||
first1 += 4;
|
||||
first2 += 4;
|
||||
}
|
||||
/* Process last 0-3 pixels. Not needed for standard vector lengths. */
|
||||
while (first1 < last1) {
|
||||
diff0 = fabs(*first1++ - *first2++);
|
||||
distsq += pow(diff0,p);
|
||||
}
|
||||
return distsq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
extern flann_distance_t flann_distance_type;
|
||||
/**
|
||||
* Custom distance function. The distance computed is dependent on the value
|
||||
* of the 'flann_distance_type' global variable.
|
||||
*
|
||||
* If the last argument 'acc' is passed, the result is accumulated to the value
|
||||
* of this argument.
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
float custom_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
|
||||
{
|
||||
switch (flann_distance_type) {
|
||||
case EUCLIDEAN:
|
||||
return (float)euclidean_dist(first1, last1, first2, acc);
|
||||
case MANHATTAN:
|
||||
return (float)manhattan_dist(first1, last1, first2, acc);
|
||||
case MINKOWSKI:
|
||||
return (float)minkowski_dist(first1, last1, first2, acc);
|
||||
default:
|
||||
return (float)euclidean_dist(first1, last1, first2, acc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a "zero iterator". It basically behaves like a zero filled
|
||||
* array to all algorithms that use arrays as iterators (STL style).
|
||||
* It's useful when there's a need to compute the distance between feature
|
||||
* and origin it and allows for better compiler optimisation than using a
|
||||
* zero-filled array.
|
||||
*/
|
||||
template <typename T>
|
||||
struct ZeroIterator {
|
||||
|
||||
T operator*() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
T operator[](int /*index*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZeroIterator<T>& operator ++(int) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZeroIterator<T>& operator+=(int) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
extern ZeroIterator<float> zero;
|
||||
|
||||
}
|
||||
|
||||
#endif //DIST_H
|
653
3rdparty/flann/algorithms/kdtree_index.h
vendored
Normal file
653
3rdparty/flann/algorithms/kdtree_index.h
vendored
Normal file
@@ -0,0 +1,653 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef KDTREE_H
|
||||
#define KDTREE_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
|
||||
#include "heap.h"
|
||||
#include "common.h"
|
||||
#include "constants.h"
|
||||
#include "allocator.h"
|
||||
#include "matrix.h"
|
||||
#include "result_set.h"
|
||||
#include "random.h"
|
||||
#include "nn_index.h"
|
||||
#include "saving.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Randomized kd-tree index
|
||||
*
|
||||
* Contains the k-d trees and other information for indexing a set of points
|
||||
* for nearest-neighbor matching.
|
||||
*/
|
||||
class KDTreeIndex : public NNIndex
|
||||
{
|
||||
|
||||
enum {
|
||||
/**
|
||||
* To improve efficiency, only SAMPLE_MEAN random values are used to
|
||||
* compute the mean and variance at each level when building a tree.
|
||||
* A value of 100 seems to perform as well as using all values.
|
||||
*/
|
||||
SAMPLE_MEAN = 100,
|
||||
/**
|
||||
* Top random dimensions to consider
|
||||
*
|
||||
* When creating random trees, the dimension on which to subdivide is
|
||||
* selected at random from among the top RAND_DIM dimensions with the
|
||||
* highest variance. A value of 5 works well.
|
||||
*/
|
||||
RAND_DIM=5
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number of randomized trees that are used
|
||||
*/
|
||||
int numTrees;
|
||||
|
||||
/**
|
||||
* Array of indices to vectors in the dataset. When doing lookup,
|
||||
* this is used instead to mark checkID.
|
||||
*/
|
||||
int* vind;
|
||||
|
||||
/**
|
||||
* An unique ID for each lookup.
|
||||
*/
|
||||
int checkID;
|
||||
|
||||
/**
|
||||
* The dataset used by this index
|
||||
*/
|
||||
const Matrix<float> dataset;
|
||||
|
||||
int size_;
|
||||
int veclen_;
|
||||
|
||||
|
||||
float* mean;
|
||||
float* var;
|
||||
|
||||
|
||||
/*--------------------- Internal Data Structures --------------------------*/
|
||||
|
||||
/**
|
||||
* A node of the binary k-d tree.
|
||||
*
|
||||
* This is All nodes that have vec[divfeat] < divval are placed in the
|
||||
* child1 subtree, else child2., A leaf node is indicated if both children are NULL.
|
||||
*/
|
||||
struct TreeSt {
|
||||
/**
|
||||
* Index of the vector feature used for subdivision.
|
||||
* If this is a leaf node (both children are NULL) then
|
||||
* this holds vector index for this leaf.
|
||||
*/
|
||||
int divfeat;
|
||||
/**
|
||||
* The value used for subdivision.
|
||||
*/
|
||||
float divval;
|
||||
/**
|
||||
* The child nodes.
|
||||
*/
|
||||
TreeSt *child1, *child2;
|
||||
};
|
||||
typedef TreeSt* Tree;
|
||||
|
||||
/**
|
||||
* Array of k-d trees used to find neighbors.
|
||||
*/
|
||||
Tree* trees;
|
||||
typedef BranchStruct<Tree> BranchSt;
|
||||
typedef BranchSt* Branch;
|
||||
/**
|
||||
* Priority queue storing intermediate branches in the best-bin-first search
|
||||
*/
|
||||
Heap<BranchSt>* heap;
|
||||
|
||||
|
||||
/**
|
||||
* Pooled memory allocator.
|
||||
*
|
||||
* Using a pooled memory allocator is more efficient
|
||||
* than allocating memory directly when there is a large
|
||||
* number small of memory allocations.
|
||||
*/
|
||||
PooledAllocator pool;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return KDTREE;
|
||||
}
|
||||
|
||||
/**
|
||||
* KDTree constructor
|
||||
*
|
||||
* Params:
|
||||
* inputData = dataset with the input features
|
||||
* params = parameters passed to the kdtree algorithm
|
||||
*/
|
||||
KDTreeIndex(const Matrix<float>& inputData, const KDTreeIndexParams& params = KDTreeIndexParams() ) : dataset(inputData)
|
||||
{
|
||||
size_ = dataset.rows;
|
||||
veclen_ = dataset.cols;
|
||||
|
||||
numTrees = params.trees;
|
||||
trees = new Tree[numTrees];
|
||||
|
||||
// get the parameters
|
||||
// if (params.find("trees") != params.end()) {
|
||||
// numTrees = (int)params["trees"];
|
||||
// trees = new Tree[numTrees];
|
||||
// }
|
||||
// else {
|
||||
// numTrees = -1;
|
||||
// trees = NULL;
|
||||
// }
|
||||
heap = new Heap<BranchSt>(size_);
|
||||
checkID = -1000;
|
||||
|
||||
// Create a permutable array of indices to the input vectors.
|
||||
vind = new int[size_];
|
||||
for (int i = 0; i < size_; i++) {
|
||||
vind[i] = i;
|
||||
}
|
||||
|
||||
mean = new float[veclen_];
|
||||
var = new float[veclen_];
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard destructor
|
||||
*/
|
||||
~KDTreeIndex()
|
||||
{
|
||||
delete[] vind;
|
||||
if (trees!=NULL) {
|
||||
delete[] trees;
|
||||
}
|
||||
delete heap;
|
||||
delete[] mean;
|
||||
delete[] var;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds the index
|
||||
*/
|
||||
void buildIndex()
|
||||
{
|
||||
/* Construct the randomized trees. */
|
||||
for (int i = 0; i < numTrees; i++) {
|
||||
/* Randomize the order of vectors to allow for unbiased sampling. */
|
||||
for (int j = size_; j > 0; --j) {
|
||||
// int rand = cast(int) (drand48() * size);
|
||||
int rnd = rand_int(j);
|
||||
assert(rnd >=0 && rnd < size_);
|
||||
swap(vind[j-1], vind[rnd]);
|
||||
}
|
||||
trees[i] = NULL;
|
||||
divideTree(&trees[i], 0, size_ - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void saveIndex(FILE* stream)
|
||||
{
|
||||
save_header(stream, *this);
|
||||
save_value(stream, numTrees);
|
||||
for (int i=0;i<numTrees;++i) {
|
||||
save_tree(stream, trees[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loadIndex(FILE* stream)
|
||||
{
|
||||
IndexHeader header = load_header(stream);
|
||||
|
||||
if (header.rows!=size() || header.cols!=veclen()) {
|
||||
throw FLANNException("The index saved belongs to a different dataset");
|
||||
}
|
||||
load_value(stream, numTrees);
|
||||
|
||||
if (trees!=NULL) {
|
||||
delete[] trees;
|
||||
}
|
||||
trees = new Tree[numTrees];
|
||||
for (int i=0;i<numTrees;++i) {
|
||||
load_tree(stream,trees[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns size of index.
|
||||
*/
|
||||
int size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of an index feature.
|
||||
*/
|
||||
int veclen() const
|
||||
{
|
||||
return veclen_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the inde memory usage
|
||||
* Returns: memory used by the index
|
||||
*/
|
||||
int usedMemory() const
|
||||
{
|
||||
return pool.usedMemory+pool.wastedMemory+dataset.rows*sizeof(int); // pool memory and vind array memory
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find set of nearest neighbors to vec. Their indices are stored inside
|
||||
* the result object.
|
||||
*
|
||||
* Params:
|
||||
* result = the result object in which the indices of the nearest-neighbors are stored
|
||||
* vec = the vector for which to search the nearest neighbors
|
||||
* maxCheck = the maximum number of restarts (in a best-bin-first manner)
|
||||
*/
|
||||
void findNeighbors(ResultSet& result, const float* vec, const SearchParams& searchParams)
|
||||
{
|
||||
int maxChecks = searchParams.checks;
|
||||
|
||||
if (maxChecks<0) {
|
||||
getExactNeighbors(result, vec);
|
||||
} else {
|
||||
getNeighbors(result, vec, maxChecks);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void continueSearch(ResultSet& result, float* vec, int maxCheck)
|
||||
{
|
||||
BranchSt branch;
|
||||
|
||||
int checkCount = 0;
|
||||
|
||||
/* Keep searching other branches from heap until finished. */
|
||||
while ( heap->popMin(branch) && (checkCount < maxCheck || !result.full() )) {
|
||||
searchLevel(result, vec, branch.node,branch.mindistsq, checkCount, maxCheck);
|
||||
}
|
||||
|
||||
assert(result.full());
|
||||
}
|
||||
|
||||
|
||||
// Params estimateSearchParams(float precision, Dataset<float>* testset = NULL)
|
||||
// {
|
||||
// Params params;
|
||||
//
|
||||
// return params;
|
||||
// }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void save_tree(FILE* stream, Tree tree)
|
||||
{
|
||||
save_value(stream, *tree);
|
||||
if (tree->child1!=NULL) {
|
||||
save_tree(stream, tree->child1);
|
||||
}
|
||||
if (tree->child2!=NULL) {
|
||||
save_tree(stream, tree->child2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void load_tree(FILE* stream, Tree& tree)
|
||||
{
|
||||
tree = pool.allocate<TreeSt>();
|
||||
load_value(stream, *tree);
|
||||
if (tree->child1!=NULL) {
|
||||
load_tree(stream, tree->child1);
|
||||
}
|
||||
if (tree->child2!=NULL) {
|
||||
load_tree(stream, tree->child2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a tree node that subdivides the list of vecs from vind[first]
|
||||
* to vind[last]. The routine is called recursively on each sublist.
|
||||
* Place a pointer to this new tree node in the location pTree.
|
||||
*
|
||||
* Params: pTree = the new node to create
|
||||
* first = index of the first vector
|
||||
* last = index of the last vector
|
||||
*/
|
||||
void divideTree(Tree* pTree, int first, int last)
|
||||
{
|
||||
Tree node;
|
||||
|
||||
node = pool.allocate<TreeSt>(); // allocate memory
|
||||
*pTree = node;
|
||||
|
||||
/* If only one exemplar remains, then make this a leaf node. */
|
||||
if (first == last) {
|
||||
node->child1 = node->child2 = NULL; /* Mark as leaf node. */
|
||||
node->divfeat = vind[first]; /* Store index of this vec. */
|
||||
} else {
|
||||
chooseDivision(node, first, last);
|
||||
subdivide(node, first, last);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Choose which feature to use in order to subdivide this set of vectors.
|
||||
* Make a random choice among those with the highest variance, and use
|
||||
* its variance as the threshold value.
|
||||
*/
|
||||
void chooseDivision(Tree node, int first, int last)
|
||||
{
|
||||
memset(mean,0,veclen_*sizeof(float));
|
||||
memset(var,0,veclen_*sizeof(float));
|
||||
|
||||
/* Compute mean values. Only the first SAMPLE_MEAN values need to be
|
||||
sampled to get a good estimate.
|
||||
*/
|
||||
int end = min(first + SAMPLE_MEAN, last);
|
||||
int count = end - first + 1;
|
||||
for (int j = first; j <= end; ++j) {
|
||||
float* v = dataset[vind[j]];
|
||||
for (int k=0; k<veclen_; ++k) {
|
||||
mean[k] += v[k];
|
||||
}
|
||||
}
|
||||
for (int k=0; k<veclen_; ++k) {
|
||||
mean[k] /= count;
|
||||
}
|
||||
|
||||
/* Compute variances (no need to divide by count). */
|
||||
for (int j = first; j <= end; ++j) {
|
||||
float* v = dataset[vind[j]];
|
||||
for (int k=0; k<veclen_; ++k) {
|
||||
float dist = v[k] - mean[k];
|
||||
var[k] += dist * dist;
|
||||
}
|
||||
}
|
||||
/* Select one of the highest variance indices at random. */
|
||||
node->divfeat = selectDivision(var);
|
||||
node->divval = mean[node->divfeat];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Select the top RAND_DIM largest values from v and return the index of
|
||||
* one of these selected at random.
|
||||
*/
|
||||
int selectDivision(float* v)
|
||||
{
|
||||
int num = 0;
|
||||
int topind[RAND_DIM];
|
||||
|
||||
/* Create a list of the indices of the top RAND_DIM values. */
|
||||
for (int i = 0; i < veclen_; ++i) {
|
||||
if (num < RAND_DIM || v[i] > v[topind[num-1]]) {
|
||||
/* Put this element at end of topind. */
|
||||
if (num < RAND_DIM) {
|
||||
topind[num++] = i; /* Add to list. */
|
||||
}
|
||||
else {
|
||||
topind[num-1] = i; /* Replace last element. */
|
||||
}
|
||||
/* Bubble end value down to right location by repeated swapping. */
|
||||
int j = num - 1;
|
||||
while (j > 0 && v[topind[j]] > v[topind[j-1]]) {
|
||||
swap(topind[j], topind[j-1]);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Select a random integer in range [0,num-1], and return that index. */
|
||||
// int rand = cast(int) (drand48() * num);
|
||||
int rnd = rand_int(num);
|
||||
assert(rnd >=0 && rnd < num);
|
||||
return topind[rnd];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subdivide the list of exemplars using the feature and division
|
||||
* value given in this node. Call divideTree recursively on each list.
|
||||
*/
|
||||
void subdivide(Tree node, int first, int last)
|
||||
{
|
||||
/* Move vector indices for left subtree to front of list. */
|
||||
int i = first;
|
||||
int j = last;
|
||||
while (i <= j) {
|
||||
int ind = vind[i];
|
||||
float val = dataset[ind][node->divfeat];
|
||||
if (val < node->divval) {
|
||||
++i;
|
||||
} else {
|
||||
/* Move to end of list by swapping vind i and j. */
|
||||
swap(vind[i], vind[j]);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
/* If either list is empty, it means we have hit the unlikely case
|
||||
in which all remaining features are identical. Split in the middle
|
||||
to maintain a balanced tree.
|
||||
*/
|
||||
if ( (i == first) || (i == last+1)) {
|
||||
i = (first+last+1)/2;
|
||||
}
|
||||
|
||||
divideTree(& node->child1, first, i - 1);
|
||||
divideTree(& node->child2, i, last);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Performs an exact nearest neighbor search. The exact search performs a full
|
||||
* traversal of the tree.
|
||||
*/
|
||||
void getExactNeighbors(ResultSet& result, const float* vec)
|
||||
{
|
||||
checkID -= 1; /* Set a different unique ID for each search. */
|
||||
|
||||
if (numTrees > 1) {
|
||||
fprintf(stderr,"It doesn't make any sense to use more than one tree for exact search");
|
||||
}
|
||||
if (numTrees>0) {
|
||||
searchLevelExact(result, vec, trees[0], 0.0);
|
||||
}
|
||||
assert(result.full());
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the approximate nearest-neighbor search. The search is approximate
|
||||
* because the tree traversal is abandoned after a given number of descends in
|
||||
* the tree.
|
||||
*/
|
||||
void getNeighbors(ResultSet& result, const float* vec, int maxCheck)
|
||||
{
|
||||
int i;
|
||||
BranchSt branch;
|
||||
|
||||
int checkCount = 0;
|
||||
heap->clear();
|
||||
checkID -= 1; /* Set a different unique ID for each search. */
|
||||
|
||||
/* Search once through each tree down to root. */
|
||||
for (i = 0; i < numTrees; ++i) {
|
||||
searchLevel(result, vec, trees[i], 0.0, checkCount, maxCheck);
|
||||
}
|
||||
|
||||
/* Keep searching other branches from heap until finished. */
|
||||
while ( heap->popMin(branch) && (checkCount < maxCheck || !result.full() )) {
|
||||
searchLevel(result, vec, branch.node,branch.mindistsq, checkCount, maxCheck);
|
||||
}
|
||||
|
||||
assert(result.full());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Search starting from a given node of the tree. Based on any mismatches at
|
||||
* higher levels, all exemplars below this level must have a distance of
|
||||
* at least "mindistsq".
|
||||
*/
|
||||
void searchLevel(ResultSet& result, const float* vec, Tree node, float mindistsq, int& checkCount, int maxCheck)
|
||||
{
|
||||
if (result.worstDist()<mindistsq) {
|
||||
// printf("Ignoring branch, too far\n");
|
||||
return;
|
||||
}
|
||||
|
||||
float val, diff;
|
||||
Tree bestChild, otherChild;
|
||||
|
||||
/* If this is a leaf node, then do check and return. */
|
||||
if (node->child1 == NULL && node->child2 == NULL) {
|
||||
|
||||
/* Do not check same node more than once when searching multiple trees.
|
||||
Once a vector is checked, we set its location in vind to the
|
||||
current checkID.
|
||||
*/
|
||||
if (vind[node->divfeat] == checkID || checkCount>=maxCheck) {
|
||||
if (result.full()) return;
|
||||
}
|
||||
checkCount++;
|
||||
vind[node->divfeat] = checkID;
|
||||
|
||||
result.addPoint(dataset[node->divfeat],node->divfeat);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Which child branch should be taken first? */
|
||||
val = vec[node->divfeat];
|
||||
diff = val - node->divval;
|
||||
bestChild = (diff < 0) ? node->child1 : node->child2;
|
||||
otherChild = (diff < 0) ? node->child2 : node->child1;
|
||||
|
||||
/* Create a branch record for the branch not taken. Add distance
|
||||
of this feature boundary (we don't attempt to correct for any
|
||||
use of this feature in a parent node, which is unlikely to
|
||||
happen and would have only a small effect). Don't bother
|
||||
adding more branches to heap after halfway point, as cost of
|
||||
adding exceeds their value.
|
||||
*/
|
||||
|
||||
float new_distsq = flann_dist(&val, &val+1, &node->divval, mindistsq);
|
||||
// if (2 * checkCount < maxCheck || !result.full()) {
|
||||
if (new_distsq < result.worstDist() || !result.full()) {
|
||||
heap->insert( BranchSt::make_branch(otherChild, new_distsq) );
|
||||
}
|
||||
|
||||
/* Call recursively to search next level down. */
|
||||
searchLevel(result, vec, bestChild, mindistsq, checkCount, maxCheck);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an exact search in the tree starting from a node.
|
||||
*/
|
||||
void searchLevelExact(ResultSet& result, const float* vec, Tree node, float mindistsq)
|
||||
{
|
||||
if (mindistsq>result.worstDist()) {
|
||||
return;
|
||||
}
|
||||
|
||||
float val, diff;
|
||||
Tree bestChild, otherChild;
|
||||
|
||||
/* If this is a leaf node, then do check and return. */
|
||||
if (node->child1 == NULL && node->child2 == NULL) {
|
||||
|
||||
/* Do not check same node more than once when searching multiple trees.
|
||||
Once a vector is checked, we set its location in vind to the
|
||||
current checkID.
|
||||
*/
|
||||
if (vind[node->divfeat] == checkID)
|
||||
return;
|
||||
vind[node->divfeat] = checkID;
|
||||
|
||||
result.addPoint(dataset[node->divfeat],node->divfeat);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Which child branch should be taken first? */
|
||||
val = vec[node->divfeat];
|
||||
diff = val - node->divval;
|
||||
bestChild = (diff < 0) ? node->child1 : node->child2;
|
||||
otherChild = (diff < 0) ? node->child2 : node->child1;
|
||||
|
||||
|
||||
/* Call recursively to search next level down. */
|
||||
searchLevelExact(result, vec, bestChild, mindistsq);
|
||||
float new_distsq = flann_dist(&val, &val+1, &node->divval, mindistsq);
|
||||
searchLevelExact(result, vec, otherChild, new_distsq);
|
||||
}
|
||||
|
||||
}; // class KDTree
|
||||
|
||||
}
|
||||
|
||||
#endif //KDTREE_H
|
1119
3rdparty/flann/algorithms/kmeans_index.h
vendored
Normal file
1119
3rdparty/flann/algorithms/kmeans_index.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
105
3rdparty/flann/algorithms/linear_index.h
vendored
Normal file
105
3rdparty/flann/algorithms/linear_index.h
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef LINEARSEARCH_H
|
||||
#define LINEARSEARCH_H
|
||||
|
||||
#include "constants.h"
|
||||
#include "nn_index.h"
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
class LinearIndex : public NNIndex {
|
||||
|
||||
const Matrix<float> dataset;
|
||||
|
||||
public:
|
||||
|
||||
LinearIndex(const Matrix<float>& inputData, const LinearIndexParams& params = LinearIndexParams() ) : dataset(inputData)
|
||||
{
|
||||
}
|
||||
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return LINEAR;
|
||||
}
|
||||
|
||||
|
||||
int size() const
|
||||
{
|
||||
return dataset.rows;
|
||||
}
|
||||
|
||||
int veclen() const
|
||||
{
|
||||
return dataset.cols;
|
||||
}
|
||||
|
||||
|
||||
int usedMemory() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void buildIndex()
|
||||
{
|
||||
/* nothing to do here for linear search */
|
||||
}
|
||||
|
||||
void saveIndex(FILE* /*stream*/)
|
||||
{
|
||||
/* nothing to do here for linear search */
|
||||
}
|
||||
|
||||
|
||||
void loadIndex(FILE* /*stream*/)
|
||||
{
|
||||
/* nothing to do here for linear search */
|
||||
}
|
||||
|
||||
void findNeighbors(ResultSet& resultSet, const float* /*vec*/, const SearchParams& /*searchParams*/)
|
||||
{
|
||||
for (int i=0;i<dataset.rows;++i) {
|
||||
resultSet.addPoint(dataset[i],i);
|
||||
}
|
||||
}
|
||||
|
||||
// Params estimateSearchParams(float precision, Matrix<float>* testset = NULL)
|
||||
// {
|
||||
// Params params;
|
||||
// return params;
|
||||
// }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LINEARSEARCH_H
|
109
3rdparty/flann/algorithms/nn_index.h
vendored
Normal file
109
3rdparty/flann/algorithms/nn_index.h
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef NNINDEX_H
|
||||
#define NNINDEX_H
|
||||
|
||||
#include "flann.hpp"
|
||||
#include "constants.h"
|
||||
#include "common.h"
|
||||
#include "matrix.h"
|
||||
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
class ResultSet;
|
||||
|
||||
/**
|
||||
* Nearest-neighbor index base class
|
||||
*/
|
||||
class NNIndex
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~NNIndex() {};
|
||||
|
||||
/**
|
||||
Method responsible with building the index.
|
||||
*/
|
||||
virtual void buildIndex() = 0;
|
||||
|
||||
/**
|
||||
Saves the index to a stream
|
||||
*/
|
||||
virtual void saveIndex(FILE* stream) = 0;
|
||||
|
||||
/**
|
||||
Loads the index from a stream
|
||||
*/
|
||||
virtual void loadIndex(FILE* stream) = 0;
|
||||
|
||||
/**
|
||||
Method that searches for nearest-neighbors
|
||||
*/
|
||||
virtual void findNeighbors(ResultSet& result, const float* vec, const SearchParams& searchParams) = 0;
|
||||
|
||||
/**
|
||||
Number of features in this index.
|
||||
*/
|
||||
virtual int size() const = 0;
|
||||
|
||||
/**
|
||||
The length of each vector in this index.
|
||||
*/
|
||||
virtual int veclen() const = 0;
|
||||
|
||||
/**
|
||||
The amount of memory (in bytes) this index uses.
|
||||
*/
|
||||
virtual int usedMemory() const = 0;
|
||||
|
||||
/**
|
||||
* Algorithm name
|
||||
*/
|
||||
virtual flann_algorithm_t getType() const = 0;
|
||||
|
||||
/**
|
||||
Estimates the search parameters required in order to get a certain precision.
|
||||
If testset is not given it uses cross-validation.
|
||||
*/
|
||||
// virtual Params estimateSearchParams(float precision, Matrix<float>* testset = NULL) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //NNINDEX_H
|
Reference in New Issue
Block a user