2013-03-04 12 views
6

Ich versuche, ein C++ - Programm zu erstellen, wo viele Bilder in einer Liste verglichen mit einem Eingabebild sind. Ich habe die ganze Sache funktioniert und das Programm erstellt DMatch Matches.OpenCV: Vergleichen mehrerer Bilder mit ORB

Jetzt versuche ich festzustellen, welche der Liste der Bilder, die mit dem Quellbild verglichen wird, die beste Übereinstimmung ist. Ich habe zuerst versucht, dies zu tun, indem ich nur die Anzahl der Übereinstimmungen zwischen den Bildern verglichen habe, aber das Problem ist, dass wenn ein generiertes Bild viele Schlüsselpunkte hat; Sie haben auch eine Menge Übereinstimmungen, zumindest in meinem Programm.

Also, wie kann ich feststellen, welche der Anordnung von Bildern ist die beste Übereinstimmung mit dem Quellbild? Ich verwende diese Schleife die Spiele, um zu bestimmen, aber es funktioniert nicht wirklich:

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

Wenn mich jemand auf die Funktionen oder die Logik Punkt kann ich muss verwenden würde ich es sehr zu schätzen!

+0

Was ist das Problem mit der Aussage "Das Match mit den meisten Inliers ist meine beste Übereinstimmung."? –

+0

Das war das erste, woran ich auch dachte, aber als ich es probierte, bekam ich keine genauen Ergebnisse. – tversteeg

+0

OK, also die Bilder (sogar die falschen) sind ziemlich ähnlich, denke ich. Wie ist die Genauigkeit, wenn Sie die durchschnittliche Distanz aller Spiele oder aller Inliers nehmen? Können Sie Beispielbilder veröffentlichen, bei denen dies fehlschlägt? –

Antwort

0

eine kurze Suche nach Ihrem Problem versorgte mich mit in den opencv Antwort Abschnitte folgenden Eintrag:

/CV Answer forum

, die die Antwort auf die Frage, die Sie haben zu sein scheinen zu liefern scheint. Um die Ergebnisse zu filtern, die Sie erhalten, wie in der Antwort vorgeschlagen, würde ich einen Blick auf den RANSAC-Algorithmus werfen, um die besten Ergebnisse in Ihrer Match-Auswahl zu finden.

RANSAC desctiption Wikipedia

Zumindest sollten Sie in die richtige Richtung weisen.

+0

Wenn Sie sich meinen Code ansehen, können Sie sehen, dass ich RANSAC bereits verwende. – tversteeg

0

Es hängt davon ab, was das Bild in der Liste ist. Sie können keine Lösung für jedes Sehproblem in der Welt haben. Zum Beispiel muss das Projekt, an dem ich arbeite, Material in Bildern von Wänden erkennen. Man kann es nicht einfach mit einem anderen Bild von Wand mit anderem Material vergleichen und hoffen, ein Match zu bekommen.

In meinem Fall musste ich Deskriptoren erstellen. Descriptors sind Algorithmen, die einen Wert ausgeben, der mit anderen Werten eines anderen Bildes verglichen werden kann. Es gibt viele Deskriptoren, die bereits in openCV wie LBP, SURF, etc. vorhanden sind. Um es einfach zu sagen, vergleichen Sie das Bild nicht mehr, vergleichen Sie den Ausgabewert des Deskriptors von Bild 1 mit dem Deskriptorwert von allen Bild in der Liste.

Sie müssen die Deskriptoren, die Ihre Augen/Gehirn verwenden, um eine Übereinstimmung im wirklichen Leben zu finden. Wenn der Abgleich beispielsweise auf Farbe basiert, können Sie CLD oder DCD verwenden. Wenn die Übereinstimmung auf Textur basiert, verwenden Sie LBP. Sie können auch so arbeiten, wie ich es in meinem Projekt getan habe, viele Deskriptoren verwenden und maschinelles Lernen mit trainierten Datenalgorithmen verwenden, um die beste Übereinstimmung zu finden.

Also, um es zusammenzufassen, gibt es keine Wunderwaffe, die alle Vision Problem beheben kann. Sie müssen Ihre Lösung an das Problem anpassen.

Hoffe es hilft!

1

Es gibt keine einfache Antwort. Um bessere Ergebnisse zu erzielen, müssen Sie eine Art Transformation implementieren und Clustering auf der transformierten Karte durchführen, anstatt nur die Entfernungen zu summieren. Das ist schwierig und sogar publishable.

Andernfalls müssen Sie mehr praktische Techniken wie Dimensions- und Histogramm-Filterung verwenden. Sie können sich OpenCV's stitcher ansehen, das Modul, das Sie interessiert, isolieren und den Quellcode an Ihre Bedürfnisse anpassen.

Verwandte Themen