上のイラストやの画像(上)から、その画像一部(下)の位置を探すタスクに取り組んでいます。
このページを参考にタスクに取り組み、元画像もテンプレート画像もpngの時にはうまくいくことを確認しました。
Python
1import cv2 2import numpy as np 3from matplotlib import pyplot as plt 4 5img = cv2.imread('cat.png') 6template = cv2.imread('cat_face.png') 7_, w, h = template.shape[::-1] 8 9res = cv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED) 10min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) 11top_left = max_loc 12btm_right = (top_left[0] + w, top_left[1] + h) 13 14cv2.rectangle(img,top_left, btm_right, 255, 2) 15 16cv2.imshow("test", img) 17cv2.waitKey(0) 18cv2.destroyAllWindows()
しかしながら、テンプレート画像の大きさが変わったり、jpgにして圧縮ノイズが入るとうまく動いてくれないときがあります。
(ノイズに関してはイラストやの画像ではOKでしたが、参考ページの猫ではうまくいきませんでした)
「テンプレートマッチング スケール」などと調べても有効そうな情報が得られず、困っております。
なお想定としては、
・スケール変換はおよそ50%~200%
・ノイズはpng→jpg変換で生ずる程度のもの
と考えております。
どのように解決すればよろしいか、お教えしてくださると助かります。
追記(POCの実装)
位相限定相関法を実装した結果、ノイズに対しては十分に耐性を持っていることが確認できました。ありがとうございます。
下に実装コードを示します。
Python
1import cv2 2import numpy as np 3 4from matplotlib import pyplot as plt 5import matplotlib.patches as patches 6 7img = cv2.imread("ai/ai.png", 0) # 元画像 8template = cv2.imread("ai/ai_part_x92.png", 0) # マッチング対象のテンプレート画像 9im_h, im_w = img.shape # 元画像のサイズ取得 10temp_h, temp_w = template.shape # テンプレート画像のサイズ取得 11 12template = cv2.copyMakeBorder( 13 template, 14 0, 15 im_h - temp_h, 16 0, 17 im_w - temp_w, 18 cv2.BORDER_CONSTANT, 19 (0, 0, 0), 20) # POCができるようにテンプレート画像をパディング 21 22shift, theta_shift = cv2.phaseCorrelate( 23 template.astype(np.float32), img.astype(np.float32) 24) # POCでシフト量を取得 25 26rect = patches.Rectangle( 27 xy=(shift), width=temp_w, height=temp_h, ec="b", fill=False 28) # テンプレートと一致する部分を四角形で表示 29 30# 図示 31plt.subplot(121), plt.imshow(img, cmap="gray") 32plt.subplot(121).add_patch(rect) 33plt.title("Input Image"), plt.xticks([]), plt.yticks([]) 34plt.subplot(122), plt.imshow(template, cmap="gray") 35plt.title("Template Image (92%)"), plt.xticks([]), plt.yticks([]) 36plt.show() 37 38print(shift) # 最後にシフト量を表示
問題点
しかしながら、スケーリングの問題に関しては92%ほど縮小したテンプレート画像に対して、下のような出力になってしまい、いわば元画像の左上とパディングされたテンプレート画像の右下が一致してしまっております。
Python
1>> print(shift) 2# (-198.66021205773234, -197.0159913577939)
位相限定相関法とか,スケール自体も探索対象となっているような方法
と伺っていて、多少縮小したものでもうまくいくと思っておりましたが、パディングしたのが悪かったのでしょうか。
cv2.copyMakeBorder()において、二つの画像が同じサイズである必要があるので、パディングさせていただきました。何か良い対処法がございましたらお教えしてくださると助かります。
回答1件
あなたの回答
tips
プレビュー