opencvを使ってファイル内にある複数枚(50~100枚を想定)の画像に対して、1枚のテンプレートでテンプレートマッチングを行いたいと考えています。
現在は、
1枚の画像撮影→元の画像にテンプレート1枚をマッチングさせるという形までは出来ています。
そこでプログラム処理の流れとして、
1.ファイル内の画像を読み込む
2.テンプレート画像でマッチングさせる
3.類似度が高い画像領域がある場合は検出画像としてその部分を枠で囲み、画像を保存する
以上の1.~3.をファイル内の画像をすべて検証するまで繰り返す、
というプログラムにしたいのです。
ファイル内からのたくさんの画像を読み込み、順番に一枚ずつマッチングを行う方法と最後の類似度を表示させる段階で表示できなくて困っています。
類似度の算出方法はSSD(Sum of Absolute Difference)という「画素値の差分の二乗値の和」で類似度を評価します。
類似度の計算方法には種類がいくつかありますが、「SAD」、「NCC」、「ZNCC」などの評価方法の場合についてもどのようなプログラムになるのでしょうか。
解決方法を教えていただけたらと思います。
動作環境は、
opencv3.2、python3.5です。
コードを以下に書きます。
よろしくお願い致します。
また、別の方法があれば教えていただきたいです。(SSDでのテンプレートマッチング法, NumpyとOpenCV)
import cv2 import numpy as np def main(): # 入力画像とテンプレート画像をで取得 img = cv2.imread("i.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 print(cv2.minMaxLoc(match)) # テンプレートマッチングの結果を出力 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()
import cv2 import numpy as np def template_matching_sad(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 = np.abs(src[dy:dy + ht, dx:dx + wt] - temp) 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_sad(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()

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。