diff --git a/modules/features2d/misc/java/test/FlannBasedDescriptorMatcherTest.java b/modules/features2d/misc/java/test/FlannBasedDescriptorMatcherTest.java index 2b1aa7a97b..72947a85cd 100644 --- a/modules/features2d/misc/java/test/FlannBasedDescriptorMatcherTest.java +++ b/modules/features2d/misc/java/test/FlannBasedDescriptorMatcherTest.java @@ -43,6 +43,10 @@ public class FlannBasedDescriptorMatcherTest extends OpenCVTestCase { + " 5\n" + " 0.\n" + " <_>\n" + + " explore_all_trees\n" + + " 8\n" + + " 0\n" + + " <_>\n" + " sorted\n" + " 8\n" // FLANN_INDEX_TYPE_BOOL + " 1\n" @@ -68,6 +72,10 @@ public class FlannBasedDescriptorMatcherTest extends OpenCVTestCase { + " type: 5\n" + " value: 0.\n" + " -\n" + + " name: explore_all_trees\n" + + " type: 8\n" + + " value: 0\n" + + " -\n" + " name: sorted\n" + " type: 8\n" // FLANN_INDEX_TYPE_BOOL + " value: 1\n"; @@ -92,6 +100,10 @@ public class FlannBasedDescriptorMatcherTest extends OpenCVTestCase { + " type: 5\n" + " value: 4.\n"// this line is changed! + " -\n" + + " name: explore_all_trees\n" + + " type: 8\n" + + " value: 1\n"// this line is changed! + + " -\n" + " name: sorted\n" + " type: 8\n" // FLANN_INDEX_TYPE_BOOL + " value: 1\n"; diff --git a/modules/features2d/test/test_matchers_algorithmic.cpp b/modules/features2d/test/test_matchers_algorithmic.cpp index 6af6f5ffc7..203b640209 100644 --- a/modules/features2d/test/test_matchers_algorithmic.cpp +++ b/modules/features2d/test/test_matchers_algorithmic.cpp @@ -582,6 +582,10 @@ TEST( Features2d_FlannBasedMatcher, read_write ) " type: 5\n" " value: 4.\n"// this line is changed! " -\n" + " name: explore_all_trees\n" + " type: 8\n" + " value: 0\n" + " -\n" " name: sorted\n" " type: 8\n" // FLANN_INDEX_TYPE_BOOL " value: 1\n"; diff --git a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h index c068e184bb..9d01644aad 100644 --- a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h +++ b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h @@ -548,6 +548,7 @@ public: { const int maxChecks = get_param(searchParams,"checks",32); + const bool explore_all_trees = get_param(searchParams,"explore_all_trees",false); // Priority queue storing intermediate branches in the best-bin-first search Heap* heap = new Heap((int)size_); @@ -555,15 +556,15 @@ public: std::vector checked(size_,false); int checks = 0; for (int i=0; i= maxChecks) && result.full()) + findNN(root[i], result, vec, checks, maxChecks, heap, checked, explore_all_trees); + if (!explore_all_trees && (checks >= maxChecks) && result.full()) break; } BranchSt branch; while (heap->popMin(branch) && (checks& result, const ElementType* vec, int& checks, int maxChecks, - Heap* heap, std::vector& checked) + Heap* heap, std::vector& checked, bool explore_all_trees = false) { if (node->childs==NULL) { - if ((checks>=maxChecks) && result.full()) { + if (!explore_all_trees && (checks>=maxChecks) && result.full()) { return; } for (int i=0; isize; ++i) { @@ -778,7 +779,7 @@ private: } } delete[] domain_distances; - findNN(node->childs[best_index],result,vec, checks, maxChecks, heap, checked); + findNN(node->childs[best_index],result,vec, checks, maxChecks, heap, checked, explore_all_trees); } } diff --git a/modules/flann/include/opencv2/flann/kdtree_index.h b/modules/flann/include/opencv2/flann/kdtree_index.h index acc87a3198..5a3d9d7fe0 100644 --- a/modules/flann/include/opencv2/flann/kdtree_index.h +++ b/modules/flann/include/opencv2/flann/kdtree_index.h @@ -204,14 +204,15 @@ public: */ void findNeighbors(ResultSet& result, const ElementType* vec, const SearchParams& searchParams) CV_OVERRIDE { - int maxChecks = get_param(searchParams,"checks", 32); - float epsError = 1+get_param(searchParams,"eps",0.0f); + const int maxChecks = get_param(searchParams,"checks", 32); + const float epsError = 1+get_param(searchParams,"eps",0.0f); + const bool explore_all_trees = get_param(searchParams,"explore_all_trees",false); if (maxChecks==FLANN_CHECKS_UNLIMITED) { getExactNeighbors(result, vec, epsError); } else { - getNeighbors(result, vec, maxChecks, epsError); + getNeighbors(result, vec, maxChecks, epsError, explore_all_trees); } } @@ -440,7 +441,8 @@ private: * because the tree traversal is abandoned after a given number of descends in * the tree. */ - void getNeighbors(ResultSet& result, const ElementType* vec, int maxCheck, float epsError) + void getNeighbors(ResultSet& result, const ElementType* vec, + int maxCheck, float epsError, bool explore_all_trees = false) { int i; BranchSt branch; @@ -451,12 +453,16 @@ private: /* Search once through each tree down to root. */ for (i = 0; i < trees_; ++i) { - searchLevel(result, vec, tree_roots_[i], 0, checkCount, maxCheck, epsError, heap, checked); + searchLevel(result, vec, tree_roots_[i], 0, checkCount, maxCheck, + epsError, heap, checked, explore_all_trees); + if (!explore_all_trees && (checkCount >= maxCheck) && result.full()) + break; } /* Keep searching other branches from heap until finished. */ while ( heap->popMin(branch) && (checkCount < maxCheck || !result.full() )) { - searchLevel(result, vec, branch.node, branch.mindist, checkCount, maxCheck, epsError, heap, checked); + searchLevel(result, vec, branch.node, branch.mindist, checkCount, maxCheck, + epsError, heap, checked, false); } delete heap; @@ -471,7 +477,7 @@ private: * at least "mindistsq". */ void searchLevel(ResultSet& result_set, const ElementType* vec, NodePtr node, DistanceType mindist, int& checkCount, int maxCheck, - float epsError, Heap* heap, DynamicBitset& checked) + float epsError, Heap* heap, DynamicBitset& checked, bool explore_all_trees = false) { if (result_set.worstDist()divfeat; - if ( checked.test(index) || ((checkCount>=maxCheck)&& result_set.full()) ) return; + if ( checked.test(index) || + (!explore_all_trees && (checkCount>=maxCheck) && result_set.full()) ) { + return; + } checked.set(index); checkCount++; diff --git a/modules/flann/include/opencv2/flann/miniflann.hpp b/modules/flann/include/opencv2/flann/miniflann.hpp index 253290790e..093646254c 100644 --- a/modules/flann/include/opencv2/flann/miniflann.hpp +++ b/modules/flann/include/opencv2/flann/miniflann.hpp @@ -143,6 +143,7 @@ struct CV_EXPORTS SavedIndexParams : public IndexParams struct CV_EXPORTS SearchParams : public IndexParams { + SearchParams( int checks, float eps, bool sorted, bool explore_all_trees ); SearchParams( int checks = 32, float eps = 0, bool sorted = true ); }; diff --git a/modules/flann/include/opencv2/flann/params.h b/modules/flann/include/opencv2/flann/params.h index b8f7331905..dd3092f065 100644 --- a/modules/flann/include/opencv2/flann/params.h +++ b/modules/flann/include/opencv2/flann/params.h @@ -46,6 +46,16 @@ typedef std::map IndexParams; struct SearchParams : public IndexParams { SearchParams(int checks = 32, float eps = 0, bool sorted = true ) + { + init(checks, eps, sorted, false); + } + + SearchParams(int checks, float eps, bool sorted, bool explore_all_trees ) + { + init(checks, eps, sorted, explore_all_trees); + } + + void init(int checks = 32, float eps = 0, bool sorted = true, bool explore_all_trees = false ) { // how many leafs to visit when searching for neighbours (-1 for unlimited) (*this)["checks"] = checks; @@ -53,6 +63,10 @@ struct SearchParams : public IndexParams (*this)["eps"] = eps; // only for radius search, require neighbours sorted by distance (default: true) (*this)["sorted"] = sorted; + // if false, search stops at the tree reaching the number of max checks (original behavior). + // When true, we do a descent in each tree and. Like before the alternative paths + // stored in the heap are not be processed further when max checks is reached. + (*this)["explore_all_trees"] = explore_all_trees; } }; diff --git a/modules/flann/src/miniflann.cpp b/modules/flann/src/miniflann.cpp index 6cb99564e5..5d2d655feb 100644 --- a/modules/flann/src/miniflann.cpp +++ b/modules/flann/src/miniflann.cpp @@ -294,6 +294,23 @@ SavedIndexParams::SavedIndexParams(const String& _filename) p["filename"] = filename; } +SearchParams::SearchParams( int checks, float eps, bool sorted, bool explore_all_trees ) +{ + ::cvflann::IndexParams& p = get_params(*this); + + // how many leafs to visit when searching for neighbours (-1 for unlimited) + p["checks"] = checks; + // search for eps-approximate neighbours (default: 0) + p["eps"] = eps; + // only for radius search, require neighbours sorted by distance (default: true) + p["sorted"] = sorted; + // if false, search stops at the tree reaching the number of max checks (original behavior). + // When true, we do a descent in each tree and. Like before the alternative paths + // stored in the heap are not be processed further when max checks is reached. + p["explore_all_trees"] = explore_all_trees; +} + + SearchParams::SearchParams( int checks, float eps, bool sorted ) { ::cvflann::IndexParams& p = get_params(*this); @@ -304,6 +321,10 @@ SearchParams::SearchParams( int checks, float eps, bool sorted ) p["eps"] = eps; // only for radius search, require neighbours sorted by distance (default: true) p["sorted"] = sorted; + // if false, search stops at the tree reaching the number of max checks (original behavior). + // When true, we do a descent in each tree and. Like before the alternative paths + // stored in the heap are not be processed further when max checks is reached. + p["explore_all_trees"] = false; }