【Python/OpenCV】テンプレートマッチング(SSD)の実装例

この記事では、PythonとOpenCVで画像のテンプレートマッチング(SSD)を行う方法をソースコード付きで解説します。

テンプレートマッチング(SSD)

テンプレートマッチング(Template matching)とは、入力画像中からテンプレート画像(部分画像)と最も類似する箇所を探索する処理です。
原理については下記事で解説しています。
【参考】テンプレートマッチングの原理・計算式・例題(SAD, SSD, NCC)

■SSD
SSD(Sum of Absolute Difference)では、「画素値の差分の二乗値の和」で類似度を評価します。
この場合も値が最小になる場所が類似度が最も高いことになります。

今回は、SSDを類似評価とし、以下の2通りの方法でテンプレートマッチングの処理を実装しました。

①NumPyライブラリで実装
②OpenCVの「cv2.matchTemplate」で実装

書式(OpenCV)

match = cv2.matchTemplate(gray, temp, cv2.TM_SQDIFF)
min_value, max_value, pt_min, pt_max = cv2.minMaxLoc(match)
パラメータ 説明
gray 入力画像(グレースケール)
temp テンプレート画像(グレースケール)
pt_min スコアが最小の走査位置(最も類似する点)
pt_max スコアが最大の走査位置(最も類似しない点)

ソースコード(Python3)

サンプルプログラムのソースコードです。

方法①

#-*- coding:utf-8 -*-
import cv2
import numpy as np

def template_matching_ssd(src, temp):
    # 画像の高さ・幅を取得
    h, w = src.shape
    ht, wt = temp.shape
   
    # スコア格納用の二次元配列
    score = np.empty((h-ht, w-wt))
  
    # 走査
    for dy in range(0, h - ht):
        for dx in range(0, w - wt):
            # 二乗誤差の和を計算
            diff = (src[dy:dy + ht, dx:dx + wt] - temp)**2
            score[dy, dx] = diff.sum()

    # スコアが最小の走査位置を返す
    pt = np.unravel_index(score.argmin(), score.shape)

    return (pt[1], pt[0])


def main():
    # 入力画像とテンプレート画像をで取得
    img = cv2.imread("input.png")
    temp = cv2.imread("temp.png")

    # グレースケール変換
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)   
    temp = cv2.cvtColor(temp, cv2.COLOR_RGB2GRAY)   

    # テンプレート画像の高さ・幅
    h, w = temp.shape

    # テンプレートマッチング(NumPyで実装)
    pt = template_matching_ssd(gray, temp)

    # テンプレートマッチングの結果を出力
    cv2.rectangle(img, (pt[0], pt[1] ), (pt[0] + w, pt[1] + h), (0,0,200), 3)
    cv2.imwrite("output.png", img)


if __name__ == "__main__":
    main()

方法②

#-*- coding:utf-8 -*-
import cv2
import numpy as np


def main():
    # 入力画像とテンプレート画像をで取得
    img = cv2.imread("input.png")
    temp = cv2.imread("temp.png")

    # グレースケール変換
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)   
    temp = cv2.cvtColor(temp, cv2.COLOR_RGB2GRAY)   

    # テンプレート画像の高さ・幅
    h, w = temp.shape

    # テンプレートマッチング(OpenCVで実装)
    match = cv2.matchTemplate(gray, temp, cv2.TM_SQDIFF)
    min_value, max_value, min_pt, max_pt = cv2.minMaxLoc(match)
    pt = min_pt

    # テンプレートマッチングの結果を出力
    cv2.rectangle(img, (pt[0], pt[1] ), (pt[0] + w, pt[1] + h), (0,0,200), 3)
    cv2.imwrite("output.png", img)


if __name__ == "__main__":
    main()

※動作には、OpenCVライブラリのインストールが必要です。

実行結果

サンプルプログラムの実行結果です。

■左から入力画像(input.jpg)、テンプレート画像(temp.jpg)、出力画像(result.jpg)

お借りした画像:プロ生ちゃん(暮井 慧)

【関連記事】
【画像処理入門】アルゴリズム&プログラミング

シェア&フォローお願いします!