1

我最近对模板匹配感兴趣,我知道 OpenCV 之类的库存在,但我想创建一个简单的函数来查找可以在搜索 BufferedImage 中找到模板的所有点,而无需任何额外的库或安装软件等。

我在 wiki 上找到了一篇关于它的文章,其中包含一些代码:

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

它似乎完全符合我的需要,所以我已经将它移植到 Java 中,但不是灰度,而是稍微改变了它以使用颜色。使用纯白色模板图像(30x30)和搜索图像(508x307)进行测试,搜索图像也是纯白色,但在某些区域带有红色矩形,代码似乎可以正确输出到控制台一段时间,但是我收到错误:

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)
    

我不确定这是否是由于它不是灰度的事实,或者 java 是否需要对循环量进行额外调整,但任何帮助使其正常工作的帮助将不胜感激。

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;
}

我测试的图像:

Template.png(它是纯白色的,因此在页面上看起来不可见)

模板.png

搜索.png

搜索.png

4

1 回答 1

1

似乎 wiki 提供了错误的代码,并且 X 和 Y 是相反的,当交换它似乎工作时。

于 2012-10-10T13:30:14.760 回答