LoginSignup
2
3

More than 1 year has passed since last update.

マスク付きテンプレートマッチングでスプラトゥーン3のイカランプを認識させてみた

Last updated at Posted at 2022-10-27

openCVのcv2.matchTemplate()によるテンプレートマッチングでは、アルファ値が使えないことで有名ですが、実はマスク付きテンプレートマッチングで透過処理が可能です。

公式ドキュメント:https://docs.opencv.org/4.x/d4/dc6/tutorial_py_template_matching.html

オライリー・ジャパンから出版されてる「詳解OpenCV 3」にもマスク付きのテンプレートマッチングのことは取り上げられていませんでした。

かなり便利な機能だったので本記事でご紹介したいと思います。

cv2.matchTemplate()にテンプレート画像を同じサイズのマスクを渡すことで、「透明なピクセル」のような扱いが可能です。アルファ値ではないため半透明を取り扱うことはできませんが、マスクの取り方としきい値である程度調整可能かと思います。
マスクを掛けることで自由な形状のテンプレート画像でマッチングさせることができます。

icons.png
(icons.png) @2022 任天堂 スプラトゥーン3

こちらはスプラトゥーンの、8人のプレイヤーの使用ブキを表したアイコン通称「イカランプ」の画像です。

ここからスプラシューターのアイコンを検出したいと思います。

splashooter.png
(splashooter.png) @2022 任天堂 スプラトゥーン3
こちらにこのようなテンプレートと、

splashooter_mask.png
(splashooter_mask.png)
マスク画像

を引数に指定してマッチングさせてみたいと思います。

import cv2
import numpy as np

img = cv2.imread(r"icons.png")
template = cv2.imread(r"splashooter.png")
mask = cv2.imread(r"splashooter_mask.png", 0)

res = cv2.matchTemplate(img, template, cv2.TM_CCORR_NORMED, mask=mask)
loc = np.where(res >= 0.95) # しきい値
for pt in zip(*loc[::-1]):
    cv2.rectangle(img, pt, (pt[0] + template.shape[1], pt[1] + template.shape[0]), (0,0,255), 1)

cv2.imshow("img", img)
cv2.waitKey() # キー入力で終了

・結果
res.png
 @2022 任天堂 スプラトゥーン3

背景によらずマッチングさせることができました!!
前からこういう画像検出をやってみたかったんですがついに実現して感動しました・・!

というかマスクなしのテンプレートマッチングってほぼ役に立たないような・・矩形でない形状の検出をしたいケースって山ほどありますし。

ちなみに余談ですが、cv2.matchTemplate()が返すRECTのリストですが、位置が重複したものを複数返してくるので重複を取り除く処理が必要になります。

検出結果の画像の赤い四角形の線が太いものになっているのは重複したRECTをすべて描画しているため太い線のように見えています。
今回のケース、本来であれば2つのRECTを取得できるのが適切な処理です。

本記事では取り扱いませんが、重複除去の手法であるNon Maximum Suppressionについて
紹介してる記事のリンク貼っておきます。お役に立てればと。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3