Изменение поведения с использованием nanoflann

#c #kdtree #flann

#c #kdtree ( кдтри ) #фланн

Вопрос:

Используя библиотеку nanoflann для поиска k-ближайших соседей на основе KDTrees, я столкнулся с очень странным поведением. Мой код представляет собой простой набор запросов:

 #include <vector>
#include <iostream>
#include <nanoflann.hpp>
#include <eigen3/Eigen/Dense>

using Eigen::MatrixX3d;
using Eigen::Vector3d;

using nanoflann::KNNResultSet;
using nanoflann::SearchParams;
using kdt = nanoflann::KDTreeEigenMatrixAdaptor<MatrixX3d, 3, nanoflann::metric_L2>;

int main()
{
    // Create simple matrix
    MatrixX3d matrix(10, 3);
    for(unsigned int i = 0; i < 10; i  )
    {
        double f_i = static_cast<double>(i);
        matrix.row(i) = Vector3d(f_i, 0, 0);
    }

    // Create test points
    std::vector<Vector3d> test_vecs;
    for(unsigned int i = 0; i < 10; i  )
    {
        double f_i = static_cast<double>(i);
        test_vecs.push_back(Vector3d(f_i, f_i, f_i));
    }
    
    // Result buffer
    double distance;
    size_t index;
    KNNResultSet<double> result_set(1);
    result_set.init(amp;index, amp;distance);
    SearchParams sp;
    // KDTree
    kdt matrix_index(3, std::ref(matrix), 10);
    matrix_index.index->buildIndex();

    //Query points backwards
    for(int i = 9; i >= 0; i--)
    {
        Vector3d curr_vec = test_vecs.at(i);
        matrix_index.index->findNeighbors(result_set, amp;curr_vec[0], sp);
        std::cout << i << std::endl;
        std::cout << index << " " << distance << std::endl << std::endl;
    }

    // Query points forwards
    for(unsigned int i = 0; i < 10; i  )
    {
        Vector3d curr_vec = test_vecs.at(i);
        matrix_index.index->findNeighbors(result_set, amp;curr_vec[0], sp);
        std::cout << i << std::endl;
        std::cout << index << " " << distance << std::endl << std::endl;
    }
}
 

Обратный запрос ( BQ ) возвращает ожидаемые результаты. Однако прямой запрос ( FQ ) выдает только нули (как индекс, так и расстояние). FQ также, похоже, полностью разрушает KDTree. Если вы измените порядок двух запросов (последние два цикла for), так что FQ это выполняется до BQ того, как оба теперь будут выдавать только нули.

Почему возникает такое поведение и как его обойти?

Ответ №1:

Комментарии:

1. Это решает проблемы, с которыми я сталкиваюсь, однако я хотел бы понять, почему эта ошибка возникла в первую очередь. Я вижу, что функция init -function сбрасывает некоторую counter переменную KNNResultSet , но для меня все еще немного загадочно, что этот счетчик делает в первую очередь и почему ошибка кажется такой «случайной».

2. Используется только место count in addPoint , которое, по-видимому, поддерживает список из N точек с наименьшим расстоянием (смещая точку только в том случае, если она ниже). Если первое местоположение, которое вы просматриваете, имеет расстояние 0, оно никогда не сместит его, поэтому все это были нули.