2014-06-27 6 views
10

OpenCV bietet keine RANSAC-Funktion an sich oder zumindest in einer Form, die Sie einfach aufrufen und damit erledigen können (z cv::ransac(...)). Alle Funktionen/Methoden, die RANSAC verwenden können, haben ein entsprechendes Flag. Dies ist jedoch nicht immer nützlich, wenn Sie tatsächlich etwas anderes mit den Inlierern machen wollen, die RANSAC berechnet, nachdem Sie eine Homographie/Fundamentalmatrix berechnet haben, um zum Beispiel eine schöne Grafik in Octave oder ähnliche Software/Bibliothek der Punkte zu erstellen verbleibender Satz von gefilterten Treffern usw.OpenCV: So erhalten Sie mit Hilfe von findHomography()/findFundamental() und RANSAC

Nach dem Vergleich von zwei Bildern erhält man einen Vektor von Übereinstimmungen. Dazu gibt es natürlich zwei Sätze von Schlüsselpunkten (einen für jedes Bild), die beim Matching-Prozess verwendet wurden. Unter Verwendung von Übereinstimmungen und Schlüsselpunkten erzeugen wir zwei Vektoren von Punkten (z. B. cv::Point2f points) und leiten diese an findHomography() weiter. Von this und this Posts habe ich entdeckt, wie genau die Inliers mit einer Maske markiert werden, die wir an diese Funktion übergeben. Jede Zeile innerhalb der Maske bezieht sich auf einen Inlier/Ausreißer. Ich bin jedoch nicht in der Lage, herauszufinden, wie ich die Zeilenindexinformationen aus meinen zwei Punktmengen verwenden soll. Der Quellcode von OpenCV hat mich nicht zu weit gebracht. In findFundamental() (ähnlich wie findHomography(), wenn es um ihre Unterschrift und den Maskenteil geht), benutzen sie compressPoints(), was irgendwie die zwei Sätze, die wir als Eingabe haben (Quell- und Zielpunkte), zu einem zusammenzufassen scheint. Während des Tests, um die Art der Maske zu bestimmen, habe ich 2 Sätze von Punkten (konvertierte cv::Keypoints bis cv::Point2f - ein Standardverfahren) versucht. Jeder Satz enthält 300 Punkte, also haben wir insgesamt 600 Punkte. Die zurückgegebene Maske enthält 300 Zeilen (Werte sind für dieses Thema nicht wichtig).

EDIT: Während ich dies schrieb, entdeckte ich die Antwort (siehe unten), entschied mich aber diese Frage trotzdem zu posten, falls jemand diese Information so schnell wie möglich und in kompakter Form benötigt. Beachten Sie, dass wir noch eine OpenCV-Funktion benötigen, die RANSAC unterstützt. Also, wenn Sie eine Reihe von Punkten, aber keine Absicht haben, Homographie oder fundamentale Matrix zu berechnen, ist dies offensichtlich nicht der Weg und ich wage zu sagen, dass ich nichts Nützliches in OpenCVs API finden konnte, das helfen kann, dieses Hindernis zu umgehen, das Sie verwenden müssen eine externe Bibliothek.

Antwort

10

Die Lösung ist eigentlich ganz trivial. Wie wir wissen, gibt jede Zeile in unserer Maske Auskunft darüber, ob wir einen Inlier oder einen Ausreißer haben. Wir haben jedoch zwei Sätze von Punkten als Eingabe, also wie genau repräsentiert eine Zeile, die einen einzelnen Wert enthält, zwei Punkte? Die Art dieser Art der Indexierung erschien mir in Gedanken, während ich darüber nachdachte, wie diese beiden Punkte in findHomography() erscheinen (in meinem Fall habe ich die Homographie zwischen zwei Bildern berechnet). Beide Sätze haben die gleiche Anzahl von Punkten in ihnen aufgrund der einfachen Tatsache, dass sie aus den Übereinstimmungen zwischen unserem Paar von Bildern extrahiert werden. Dies bedeutet, dass eine Zeile in unserer Maske der tatsächliche Index der Punkte in den beiden Mengen und auch der Index im Vektor der Treffer für die zwei Bilder ist. Es ist mir gelungen, auf dieser Basis manuell auf eine kleine Teilmenge von übereinstimmenden Punkten zu verweisen, und die Ergebnisse sind wie erwartet. Es ist wichtig, dass Sie die Reihenfolge Ihrer Übereinstimmungen und die 2D-Punkte, die Sie daraus extrahiert haben, nicht mit den Schlüsselpunkten ändern, auf die in jeder cv::DMatch verwiesen wird. Unten sehen Sie ein einfaches Beispiel für ein einzelnes Inlierpaar.

for(int i = 0; i < matchesObjectScene.size(); ++i) 
{ 
    // extract points from keypoints based on matches 
    pointsObject.push_back(keypointsObject.at(matchesObjectScene.at(i).queryIdx).pt); 
    pointsScene.push_back(keypointsScene.at(matchesObjectScene.at(i).trainIdx).pt); 
} 
// compute homography using RANSAC 
cv::Mat mask; 
cv::Mat H = cv::findHomography(pointsObject, pointsScene, CV_RANSAC, ransacThreshold, mask); 

In dem obigen Beispiel, wenn wir

int maskRow = 10; 
std::cout << "POINTS: object(" << pointsObject.at(maskRow).x << "," << pointsObject.at(maskRow).y << ") - scene(" << pointsScene.at(maskRow).x << "," << pointsScene.at(maskRow).y << ")" << std::endl; 

und dann wieder, aber dieses Mal mit unserem keypoints (kann auch mit den extrahierten 2D-Punkten erfolgen)

std::cout << "POINTS (via match-set): object(" << keypointsObject.at(matchesCurrentObject.at(maskRow).queryIdx).pt.x << "," << keypointsObject.at(matchesCurrentObject.at(maskRow).queryIdx).pt.y << ") - scene(" << keypointsScene.at(matchesCurrentObject.at(maskRow).trainIdx).pt.x << "," << keypointsScene.at(matchesCurrentObject.at(maskRow).trainIdx).pt.y << ")" << std::endl; 

einige inlier drucken Wir erhalten tatsächlich die gleiche Ausgabe:

POINTS: object(462,199) - sscene(485,49) 
POINTS (via match-set): object(462,199) - scene(485,49) 

Um die tatsächliche inlier bekommen wir müssen einfach überprüfen, ob die aktuelle Zeile in der Maske tatsächlich einen 0 oder Nicht-Null-Wert enthält:

if((unsigned int)mask.at<uchar>(maskRow)) 
    // store match or keypoints or points somewhere where you can access them later 
+1

Für den ersten Satz tatsächlich die Zeile in der Maske repräsentiert nicht ein Inlier. Die Zeile repräsentiert den Status von Inlier oder Ausreißer. Weitere Informationen finden Sie in diesem Beitrag [link] (http://stackoverflow.com/questions/15815304/opencv-c-findhomography-mask-values-meaning). –

+0

Ja, das ist richtig und das ist es, was ich meinte, aber jetzt, wo ich diesen Satz noch einmal durchgelesen habe, sehe ich, wie er falsch interpretiert werden kann. Ich werde es ändern. – rbaleksandar

+0

Aber row repräsentiert den Status von inlier oder outliers, aber es gibt keinen Schlüsselpunkt für jeden inlier- oder outliers-Status. Schlüsselpunkte werden im Vektor gespeichert. also wie können wir den entsprechenden schlüsselpunkt von inlier in maske bekommen? – Abc

Verwandte Themen