Различные типы возврата и координат в поиске нанофланцевого радиуса

Я пытаюсь использовать нанофланн в проекте и смотрю примеры поиска векторов и радиусов.

Я не могу найти способ выполнить поиск по радиусу с типом данных, отличным от типа координат. Например, мои координаты vectorс uint8_t; Я пытаюсь ввести радиус типа uint32_t с небольшим успехом.

Я вижу в источнике, что metric_L2 struct (который я использую для расстояния) использует L2_Adaptor с двумя параметрами шаблона. L2_Adaptor сам принимает три параметра, третий по умолчанию - первый, что кажется проблемой, если я правильно понимаю код. Однако попытка принудительного использования третьего всегда приводит к 0 совпадениям в поиске радиуса.

Есть ли способ сделать это?

Изменить: в том же коде ниже все работает. Однако, если я изменю search_radius (и ret_matches) на uint32_t, метод radiusSearch не будет работать.

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

typedef Eigen::Matrix<uint8_t, Eigen::Dynamic, 1>   coord_t;

using namespace nanoflann;

struct Point
{
        coord_t address;

        Point() {}
        Point(uint8_t coordinates) : address(coord_t::Random(coordinates)) {}
};

struct Container
{
        std::vector<Point> points;

        Container(uint8_t coordinates, uint32_t l)
        : points(l)
        {
                for(auto& each_location: points)
                {
                        each_location = Point(coordinates);
                }
        }
};

struct ContainerAdaptor
{
        typedef ContainerAdaptor self_t;
        typedef nanoflann::metric_L2::traits<uint8_t, self_t>::distance_t metric_t;
        typedef KDTreeSingleIndexAdaptor<metric_t, self_t, -1, size_t> index_t;

        index_t *index;
        const Container &container;

        ContainerAdaptor(const int dimensions, const Container &container, const int leaf_max_size = 10)
        : container(container)
        {
                assert(container.points.size() != 0 && container.points[0].address.rows() != 0);

                const size_t dims = container.points[0].address.rows();
                index = new index_t(dims, *this, nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size));
                index->buildIndex();
        }

        ~ContainerAdaptor()
        {
                delete index;
        }

        inline void query(const uint8_t *query_point, const size_t num_closest, size_t *out_indices, uint32_t *out_distances_sq, const int ignoreThis = 10) const
        {
                nanoflann::KNNResultSet<uint32_t, size_t, size_t> resultSet(num_closest);
                resultSet.init(out_indices, out_distances_sq);
                index->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
        }

        const self_t& derived() const
        {
                return *this;
        }

        self_t& derived()
        {
                return *this;
        }

        inline size_t kdtree_get_point_count() const
        {
                return container.points.size();
        }

        inline size_t kdtree_distance(const uint8_t *p1, const size_t idx_p2, size_t size) const
        {
                size_t s = 0;
                for (size_t i = 0; i < size; i++)
                {
                        const uint8_t d = p1[i] - container.points[idx_p2].address[i];
                        s += d * d;
                }

                return s;
        }

        inline coord_t::Scalar kdtree_get_pt(const size_t idx, int dim) const
        {
                return container.points[idx].address[dim];
        }

        template <class BBOX>
        bool kdtree_get_bbox(BBOX & bb) const
        {
                for(size_t i = 0; i < bb.size(); i++)
                {
                        bb[i].low = 0;
                        bb[i].high = UINT8_MAX;
                }
                return true;
        }
};

void container_demo(const size_t points, const size_t coordinates)
{
        Container s(coordinates, points);
        coord_t query_pt(coord_t::Random(coordinates));

        typedef ContainerAdaptor my_kd_tree_t;
        my_kd_tree_t mat_index(coordinates, s, 25);
        mat_index.index->buildIndex();

        const uint8_t search_radius = static_cast<uint8_t>(100);
        std::vector<std::pair<size_t, uint8_t>> ret_matches;
        nanoflann::SearchParams params;
        const size_t nMatches = mat_index.index->radiusSearch(query_pt.data(), search_radius, ret_matches, params);

        for (size_t i = 0; i < nMatches; i++)
        {
                std::cout << "idx[" << i << "]=" << +ret_matches[i].first << " dist[" << i << "]=" << +ret_matches[i].second << std::endl;
        }
        std::cout << std::endl;

        std::cout << "radiusSearch(): radius=" << +search_radius << " -> " << +nMatches << " matches" << std::endl;
}

int main()
{
        container_demo(1e6, 32);
    return 0;
}

Больше информации: так кажется, что тип расстояния, который является третьим параметром L2_Adaptor, должен быть подписанным типом. Изменение typedef для metric_t на следующее решает проблему, если search_radius а также ret_matches также изменены на int64_t.

typedef L2_Adaptor<uint8_t, self_t, int64_t> metric_t;

0 ответов

Другие вопросы по тегам