2013-03-04 17 views
6

Sto provando a creare un programma C++ in cui ci sono molte immagini in un elenco rispetto a un'immagine di input. Ho capito tutto e il programma sta creando le partite DMatch.OpenCV: confronto di più immagini utilizzando ORB

Ora sto cercando di determinare quale della lista di immagini che viene confrontata con l'immagine sorgente è la migliore corrispondenza. Ho provato per la prima volta a fare questo semplicemente confrontando quante partite ci sono tra le immagini, ma il problema è che quando un'immagine generata ha molti punti chiave; inoltre tendono ad avere molte partite, almeno nel mio programma.

Quindi, come è possibile determinare quale matrice di immagini corrisponde alla migliore immagine sorgente? Sto usando questo ciclo per determinare le partite, ma in realtà non funziona:

vector< vector<DMatch> > filteredMatches; 
vector<int> goodIds; 
Ptr<DescriptorMatcher> matcher(new BFMatcher(NORM_HAMMING, false)); 

printf("bad matches: "); 

for(size_t i = 0; i < images.size();i++){ 
    vector<DMatch> matches, good_matches; 

    matcher->clear(); 
    matcher->match(images[i], tex_des, matches); 
    if(matches.size() < 8){ 
     printf("F%d,", (int)i + 1); 
     continue; 
    } 

    double min_dist = 100; 

    for(size_t j = 0; j < matches.size(); j++){ 
     double dist = matches[j].distance; 
     if(dist < min_dist) 
      min_dist = dist; 
    } 

    if(min_dist > 50.0){ 
     printf("D%d,", (int)i + 1); 
     continue; 
    } 

    double good_dist = min_dist * 3; 
    for(size_t j = 0; j < matches.size(); j++){ 
     if(matches[j].distance < good_dist) 
      good_matches.push_back(matches[j]); 
    } 

    size_t size = good_matches.size(); 
    if(size < 8){ 
     printf("M%d,", (int)i + 1); 
     continue; 
    } 

    vector<Point2f> srcPoints(size); 
    vector<Point2f> dstPoints(size); 

    for(size_t j = 0; j < size; j++){ 
     srcPoints[j] = destination[good_matches[j].trainIdx].pt;  
     dstPoints[j] = keyPoints[i][good_matches[j].queryIdx].pt; 
    } 

    vector<unsigned char> inliersMask(srcPoints.size()); 
    Mat H = findHomography(srcPoints, dstPoints, CV_FM_RANSAC, 3.0, inliersMask); 

    vector<DMatch> inliers; 
    for(size_t j = 0; j < inliersMask.size(); j++){ 
     if(inliersMask[j]){ 
      inliers.push_back(good_matches[j]); 
     } 
    } 
    if(inliers.size() < 4){ 
     printf("S%d,", (int)i + 1); 
     continue; 
    } 

    filteredMatches.push_back(inliers); 
    goodIds.push_back((int)i); 

    H.release(); 
} 

printf(" good matches: "); 

int best = -1; 
int amount = 0; 
for(size_t i = 0; i < filteredMatches.size(); i++){ 
    int size = (int)filteredMatches.at(i).size(); 
    if(size < 8) continue; 

    printf("%d,", goodIds[i] + 1); 

    if(amount < size){ 
     amount = size; 
     best = i; 
    } 
} 

if(best >= 0) printf(" best match on image: %d, keypoints: %d, ", goodIds[best] + 1, amount); 

Se qualcuno mi può indicare le funzioni o la logica devo usare sarei molto grato!

+0

Qual è il problema nel dire "La partita con il maggior numero di inlier è la mia migliore partita"? –

+0

Anche questa è stata la prima cosa che ho pensato, ma quando l'ho provato non ho ottenuto risultati accurati. – tversteeg

+0

OK, quindi le immagini (anche quelle false) sono abbastanza simili credo. Com'è la precisione se prendi la distanza media di tutte le partite o di tutti gli inlier? Puoi pubblicare immagini di esempio in cui ciò non riesce? –

risposta

0

una breve ricerca per il vostro problema mi ha fornito seguente voce in sezioni OpenCV risposta:

/CV Answer forum

che sembra fornire la risposta alla domanda che sembrano avere. Per filtrare i risultati ottenuti come suggerito nella risposta, darei un'occhiata all'algoritmo RANSAC, per trovare i migliori risultati nella selezione delle partite.

RANSAC desctiption Wikipedia

Almeno questo dovrebbe puntare nella giusta direzione.

+0

Se si guarda il mio codice, è possibile vedere che sto già utilizzando RANSAC. – tversteeg

0

Dipende da cosa è l'immagine nell'elenco. Non puoi avere una soluzione per ogni problema di visione nel mondo. Ad esempio, il progetto su cui lavoro ha bisogno di riconoscere il materiale nelle immagini dei muri. Non puoi semplicemente confrontarlo con una diversa immagine di muro con materiali diversi e sperare di ottenere una corrispondenza.

Nel mio caso, avevo bisogno di creare descrittori. Descriptors sono un algoritmo con un valore di output che può essere confrontato con un altro valore di un'altra immagine. Ci sono molti descrittori già disponibili in openCV come LBP, SURF, ecc. Per dirla semplicemente, non si confronta più l'immagine, si confronta il valore di uscita del descrittore dell'immagine 1 con il valore del descrittore di tutti immagine nella lista.

È necessario raccogliere i descrittori che gli occhi/il cervello utilizzano per trovare una corrispondenza nella vita reale. Ad esempio, se la corrispondenza è basata sul colore, è possibile utilizzare CLD o DCD. Se la corrispondenza è basata sulla trama, utilizzare LBP. Puoi anche fare come ho fatto nel mio progetto e usare un sacco di descrittori e utilizzare Machine Learning con algoritmi di dati addestrati per trovare la migliore corrispondenza.

Quindi, per riassumere, non esiste un proiettile d'argento in grado di risolvere tutti i problemi di visione. Devi adattare la tua soluzione al problema.

Spero che aiuti!

1

Non c'è una risposta semplice. Per ottenere risultati migliori, devi implementare una sorta di trasformazione e fare il clustering sulla mappa trasformata invece di sommare le distanze. È difficile e anche publishable.

In caso contrario, sarà necessario utilizzare più tecniche pratiche come il filtro dimensionale e istogramma. Puoi dare un'occhiata a stitcher di OpenCV, isolare il modulo che ti interessa e personalizzare il codice sorgente in base alle tue esigenze.

Problemi correlati