前提・実現したいこと
画面の一部をスクリーンショットでキャプチャして,事前に用意した画像のどのあたりにキャプチャした内容が含まれているか判定したいです.
発生している問題
テンプレートマッチングの精度が低く,全く異なる位置とテンプレートマッチングします.
スクリーンショットを一旦書き込んで再読み込みするととりあえずは解消しますが,処理速度を速くしたいのとファイルの作成は出来るだけ控えたいので,別の方法でこの問題を解消したいです.
該当のソースコード
デスクトップ画面のゴミ箱のあたり(left, top, width, height) = (60, 20, 40, 40)をスクリーンショットでキャプチャして,
事前に用意しておいたデスクトップ画像のどこにキャプチャとの類似領域が存在するか判定するプログラムです.
最終的には,画面に次々現れる大量のアイコンを順にキャプチャして,事前に用意した全アイコンを表状に並べた画像中からキャプチャした対象とマッチするものを発見するプログラムにするつもりです.
Python
1import pyautogui 2import cv2 3import numpy as np 4 5IMG_DESKTOP = cv2.imread("desktop.png") 6 7if __name__ == '__main__': 8 # スクリーンショット 9 cap = pyautogui.screenshot(region = (60, 20, 40, 40)) 10 11 # 方法1 12 print("方法1") 13 result = cv2.matchTemplate(IMG_DESKTOP, np.uint8(cap), cv2.TM_CCOEFF_NORMED) 14 min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) 15 top_left = max_loc 16 print("位置:", top_left) 17 print("類似度:", max_val) 18 19 # 方法2 20 print("方法2") 21 cap.save("cap.png") 22 img_tmp = cv2.imread("cap.png") 23 result = cv2.matchTemplate(IMG_DESKTOP, img_tmp, cv2.TM_CCOEFF_NORMED) 24 min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) 25 top_left = max_loc 26 print("位置:", top_left) 27 print("類似度:", max_val) 28
結果
方法1 位置: (67, 644) 類似度: 0.3924467861652374 方法2 位置: (60, 20) 類似度: 0.9999991059303284
試したこと
上のコードの方法1のようなファイル読み書きをしない方法で実装したいです.
方法1と方法2を10000回繰り返すと,方法1の方が50秒も速く終わりました.
しかし上の結果の通り,方法1では(60, 20)とはまったく違う場所をマッチングしました.類似度も小さいです.
uint8へのキャストがマズいのかと思い,np.uint8をnp.float32に変えてみましたが,以下のようなエラーが返され,キャストはnp.float32では良くなさそうだというところまでは来ましたが,それ以上長時間手詰まりになってしまいました.
cv2.error: OpenCV(4.4.0) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-9d_dfo3_\opencv\modules\imgproc\src\templmatch.cpp:1163: erro163: error: (-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 in function 'Template'cv::matchTemplate'
補足情報(FW/ツールのバージョンなど)
python 3.8.5
opencv-python 4.4.0.44
PyAutoGUI 0.9.52
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。