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ß Saul

    Hab 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.png

    Hä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.


Anmelden zum Antworten