35 #ifndef OPENCV_FLANN_LSH_TABLE_H_
36 #define OPENCV_FLANN_LSH_TABLE_H_
45 #ifdef __GXX_EXPERIMENTAL_CXX0X__
46 # define USE_UNORDERED_MAP 1
48 # define USE_UNORDERED_MAP 0
51 #include <unordered_map>
58 #include "dynamic_bitset.h"
63 #pragma warning(disable: 4702)
77 typedef uint32_t FeatureIndex;
80 typedef unsigned int BucketKey;
94 size_t bucket_size_mean_;
95 size_t bucket_size_median_;
96 size_t bucket_size_min_;
97 size_t bucket_size_max_;
98 size_t bucket_size_std_dev;
124 stats.size_histogram_.end(); iterator !=
end; ++iterator) out << (*iterator)[0] <<
"-" << (*iterator)[1] <<
": " << (*iterator)[2] <<
", ";
137 template<
typename ElementType>
143 #if USE_UNORDERED_MAP
159 speed_level_ = kArray;
167 LshTable(
unsigned int feature_size,
unsigned int key_size)
169 feature_size_ = feature_size;
178 void add(
unsigned int value,
const ElementType* feature)
181 BucketKey key = (lsh::BucketKey)getKey(feature);
183 switch (speed_level_) {
186 buckets_speed_[key].push_back(
value);
190 key_bitset_.set(key);
191 buckets_space_[key].push_back(
value);
196 buckets_space_[key].push_back(
value);
205 void add(Matrix<ElementType> dataset)
207 #if USE_UNORDERED_MAP
208 buckets_space_.rehash((buckets_space_.size() + dataset.rows) * 1.2);
211 for (
unsigned int i = 0; i < dataset.rows; ++i)
add(i, dataset[i]);
218 inline const Bucket* getBucketFromKey(BucketKey key)
const
221 switch (speed_level_) {
224 return &buckets_speed_[key];
228 if (key_bitset_.test(key))
return &buckets_space_.find(key)->second;
234 BucketsSpace::const_iterator bucket_it, bucket_end = buckets_space_.end();
235 bucket_it = buckets_space_.find(key);
237 if (bucket_it == bucket_end)
return 0;
238 else return &bucket_it->second;
247 size_t getKey(
const ElementType* )
const
255 LshStats getStats()
const;
265 kArray, kBitsetHash, kHash
270 void initialize(
size_t key_size)
272 const size_t key_size_lower_bound = 1;
274 const size_t key_size_upper_bound = (
std::min)(
sizeof(BucketKey) * CHAR_BIT + 1,
sizeof(size_t) * CHAR_BIT);
275 if (key_size < key_size_lower_bound || key_size >= key_size_upper_bound)
277 CV_Error(
cv::Error::StsBadArg,
cv::format(
"Invalid key_size (=%d). Valid values for your system are %d <= key_size < %d.", (
int)key_size, (
int)key_size_lower_bound, (
int)key_size_upper_bound));
280 speed_level_ = kHash;
281 key_size_ = (unsigned)key_size;
289 if (speed_level_ == kArray)
return;
292 if (buckets_space_.size() > ((
size_t(1) << key_size_) / 2)) {
293 speed_level_ = kArray;
295 buckets_speed_.resize(
size_t(1) << key_size_);
296 for (BucketsSpace::const_iterator key_bucket = buckets_space_.begin(); key_bucket != buckets_space_.end(); ++key_bucket) buckets_speed_[key_bucket->first] = key_bucket->second;
299 buckets_space_.clear();
305 if (((
std::max(buckets_space_.size(), buckets_speed_.size()) * CHAR_BIT * 3 *
sizeof(BucketKey)) / 10
306 >= (
size_t(1) << key_size_)) || (key_size_ <= 32)) {
307 speed_level_ = kBitsetHash;
308 key_bitset_.resize(
size_t(1) << key_size_);
311 for (BucketsSpace::const_iterator key_bucket = buckets_space_.begin(); key_bucket != buckets_space_.end(); ++key_bucket) key_bitset_.set(key_bucket->first);
314 speed_level_ = kHash;
321 BucketsSpeed buckets_speed_;
325 BucketsSpace buckets_space_;
328 SpeedLevel speed_level_;
333 DynamicBitset key_bitset_;
337 unsigned int key_size_;
339 unsigned int feature_size_;
352 inline LshTable<unsigned char>::LshTable(
unsigned int feature_size,
unsigned int subsignature_size)
354 feature_size_ = feature_size;
355 initialize(subsignature_size);
357 mask_ =
std::vector<size_t>((feature_size *
sizeof(
char) +
sizeof(
size_t) - 1) /
sizeof(
size_t), 0);
361 for (
size_t i = 0; i < feature_size * CHAR_BIT; ++i) indices[i] = (
int)i;
362 #ifndef OPENCV_FLANN_USE_STD_RAND
369 for (
unsigned int i = 0; i < key_size_; ++i) {
370 size_t index = indices[i];
373 size_t divisor = CHAR_BIT *
sizeof(size_t);
375 mask_[
idx] |= size_t(1) << (
index % divisor);
382 BOOST_FOREACH(
size_t mask_block, mask_){
385 bcount += __builtin_popcountll(mask_block);
388 out <<
"mask size : " << mask_.size() <<
std::endl;
398 inline size_t LshTable<unsigned char>::getKey(
const unsigned char* feature)
const
403 const size_t* feature_block_ptr =
reinterpret_cast<const size_t*
> ((
const void*)feature);
408 size_t subsignature = 0;
409 size_t bit_index = 1;
411 for (
unsigned i = 0; i < feature_size_; i +=
sizeof(size_t)) {
413 size_t feature_block;
414 if (i <= feature_size_ -
sizeof(
size_t))
416 feature_block = *feature_block_ptr;
421 memcpy(&tmp, feature_block_ptr, feature_size_ - i);
424 size_t mask_block = mask_[i /
sizeof(size_t)];
427 size_t lowest_bit = mask_block & ~(mask_block - 1);
429 subsignature += (feature_block & lowest_bit) ? bit_index : 0;
431 mask_block ^= lowest_bit;
442 inline LshStats LshTable<unsigned char>::getStats()
const
445 stats.bucket_size_mean_ = 0;
446 if ((buckets_speed_.empty()) && (buckets_space_.empty())) {
447 stats.n_buckets_ = 0;
448 stats.bucket_size_median_ = 0;
449 stats.bucket_size_min_ = 0;
450 stats.bucket_size_max_ = 0;
454 if (!buckets_speed_.empty()) {
455 for (BucketsSpeed::const_iterator pbucket = buckets_speed_.begin(); pbucket != buckets_speed_.end(); ++pbucket) {
456 stats.bucket_sizes_.push_back((lsh::FeatureIndex)pbucket->size());
457 stats.bucket_size_mean_ += pbucket->
size();
459 stats.bucket_size_mean_ /= buckets_speed_.
size();
460 stats.n_buckets_ = buckets_speed_.
size();
463 for (BucketsSpace::const_iterator
x = buckets_space_.begin();
x != buckets_space_.end(); ++
x) {
464 stats.bucket_sizes_.push_back((lsh::FeatureIndex)
x->second.size());
465 stats.bucket_size_mean_ +=
x->second.size();
467 stats.bucket_size_mean_ /= buckets_space_.
size();
468 stats.n_buckets_ = buckets_space_.
size();
477 stats.bucket_size_min_ =
stats.bucket_sizes_.front();
478 stats.bucket_size_max_ =
stats.bucket_sizes_.back();
486 unsigned int bin_start = 0;
487 unsigned int bin_end = 20;
488 bool is_new_bin =
true;
491 if (*iterator < bin_end) {
494 stats.size_histogram_.back()[0] = bin_start;
495 stats.size_histogram_.back()[1] = bin_end - 1;
498 ++
stats.size_histogram_.back()[2];
CV_EXPORTS_W void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask=noArray(), int dtype=-1)
Calculates the per-element sum of two arrays or an array and a scalar.
CV_EXPORTS_W void randShuffle(InputOutputArray dst, double iterFactor=1., RNG *rng=0)
Shuffles the array elements randomly.
int CvScalar value
Definition: core_c.h:720
double double end
Definition: core_c.h:1381
const int * idx
Definition: core_c.h:668
int index
Definition: core_c.h:634
const CvArr CvArr * x
Definition: core_c.h:1195
#define CV_Error(code, msg)
Call the error handler.
Definition: base.hpp:320
CV_EXPORTS String format(const char *fmt,...) CV_FORMAT_PRINTF(1
Returns a text string formatted using the printf-like expression.
std::ostream & operator<<(std::ostream &, const DualQuat< _Tp > &)
OutputArray OutputArray stats
Definition: imgproc.hpp:3975
@ StsUnsupportedFormat
the data format/type is not supported by the function
Definition: base.hpp:110
@ StsBadArg
function arg/param is bad
Definition: base.hpp:74
T random_shuffle(T... args)