YOLOv3を用いてポケモンGOの黒卵の出現を自動検出してGoogle-Homeに喋らせる

はじめに

みなさんはポケモンGOというゲームをご存知でしょうか.ポケモンGOは位置情報を利用し,実際に現実世界に繰り出し様々な土地で出現するポケモンをゲットし収集するゲームです.

このポケモンGOの中に『レイド』なるものがあります.レイドでは,ポケモンGOの世界で『ジム』と呼ばれる場所に45分間出現する特別なポケモンをみんなで協力して倒すことができ,ポケモンを倒した人は報酬としてそのポケモンをゲットするチャンスが与えられます.ジムでレイドが行われる場合,一時間前にそのジム上に『卵』が出現します.出現する卵の色によって,出現する特別なポケモンの強さが変わり,黒卵の場合は『伝説のポケモン』が出現します.

伝説のポケモンは黒卵のレイドでしか入手できないため,ポケモンGOをプレイするポケモンマスターは日々黒卵が出現しているかをチェックし,黒卵が出現したジムの周りに集まる習性があります.私も土日はポケモンGOの画面を開き黒卵が出現しているかをチェックしています.

 

しかし,常にポケモンGOの画面を開き黒卵の出現をチェックするのは大変で,出現に気づかないことが多々あります.

そこでふと『黒卵が出現しているかのチェックを自動化できないか』と思い,やってみました.

どうやって作るか

YOLOv3を用いてMacbookPro上に出力したポケモンGO内のレイド一覧画面を認識し,黒卵を検出 → 黒卵を検出した場合,google-home-notifierを用いてGoolgleHomeに喋らせる,という方法で自動化したいと思います(無理矢理感あふれる)

YOLOv3の導入

 cd 任意の場所
 git clone https://github.com/pjreddie/darknet.git

認識させたい物体(黒卵)の学習準備

下記サイトを参考に黒卵の画像を学習させます.黒卵の画像の水増し,画像内の検出させたい物体の位置とラベルの出力を行います.

wakuphas.hatenablog.com

認識させたい物体(黒卵)の学習

Google Colaboratory(無料でGPUを利用できる環境が提供されている)を用いて学習を行います.

  • Google Colab上にYolo v3動作環境を用意する
 !apt update
 !nvcc -V
 !ln -sf /usr/local/cuda-9.2 /usr/local/cuda
 !apt-get install gcc-4.8 g++-4.8
 !update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 40 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8 
 !update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 50 --slave /usr/bin/g++ g++ /usr/bin/g++-7
 !update-alternatives --config gcc
 # 入力欄が出てくるのでg++-4.8のインデックスを入力
  • GoogleDriveからGoogle Colabへファイルを取得する 下記サイトを参考に先ほどGoogleDriveにアップロードしたファイルをGoogle Colabへコピーする.
 import os
 import google.colab
 import googleapiclient.discovery
 import googleapiclient.http
 
 google.colab.auth.authenticate_user()
 drive_service = googleapiclient.discovery.build('drive', 'v3')
 
 upload_filename = 'darknet.zip'
 
 file_list = drive_service.files().list(q="name='" + upload_filename + "'").execute().get('files')
 
 file_id = None
 for file in file_list:
   if file.get('name') == upload_filename:
     file_id = file.get('id')
     break
 
 if file_id is None:
   print(upload_filename + ' is None.')
 else:
   with open(upload_filename, 'wb') as f:
     request = drive_service.files().get_media(fileId=file_id)
     media = googleapiclient.http.MediaIoBaseDownload(f, request)
 
     done = False
     while not done:
       progress_status, done = media.next_chunk()
       print(100*progress_status.progress(), end="")
       print("complete")
  • GoogleDriveからダウンロードしたzipを解凍
 !unzip darknet.zip
 %%bash
 cd darknet
 make
  • 学習を開始.darknet53.conv.74は重みの初期値ファイル.
 %%bash
 cd darknet
 ./darknet  detector  train  cfg/obj.data cfg/yolov3-voc-obj.cfg darknet53.conv.74

学習が開始されると,あらかじめ設定されている試行回数(ここでは100)毎に重みファイルが出力されます.試したところ,だいたい試行回数1000の重みファイルで物体はある程度検出可能であったため,試行回数1100で学習を終えました.重みファイルは随時ダウンロードしておきます.

  • 黒卵を検出できるかの確認
 ./darknet detector test  cfg/obj.data cfg/yolov3-voc-obj.cfg backup/yolov3-voc-obj_1100.weights iOS.png

f:id:ykmrt777:20190407162545j:plain
きちんと黒卵を検出できている

YOLOv3によるポケモンGO画面の監視方法

ポケモンGOの画面をミラーリングソフト(iPad/iPhone画面録画ソフト)を利用してMacbookProに出力し,MacbookProのスクリーンショット画像をYOLOv3で認識します.

screencapture ./test.jpg
./darknet detector test cfg/obj.data cfg/yolov3-voc-obj.cfg backup/yolov3-voc-obj_1100.weights test.jpg > result.txt

GoogleHomeへの通知

google-home-notifierを利用する.下記サイトにmacOSでのgoogle-home-notifier導入について解説されているので,指示に従って行います.

qiita.com

  • main.jsの作成
const googlehome = require('google-home-notifier')
const language = 'ja';

googlehome.device('Google-Home', language); 

googlehome.notify('ポケモンGOで星5レイドが出現しました。', function(res) {
  console.log(res);
});

コマンドを実行すると,GoogleHomeMiniが独特の声で喋ります.

YOLOv3の黒卵検知とGoogleHomeへの通知の自動化

Pythonとlaunchdで自動化を行う.

  • search_black_eggs.pyの作成 ポケモンGOのスクショ画像を画像認識し,黒卵を検出した場合GoogleHomeに通知するまでの流れのスクリプトを記述します.
import os
import subprocess

cmd = 'screencapture ./pokemongo_raid.jpg'
cmd_darknet = './darknet detector test cfg/obj.data cfg/yolov3-voc-obj.cfg backup/yolov3-voc-obj_1100.weights pokemongo_raid.jpg > result.txt'
subprocess.call(cmd,shell=True)
subprocess.call(cmd_darknet,shell=True)
test_data = open("result.txt", "r")
contents = test_data.read()
fd = contents.find('black_eggs')
test_data.close()
if fd > 0:
    notification_cmd = './notification_gh.sh'
    subprocess.call(notification_cmd.split(),shell=True)
    print('end')
  • launchdでsearch_black_eggs.pyを自動実行させる 下記サイトを参考に行います. banmian.hatenablog.com

結果

こんな感じになりました.

これでゲームに熱中していてもGooleHomeが教えてくれます,やったね!

感想

初めてこうして記事を書きましたが,文字に起こしてアウトプットすることは非常に大変でした.ただ,継続は力なりと言いますので今後も何かネタがあったら書きたいと思います.