Template Matching auf Desktop-Icons (OpenCV)
-
Hallo Community,
ich versuche mich gerade am Template-Matching und nutze hierzu OpenCV. Mein Ziel ist es von einem Desktop Screenshot alle Icons zu detektieren und anschließend mit einem Rechteck zu markieren.
Um aber alle Icons zu erkennen, muss man ein Template anfertigen was die zu erkennenden Icons beschreibt und dieses dann anschließend dem Programm übergeben. Dachte da an zwei Möglichkeiten für die Template Erstellung:- entweder man ließt alle Icons ein, die man vorher zuschneidet
- oder man erstellt ein Durchschnittsbild von diesen Icons
Bin gerade dabei die Variante mit dem Durchschnittsbild zu testen. Dummerweise erhalte ich aber nicht die optimale Lösung ...
#include <stdio.h> #include <cv.h> #include <highgui.h> int main(int argc, char** argv) { IplImage* image; // Image auf dem gesucht werden soll -> Screenshot IplImage* icon; // Template IplImage* temp = cvCreateImage(cvSize(800,600), IPL_DEPTH_8U, 3); // temporäre Bilder für die spätere Ausgabe/Visualisierung IplImage* temp2 = cvCreateImage(cvSize(800,600), IPL_DEPTH_32F, 1); image=cvLoadImage("image.png",1); // laden des Screenshots icon=cvLoadImage("icons.png",1); // laden des Templates int resultW = image->width - icon->width + 1; int resultH = image->height - icon->height +1; IplImage* result = cvCreateImage(cvSize(resultW, resultH), IPL_DEPTH_32F, 1); // Map für die Vergleichsresultate durch cvMatchTemplate; If the image is W×H and the template is w×h then the result must be W-w+1×H-h+1. cvMatchTemplate(image, icon, result, CV_TM_CCOEFF); // OpenCV match Template Funktion + die drei verschiedenen Methoden bzw. drei weitere normierte // CV_TM_SQDIFF a perfect match will be 0 and bad matches will be large // CV_TM_CCORR a perfect match will be large and bad matches will be small or 0 // CV_TM_CCOEFF a perfect match will be 1 and a perfect mismatch will be –1; a value of 0 = no correlation (random alignments) // bzw. CV_TM_SQDIFF_NORMED, CV_TM_CCORR_NORMED, CV_TM_CCOEFF_NORMED //VARIANTE 1 markiert nur den am besten übereinstimmenden Abschnitt zwischen Template und Screenshot -> somit wird nur ein Icon erkannt CvPoint min_loc, max_loc; double min_val,max_val; cvMinMaxLoc(result, &min_val, &max_val, &min_loc, &max_loc, NULL); // best matches can be found as global minimums (CV_TM_SQDIFF*) or maximums (CV_TM_CCORR* and CV_TM_CCOEFF*) cvRectangle(image, max_loc, cvPoint( max_loc.x + icon->width, max_loc.y + icon->height ), cvScalar( 0, 0, 255, 0 ), 3, 8, 0 ); printf("min value = %f\tmax value = %f\nmin location: x = %d\ty = %d\nmax location: x = %d\ty = %d ", min_val, max_val, min_loc.x, min_loc.y, max_loc.x, max_loc.y); /* //VARIANTE 2 soll alle Icons markieren ... aber scheinbar funktioniert das mit dem Grenzwert nicht richtig float grenzwert = 2; CvScalar s; // loop the comparison result array for(int y = 0 ; y < result->height ; y++ ) for(int x = 0 ; x < result->width ; x++ ) { // get an element s = cvGet2D( result, y, x ); // if value below the grenzwert, similar object is found if(s.val[0] <= grenzwert ) cvRectangle(image, cvPoint( x, y ), cvPoint( x + icon->width, y + icon->height ), CV_RGB(255, 0, 0), 2, 8, 0 ); } */ // Windows erstellen + Ausgabe über temp und temp2 cvNamedWindow("output", 1); cvNamedWindow("result", 1); cvMoveWindow("output", 466, 361); cvMoveWindow("result", 0, 361); cvResize(image, temp, CV_INTER_LINEAR); cvResize(result, temp2, CV_INTER_LINEAR); cvShowImage("output", temp); cvShowImage("result", temp2); cvWaitKey(); // cleanup cvDestroyWindow("output"); cvDestroyWindow("result"); cvReleaseImage(&image); cvReleaseImage(&icon); cvReleaseImage(&result); cvReleaseImage(&temp); cvReleaseImage(&temp2); return 0; }
Dummerweise erhalte ich mit der VARIANTE 2 aber nicht so die Top Ergebnisse. Es wird meist nur ein Icon erkannt. Liegt das am Grenzwert?
Wäre cool wenn sich das mal jemand anschauen könnte.
Gruß SaulHab mal meine Test Bilder Hochgeladen:
image.png http://img691.imageshack.us/img691/8718/imageuhc.png
icons.png http://img576.imageshack.us/img576/4613/iconsj.png
-
Hm also ich habs jetzt. Die Grenzwerte zu den normierten Modi sind:
- CV_TM_SQDIFF_NORMED: s.val[0] <= 0.17
- CV_TM_CCORR_NORMED: s.val[0] >= 0.92
- CV_TM_CCOEFF_NORMED: s.val[0] >= 0.47
Sind aber nicht wirklich optimale Ergebnisse, wobei das von dem korreliertem Matching mit CV_TM_CCOEFF_NORMED am besten ist.
http://img337.imageshack.us/img337/1097/ergebnis.pngHätte jemand eine Idee wie man es vielleicht verbessern könnte?
Hab gerade was von der Maximum-Likelihood-Methode gefunden ... vielleicht hilft mir das ja weiter!?Des weiteren bin ich gerade am grübeln, wie ich die vielen roten Rechtecke um ein Icon zu einem Rechteck vereinen kann ... auf dem Bild ist ja gut zu sehen, das mehrere Rechtecke ein Icon umschließen.
Gruß Saul
-
Ich würde das Bild zunächst so umwandeln, dass du ein Grayscale-Bild erhältst. Und dann kannst du die Helligkeit noch um 200% erhöhen. Das Template muss natürlich ebenso bearbeitet werden.
http://img714.imageshack.us/i/12768.jpg/
http://img39.imageshack.us/i/photo1c35d14288ab85d8a5.jpg/Ich denke, dass man dann anschließend bessere Ergebnisse erhalten sollte. Ist aber nur eine spontante Idee, müsste man ausprobieren.