前回、パターンマッチを試しましたが、異なるサイズに対応できていなかったので、今回は異なるサイズに対するパターンマッチングを試してみます。
なお、回転とかも同じ考え方でできると思うので傾き違いに関しては割愛します。
また、アルゴリズムについては勉強したわけではないので王道があるのかとかは知らないですし、パフォーマンス面も考慮していません。
環境
- VSCode
- python 3.11.0
使用するライブラリ
- cv2
パッケージのインストール方法についてはこちら
異なるサイズへのパターンマッチ
考え方
何もひねっていません。
サイズが違うと検出できないなら、サイズを変えながら総当たりするだけです。
コード
import cv2 import numpy as np 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) show_image("img", image_gray) template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) ret_image = image.copy() for i in range(10,100,5): t2 = template_gray.copy() t3 = cv2.resize(t2, None, fx=i/100, fy=i/100, interpolation=cv2.INTER_CUBIC) result = cv2.matchTemplate(image_gray, t3, cv2.TM_CCOEFF_NORMED) loc = np.where(result > 0.7) w, h = t3.shape for pt in zip(*loc[::-1]): ret_image = cv2.rectangle(ret_image, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2) show_image("img", ret_image) if __name__=="__main__": pattern_match()
サイズを変えながら繰り返し
ret_image = image.copy() for i in range(10,100,5): t2 = template_gray.copy() t3 = cv2.resize(t2, None, fx=i/100, fy=i/100, interpolation=cv2.INTER_CUBIC) result = cv2.matchTemplate(image_gray, t3, cv2.TM_CCOEFF_NORMED)
テンプレート画像を10%~100%の間で5%刻みに繰り返します。
リサイズはcv2.resize()
で割合指定でサイズ変更しています。
一応、滑らかに拡縮してほしいので補間モードはcv2.INTER_CUBIC
を指定しました。
一致度でフィルタをかける
cv2.minMaxLoc()
では一つしか検出できないので、探し方を変えます。
loc = np.where(result > 0.7) w, h = t3.shape for pt in zip(*loc[::-1]): ret_image = cv2.rectangle(ret_image, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
np.where()
を使ってマッチ結果の中から閾値を超えたもののみを抽出します。
この閾値はフィルタによっても画像によっても変わってくるので正しくは外部からパラメータとして渡すべきでしょう。
今回はよさげな結果が得られるパラメータを見つけてベタ打ちしています。
後は、得られた結果から検出個所を可視化しています。
結果
無事すべての「G」を見つけることができました。
おしまい
より効率的にやるにはどうしたらよいのかはぼちぼち調べてみようと思います