ちまたで話題のRPA(Robotic Process Automation)をpythonで自作することで、業務効率化はもちろん、必要に応じて内製でカスタマイズできるシステム作成を目指します。
今回は今まで検証したモジュールを使用してRPAベースとなる画像検知スクリプトを作ってみたいと思います。
-- 実行環境 --
Windows 10 64ビット版(1903)、python 3.7.4
これまで
今までPyAutoGUI、OpenCV、PyWin32を使用してマウス操作や画像検知、マルチモニタ時のデスクトップ全体画像取得など試してきました。
ここでいったん、検証した内容をまとめて画像検知→ダブルクリックして起動するモジュールを作ってみたいと思います。
今回テストで使用するモニタ全体とターゲット(検知/実行対象)は下記となっています。
デスクトップ全体

ターゲット画像

サンプル
今回はターゲット画像を検知/座標を取得して、取得座標に対してダブルクリックを行うサンプルとなっています。
import time
import numpy as np
from datetime import datetime, timedelta
import win32api
import win32gui
import win32ui
import win32con
import pyautogui
import cv2
def main():
print( "Time:", datetime.now())
# パラメーター指定
target_pict = r"D:\test_python\target.png"
limit_val = 0.95 # 類似度限界
limit_time = 60 # 見つかるまで60秒待機
click_type = 2 # ダブルクリック
# 検索→ダブルクリック
x, y = search_picture(target_pict, limit_val, limit_time)
result = fnc_click( x, y, click_type)
if result is True:
print( "-> Success")
else:
print( "-> Failure")
print( "Time:", datetime.now())
#=========================================
# デスクトップのキャプチャ取得(マルチモニタ対応)
#=========================================
def get_capture():
try:
# ウィンドウサイズ取得
w = vscreenwidth = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
h = vscreenheigth = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
l = vscreenx = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
t = vscreeny = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)
width = l + w
height = t + h
# ウィンドウのデバイスコンテキスト取得
hwnd = win32gui.GetDesktopWindow()
windc = win32gui.GetWindowDC(hwnd)
srcdc = win32ui.CreateDCFromHandle(windc)
memdc = srcdc.CreateCompatibleDC()
# デバイスコンテキストからピクセル情報コピー, bmp化
bmp = win32ui.CreateBitmap()
bmp.CreateCompatibleBitmap(srcdc, width, height)
memdc.SelectObject(bmp)
memdc.BitBlt((0, 0), (width, height), srcdc, (0, 0), win32con.SRCCOPY)
# イメージ取得/グレイスケール化
img = np.frombuffer(bmp.GetBitmapBits(True), np.uint8).reshape(height, width, 4)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 解放
srcdc.DeleteDC()
memdc.DeleteDC()
win32gui.ReleaseDC(hwnd, windc)
win32gui.DeleteObject(bmp.GetHandle())
return img
except Exception as err:
# 取得失敗
return None
#================================================
# 画像検索 座標取得
#================================================
def search_picture(target_pict, limit_val, limit_time):
try:
# タイムアウト時間取得
end_time = datetime.now() + timedelta( seconds=limit_time)
while True:
# 全体画面キャプチャ取得
capture = get_capture()
# ターゲット画像取得/グレイスケール化
target = cv2.imread(target_pict)
target = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
# 画像検索
result = cv2.matchTemplate( target, capture, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
print( "-> 類似度 : "+str( max_val))
if max_val > limit_val:
break
# タイムアウト時間超えたらエラー
if datetime.now() > end_time:
return 0, 0
print( "-> search target pict...")
time.sleep(1)
# 検知した座標取得(ターゲット画像の中心)
h ,w = target.shape[:2]
x = max_loc[0] + int(w/2)
y = max_loc[1] + int(h/2)
return x, y
except Exception as err:
return 0, 0
#================================================
# 指定座標でマウスイベント
#
# click_type:
# 1 Left Click
# 2 Left DoubleClick
# -1 Right Click
#================================================
def fnc_click(x, y, click_type):
try:
if x == 0 or y == 0:
return False
if click_type == 1:
pyautogui.click( x, y, button="left")
print( "-> Left Click Act OK")
if click_type == 2:
pyautogui.doubleClick( x, y)
print( "-> Left DoubleClick Act OK")
if click_type == -1:
pyautogui.click( x, y, button="right")
print( "-> Right Click Act OK")
return True
except Exception as err:
return False
if __name__ == '__main__':
# メイン処理
main()
実行結果

検知対象の「ターゲット.txt」を検知してダブルクリックでテキストファイルが開くことを確認しました。処理時間も1秒以内と十分実用に耐えうるのではないでしょうか。
1点、今回は検知をメインにしているためマウスイベントに関する処理が適当です。
マウスイベント自体の結果はもちろんですが、望んでいる処理が実行されているかはこの後に必ずチェックが必要となります。(今回のサンプルではテキストファイルがOPENされたか否か)
まとめ
今回は今まで検証した内容をまとめて、ターゲット画像からモニタの座標を取得してマウスイベントを実行するサンプルを紹介しました。思ったより処理も早く、実用に耐えうるものになったのではないでしょうか。
よりよい方法等あればコメントで教えて頂けると嬉しいです。
今回は閲覧頂きありがとうございました。
コメント