OpenCV のテンプレートマッチングについて知りたいです…
「テンプレートマッチングとは何か?」
「コードで実装する方法」
について解説しよう。
✔️ 本記事のテーマ
OpenCV のテンプレートマッチング
✔️ 読者さんへの前置きメッセージ
本記事は
「テンプレートマッチングとは?」 や 「サンプルコード」
について書いています。
テンプレートマッチングとは
「画像中からテンプレートと類似した部分を探し出す画像処理」のことです。
OpenCV ではこのテンプレートマッチングを簡単なコードで実装することができます。
この記事に掲載しているサンプルコードは環境さえ整っていれば、
コピペで動くはずなので使用して頂いてOKです。
では、解説していきましょう。
OpenCV のテンプレートマッチング処理とは
OpenCV のテンプレートマッチングには
- 「処理対象画像」
- 「テンプレート画像」
の 2 つが必要です。
処理概要としては
「処理対象画像」から「テンプレート画像」と類似した部分を抽出する
という処理になります。
例えば、以下のような「テンプレート画像」を用意して
以下のような「処理対象画像」に対してテンプレートマッチング処理をかけます。
すると、以下のように
「処理対象画像」から「テンプレート画像」と類似した部分
を抽出することができます。
上記処理では、マリオのコインと同じ部分を抽出しています。
注目すべきは、赤コインは類似箇所として検出していない点です。
このように色の違いなども判定してくれる精度の高い処理になっています。
OpenCV では関数を呼び出すだけでこのような処理を実現することができます。
次の章から、コードベースで解説していきましょう。
OpenCV のテンプレートマッチングのサンプルコード
OpenCV でテンプレートマッチングを実装するコードの全体像は以下になります。
import cv2
import numpy as np
# 画像の読み込み + グレースケール化
img = cv2.imread('./tpl_match.png')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
template = cv2.imread('./tpl_match_tpl.png')
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
# 処理対象画像に対して、テンプレート画像との類似度を算出する
res = cv2.matchTemplate(img_gray, template_gray, cv2.TM_CCOEFF_NORMED)
# 類似度の高い部分を検出する
threshold = 0.8
loc = np.where(res >= threshold)
# テンプレートマッチング画像の高さ、幅を取得する
h, w = template_gray.shape
# 検出した部分に赤枠をつける
for pt in zip(*loc[::-1]):
cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
# 画像の保存
cv2.imwrite('./tpl_match_after.png', img)
処理の内容を順番に見ていきましょう。
ライブラリのインポート
まずは、使用するライブラリを import します。
import cv2
import numpy as np
今回は OpenCV を使うために cv2 と、
テンプレートマッチング処理の中で使用する numpy を import します。
画像の読み込み + グレースケール化
次に、処理で使用する画像を読み込みます。
テンプレートマッチングでは「処理対象画像」と「テンプレート画像」を使うため、
2 つの画像を読み込みます。
また、テンプレートマッチング処理ではどちらの画像もグレースケールである必要があります。
そこで cv2.cvtColor 関数でグレースケール画像に変換します。
img = cv2.imread('./tpl_match.png')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
template = cv2.imread('./tpl_match_tpl.png')
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
このようにすることで、テンプレートマッチング処理のための前処理が完了します。
処理対象画像に対して、テンプレート画像との類似度を算出する
テンプレートマッチングでは
「処理対象画像」中から「テンプレート画像」と似ている箇所を検出します。
そこで、まず処理対象画像全体における「テンプレート画像」との類似度を算出します。
類似度の算出には cv2.matchTemplate 関数を使用します。
res = cv2.matchTemplate(img_gray, template_gray, cv2.TM_CCOEFF_NORMED)
cv2.matchTemplate 関数は
- 第 1 引数: 処理対象画像
- 第 2 引数: テンプレート画像
- 第 3 引数: 類似度の計算方法
を渡して使用します。
関数の戻り値には画像全体の類似度が格納された Numpy 配列になっています。
類似度の高い部分を検出する
続いて、画像中から「類似度の高い部分」だけを検出します。
cv2.matchTemplate 関数の戻り値には画像全体の類似度が全て格納されているので、
特に類似度の高い部分だけを抽出します。
cv2.matchTemplate 関数の戻り値は Numpy 配列になっているので、
Numpy ライブラリの where 関数を使用して threshold (閾値)以上の箇所を特定します。
今回は閾値を 0.8 に設定しています。
threshold = 0.8
loc = np.where(res >= threshold)
np.where 関数の引数に条件(res >= threshold)だけを渡すことで、
条件を満たす配列インデックスが返ってきます。
テンプレートマッチング画像の高さ、幅を取得する
cv2.matchTemplate 関数で取得できるのは「類似度の高い部分(四角形)」の左上座標です。
後続の処理で類似度の高い部分に赤枠をつけるために、
テンプレート画像の幅と高さを取得します。
h, w = template_gray.shape
これにより、後続の処理で検出した部分に四角形の赤枠をつけることができます。
検出した部分に赤枠をつける
最後に、ここまでで算出した
「類似度の高い部分の座標」「高さ」「幅」を使って赤枠をつけていきます。
赤枠の描写には cv2.rectangle 関数を使用します。
for pt in zip(*loc[::-1]):
cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
変数 loc には x 座標, y 座標が以下のような形式で格納されています。
(array([91, 92, 92, 92, 92, 92]), array([195, 145, 146, 170, 171, 195]))
これを zip 関数、list 展開(*)、スライス(::-1) を使うことで
(x座標, y座標) のタプルとして pt に格納して、for ループ処理の中で使っています。
for pt in zip(*loc[::-1]):
なお cv2.rectangle 関数の使い方については
「cv2.rectangle関数の使い方【長方形を描画する】」
の記事で詳しく解説しています。
画像の保存
最後に、赤枠をつけた画像データを画像ファイルとして保存します。
cv2.imwrite('./tpl_match_after.png', img)
なお cv2.imwrite 関数の使い方については
「OpenCVで画像を保存する方法【Python】」
の記事で詳しく解説しています。
画像処理を独学で学ぶのに「最適」の 1 冊
OpenCVのテンプレートマッチング処理について解説しました。
OpenCVは画像処理には欠かすことのできないライブラリです。
もし、OpenCVについて独学でスキルをつけるなら、以下の書籍がオススメです。
この書籍はOpenCVの基礎から応用までを
丁寧にかつ詳細に解説しています。
OpenCVのほぼ全てを網羅しているとも言えるほどの徹底ぶりなので、
関数のリファレンスとしても使用することができます。
本記事で解説したcv2.matchTemplate 関数も掲載されています。
エンジニアとしての自身の価値をチェックする(完全無料)
エンジニアとして、
自分の価値がどれくらいのものかご存知でしょうか?
エンジニアとしてIT業界に身を置いていると
今の会社でずっと働くのか、フリーランスとして独立するのか …
と様々な選択肢があります。
どの選択肢が正解なのかを見極めるためにも、選択肢を広げるためにも
自身の価値を知っておくことはとても重要です。
TechClips ME では、
職務経歴書をアップロードするだけで企業からのスカウトを受けることができます。
▼▼▼▼▼
▲▲▲▲▲
しかもTechClips MEでは想定年収を企業から提示してくれるので、
自身の価値を数字で分かりやすくたしかめることができます。
登録はもちろん完全無料なので、一度登録してみると良いかもしれません。
コメント