Question

I have recently been interested in template matching, I know librarys like OpenCV exist but i wanted to make a simple function to find all the points where a template can be found in a search BufferedImage without the need for any extra librarys or installing software etc.

I found a article on wiki about it which contained some code:

http://en.wikipedia.org/wiki/Template_matching

It seems to do exactly what i need so i have ported this to Java but instead rather than greyscale changed it slightly to use colors. Testing with a solid white Template image (30x30) and a Search image (508x307) which is also solid white but with red rectangles in some areas the code seems to output correctly to the console for a while however i am then getting errors:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!
    at sun.awt.image.ByteInterleavedRaster.getDataElements(Unknown Source)
    at java.awt.image.BufferedImage.getRGB(Unknown Source)
    

I am not sure if this is due to the fact it's not greyscale or if java requires additional adjustments to the loop amounts but any help getting this to work correctly would be appreciated.

public Point[] TemplateMatchBI(BufferedImage Search, BufferedImage Template){

// Point list
ArrayList<Point> temp = new ArrayList<Point>(); 

//Matched Colors Boolean
boolean m = false; 

//Current Index, Matched Colors Count, Search Color (Int), Template Color (Int)
int index = 0, mcc = 0, sc = 0, tc = 0; 

// Quick Strings
String s01 = "Index = ", s02 = ", Search color = ", s03 = ", Template color = ", 
s04 = ", Matched? = ", s05 = ", Matched? = ", s06 = ", Template scan = ";

// Loop through the search image
for ( int x = 0; x <= Search.getHeight() - Template.getHeight(); x++ ) {
    for ( int y = 0; y <= Search.getWidth() - Template.getWidth(); y++ ) {

        // Loop through the template image
        for (int i = 0; i < Template.getHeight(); i++)
            for (int j = 0; j < Template.getWidth(); j++) {

                sc = Search.getRGB(x+i, y+j); // Set Search Color
                tc = Template.getRGB(i, j); // Set Template Color
                
                index++; // Increase index int
                m = false; // Reset m to false
                
                if ( sc == tc ){ // If the Search and Template Colors match then
                    mcc++; // Increase match count
                    m = true; // Colors match
                    //temp.add(new Point(i, j)); // Template scan point
                }

                Log(s01 + index + s02 + sc + s03 + tc + s04 + m + s05 + mcc + s06 + new Point(x, y));
                //Log("i = " + i + ", j = " + j + ", point = " + new Point(x+i, y+j));
            }
        }
    }
Point[] tempReturn = new Point[temp.size()];
temp.toArray(tempReturn);
return tempReturn;
}

The images i test with:

Template.png (It's solid white so it looks invisible on the page)

Template.png

Search.png

Search.png

Était-ce utile?

La solution

The seems to be that wiki gives the wrong code and the X and Y are in reverse, when swapped around it appears to work.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top