ちまたで話題のRPA(Robotic Process Automation)をpythonで自作することで、業務効率化はもちろん、必要に応じて内製でカスタマイズできるシステム作成を目指します。
今回は使えそうなライブラリ PyAutoGUI を試します。
-- 実行環境 --
Windows 10 64ビット版(1903)、python 3.7.4
PyAutoGUI
PyAutoUI はpythonからマウスやキーボードを制御するためのライブラリです。ドキュメントは下記になります。使えそうな関数を試してみます。
情報取得
import pyautogui as ag
# 解像度取得
(x, y) = ag.size()
print( "Monitor Size x=",x," y=",y)
# マウスのポジション取得
(x, y) = ag.position()
print( "Position x=",x," y=",y)

パッとマニュアル見た感じではデュアルモニタには対応していないように見えますが、取り急ぎ要件的には問題ないのでスルーします。
— 追記 —
解像度、デュアルモニタ側のサイズは取得できませんが、マウスの移動やクリックで解像度以上の座標を指定することで移動やクリックは動作することを確認しました。
マウス操作
import pyautogui as ag
# マウス移動
ag.moveTo( 1000, 600, 0)
ag.moveTo( 10, 10, 3, ag.easeInQuad)
# マウスクリック
ag.click()
ag.click(button='right')
ag.click( x=25, y=40)
# ドラッグ&ドロップ1(デスクトップ上の指定座標にファイルアイコンあり)
# dragTo はWait 0 だと動作しない
ag.moveTo( 553, 230, 0)
ag.dragTo( 1053, 230, 1, button='left')
# ドラッグ&ドロップ2(アイコン位置を戻す)
# wait なしでも動作可
ag.mouseDown( button='left')
ag.moveTo( 553, 230, 0)
ag.mouseUp( button='left')
# ダブルクリック(移動させたアイコン実行)
ag.doubleClick()
座標さえ指定出来れば思った以上に簡単&スムーズに動くようです。もう少し様々なケースや環境での検証は必要ですがマウス操作はこれで行きたいですね。
この関数を使用する場合、課題となりそうなのが「ターゲットウィンドウのZオーダー制御」「操作対象の座標取得」「結果のチェック」あたりでしょうか。
キーボード操作
import pyautogui as ag
import subprocess as sp
import time
# メモ帳OPEN
sp.Popen( "notepad.exe")
time.sleep(1)
# 書き込み
ag.typewrite( "typewrite pyautugui test!")
ag.press( "enter")
# 書き込み2
ag.keyDown("shift")
ag.typewrite( "typewrite pyautugui test!")
ag.keyUp("shift")
ag.press( "enter")
# コピー/ペースト
ag.hotkey( "ctrl", "a")
ag.hotkey( "ctrl", "c")
ag.press( "right")
ag.press( "enter")
ag.hotkey( "ctrl", "v")
# 全角
ag.press( "kanji")
ag.press( "a")
ag.typewrite( "a")
ag.press( "enter")
ag.press( "kanji")

書き込み自体はスムーズに実行できているが、下記の課題からあまり現実的ではないように思われる。(負荷が高いタイミングで誤動作する様が目に浮かびます)
- 入力箇所にカーソルを合わせておく必要がある
- 全角入力する場合はキー単位で入力する必要がある
キーボード操作という観点ではおそらく他のライブラリを使用しても変わらないのではないかと思っています。高精度の方法があればコメントで教えて頂けると嬉しいです。
スクリーンショット機能
画面上から検索するターゲットとなるボタンの画像を事前に取得しておきます。サンプルでは「ss-01-target.png」としています。
import pyautogui as ag
# 画像取得
ag.screenshot( "ss-01.png")
# 画像認識1
pos = ag.locateOnScreen( "ss-01-target.png")
print( pos)
# 画像認識2
pos = ag.locateCenterOnScreen( "ss-01-target.png")
print( pos)

単体での動作は問題ないように見えます。ただし、下記課題があるようです。
- 透過ウィンドウだと正常に検知出来ない
- デュアルモニタ側の検知は出来ない
- ほんの僅かな差があっても検知出来ない
透過ウィンドウについては背面の色が表に影響します。そのため、3番目の僅かな差に該当してヒットしないようです。OS標準の電卓で試してみましたがウィンドウ選択時と非選択時で透過の状態が変わっているようで確かにエラーとなることを確認しました。

ドキュメントを見るとPyAutoGUIでは 「精度を下げる方法」と「グレイスケールを使用する方法」があるようです。精度を下げる場合には事前に別ライブラリOpenCVをインストールする必要があります。下記コマンドで事前にインストールを行ってください。
pip install opencv-python
画像検知の検証
デフォルト値での画像検知ではほんの僅かな差異も認められないため、他のPCで取得した画像などで全く動作しないといった事象が起きるようです。そういった環境や透過ウィンドウでの動作不良の回避方法について検証してみます。
使用するアプリとその画面
OS標準の電卓を使用します。OS標準の電卓はストアアプリになってからアクティブ時と非アクティブ時で画面の状態が変わることから画像検知が難しくなっています。下記に画像の状態をアップしておきます。
非アクティブ時の電卓

アクティブ時の電卓

画像検知 - 検証1 精度
画像検知の結果を「デフォルト」「グレイスケール」「精度調整」の3パターンで実行してみました。今回検知で使用した画像 ss-03-target.png は電卓選択状態のボタン 9 を枠を含んだ画像になっています。
import pyautogui as ag
import time
print( "3秒以内に電卓をアクティブにしてください。")
time.sleep(3)
# 画像認識1 - Default
try:
pos = ag.locateCenterOnScreen( "ss-03-target.png")
print( "Default : ", pos)
except:
print( "Default : ERROR")
# 画像認識2 - グレイスケール
try:
pos = ag.locateCenterOnScreen( "ss-03-target.png", grayscale=True)
print( "glayscale : ", pos)
except:
print( "glayscale : ERROR")
# 画像認識3 - 精度 1.0 → 0.9
try:
pos = ag.locateCenterOnScreen( "ss-03-target.png", confidence=0.9)
print( "confidence : ", pos)
except:
print( "confidence : ERROR")

成功したのは精度を0.9まで落としたケースのみでした。精度を落とせば当然誤検知が発生する可能性が出てくるので「精度を可能な限り保ちつつ」「未検知をなくし」「誤検知を減らす」ことが出来るパラメーターを模索する必要がありそうです。
また、今回はグレイスケールでも検知できませんでしたがopencvを使えば様々な手法があるそうなので、そちらのライブラリ検証時に色々やってみたいと思います。
画像検知 - 検証2 検知対象複数
OKボタンなど同一画面上に複数同じ個所が存在する場合を試してみました。結果は下記のようになります。複数ターゲットが出来ないように検知対象画像をうまく生成する必要がありそうです。
- 結果は最初にヒットした1か所のみしか取得出来ない。
- Y座標の値が低いほうが先にヒットする。
- デュアルモニタ側は対象外
まとめ
今回は使えそうなライブラリから PyAutoGUI を試しました。思った以上に簡単に各処理を行うことが出来ました。それぞれの機能について下記にまとめました。
処理内容 | 採用 | 検討 |
情報収集 | △ | デュアルモニタの場合など処理が出来ない。 別のライブラリを使用したほうが将来的にはよさそう。 |
マウス操作 | ◎ | PyAutoGUIで十分だと思われる。非常にシンプルに 処理が書けるのがいいです。 |
キーボード操作 | ○ | 一字ずつ入力はかなり不安。入力エリアの情報取得→修正 →一括書き戻しなど入力方法の検討が必要。 |
画像検知 マッチング | △ | 検知対象の画像を動作させるPCと同一環境で作成する場合は 問題なく動作。ただし、下記問題点あり。 ・他のPCで作ったテンプレートで正常に動かない。 ・デュアルモニタ側を検知しない。 |
次回はOpenCVを検証してみたいと思います。精度の高い画像検知/入力チェックの機構は必須要件なのでより良い結果が出せればうれしいところです。
— 追記 —
作成したプログラム&マッチング用画像を別PCで使用した時に全く検知しないケースが確認されました。どうやら画像のマッチングで必要となる前提条件に抵触するようです。
(テンプレートを取得したPCとマッチングの際に取得するモニタ画像でビットの深さが違う等が確認できました)
さらにグレイスケール化のやり方によりビットの深さが変わっていない場合があるようです。画像マッチングについては、デュアルモニタ対策や画像の調整も考えるとOpenCVを使うほうがデバッグも含めよさそうです。
コメント