「逆転オセロニア」を画像解析して自動ダメージ計算 part3 (キャラ識別編)

# 逆転オセロニア画面を解析して自動でダメージ計算

逆転オセロニアとはオセロのルールで駒を置いていき、スキルやコンボを駆使して相手のHPを削ったら勝ちという対戦型のスマホゲームアプリになります。

そのためダメージ計算はかなり重要な部分になってきます。

詳しくは

[逆転オセロニア最速攻略wiki](https://xn--cckp5c6czi2302avwxa.gamematome.jp/game/964/wiki/%E3%83%88%E3%83%83%E3%83%97%E3%83%9A%E3%83%BC%E3%82%B8)

で確認してみてください。

その逆転オセロニアのダメージ計算を自動で行うためのプログラムを1年ほど前に作成していましたが、その時の作業手順を思い出しながら少しだけ解説していこうと思います。

---
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">オセロニアの画面を解析してダメージ計算できるプログラムを作ってみました(●´ω｀●) <br><br>端数の計算が間違ってるなど、まだまだ問題だらけです(＠_＠;) <a href="https://t.co/WL7FaiBmz3">pic.twitter.com/WL7FaiBmz3</a></p>&mdash; とよとよ (@toyotoyo_) 
<a href="https://twitter.com/toyotoyo_/status/1055465528242786305?ref_src=twsrc%5Etfw">October 25, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
---
## 前回までの記事

[「逆転オセロニア」を画像解析して自動ダメージ計算 part1 (iPhone PC表示編)](https://qiita.com/toyotoyo_/items/eb1198074eafabcc8a67)

[「逆転オセロニア」を画像解析して自動ダメージ計算 part2 (文字識別編)](https://qiita.com/toyotoyo_/items/161496e1bcf685e6ecb3)


前回までの記事では「逆転オセロニア」をPCで表示し、PythonでATKの数値を読み込むまでの手順を紹介しました。

## 今回の記事

今回の記事は手駒のキャラを識別する部分を紹介したいと思います。


## 教師データ用のキャラの画像抽出

手駒キャラを識別するためにはキャラの元画像が必要になります。
元画像をどれだけ集めれるかがキャラ識別の鍵になります。

本来なら戦闘画面の手駒の画像データを教師データとして準備しないといけませんが、とりあえずデッキ選択画面でキャラ画像データを抽出してみました。

精度が悪ければ戦闘画面の手駒からも画像データを集めるようにします。

前回の記事で行ったようにLonelyScreenで「逆転オセロニア」を全画面表示させます。

デッキ選択画面を表示

![デッキ選択画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/e6ace9d1-74ac-03e2-1ba1-c1bc88adda1a.png)

### 画像出力先のフォルダを作成
imgというフォルダを作成し、imgフォルダの中にcharacterフォルダを作成。


### 抽出処理実行

Jupyter Notebookで実行

```
from PIL import ImageGrab

#キャラ駒の大きさ
CHARACTER_SIZE_X=50
CHARACTER_SIZE_Y=50
#左上キャラの開始座標
CHARACTER_START_X=760
CHARACTER_START_Y=310
#キャラ駒の間隔
CHARACTER_SPACE_X=116
CHARACTER_SPACE_Y=108

#デッキ編成画面
for row in range(4):
    for col in range(4):
        url_img = "img\\character\\hensei" + str(col) + "_" + str(row) + ".png"
        print(url_img)
        ImageGrab.grab(bbox=(CHARACTER_START_X+CHARACTER_SPACE_X*row, CHARACTER_START_Y+CHARACTER_SPACE_Y*col, CHARACTER_START_X+CHARACTER_SIZE_X+CHARACTER_SPACE_X*row, CHARACTER_START_Y+CHARACTER_SIZE_Y+CHARACTER_SPACE_Y*col)).save(url_img)
```
img\characterフォルダの中に16個のキャラ画像が抽出出来ていると思います。

![デッキ選択画面のキャラ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/31d8fec8-db31-15a0-081f-1fd07d68a14b.png)


# 戦闘画面からのデータ抽出
デッキ選択画面と同じように、戦闘画面でも手駒キャラの画像を抽出します。

![戦闘画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/ce26e65c-ceab-866f-8e50-395aebbb9de7.png)

imgフォルダの中にtegomaフォルダを作成し実行

```
from PIL import ImageGrab

#キャラ駒の大きさ
CHARACTER_SIZE_X=50
CHARACTER_SIZE_Y=50
#左キャラの開始座標
TEGOMA_START_X=737
TEGOMA_START_Y=870
#キャラ駒の間隔
TEGOMA_SPACE_X=132

#戦闘画面の手駒
for row in range(4):
    url_img = "img\\tegoma\\tegoma" + str(row) + ".png"
    print(url_img)
    ImageGrab.grab(bbox=(TEGOMA_START_X+TEGOMA_SPACE_X*row, TEGOMA_START_Y, TEGOMA_START_X+CHARACTER_SIZE_X+TEGOMA_SPACE_X*row, TEGOMA_START_Y+CHARACTER_SIZE_Y)).save(url_img)
```

img\tegomaフォルダの中に4個のキャラ画像が抽出出来ていると思います。

![手駒キャラ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/8ce37e2e-90a4-e97e-a8d2-00cffe70d2c1.png)



## 手駒キャラの識別方法

教師データが大量に集めれるのであれば、TensorFlowなどで機械学習を使い画像識別のモデルを作ろうと思っていましたが、とりあえずは画像の類似度でどこまでキャラ識別が出来るかを確認してみました。

類似度判断にはOpenCVを使います。
※ OpenCVのインストール方法などは前回記事を参照してください。

## 類似度判断処理

OpenCV - デッキ編成画面で取得したキャラ画像と手駒のキャラ画像の類似度を compareHist() で計算してみます。

比較方法は2つの画像のヒストグラムを作成し、その画像の成分値を比較して類似度を判断しています。
数値が高いほど似ている画像ということになります。

とりあえずはtegoma1.png(ジェンイー)で比較を行ってみます。

![tegoma1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/b2e173b1-81d2-c725-8c4a-af2c41c84578.png)

```
import cv2
import os
IMG_DIR = 'img\\character\\'
TEGOMA_IMG_PATH = "img\\tegoma\\tegoma1.png"
# 手駒画像を読み込みヒストグラム作成
target_img = cv2.imread(TEGOMA_IMG_PATH)
target_hist = cv2.calcHist([target_img], [0], None, [256], [0, 256])

# characterフォルダの中にあるデッキ編成画像と類似度を比較していく
files = os.listdir(IMG_DIR)
for file in files:
    comparing_img_path = IMG_DIR + file
    # デッキ編成画像を読み込みヒストグラム作成
    comparing_img = cv2.imread(comparing_img_path)
    comparing_hist = cv2.calcHist([comparing_img], [0], None, [256], [0, 256])
    # 手駒とデッキ編成画像のヒストグラム比較を行う
    ret = cv2.compareHist(target_hist, comparing_hist, 0)
    print(file, ret)
```

出力結果

```
hensei0_0.png -0.08261034155462636
hensei0_1.png 0.0945696845478827
hensei0_2.png 0.7175182510178206
hensei0_3.png -0.47020588320002626
hensei1_0.png 0.7092531600717752
hensei1_1.png 0.4578690069347536
hensei1_2.png -0.19562547456319723
hensei1_3.png 0.4155359056985218
hensei2_0.png 0.5424911981946322
hensei2_1.png 0.35780300035511314
hensei2_2.png 0.6412738972790805
hensei2_3.png 0.6784556560900322
hensei3_0.png 0.5287740001351381
hensei3_1.png 0.025127832142219753
hensei3_2.png 0.2404974390822483
hensei3_3.png 0.46980532755469073
```
一番高い数値は hensei0_2.png(ジェンイー) という結果になりました！！


![hensei0_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/65665f07-babb-26fb-21d1-d1b9c74de140.png)

正解していますね！！

hensei1_0.png(カーンライズ)の値も結構高いので、カーンライズはジェンイーに似ているのかな？

![hensei1_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/731a27df-7f6d-5806-35a1-30539ff0c378.png)

※ 記事を分かりやすくするため、ファイル名にキャラ名を追加して試したのですが、日本語がダメだったらしく正しく動作しませんでした。



## まとめ
今回はここまでにします。

手駒の判断まで出来れば前回記事のATKの値と組み合わせてダメージ計算まで出来そうですよね！

~~気力があれば続きも書いていきたいと思います。~~

続きを書きました！
[「逆転オセロニア」を画像解析して自動ダメージ計算 part4 (ダメージ計算編)]
(https://qiita.com/toyotoyo_/items/59ad4cc24cfd78ddc700)