openCV library for Renesas RZ/A
Dependents: RZ_A2M_Mbed_samples
include/opencv2/flann/lsh_index.h@0:0e0631af0305, 2021-01-29 (annotated)
- Committer:
- RyoheiHagimoto
- Date:
- Fri Jan 29 04:53:38 2021 +0000
- Revision:
- 0:0e0631af0305
copied from https://github.com/d-kato/opencv-lib.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
RyoheiHagimoto | 0:0e0631af0305 | 1 | /*********************************************************************** |
RyoheiHagimoto | 0:0e0631af0305 | 2 | * Software License Agreement (BSD License) |
RyoheiHagimoto | 0:0e0631af0305 | 3 | * |
RyoheiHagimoto | 0:0e0631af0305 | 4 | * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. |
RyoheiHagimoto | 0:0e0631af0305 | 5 | * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. |
RyoheiHagimoto | 0:0e0631af0305 | 6 | * |
RyoheiHagimoto | 0:0e0631af0305 | 7 | * THE BSD LICENSE |
RyoheiHagimoto | 0:0e0631af0305 | 8 | * |
RyoheiHagimoto | 0:0e0631af0305 | 9 | * Redistribution and use in source and binary forms, with or without |
RyoheiHagimoto | 0:0e0631af0305 | 10 | * modification, are permitted provided that the following conditions |
RyoheiHagimoto | 0:0e0631af0305 | 11 | * are met: |
RyoheiHagimoto | 0:0e0631af0305 | 12 | * |
RyoheiHagimoto | 0:0e0631af0305 | 13 | * 1. Redistributions of source code must retain the above copyright |
RyoheiHagimoto | 0:0e0631af0305 | 14 | * notice, this list of conditions and the following disclaimer. |
RyoheiHagimoto | 0:0e0631af0305 | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
RyoheiHagimoto | 0:0e0631af0305 | 16 | * notice, this list of conditions and the following disclaimer in the |
RyoheiHagimoto | 0:0e0631af0305 | 17 | * documentation and/or other materials provided with the distribution. |
RyoheiHagimoto | 0:0e0631af0305 | 18 | * |
RyoheiHagimoto | 0:0e0631af0305 | 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
RyoheiHagimoto | 0:0e0631af0305 | 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
RyoheiHagimoto | 0:0e0631af0305 | 21 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
RyoheiHagimoto | 0:0e0631af0305 | 22 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
RyoheiHagimoto | 0:0e0631af0305 | 23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
RyoheiHagimoto | 0:0e0631af0305 | 24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
RyoheiHagimoto | 0:0e0631af0305 | 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
RyoheiHagimoto | 0:0e0631af0305 | 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
RyoheiHagimoto | 0:0e0631af0305 | 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
RyoheiHagimoto | 0:0e0631af0305 | 28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
RyoheiHagimoto | 0:0e0631af0305 | 29 | *************************************************************************/ |
RyoheiHagimoto | 0:0e0631af0305 | 30 | |
RyoheiHagimoto | 0:0e0631af0305 | 31 | /*********************************************************************** |
RyoheiHagimoto | 0:0e0631af0305 | 32 | * Author: Vincent Rabaud |
RyoheiHagimoto | 0:0e0631af0305 | 33 | *************************************************************************/ |
RyoheiHagimoto | 0:0e0631af0305 | 34 | |
RyoheiHagimoto | 0:0e0631af0305 | 35 | #ifndef OPENCV_FLANN_LSH_INDEX_H_ |
RyoheiHagimoto | 0:0e0631af0305 | 36 | #define OPENCV_FLANN_LSH_INDEX_H_ |
RyoheiHagimoto | 0:0e0631af0305 | 37 | |
RyoheiHagimoto | 0:0e0631af0305 | 38 | #include <algorithm> |
RyoheiHagimoto | 0:0e0631af0305 | 39 | #include <cassert> |
RyoheiHagimoto | 0:0e0631af0305 | 40 | #include <cstring> |
RyoheiHagimoto | 0:0e0631af0305 | 41 | #include <map> |
RyoheiHagimoto | 0:0e0631af0305 | 42 | #include <vector> |
RyoheiHagimoto | 0:0e0631af0305 | 43 | |
RyoheiHagimoto | 0:0e0631af0305 | 44 | #include "general.h" |
RyoheiHagimoto | 0:0e0631af0305 | 45 | #include "nn_index.h" |
RyoheiHagimoto | 0:0e0631af0305 | 46 | #include "matrix.h" |
RyoheiHagimoto | 0:0e0631af0305 | 47 | #include "result_set.h" |
RyoheiHagimoto | 0:0e0631af0305 | 48 | #include "heap.h" |
RyoheiHagimoto | 0:0e0631af0305 | 49 | #include "lsh_table.h" |
RyoheiHagimoto | 0:0e0631af0305 | 50 | #include "allocator.h" |
RyoheiHagimoto | 0:0e0631af0305 | 51 | #include "random.h" |
RyoheiHagimoto | 0:0e0631af0305 | 52 | #include "saving.h" |
RyoheiHagimoto | 0:0e0631af0305 | 53 | |
RyoheiHagimoto | 0:0e0631af0305 | 54 | namespace cvflann |
RyoheiHagimoto | 0:0e0631af0305 | 55 | { |
RyoheiHagimoto | 0:0e0631af0305 | 56 | |
RyoheiHagimoto | 0:0e0631af0305 | 57 | struct LshIndexParams : public IndexParams |
RyoheiHagimoto | 0:0e0631af0305 | 58 | { |
RyoheiHagimoto | 0:0e0631af0305 | 59 | LshIndexParams(unsigned int table_number = 12, unsigned int key_size = 20, unsigned int multi_probe_level = 2) |
RyoheiHagimoto | 0:0e0631af0305 | 60 | { |
RyoheiHagimoto | 0:0e0631af0305 | 61 | (* this)["algorithm"] = FLANN_INDEX_LSH; |
RyoheiHagimoto | 0:0e0631af0305 | 62 | // The number of hash tables to use |
RyoheiHagimoto | 0:0e0631af0305 | 63 | (*this)["table_number"] = table_number; |
RyoheiHagimoto | 0:0e0631af0305 | 64 | // The length of the key in the hash tables |
RyoheiHagimoto | 0:0e0631af0305 | 65 | (*this)["key_size"] = key_size; |
RyoheiHagimoto | 0:0e0631af0305 | 66 | // Number of levels to use in multi-probe (0 for standard LSH) |
RyoheiHagimoto | 0:0e0631af0305 | 67 | (*this)["multi_probe_level"] = multi_probe_level; |
RyoheiHagimoto | 0:0e0631af0305 | 68 | } |
RyoheiHagimoto | 0:0e0631af0305 | 69 | }; |
RyoheiHagimoto | 0:0e0631af0305 | 70 | |
RyoheiHagimoto | 0:0e0631af0305 | 71 | /** |
RyoheiHagimoto | 0:0e0631af0305 | 72 | * Randomized kd-tree index |
RyoheiHagimoto | 0:0e0631af0305 | 73 | * |
RyoheiHagimoto | 0:0e0631af0305 | 74 | * Contains the k-d trees and other information for indexing a set of points |
RyoheiHagimoto | 0:0e0631af0305 | 75 | * for nearest-neighbor matching. |
RyoheiHagimoto | 0:0e0631af0305 | 76 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 77 | template<typename Distance> |
RyoheiHagimoto | 0:0e0631af0305 | 78 | class LshIndex : public NNIndex<Distance> |
RyoheiHagimoto | 0:0e0631af0305 | 79 | { |
RyoheiHagimoto | 0:0e0631af0305 | 80 | public: |
RyoheiHagimoto | 0:0e0631af0305 | 81 | typedef typename Distance::ElementType ElementType; |
RyoheiHagimoto | 0:0e0631af0305 | 82 | typedef typename Distance::ResultType DistanceType; |
RyoheiHagimoto | 0:0e0631af0305 | 83 | |
RyoheiHagimoto | 0:0e0631af0305 | 84 | /** Constructor |
RyoheiHagimoto | 0:0e0631af0305 | 85 | * @param input_data dataset with the input features |
RyoheiHagimoto | 0:0e0631af0305 | 86 | * @param params parameters passed to the LSH algorithm |
RyoheiHagimoto | 0:0e0631af0305 | 87 | * @param d the distance used |
RyoheiHagimoto | 0:0e0631af0305 | 88 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 89 | LshIndex(const Matrix<ElementType>& input_data, const IndexParams& params = LshIndexParams(), |
RyoheiHagimoto | 0:0e0631af0305 | 90 | Distance d = Distance()) : |
RyoheiHagimoto | 0:0e0631af0305 | 91 | dataset_(input_data), index_params_(params), distance_(d) |
RyoheiHagimoto | 0:0e0631af0305 | 92 | { |
RyoheiHagimoto | 0:0e0631af0305 | 93 | // cv::flann::IndexParams sets integer params as 'int', so it is used with get_param |
RyoheiHagimoto | 0:0e0631af0305 | 94 | // in place of 'unsigned int' |
RyoheiHagimoto | 0:0e0631af0305 | 95 | table_number_ = (unsigned int)get_param<int>(index_params_,"table_number",12); |
RyoheiHagimoto | 0:0e0631af0305 | 96 | key_size_ = (unsigned int)get_param<int>(index_params_,"key_size",20); |
RyoheiHagimoto | 0:0e0631af0305 | 97 | multi_probe_level_ = (unsigned int)get_param<int>(index_params_,"multi_probe_level",2); |
RyoheiHagimoto | 0:0e0631af0305 | 98 | |
RyoheiHagimoto | 0:0e0631af0305 | 99 | feature_size_ = (unsigned)dataset_.cols; |
RyoheiHagimoto | 0:0e0631af0305 | 100 | fill_xor_mask(0, key_size_, multi_probe_level_, xor_masks_); |
RyoheiHagimoto | 0:0e0631af0305 | 101 | } |
RyoheiHagimoto | 0:0e0631af0305 | 102 | |
RyoheiHagimoto | 0:0e0631af0305 | 103 | |
RyoheiHagimoto | 0:0e0631af0305 | 104 | LshIndex(const LshIndex&); |
RyoheiHagimoto | 0:0e0631af0305 | 105 | LshIndex& operator=(const LshIndex&); |
RyoheiHagimoto | 0:0e0631af0305 | 106 | |
RyoheiHagimoto | 0:0e0631af0305 | 107 | /** |
RyoheiHagimoto | 0:0e0631af0305 | 108 | * Builds the index |
RyoheiHagimoto | 0:0e0631af0305 | 109 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 110 | void buildIndex() |
RyoheiHagimoto | 0:0e0631af0305 | 111 | { |
RyoheiHagimoto | 0:0e0631af0305 | 112 | tables_.resize(table_number_); |
RyoheiHagimoto | 0:0e0631af0305 | 113 | for (unsigned int i = 0; i < table_number_; ++i) { |
RyoheiHagimoto | 0:0e0631af0305 | 114 | lsh::LshTable<ElementType>& table = tables_[i]; |
RyoheiHagimoto | 0:0e0631af0305 | 115 | table = lsh::LshTable<ElementType>(feature_size_, key_size_); |
RyoheiHagimoto | 0:0e0631af0305 | 116 | |
RyoheiHagimoto | 0:0e0631af0305 | 117 | // Add the features to the table |
RyoheiHagimoto | 0:0e0631af0305 | 118 | table.add(dataset_); |
RyoheiHagimoto | 0:0e0631af0305 | 119 | } |
RyoheiHagimoto | 0:0e0631af0305 | 120 | } |
RyoheiHagimoto | 0:0e0631af0305 | 121 | |
RyoheiHagimoto | 0:0e0631af0305 | 122 | flann_algorithm_t getType() const |
RyoheiHagimoto | 0:0e0631af0305 | 123 | { |
RyoheiHagimoto | 0:0e0631af0305 | 124 | return FLANN_INDEX_LSH; |
RyoheiHagimoto | 0:0e0631af0305 | 125 | } |
RyoheiHagimoto | 0:0e0631af0305 | 126 | |
RyoheiHagimoto | 0:0e0631af0305 | 127 | |
RyoheiHagimoto | 0:0e0631af0305 | 128 | void saveIndex(FILE* stream) |
RyoheiHagimoto | 0:0e0631af0305 | 129 | { |
RyoheiHagimoto | 0:0e0631af0305 | 130 | save_value(stream,table_number_); |
RyoheiHagimoto | 0:0e0631af0305 | 131 | save_value(stream,key_size_); |
RyoheiHagimoto | 0:0e0631af0305 | 132 | save_value(stream,multi_probe_level_); |
RyoheiHagimoto | 0:0e0631af0305 | 133 | save_value(stream, dataset_); |
RyoheiHagimoto | 0:0e0631af0305 | 134 | } |
RyoheiHagimoto | 0:0e0631af0305 | 135 | |
RyoheiHagimoto | 0:0e0631af0305 | 136 | void loadIndex(FILE* stream) |
RyoheiHagimoto | 0:0e0631af0305 | 137 | { |
RyoheiHagimoto | 0:0e0631af0305 | 138 | load_value(stream, table_number_); |
RyoheiHagimoto | 0:0e0631af0305 | 139 | load_value(stream, key_size_); |
RyoheiHagimoto | 0:0e0631af0305 | 140 | load_value(stream, multi_probe_level_); |
RyoheiHagimoto | 0:0e0631af0305 | 141 | load_value(stream, dataset_); |
RyoheiHagimoto | 0:0e0631af0305 | 142 | // Building the index is so fast we can afford not storing it |
RyoheiHagimoto | 0:0e0631af0305 | 143 | buildIndex(); |
RyoheiHagimoto | 0:0e0631af0305 | 144 | |
RyoheiHagimoto | 0:0e0631af0305 | 145 | index_params_["algorithm"] = getType(); |
RyoheiHagimoto | 0:0e0631af0305 | 146 | index_params_["table_number"] = table_number_; |
RyoheiHagimoto | 0:0e0631af0305 | 147 | index_params_["key_size"] = key_size_; |
RyoheiHagimoto | 0:0e0631af0305 | 148 | index_params_["multi_probe_level"] = multi_probe_level_; |
RyoheiHagimoto | 0:0e0631af0305 | 149 | } |
RyoheiHagimoto | 0:0e0631af0305 | 150 | |
RyoheiHagimoto | 0:0e0631af0305 | 151 | /** |
RyoheiHagimoto | 0:0e0631af0305 | 152 | * Returns size of index. |
RyoheiHagimoto | 0:0e0631af0305 | 153 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 154 | size_t size() const |
RyoheiHagimoto | 0:0e0631af0305 | 155 | { |
RyoheiHagimoto | 0:0e0631af0305 | 156 | return dataset_.rows; |
RyoheiHagimoto | 0:0e0631af0305 | 157 | } |
RyoheiHagimoto | 0:0e0631af0305 | 158 | |
RyoheiHagimoto | 0:0e0631af0305 | 159 | /** |
RyoheiHagimoto | 0:0e0631af0305 | 160 | * Returns the length of an index feature. |
RyoheiHagimoto | 0:0e0631af0305 | 161 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 162 | size_t veclen() const |
RyoheiHagimoto | 0:0e0631af0305 | 163 | { |
RyoheiHagimoto | 0:0e0631af0305 | 164 | return feature_size_; |
RyoheiHagimoto | 0:0e0631af0305 | 165 | } |
RyoheiHagimoto | 0:0e0631af0305 | 166 | |
RyoheiHagimoto | 0:0e0631af0305 | 167 | /** |
RyoheiHagimoto | 0:0e0631af0305 | 168 | * Computes the index memory usage |
RyoheiHagimoto | 0:0e0631af0305 | 169 | * Returns: memory used by the index |
RyoheiHagimoto | 0:0e0631af0305 | 170 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 171 | int usedMemory() const |
RyoheiHagimoto | 0:0e0631af0305 | 172 | { |
RyoheiHagimoto | 0:0e0631af0305 | 173 | return (int)(dataset_.rows * sizeof(int)); |
RyoheiHagimoto | 0:0e0631af0305 | 174 | } |
RyoheiHagimoto | 0:0e0631af0305 | 175 | |
RyoheiHagimoto | 0:0e0631af0305 | 176 | |
RyoheiHagimoto | 0:0e0631af0305 | 177 | IndexParams getParameters() const |
RyoheiHagimoto | 0:0e0631af0305 | 178 | { |
RyoheiHagimoto | 0:0e0631af0305 | 179 | return index_params_; |
RyoheiHagimoto | 0:0e0631af0305 | 180 | } |
RyoheiHagimoto | 0:0e0631af0305 | 181 | |
RyoheiHagimoto | 0:0e0631af0305 | 182 | /** |
RyoheiHagimoto | 0:0e0631af0305 | 183 | * \brief Perform k-nearest neighbor search |
RyoheiHagimoto | 0:0e0631af0305 | 184 | * \param[in] queries The query points for which to find the nearest neighbors |
RyoheiHagimoto | 0:0e0631af0305 | 185 | * \param[out] indices The indices of the nearest neighbors found |
RyoheiHagimoto | 0:0e0631af0305 | 186 | * \param[out] dists Distances to the nearest neighbors found |
RyoheiHagimoto | 0:0e0631af0305 | 187 | * \param[in] knn Number of nearest neighbors to return |
RyoheiHagimoto | 0:0e0631af0305 | 188 | * \param[in] params Search parameters |
RyoheiHagimoto | 0:0e0631af0305 | 189 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 190 | virtual void knnSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, int knn, const SearchParams& params) |
RyoheiHagimoto | 0:0e0631af0305 | 191 | { |
RyoheiHagimoto | 0:0e0631af0305 | 192 | assert(queries.cols == veclen()); |
RyoheiHagimoto | 0:0e0631af0305 | 193 | assert(indices.rows >= queries.rows); |
RyoheiHagimoto | 0:0e0631af0305 | 194 | assert(dists.rows >= queries.rows); |
RyoheiHagimoto | 0:0e0631af0305 | 195 | assert(int(indices.cols) >= knn); |
RyoheiHagimoto | 0:0e0631af0305 | 196 | assert(int(dists.cols) >= knn); |
RyoheiHagimoto | 0:0e0631af0305 | 197 | |
RyoheiHagimoto | 0:0e0631af0305 | 198 | |
RyoheiHagimoto | 0:0e0631af0305 | 199 | KNNUniqueResultSet<DistanceType> resultSet(knn); |
RyoheiHagimoto | 0:0e0631af0305 | 200 | for (size_t i = 0; i < queries.rows; i++) { |
RyoheiHagimoto | 0:0e0631af0305 | 201 | resultSet.clear(); |
RyoheiHagimoto | 0:0e0631af0305 | 202 | std::fill_n(indices[i], knn, -1); |
RyoheiHagimoto | 0:0e0631af0305 | 203 | std::fill_n(dists[i], knn, std::numeric_limits<DistanceType>::max()); |
RyoheiHagimoto | 0:0e0631af0305 | 204 | findNeighbors(resultSet, queries[i], params); |
RyoheiHagimoto | 0:0e0631af0305 | 205 | if (get_param(params,"sorted",true)) resultSet.sortAndCopy(indices[i], dists[i], knn); |
RyoheiHagimoto | 0:0e0631af0305 | 206 | else resultSet.copy(indices[i], dists[i], knn); |
RyoheiHagimoto | 0:0e0631af0305 | 207 | } |
RyoheiHagimoto | 0:0e0631af0305 | 208 | } |
RyoheiHagimoto | 0:0e0631af0305 | 209 | |
RyoheiHagimoto | 0:0e0631af0305 | 210 | |
RyoheiHagimoto | 0:0e0631af0305 | 211 | /** |
RyoheiHagimoto | 0:0e0631af0305 | 212 | * Find set of nearest neighbors to vec. Their indices are stored inside |
RyoheiHagimoto | 0:0e0631af0305 | 213 | * the result object. |
RyoheiHagimoto | 0:0e0631af0305 | 214 | * |
RyoheiHagimoto | 0:0e0631af0305 | 215 | * Params: |
RyoheiHagimoto | 0:0e0631af0305 | 216 | * result = the result object in which the indices of the nearest-neighbors are stored |
RyoheiHagimoto | 0:0e0631af0305 | 217 | * vec = the vector for which to search the nearest neighbors |
RyoheiHagimoto | 0:0e0631af0305 | 218 | * maxCheck = the maximum number of restarts (in a best-bin-first manner) |
RyoheiHagimoto | 0:0e0631af0305 | 219 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 220 | void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& /*searchParams*/) |
RyoheiHagimoto | 0:0e0631af0305 | 221 | { |
RyoheiHagimoto | 0:0e0631af0305 | 222 | getNeighbors(vec, result); |
RyoheiHagimoto | 0:0e0631af0305 | 223 | } |
RyoheiHagimoto | 0:0e0631af0305 | 224 | |
RyoheiHagimoto | 0:0e0631af0305 | 225 | private: |
RyoheiHagimoto | 0:0e0631af0305 | 226 | /** Defines the comparator on score and index |
RyoheiHagimoto | 0:0e0631af0305 | 227 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 228 | typedef std::pair<float, unsigned int> ScoreIndexPair; |
RyoheiHagimoto | 0:0e0631af0305 | 229 | struct SortScoreIndexPairOnSecond |
RyoheiHagimoto | 0:0e0631af0305 | 230 | { |
RyoheiHagimoto | 0:0e0631af0305 | 231 | bool operator()(const ScoreIndexPair& left, const ScoreIndexPair& right) const |
RyoheiHagimoto | 0:0e0631af0305 | 232 | { |
RyoheiHagimoto | 0:0e0631af0305 | 233 | return left.second < right.second; |
RyoheiHagimoto | 0:0e0631af0305 | 234 | } |
RyoheiHagimoto | 0:0e0631af0305 | 235 | }; |
RyoheiHagimoto | 0:0e0631af0305 | 236 | |
RyoheiHagimoto | 0:0e0631af0305 | 237 | /** Fills the different xor masks to use when getting the neighbors in multi-probe LSH |
RyoheiHagimoto | 0:0e0631af0305 | 238 | * @param key the key we build neighbors from |
RyoheiHagimoto | 0:0e0631af0305 | 239 | * @param lowest_index the lowest index of the bit set |
RyoheiHagimoto | 0:0e0631af0305 | 240 | * @param level the multi-probe level we are at |
RyoheiHagimoto | 0:0e0631af0305 | 241 | * @param xor_masks all the xor mask |
RyoheiHagimoto | 0:0e0631af0305 | 242 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 243 | void fill_xor_mask(lsh::BucketKey key, int lowest_index, unsigned int level, |
RyoheiHagimoto | 0:0e0631af0305 | 244 | std::vector<lsh::BucketKey>& xor_masks) |
RyoheiHagimoto | 0:0e0631af0305 | 245 | { |
RyoheiHagimoto | 0:0e0631af0305 | 246 | xor_masks.push_back(key); |
RyoheiHagimoto | 0:0e0631af0305 | 247 | if (level == 0) return; |
RyoheiHagimoto | 0:0e0631af0305 | 248 | for (int index = lowest_index - 1; index >= 0; --index) { |
RyoheiHagimoto | 0:0e0631af0305 | 249 | // Create a new key |
RyoheiHagimoto | 0:0e0631af0305 | 250 | lsh::BucketKey new_key = key | (1 << index); |
RyoheiHagimoto | 0:0e0631af0305 | 251 | fill_xor_mask(new_key, index, level - 1, xor_masks); |
RyoheiHagimoto | 0:0e0631af0305 | 252 | } |
RyoheiHagimoto | 0:0e0631af0305 | 253 | } |
RyoheiHagimoto | 0:0e0631af0305 | 254 | |
RyoheiHagimoto | 0:0e0631af0305 | 255 | /** Performs the approximate nearest-neighbor search. |
RyoheiHagimoto | 0:0e0631af0305 | 256 | * @param vec the feature to analyze |
RyoheiHagimoto | 0:0e0631af0305 | 257 | * @param do_radius flag indicating if we check the radius too |
RyoheiHagimoto | 0:0e0631af0305 | 258 | * @param radius the radius if it is a radius search |
RyoheiHagimoto | 0:0e0631af0305 | 259 | * @param do_k flag indicating if we limit the number of nn |
RyoheiHagimoto | 0:0e0631af0305 | 260 | * @param k_nn the number of nearest neighbors |
RyoheiHagimoto | 0:0e0631af0305 | 261 | * @param checked_average used for debugging |
RyoheiHagimoto | 0:0e0631af0305 | 262 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 263 | void getNeighbors(const ElementType* vec, bool /*do_radius*/, float radius, bool do_k, unsigned int k_nn, |
RyoheiHagimoto | 0:0e0631af0305 | 264 | float& /*checked_average*/) |
RyoheiHagimoto | 0:0e0631af0305 | 265 | { |
RyoheiHagimoto | 0:0e0631af0305 | 266 | static std::vector<ScoreIndexPair> score_index_heap; |
RyoheiHagimoto | 0:0e0631af0305 | 267 | |
RyoheiHagimoto | 0:0e0631af0305 | 268 | if (do_k) { |
RyoheiHagimoto | 0:0e0631af0305 | 269 | unsigned int worst_score = std::numeric_limits<unsigned int>::max(); |
RyoheiHagimoto | 0:0e0631af0305 | 270 | typename std::vector<lsh::LshTable<ElementType> >::const_iterator table = tables_.begin(); |
RyoheiHagimoto | 0:0e0631af0305 | 271 | typename std::vector<lsh::LshTable<ElementType> >::const_iterator table_end = tables_.end(); |
RyoheiHagimoto | 0:0e0631af0305 | 272 | for (; table != table_end; ++table) { |
RyoheiHagimoto | 0:0e0631af0305 | 273 | size_t key = table->getKey(vec); |
RyoheiHagimoto | 0:0e0631af0305 | 274 | std::vector<lsh::BucketKey>::const_iterator xor_mask = xor_masks_.begin(); |
RyoheiHagimoto | 0:0e0631af0305 | 275 | std::vector<lsh::BucketKey>::const_iterator xor_mask_end = xor_masks_.end(); |
RyoheiHagimoto | 0:0e0631af0305 | 276 | for (; xor_mask != xor_mask_end; ++xor_mask) { |
RyoheiHagimoto | 0:0e0631af0305 | 277 | size_t sub_key = key ^ (*xor_mask); |
RyoheiHagimoto | 0:0e0631af0305 | 278 | const lsh::Bucket* bucket = table->getBucketFromKey(sub_key); |
RyoheiHagimoto | 0:0e0631af0305 | 279 | if (bucket == 0) continue; |
RyoheiHagimoto | 0:0e0631af0305 | 280 | |
RyoheiHagimoto | 0:0e0631af0305 | 281 | // Go over each descriptor index |
RyoheiHagimoto | 0:0e0631af0305 | 282 | std::vector<lsh::FeatureIndex>::const_iterator training_index = bucket->begin(); |
RyoheiHagimoto | 0:0e0631af0305 | 283 | std::vector<lsh::FeatureIndex>::const_iterator last_training_index = bucket->end(); |
RyoheiHagimoto | 0:0e0631af0305 | 284 | DistanceType hamming_distance; |
RyoheiHagimoto | 0:0e0631af0305 | 285 | |
RyoheiHagimoto | 0:0e0631af0305 | 286 | // Process the rest of the candidates |
RyoheiHagimoto | 0:0e0631af0305 | 287 | for (; training_index < last_training_index; ++training_index) { |
RyoheiHagimoto | 0:0e0631af0305 | 288 | hamming_distance = distance_(vec, dataset_[*training_index], dataset_.cols); |
RyoheiHagimoto | 0:0e0631af0305 | 289 | |
RyoheiHagimoto | 0:0e0631af0305 | 290 | if (hamming_distance < worst_score) { |
RyoheiHagimoto | 0:0e0631af0305 | 291 | // Insert the new element |
RyoheiHagimoto | 0:0e0631af0305 | 292 | score_index_heap.push_back(ScoreIndexPair(hamming_distance, training_index)); |
RyoheiHagimoto | 0:0e0631af0305 | 293 | std::push_heap(score_index_heap.begin(), score_index_heap.end()); |
RyoheiHagimoto | 0:0e0631af0305 | 294 | |
RyoheiHagimoto | 0:0e0631af0305 | 295 | if (score_index_heap.size() > (unsigned int)k_nn) { |
RyoheiHagimoto | 0:0e0631af0305 | 296 | // Remove the highest distance value as we have too many elements |
RyoheiHagimoto | 0:0e0631af0305 | 297 | std::pop_heap(score_index_heap.begin(), score_index_heap.end()); |
RyoheiHagimoto | 0:0e0631af0305 | 298 | score_index_heap.pop_back(); |
RyoheiHagimoto | 0:0e0631af0305 | 299 | // Keep track of the worst score |
RyoheiHagimoto | 0:0e0631af0305 | 300 | worst_score = score_index_heap.front().first; |
RyoheiHagimoto | 0:0e0631af0305 | 301 | } |
RyoheiHagimoto | 0:0e0631af0305 | 302 | } |
RyoheiHagimoto | 0:0e0631af0305 | 303 | } |
RyoheiHagimoto | 0:0e0631af0305 | 304 | } |
RyoheiHagimoto | 0:0e0631af0305 | 305 | } |
RyoheiHagimoto | 0:0e0631af0305 | 306 | } |
RyoheiHagimoto | 0:0e0631af0305 | 307 | else { |
RyoheiHagimoto | 0:0e0631af0305 | 308 | typename std::vector<lsh::LshTable<ElementType> >::const_iterator table = tables_.begin(); |
RyoheiHagimoto | 0:0e0631af0305 | 309 | typename std::vector<lsh::LshTable<ElementType> >::const_iterator table_end = tables_.end(); |
RyoheiHagimoto | 0:0e0631af0305 | 310 | for (; table != table_end; ++table) { |
RyoheiHagimoto | 0:0e0631af0305 | 311 | size_t key = table->getKey(vec); |
RyoheiHagimoto | 0:0e0631af0305 | 312 | std::vector<lsh::BucketKey>::const_iterator xor_mask = xor_masks_.begin(); |
RyoheiHagimoto | 0:0e0631af0305 | 313 | std::vector<lsh::BucketKey>::const_iterator xor_mask_end = xor_masks_.end(); |
RyoheiHagimoto | 0:0e0631af0305 | 314 | for (; xor_mask != xor_mask_end; ++xor_mask) { |
RyoheiHagimoto | 0:0e0631af0305 | 315 | size_t sub_key = key ^ (*xor_mask); |
RyoheiHagimoto | 0:0e0631af0305 | 316 | const lsh::Bucket* bucket = table->getBucketFromKey(sub_key); |
RyoheiHagimoto | 0:0e0631af0305 | 317 | if (bucket == 0) continue; |
RyoheiHagimoto | 0:0e0631af0305 | 318 | |
RyoheiHagimoto | 0:0e0631af0305 | 319 | // Go over each descriptor index |
RyoheiHagimoto | 0:0e0631af0305 | 320 | std::vector<lsh::FeatureIndex>::const_iterator training_index = bucket->begin(); |
RyoheiHagimoto | 0:0e0631af0305 | 321 | std::vector<lsh::FeatureIndex>::const_iterator last_training_index = bucket->end(); |
RyoheiHagimoto | 0:0e0631af0305 | 322 | DistanceType hamming_distance; |
RyoheiHagimoto | 0:0e0631af0305 | 323 | |
RyoheiHagimoto | 0:0e0631af0305 | 324 | // Process the rest of the candidates |
RyoheiHagimoto | 0:0e0631af0305 | 325 | for (; training_index < last_training_index; ++training_index) { |
RyoheiHagimoto | 0:0e0631af0305 | 326 | // Compute the Hamming distance |
RyoheiHagimoto | 0:0e0631af0305 | 327 | hamming_distance = distance_(vec, dataset_[*training_index], dataset_.cols); |
RyoheiHagimoto | 0:0e0631af0305 | 328 | if (hamming_distance < radius) score_index_heap.push_back(ScoreIndexPair(hamming_distance, training_index)); |
RyoheiHagimoto | 0:0e0631af0305 | 329 | } |
RyoheiHagimoto | 0:0e0631af0305 | 330 | } |
RyoheiHagimoto | 0:0e0631af0305 | 331 | } |
RyoheiHagimoto | 0:0e0631af0305 | 332 | } |
RyoheiHagimoto | 0:0e0631af0305 | 333 | } |
RyoheiHagimoto | 0:0e0631af0305 | 334 | |
RyoheiHagimoto | 0:0e0631af0305 | 335 | /** Performs the approximate nearest-neighbor search. |
RyoheiHagimoto | 0:0e0631af0305 | 336 | * This is a slower version than the above as it uses the ResultSet |
RyoheiHagimoto | 0:0e0631af0305 | 337 | * @param vec the feature to analyze |
RyoheiHagimoto | 0:0e0631af0305 | 338 | */ |
RyoheiHagimoto | 0:0e0631af0305 | 339 | void getNeighbors(const ElementType* vec, ResultSet<DistanceType>& result) |
RyoheiHagimoto | 0:0e0631af0305 | 340 | { |
RyoheiHagimoto | 0:0e0631af0305 | 341 | typename std::vector<lsh::LshTable<ElementType> >::const_iterator table = tables_.begin(); |
RyoheiHagimoto | 0:0e0631af0305 | 342 | typename std::vector<lsh::LshTable<ElementType> >::const_iterator table_end = tables_.end(); |
RyoheiHagimoto | 0:0e0631af0305 | 343 | for (; table != table_end; ++table) { |
RyoheiHagimoto | 0:0e0631af0305 | 344 | size_t key = table->getKey(vec); |
RyoheiHagimoto | 0:0e0631af0305 | 345 | std::vector<lsh::BucketKey>::const_iterator xor_mask = xor_masks_.begin(); |
RyoheiHagimoto | 0:0e0631af0305 | 346 | std::vector<lsh::BucketKey>::const_iterator xor_mask_end = xor_masks_.end(); |
RyoheiHagimoto | 0:0e0631af0305 | 347 | for (; xor_mask != xor_mask_end; ++xor_mask) { |
RyoheiHagimoto | 0:0e0631af0305 | 348 | size_t sub_key = key ^ (*xor_mask); |
RyoheiHagimoto | 0:0e0631af0305 | 349 | const lsh::Bucket* bucket = table->getBucketFromKey((lsh::BucketKey)sub_key); |
RyoheiHagimoto | 0:0e0631af0305 | 350 | if (bucket == 0) continue; |
RyoheiHagimoto | 0:0e0631af0305 | 351 | |
RyoheiHagimoto | 0:0e0631af0305 | 352 | // Go over each descriptor index |
RyoheiHagimoto | 0:0e0631af0305 | 353 | std::vector<lsh::FeatureIndex>::const_iterator training_index = bucket->begin(); |
RyoheiHagimoto | 0:0e0631af0305 | 354 | std::vector<lsh::FeatureIndex>::const_iterator last_training_index = bucket->end(); |
RyoheiHagimoto | 0:0e0631af0305 | 355 | DistanceType hamming_distance; |
RyoheiHagimoto | 0:0e0631af0305 | 356 | |
RyoheiHagimoto | 0:0e0631af0305 | 357 | // Process the rest of the candidates |
RyoheiHagimoto | 0:0e0631af0305 | 358 | for (; training_index < last_training_index; ++training_index) { |
RyoheiHagimoto | 0:0e0631af0305 | 359 | // Compute the Hamming distance |
RyoheiHagimoto | 0:0e0631af0305 | 360 | hamming_distance = distance_(vec, dataset_[*training_index], (int)dataset_.cols); |
RyoheiHagimoto | 0:0e0631af0305 | 361 | result.addPoint(hamming_distance, *training_index); |
RyoheiHagimoto | 0:0e0631af0305 | 362 | } |
RyoheiHagimoto | 0:0e0631af0305 | 363 | } |
RyoheiHagimoto | 0:0e0631af0305 | 364 | } |
RyoheiHagimoto | 0:0e0631af0305 | 365 | } |
RyoheiHagimoto | 0:0e0631af0305 | 366 | |
RyoheiHagimoto | 0:0e0631af0305 | 367 | /** The different hash tables */ |
RyoheiHagimoto | 0:0e0631af0305 | 368 | std::vector<lsh::LshTable<ElementType> > tables_; |
RyoheiHagimoto | 0:0e0631af0305 | 369 | |
RyoheiHagimoto | 0:0e0631af0305 | 370 | /** The data the LSH tables where built from */ |
RyoheiHagimoto | 0:0e0631af0305 | 371 | Matrix<ElementType> dataset_; |
RyoheiHagimoto | 0:0e0631af0305 | 372 | |
RyoheiHagimoto | 0:0e0631af0305 | 373 | /** The size of the features (as ElementType[]) */ |
RyoheiHagimoto | 0:0e0631af0305 | 374 | unsigned int feature_size_; |
RyoheiHagimoto | 0:0e0631af0305 | 375 | |
RyoheiHagimoto | 0:0e0631af0305 | 376 | IndexParams index_params_; |
RyoheiHagimoto | 0:0e0631af0305 | 377 | |
RyoheiHagimoto | 0:0e0631af0305 | 378 | /** table number */ |
RyoheiHagimoto | 0:0e0631af0305 | 379 | unsigned int table_number_; |
RyoheiHagimoto | 0:0e0631af0305 | 380 | /** key size */ |
RyoheiHagimoto | 0:0e0631af0305 | 381 | unsigned int key_size_; |
RyoheiHagimoto | 0:0e0631af0305 | 382 | /** How far should we look for neighbors in multi-probe LSH */ |
RyoheiHagimoto | 0:0e0631af0305 | 383 | unsigned int multi_probe_level_; |
RyoheiHagimoto | 0:0e0631af0305 | 384 | |
RyoheiHagimoto | 0:0e0631af0305 | 385 | /** The XOR masks to apply to a key to get the neighboring buckets */ |
RyoheiHagimoto | 0:0e0631af0305 | 386 | std::vector<lsh::BucketKey> xor_masks_; |
RyoheiHagimoto | 0:0e0631af0305 | 387 | |
RyoheiHagimoto | 0:0e0631af0305 | 388 | Distance distance_; |
RyoheiHagimoto | 0:0e0631af0305 | 389 | }; |
RyoheiHagimoto | 0:0e0631af0305 | 390 | } |
RyoheiHagimoto | 0:0e0631af0305 | 391 | |
RyoheiHagimoto | 0:0e0631af0305 | 392 | #endif //OPENCV_FLANN_LSH_INDEX_H_ |