| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #ifndef FLANN_HPP_ |
| #define FLANN_HPP_ |
|
|
|
|
| #include <vector> |
| #include <string> |
| #include <cassert> |
| #include <cstdio> |
|
|
| #include "FLANN/general.h" |
| #include "FLANN/util/matrix.h" |
| #include "FLANN/util/params.h" |
| #include "FLANN/util/saving.h" |
|
|
| #include "FLANN/algorithms/all_indices.h" |
|
|
| namespace flann |
| { |
|
|
| |
| |
| |
| |
| inline void log_verbosity(int level) |
| { |
| if (level >= 0) { |
| Logger::setLevel(level); |
| } |
| } |
|
|
| |
| |
| |
| struct SavedIndexParams : public IndexParams |
| { |
| SavedIndexParams(std::string filename) |
| { |
| (*this)["algorithm"] = FLANN_INDEX_SAVED; |
| (*this)["filename"] = filename; |
| } |
| }; |
|
|
|
|
|
|
| template<typename Distance> |
| class Index |
| { |
| public: |
| typedef typename Distance::ElementType ElementType; |
| typedef typename Distance::ResultType DistanceType; |
| typedef NNIndex<Distance> IndexType; |
|
|
| Index(const IndexParams& params, Distance distance = Distance() ) |
| : index_params_(params) |
| { |
| flann_algorithm_t index_type = get_param<flann_algorithm_t>(params,"algorithm"); |
| loaded_ = false; |
|
|
| Matrix<ElementType> features; |
| if (index_type == FLANN_INDEX_SAVED) { |
| nnIndex_ = load_saved_index(features, get_param<std::string>(params,"filename"), distance); |
| loaded_ = true; |
| } |
| else { |
| flann_algorithm_t index_type = get_param<flann_algorithm_t>(params, "algorithm"); |
| nnIndex_ = create_index_by_type<Distance>(index_type, features, params, distance); |
| } |
| } |
|
|
|
|
| Index(const Matrix<ElementType>& features, const IndexParams& params, Distance distance = Distance() ) |
| : index_params_(params) |
| { |
| flann_algorithm_t index_type = get_param<flann_algorithm_t>(params,"algorithm"); |
| loaded_ = false; |
|
|
| if (index_type == FLANN_INDEX_SAVED) { |
| nnIndex_ = load_saved_index(features, get_param<std::string>(params,"filename"), distance); |
| loaded_ = true; |
| } |
| else { |
| flann_algorithm_t index_type = get_param<flann_algorithm_t>(params, "algorithm"); |
| nnIndex_ = create_index_by_type<Distance>(index_type, features, params, distance); |
| } |
| } |
|
|
|
|
| Index(const Index& other) : loaded_(other.loaded_), index_params_(other.index_params_) |
| { |
| nnIndex_ = other.nnIndex_->clone(); |
| } |
|
|
| Index& operator=(Index other) |
| { |
| this->swap(other); |
| return *this; |
| } |
|
|
| virtual ~Index() |
| { |
| delete nnIndex_; |
| } |
|
|
| |
| |
| |
| void buildIndex() |
| { |
| if (!loaded_) { |
| nnIndex_->buildIndex(); |
| } |
| } |
|
|
| void buildIndex(const Matrix<ElementType>& points) |
| { |
| nnIndex_->buildIndex(points); |
| } |
|
|
| void addPoints(const Matrix<ElementType>& points, float rebuild_threshold = 2) |
| { |
| nnIndex_->addPoints(points, rebuild_threshold); |
| } |
|
|
| |
| |
| |
| |
| void removePoint(size_t point_id) |
| { |
| nnIndex_->removePoint(point_id); |
| } |
|
|
| |
| |
| |
| |
| |
| ElementType* getPoint(size_t point_id) |
| { |
| return nnIndex_->getPoint(point_id); |
| } |
|
|
| |
| |
| |
| |
| void save(std::string filename) |
| { |
| FILE* fout = fopen(filename.c_str(), "wb"); |
| if (fout == NULL) { |
| throw FLANNException("Cannot open file"); |
| } |
| nnIndex_->saveIndex(fout); |
| fclose(fout); |
| } |
|
|
| |
| |
| |
| size_t veclen() const |
| { |
| return nnIndex_->veclen(); |
| } |
|
|
| |
| |
| |
| size_t size() const |
| { |
| return nnIndex_->size(); |
| } |
|
|
| |
| |
| |
| flann_algorithm_t getType() const |
| { |
| return nnIndex_->getType(); |
| } |
|
|
| |
| |
| |
| int usedMemory() const |
| { |
| return nnIndex_->usedMemory(); |
| } |
|
|
|
|
| |
| |
| |
| IndexParams getParameters() const |
| { |
| return nnIndex_->getParameters(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| int knnSearch(const Matrix<ElementType>& queries, |
| Matrix<size_t>& indices, |
| Matrix<DistanceType>& dists, |
| size_t knn, |
| const SearchParams& params) const |
| { |
| return nnIndex_->knnSearch(queries, indices, dists, knn, params); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| int knnSearch(const Matrix<ElementType>& queries, |
| Matrix<int>& indices, |
| Matrix<DistanceType>& dists, |
| size_t knn, |
| const SearchParams& params) const |
| { |
| return nnIndex_->knnSearch(queries, indices, dists, knn, params); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| int knnSearch(const Matrix<ElementType>& queries, |
| std::vector< std::vector<size_t> >& indices, |
| std::vector<std::vector<DistanceType> >& dists, |
| size_t knn, |
| const SearchParams& params) const |
| { |
| return nnIndex_->knnSearch(queries, indices, dists, knn, params); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| int knnSearch(const Matrix<ElementType>& queries, |
| std::vector< std::vector<int> >& indices, |
| std::vector<std::vector<DistanceType> >& dists, |
| size_t knn, |
| const SearchParams& params) const |
| { |
| return nnIndex_->knnSearch(queries, indices, dists, knn, params); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| int radiusSearch(const Matrix<ElementType>& queries, |
| Matrix<size_t>& indices, |
| Matrix<DistanceType>& dists, |
| float radius, |
| const SearchParams& params) const |
| { |
| return nnIndex_->radiusSearch(queries, indices, dists, radius, params); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| int radiusSearch(const Matrix<ElementType>& queries, |
| Matrix<int>& indices, |
| Matrix<DistanceType>& dists, |
| float radius, |
| const SearchParams& params) const |
| { |
| return nnIndex_->radiusSearch(queries, indices, dists, radius, params); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| int radiusSearch(const Matrix<ElementType>& queries, |
| std::vector< std::vector<size_t> >& indices, |
| std::vector<std::vector<DistanceType> >& dists, |
| float radius, |
| const SearchParams& params) const |
| { |
| return nnIndex_->radiusSearch(queries, indices, dists, radius, params); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| int radiusSearch(const Matrix<ElementType>& queries, |
| std::vector< std::vector<int> >& indices, |
| std::vector<std::vector<DistanceType> >& dists, |
| float radius, |
| const SearchParams& params) const |
| { |
| return nnIndex_->radiusSearch(queries, indices, dists, radius, params); |
| } |
|
|
| private: |
| IndexType* load_saved_index(const Matrix<ElementType>& dataset, const std::string& filename, Distance distance) |
| { |
| FILE* fin = fopen(filename.c_str(), "rb"); |
| if (fin == NULL) { |
| return NULL; |
| } |
| IndexHeader header = load_header(fin); |
| if (header.h.data_type != flann_datatype_value<ElementType>::value) { |
| throw FLANNException("Datatype of saved index is different than of the one to be loaded."); |
| } |
|
|
| IndexParams params; |
| params["algorithm"] = header.h.index_type; |
| IndexType* nnIndex = create_index_by_type<Distance>(header.h.index_type, dataset, params, distance); |
| rewind(fin); |
| nnIndex->loadIndex(fin); |
| fclose(fin); |
|
|
| return nnIndex; |
| } |
|
|
| void swap( Index& other) |
| { |
| std::swap(nnIndex_, other.nnIndex_); |
| std::swap(loaded_, other.loaded_); |
| std::swap(index_params_, other.index_params_); |
| } |
|
|
| private: |
| |
| IndexType* nnIndex_; |
| |
| bool loaded_; |
| |
| IndexParams index_params_; |
| }; |
|
|
|
|
|
|
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| template <typename Distance> |
| int hierarchicalClustering(const Matrix<typename Distance::ElementType>& points, Matrix<typename Distance::ResultType>& centers, |
| const KMeansIndexParams& params, Distance d = Distance()) |
| { |
| KMeansIndex<Distance> kmeans(points, params, d); |
| kmeans.buildIndex(); |
|
|
| int clusterNum = kmeans.getClusterCenters(centers); |
| return clusterNum; |
| } |
|
|
| } |
| #endif |
|
|