Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

Robotgoでgo言語で自動化

先日、Robotgoを用いた自動化する方法に関してまとめました。
elsammit-beginnerblg.hatenablog.com

今回はこちらの続き。
画像認識やマウス・キーボード入力イベントの取得方法についてまとめたいと思います。



■マウス・キーボードイベント取得

では早速、マウスやキーボードの入力イベントを取得する方法をまとめます。
こちらはユーザが操作したマウスやキーボード操作を記憶するのに利用できるかと思います。

コードですが、こちらも公式のサンプルコードを少し変更を加えております。

package main

import (
  "fmt"
  hook "github.com/robotn/gohook"
)

func main() {
  low()
}

func low() {
	EvChan := hook.Start()
	defer hook.End()

	for ev := range EvChan {
		fmt.Println("hook: ", ev)
	}
}

こちらを実行すると、マウスを動かすごとに

 Event: {Kind: MouseMove, Button: 0, X: 920, Y: 720, Clicks: 0}

といったようにマウスのカーソル位置がX,Yに格納されています。
さらに、Clicksにはクリック押下状態が格納されます。
Clicksが1であればクリックした状態、0であればnotクリックです。

また、マウスの左クリック/右クリックどちらを押下したかの情報は、
Buttonに格納されます。
Buttonが1の場合には左クリック、2の場合には右クリックを示しているようです。

さらにこちらのコードが実行された状態で、
キーボードを入力してみると、

Event: {Kind: KeyDown, Rawcode: 65, Keychar: 97}

といったログが出力されます。
Keycharに押下したボタンのASCIIコードが格納されます。
このため、こちらを追えばキーボードで何を入力されたのかを判定することが出来ます。

また、特定の入力を検知するためにはこちらのコードで実行可能です。

package main

import (
  "fmt"
  "github.com/go-vgo/robotgo"
)

func main() {
  add()
}

func add() {
  fmt.Println("--- Please press ctrl + shift + q to stop hook ---")
  robotgo.EventHook(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) {
    fmt.Println("ctrl-shift-q")
    robotgo.EventEnd()
  })

  fmt.Println("--- Please press w---")
  robotgo.EventHook(hook.KeyDown, []string{"w"}, func(e hook.Event) {
    fmt.Println("w")
  })

  s := robotgo.EventStart()
  <-robotgo.EventProcess(s)
}

こちらを実行すると、wのキーを押すとログが出力され、
ctrl + shift + q
で実行から抜けることが出来ます。

■画像認識方法

では次に画像認識です。
PyAutoGuiで言うこところのlocateOnScreenに該当します。
あらかじめ取得した画像と一致した情報が画面上に存在するかチェックしたり、その座標情報を取得するために用います。

こちらは前回と同様、vscode上の新しいファイルを作成のボタンが存在するかをチェックするコードを載せたいと思います。
※下記画像をtest_3.pngという名前で実行ファイルと同階層に置いた場合をサンプルとして載せます。
f:id:Elsammit:20210922224932p:plain

コードはこちら。

package main

import (
	"fmt"
	"github.com/go-vgo/robotgo"
	"image"
	"os"
)

func main() {
	whereBitmap := robotgo.CaptureScreen(0, 0, 500, 500)
	fmt.Println("whereBitmap------ ", whereBitmap)
	file, _ := os.Open("test_3.png")
	img, _, _ := image.Decode(file)

	bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img))
	fx, fy := robotgo.FindBitmap(bit2, whereBitmap, 0.2)
	fmt.Println("FindBitmap------ ", fx, fy)
	
	arr := robotgo.FindEveryBitmap(bit2, whereBitmap, 0.5)
	fmt.Println("Find every bitmap: ", arr)

	fx, fy = robotgo.FindPic("test_3.png", whereBitmap, 0.5)
	fmt.Println("FindPic------ ", fx, fy)
}

画像認識方法に関して、
 ・FindBitmap
 ・FindEveryBitmap
 ・FindPic
3種類載せています。

ToCBitmap関数とFindEveryBitmap関数は引数として画像を一旦ビットマップに変換した後、
画像認識を行うAPIになります。
一方、FindPic関数は引数に画像パスを与えればよいです。

ToCBitmap関数やFindPic関数は画面上で見つかった単一の座標情報を変換しますが、
FindEveryBitmap関数は画面上に存在する複数位置の座標情報を配列で返します。

FindPicのような画像パスを指定して複数座標位置を取得する関数は存在しないように見受けられました。
ですので、複数座標位置を取得したい場合にはFindEveryBitmap関数一択になってしまいそう。
まぁ、自作すればよいのでしょうが。。

こちらの画像認識を行う上で注意点が2点あります。

①画像認識するキャプチャ画像をあらかじめ指定(取得)する必要がある。
ここまで触れてきませんでしたが先ほどの3種類の関数ですがどれも3つの引数を与えております。
これらは、
 ・第1引数:ビットマップ情報などの画像情報
 ・第2引数:画面上で画像認識する画面キャプチャ
 ・第3引数:認識精度
です。

この第2引数として与えるキャプチャ画像を

whereBitmap := robotgo.CaptureScreen(0, 0, 500, 500)

といった関数であらかじめ取得しなければならないのです。
上記コードは縦横どちらも0~500pxの500x500のサイズのキャプチャを取得する関数になります。
こちらを画像認識させる関数に与えないと、画像認識が正しく行えないです。

ですので、必ず前もって認識させる画面のキャプチャは取得してください。

②精度の範囲は0.2 ~ 1
第3引数に与える認識精度ですが、locateOnScreenと同様に1にしてしまうと全く認識しなくなってしまいます。
このため、値を落とす必要があるのですが、0.2を下回ると逆に認識しなくなってしまうようです。
このため、最低でも0.2以上は設定するようにしてあげてください。
※自分はここに躓いてしまいました。。

また結構厳しめに作られているようで、
0.8や0.7でも結構高い一致率でないと反応しないようでした。

■クロスコンパイル方法

最後にUbuntuWindowsへのクロスコンパイル方法についてまとめておきます。

まず必要なライブラリをUbuntuにインストールします。

sudo apt install gcc-multilib
sudo apt install gcc-mingw-w64
sudo apt install libz-mingw-w64-dev

次に下記コマンドを実行すればOKです。
32bit/64bitは当たり前ですが、WIndows側のOSに合わせてください。

・64bit

GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ファイル名

・32bit

GOOS=windows GOARCH=386 CGO_ENABLED=1 CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ go build -x ファイル名

なお、windows側にはmingwが必要になるので注意ください。

■最後に

今回もRobotgoを用いた自動化についてまとめてみました。
pythonを使うか、go言語を使うかは好みになるかな?
自分はPythonで作り始めてしまったのでRobotgoはまたの機会かな。
ただ、クロスコンパイル出来るのは魅力的ですので今後はRobotgoを使うかも。