ぺんちゃん日記

食と歴史と IT と。 Web の旅人ぺんじろうが好奇心赴くままに彷徨います 。

【AutoHotkey】画像認識ライブラリ FindText を試してみる

目次


f:id:yasushiito:20190403184928p:plain

はじめに。

ahkで画面からボタンなどを探す場合、画像認識 ImageSearchコマンドを使います。
このコマンドはキーボードショートカットなどで操作できないアプリケーションで自動操作したい時に有効です。
ImageSearchコマンドはとても強力で、多くの場面で自動操作に対応できます。
しかし、図柄ではなく文字を探す機能に限定すればパフォーマンスが向上する可能性もあります。
状況に合わせて画像認識コマンドを使い分けられるようにしておくに越したことはありません。
代替となるライブラリを探して見たところ、次のページで FindText というライブラリがあることを知りました。
そこで今回は FindTextを試してみます。


qiita.com

概要

FindText は、画像をスクリーンから探して座標を返す外部ライブラリです。
AHK のライブラリディレクトリに配置しておけば、関数呼び出しで利用できます。

作者はFeiYue。

特徴。

目的の画像をモノクロ化してシルエットで探します。
色の要素を落とせるので、 画像の表示の際の風合いで判定を取りこぼす心配が少なくなります。
BMP などの画像ファイルではなく、数百文字程度の文字列に変換するのでスクリプト内で扱いやすいです。

画像認識と言っても、 OCR のように画像の中から文字を探すものではありません。
キャプチャした画像と同じパターンの図柄をスクリーンから探すだけです。
つまり、フォントと文字サイズが違うと判別できません。
あくまで画像のコントラストをきつくして輪郭を抽出してパターン一致を調べているだけです。
ある程度のコントラストが必要なので、色合いの薄い文字は苦手です。
写真のような輪郭の薄い画像を探すのも苦手です。

入手方法。

AutoHotkey掲示板で公開されているので、そこからダウンロードできます。

FeiYue

FindText - Capture screen image into text and then find it - AutoHotkey Community


現時点で バージョン7.5、最新更新日は2020年4月13日です。
発表されたのが2016年5月のようですから、安定してメンテナンスされているようですね。


使い方。

手順は次のようになります。

  • ダウンロードしたファイルを実行するとアプリケーションが起動します。
  • アプリケーションから、認識したい画像のサンプルを採取します。
  • アプリケーションから生成されたコードをコピペしてファイルに保存します。
  • そのファイルを実行すれば画像認識の結果が表示されます。
  • 必要なら、生成されたコードから テキストエンコードされた画像データだけを切り出せば関数呼び出しの形で利用できます。


まず上で紹介したページからダウンロードまたはコピペでahkファイルとして保存します。
そのファイルを実行すると、アプリケーションが起動します。

f:id:yasushiito:20200516161552p:plain


Captureボタンをクリックすると、アプリケーションは最小化して、マウスポインタが赤い枠の四角形に変わって、キャプチャーモードになります。

f:id:yasushiito:20200516161652p:plain


マウスポインタを画像認識したい場所に移動させ、右クリック2回で枠線内の表示内容を取り込みます。
今回は試しにはてなブログの編集ページが表示される「下書きを更新する」ボタンをキャプチャしてみました。

f:id:yasushiito:20200516161715p:plain


キャプチャされた画像がドット絵で表示されます。

f:id:yasushiito:20200516161912p:plain


余分な部分をトリミングします。
上下左右も余分なラインをU、D、L、Rボタンで削っていきます。
3行まとめて消すこともできます。

f:id:yasushiito:20200516161943p:plain


Gray2Twoボタンでモノクロ化して OK ボタンでキャプチャを完了します。

f:id:yasushiito:20200516162018p:plain


testボタンで認識テストします。

f:id:yasushiito:20200516162055p:plain


テストに成功したら messagebox に検出した座標が表示されます。

f:id:yasushiito:20200516162149p:plain


アプリケーションの下にある textarea に生成されたスクリプトをコピペします。

画像認識させてみる。

生成されてコピペしたスクリプトを保存したファイルを実行します。
キャプチャーした画像をスクリーンから探します。
メッセージボックスが表示され、画像が認識された場合は発見した個数と座標が表示されます。
なお、返される座標は画像の中心です。
ImageSearch は座標の左上を返したので、割とボタンのギリギリをクリックすることも多く、実行するたびにドキドキするんですよね。

関数化する。

生成されたスクリプトの20行目あたりにコメント行が並んでいます。
ここから下は FindText 関数なので、 この部分だけを切り取ってLibディレクトリの下に FindText.ahkとして保存しておけば関数として利用できます。

関数を呼び出すコードは切り取って残った20行程度の部分です。
画像認識の結果をメッセージボックスで表示するコードです。
今回私が試しに作ってみたサンプルではこんな感じになりました。

; #Include <FindText>

 t1:=A_TickCount, X:=Y:=""

Text:="|<>*190$60.zzzzzzzzzzzzzzzzzkzzk0000zUkzzk0000zUkzzk0000z1kzzzzUzzz1kzzzzUzzy0003w0007y0003w0007w0003w0007s0003w7Uy7k7kzzw7Uy7sDkzzw0007wTkzzw0007zzkzzw0007w0003w7Uy7w0003w7Uy7w0003U0000w0003U0000zzkzzU0000zzkzzw7zy7zzkzzw7zy7zzkzzw7zy7zzkzzw7z07k0001U"

 if (ok:=FindText(1417-150000, 764-150000, 1417+150000, 764+150000, 0, 0, Text))
 {
   CoordMode, Mouse
   X:=ok.1.x, Y:=ok.1.y, Comment:=ok.1.id
   ; Click, %X%, %Y%
 }

 MsgBox, 4096, Tip, % "Found :`t" Round(ok.MaxIndex())
   . "`n`nTime  :`t" (A_TickCount-t1) " ms"
   . "`n`nPos   :`t" X ", " Y
   . "`n`nResult:`t" (ok ? "Success !" : "Failed !")

 for i,v in ok
   if (i<=2)
     MouseTip(ok[i].x, ok[i].y)


;===== Copy The Following Functions To Your Own Code Just once =====

ExitApp, 1

myahk/testfindtext.ahk at master · yasushiito/myahk


特に重要なのは変数Textに代入されているテキストデータです。
こいつが認識させたい画像をテキストエンコードしたものです。
これを FindText 関数の第7引数に与えれば画像認識できます。

小技。

右クリックではキャプチャできない。

私は右クリックできないので、右クリック2回でキャプチャできると言われても実行できません。
そこで右クリック判定処理を全部左クリックに書き換えました。
そしたらボタンをキャプチャする瞬間に、ボタンクリックによって画面が状態遷移してしまって困ってしまいました。
なるほどだから右クリックかと腑に落ちましたが、右クリックでもポップアップが開いてキャプチャに支障が出るかもしれません。
どうやら右クリック以外にも Ctrl キーでキャプチャできるようなので、健常者の方はキーボードでキャプチャするのが良いでしょう。
リッチなアプリだとマウスポインタをフォーカスするとエフェクトでアイコンが動いたりフォントが大きくなったりしちゃうかもしれませんね。
私は潔くスクリーンショットを撮影して、画像編集ソフトに貼り付けて100%表示させたものをキャプチャしてます。

画像認識の領域を広くしたい。

画像認識の領域(キャプチャする時の赤枠)が狭くて目的のテキストが入りきらないことがあります。
アプリケーション左上にwidthとheightを入力する場所があります。
これを操作すればキャプチャ領域を変更できるはずなのですが、私の環境では動いていません。
コードを見てみましたが、作り込んであるものの機能してません。
幅と高さの変数に代入している処理を書き換えてみましたが、期待する動作を得られませんでした。

必ず終了させよう。

Find Text 関数を呼び出した後に何の宣言もなくふんわりとスクリプトを終了させると、 ahk のプロセスが解放されずに残ってしまいます。
最後は必ず ExitApp してくださいね。

この記事に登場するAutohotkey スクリプトについて

この記事の中で私が作成したプログラムは、全て自由に使うことができます。
詳しくはこちら