UWSCという開発ソフトを使って作り上げる作業を実際にやってみるカテゴリ。準備した自作関数や使い方、トラブルを記事にしていきます。得るものがあれば幸いです。
今回は、非常にトラブルの原因になりやすい画像認識、画像検索について整理します。
今回は、非常にトラブルの原因になりやすい画像認識、画像検索について整理します。
記事の内容
○画像認識ができない理由を掴む
○画像認識ができない理由を掴む
画像をUWSC自身に取得させる
画像の検索範囲をすぐ見れるよう準備
画像の検索範囲をすぐ見れるよう準備
ポク太郎です。
できるだけ画像認識は使わないのが定石ですが、やむを得ず必要になることがあります。あいまいな画像検索用の関数を作成した方がいて、CHKIMGXとして配布されていますが、筆者はまだ試しておりません。
その前に、標準の画像認識で失敗する理由を確実につかもうと思い、関数を作成しました。
画像認識ができない理由
今、筆者から見えている“画像認識できない”理由は下記です。
※ここではUWSCに画像を比較させるための画像をリファレンス画像と呼んでいます。
※ここではUWSCに画像を比較させるための画像をリファレンス画像と呼んでいます。
1 リファレンス画像と異なるものを検索 | |
1-1 リファレンス画像をBMPで取得していない PNGやJPEGなど非可逆圧縮で保存すると元の画像を劣化させてしまうのでBMP(ビットマップ)で保存する必要があります。 | |
1-2 リファレンス画像を保存する際加工されてしまった Alt+PrintScreenキーで画像編集ソフトに貼り付けて保存する場合に、そのまま保存したつもりが加工されてしまうものがある。筆者が経験しているのはWin10標準アプリの「Paintペイント」。 | |
1-3 グラボによりγカーブが掛けられ色味が異なる 画像を採取したPCと別環境ではグラボが異なるので、別のγカーブが当てられる。同じベンダ(nVidia、Radeonなど)同士であれば初期状態は同じなので、大抵は認識できるが完全には難しい。 | |
1-4 対象のソフトがアップデートされ異なる表示になってしまった 特にブラウザのように頻繁にアップデートされるソフトではよく遭遇すると思います。 | |
2 検索範囲がずれている | |
2-1 検索範囲を勘違いしている 処理速度を上げようと画像検索の範囲を絞ろうとした場合などによく陥ります。 |
そこで、通常の画像認識でどこまで確実にできるかを確認したいと思い、デバッグ機能付きの関数を作成します。
※上記の1-3、1-4は回避できませんが、1-1、1-2、2-1は回避可能になるので追加機能が必要かどうか確かめることができます。曖昧な画像認識が可能なCHKIMGXを使用した場合に1-3、1-4が完全対応できるかどうかは筆者はまだわかっておりません。
スクリーンショット画像をUWSC自身に取得させる
Alt+PrintScreenキーで画像を取得していると上で挙げた操作ミスなどを招いてしまう&面倒なので、画像を取得する機能を関数として作成しました。
この関数を呼び出すと、選択ボタン2つ(“取得”と“5秒後に取得”)で動作を選択させるダイアログを出します。押されたボタンに従い、ソースコードのあるディレクトリに“画像_000X.bmp”というファイル名で画像を保存します。関数を抜ける条件はダイアログの閉じるボタン(Xボタン)が押されたとき。
※関数の形にしておりますが、独立したアプリにしておいてもいいかもしれません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | FUNCTION get_pic(id) cancel=0 WHILE (cancel=0) SELECT SLCTBOX(slct_btn,0,1,400,“画像を取得します。“,“取得“,“5秒後に取得“) CASE –1 cancel=1 CASE 1 wait=0 CASE 2 wait=1 SELEND IF cancel=0 PRINT “準備しています。“ IF id<>–1 IF STATUS(id,ST_ICON)//最小化状態かどうか CTRLWIN(id,NORMAL)//通常表示に ENDIF IF !STATUS(id,ST_ACTIVE)//非アクティブかどうか CTRLWIN(id,ACTIVATE)//アクティブに ENDIF ELSE PRINT “アプリが見つからないので全体画像を取得します。“ ENDIF IF wait=1 FOR i=5 TO 1 step –1 PRINT i+“秒後に取得します。“ SLEEP(1) NEXT ENDIF n=0 WHILE (0=0) path=GET_CUR_DIR+“\画像_“+REPLACE(FORMAT(n,4),“ “,“0“)+“.bmp“ IF FOPEN(path,F_EXISTS) n=n+1 ELSE IF id<>–1 SAVEIMG(path,id) ELSE SAVEIMG(path) ENDIF PRINT “画像を取得しました。“ break ENDIF SLEEP(0.1) WEND ENDIF SLEEP(0.05) WEND RESULT=1 FEND |
1,50行目 | 1 50 | FUNCTION get_pic(id) FEND |
get_pic(id)関数宣言:画像をUWSC自身に取得させる関数。 引数id:アプリIDを渡します。画面全体を取得する場合は-1指定。 | ||
2~3,47~48行目 | 2 3 47 48 | cancel=0 WHILE (cancel=0) SLEEP(0.05) WEND |
変数cancel:下で表示させるダイアログの閉じるボタンが押された場合に1になる変数。 閉じるボタンが押されるまで、4~46行目の間をループします。 | ||
4~11行目 | 4 5 6 7 8 9 10 11 | SELECT SLCTBOX(slct_btn,0,1,400,“画像を取得します。“,“取得“,“5秒後に取得“) CASE –1 cancel=1 CASE 1 wait=0 CASE 2 wait=1 SELEND |
セレクトボックスを表示します。 case -1 ⇒ 閉じるボタンが押された場合の処理 case 1 ⇒ 取得ボタンが押された場合の処理 case 2 ⇒ 5秒後に取得ボタンが押された場合の処理(取得したい状態を準備するための待ち時間として5秒) 変数wait:画像取得までに5秒間の待ち時間を入れるかどうかを記憶します。 | ||
12,46行目 | 12 46 | IF cancel=0 ENDIF |
閉じるボタンが押されていない場合のみ、13~45行目を実行。 | ||
14~23行目 | 14 15 16 17 18 19 20 21 22 23 | IF id<>–1 IF STATUS(id,ST_ICON)//最小化状態かどうか CTRLWIN(id,NORMAL)//通常表示に ENDIF IF !STATUS(id,ST_ACTIVE)//非アクティブかどうか CTRLWIN(id,ACTIVATE)//アクティブに ENDIF ELSE PRINT “アプリが見つからないので全体画像を取得します。“ ENDIF |
引数idが-1ではないとき(対象が画面全体ではないとき)、 ウィンドウが最小化状態なら ⇒ 通常表示にする ウィンドウが非アクティブ状態なら ⇒ アクティブにする | ||
24~29行目 | 24 25 26 27 28 29 | IF wait=1 FOR i=5 TO 1 step –1 PRINT i+“秒後に取得します。“ SLEEP(1) NEXT ENDIF |
上記のセレクトボックスで“5秒後に取得”ボタンが押された場合(変数waitが1)に実行。1秒ごとのカウントダウンを表示していきます。 | ||
30~45行目 | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | n=0 WHILE (0=0) path=GET_CUR_DIR+“\画像_“+REPLACE(FORMAT(n,4),“ “,“0“)+“.bmp“ IF FOPEN(path,F_EXISTS) n=n+1 ELSE IF id<>–1 SAVEIMG(path,id) ELSE SAVEIMG(path) ENDIF PRINT “画像を取得しました。“ break ENDIF SLEEP(0.1) WEND |
ファイル名を“画像_000x.bmp”として保存していきますが、空きファイル名を調べるためのルーチン。被らないファイル名ができるまでループを回り続けます。保存完了するとループを抜け関数を抜けます。 32行目 :変数pathにファイル名を作り出します。 33行目 :作成したファイル名のものが存在しているかどうかを調べ、 (存在する) 変数nをインクリメントして再度ループ先頭へ (存在しない) 画像を保存(引数idにより分岐)、ループ抜ける します。 |
画像の検索範囲をカーソルで描く
以前こちらで([UWSC]表示された指定画像の中心座標を返す関数)で作成した関数にデバッグの引数を追加し、検索範囲の外周に沿ってマウスカーソル移動させ、その動きを見てすぐにわかるように機能追加します。
トラブルがあった際に、呼び出し側のソースをデバッグ用に変更して(デバッグ用引数として1を渡す)すぐに検索範囲を確認できるようにしておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | FUNCTION imgxyd(m,pic,db) DIM xy[1] wh=bmp(pic) IF db=1 FUKIDASI(SX1+“,“+SY1,SX1,SY1,0,,,$000000,$00CCEE) FOR i=SX1 TO SX2 step (SX2–SX1)/100 MMV(i,SY1) SLEEP(0.001) NEXT FUKIDASI(SX2+“,“+SY1,SX2,SY1,0,,,$000000,$00CCEE) FOR j=SY1 TO SY2 step (SY2–SY1)/100 MMV(SX2,j) SLEEP(0.001) NEXT FUKIDASI(SX2+“,“+SY2,SX2,SY2,0,,,$000000,$00CCEE) FOR i=SX2 TO SX1 step (SX1–SX2)/100 MMV(i,SY2) SLEEP(0.001) NEXT FUKIDASI(SX1+“,“+SY2,SX1,SY2,0,,,$000000,$00CCEE) FOR j=SY2 TO SY1 step (SY1–SY2)/100 MMV(SX1,j) SLEEP(0.001) NEXT ENDIF SELECT m CASE 1 haba=“IMG_MSK_BGR1“ CASE 2 haba=“IMG_MSK_BGR2“ CASE 3 haba=“IMG_MSK_BGR3“ CASE 4 haba=“IMG_MSK_BGR4“ DEFAULT haba=“IMG_MSK_BGR4“ SELEND IF CHKIMG(pic,,SX1,SY1,SX2,SY2,,haba) xy[0]=G_IMG_X+wh[0]/2 xy[1]=G_IMG_Y+wh[1]/2 FUKIDASI(xy[0]+“,“+xy[1],xy[0],xy[1],0,,,$FFFFFF,$008800) ELSE xy[0]=0 xy[1]=0 FUKIDASI(“画像が見つかりません。“,0,0,0,,,$FFFFFF,$008800) ENDIF RESULT=SLICE(xy,0,LENGTH(xy)–1) FEND |
1,48行目 | 1 48 | FUNCTION imgxyd(m,pic,db) FEND |
imgxyd(m,pic,db)関数宣言:表示された指定画像の中心座標を返す関数。(デバッグ機能付) 引数m:色幅を1~4で指定します。 引数pic:リファレンス画像のパスを渡します。 引数db:デバッグのオンオフ指定。デバッグ時には1を渡す。 【ご注意】この関数を使用する際には、グローバル変数として以下を宣言、代入しておく必要があります。 | ||
2,3行目 | 2 3 | DIM xy[1] wh=bmp(pic) |
配列変数の定義とBMP画像の幅と高さを取得。 bmp()関数はこちら([UWSC]BMP画像の幅と高さを得る関数)で作成した自作関数。 配列変数xy[1]:画像を見つけた座標。xy[0]がX座標、xy[1]がY座標。 | ||
4~25行目 | 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | IF db=1 FUKIDASI(SX1+“,“+SY1,SX1,SY1,0,,,$000000,$00CCEE) FOR i=SX1 TO SX2 step (SX2–SX1)/100 MMV(i,SY1) SLEEP(0.001) NEXT FUKIDASI(SX2+“,“+SY1,SX2,SY1,0,,,$000000,$00CCEE) FOR j=SY1 TO SY2 step (SY2–SY1)/100 MMV(SX2,j) SLEEP(0.001) NEXT FUKIDASI(SX2+“,“+SY2,SX2,SY2,0,,,$000000,$00CCEE) FOR i=SX2 TO SX1 step (SX1–SX2)/100 MMV(i,SY2) SLEEP(0.001) NEXT FUKIDASI(SX1+“,“+SY2,SX1,SY2,0,,,$000000,$00CCEE) FOR j=SY2 TO SY1 step (SY1–SY2)/100 MMV(SX1,j) SLEEP(0.001) NEXT ENDIF |
引数db=1のときは、マウスカーソルを検索範囲の外周に沿って動かします。四隅で座標を吹き出し表示。 4~9行目 : 上の辺を移動 | ||
26~37行目 | 26 27 28 29 30 31 32 33 34 35 36 37 | SELECT m CASE 1 haba=“IMG_MSK_BGR1“ CASE 2 haba=“IMG_MSK_BGR2“ CASE 3 haba=“IMG_MSK_BGR3“ CASE 4 haba=“IMG_MSK_BGR4“ DEFAULT haba=“IMG_MSK_BGR4“ SELEND |
引数mに従い、CHKIMG()関数へ渡す“色幅”を指定します。 | ||
38~46行目 | 38 39 40 41 42 43 44 45 46 | IF CHKIMG(pic,,SX1,SY1,SX2,SY2,,haba) xy[0]=G_IMG_X+wh[0]/2 xy[1]=G_IMG_Y+wh[1]/2 FUKIDASI(xy[0]+“,“+xy[1],xy[0],xy[1],0,,,$FFFFFF,$008800) ELSE xy[0]=0 xy[1]=0 FUKIDASI(“画像が見つかりません。“,0,0,0,,,$FFFFFF,$008800) ENDIF |
画像を検索します。 (見つかった場合) 配列変数xy[1]にそれぞれの座標を代入し、見つかった位置に座標を吹き出し表示。 (見つからなかった場合) 座標を(0、0)とし、見つからない由を吹き出し表示します。 | ||
47行目 | 47 | RESULT=SLICE(xy,0,LENGTH(xy)–1) |
関数の戻り値としてX座標とY座標の入った配列変数xy[1]を返します。 |
トラブルがあった場合にはこの関数の引数dbを1にしてやることですぐ調べられます。
![]() | Excel VBAでIEを思いのままに操作できるプログラミング術 Excel 2013/2010/2007/2003対応 |
![]() |
記事の内容は伝わりましたでしょうか。
○画像認識ができない理由を掴む
○画像認識ができない理由を掴む
画像をUWSC自身に取得させる
画像の検索範囲をすぐ見れるよう準備
画像の検索範囲をすぐ見れるよう準備
コメント