Verwenden von opencv, um ein Bild aus einer Gruppe von Bildern zum Zweck der Identifikation in C ++ abzugleichen
EDIT: ich habe genügend Ruf erworben, durch diesen Beitrag, um in der Lage sein, um es zu Bearbeiten mit mehr links, die mir helfen, meinen Standpunkt besser rüber
Menschen spielt binding of isaac kommen oft über wichtige Elemente, die auf kleinen Sockeln.
Ziel ist es, dass ein Benutzer verwirrt über das, was ein Element ist in der Lage sein, einen Knopf zu drücken, das wird sich dann weisen ihn an, "box" das Objekt(denken, dass windows-desktop-Boxen). Die box gibt uns die region of interest(der eigentliche Artikel sowie einige hintergrund-Umgebung) vergleichen zu was wird ein ganzes Netz von Elementen.
Theoretische Benutzer boxed Element
Theoretischen raster der Elemente(es gibt nicht mehr viele, die ich gerade kopiert aus the binding of isaac wiki)
Die Position im raster der Elemente identifiziert als Element der Benutzer boxed würde repräsentiert einen bestimmten Bereich des Bildes bezieht sich auf einen entsprechenden link zu the binding of isaac wiki die Informationen über das Element.
In das raster der Artikel ist der 1. Spalte 3. in der untersten Zeile. Ich benutze diese beiden Bilder in allen Sachen, die ich habe versucht, aus
Mein Ziel ist, erstellen Sie ein Programm, dass kann eine manuelle Ernte ein Element aus dem Spiel "The Binding of Isaac", identifizieren Sie das zugeschnittene Element finden, vergleichen Sie das Bild zu einem Bild, einer Tabelle der Elemente in das Spiel, zeigt dann die richtige wiki-Seite.
Wäre dies meine erste "richtige Projekt", in dem Sinne, dass es erfordert eine große Menge der Bibliothek zu lernen, was ich will, fertig. Es war ein bisschen überwältigend.
Habe ich Durcheinander gebracht mit ein paar Optionen, die nur vom googeln um. (Sie können schnell zu finden, die tutorials, die ich verwendet, durch die Suche den Namen der Methode und opencv. mein Konto ist stark eingeschränkt, mit link-posting aus irgendeinem Grund)
mit bruteforcematcher:
http://docs.opencv.org/doc/tutorials/features2d/feature_description/feature_description.html
#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include <opencv2/legacy/legacy.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
void readme();
/** @function main */
int main( int argc, char** argv )
{
if( argc != 3 )
{ return -1; }
Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );
if( !img_1.data || !img_2.data )
{ return -1; }
//-- Step 1: Detect the keypoints using SURF Detector
int minHessian = 400;
SurfFeatureDetector detector( minHessian );
std::vector<KeyPoint> keypoints_1, keypoints_2;
detector.detect( img_1, keypoints_1 );
detector.detect( img_2, keypoints_2 );
//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;
Mat descriptors_1, descriptors_2;
extractor.compute( img_1, keypoints_1, descriptors_1 );
extractor.compute( img_2, keypoints_2, descriptors_2 );
//-- Step 3: Matching descriptor vectors with a brute force matcher
BruteForceMatcher< L2<float> > matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );
//-- Draw matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2, matches, img_matches );
//-- Show detected matches
imshow("Matches", img_matches );
waitKey(0);
return 0;
}
/** @function readme */
void readme()
{ std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; }
Ergebnisse in nicht so nützliche Sachen suchen. Sauberer, aber ebenso unzuverlässig Suchergebnisse mit flann.
http://docs.opencv.org/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.html
#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include <opencv2/legacy/legacy.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
void readme();
/** @function main */
int main( int argc, char** argv )
{
if( argc != 3 )
{ readme(); return -1; }
Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );
if( !img_1.data || !img_2.data )
{ std::cout<< " --(!) Error reading images " << std::endl; return -1; }
//-- Step 1: Detect the keypoints using SURF Detector
int minHessian = 400;
SurfFeatureDetector detector( minHessian );
std::vector<KeyPoint> keypoints_1, keypoints_2;
detector.detect( img_1, keypoints_1 );
detector.detect( img_2, keypoints_2 );
//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;
Mat descriptors_1, descriptors_2;
extractor.compute( img_1, keypoints_1, descriptors_1 );
extractor.compute( img_2, keypoints_2, descriptors_2 );
//-- Step 3: Matching descriptor vectors using FLANN matcher
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors_1.rows; i++ )
{ double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
printf("-- Max dist : %f \n", max_dist );
printf("-- Min dist : %f \n", min_dist );
//-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist )
//-- PS.- radiusMatch can also be used here.
std::vector< DMatch > good_matches;
for( int i = 0; i < descriptors_1.rows; i++ )
{ if( matches[i].distance < 2*min_dist )
{ good_matches.push_back( matches[i]); }
}
//-- Draw only "good" matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//-- Show detected matches
imshow( "Good Matches", img_matches );
for( int i = 0; i < good_matches.size(); i++ )
{ printf( "-- Good Match [%d] Keypoint 1: %d -- Keypoint 2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); }
waitKey(0);
return 0;
}
/** @function readme */
void readme()
{ std::cout << " Usage: ./SURF_FlannMatcher <img1> <img2>" << std::endl; }
templatematching hat meine beste Methode so weit. der 6 Methoden, es reicht immer nur 0-4 richtige Identifizierungen aber.
http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
///Global Variables
Mat img; Mat templ; Mat result;
char* image_window = "Source Image";
char* result_window = "Result window";
int match_method;
int max_Trackbar = 5;
///Function Headers
void MatchingMethod( int, void* );
/** @function main */
int main( int argc, char** argv )
{
///Load image and template
img = imread( argv[1], 1 );
templ = imread( argv[2], 1 );
///Create windows
namedWindow( image_window, CV_WINDOW_AUTOSIZE );
namedWindow( result_window, CV_WINDOW_AUTOSIZE );
///Create Trackbar
char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );
MatchingMethod( 0, 0 );
waitKey(0);
return 0;
}
/**
* @function MatchingMethod
* @brief Trackbar callback
*/
void MatchingMethod( int, void* )
{
///Source image to display
Mat img_display;
img.copyTo( img_display );
///Create the result matrix
int result_cols = img.cols - templ.cols + 1;
int result_rows = img.rows - templ.rows + 1;
result.create( result_cols, result_rows, CV_32FC1 );
///Do the Matching and Normalize
matchTemplate( img, templ, result, match_method );
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
///Localizing the best match with minMaxLoc
double minVal; double maxVal; Point minLoc; Point maxLoc;
Point matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
///For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
{ matchLoc = minLoc; }
else
{ matchLoc = maxLoc; }
///Show me what you got
rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
imshow( image_window, img_display );
imshow( result_window, result );
return;
}
http://imgur.com/pIRBPQM,h0wkqer,1JG0QY0,haLJzRF,CmrlTeL,DZuW73V#3
des 6
fail,pass,fail,pass,pass,pass
Das war eine Art best-case-Ergebnis aber. Der nächste Artikel, den ich versuchte, war
und führte in fail,fail,fail,fail,fail,fail
Von Element zu Element alle diese Methoden haben einige, die gut funktionieren und einige, die tun furchtbar
Deshalb frag ich mal: ist templatematching meine beste Wette oder gibt es eine Methode, die ich bin nicht, wenn man bedenkt, dass meine Heiligen Gral?
Wie kann ich einen BENUTZER zu erstellen, die Ernte manuell? Opencv - Dokumentation, die auf dieser ist wirklich schlecht, und die Beispiele, die ich online finden, sind extrem alt cpp oder gerade C.
Vielen Dank für jede Hilfe. Dieses Unterfangen war eine interessante Erfahrung, so weit. Ich hatte zu Streifen alle links, die würde besser darzustellen, wie alles arbeitet, aber die Seite sagt, ich werde Entsendung mehr als 10 links, auch wenn ich nicht.
einige weitere Beispiele für Gegenstände, die während des Spiels:
dem rock ist eine seltene Sache und eine der wenigen die man "irgendwo" auf dem Bildschirm. Elemente wie der rock sind der Grund, warum zuschneiden des Elements durch den Benutzer ist die beste Methode zum isolieren der Sache, anders sind Ihre Positionen nur in ein paar bestimmte stellen.
Einem Element nach einem boss-Kampf, eine Menge Sachen, die überall und Transparenz in der Mitte. Ich könnte mir vorstellen, dass das eine der härteren, um korrekt zu arbeiten
Selten Raum. einfachen hintergrund. kein Element der Transparenz.
hier sind die zwei Tische, die alle Elemente im Spiel sind.. ich werde Sie ein Bild schließlich aber für jetzt, Sie waren direkt aus der isaac-wiki.
InformationsquelleAutor der Frage 2c2c | 2013-02-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Eine wichtige detail hier ist, dass Sie Reine Bild jeder Artikel in der Tabelle. Sie kennen die Farbe von hintergrund und kannst ein Element aus dem rest des Bildes. Zum Beispiel, zusätzlich zu matrix, der Vertretung der Bild selbst, können Sie speichern-matrix von 1-en und 0-en in der gleichen Größe, wo diejenigen entsprechen Bildausschnitt und Nullen - zu hintergrund. Nennen wir diese matrix "Maske" und reines Bild des Artikels - "Muster".
Gibt es 2 Möglichkeiten, um Bilder zu vergleichen: match-Bild mit dem Muster und das Muster passen, mit dem Bild. Was Sie beschrieben haben ist das passende Bild mit dem Muster - Sie haben einige beschnittene Bild und wollen zu finden, die ähnliche Muster. Stattdessen denken Sie über Suche Muster auf Bild.
Lassen Sie uns zuerst definieren die Funktion
match()
nimmt Muster, Maske und Bild von der gleichen Größe und überprüft, ob die Fläche auf dem Muster unter der Maske ist genau das gleiche wie im Bild (pseudocode):Aber Größen von Muster und Bildausschnitt abweichen können. Standard Lösung für dieses (verwendet, zum Beispiel in cascade classifier) ist die Verwendung Schiebefenster - bewegen-Muster "das Fenster" über Bild und überprüfen, ob das Suchmuster mit ausgewählten region. Das ist ziemlich viel, wie Bild-Erkennung arbeitet in OpenCV.
Natürlich, diese Lösung ist nicht sehr robust - zuschneiden, ändern der Größe oder irgendwelche anderen Bild-Transformationen ändern kann, einzelne Pixel, und in diesem Fall Methode
match()
wird immer false zurückgeben. Um dies zu überwinden, statt boolean Antwort, die Sie verwenden können, Abstand zwischen Bild und Muster. In diesem Fall Funktionmatch()
sollte wieder etwas Wert der ähnlichkeit, sagen wir, zwischen 0 und 1, wobei 1 steht für "genau das gleiche", während 0 für "völlig anders". Dann haben Sie entweder den Schwellenwert für ähnlichkeit (z.B. Bild sollte mindestens 85% ähnlich dem Muster), oder wählen Sie einfach das Muster mit dem höchsten Wert der ähnlichkeit.Da Gegenstände im Spiel sind, künstliche Bilder und Variationen in Sie sehr klein ist, ist dieser Ansatz sollte genug sein. Jedoch, für kompliziertere Fälle müssen Sie andere Funktionen als einfach nur die Pixel unter der Maske. Wie ich schon in meinem Kommentar Methoden wie die Eigenfaces -, Kaskaden-Klassifikator mittels Haar-like features oder auch Active Appearance Modellen kann effizienter sein, für diese Aufgaben. Für SURFEN, soweit ich weiß, es ist besser geeignet für Aufgaben mit unterschiedlichem Winkel und Größe des Objekts, aber nicht für die verschiedenen Hintergründe und all solche Dinge.
InformationsquelleAutor der Antwort ffriend
Kam ich auf Ihre Frage, während Sie versuchen, herauszufinden, meine eigene template-matching-Problem, und jetzt bin ich wieder zu teilen, was ich denke, könnte Ihre beste Wette auf meinen eigenen Erfahrungen beruhen. Wahrscheinlich haben Sie längst aufgegeben, aber hey könnte jemand anderes sein, in ähnliche Schuhe eines Tages.
Keiner der Artikel, die Sie gemeinsam sind eine solide Rechteck, und da template-matching in opencv kann nicht arbeiten Sie mit einer Maskewerden Sie immer vergleichen Sie Ihr Referenz-Bild gegen das, was muss ich davon ausgehen, ist zumindest verschiedene Hintergründe (nicht zu vergessen die Elemente, die sich in verschiedenen Orten und auf verschiedenen Hintergründen, so dass das template match noch schlimmer).
Wird es immer sein Vergleich der hintergrund-Pixel und verwechseln Ihr Spiel es sei denn, Sie sammeln die Ernte jeder einzelnen situation, in der das Referenz-image gefunden werden kann. Wenn die decals von Blut/etc einführen, die noch mehr Variabilität in die Hintergründe um die Elemente dann zu template-matching wird wahrscheinlich nicht bekommen Sie tolle Ergebnisse.
Also die zwei Dinge, die ich versuchen würde, wenn ich du wäre, sind abhängig von einigen details:
Bin ich zuversichtlich, dass entweder die funktionieren könnte für Sie, abhängig davon, ob das Spiel gut ist -, vertreten durch Ihre screenshots.
Hinweis: Die konturerkennung wird viel, viel schnellerals das template-matching. Schnell genug für die Ausführung in Echtzeit und negieren die Notwendigkeit für den Benutzer zu beschneiden, etwas, vielleicht.
InformationsquelleAutor der Antwort Christopher Peterson