Commit 9153018b authored by Marius Muja's avatar Marius Muja

Updated FLANN

parent 2e54482d
...@@ -27,50 +27,129 @@ ...@@ -27,50 +27,129 @@
*************************************************************************/ *************************************************************************/
#ifndef _OPENCV_ALL_INDICES_H_ #ifndef OPENCV_FLANN_ALL_INDICES_H_
#define _OPENCV_ALL_INDICES_H_ #define OPENCV_FLANN_ALL_INDICES_H_
#include "opencv2/flann/general.h" #include "general.h"
#include "opencv2/flann/nn_index.h" #include "nn_index.h"
#include "opencv2/flann/kdtree_index.h" #include "kdtree_index.h"
#include "opencv2/flann/kmeans_index.h" #include "kdtree_single_index.h"
#include "opencv2/flann/composite_index.h" #include "kmeans_index.h"
#include "opencv2/flann/linear_index.h" #include "composite_index.h"
#include "opencv2/flann/autotuned_index.h" #include "linear_index.h"
#include "hierarchical_clustering_index.h"
#include "lsh_index.h"
#include "autotuned_index.h"
namespace cvflann
namespace cvflann
{
template<typename KDTreeCapability, typename VectorSpace, typename Distance>
struct index_creator
{
static NNIndex<Distance>* create(const Matrix<typename Distance::ElementType>& dataset, const IndexParams& params, const Distance& distance)
{
flann_algorithm_t index_type = get_param<flann_algorithm_t>(params, "algorithm");
NNIndex<Distance>* nnIndex;
switch (index_type) {
case FLANN_INDEX_LINEAR:
nnIndex = new LinearIndex<Distance>(dataset, params, distance);
break;
case FLANN_INDEX_KDTREE_SINGLE:
nnIndex = new KDTreeSingleIndex<Distance>(dataset, params, distance);
break;
case FLANN_INDEX_KDTREE:
nnIndex = new KDTreeIndex<Distance>(dataset, params, distance);
break;
case FLANN_INDEX_KMEANS:
nnIndex = new KMeansIndex<Distance>(dataset, params, distance);
break;
case FLANN_INDEX_COMPOSITE:
nnIndex = new CompositeIndex<Distance>(dataset, params, distance);
break;
case FLANN_INDEX_AUTOTUNED:
nnIndex = new AutotunedIndex<Distance>(dataset, params, distance);
break;
case FLANN_INDEX_HIERARCHICAL:
nnIndex = new HierarchicalClusteringIndex<Distance>(dataset, params, distance);
break;
case FLANN_INDEX_LSH:
nnIndex = new LshIndex<Distance>(dataset, params, distance);
break;
default:
throw FLANNException("Unknown index type");
}
return nnIndex;
}
};
template<typename VectorSpace, typename Distance>
struct index_creator<False,VectorSpace,Distance>
{ {
static NNIndex<Distance>* create(const Matrix<typename Distance::ElementType>& dataset, const IndexParams& params, const Distance& distance)
{
flann_algorithm_t index_type = get_param<flann_algorithm_t>(params, "algorithm");
template<typename T> NNIndex<Distance>* nnIndex;
NNIndex<T>* create_index_by_type(const Matrix<T>& dataset, const IndexParams& params) switch (index_type) {
case FLANN_INDEX_LINEAR:
nnIndex = new LinearIndex<Distance>(dataset, params, distance);
break;
case FLANN_INDEX_KMEANS:
nnIndex = new KMeansIndex<Distance>(dataset, params, distance);
break;
case FLANN_INDEX_HIERARCHICAL:
nnIndex = new HierarchicalClusteringIndex<Distance>(dataset, params, distance);
break;
case FLANN_INDEX_LSH:
nnIndex = new LshIndex<Distance>(dataset, params, distance);
break;
default:
throw FLANNException("Unknown index type");
}
return nnIndex;
}
};
template<typename Distance>
struct index_creator<False,False,Distance>
{ {
flann_algorithm_t index_type = params.getIndexType(); static NNIndex<Distance>* create(const Matrix<typename Distance::ElementType>& dataset, const IndexParams& params, const Distance& distance)
{
NNIndex<T>* nnIndex; flann_algorithm_t index_type = get_param<flann_algorithm_t>(params, "algorithm");
switch (index_type) {
case FLANN_INDEX_LINEAR: NNIndex<Distance>* nnIndex;
nnIndex = new LinearIndex<T>(dataset, (const LinearIndexParams&)params); switch (index_type) {
break; case FLANN_INDEX_LINEAR:
case FLANN_INDEX_KDTREE: nnIndex = new LinearIndex<Distance>(dataset, params, distance);
nnIndex = new KDTreeIndex<T>(dataset, (const KDTreeIndexParams&)params); break;
break; case FLANN_INDEX_HIERARCHICAL:
case FLANN_INDEX_KMEANS: nnIndex = new HierarchicalClusteringIndex<Distance>(dataset, params, distance);
nnIndex = new KMeansIndex<T>(dataset, (const KMeansIndexParams&)params); break;
break; case FLANN_INDEX_LSH:
case FLANN_INDEX_COMPOSITE: nnIndex = new LshIndex<Distance>(dataset, params, distance);
nnIndex = new CompositeIndex<T>(dataset, (const CompositeIndexParams&) params); break;
break; default:
case FLANN_INDEX_AUTOTUNED: throw FLANNException("Unknown index type");
nnIndex = new AutotunedIndex<T>(dataset, (const AutotunedIndexParams&) params); }
break;
default: return nnIndex;
throw FLANNException("Unknown index type"); }
} };
return nnIndex; template<typename Distance>
NNIndex<Distance>* create_index_by_type(const Matrix<typename Distance::ElementType>& dataset, const IndexParams& params, const Distance& distance)
{
return index_creator<typename Distance::is_kdtree_distance,
typename Distance::is_vector_space_distance,
Distance>::create(dataset, params,distance);
} }
} //namespace cvflann }
#endif /* _OPENCV_ALL_INDICES_H_ */ #endif /* OPENCV_FLANN_ALL_INDICES_H_ */
...@@ -28,12 +28,13 @@ ...@@ -28,12 +28,13 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*************************************************************************/ *************************************************************************/
#ifndef _OPENCV_ALLOCATOR_H_ #ifndef OPENCV_FLANN_ALLOCATOR_H_
#define _OPENCV_ALLOCATOR_H_ #define OPENCV_FLANN_ALLOCATOR_H_
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
namespace cvflann namespace cvflann
{ {
...@@ -47,8 +48,8 @@ namespace cvflann ...@@ -47,8 +48,8 @@ namespace cvflann
template <typename T> template <typename T>
T* allocate(size_t count = 1) T* allocate(size_t count = 1)
{ {
T* mem = (T*) ::malloc(sizeof(T)*count); T* mem = (T*) ::malloc(sizeof(T)*count);
return mem; return mem;
} }
...@@ -70,118 +71,118 @@ T* allocate(size_t count = 1) ...@@ -70,118 +71,118 @@ T* allocate(size_t count = 1)
const size_t WORDSIZE=16; const size_t WORDSIZE=16;
const size_t BLOCKSIZE=8192; const size_t BLOCKSIZE=8192;
class CV_EXPORTS PooledAllocator class PooledAllocator
{ {
/* We maintain memory alignment to word boundaries by requiring that all /* We maintain memory alignment to word boundaries by requiring that all
allocations be in multiples of the machine wordsize. */ allocations be in multiples of the machine wordsize. */
/* Size of machine word in bytes. Must be power of 2. */ /* Size of machine word in bytes. Must be power of 2. */
/* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */ /* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */
int remaining; /* Number of bytes left in current block of storage. */ int remaining; /* Number of bytes left in current block of storage. */
void* base; /* Pointer to base of current block of storage. */ void* base; /* Pointer to base of current block of storage. */
void* loc; /* Current location in block to next allocate memory. */ void* loc; /* Current location in block to next allocate memory. */
int blocksize; int blocksize;
public: public:
int usedMemory; int usedMemory;
int wastedMemory; int wastedMemory;
/** /**
Default constructor. Initializes a new pool. Default constructor. Initializes a new pool.
*/ */
PooledAllocator(int blocksize = BLOCKSIZE) PooledAllocator(int blocksize = BLOCKSIZE)
{ {
this->blocksize = blocksize; this->blocksize = blocksize;
remaining = 0; remaining = 0;
base = NULL; base = NULL;
usedMemory = 0; usedMemory = 0;
wastedMemory = 0; wastedMemory = 0;
} }
/** /**
* Destructor. Frees all the memory allocated in this pool. * Destructor. Frees all the memory allocated in this pool.
*/ */
~PooledAllocator() ~PooledAllocator()
{ {
void *prev; void* prev;
while (base != NULL) { while (base != NULL) {
prev = *((void **) base); /* Get pointer to prev block. */ prev = *((void**) base); /* Get pointer to prev block. */
::free(base); ::free(base);
base = prev; base = prev;
} }
} }
/** /**
* Returns a pointer to a piece of new memory of the given size in bytes * Returns a pointer to a piece of new memory of the given size in bytes
* allocated from the pool. * allocated from the pool.
*/ */
void* allocateBytes(int size) void* allocateMemory(int size)
{ {
int blocksize; int blocksize;
/* Round size up to a multiple of wordsize. The following expression /* Round size up to a multiple of wordsize. The following expression
only works for WORDSIZE that is a power of 2, by masking last bits of only works for WORDSIZE that is a power of 2, by masking last bits of
incremented size to zero. incremented size to zero.
*/ */
size = (size + (WORDSIZE - 1)) & ~(WORDSIZE - 1); size = (size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
/* Check whether a new block must be allocated. Note that the first word /* Check whether a new block must be allocated. Note that the first word
of a block is reserved for a pointer to the previous block. of a block is reserved for a pointer to the previous block.
*/ */
if (size > remaining) { if (size > remaining) {
wastedMemory += remaining; wastedMemory += remaining;
/* Allocate new storage. */ /* Allocate new storage. */
blocksize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ? blocksize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ?
size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE; size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE;
// use the standard C malloc to allocate memory // use the standard C malloc to allocate memory
void* m = ::malloc(blocksize); void* m = ::malloc(blocksize);
if (!m) { if (!m) {
fprintf(stderr,"Failed to allocate memory.\n"); fprintf(stderr,"Failed to allocate memory.\n");
exit(1); return NULL;
} }
/* Fill first word of new block with pointer to previous block. */ /* Fill first word of new block with pointer to previous block. */
((void **) m)[0] = base; ((void**) m)[0] = base;
base = m; base = m;
int shift = 0; int shift = 0;
//int shift = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1); //int shift = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1);
remaining = blocksize - sizeof(void*) - shift; remaining = blocksize - sizeof(void*) - shift;
loc = ((char*)m + sizeof(void*) + shift); loc = ((char*)m + sizeof(void*) + shift);
} }
void* rloc = loc; void* rloc = loc;
loc = (char*)loc + size; loc = (char*)loc + size;
remaining -= size; remaining -= size;
usedMemory += size; usedMemory += size;
return rloc; return rloc;
} }
/** /**
* Allocates (using this pool) a generic type T. * Allocates (using this pool) a generic type T.
* *
* Params: * Params:
* count = number of instances to allocate. * count = number of instances to allocate.
* Returns: pointer (of type T*) to memory buffer * Returns: pointer (of type T*) to memory buffer
*/ */
template <typename T> template <typename T>
T* allocate(size_t count = 1) T* allocate(size_t count = 1)
{ {
T* mem = (T*) this->allocateBytes((int)(sizeof(T)*count)); T* mem = (T*) this->allocateMemory((int)(sizeof(T)*count));
return mem; return mem;
} }
}; };
} // namespace cvflann }
#endif //_OPENCV_ALLOCATOR_H_ #endif //OPENCV_FLANN_ALLOCATOR_H_
#ifndef OPENCV_FLANN_ANY_H_
#define OPENCV_FLANN_ANY_H_
/*
* (C) Copyright Christopher Diggins 2005-2011
* (C) Copyright Pablo Aguilar 2005
* (C) Copyright Kevlin Henney 2001
*
* Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt
*
* Adapted for FLANN by Marius Muja
*/
#include <stdexcept>
#include <ostream>
namespace cdiggins
{
namespace anyimpl
{
struct bad_any_cast
{
};
struct empty_any
{
};
struct base_any_policy
{
virtual void static_delete(void** x) = 0;
virtual void copy_from_value(void const* src, void** dest) = 0;
virtual void clone(void* const* src, void** dest) = 0;
virtual void move(void* const* src, void** dest) = 0;
virtual void* get_value(void** src) = 0;
virtual size_t get_size() = 0;
virtual void print(std::ostream& out, void* const* src) = 0;
};
template<typename T>
struct typed_base_any_policy : base_any_policy
{
virtual size_t get_size() { return sizeof(T); }
};
template<typename T>
struct small_any_policy : typed_base_any_policy<T>
{
virtual void static_delete(void**) { }
virtual void copy_from_value(void const* src, void** dest)
{
new (dest) T(* reinterpret_cast<T const*>(src));
}
virtual void clone(void* const* src, void** dest) { *dest = *src; }
virtual void move(void* const* src, void** dest) { *dest = *src; }
virtual void* get_value(void** src) { return reinterpret_cast<void*>(src); }
virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(src); }
};
template<typename T>
struct big_any_policy : typed_base_any_policy<T>
{
virtual void static_delete(void** x)
{
if (* x) delete (* reinterpret_cast<T**>(x)); *x = NULL;
}
virtual void copy_from_value(void const* src, void** dest)
{
*dest = new T(*reinterpret_cast<T const*>(src));
}
virtual void clone(void* const* src, void** dest)
{
*dest = new T(**reinterpret_cast<T* const*>(src));
}
virtual void move(void* const* src, void** dest)
{
(*reinterpret_cast<T**>(dest))->~T();
**reinterpret_cast<T**>(dest) = **reinterpret_cast<T* const*>(src);
}
virtual void* get_value(void** src) { return *src; }
virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(*src); }
};
template<typename T>
struct choose_policy
{
typedef big_any_policy<T> type;
};
template<typename T>
struct choose_policy<T*>
{
typedef small_any_policy<T*> type;
};
struct any;
/// Choosing the policy for an any type is illegal, but should never happen.
/// This is designed to throw a compiler error.
template<>
struct choose_policy<any>
{
typedef void type;
};
/// Specializations for small types.
#define SMALL_POLICY(TYPE) \
template<> \
struct choose_policy<TYPE> { typedef small_any_policy<TYPE> type; \
};
SMALL_POLICY(signed char);
SMALL_POLICY(unsigned char);
SMALL_POLICY(signed short);
SMALL_POLICY(unsigned short);
SMALL_POLICY(signed int);
SMALL_POLICY(unsigned int);
SMALL_POLICY(signed long);
SMALL_POLICY(unsigned long);
SMALL_POLICY(float);
SMALL_POLICY(bool);
#undef SMALL_POLICY
/// This function will return a different policy for each type.
template<typename T>
base_any_policy* get_policy()
{
static typename choose_policy<T>::type policy;
return &policy;
}
} // namespace anyimpl
struct any
{
private:
// fields
anyimpl::base_any_policy* policy;
void* object;
public:
/// Initializing constructor.
template <typename T>
any(const T& x)
: policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
{
assign(x);
}
/// Empty constructor.
any()
: policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
{ }
/// Special initializing constructor for string literals.
any(const char* x)
: policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
{
assign(x);
}
/// Copy constructor.
any(const any& x)
: policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
{
assign(x);
}
/// Destructor.
~any()
{
policy->static_delete(&object);
}
/// Assignment function from another any.
any& assign(const any& x)
{
reset();
policy = x.policy;
policy->clone(&x.object, &object);
return *this;
}
/// Assignment function.
template <typename T>
any& assign(const T& x)
{
reset();
policy = anyimpl::get_policy<T>();
policy->copy_from_value(&x, &object);
return *this;
}
/// Assignment operator.
template<typename T>
any& operator=(const T& x)
{
return assign(x);
}
/// Assignment operator, specialed for literal strings.
/// They have types like const char [6] which don't work as expected.
any& operator=(const char* x)
{
return assign(x);
}
/// Utility functions
any& swap(any& x)
{
std::swap(policy, x.policy);
std::swap(object, x.object);
return *this;
}
/// Cast operator. You can only cast to the original type.
template<typename T>
T& cast()
{
if (policy != anyimpl::get_policy<T>()) throw anyimpl::bad_any_cast();
T* r = reinterpret_cast<T*>(policy->get_value(&object));
return *r;
}
/// Cast operator. You can only cast to the original type.
template<typename T>
const T& cast() const
{
if (policy != anyimpl::get_policy<T>()) throw anyimpl::bad_any_cast();
T* r = reinterpret_cast<T*>(policy->get_value((void**)&object));
return *r;
}
/// Returns true if the any contains no value.
bool empty() const
{
return policy == anyimpl::get_policy<anyimpl::empty_any>();
}
/// Frees any allocated memory, and sets the value to NULL.
void reset()
{
policy->static_delete(&object);
policy = anyimpl::get_policy<anyimpl::empty_any>();
}
/// Returns true if the two types are the same.
bool compatible(const any& x) const
{
return policy == x.policy;
}
/// Returns if the type is compatible with the policy
template<typename T>
bool has_type()
{
return policy == anyimpl::get_policy<T>();
}
friend std::ostream& operator <<(std::ostream& out, const any& any_val);
};
inline std::ostream& operator <<(std::ostream& out, const any& any_val)
{
any_val.policy->print(out,&any_val.object);
return out;
}
}
#endif // OPENCV_FLANN_ANY_H_
...@@ -28,135 +28,167 @@ ...@@ -28,135 +28,167 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*************************************************************************/ *************************************************************************/
#ifndef _OPENCV_COMPOSITETREE_H_ #ifndef OPENCV_FLANN_COMPOSITE_INDEX_H_
#define _OPENCV_COMPOSITETREE_H_ #define OPENCV_FLANN_COMPOSITE_INDEX_H_
#include "opencv2/flann/general.h" #include "general.h"
#include "opencv2/flann/nn_index.h" #include "nn_index.h"
#include "kdtree_index.h"
#include "kmeans_index.h"
namespace cvflann namespace cvflann
{ {
/**
struct CompositeIndexParams : public IndexParams { * Index parameters for the CompositeIndex.
CompositeIndexParams(int trees_ = 4, int branching_ = 32, int iterations_ = 11, */
flann_centers_init_t centers_init_ = FLANN_CENTERS_RANDOM, float cb_index_ = 0.2 ) : struct CompositeIndexParams : public IndexParams
IndexParams(FLANN_INDEX_COMPOSITE), {
trees(trees_), CompositeIndexParams(int trees = 4, int branching = 32, int iterations = 11,
branching(branching_), flann_centers_init_t centers_init = FLANN_CENTERS_RANDOM, float cb_index = 0.2 )
iterations(iterations_), {
centers_init(centers_init_), (*this)["algorithm"] = FLANN_INDEX_KMEANS;
cb_index(cb_index_) {}; // number of randomized trees to use (for kdtree)
(*this)["trees"] = trees;
int trees; // number of randomized trees to use (for kdtree) // branching factor
int branching; // branching factor (for kmeans tree) (*this)["branching"] = branching;
int iterations; // max iterations to perform in one kmeans clustering (kmeans tree) // max iterations to perform in one kmeans clustering (kmeans tree)
flann_centers_init_t centers_init; // algorithm used for picking the initial cluster centers for kmeans tree (*this)["iterations"] = iterations;
float cb_index; // cluster boundary index. Used when searching the kmeans tree // algorithm used for picking the initial cluster centers for kmeans tree
(*this)["centers_init"] = centers_init;
void print() const // cluster boundary index. Used when searching the kmeans tree
{ (*this)["cb_index"] = cb_index;
logger().info("Index type: %d\n",(int)algorithm); }
logger().info("Trees: %d\n", trees);
logger().info("Branching: %d\n", branching);
logger().info("Iterations: %d\n", iterations);
logger().info("Centres initialisation: %d\n", centers_init);
logger().info("Cluster boundary weight: %g\n", cb_index);
}
}; };
/**
template <typename ELEM_TYPE, typename DIST_TYPE = typename DistType<ELEM_TYPE>::type > * This index builds a kd-tree index and a k-means index and performs nearest
class CompositeIndex : public NNIndex<ELEM_TYPE> * neighbour search both indexes. This gives a slight boost in search performance
* as some of the neighbours that are missed by one index are found by the other.
*/
template <typename Distance>
class CompositeIndex : public NNIndex<Distance>
{ {
KMeansIndex<ELEM_TYPE, DIST_TYPE>* kmeans;
KDTreeIndex<ELEM_TYPE, DIST_TYPE>* kdtree;
const Matrix<ELEM_TYPE> dataset;
const IndexParams& index_params;
CompositeIndex& operator=(const CompositeIndex&);
CompositeIndex(const CompositeIndex&);
public: public:
typedef typename Distance::ElementType ElementType;
typedef typename Distance::ResultType DistanceType;
/**
* Index constructor
* @param inputData dataset containing the points to index
* @param params Index parameters
* @param d Distance functor
* @return
*/
CompositeIndex(const Matrix<ElementType>& inputData, const IndexParams& params = CompositeIndexParams(),
Distance d = Distance()) : index_params_(params)
{
kdtree_index_ = new KDTreeIndex<Distance>(inputData, params, d);
kmeans_index_ = new KMeansIndex<Distance>(inputData, params, d);
CompositeIndex(const Matrix<ELEM_TYPE>& inputData, const CompositeIndexParams& params = CompositeIndexParams() ) : }
dataset(inputData), index_params(params)
{
KDTreeIndexParams kdtree_params(params.trees);
KMeansIndexParams kmeans_params(params.branching, params.iterations, params.centers_init, params.cb_index);
kdtree = new KDTreeIndex<ELEM_TYPE, DIST_TYPE>(inputData,kdtree_params);
kmeans = new KMeansIndex<ELEM_TYPE, DIST_TYPE>(inputData,kmeans_params);
}
virtual ~CompositeIndex() CompositeIndex(const CompositeIndex&);
{ CompositeIndex& operator=(const CompositeIndex&);
delete kdtree;
delete kmeans;
}
virtual ~CompositeIndex()
{
delete kdtree_index_;
delete kmeans_index_;
}
/**
* @return The index type
*/
flann_algorithm_t getType() const flann_algorithm_t getType() const
{ {
return FLANN_INDEX_COMPOSITE; return FLANN_INDEX_COMPOSITE;
} }
/**
* @return Size of the index
*/
size_t size() const size_t size() const
{ {
return dataset.rows; return kdtree_index_->size();
} }
size_t veclen() const
{
return dataset.cols;
}
int usedMemory() const /**
{ * \returns The dimensionality of the features in this index.
return kmeans->usedMemory()+kdtree->usedMemory(); */
} size_t veclen() const
{
return kdtree_index_->veclen();
}
void buildIndex() /**
{ * \returns The amount of memory (in bytes) used by the index.
logger().info("Building kmeans tree...\n"); */
kmeans->buildIndex(); int usedMemory() const
logger().info("Building kdtree tree...\n"); {
kdtree->buildIndex(); return kmeans_index_->usedMemory() + kdtree_index_->usedMemory();
} }
/**
* \brief Builds the index
*/
void buildIndex()
{
Logger::info("Building kmeans tree...\n");
kmeans_index_->buildIndex();
Logger::info("Building kdtree tree...\n");
kdtree_index_->buildIndex();
}
/**
* \brief Saves the index to a stream
* \param stream The stream to save the index to
*/
void saveIndex(FILE* stream) void saveIndex(FILE* stream)
{ {
kmeans->saveIndex(stream); kmeans_index_->saveIndex(stream);
kdtree->saveIndex(stream); kdtree_index_->saveIndex(stream);
} }
/**
* \brief Loads the index from a stream
* \param stream The stream from which the index is loaded
*/
void loadIndex(FILE* stream) void loadIndex(FILE* stream)
{ {
kmeans->loadIndex(stream); kmeans_index_->loadIndex(stream);
kdtree->loadIndex(stream); kdtree_index_->loadIndex(stream);
} }
void findNeighbors(ResultSet<ELEM_TYPE>& result, const ELEM_TYPE* vec, const SearchParams& searchParams) /**
{ * \returns The index parameters
kmeans->findNeighbors(result,vec,searchParams); */
kdtree->findNeighbors(result,vec,searchParams); IndexParams getParameters() const
} {
return index_params_;
}
/**
* \brief Method that searches for nearest-neighbours
*/
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
{
kmeans_index_->findNeighbors(result, vec, searchParams);
kdtree_index_->findNeighbors(result, vec, searchParams);
}
const IndexParams* getParameters() const private:
{ /** The k-means index */
return &index_params; KMeansIndex<Distance>* kmeans_index_;
}
/** The kd-tree index */
KDTreeIndex<Distance>* kdtree_index_;
/** The index parameters */
const IndexParams index_params_;
}; };
} // namespace cvflann }
#endif //_OPENCV_COMPOSITETREE_H_ #endif //OPENCV_FLANN_COMPOSITE_INDEX_H_
/***********************************************************************
* Software License Agreement (BSD License)
*
* Copyright 2008-2011 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
* Copyright 2008-2011 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
*
* 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 OPENCV_FLANN_CONFIG_H_
#define OPENCV_FLANN_CONFIG_H_
#define FLANN_VERSION "1.6.10"
#endif /* OPENCV_FLANN_CONFIG_H_ */
/***********************************************************************
* Software License Agreement (BSD License)
*
* Copyright 2008-2011 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
* Copyright 2008-2011 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
*
* 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 OPENCV_FLANN_DEFINES_H_
#define OPENCV_FLANN_DEFINES_H_
#include "config.h"
#ifdef WIN32
/* win32 dll export/import directives */
#ifdef FLANN_EXPORTS
#define FLANN_EXPORT __declspec(dllexport)
#elif defined(FLANN_STATIC)
#define FLANN_EXPORT
#else
#define FLANN_EXPORT __declspec(dllimport)
#endif
#else
/* unix needs nothing */
#define FLANN_EXPORT
#endif
#ifdef __GNUC__
#define FLANN_DEPRECATED __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define FLANN_DEPRECATED __declspec(deprecated)
#else
#pragma message("WARNING: You need to implement FLANN_DEPRECATED for this compiler")
#define FLANN_DEPRECATED
#endif
#if __amd64__ || __x86_64__ || _WIN64 || _M_X64
#define FLANN_PLATFORM_64_BIT
#else
#define FLANN_PLATFORM_32_BIT
#endif
#define FLANN_ARRAY_LEN(a) (sizeof(a)/sizeof(a[0]))
/* Nearest neighbour index algorithms */
enum flann_algorithm_t
{
FLANN_INDEX_LINEAR = 0,
FLANN_INDEX_KDTREE = 1,
FLANN_INDEX_KMEANS = 2,
FLANN_INDEX_COMPOSITE = 3,
FLANN_INDEX_KDTREE_SINGLE = 4,
FLANN_INDEX_HIERARCHICAL = 5,
FLANN_INDEX_LSH = 6,
FLANN_INDEX_SAVED = 254,
FLANN_INDEX_AUTOTUNED = 255,
// deprecated constants, should use the FLANN_INDEX_* ones instead
LINEAR = 0,
KDTREE = 1,
KMEANS = 2,
COMPOSITE = 3,
KDTREE_SINGLE = 4,
SAVED = 254,
AUTOTUNED = 255
};
enum flann_centers_init_t
{
FLANN_CENTERS_RANDOM = 0,
FLANN_CENTERS_GONZALES = 1,
FLANN_CENTERS_KMEANSPP = 2,
// deprecated constants, should use the FLANN_CENTERS_* ones instead
CENTERS_RANDOM = 0,
CENTERS_GONZALES = 1,
CENTERS_KMEANSPP = 2
};
enum flann_log_level_t
{
FLANN_LOG_NONE = 0,
FLANN_LOG_FATAL = 1,
FLANN_LOG_ERROR = 2,
FLANN_LOG_WARN = 3,
FLANN_LOG_INFO = 4,
};
enum flann_distance_t
{
FLANN_DIST_EUCLIDEAN = 1,
FLANN_DIST_L2 = 1,
FLANN_DIST_MANHATTAN = 2,
FLANN_DIST_L1 = 2,
FLANN_DIST_MINKOWSKI = 3,
FLANN_DIST_MAX = 4,
FLANN_DIST_HIST_INTERSECT = 5,
FLANN_DIST_HELLINGER = 6,
FLANN_DIST_CHI_SQUARE = 7,
FLANN_DIST_CS = 7,
FLANN_DIST_KULLBACK_LEIBLER = 8,
FLANN_DIST_KL = 8,
// deprecated constants, should use the FLANN_DIST_* ones instead
EUCLIDEAN = 1,
MANHATTAN = 2,
MINKOWSKI = 3,
MAX_DIST = 4,
HIST_INTERSECT = 5,
HELLINGER = 6,
CS = 7,
KL = 8,
KULLBACK_LEIBLER = 8
};
enum flann_datatype_t
{
FLANN_INT8 = 0,
FLANN_INT16 = 1,
FLANN_INT32 = 2,
FLANN_INT64 = 3,
FLANN_UINT8 = 4,
FLANN_UINT16 = 5,
FLANN_UINT32 = 6,
FLANN_UINT64 = 7,
FLANN_FLOAT32 = 8,
FLANN_FLOAT64 = 9
};
const int FLANN_CHECKS_UNLIMITED = -1;
const int FLANN_CHECKS_AUTOTUNED = -2;
#endif /* OPENCV_FLANN_DEFINES_H_ */
This diff is collapsed.
/***********************************************************************
* 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.
*************************************************************************/
/***********************************************************************
* Author: Vincent Rabaud
*************************************************************************/
#ifndef OPENCV_FLANN_DYNAMIC_BITSET_H_
#define OPENCV_FLANN_DYNAMIC_BITSET_H_
//#define FLANN_USE_BOOST 1
#if FLANN_USE_BOOST
#include <boost/dynamic_bitset.hpp>
typedef boost::dynamic_bitset<> DynamicBitset;
#else
#include <limits.h>
#include "dist.h"
/** Class re-implementing the boost version of it
* This helps not depending on boost, it also does not do the bound checks
* and has a way to reset a block for speed
*/
class DynamicBitset
{
public:
/** @param default constructor
*/
DynamicBitset()
{
}
/** @param only constructor we use in our code
* @param the size of the bitset (in bits)
*/
DynamicBitset(size_t size)
{
resize(size);
reset();
}
/** Sets all the bits to 0
*/
void clear()
{
std::fill(bitset_.begin(), bitset_.end(), 0);
}
/** @brief checks if the bitset is empty
* @return true if the bitset is empty
*/
bool empty() const
{
return bitset_.empty();
}
/** @param set all the bits to 0
*/
void reset()
{
std::fill(bitset_.begin(), bitset_.end(), 0);
}
/** @brief set one bit to 0
* @param
*/
void reset(size_t index)
{
bitset_[index / cell_bit_size_] &= ~(size_t(1) << (index % cell_bit_size_));
}
/** @brief sets a specific bit to 0, and more bits too
* This function is useful when resetting a given set of bits so that the
* whole bitset ends up being 0: if that's the case, we don't care about setting
* other bits to 0
* @param
*/
void reset_block(size_t index)
{
bitset_[index / cell_bit_size_] = 0;
}
/** @param resize the bitset so that it contains at least size bits
* @param size
*/
void resize(size_t size)
{
size_ = size;
bitset_.resize(size / cell_bit_size_ + 1);
}
/** @param set a bit to true
* @param index the index of the bit to set to 1
*/
void set(size_t index)
{
bitset_[index / cell_bit_size_] |= size_t(1) << (index % cell_bit_size_);
}
/** @param gives the number of contained bits
*/
size_t size() const
{
return size_;
}
/** @param check if a bit is set
* @param index the index of the bit to check
* @return true if the bit is set
*/
bool test(size_t index) const
{
return (bool)(bitset_[index / cell_bit_size_] & (size_t(1) << (index % cell_bit_size_)));
}
private:
std::vector<size_t> bitset_;
size_t size_;
static const unsigned int cell_bit_size_ = CHAR_BIT * sizeof(size_t);
};
#endif
#endif // OPENCV_FLANN_DYNAMIC_BITSET_H_
...@@ -28,119 +28,25 @@ ...@@ -28,119 +28,25 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*************************************************************************/ *************************************************************************/
#ifndef _OPENCV_GENERAL_H_ #ifndef OPENCV_FLANN_GENERAL_H_
#define _OPENCV_GENERAL_H_ #define OPENCV_FLANN_GENERAL_H_
#ifdef __cplusplus
#include "defines.h"
#include <stdexcept> #include <stdexcept>
#include <cassert> #include <cassert>
#include "opencv2/flann/object_factory.h"
#include "opencv2/flann/logger.h"
namespace cvflann {
#undef ARRAY_LEN
#define ARRAY_LEN(a) (sizeof(a)/sizeof(a[0]))
/* Nearest neighbour index algorithms */
enum flann_algorithm_t {
FLANN_INDEX_LINEAR = 0,
FLANN_INDEX_KDTREE = 1,
FLANN_INDEX_KMEANS = 2,
FLANN_INDEX_COMPOSITE = 3,
FLANN_INDEX_SAVED = 254,
FLANN_INDEX_AUTOTUNED = 255
};
enum flann_centers_init_t {
FLANN_CENTERS_RANDOM = 0,
FLANN_CENTERS_GONZALES = 1,
FLANN_CENTERS_KMEANSPP = 2
};
enum flann_distance_t {
FLANN_DIST_EUCLIDEAN = 1,
FLANN_DIST_L2 = 1,
FLANN_DIST_MANHATTAN = 2,
FLANN_DIST_L1 = 2,
FLANN_DIST_MINKOWSKI = 3,
FLANN_DIST_MAX = 4,
FLANN_DIST_HIST_INTERSECT = 5,
FLANN_DIST_HELLINGER = 6,
FLANN_DIST_CHI_SQUARE = 7,
FLANN_DIST_CS = 7,
FLANN_DIST_KULLBACK_LEIBLER = 8,
FLANN_DIST_KL = 8
};
enum flann_datatype_t {
FLANN_INT8 = 0,
FLANN_INT16 = 1,
FLANN_INT32 = 2,
FLANN_INT64 = 3,
FLANN_UINT8 = 4,
FLANN_UINT16 = 5,
FLANN_UINT32 = 6,
FLANN_UINT64 = 7,
FLANN_FLOAT32 = 8,
FLANN_FLOAT64 = 9
};
template <typename ELEM_TYPE>
struct DistType
{
typedef ELEM_TYPE type;
};
template <> namespace cvflann
struct DistType<unsigned char>
{ {
typedef float type;
};
template <> class FLANNException : public std::runtime_error
struct DistType<int>
{ {
typedef float type;
};
class FLANNException : public std::runtime_error {
public:
FLANNException(const char* message) : std::runtime_error(message) { }
FLANNException(const std::string& message) : std::runtime_error(message) { }
};
struct CV_EXPORTS IndexParams {
protected:
IndexParams(flann_algorithm_t algorithm_) : algorithm(algorithm_) {};
public: public:
virtual ~IndexParams() {} FLANNException(const char* message) : std::runtime_error(message) { }
virtual flann_algorithm_t getIndexType() const { return algorithm; }
virtual void print() const = 0;
flann_algorithm_t algorithm;
};
typedef ObjectFactory<IndexParams, flann_algorithm_t> ParamsFactory;
CV_EXPORTS ParamsFactory& ParamsFactory_instance();
struct CV_EXPORTS SearchParams {
SearchParams(int checks_ = 32) :
checks(checks_) {};
int checks; FLANNException(const std::string& message) : std::runtime_error(message) { }
}; };
} // namespace cvflann }
#endif
#endif /* _OPENCV_GENERAL_H_ */ #endif /* OPENCV_FLANN_GENERAL_H_ */
...@@ -28,39 +28,41 @@ ...@@ -28,39 +28,41 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*************************************************************************/ *************************************************************************/
#ifndef _OPENCV_GROUND_TRUTH_H_ #ifndef OPENCV_FLANN_GROUND_TRUTH_H_
#define _OPENCV_GROUND_TRUTH_H_ #define OPENCV_FLANN_GROUND_TRUTH_H_
#include "dist.h"
#include "matrix.h"
#include "opencv2/flann/dist.h"
#include "opencv2/flann/matrix.h"
namespace cvflann namespace cvflann
{ {
template <typename T> template <typename Distance>
void find_nearest(const Matrix<T>& dataset, T* query, int* matches, int nn, int skip = 0) void find_nearest(const Matrix<typename Distance::ElementType>& dataset, typename Distance::ElementType* query, int* matches, int nn,
int skip = 0, Distance distance = Distance())
{ {
typedef typename Distance::ElementType ElementType;
typedef typename Distance::ResultType DistanceType;
int n = nn + skip; int n = nn + skip;
T* query_end = query + dataset.cols; int* match = new int[n];
DistanceType* dists = new DistanceType[n];
long* match = new long[n];
T* dists = new T[n];
dists[0] = (float)flann_dist(query, query_end, dataset[0]); dists[0] = distance(dataset[0], query, dataset.cols);
match[0] = 0; match[0] = 0;
int dcnt = 1; int dcnt = 1;
for (size_t i=1;i<dataset.rows;++i) { for (size_t i=1; i<dataset.rows; ++i) {
T tmp = (T)flann_dist(query, query_end, dataset[i]); DistanceType tmp = distance(dataset[i], query, dataset.cols);
if (dcnt<n) { if (dcnt<n) {
match[dcnt] = (long)i; match[dcnt] = i;
dists[dcnt++] = tmp; dists[dcnt++] = tmp;
} }
else if (tmp < dists[dcnt-1]) { else if (tmp < dists[dcnt-1]) {
dists[dcnt-1] = tmp; dists[dcnt-1] = tmp;
match[dcnt-1] = (long)i; match[dcnt-1] = i;
} }
int j = dcnt-1; int j = dcnt-1;
...@@ -72,7 +74,7 @@ void find_nearest(const Matrix<T>& dataset, T* query, int* matches, int nn, int ...@@ -72,7 +74,7 @@ void find_nearest(const Matrix<T>& dataset, T* query, int* matches, int nn, int
} }
} }
for (int i=0;i<nn;++i) { for (int i=0; i<nn; ++i) {
matches[i] = match[i+skip]; matches[i] = match[i+skip];
} }
...@@ -81,15 +83,16 @@ void find_nearest(const Matrix<T>& dataset, T* query, int* matches, int nn, int ...@@ -81,15 +83,16 @@ void find_nearest(const Matrix<T>& dataset, T* query, int* matches, int nn, int
} }
template <typename T> template <typename Distance>
void compute_ground_truth(const Matrix<T>& dataset, const Matrix<T>& testset, Matrix<int>& matches, int skip=0) void compute_ground_truth(const Matrix<typename Distance::ElementType>& dataset, const Matrix<typename Distance::ElementType>& testset, Matrix<int>& matches,
int skip=0, Distance d = Distance())
{ {
for (size_t i=0;i<testset.rows;++i) { for (size_t i=0; i<testset.rows; ++i) {
find_nearest(dataset, testset[i], matches[i], (int)matches.cols, skip); find_nearest<Distance>(dataset, testset[i], matches[i], (int)matches.cols, skip, d);
} }
} }
} // namespace cvflann }
#endif //_OPENCV_GROUND_TRUTH_H_ #endif //OPENCV_FLANN_GROUND_TRUTH_H_
...@@ -27,137 +27,207 @@ ...@@ -27,137 +27,207 @@
*************************************************************************/ *************************************************************************/
#ifndef _OPENCV_HDF5_H_ #ifndef OPENCV_FLANN_HDF5_H_
#define _OPENCV_HDF5_H_ #define OPENCV_FLANN_HDF5_H_
#include <H5Cpp.h> #include <hdf5.h>
#include "opencv2/flann/matrix.h" #include "matrix.h"
namespace cvflann
{
#ifndef H5_NO_NAMESPACE namespace
using namespace H5; {
#endif
namespace cvflann template<typename T>
hid_t get_hdf5_type()
{ {
throw FLANNException("Unsupported type for IO operations");
}
template<>
hid_t get_hdf5_type<char>() { return H5T_NATIVE_CHAR; }
template<>
hid_t get_hdf5_type<unsigned char>() { return H5T_NATIVE_UCHAR; }
template<>
hid_t get_hdf5_type<short int>() { return H5T_NATIVE_SHORT; }
template<>
hid_t get_hdf5_type<unsigned short int>() { return H5T_NATIVE_USHORT; }
template<>
hid_t get_hdf5_type<int>() { return H5T_NATIVE_INT; }
template<>
hid_t get_hdf5_type<unsigned int>() { return H5T_NATIVE_UINT; }
template<>
hid_t get_hdf5_type<long>() { return H5T_NATIVE_LONG; }
template<>
hid_t get_hdf5_type<unsigned long>() { return H5T_NATIVE_ULONG; }
template<>
hid_t get_hdf5_type<float>() { return H5T_NATIVE_FLOAT; }
template<>
hid_t get_hdf5_type<double>() { return H5T_NATIVE_DOUBLE; }
template<>
hid_t get_hdf5_type<long double>() { return H5T_NATIVE_LDOUBLE; }
}
namespace { #define CHECK_ERROR(x,y) if ((x)<0) throw FLANNException((y));
template<typename T> template<typename T>
PredType get_hdf5_type() void save_to_file(const cvflann::Matrix<T>& dataset, const std::string& filename, const std::string& name)
{ {
throw FLANNException("Unsupported type for IO operations");
}
template<> PredType get_hdf5_type<char>() { return PredType::NATIVE_CHAR; } #if H5Eset_auto_vers == 2
template<> PredType get_hdf5_type<unsigned char>() { return PredType::NATIVE_UCHAR; } H5Eset_auto( H5E_DEFAULT, NULL, NULL );
template<> PredType get_hdf5_type<short int>() { return PredType::NATIVE_SHORT; } #else
template<> PredType get_hdf5_type<unsigned short int>() { return PredType::NATIVE_USHORT; } H5Eset_auto( NULL, NULL );
template<> PredType get_hdf5_type<int>() { return PredType::NATIVE_INT; } #endif
template<> PredType get_hdf5_type<unsigned int>() { return PredType::NATIVE_UINT; }
template<> PredType get_hdf5_type<long>() { return PredType::NATIVE_LONG; } herr_t status;
template<> PredType get_hdf5_type<unsigned long>() { return PredType::NATIVE_ULONG; } hid_t file_id;
template<> PredType get_hdf5_type<float>() { return PredType::NATIVE_FLOAT; } file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
template<> PredType get_hdf5_type<double>() { return PredType::NATIVE_DOUBLE; } if (file_id < 0) {
template<> PredType get_hdf5_type<long double>() { return PredType::NATIVE_LDOUBLE; } file_id = H5Fcreate(filename.c_str(), H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT);
}
CHECK_ERROR(file_id,"Error creating hdf5 file.");
hsize_t dimsf[2]; // dataset dimensions
dimsf[0] = dataset.rows;
dimsf[1] = dataset.cols;
hid_t space_id = H5Screate_simple(2, dimsf, NULL);
hid_t memspace_id = H5Screate_simple(2, dimsf, NULL);
hid_t dataset_id;
#if H5Dcreate_vers == 2
dataset_id = H5Dcreate2(file_id, name.c_str(), get_hdf5_type<T>(), space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
#else
dataset_id = H5Dcreate(file_id, name.c_str(), get_hdf5_type<T>(), space_id, H5P_DEFAULT);
#endif
if (dataset_id<0) {
#if H5Dopen_vers == 2
dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT);
#else
dataset_id = H5Dopen(file_id, name.c_str());
#endif
}
CHECK_ERROR(dataset_id,"Error creating or opening dataset in file.");
status = H5Dwrite(dataset_id, get_hdf5_type<T>(), memspace_id, space_id, H5P_DEFAULT, dataset.data );
CHECK_ERROR(status, "Error writing to dataset");
H5Sclose(memspace_id);
H5Sclose(space_id);
H5Dclose(dataset_id);
H5Fclose(file_id);
} }
template<typename T> template<typename T>
void save_to_file(const cvflann::Matrix<T>& flann_dataset, const std::string& filename, const std::string& name) void load_from_file(cvflann::Matrix<T>& dataset, const std::string& filename, const std::string& name)
{ {
// Try block to detect exceptions raised by any of the calls inside it herr_t status;
try hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
{ CHECK_ERROR(file_id,"Error opening hdf5 file.");
/*
* Turn off the auto-printing when failure occurs so that we can hid_t dataset_id;
* handle the errors appropriately #if H5Dopen_vers == 2
*/ dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT);
Exception::dontPrint(); #else
dataset_id = H5Dopen(file_id, name.c_str());
/* #endif
* Create a new file using H5F_ACC_TRUNC access, CHECK_ERROR(dataset_id,"Error opening dataset in file.");
* default file creation properties, and default file
* access properties. hid_t space_id = H5Dget_space(dataset_id);
*/
H5File file( filename, H5F_ACC_TRUNC ); hsize_t dims_out[2];
H5Sget_simple_extent_dims(space_id, dims_out, NULL);
/*
* Define the size of the array and create the data space for fixed dataset = cvflann::Matrix<T>(new T[dims_out[0]*dims_out[1]], dims_out[0], dims_out[1]);
* size dataset.
*/ status = H5Dread(dataset_id, get_hdf5_type<T>(), H5S_ALL, H5S_ALL, H5P_DEFAULT, dataset[0]);
hsize_t dimsf[2]; // dataset dimensions CHECK_ERROR(status, "Error reading dataset");
dimsf[0] = flann_dataset.rows;
dimsf[1] = flann_dataset.cols; H5Sclose(space_id);
DataSpace dataspace( 2, dimsf ); H5Dclose(dataset_id);
H5Fclose(file_id);
/*
* Create a new dataset within the file using defined dataspace and
* datatype and default dataset creation properties.
*/
DataSet dataset = file.createDataSet( name, get_hdf5_type<T>(), dataspace );
/*
* Write the data to the dataset using default memory space, file
* space, and transfer properties.
*/
dataset.write( flann_dataset.data, get_hdf5_type<T>() );
} // end of try block
catch( H5::Exception& error )
{
error.printError();
throw FLANNException(error.getDetailMsg());
}
} }
#ifdef HAVE_MPI
namespace mpi
{
/**
* Loads a the hyperslice corresponding to this processor from a hdf5 file.
* @param flann_dataset Dataset where the data is loaded
* @param filename HDF5 file name
* @param name Name of dataset inside file
*/
template<typename T> template<typename T>
void load_from_file(cvflann::Matrix<T>& flann_dataset, const std::string& filename, const std::string& name) void load_from_file(cvflann::Matrix<T>& dataset, const std::string& filename, const std::string& name)
{ {
try MPI_Comm comm = MPI_COMM_WORLD;
{ MPI_Info info = MPI_INFO_NULL;
Exception::dontPrint();
int mpi_size, mpi_rank;
H5File file( filename, H5F_ACC_RDONLY ); MPI_Comm_size(comm, &mpi_size);
DataSet dataset = file.openDataSet( name ); MPI_Comm_rank(comm, &mpi_rank);
/* herr_t status;
* Check the type used by the dataset matches
*/ hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS);
if ( !(dataset.getDataType()==get_hdf5_type<T>())) { H5Pset_fapl_mpio(plist_id, comm, info);
throw FLANNException("Dataset matrix type does not match the type to be read."); hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, plist_id);
} CHECK_ERROR(file_id,"Error opening hdf5 file.");
H5Pclose(plist_id);
/* hid_t dataset_id;
* Get dataspace of the dataset. #if H5Dopen_vers == 2
*/ dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT);
DataSpace dataspace = dataset.getSpace(); #else
dataset_id = H5Dopen(file_id, name.c_str());
/* #endif
* Get the dimension size of each dimension in the dataspace and CHECK_ERROR(dataset_id,"Error opening dataset in file.");
* display them.
*/ hid_t space_id = H5Dget_space(dataset_id);
hsize_t dims_out[2]; hsize_t dims[2];
dataspace.getSimpleExtentDims( dims_out, NULL); H5Sget_simple_extent_dims(space_id, dims, NULL);
flann_dataset.rows = dims_out[0];
flann_dataset.cols = dims_out[1];
flann_dataset.data = new T[flann_dataset.rows*flann_dataset.cols];
dataset.read( flann_dataset.data, get_hdf5_type<T>() );
} // end of try block
catch( H5::Exception &error )
{
error.printError();
throw FLANNException(error.getDetailMsg());
}
}
hsize_t count[2];
hsize_t offset[2];
} // namespace cvflann hsize_t item_cnt = dims[0]/mpi_size+(dims[0]%mpi_size==0 ? 0 : 1);
hsize_t cnt = (mpi_rank<mpi_size-1 ? item_cnt : dims[0]-item_cnt*(mpi_size-1));
count[0] = cnt;
count[1] = dims[1];
offset[0] = mpi_rank*item_cnt;
offset[1] = 0;
hid_t memspace_id = H5Screate_simple(2,count,NULL);
H5Sselect_hyperslab(space_id, H5S_SELECT_SET, offset, NULL, count, NULL);
dataset.rows = count[0];
dataset.cols = count[1];
dataset.data = new T[dataset.rows*dataset.cols];
plist_id = H5Pcreate(H5P_DATASET_XFER);
H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);
status = H5Dread(dataset_id, get_hdf5_type<T>(), memspace_id, space_id, plist_id, dataset.data);
CHECK_ERROR(status, "Error reading dataset");
H5Pclose(plist_id);
H5Sclose(space_id);
H5Sclose(memspace_id);
H5Dclose(dataset_id);
H5Fclose(file_id);
}
}
#endif // HAVE_MPI
} // namespace cvflann::mpi
#endif /* _OPENCV_HDF5_H_ */ #endif /* OPENCV_FLANN_HDF5_H_ */
This diff is collapsed.
This diff is collapsed.
...@@ -28,41 +28,40 @@ ...@@ -28,41 +28,40 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*************************************************************************/ *************************************************************************/
#ifndef _OPENCV_LINEARSEARCH_H_ #ifndef OPENCV_FLANN_LINEAR_INDEX_H_
#define _OPENCV_LINEARSEARCH_H_ #define OPENCV_FLANN_LINEAR_INDEX_H_
#include "opencv2/flann/general.h"
#include "opencv2/flann/nn_index.h"
#include "general.h"
#include "nn_index.h"
namespace cvflann namespace cvflann
{ {
struct CV_EXPORTS LinearIndexParams : public IndexParams { struct LinearIndexParams : public IndexParams
LinearIndexParams() : IndexParams(FLANN_INDEX_LINEAR) {}; {
LinearIndexParams()
void print() const {
{ (* this)["algorithm"] = FLANN_INDEX_LINEAR;
logger().info("Index type: %d\n",(int)algorithm); }
}
}; };
template <typename Distance>
template <typename ELEM_TYPE, typename DIST_TYPE = typename DistType<ELEM_TYPE>::type > class LinearIndex : public NNIndex<Distance>
class LinearIndex : public NNIndex<ELEM_TYPE>
{ {
const Matrix<ELEM_TYPE> dataset; public:
const LinearIndexParams& index_params;
LinearIndex(const LinearIndex&); typedef typename Distance::ElementType ElementType;
LinearIndex& operator=(const LinearIndex&); typedef typename Distance::ResultType DistanceType;
public:
LinearIndex(const Matrix<ELEM_TYPE>& inputData, const LinearIndexParams& params = LinearIndexParams() ) : LinearIndex(const Matrix<ElementType>& inputData, const IndexParams& params = LinearIndexParams(),
dataset(inputData), index_params(params) Distance d = Distance()) :
{ dataset_(inputData), index_params_(params), distance_(d)
} {
}
LinearIndex(const LinearIndex&);
LinearIndex& operator=(const LinearIndex&);
flann_algorithm_t getType() const flann_algorithm_t getType() const
{ {
...@@ -70,52 +69,64 @@ public: ...@@ -70,52 +69,64 @@ public:
} }
size_t size() const size_t size() const
{ {
return dataset.rows; return dataset_.rows;
} }
size_t veclen() const size_t veclen() const
{ {
return dataset.cols; return dataset_.cols;
} }
int usedMemory() const int usedMemory() const
{ {
return 0; return 0;
} }
void buildIndex() void buildIndex()
{ {
/* nothing to do here for linear search */ /* nothing to do here for linear search */
} }
void saveIndex(FILE*) void saveIndex(FILE*)
{ {
/* nothing to do here for linear search */ /* nothing to do here for linear search */
} }
void loadIndex(FILE*) void loadIndex(FILE*)
{ {
/* nothing to do here for linear search */ /* nothing to do here for linear search */
index_params_["algorithm"] = getType();
}
void findNeighbors(ResultSet<DistanceType>& resultSet, const ElementType* vec, const SearchParams& /*searchParams*/)
{
ElementType* data = dataset_.data;
for (size_t i = 0; i < dataset_.rows; ++i, data += dataset_.cols) {
DistanceType dist = distance_(data, vec, dataset_.cols);
resultSet.addPoint(dist, i);
}
} }
void findNeighbors(ResultSet<ELEM_TYPE>& resultSet, const ELEM_TYPE*, const SearchParams&) IndexParams getParameters() const
{ {
for (size_t i=0;i<dataset.rows;++i) { return index_params_;
resultSet.addPoint(dataset[i],(int)i); }
}
}
const IndexParams* getParameters() const private:
{ /** The dataset */
return &index_params; const Matrix<ElementType> dataset_;
} /** Index parameters */
IndexParams index_params_;
/** Index distance */
Distance distance_;
}; };
} // namespace cvflann }
#endif // _OPENCV_LINEARSEARCH_H_ #endif // OPENCV_FLANN_LINEAR_INDEX_H_
This diff is collapsed.
This diff is collapsed.
...@@ -28,60 +28,58 @@ ...@@ -28,60 +28,58 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*************************************************************************/ *************************************************************************/
#ifndef _OPENCV_DATASET_H_ #ifndef OPENCV_FLANN_DATASET_H_
#define _OPENCV_DATASET_H_ #define OPENCV_FLANN_DATASET_H_
#include <stdio.h> #include <stdio.h>
#include "opencv2/flann/general.h" #include "general.h"
namespace cvflann
namespace cvflann
{ {
/** /**
* Class that implements a simple rectangular matrix stored in a memory buffer and * Class that implements a simple rectangular matrix stored in a memory buffer and
* provides convenient matrix-like access using the [] operators. * provides convenient matrix-like access using the [] operators.
*/ */
template <typename T> template <typename T>
class Matrix { class Matrix
{
public: public:
typedef T type;
size_t rows; size_t rows;
size_t cols; size_t cols;
size_t stride;
T* data; T* data;
Matrix() : rows(0), cols(0), data(NULL) Matrix() : rows(0), cols(0), stride(0), data(NULL)
{ {
} }
Matrix(T* data_, long rows_, long cols_) : Matrix(T* data_, size_t rows_, size_t cols_, size_t stride_ = 0) :
rows(rows_), cols(cols_), data(data_) rows(rows_), cols(cols_), stride(stride_), data(data_)
{ {
} if (stride==0) stride = cols;
}
/** /**
* Convenience function for deallocating the storage data. * Convenience function for deallocating the storage data.
*/ */
void release() FLANN_DEPRECATED void free()
{ {
if (data!=NULL) delete[] data; fprintf(stderr, "The cvflann::Matrix<T>::free() method is deprecated "
"and it does not do any memory deallocation any more. You are"
"responsible for deallocating the matrix memory (by doing"
"'delete[] matrix.data' for example)");
} }
~Matrix()
{
}
/** /**
* Operator that return a (pointer to a) row of the data. * Operator that return a (pointer to a) row of the data.
*/ */
T* operator[](size_t index)
{
return data+index*cols;
}
T* operator[](size_t index) const T* operator[](size_t index) const
{ {
return data+index*cols; return data+index*stride;
} }
}; };
...@@ -95,7 +93,7 @@ public: ...@@ -95,7 +93,7 @@ public:
flann_datatype_t type; flann_datatype_t type;
UntypedMatrix(void* data_, long rows_, long cols_) : UntypedMatrix(void* data_, long rows_, long cols_) :
rows(rows_), cols(cols_), data(data_) rows(rows_), cols(cols_), data(data_)
{ {
} }
...@@ -113,6 +111,6 @@ public: ...@@ -113,6 +111,6 @@ public:
} // namespace cvflann }
#endif //_OPENCV_DATASET_H_ #endif //OPENCV_FLANN_DATASET_H_
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "opencv2/flann/dist.h" #include "opencv2/flann/dist.h"
#include "opencv2/flann/index_testing.h" #include "opencv2/flann/index_testing.h"
#include "opencv2/flann/params.h"
#include "opencv2/flann/saving.h" #include "opencv2/flann/saving.h"
#include "opencv2/flann/general.h" #include "opencv2/flann/general.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment