From e85bacff7b676a7789bea6501e694cac299b21be Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Viel Date: Thu, 26 Dec 2013 19:44:23 +0100 Subject: [PATCH 1/4] Avoid obtaining several identical dimensions between two LSH sub-vectors by choosing orthogonal sub-vectors. --- modules/flann/include/opencv2/flann/lsh_table.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/modules/flann/include/opencv2/flann/lsh_table.h b/modules/flann/include/opencv2/flann/lsh_table.h index b0f3223851..6b8d614f23 100644 --- a/modules/flann/include/opencv2/flann/lsh_table.h +++ b/modules/flann/include/opencv2/flann/lsh_table.h @@ -348,13 +348,21 @@ inline LshTable::LshTable(unsigned int feature_size, unsigned int mask_ = std::vector((size_t)ceil((float)(feature_size * sizeof(char)) / (float)sizeof(size_t)), 0); // A bit brutal but fast to code - std::vector indices(feature_size * CHAR_BIT); - for (size_t i = 0; i < feature_size * CHAR_BIT; ++i) indices[i] = i; - std::random_shuffle(indices.begin(), indices.end()); + static std::vector indices(feature_size * CHAR_BIT); + + //Ensure the Nth bit will be selected only once among the different LshTables + //to avoid having two different tables with signatures sharing many dimensions/many bits + if( (indices.size() == feature_size * CHAR_BIT) || (indices.size() < key_size_) ) + { + indices.resize( feature_size * CHAR_BIT ); + for (size_t i = 0; i < feature_size * CHAR_BIT; ++i) indices[i] = i; + std::random_shuffle(indices.begin(), indices.end()); + } // Generate a random set of order of subsignature_size_ bits for (unsigned int i = 0; i < key_size_; ++i) { - size_t index = indices[i]; + size_t index = indices[0]; + indices.erase( indices.begin() ); // Set that bit in the mask size_t divisor = CHAR_BIT * sizeof(size_t); From 8e93c19de311a76704028b0195abfe04cfad900d Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Viel Date: Thu, 26 Dec 2013 23:04:54 +0100 Subject: [PATCH 2/4] Fix a heap issue with static on Windows --- .../flann/include/opencv2/flann/lsh_table.h | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/modules/flann/include/opencv2/flann/lsh_table.h b/modules/flann/include/opencv2/flann/lsh_table.h index 6b8d614f23..18fb139c91 100644 --- a/modules/flann/include/opencv2/flann/lsh_table.h +++ b/modules/flann/include/opencv2/flann/lsh_table.h @@ -348,21 +348,27 @@ inline LshTable::LshTable(unsigned int feature_size, unsigned int mask_ = std::vector((size_t)ceil((float)(feature_size * sizeof(char)) / (float)sizeof(size_t)), 0); // A bit brutal but fast to code - static std::vector indices(feature_size * CHAR_BIT); + static std::vector* indices = NULL; //Ensure the Nth bit will be selected only once among the different LshTables //to avoid having two different tables with signatures sharing many dimensions/many bits - if( (indices.size() == feature_size * CHAR_BIT) || (indices.size() < key_size_) ) + if( indices == NULL ) { - indices.resize( feature_size * CHAR_BIT ); - for (size_t i = 0; i < feature_size * CHAR_BIT; ++i) indices[i] = i; - std::random_shuffle(indices.begin(), indices.end()); + indices = new std::vector( feature_size * CHAR_BIT ); + } + else if( indices->size() < key_size_ ) + { + indices->resize( feature_size * CHAR_BIT ); + for (size_t i = 0; i < feature_size * CHAR_BIT; ++i) { + (*indices)[i] = i; + } + std::random_shuffle(indices->begin(), indices->end()); } // Generate a random set of order of subsignature_size_ bits for (unsigned int i = 0; i < key_size_; ++i) { - size_t index = indices[0]; - indices.erase( indices.begin() ); + size_t index = (*indices)[0]; + indices->erase( indices->begin() ); // Set that bit in the mask size_t divisor = CHAR_BIT * sizeof(size_t); From e63d7de87c3565555e4a73220a465ed39488160d Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Viel Date: Tue, 20 May 2014 22:52:11 +0200 Subject: [PATCH 3/4] Allows to choose orthogonal sub-vectors for LSH without using a static table among LshTable instances --- .../flann/include/opencv2/flann/lsh_index.h | 14 ++++++++- .../flann/include/opencv2/flann/lsh_table.h | 30 +++++-------------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/modules/flann/include/opencv2/flann/lsh_index.h b/modules/flann/include/opencv2/flann/lsh_index.h index 4d4670ea50..2530a0143a 100644 --- a/modules/flann/include/opencv2/flann/lsh_index.h +++ b/modules/flann/include/opencv2/flann/lsh_index.h @@ -109,10 +109,22 @@ public: */ void buildIndex() { + std::vector indices(feature_size_ * CHAR_BIT); + tables_.resize(table_number_); for (unsigned int i = 0; i < table_number_; ++i) { + + //re-initialize the random indices table that the LshTable will use to pick its sub-dimensions + if( (indices.size() == feature_size_ * CHAR_BIT) || (indices.size() < key_size_) ) + { + indices.resize( feature_size_ * CHAR_BIT ); + for (size_t i = 0; i < feature_size_ * CHAR_BIT; ++i) + indices[i] = i; + std::random_shuffle(indices.begin(), indices.end()); + } + lsh::LshTable& table = tables_[i]; - table = lsh::LshTable(feature_size_, key_size_); + table = lsh::LshTable(feature_size_, key_size_, indices); // Add the features to the table table.add(dataset_); diff --git a/modules/flann/include/opencv2/flann/lsh_table.h b/modules/flann/include/opencv2/flann/lsh_table.h index 18fb139c91..f6e68dc767 100644 --- a/modules/flann/include/opencv2/flann/lsh_table.h +++ b/modules/flann/include/opencv2/flann/lsh_table.h @@ -153,7 +153,7 @@ public: * @param feature_size is the size of the feature (considered as a ElementType[]) * @param key_size is the number of bits that are turned on in the feature */ - LshTable(unsigned int /*feature_size*/, unsigned int /*key_size*/) + LshTable(unsigned int /*feature_size*/, unsigned int /*key_size*/, std::vector & /*indices*/) { std::cerr << "LSH is not implemented for that type" << std::endl; assert(0); @@ -341,34 +341,20 @@ private: // Specialization for unsigned char template<> -inline LshTable::LshTable(unsigned int feature_size, unsigned int subsignature_size) +inline LshTable::LshTable( unsigned int feature_size, + unsigned int subsignature_size, + std::vector & indices ) { initialize(subsignature_size); // Allocate the mask mask_ = std::vector((size_t)ceil((float)(feature_size * sizeof(char)) / (float)sizeof(size_t)), 0); - // A bit brutal but fast to code - static std::vector* indices = NULL; - - //Ensure the Nth bit will be selected only once among the different LshTables - //to avoid having two different tables with signatures sharing many dimensions/many bits - if( indices == NULL ) - { - indices = new std::vector( feature_size * CHAR_BIT ); - } - else if( indices->size() < key_size_ ) - { - indices->resize( feature_size * CHAR_BIT ); - for (size_t i = 0; i < feature_size * CHAR_BIT; ++i) { - (*indices)[i] = i; - } - std::random_shuffle(indices->begin(), indices->end()); - } - // Generate a random set of order of subsignature_size_ bits for (unsigned int i = 0; i < key_size_; ++i) { - size_t index = (*indices)[0]; - indices->erase( indices->begin() ); + //Ensure the Nth bit will be selected only once among the different LshTables + //to avoid having two different tables with signatures sharing many dimensions/many bits + size_t index = indices[0]; + indices.erase( indices.begin() ); // Set that bit in the mask size_t divisor = CHAR_BIT * sizeof(size_t); From 2f8b5731dabb3162ca62a0e1901bb13f0ed83e4c Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Viel Date: Wed, 21 May 2014 12:27:38 +0200 Subject: [PATCH 4/4] Fix local variable shadowing --- modules/flann/include/opencv2/flann/lsh_index.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/flann/include/opencv2/flann/lsh_index.h b/modules/flann/include/opencv2/flann/lsh_index.h index 2530a0143a..23988d436a 100644 --- a/modules/flann/include/opencv2/flann/lsh_index.h +++ b/modules/flann/include/opencv2/flann/lsh_index.h @@ -118,8 +118,8 @@ public: if( (indices.size() == feature_size_ * CHAR_BIT) || (indices.size() < key_size_) ) { indices.resize( feature_size_ * CHAR_BIT ); - for (size_t i = 0; i < feature_size_ * CHAR_BIT; ++i) - indices[i] = i; + for (size_t j = 0; j < feature_size_ * CHAR_BIT; ++j) + indices[j] = j; std::random_shuffle(indices.begin(), indices.end()); }