私は最近、テンプレート マッチングに興味を持っています。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