ある画像の中から、パターン(テンプレート)と一致する個所を検出するパターンマッチングを試してみました。
環境
- VSCode
- python 3.11.0
使用するライブラリ
- cv2
パッケージのインストール方法についてはこちら
使用する画像
検索対象
google先生のTOPページ
テンプレート画像
試してみる
上記検索対象画像から、テンプレート画像にマッチする個所を探していきます。
コード全文
import cv2 import pandas as pd import seaborn as sns import matplotlib.pyplot as plt def show_image(title, image): cv2.imshow(title, image) cv2.waitKey() cv2.destroyAllWindows() def pattern_match(): file_image = r"./google.png" file_template = r"./google_template.png" image = cv2.imread(file_image) template = cv2.imread(file_template) image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) result = cv2.matchTemplate(image_gray, template_gray, cv2.TM_CCOEFF_NORMED) df = pd.DataFrame(result) sns.heatmap(df) plt.show() min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) w, h = template_gray.shape[::-1] top_left = max_loc bottom_right = (top_left[0] + w, top_left[1] + h) ret_image = cv2.rectangle(image, top_left, bottom_right, (0, 0, 255), 2) show_image("img", ret_image) if __name__=="__main__": pattern_match()
グレースケール化
画像を読み込み、グレースケール化します。
パターンマッチはグレースケール化されてないと動作しません。
image = cv2.imread(file_image) template = cv2.imread(file_template) image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
パターンマッチ
cv2.matchTemplate
を使用します。
result = cv2.matchTemplate(image_gray, template_gray, cv2.TM_CCOEFF_NORMED) df = pd.DataFrame(result) sns.heatmap(df) plt.show()
第1引数:対象画像
第2引数:テンプレート画像
第3引数:検出方法
検出方法にはいくつか種類があります(6種)。
どのような場合にどの方法を選択すればよいのかはわかりません。
とりあえず今回はTM_CCOEFF_NORMED
を選択してみました。
戻り値にはマッチ結果の情報が含まれています。
これをヒートマップで表示してみると↓のような結果が得られました。
それっぽいところが一致度高そうに見えています。
以下は参考です。
TM_CCOEFF
TM_CCORR
TM_SQDIFF
マッチ度の高い箇所を表示する
検出した個所を可視化します。
cv2.minMaxLoc()
に得られた結果を渡すことで、マッチ度最小、最大、その位置を取得できます。
その情報を使って、四角で囲みます。
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) w, h = template_gray.shape[::-1] top_left = max_loc bottom_right = (top_left[0] + w, top_left[1] + h) ret_image = cv2.rectangle(image, top_left, bottom_right, (0, 0, 255), 2) show_image("img", ret_image)
結果
無事検出できました。
おしまい
パターンマッチはサイズや傾きまで一致していないと検出してくれないようです。
せっかくなので、異なるサイズのパターンマッチも試してみます。