我对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));
请帮忙
你不应该将flann文件加载到 Mat()
,因为它是存储索引的地方。它是在调用构造函数后销毁的临时对象。这就是为什么当你打电话时索引没有指向任何有用的原因 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
);
诀窍。
你不应该将flann文件加载到 Mat()
,因为它是存储索引的地方。它是在调用构造函数后销毁的临时对象。这就是为什么当你打电话时索引没有指向任何有用的原因 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
);
诀窍。
在接受的答案中,某种程度上不清楚和误导为什么输入矩阵在 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
必须匹配 sample
矩阵和 query
点。