How to use opencv flann::Index?

橙三吉。 提交于 2019-12-02 19:35:05

You should not load the flann-file into a Mat(), as it is the place where the index is stored. It is a temporary object destroyed after the constructor was called. That's why the index isn't pointing anywhere useful when you call knnSearch().

I tried following:

cv::Mat indexMat;
cv::flann::Index flann_index(
    indexMat,
    cv::flann::SavedIndexParams("c:\\index.fln"),
    cvflann::FLANN_DIST_EUCLIDEAN
);

resulting in:

Reading FLANN index error: the saved data size (100, 64) or type (5) is different from the passed one (0, 0), 0

which means, that the matrix has to be initialized with the correct dimensions (seems very stupid to me, as I don't necessarily know, how many elements are stored in my index).

cv::Mat indexMat(samples.size(), CV_32FC1);
cv::flann::Index flann_index(
    indexMat,
    cv::flann::SavedIndexParams("c:\\index.fln"),
    cvflann::FLANN_DIST_EUCLIDEAN
);

does the trick.

In the accepted answer is somehow not clear and misleading why the input matrix in the cv::flann::Index constructor must have the same dimension as the matrix used for generating the saved Index. I'll elaborate on @Sau's comment with an example.

KDTreeIndex was generated using as input a cv::Mat sample, and then saved. When you load it, you must provide the same sample matrix to generate it, something like (using the templated GenericIndex interface):

cv::Mat sample(sample_num, sample_size, ... /* other params */);
cv::flann::SavedIndexParams index_params("c:\\index.fln");
cv::flann::GenericIndex<cvflann::L2<float>> flann_index(sample, index_params);

L2 is the usual Euclidean distance (other types can be found in opencv2/flann/dist.h).

Now the index can be used as shown the find the K nearest neighbours of a query point:

std::vector<float> query(sample_size);
std::vector<int> indices(K);
std::vector<float> distances(K);

flann_index.knnSearch(query, indices, distances, K, cv::flann::SearchParams(64));

The matrix indices will contain the locations of the nearest neighbours in the matrix sample, which was used at first to generate the index. That's why you need to load the saved index with the very matrix used to generate the index, otherwise the returned vector will contain indices pointing to meaningless "nearest neighbours".

In addition you get a distances matrix containing how far are the found neighbours from your query point, which you can later use to perform some inverse distance weighting, for example.

Please also note that sample_size has to match across sample matrix and query point.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!