mirror of
https://github.com/opencv/opencv.git
synced 2026-09-12 05:11:04 -05:00
Merge pull request #29772 from vrabaud:min_empty
Fix kd-tree on empty data
This commit is contained in:
@@ -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<DistanceType>& 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<Node>(); // allocate memory
|
||||
|
||||
/* If too few exemplars remain, then make this a leaf node. */
|
||||
@@ -481,6 +497,10 @@ private:
|
||||
void searchLevel(ResultSet<DistanceType>& result_set, const ElementType* vec, NodePtr node, DistanceType mindist, int& checkCount, int maxCheck,
|
||||
float epsError, const cv::Ptr<Heap<BranchSt>>& heap, DynamicBitset& checked, bool explore_all_trees = false)
|
||||
{
|
||||
if (node == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result_set.worstDist()<mindist) {
|
||||
// printf("Ignoring branch, too far\n");
|
||||
return;
|
||||
@@ -535,6 +555,10 @@ private:
|
||||
*/
|
||||
void searchLevelExact(ResultSet<DistanceType>& 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;
|
||||
|
||||
@@ -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_<float>(1, 2) << 1.0f, 2.0f);
|
||||
std::vector<int> indices;
|
||||
std::vector<float> 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_<double> features(0, 3);
|
||||
cv::flann::GenericIndex<cvflann::L2_Simple<double>> index(
|
||||
features, cvflann::KDTreeIndexParams(1));
|
||||
|
||||
std::vector<double> query = {1.0, 2.0, 3.0};
|
||||
std::vector<int> indices(5, -1);
|
||||
std::vector<double> distances(5, 0.0);
|
||||
index.radiusSearch(query, indices, distances, 1.0, cvflann::SearchParams(-1));
|
||||
EXPECT_EQ(indices[0], -1);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
Reference in New Issue
Block a user