diff --git a/modules/flann/include/opencv2/flann/kdtree_index.h b/modules/flann/include/opencv2/flann/kdtree_index.h index a279aeae77..1b732b6037 100644 --- a/modules/flann/include/opencv2/flann/kdtree_index.h +++ b/modules/flann/include/opencv2/flann/kdtree_index.h @@ -95,6 +95,9 @@ public: trees_ = get_param(index_params_,"trees",4); tree_roots_ = new NodePtr[trees_]; + for (int i = 0; i < trees_; ++i) { + tree_roots_[i] = NULL; + } // Create a permutable array of indices to the input vectors. vind_.resize(size_); @@ -127,6 +130,13 @@ public: */ void buildIndex() CV_OVERRIDE { + if (size_ == 0) { + for (int i = 0; i < trees_; i++) { + tree_roots_[i] = NULL; + } + return; + } + /* Construct the randomized trees. */ for (int i = 0; i < trees_; i++) { /* Randomize the order of vectors to allow for unbiased sampling. */ @@ -136,7 +146,7 @@ public: std::random_shuffle(vind_.begin(), vind_.end()); #endif - tree_roots_[i] = divideTree(&vind_[0], int(size_) ); + tree_roots_[i] = divideTree(vind_.data(), int(size_) ); } } @@ -208,6 +218,8 @@ public: */ void findNeighbors(ResultSet& result, const ElementType* vec, const SearchParams& searchParams) CV_OVERRIDE { + if (size_ == 0) return; + 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); @@ -286,6 +298,10 @@ private: */ NodePtr divideTree(int* ind, int count) { + if (count <= 0) { + return NULL; + } + NodePtr node = pool_.allocate(); // allocate memory /* If too few exemplars remain, then make this a leaf node. */ @@ -481,6 +497,10 @@ private: void searchLevel(ResultSet& result_set, const ElementType* vec, NodePtr node, DistanceType mindist, int& checkCount, int maxCheck, float epsError, const cv::Ptr>& heap, DynamicBitset& checked, bool explore_all_trees = false) { + if (node == NULL) { + return; + } + if (result_set.worstDist()& result_set, const ElementType* vec, const NodePtr node, DistanceType mindist, const float epsError) { + if (node == NULL) { + return; + } + /* If this is a leaf node, then do check and return. */ if ((node->child1 == NULL)&&(node->child2 == NULL)) { int index = node->divfeat; diff --git a/modules/flann/test/test_radius_search.cpp b/modules/flann/test/test_radius_search.cpp index 5973a2380e..03d4ae7847 100644 --- a/modules/flann/test/test_radius_search.cpp +++ b/modules/flann/test/test_radius_search.cpp @@ -78,4 +78,31 @@ TEST(Flann_Index, radiusSearch_output_size_matches_returned_count) } } +TEST(Flann_Index, empty_data_build_and_search) +{ + cv::flann::KDTreeIndexParams indexParams(1); + cv::Mat data(0, 2, CV_32F); + cv::flann::Index index(data, indexParams); + + cv::Mat query = (cv::Mat_(1, 2) << 1.0f, 2.0f); + std::vector indices; + std::vector dists; + int nn = index.radiusSearch(query, indices, dists, 100, 4); + EXPECT_EQ(nn, 0); + EXPECT_TRUE(indices.empty()); +} + +TEST(Flann_GenericIndex, empty_data_kdtree) +{ + cv::Mat_ features(0, 3); + cv::flann::GenericIndex> index( + features, cvflann::KDTreeIndexParams(1)); + + std::vector query = {1.0, 2.0, 3.0}; + std::vector indices(5, -1); + std::vector distances(5, 0.0); + index.radiusSearch(query, indices, distances, 1.0, cvflann::SearchParams(-1)); + EXPECT_EQ(indices[0], -1); +} + }} // namespace