OCR機能を使うときは、読み取り領域の座標や幅・高さを指定します。Automation Anywhereでは読み取り位置を指定する際に、アプリケーションのウィンドウ左上からの相対座標を指定します。スクリーン上の絶対座標ではないので、スクリーン上のどこにウィンドウを表示していても、ウィンドウ内の指定した座標から読み取ることができます。ウィンドウ内で読み取る位置が常に一定の場合はとても便利です。
ところが、紙の伝票を複写機で読み取って画像にしたものを読み取るような場合には、複写機で読み取るときに微妙なズレが発生して、ウィンドウ内の相対位置が変化する場合があります。この場合にはうまく読み取れません。
多少のズレがあっても読み取れるようにするためには、読み取り位置を可変にする必要があります。このようなケースに対応するため、ウィンドウの表示位置やウィンドウ内の項目の位置を取得する方法、ウィンドウの表示位置を設定する方法、について紹介します。
※ディスプレイの表示スケール設定を倍率=100%に設定した状態で動作確認しています。表示倍率を変更した場合については未確認ですので、ご了承願います。
座標を固定値で設定する例
PDFファイルを「Acrobat Reader DC」で開いて、「伝票番号」の値を取得したい場合の例です。
「OCR」パッケージの「領域をキャプチャ」アクションで、このように設定したとします。
複写機で読み取るときに上にズレた場合はこのようになり、読み取ることができなくなります。
基準点からの相対座標を使って、座標を可変に設定する例
『伝票番号の項目タイトルと表示枠の位置関係は変わらない。』ということを利用して、項目タイトルの位置を基準にして読み取り位置の座標を求める方法にすれば、ズレが発生した場合でも対応できます。
「OCR」パッケージの「領域をキャプチャ」アクションでは、X,Y座標に変数を設定するようにすれば良い訳です。(下記の例では幅や高さも変数を設定していますが幅や高さは固定値です。アクションの設定値に固定値を埋め込むのではなくて、変数の初期値に設定しておく例です。)
■読み取り位置の求め方
「領域をキャプチャ」アクションでX,Y座標に設定している変数$N_X$と$N_Y$の値は、以下の手順で求めます。
(1)画像「伝票番号」の中心から読み取り位置までのオフセット値(X_offset = 57, Y_offset = -13)は固定値とします。
(2)Acrobat Readerウィンドウの左上角のスクリーン上での座標(X_Win, Y_Win)を求めます。
(3)項目タイトル「伝票番号」を画像で検索して、画像中心のスクリーン上での座標(X_Kijun, Y_Kijun)を求めます。
(4)画像中心の座標(X_Kijun, Y_Kijun)をAcrobat Readerウィンドウ内の座標に変換します。
X_KijunW = X_Kijun – X_Win
Y_KijunW = Y_Kijun – Y_Win
(5)読み取り位置のAcrobat Readerウインドウ内の座標(N_X, N_Y)を求めます。
N_X = X_KijunW + X_offset
N_Y = Y_KijunW + Y_offset
【補足】
Acrobat Readerウィンドウの表示位置をスクリーン左上(X座標=0, Y座標=0)に固定している場合は、上記(2)でX_win=0, Y_Win=0となるので、(4)の式は X_KijunW = X_Kijun, Y_KijunW = Y_Kijun となります。
座標の取得や設定方法
上記で説明した処理を実現する際に必要となるスクリーン座標の取得や設定方法を紹介します。
1.マウスカーソルの座標取得
マウスカーソルの座標を取得する方法としては、VBScriptでGetMessagePos(WindowsのAPI)を呼び出す方法があるようですが、PowerShellでSystem.Windows.Formsのcursorオブジェクト(.NET Framework クラス ライブラリ)のプロパティを使うのが直感的で分かりやすいと思いますので、その方法を紹介します。
(1)PowerShellスクリプト
座標を取得してクリップボードに 「X座標, Y座標」の形式で出力するスクリプトです。
$OutputEncoding = [Text.Encoding]::Default function GetCursorPosition(){ Add-Type -AssemblyName System.Windows.Forms $x = [System.Windows.Forms.Cursor]::Position.X #マウスのX座標 $y = [System.Windows.Forms.Cursor]::Position.Y #マウスのY座標 $result = [string]$x + ","+ [string]$y $result | Clip } GetCursorPosition
(2)Pythonスクリプト
上記PowerShellスクリプトを実行するためのPythonスクリプトです。「Python script」パッケージの「Open」アクションでこのスクリプトを設定します。引数のScriptFilePathは、上記PowerShellスクリプトファイルへのパスです。
# -*- coding: utf-8 -*- def GetCursorPosition(ScriptFilePath): import subprocess cmd = "powershell.exe -ExecutionPolicy RemoteSigned -WindowStyle Hidden -nologo -File \"" + ScriptFilePath + "\"" result = subprocess.call(cmd, shell=True)
【補足】
画像の検索には「Image Recognition」パッケージの「ウィンドウで画像を検索」アクションを使ってクリック動作をすれば、指定した画像の中心にマウスカーソルが移動しますので、その後の処理で座標を取得します。
2.ウィンドウの表示位置設定
Acrobat Readerウィンドウの表示位置をスクリーン左上(X座標=0, Y座標=0)に固定する例です。
(1)PowerShellスクリプト
API「MoveWindow」を呼び出すC#のコードをPowerShellスクリプトにインラインで追加して使っています。
#----------------------------------------------------- #<定義情報> #ProcessName(「Acrobat Reader DC」のProcessName) $name = "AcroRd32" #X座標 $x = 0 #Y座標 $y = 0 #幅(ここは用途により調整が必要) $widht = 1100 #高さ(ここは用途により調整が必要) $height = 950 #----------------------------------------------------- #API「MoveWindow」を呼び出すC#のコードをインラインで追加する。 Add-Type @" using System; using System.Runtime.InteropServices; public class Win32Api { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); } "@ #定義情報の位置へ移動する。 Get-Process -Name $name | ? { $_.MainWindowTitle -ne "" } | % { [Win32Api]::MoveWindow($_.MainWindowHandle, $x, $y, $widht, $height, $true) } | Out-Null
(2)Pythonスクリプト
上記PowerShellスクリプトを実行するためのPythonスクリプトです。「Python script」パッケージの「Open」アクションでこのスクリプトを設定します。引数のScriptFilePathは、上記PowerShellスクリプトファイルへのパスです。
def setWindowPosition(ScriptFilePath): import subprocess cmd = "powershell.exe -ExecutionPolicy RemoteSigned -WindowStyle Hidden -nologo -File \"" + ScriptFilePath + "\"" result = subprocess.call(cmd, shell=True)
3.ウィンドウの座標取得
WindowsのAPIを呼び出すコードをC#で記述する方法もありますが、PowerShellでライブラリ「UIAutomation PowerShell Extensions」を利用すると数行で書けるので、この方法を紹介します。
(1)PowerShellスクリプト
座標を取得したいウィンドウのタイトルをクリップボードに入力してからこのスクリプトを実行すると、ウィンドウの情報を取得して「X座標, Y座標, 幅, 高さ」の形式でクリップボードに出力するスクリプトです。
Import-Module C:\UIAPE\UIAutomation.9.8.7B3.NET35\UIAutomation.dll $OutputEncoding = [Text.Encoding]::Default [UIAutomation.Preferences]::Highlight=$false #関数の定義する。 function GetWindowInformation(){ $WindowTitle = Get-Clipboard -Format Text $w =Get-UiaWindow -Name $WindowTitle $r = $w.Current.BoundingRectangle $ans = [string]$r.X+","+[string]$r.Y+","+[string]$r.Width+","+[string]$r.Height $ans | Clip } #関数をCallする。 GetWindowInformation
(2)Pythonスクリプト
上記PowerShellスクリプトを実行するためのPythonスクリプトです。「Python script」パッケージの「Open」アクションでこのスクリプトを設定します。引数のScriptFilePathは、上記PowerShellスクリプトファイルへのパスです。
# -*- coding: utf-8 -*- def GetWindowInformation(ScriptFilePath): import subprocess cmd = "powershell.exe -ExecutionPolicy RemoteSigned -WindowStyle Hidden -nologo -File \"" + ScriptFilePath + "\"" result = subprocess.call(cmd, shell=True)
【余談】
Acrobat Readerウィンドウをスクリーン座標(0, 0)の位置に移動してみて分かったことですが、左上角に移動したはずなのに、ウィンドウの左側にデスクトップの表示が見えます。アプリケーションのウィンドウは見た目より横方向に少し大きいようです。(@_@)
Pythonスクリプトの動作が思った通りの結果にならないときは、「C:\ProgramData\AutomationAnywhere\BotRunner\Logs」に出力されるログ「python2wrapper.log」や「python3wrapper.log」が頼りになります。スクリプト名には全角を使わないように気を付けましょう。(^^;)
【関連】
Control RoomにアップロードするPythonやVBScriptのファイル名称やパスに全角文字を含んではいけない