2014-05-14 3 views
6

Der Zweck der Anwendung besteht darin, ein Bild aus einer bereits festgelegten Liste von Bildern zu erkennen. Die SIFT-Deskriptoren der Liste der Bilder wurden extrahiert und in Dateien gespeichert. Nichts interessantes hier:Erkennen eines Bildes aus einer Liste mit OpenCV SIFT unter Verwendung des FLANN-Abgleichs

std::vector<cv::KeyPoint> detectedKeypoints; 
cv::Mat objectDescriptors; 

// Extract data 
cv::SIFT sift; 
sift.detect(image, detectedKeypoints); 
sift.compute(image, detectedKeypoints, objectDescriptors); 

// Save the file 
cv::FileStorage fs(file, cv::FileStorage::WRITE); 
fs << "descriptors" << objectDescriptors; 
fs << "keypoints" << detectedKeypoints; 
fs.release(); 

Dann nimmt das Gerät ein Bild. SIFT-Deskriptoren werden auf die gleiche Weise extrahiert. Die Idee war nun, die Deskriptoren mit denen aus den Dateien zu vergleichen. Ich mache das mit dem FLANN-Matcher von OpenCV. Ich versuche die Ähnlichkeit Bild für Bild zu quantifizieren. Nachdem ich die ganze Liste durchgegangen bin, sollte ich die beste Übereinstimmung haben.

const cv::Ptr<cv::flann::IndexParams>& indexParams = new cv::flann::KDTreeIndexParams(1); 
const cv::Ptr<cv::flann::SearchParams>& searchParams = new cv::flann::SearchParams(64); 

// Match using Flann 
cv::Mat indexMat; 
cv::FlannBasedMatcher matcher(indexParams, searchParams); 
std::vector<cv::DMatch> matches; 
matcher.match(objectDescriptors, readDescriptors, matches); 

Nach dem Abgleich verstehe ich, dass ich eine Liste der am nächsten gefundenen Abstände zwischen den Merkmalsvektoren erhalten. Ich finde den Mindestabstand und es verwendet, kann ich „gute Spiele“ zählen und sogar eine Liste der entsprechenden Punkte:

// Count the number of mathes where the distance is less than 2 * min_dist 
int goodCount = 0; 
for (int i = 0; i < objectDescriptors.rows; i++) 
{ 
    if (matches[i].distance < 2 * min_dist) 
    { 
     ++goodCount; 
     // Save the points for the homography calculation 
     obj.push_back(detectedKeypoints[matches[i].queryIdx].pt); 
     scene.push_back(readKeypoints[matches[i].trainIdx].pt); 
    } 
} 

Ich zeige einfach Teile des Codes nur, um diese leichter zu folgen Ich weiß, dass einiges davon nicht hier sein muss.

Ich hoffte weiter, dass das Zählen der Anzahl der guten Übereinstimmungen ausreichend wäre, aber es stellte sich heraus, dass es meistens nur auf das Bild mit den meisten Deskriptoren hinweist. Was ich danach versuchte, war die Homographie zu berechnen. Das Ziel war es zu berechnen und zu sehen, ob es eine gültige Homoraphie ist oder nicht. Die Hoffnung war, dass eine gute Übereinstimmung, und nur eine gute Übereinstimmung, eine Homographie haben würde, die eine gute Transformation ist. Erstellen wurde die Homografie einfach cv durchgeführt unter Verwendung :: findHomography auf dem obj und Szene welche sind std :: vector < cv :: Point2f>. Ich überprüfte die Gültigkeit des Homografie einige Code unter Verwendung fand ich online:

bool niceHomography(cv::Mat H) 
{ 
    std::cout << H << std::endl; 

    const double det = H.at<double>(0, 0) * H.at<double>(1, 1) - H.at<double>(1, 0) * H.at<double>(0, 1); 
    if (det < 0) 
    { 
     std::cout << "Homography: bad determinant" << std::endl; 
     return false; 
    } 

    const double N1 = sqrt(H.at<double>(0, 0) * H.at<double>(0, 0) + H.at<double>(1, 0) * H.at<double>(1, 0)); 
    if (N1 > 4 || N1 < 0.1) 
    { 
     std::cout << "Homography: bad first column" << std::endl; 
     return false; 
    } 

    const double N2 = sqrt(H.at<double>(0, 1) * H.at<double>(0, 1) + H.at<double>(1, 1) * H.at<double>(1, 1)); 
    if (N2 > 4 || N2 < 0.1) 
    { 
     std::cout << "Homography: bad second column" << std::endl; 
     return false; 
    } 

    const double N3 = sqrt(H.at<double>(2, 0) * H.at<double>(2, 0) + H.at<double>(2, 1) * H.at<double>(2, 1)); 
    if (N3 > 0.002) 
    { 
     std::cout << "Homography: bad third row" << std::endl; 
     return false; 
    } 

    return true; 
} 

Ich verstehe nicht die Mathematik dahinter so, während des Tests, habe ich manchmal diese Funktion mit einer einfachen Prüfung, ob die Determinante des Homografie ersetzt war positiv. Das Problem ist, dass ich hier immer wieder Probleme hatte. Die Homographien waren entweder alle schlecht oder gut, wenn sie nicht hätten sein sollen (wenn ich nur die Determinante überprüfte).

Ich dachte mir, ich sollte eigentlich die Homographie verwenden und für einige Punkte ihre Position im Zielbild anhand ihrer Position im Quellbild berechnen. Dann würde ich diese durchschnittlichen Entfernungen vergleichen, und ich würde im Idealfall eine sehr offensichtliche kleinere durchschnittliche Entfernung im Falle des richtigen Bildes erhalten. Dies hat nicht funktioniert überhaupt. Alle Entfernungen waren kolossal. Ich dachte, ich hätte die Homographie anders herum verwendet, um die richtige Position zu berechnen, aber das Umschalten obj und Szene miteinander ergab ähnliche Ergebnisse.

Andere Dinge, die ich versuchte, waren SURF Deskriptoren statt SIFT, BFMatcher (Brute-Force) anstelle von FLANN, die n kleinsten Abstände für jedes Bild immer an Stelle einer Zahl abhängig von dem Mindestabstand oder Entfernungen immer auf einer Abhängigkeit globale maximale Entfernung. Keiner dieser Ansätze hat mir definitiv gute Ergebnisse gebracht, und ich fühle mich jetzt festgefahren.

Meine einzige nächste Strategie wäre, die Bilder zu schärfen oder sie sogar zu binären Bildern zu machen, die einen lokalen Schwellenwert oder einige Algorithmen zur Segmentierung verwenden. Ich suche nach irgendwelchen Vorschlägen oder Fehlern, die jeder in meiner Arbeit sehen kann.

Ich weiß nicht, ob das relevant ist, aber ich habe einige der Bilder, die ich gerade teste, hinzugefügt. Viele Male in den Testbildern stammen die meisten SIFT-Vektoren aus dem Rahmen (höherer Kontrast) als das Gemälde. Deshalb denke ich, dass das Schärfen der Bilder funktionieren könnte, aber ich möchte nicht tiefer gehen, falls etwas, was ich vorher getan habe, falsch ist.

Die Bildergalerie ist here mit den Beschreibungen in den Titeln. Die Bilder haben eine recht hohe Auflösung, bitte sehen Sie, falls es Hinweise geben könnte.

+0

Hey, ich versuche, eine Anwendung ähnlich wie bei Ihnen zu tun. Haben Sie eine Lösung für Ihr Problem gefunden? – definera

+0

Die Logik war gut, du kannst ihr folgen. Vielleicht möchten Sie die Homographie nachschlagen, ich denke, ich musste das ändern. Leider kann ich den Code nicht mehr teilen. – octafbr

Antwort

0

Sie gehen den richtigen Weg.

Verwenden Sie als erstes das zweitnächste Verhältnis statt Ihrer "guten Übereinstimmung mit 2 * min_dist" https://stackoverflow.com/a/23019889/1983544.

Zweitens, verwenden Sie Homographie anders. Wenn Sie Homographie finden, haben Sie nicht nur H, Matrix, sondern auch die Anzahl übereinstimmender Korrespondenzen. Überprüfen Sie, ob es eine vernünftige Zahl ist, sagen wir> = 15. Wenn weniger, als Objekt nicht übereinstimmt.

Drittens, wenn Sie eine große Blickwinkeländerung haben, können SIFT oder SURF keine Bilder zuordnen. Versuchen Sie MODS zu verwenden, anstatt (http://cmp.felk.cvut.cz/wbs/ hier ist Windows- und Linux-Binaries sowie Papier beschreibt Algorithmus) oder ASIFT (viel langsamer und passt viel schlimmer, aber Open Source) http://www.ipol.im/pub/art/2011/my-asift/

Oder zumindest Verwendung MSER oder hessisch-Affine Detektor anstelle von SIFT (wobei SIFT als Deskriptor beibehalten wird).

1

Sie können versuchen, zu testen, ob beim Abgleich die Linien zwischen dem Quellbild und dem Zielbild relativ parallel sind. Wenn es keine korrekte Übereinstimmung ist, dann haben Sie eine Menge Rauschen und die Linien werden nicht parallel sein.

Siehe das beigefügte Bild, das eine korrekte Übereinstimmung zeigt (mit SURF und BF) - alle Linien sind größtenteils parallel (obwohl ich darauf hinweisen sollte, dass dies ein einfaches Beispiel ist).

enter image description here

Verwandte Themen