2015年7月23日木曜日

ゲームの自動操作装置(7):画像解析部のコード

ゲームの自動操作装置(6):画像解析部 からの続き


以下は画像解析部のコードの抜粋
いずれも簡単な方法で実装しており動作は低速である

・PC画面のスクリーンキャプチャ処理部分

 キャプチャの取得はSystem.Drawing.Graphicsクラスを使用している
 画面の左上にゲーム画面キャプチャソフトのウィンドウ(720x480ドット)がある前提
 サブディスプレイで動かすためにプライマリ/セカンダリスクリーンの切り替えが仕込んである
 PC画面の左上(0,0)から720x480ドット分のビットマップ(=ゲーム画面)を切り出す

  
        public static Bitmap GetDesktop()
        {
            Rectangle rect;
            if (outputDisplayNum == 0)
            {
                rect = Screen.PrimaryScreen.Bounds;
            }
            else
            {
                rect = Screen.AllScreens[1].Bounds;
            }
            //※※高速化のために全画面取得は廃止
            rect.Width = 720;
            rect.Height = 480;

            Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.CopyFromScreen(rect.X, rect.Y, 0, 0, rect.Size, CopyPixelOperation.SourceCopy);
            }
            return bmp;
        }

・画像の解析処理部分

 ゲーム画面の任意座標にオブジェクトがあるかどうかの判定を行う
 オブジェクトチェック用にキャプチャ画面から矩形に画像を切り出しておく

 前述のゲーム画面とオブジェクトチェック用の画像のマッチングを行う
 マッチングの指標は各ピクセルの輝度の差の二乗和をピクセル数で割ったもの
  (3プレーンともチェックする場合は、更にプレーン分を足した後3で割る)

  実行時間はチェック用画像のサイズに依存する
  highSpeedフラグがある場合はRプレーン以外は無視する
 (処理は速くなるが当然精度は相応に落ちる)


ゲームの自動操作装置(8):メインプログラム へ続く

        private Bitmap gameBitmap;
        private int imgMuchValue;

        public bool checkMenuBase(Bitmap checkBitmap, int x, int y, bool highSpeed)
        {
            bool ret = false;
            int testVal;

            gameBitmap = Win32APICall.GetDesktop();

            testVal = cmpBitmapSSD(gameBitmap, checkBitmap, x, y, highSpeed);
            if (testVal < imgMuchValue)
            {
                ret = true;
            }
            else
            {
                ret = false;
            }
            return ret;
        }

        private int cmpBitmapSSD(Bitmap lb1, Bitmap lb2, int x, int y, bool highSpeed)
        {
            int xBuf, yBuf;
            int muchCountR = 0;
            int muchCountG = 0;
            int muchCountB = 0;

            int buf;
            int retbuf;

            if (highSpeed)
            {
                for (yBuf = y; yBuf < (y + lb2.Height); yBuf++)
                {
                    for (xBuf = x; xBuf < (x + lb2.Width); xBuf++)
                    {
                        buf = lb1.GetPixel(xBuf, yBuf).R - lb2.GetPixel(xBuf - x, yBuf - y).R;
                        muchCountR += buf * buf;
                    }
                }
                retbuf = muchCountR / lb2.Height / lb2.Width;
            }
            else
            {
                for (yBuf = y; yBuf < (y + lb2.Height); yBuf++)
                {
                    for (xBuf = x; xBuf < (x + lb2.Width); xBuf++)
                    {
                        buf = lb1.GetPixel(xBuf, yBuf).R - lb2.GetPixel(xBuf - x, yBuf - y).R;
                        muchCountR += buf * buf;

                        buf = lb1.GetPixel(xBuf, yBuf).G - lb2.GetPixel(xBuf - x, yBuf - y).G;
                        muchCountG += buf * buf;

                        buf = lb1.GetPixel(xBuf, yBuf).B - lb2.GetPixel(xBuf - x, yBuf - y).B;
                        muchCountB += buf * buf;
                    }
                }
                muchCountR = muchCountR / lb2.Height / lb2.Width;
                muchCountG = muchCountG / lb2.Height / lb2.Width;
                muchCountB = muchCountB / lb2.Height / lb2.Width;

                retbuf = (muchCountR + muchCountG + muchCountB) / 3;
            }
            lastCheckResult = retbuf;
            return retbuf;
        }

0 件のコメント:

コメントを投稿