2012-04-26 7 views
11

Ho alcuni problemi con OpenCV Flann :: Index -Come usare opencv flann :: Indice?

Sto creando indice

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

D opo che Sto cercando di caricarlo e trovare neiborhoods più vicine

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

E avere violazione di accesso in miniflann.cpp nella riga

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

Pl eas help

risposta

12

Non caricare il file flann in un Mat(), poiché è il luogo in cui è memorizzato l'indice. È un oggetto temporaneo distrutto dopo la chiamata del costruttore. Ecco perché l'indice non punta in alcun modo utile quando chiami knnSearch().

Ho cercato seguente:

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

conseguente:

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

che significa, che la matrice deve essere inizializzato con le dimensioni corrette (sembra molto stupido me, come I don' so per forza, quanti elementi sono memorizzati nel mio indice).

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

fa il trucco.

+4

Un punto da notare è che è necessario fornire il dataset originale effettivo, non solo un Mat con le dimensioni corrette. Non è molto chiaro nella documentazione di OpenCV, ma è citato nella Sezione 3.3.4 della [documentazione di flann] (http://www.cs.ubc.ca/~mariusm/uploads/FLANN/flann_manual-1.6.pdf) – Sau

+0

@Sau non è la Sezione 3.3.4 che parla di Matlab e non di C++? Hai verificato il tuo commento in OpenCV o nella versione C++ di flann? – t2k32316

1

Nella risposta accettata è in qualche modo non chiaro e fuorviante il motivo per cui la matrice di input nel costruttore deve avere la stessa dimensione della matrice utilizzata per generare l'indice salvato. Elaborerò il commento di @ Sau con un esempio.

KDTreeIndex è stato generato utilizzando come input un cv::Mat sample e quindi salvato. Quando si carica, è necessario fornire lo stesso sample matrice per generare esso, qualcosa di simile (utilizzando l'interfaccia su modelli 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 è la distanza euclidea solito (altri tipi possono essere trovati in opencv2/flann/dist.h).

Ora l'indice può essere utilizzato come indicato il trovare le K vicini più prossimi di un punto 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)); 

La matrice indices conterrà le posizioni delle vicini più prossiminella matrice sample, che è stato utilizzato inizialmente per generare l'indice. Ecco perché è necessario caricare l'indice salvato con la matrice utilizzata per generare l'indice, altrimenti il ​​vettore restituito conterrà indici che puntano a "vicini più vicini" privi di significato.

Inoltre si ottiene una matrice distances che contiene quanto sono lontani i vicini dal proprio punto , che è possibile utilizzare successivamente per eseguire alcuni inverse distance weighting, ad esempio.

Si noti inoltre che lo sample_size deve corrispondere alla matrice sample e al punto query.