今からでも間に合う

技術を学ぶのは今からでも遅くない

opencvでパターンマッチング(異なるサイズ)

前回、パターンマッチを試しましたが、異なるサイズに対応できていなかったので、今回は異なるサイズに対するパターンマッチングを試してみます。

なお、回転とかも同じ考え方でできると思うので傾き違いに関しては割愛します。
また、アルゴリズムについては勉強したわけではないので王道があるのかとかは知らないですし、パフォーマンス面も考慮していません。

環境

  • 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」を見つけることができました。

異なるサイズを複数検出

おしまい

より効率的にやるにはどうしたらよいのかはぼちぼち調べてみようと思います

python入門Top

プライバシーポリシー


d払いポイントGETモール