Pythonでテンプレートマッチングをして遊んでみた

Pythonで画像認識で色々試していた時に、ポケモンの識別ができたら面白いなと思い勉強がてら実装してみました。

## 仕様
ディレクトリ構造は以下です。
```

pokemonPython/
    ├── pokemonImages/
    │   ├── カイリュー.jpg
    │   ├── サザンドラ.jpg
    │   ├── シビルドン.jpg
    │   ├── テツノツツミ.jpg
    │   ├── デリバード.jpg
    │   └── バンギラス.jpg
    ├── importImage.jpg
    └── template.py
```
importImage.jpgとpokemonImagesフォルダの中の画像たちを比較して同じポケモンのファイル名を出力します。

取り込んだポケモンの画像からポケモンの名前を取得したい！とかいう処理に使えるかなと思います。

pokemonImagesフォルダの中に比較対象のポケモンの画像を入れていけば比較できるポケモンを増やせます。

ちなみに想定としては、ゲームに登場したポケモンの名前を知りたい時に使います。
なのでpokemonImagesフォルダの中には、PokemonHOMEから取ってきました。

https://www.pokemon.co.jp/ex/pokemonhome/

| ファイル名 | ポケモン画像 |
|:-:|:-:|
| カイリュー.jpg | ![カイリュー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/a671c1be-95a6-c6d3-de03-f919d21b50d2.jpeg)  |
| サザンドラ.jpg  | ![サザンドラ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/6dda0850-cf47-d5eb-4a3d-f4837060b46f.jpeg)  |
| シビルドン.jpg  | ![シビルドン.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/0911db2e-c111-7727-d37c-a7c542f1987f.jpeg)  |
| テツノツツミ.jpg  | ![テツノツツミ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/32c888ee-0580-2e3e-606b-577992a943e7.jpeg)  |
| デリバード.jpg  | ![デリバード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/817fcdbc-70b8-da7b-71dd-f843d8c035f3.jpeg)  |
| バンギラス.jpg  | ![バンギラス.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/7f10c92c-439d-39c2-031c-37e239de7d74.jpeg)　|

## 実際に動かしてみよう

以下のコードを使って比較したいと思います。

ゲーム画面からポケモンのアイコンを撮影したものを比較します。
↓こんな感じ(importImage.jpg)
![importImage.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/b7ab6141-d45b-ab74-4da3-d615e4c4b2cb.jpeg)


```Python:template.py
import cv2
import os

TARGET_FILE = 'importImage.jpg'
IMG_DIR = os.path.abspath(os.path.dirname(__file__)) + '/pokemonImages/'
IMG_SIZE = (200, 200)

target_img_path = TARGET_FILE
target_img = cv2.imread(target_img_path, cv2.IMREAD_GRAYSCALE)
target_img = cv2.resize(target_img, IMG_SIZE)

bf = cv2.BFMatcher(cv2.NORM_HAMMING)
detector = cv2.AKAZE_create()
(target_kp, target_des) = detector.detectAndCompute(target_img, None)

files = os.listdir(IMG_DIR)
rets = []
filesMap = {}
for file in files:
    if file == '.DS_Store' or file == TARGET_FILE:
        continue

    comparing_img_path = IMG_DIR + file
    try:
        comparing_img = cv2.imread(comparing_img_path, cv2.IMREAD_GRAYSCALE)
        comparing_img = cv2.resize(comparing_img, IMG_SIZE)
        (comparing_kp, comparing_des) = detector.detectAndCompute(comparing_img, None)
        matches = bf.match(target_des, comparing_des)
        dist = [m.distance for m in matches]
        ret = sum(dist) / len(dist)
    except cv2.error:
        ret = 100000

    rets.append(ret)
    filesMap[ret] = file
    print(file, ret)

print(filesMap[min(rets)])

```

さあ実行してみます！
```:ターミナル
[pokemonPython(main)] $ Python3 template.py
```

```:結果
バンギラス.jpg 109.13300492610837
テツノツツミ.jpg 138.04926108374383
サザンドラ.jpg 142.66995073891624
カイリュー.jpg 133.2167487684729
デリバード.jpg 135.935960591133
シビルドン.jpg 135.72413793103448
バンギラス.jpg
```
importImage.jpgとpokemonImagesフォルダの中の画像たちを一つずつ比較して類似度のような数値を算出しています。
この数値が一番低い画像がimportImage.jpgと一番近い画像になります。

なので一番低い画像だった画像名を取得すればポケモン名が取得できますね。

今回だとバンギラスが一番近い画像として表示されているので成功です！

## 精度
算出する精度ですが、似ているポケモンで試してみます。
| ファイル名 | ポケモン画像 |
|:-:|:-:|
| テツノツツミ.jpg  | ![テツノツツミ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/32c888ee-0580-2e3e-606b-577992a943e7.jpeg)  |
| デリバード.jpg  | ![デリバード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/817fcdbc-70b8-da7b-71dd-f843d8c035f3.jpeg)  |

最新作から登場した「テツノツツミ」というポケモンですが、デリバードに酷似しています。
どうやらテツノツツミはデリバードの未来の姿だという知見がどこかのオカルト雑誌に載っているらしい。。。

すごく似ているので実際ゲーム画面でもぱっと見で見間違えたりします。。。

Pythonさんはどうでしょうか。
importImageをテツノツツミに変えて実行してみます。（ゲーム画面を写真で撮ったら画質が大変なことに）
![importImageのコピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/5a6be4e6-11e4-baa6-daa1-10a0b349e582.jpeg)

```:結果
バンギラス.jpg 133.12389380530973
テツノツツミ.jpg 104.02654867256638
サザンドラ.jpg 138.64601769911505
カイリュー.jpg 130.8230088495575
デリバード.jpg 132.63716814159292
シビルドン.jpg 133.5929203539823
テツノツツミ.jpg
```
しっかりとテツノツツミが表示されました。

importImageをデリバードに変えてみると
![importImage.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2917311/73572262-f168-d1b9-3373-6c92aef914f8.jpeg)
```:結果
バンギラス.jpg 129.88695652173914
テツノツツミ.jpg 132.90434782608696
サザンドラ.jpg 139.44347826086957
カイリュー.jpg 132.18260869565216
デリバード.jpg 89.74782608695652
シビルドン.jpg 133.8521739130435
デリバード.jpg
```
しっかりとデリバードが表示されました。
意外と算出した数値に差がありましたね。

この二匹の比較がうまくいけば、今作は全ポケモン対応できそうですね！

以上、Pythonとポケモンで遊んでみた！でした。