SikuliXの使い方を詳しく解説する日本語のサイトはあまりない。前述した参考書にも、関数の使い方など多くの説明はない。こういうときには英語でも、公式ドキュメントを読むのが一番だ。
公式ドキュメントには、「全てのチャプターに目を通すか、関心あるコンテンツだけ読むか、あるいはRegionクラス、Matchクラス、Screenクラスの説明を読め」(意訳)と書いてある。記者は最後の3クラスの説明をまず読むことにした。
この中でも、Regionクラスの理解が最も重要だ。なぜなら、MatchクラスもScreenクラスもRegionクラスの性質を全て受け継いでおり(継承)、Regionでできることはこの2つのクラスでもできるからだ。
Regionは先ほど紹介したdragDrop()やclick()などを関数に持つ、SikuliXの中心的なクラスだ。
例えば、
hoge_region = Region(0,0,100,200)
と、Region()に左上からのX座標、Y座標、幅、高さ(ピクセル)を与えてインスタンスを作成することで、スクリーン上の調べたい領域を設定できる。
調べたい領域を設定するのは、スクリーン上の全ての領域で画像一致を探索すると、時間がかかったり、予想外の物体を誤認識してしまったりするためだ。
そして、
match_obj = hoge_region.find("foo.png")
のようにfind()関数を用いると、foo.pngの画像に一致する物体をhoge_regionから探索し、発見できた場合はその位置・サイズ情報を持ったMatchインスタンスを返す。なお、探索に失敗した場合はFindFailedエラー例外を出すため、try-exceptで例外処理をするべきだ。
ここで得たMatchインスタンスをdragDrop()関数などに与えることで、物体の操作ができる。
Regionインスタンスの初期化は、全てを手で入力しなくても、SikuliX IDE上部にある「Region」というボタンをクリックしてキャプチャモードから矩形を指定すれば位置・サイズ情報を自動入力してくれる。
気を付けてほしいのは、この方法では絶対座標による指定になるということだ。例えばフルHDの画面ではうまく動いているとしても、HDやWQHDなど別の解像度になってしまうと思った場所に領域設定できないということもありえる。
他の解像度のスクリーンにも対応させることを考えるなら、得た絶対座標とスクリーンの解像度から相対座標を計算しておくか、あるいはRegionの初期化に絶対座標ではなく、スクリーン全体からfindしたMatchインスタンスを与えるなどの工夫が必要だ。
変数や配列の宣言、関数・クラス定義、条件分岐の入れ子などをしていると、コードもそれなりの行数になってくる。
少ない行数の簡潔なコードであればSikuliX IDE上でのコーディングでもあまり違和感はないのだが、長く複雑になってくると話は別だ。
SikuliX IDEには変数を画像で見せる仕組みこそあれ、一般的によく使われているIDEやエディタのような、構造の折りたたみ、コード補完、リファクタリングなどの機能はない。
こうしたモダンな環境で快適なプログラミングをしたいのであれば、一般的によく使われているPython対応IDE・エディタでコーディングしていった方がいいだろう。
記者の場合は、コードを追加して実行・デバッグする作業はSikuliXで、複雑になったコードの編集は「Visual Studio Code」で、というように使い分けた。
2日間でクリアに至らなかった原因の一つには、1回当たりの実行に時間がかかりすぎてしまったということがある。
時間がかかってしまったのは、forループの回数を考慮しきれなかったからだ。
トランプのカードは52枚あるため、目の前にある1枚のカードが何であるか調べようとすると、最大52回の画像一致を試さなくてはいけない。
find()関数のタイムアウト時間はデフォルトで3秒、スキャンレートは3回/秒となっている。このまま1枚のカードを特定しようとforループしてしまうと、最大で52枚×3秒/枚=156秒かかることになってしまう。
タイムアウトとスキャンレートは自分で設定できるため、短く、早く設定して短縮化を試みたが、そもそもカード1枚に最大52回ループをかけるという実装が良くなかった。
今後考えられる改善策としては、数字部分に画像一致ではなくOCRをかけて(SikuliXにはOCR機能も備わっている)数字を認識し、認識した数字のうちどのマーク(スペード、ハート、ダイヤ、クラブ)なのか4回ループして認識する、などが考えられる。あるいは、公式ドキュメントを読み込んだり、フォーラムに質問したりすればもっと良い解法が見つかるかもしれない。
最終的にクリアに至らなかったのは、どちらかといえばこちらが直接的な原因だ。
find()関数は、画像と画像の「類似度」、つまりどれだけ似ているかを求めている。類似度は0〜0.99で表され、0.99が完全一致だ。
デフォルトの設定では、0.7以上の類似度であれば「一致」としてMatchインスタンスを返すのだが、トランプのカードに関していえば、類似度0.7では例えばスペードの8がスペードの6と認識されてしまうなど、誤認識が多発してしまう。
一致とする類似度は変えられるため、類似度を上げていけば基本的にこうした誤認識は避けられる。
しかし、それにしても困ったのが「ハートの5」と「ハートの6」だった。類似度0.97の設定でも、ハートの6をハートの5と誤認識してしまう。
類似度0.98の設定でようやくこの2枚を区別できるようになるのだが、今度は他のカードで「本来同じなのに一致してくれない」、つまり認識できないという事態が発生する。
この「あちらを立てればこちらが立たぬ」というにっちもさっちもいかない状況に陥り、ゲームクリアに至れなかったのだ。
実は、類似度の設定は全て一律に変える以外にも、画像別に設定することもできたため、これでうまく調整すればこの事態は防げたのかもしれない。
しかし、だいぶコーディングを進めてからその仕様に気付いたため、個別の類似度設定を十分に試す時間がなかった。
業務ソフトの定型業務に見立てて解き始めたソリティアだったが、実際にやってみるとカード分類の試行回数と条件分岐の複雑さ、画像認識の設定の難しさが立ちはだかることが分かった。
これらの理由から、ソリティアはRPAが最も得意とする「定型業務」というよりは「非定型業務」に相当するといえる。
そして、こうした作業にRPAを適用するとしても、条件分岐やループ回数の考え方など、プログラミングスキルが要求されることも分かった。
SikuliXだから特にスキルが要求されたのであって、他の有償のRPAソフトであればもう少し状況は違うのかもしれない。
だが、仮にコーディングを必要とせず、GUIによる操作だけで完結するRPAソフトだったとしても、問題を解くに当たって試行にかかる時間や条件分岐、例外処理といったプログラミングの素養は必須になるだろう。
今回、ソリティアのクリアには失敗してしまったが、例えば同じ場所を何度もクリックやドラッグ&ドロップするような定型作業であれば、このSikuliXでも十分自動化できることは分かっていただけたのではないだろうか。
ほとんどのRPAソフトが有料の中、SikuliXは完全に無料だ。公式ドキュメントが日本語非対応だったりハードルはあるにせよ、「自分の環境でRPAソフトを使うとどんなことができるのか」と試してみるのにはいいだろう。無料RPAソフトは他にもあり、有償ソフトを導入する前の参考にするのもよさそうだ。
記者が遭遇したハマりどころも含め、本記事が作業自動化の参考になれば幸いだ。
Copyright © ITmedia, Inc. All Rights Reserved.
Special
PR