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());
}