2012-04-26 164 views
11

我有一些問題OpenCV的FLANN ::首頁 -如何使用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)); 

P1簡化幫助

回答

12

您不應將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 
); 

有竅門。

+4

需要注意的一點是,您需要提供實際的原始數據集,而不僅僅是具有正確尺寸的Mat。 OpenCV文檔中並不十分清楚,但在[flann文檔]的第3.3.4節中提到(http://www.cs.ubc.ca/~mariusm/uploads/FLANN/flann_manual-1.6.pdf) – Sau 2013-04-11 19:41:56

+0

@Sau不是第3.3.4節討論Matlab而不是C++?你有沒有在OpenCV或Flann的C++版本中驗證你的評論? – t2k32316 2015-03-11 04:00:12

1

在接受的答案中,某種程度上不清楚和誤導爲什麼cv::flann::Index構造函數中的輸入矩陣必須與用於生成保存的索引的矩陣具有相同的維數。我會用一個例子來詳細闡述@ Sau的評論。

KDTreeIndex使用作爲輸入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找到)。

現在可以使用的指數示出的查找query點的K最近鄰居:

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點,你可以在以後用它來執行一些inverse distance weighting,例如發現鄰居有多遠。

請注意,sample_size必須匹配sample矩陣和query點。