섀도바의 승패를 화상 인식으로 판정한다

이 기사는 링크 정보 시스템 의 "2020 신춘 모험 달력 TechConnect! "릴레이 기사입니다.
TechConnect!는 마음대로 시작하는 어드벤트 캘린더로서 engineer.hanzomon이라는 마음대로 만든 그룹에 의해 릴레이됩니다.
(링크 정보 시스템의 Facebook은 여기에서)

테마가 자유였기 때문에 자유로운 기사가 ​​됩니다. (사용 기술은 진지합니다.)
튜토리얼을 구사해, 열심히 화상 인식을 했습니다.

할 수있는 것



Shadowverse(Steam판)의 Win/Lose 판정을 실시하는 프로그램이 생겼습니다.

(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로 설치하는 것만으로 할 수 있었으므로 특히 막힌 곳은 없었습니다.

    방법


  • 게임 화면을 화면 캡처
  • 캡처한 이미지와 Win/Lose 이미지를 비교
  • 특징점을 Distance로 발자국하고 일정 이상의 특징점이 일치하면 Win/Lose로 판단

  • 일정 횟수 이상 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씨입니다.

    좋은 웹페이지 즐겨찾기