11

我对 opencv flann::Index 有一些问题-

我正在创建索引

    Mat samples = Mat::zeros(vfv_net_quie.size(),24,CV_32F);
        for (int i =0; i < vfv_net_quie.size();i++)
        {
           for (int j = 0;j<24;j++)
           {
              samples.at<float>(i,j)=(float)vfv_net_quie[i].vfv[j];
           }
        }
    cv::flann::Index flann_index(
            samples,
            cv::flann::KDTreeIndexParams(4),
            cvflann::FLANN_DIST_EUCLIDEAN
               );
    flann_index.save("c:\\index.fln");

之后,我试图加载它并找到最近的 neiborhoods

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

cv::Mat resps(vfv_reg_quie.size(), K, CV_32F);
cv::Mat nresps(vfv_reg_quie.size(), K, CV_32S);
cv::Mat dists(vfv_reg_quie.size(), K, CV_32F);

flann_index.knnSearch(sample,nresps,dists,K,cv::flann::SearchParams(64));

并且在 miniflann.cpp 中存在访问冲突

((IndexType*)index)->knnSearch(_query, _indices, _dists, knn,
                          (const ::cvflann::SearchParams&)get_params(params));

请帮忙

4

2 回答 2

12

您不应该将 flann 文件加载到 aMat()中,因为它是存储索引的地方。它是一个在构造函数被调用后被销毁的临时对象。这就是为什么当您调用knnSearch().

我试过以下:

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

导致:

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

这意味着,必须使用正确的维度初始化矩阵(对我来说似乎很愚蠢,因为我不一定知道索引中存储了多少元素)。

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

成功了。

于 2012-05-10T17:39:32.670 回答
2

在接受的答案中,为什么cv::flann::Index构造函数中的输入矩阵必须与用于生成保存的索引的矩阵具有相同的维度,并不清楚和误导。我将举例详细说明@Sau 的评论。

KDTreeIndex使用 a 作为输入生成cv::Mat sample,然后保存。当您加载它时,您必须提供相同的sample矩阵来生成它,例如(使用模板化GenericIndex界面):

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是通常的欧几里得距离(其他类型可以在 中找到opencv2/flann/dist.h)。

现在可以使用索引,如图所示找到一个点的K最近邻居:query

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));

该矩阵indices将包含矩阵中最近邻居的位置该矩阵最初用于生成索引。这就是为什么您需要使用用于生成索引的矩阵加载保存的索引,否则返回的向量将包含指向无意义的“最近邻居”的索引。 sample

此外,您还会得到一个distances矩阵,其中包含找到的邻居距您的点有多远query,例如,您以后可以使用它来执行一些反距离加权

另请注意,必须跨矩阵和点sample_size匹配。samplequery

于 2016-12-07T09:23:41.293 回答