ゲーム自動化などのキーワードでよく使われるのが画像認識らしく、AutoItでもImageSearch UDF+ImageSearch.dllがあります。画面をキャプチャ(スクリーンショット)して、指定した画像があるかマッチングを行うもののようです。
なので、Win+Shift+S的な画面キャプチャした画像から対象画像があるかのマッチングですね。
1. ImageSearch UDFを取得する
下記 urlでCenrrally氏が提供しています。トピック1番目の最後にダウンロードリンクがあるので、ダウンロードしrarを解凍します。
32bit用、64bit用でdllが違うのでそれぞれ環境に合わせてダウンロードします。
2. 関数は2つ。全体から検索か、エリア内検索か
画面全体から_ImageSearch()か、画面の一部から_ImageSearchArea()です。
_ImageSearch()は内部で_ImageSearchArea()呼んでいるだけですね。なので自分の使い方に合わせて関数を更に簡略化してもいいかと。
引数は以下のようになっています。
- $findImage マッチングしたい画像 ファイル名か、画像データのポインタ
ファイル名: target.bmp
画像データのポインタ - $resultPosition 返ってくるxy座標が画像の中心=1か、左上=0か
- $x, $y 返ってくる座標
- $tolerance 0~255
0は色完全マッチ、255にすると左上にあるごみ箱を探すなど変。
JPEGは非可逆圧縮なので、0だと当然マッチしなく100でマッチする(かなり遅い)
可逆圧縮のBMPかPNGを使うほうが良い - $HBMP $findImageと、どう組み合わせるのかわからない
- $x1,$y1,$right, $bottom 画面のどこを対象にするか
2.1 まずは動作確認
OSが64bitならSciTEのビルドオプション(Ctrl+F7)で64bitにチェックしてから。
今回はgoogle analyticsのアイコンを探してみます。キャプチャをPNGで保存しました。

見つけたらマウスをアイコンに移動するスクリプトです。
#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include "ImageSearch.au3" Local $x1 Local $y1 Local $ret = _ImageSearch(@ScriptDir & "\target.png", 1, $x1,$y1,0) If $ret Then MsgBox(0,"found", "found") MouseMove($x1,$y1) EndIf ConsoleWrite("x="& $x1 & ", y=" & $y1)
Google Analyticsをブラウザで立ち上げてアイコンが見えるようにして、このスクリプトを実行すると、見つかればマウスが移動します。
3. 特定のアプリ内画像検索はまずアプリの矩形を取得
Citrixのような一見ウィンドウだけど実は画像となるとUIAutomationなどではコントロール取得できないので、ImageSearchAreaの出番になりますね。
その為にもまずはウィンドウを取得して、その矩形をImageSearchArea()に渡すことが必要になります。
Citrix持っていないので、ChromeウィンドウをUIAutomationで取得し、それを渡すことでそのウィンドウ矩形を取得します。UIAutomationでコントロールなど取得するには下記記事を参考に。
ウィンドウ矩形を取得し、ImageSearchAreaに渡せば速度も速くなり、他アプリのコントロールを取得するような誤動作減る期待が持てますね。
#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Array.au3> #include "UIA_Constants.au3" #include "ImageSearch.au3" Opt( "MustDeclareVars", 1) Global $b_box = _get_chrome_rect() If Not IsArray($b_box) Then Exit EndIf Func _get_chrome_rect() ; UIAutomation オブジェクト生成 Local $oUIAutomation = ObjCreateInterface( $sCLSID_CUIAutomation8, $sIID_IUIAutomation6, $dtag_IUIAutomation6 ) If Not IsObj( $oUIAutomation ) Then Return ConsoleWrite( "$oUIAutomation ERR" & @CRLF ) ConsoleWrite( "$oUIAutomation OK" & @CRLF ) ; デスクトップ 取得 Local $pDesktop, $oDesktop $oUIAutomation.GetRootElement( $pDesktop ) $oDesktop = ObjCreateInterface( $pDesktop, $sIID_IUIAutomationElement9, $dtag_IUIAutomationElement9 ) If Not IsObj( $oDesktop ) Then Return ConsoleWrite( "$oDesktop ERR" & @CRLF ) ConsoleWrite( "$oDesktop OK" & @CRLF ) Local $pCondition $oUIAutomation.CreatePropertyCondition( $UIA_NamePropertyId, "アナリティクス - Google Chrome", $pCondition ) If Not $pCondition Then Return ConsoleWrite( "$pCondition ERR" & @CRLF ) ConsoleWrite( "$pCondition OK" & @CRLF ) Local $pChrome, $oChrome $oDesktop.FindFirst($TreeScope_Children, $pCondition, $pChrome) $oChrome = ObjCreateInterface( $pChrome, $sIID_IUIAutomationElement9, $dtag_IUIAutomationElement9) If Not IsObj( $oChrome ) Then Return ConsoleWrite( "$oChrome ERR" & @CRLF ) ConsoleWrite( "$oChrome OK" & @CRLF ) Local $bbox ;l,t,w,h $oChrome.GetCurrentPropertyValue( $UIA_BoundingRectanglePropertyId, $bbox) ; _ArrayDisplay($bbox) ConsoleWrite("bbox l=" & $bbox[0] & " t=" & $bbox[1] & " w=" & $bbox[2] & " h=" & $bbox[3] & @CRLF) Return $bbox EndFunc Global $x1 Global $y1 ;Local $ret = _ImageSearch(@ScriptDir & "\target.png", 1, $x1,$y1,0) Global $ret = _ImageSearchArea(@ScriptDir & "\target.png", 1, $b_box[0],$b_box[1],$b_box[2],$b_box[3],$x1,$y1,0) If $ret Then MsgBox(0,"found", "found") MouseMove($x1,$y1) EndIf ConsoleWrite("x=" & $x1 & ", y=" & $y1)
4. マスク画像も認識出来るか
先ほどのGoogle Analyticsのアイコンの白背景をマスキングしたPNGを用意し、これを画面内から検索します。
画面も背景を青に変更したものを用意しました。


ChromeにもAnalytics表示(背景白)していたのですが、うまく認識されません。
マスキングにコツがあるのでしょうか。ImageSearch.dllではちょっと厳しいようです。
5. OpenCVを使ったほうが良い
AutoItでOpenCVの画像認識を用いた画面内マッチングの記事を書きました。
コメント
ImageSearchライブラリ使用時に、au3checkを走らせると
error:missing separator character before keyword
というメッセージが表示されます。
この問題が起きた場合、
……$findImage,$waitSecs,$resultPosition,ByRef $x,……
の行の”ByRef”の前に半角スペースを置くとエラーが消えます。
全部で4か所あります。
使用ライブラリ:ImageSearch 64 bit
開発環境:Windows 10 HOME 64bit 2105, VS Code, Autoit v3.3.14.5
参考にしたサイト:https://www.autoitscript.com/forum/topic/188369-error-missing-separator-character-before-keyword/
どうやら上記だけでは正しく動かないようで、実行時にまだエラーが発生します。
これはImageSearch内で結果を受け取る変数が配列ではないのに、0個目の要素にアクセスしようとしてエラーが吐かれているようです。
; If error exit
if $result[0]=”0″ then return 0
この部分を
; Error checking goes here
If (IsArray($result) = False) Then Return 0
; If error exit
if $result[0]=”0″ then return 0
と書き換えるとうまく動きます。
使用ライブラリ:ImageSearch 64 bit
開発環境:Windows 10 HOME 64bit 2105, VS Code, Autoit v3.3.14.5
参考にしたサイト:https://www.autoitscript.com/forum/topic/186000-image-search-subscript-used-on-on-accessible-variable/?do=findComment&comment=1335873
はじめまして。Autoitを勉強中です。
UWSCからの乗り換えで試行錯誤していますが、同一画像の数をカウントするというのがUWSCの場合だと同一の画像をカウントさせる方法があったのですが(引数の最後を変える方法)、Autoitの場合は、何か方法があるのかそれとも仕組みを自分で作るのでしょうか?
宜しくお願い致します。
フォーラムでも似たような質問がありますが、自作するしかないようですね。
ImageSearchAreaを使って
$x,$yが検索対象の画面範囲で、検索結果座標でもあり、検索結果を左上座標にしておく感じで。
$count=0 初期化
$x=0
$y=0
$result = 1
While $result=1
$result = ImageSearchArea()
If $result = 1 Then
$count+=1
$x+=1
$h=画像の高さ
EndIf
WEnd
これだと甘いので、見つかったらその$x+=1から右残り、高さは画像の高さ。
この次は$x=0, $y+=1にして残り画面全部に対してImageSearchAreaする
といったところでしょうか。
さらっとしか見ていませんが、下記はどうでしょう?
https://www.autoitscript.com/forum/topic/194433-imagesearch-multiple-occurrence/
ご返信有難うございます。
UWSCとはまた勝手も違いますけど、奥が深いですね。
参考にしながら試してみたいと思います。