Regionとは?SikuliXで画面領域を扱うRegionクラスの基本的な使い方

Regionとは?SikuliXで画面領域を扱うRegionクラスの基本的な使い方

こんにちは、業務自動化ツール開発担当の吉池(@valmore_myoshi)です。

SikuliXはパソコン操作を自動化してくれる便利なツールです。画像認識でPC画面上の操作対象を識別し、クリックやテキスト入力が可能です。

これらの画像認識やクリック処理といったSikuliXプログラミングの根幹を担うのがRegionクラスです。ほかにもMatchやScreenといった重要なクラスもありますが、実務で必要な知識はRegionが大半を占めています。

そこで本記事では、プログラミング初心者の方でもわかるようにRegionクラスの使い方をわかりやすく解説します。

Regionとは?

Regionは画面上の長方形領域を扱うクラスで、SikuliXプログラミングで最も基本的な要素です。画面上の左上を起点とするX座標Y座標、そして領域の幅(Width)高さ(Height)でRegionを指定します。

Regionの指定

上記画像のように画面左上から右に100px、左に150px、幅300px、高さ250pxのRegionを指定すると下記コードのようになります。

# Region(x, y, width, height)
reg = Region(100, 150, 300, 250)

作成したRegionオブジェクトをもとに領域内を画像認識したり、クリックやテキスト入力といった操作を行います。そのほか、指定した画像が画面上に現れるまで待機、監視する処理も可能です。

監視処理に興味のある方はこちらの記事をご覧ください。
SikuliXでパソコン画面上の変化を監視する方法

RegionとMatchの違い

Regionと似たクラスにMatchがあります。MatchはRegion.find()の返り値であり、領域内の検索結果として取得できます。

MatchもRegionのプロパティやメソッドを使えますが、Regionにはない類似度という属性を持っています。類似度は指定した画像と画面上で見つけた画像がどれだけ似ているかスコア化したもの。0から1の範囲の値を取り、値が高いほど類似しているといえます。

デフォルトの閾値は0.7でこれ以上の類似度であればMatchを返します。類似度が低いと意図しない要素を引っ張ってきてしまうため、0.85以上の類似度が適正といえます。デフォルトの閾値はSettings.MinSimilarityで変更できます。

Regionの指定

Regionを作成するには、画面上の左上を起点としたX座標とY座標、そして領域の幅(Width)と高さ(Height)を指定します。Screen.selectRegion()を使えば画面上の任意の領域をドラッグして指定できます。

# Region(x, y, width, height)
reg = Region(100, 150, 300, 250)

# 画面上をドラッグしてRegionを作成する場合
reg = selectRegion()

Regionの位置、サイズ変更

すでに作成したRegionの位置やサイズを変更する方法はいくつかあります。座標や幅、高さを一つずつ指定する方法は下記の通り。

reg.setX(number)
reg.setY(number)
reg.setW(number)
reg.setH(number)

座標のみ変更する場合はRegion.moveTo()にLocationを指定します。

reg.moveTo(location)

# Locationオブジェクトの指定方法は下記の通り
# location = Location(x, y)

座標と幅、高さを一度に指定するにはRegion.setROI()かRegion.setRect()を使います。コードの読みやすさのためだけに名前が異なっており、機能は同じです。ROIはRegion of Interestの略で、領域内の画像認識スピードを上げるために、すでに存在するRegionをさらに狭めるときに使うよう意図されています。

reg.setROI(x, y, w, h)
reg.setRect(x, y, w, h)

Region.morphTo()を使えば、すでに存在するRegionを直接指定して、そのRegionの座標やサイズに変更することもできます。

reg.morphTo(anotherRegion)

# 下記と同様の処理
# r = anotherRegion
# reg.setX(r.x)
# reg.setY(r.y)
# reg.setW(r.w)
# reg.setH(r.h)

Regionプロパティへのアクセス

Regionの座標や幅、高さを一つずつ取得する方法は下記の通り。

reg.getX()
reg.getY()
reg.getW()
reg.getH()

Regionの中心や四隅の位置をLocationオブジェクトとして取得することも可能です。

# Regionの中心座標をLocationオブジェクトとして取得
location = reg.getCenter()

# Regionの四隅をLocationオブジェクトとして取得
location = reg.getTopLeft()
location = reg.getTopRight()
location = reg.getBottomLeft()
location = reg.getBottomRight()

Region.find()やRegion.click()といった検索あるいは要素を操作するメソッドは、指定した画像を領域内で検索しています。これらのメソッドのあとにRegion.getLastMatch()を使うと、検索処理で最後に見つけたMatchを返します。複数画像を検索するRegion.findAll()のあとにRegion.getLastMatches()を使えば複数Matchをリスト形式で取得できます。

reg.find(path/to/target/image.png)
item = reg.getLastMatch()

# 複数の場合
reg.findAll(path/to/target/image.png)
items = reg.getLastMatches()

Region.getLastMatch()で二重検索を防ぐ

Region.getLastMatch()は二重検索を防ぐこともできます。例えば、下記のコードは対象の要素が現れるまで待機し、現れた段階でクリックしています。つまり、待機処理時と要素が見つかったあとのクリック時の二度検索しているのです。

wait(someVisual)
click(someVisual)

一方、Region.getLastMatch()を使えば、一度検索して見つかった要素を取得しているので二重検索を防げます。

wait(someVisual)
click(getLastMatch())

実はRegion.click()に何も指定しないと、自動で最後に一致したMatchオブジェクトをクリックするようになっています。コード量が減るので覚えておきましょう。

wait(someVisual)
click()

Region内の検索処理

特定のPatternや画像を探すにはRegion.find()を使います。検索対象が見つかるとMatchオブジェクトを返します。複数の要素を検索する場合はRegion.findAll()を使います。Region.findAll()では、リスト形式のMatchを返します。

target = reg.find(path/to/target/image.png)

# 複数の場合
targets = reg.findAll(path/to/target/image.png)

待機処理

アプリケーションの画面遷移など画面上に特定の画像やPatternが現れるまで待機処理を挟むことはよくあります。待機処理を挟まないと処理が早すぎて操作対象が見つからないことがあるからです。

待機処理でよく使うのはRegion.wait()とRegion.exitsts()の2つです。どちらも画面上にターゲットが現れるまで指定秒数待機する処理です。

しかし、ターゲットが見つからないときの動きが異なります。Region.wait()はFindFailed例外を投げ、Region.exitsts()はNoneを返します。例外を発生させたくないならRegion.exists()を使いましょう

# Region.wait()の使い方
try:
    wait(someVisual, 10)
    click()
except FindFailed:
    # 例外処理

# Region.exists()の使い方
exists(someVisual, 10)
if(getLastMatch() is not None):
    click()

要素の操作

Regionクラスにはクリックやテキスト入力など、要素を操作するメソッドが用意されています。よく使うコマンドを見ていきましょう。

まずはクリック処理。単純なクリックからダブルクリック、右クリックがあります。画面上のPatternや画像を指定します。

click(someVisual)
doubleClick(someVisual)
rightClick(someVisual)

次にテキスト入力にはRegion.type()とRegion.paste()が使えます。Region.type()は指定した文字をキーボードで打ち込む操作を模倣し、Region.paste()はコピーした文字列をペーストします。

テキスト入力だけなら一気にペーストできるRegion.paste()の方が速いです。Region.type()はエンターキーやタブキーといった特殊キーを押すときに使いましょう。

# Region.type()は特殊キーを押すときに使う
type(Key.Enter)

# 複数キーを同時押しする場合
type('c', Key.CTRL)

# 文字のペースト
paste(someText)

最後にRegion.highlight()を紹介します。これはRegionの領域を赤枠(色変更も可)でハイライトしてくれます。デバッグ中にRegionを指定できているか確認するときに役立ちます。

# 3秒間ハイライト表示
reg.highlight(3)
Region.highlight()実行結果
実行結果

まとめ

SikuliXプログラミングで最もよく使うRegionクラスの使い方を解説しました。コードをご覧いただいたようにそれほど難しくはないと思います。

操作対象の領域を指定し、検索、見つかればクリック処理といった流れが基本です。画面遷移があれば待機処理を挟みましょう。これら一連の処理をRegionクラスが扱っています。SikuliXにおいて真っ先にRegionクラスを覚えるべき理由がお判りいただけると思います。

本記事が業務自動化の参考になれば幸いです。