JavaCV を使用して 三国志大戦4 解任済み武将カード の 武将 を判定する

kameyatakefumi.hatenablog.com

前回は難しい事をして失敗したので、今回は単純にテンプレート画像を縮小してマッチングしてみる。

以下、テンプレート画像のリサイズをしてマッチングしている。

public class TemplateMatching {

    private static final float SIKITI = 0.95f;

    public static void main(String[] args) {

        List<Mat> images = Arrays.asList(
                imread("{武将カードリスト画像}"),
                imread("{武将カードリスト画像}"),
                imread("{武将カードリスト画像}"));

        Mat template = imread("{テンプレート画像}", CV_LOAD_IMAGE_GRAYSCALE);

        // サイズ調整
        resize(template, template, new Size(40, 64), 0, 0, INTER_AREA);

        for (Mat image : images) {

            Mat grey = new Mat(image.size(), CV_8UC1);
            cvtColor(image, grey, COLOR_BGR2GRAY);

            Size size = new Size(grey.cols() - template.cols() + 1, grey.rows() - template.rows() + 1);
            Mat result = new Mat(size, CV_32FC1);
            matchTemplate(grey, template, result, TM_CCORR_NORMED);

            getPointsFromMatAboveThreshold(result, SIKITI).stream().forEach((point) -> {
                rectangle(image, new Rect(point.x(), point.y(), template.cols(), template.rows()), Scalar.RED, 2, 0, 0);
            });

            imshow("Result", image);
            waitKey(0);
        }

        destroyAllWindows();
    }

    public static List<Point> getPointsFromMatAboveThreshold(Mat m, float t) {
        List<Point> matches = new ArrayList<>();
        FloatIndexer indexer = m.createIndexer();
        for (int y = 0; y < m.rows(); y++) {
            for (int x = 0; x < m.cols(); x++) {
                if (indexer.get(y, x) > t) {
                    System.out.println("(" + x + "," + y + ") = " + indexer.get(y, x));
                    matches.add(new Point(x, y));
                }
            }
        }
        return matches;
    }

}

リサイズは 横40 縦64 としている。
この数値は 三国志大戦.NET から参照している。

以下、実行結果。
f:id:kameya_takefumi:20171108101250j:plain
f:id:kameya_takefumi:20171108101320j:plain
いい感じに判定されている!
画像を縮小させる事は大事ですね。

ただ比較対象の画像サイズによっては 横40 縦64 でもうまく判定されないものがあります。
機器によって画面サイズが違うのでズレが生じるのかな。

より精度を上げるには比較する画像から武将カードのサイズを取得して、それに合わせてテンプレート画像をリサイズする必要がありますね。

うーん、どんどん深い所へと行っていますね。
肝となる部分なので後回しにしても痛い目を見そうだ。
どうしようかな。