17
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

シャドバの勝ち負けを画像認識で判定する

Last updated at Posted at 2020-01-19

この記事は リンク情報システム の「2020新春アドベントカレンダー TechConnect!」のリレー記事です。
TechConnect! は勝手に始めるアドベントカレンダーとして、engineer.hanzomon という勝手に作ったグループによってリレーされます。
(リンク情報システムのFacebookはこちらから)


テーマが自由だったので自由な記事となります。(使用技術は真面目です。)
チュートリアルを駆使し、頑張って画像認識をしました。

出来たもの

Shadowverse(Steam版)のWin/Lose判定を行うプログラムが出来ました。
ダウンロード.gif
(gifの画面はLose判定を確認するために描画しています。判定は描画しなくても可能です。)

見ての通り、Win/Lose画像とキャプチャ画面を比較して判定しているだけなので、
「特定のアプリケーションのキャプチャに、指定画像が出現しているかをリアルタイムで判定する」
ことがしたい人の参考にもなるかと思います。

使ったもの

  • Python 3.7.4
  • pip 19.3.1
  • numpy 1.17.3
  • opencv-contrib-python 4.1.1.26
  • Pillow 6.2.0

導入方法は後述する参考記事を参照してください。
片っ端からpipでインストールするだけで出来たので特に詰まった所は無かったです。

やり方

  1. ゲーム画面をスクリーンキャプチャする
  2. キャプチャした画像と、Win/Lose画像を比較
  3. 特徴点をDistanceで足切りし、一定以上の特徴点がマッチしていればWin/Loseと判断
  4. 一定回数以上Win/Lose判定が連続した場合に、Win画面/Lose画面と判定

ゲーム画面をスクリーンキャプチャする

以下の記事を参考にPILを使用してキャプチャを行いました。
[Python][Windows] Pythonでスクリーンキャプチャを行う

from PIL import ImageGrab
import numpy as np

TARGET_NAME = 'Shadowverse'
handle = win32gui.FindWindow(None, TARGET_NAME)

while True:
    rect = win32gui.GetWindowRect(handle)
    img = ImageGrab.grab(rect)
    ocv_im = np.asarray(img)

    #OpenCV用に色変換
    ocv_im = cv2.cvtColor(ocv_im, cv2.COLOR_BGR2RGB)

    #画面に描画(確認用)
    cv2.imshow("images", ocv_im, )

    #適当な方法でWaitをかける(描画時間の確保)
    cv2.waitKey(10)

##キャプチャした画像と、Win/Lose画像を比較

(あらかじめWin/Lose画像はスクリーンショットから切り抜いておきます。)

以下の記事を参考に、AKAZEで特徴量マッチングを行います。
OpenCV 3とPython 3で特徴量マッチング(A-KAZE, KNN)

def MatchResultCheck(ocv_img):
    win_img = cv2.imread(WIN_IMAGE_PATH)
    lose_img = cv2.imread(LOSE_IMAGE_PATH)

    akaze = cv2.AKAZE_create()

    kp2, des2 = akaze.detectAndCompute(ocv_img, None)
    kp1_l, des1_l = akaze.detectAndCompute(lose_img, None)
    kp1_w, des1_w = akaze.detectAndCompute(win_img, None)

    is_win = False
    is_lose = False

    bf = cv2.BFMatcher()
    if not des2 is None :
        #Lose画像とキャプチャ画像で特徴量マッチング
        matches_l = bf.knnMatch(des1_l,des2, k=2)
        #Win画像とキャプチャ画像で特徴量マッチング
        matches_w = bf.knnMatch(des1_w,des2, k=2)

        #Lose判定
        good_l = []
        for match1, match2 in matches_l:
            if match1.distance < 0.75*match2.distance:
                good_l.append([match1])
        #Win判定
        good_w = []
        for match1, match2 in matches_w:
            if match1.distance < 0.75*match2.distance:
                good_w.append([match1])

        #確認用の画像を作成
        akaze_matches = cv2.drawMatchesKnn(lose_img,kp1_l,ocv_img,kp2,good_l,None,flags=2) 
        #画面に描画(確認用)
        cv2.imshow("match", akaze_matches, )

        if len(good_l) > 20 :
            print("is lose")
            is_lose = True

        if len(good_w) > 20 :
            print("is win")
            is_win = True

    return is_win, is_lose

###Win/Loseの判定
マッチング結果にはDistance(どれだけマッチしているか)が格納されているので、Distanceで足切りを行います。

        #Lose判定
        good_l = []
        for match1, match2 in matches_l:
            #Distanceが一定以上の特徴点だけを抜き出す
            if match1.distance < 0.75*match2.distance:
                good_l.append([match1])

足切り後、一定以上特徴点が残っていれば、Win/Lose画像が存在していると判断します。

        if len(good_l) > 20 :
            print("is lose")
            is_lose = True

##Win画面/Lose画面の判定
誤検知を抑止するために、一定回数以上連続でWin/Lose画像と判断した場合のみWin/Lose画面と判定します。
(python使ってるんだからもっと簡素に書けそう……)

    is_win, is_lose = MatchResultCheck(ocv_im)

    if is_lose :
        cnt_lose_match += 1
        if cnt_lose_match >= 4:
            print("is lose match")
            cnt_lose_match = 0
            cv2.waitKey(1000)
    else :
        cnt_lose_match = 0

#出来なかったこと
同様に先攻/後攻も判定しよう!と思ったら上手く出来ませんでした……
Win/Loseと違って判定画像が小さすぎるのと、漢字なのが辛いのかなって思ってます。
引き続き精進していきます。

#まとめ
スクリーンキャプチャに特定の画像が存在しているか判定できました。
判定結果をリアルタイムに描画できると面白いですね。

次回は@rysk001さんです。

17
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?