絶対じゃんけんに勝つマンを実装

こちらの記事に沿って絶対じゃんけんに勝つマンを作ってみました。

前提

Macユーザを前提として進めていきます。

写真撮影

先に言うと、学習データの準備だけで約53分かかりました。

「そんな暇じゃねぇよ、、」という方は、私が用意したデータ使ってやってください。

自由に使っていただいて構いません。

では、ぐーちょきぱーの画像を集めていきます。

# ターミナルから写真撮影できるツールをインストール
$ brew install imagesnap

# gtimeoutをインストール
$ brew install coreutils

# 写真保存用のディレクトリ作成
$ mkdir assets
$ cd assets

# 「ぐー」の写真撮影(0.1秒に1枚を25秒間撮影 = だいたい200枚くらい)
$ gtimeout 25 imagesnap -w 1 -t 0.1

# 「ちょき」と「ぱー」も同様に撮影していく
$ gtimeout 25 imagesnap -w 1 -t 0.1
$ gtimeout 25 imagesnap -w 1 -t 0.1

こんな感じで、「ぐー、ちょき、ぱー」の画像を合計600枚撮りました。

ラベリング作業

次に、撮った画像に対し、「ぐー」「ちょき」「ぱー」というラベルを付けていきます。

# ラベリングツールのインストール
$ pip install labelImg

# ラベリングツール起動(起動できない場合はターミナル再起動)
$ labelImg
  1. 「ディレクトリを開く」から写真を保存したディレクトリを選択
  2. 「指定されたラベル名を使う」にチェックを入れ「choki」などのラベルを入力
  3. メニューバーの「表示」から「自動で保存する」を選択
  4. 「保存先を変更する」から写真を保存したディレクトリを選択
  5. 保存形式を「YOLO」に設定
  6. 「Command + W」を押し、手の部分のみを選択し、「次の画像」を選択
  7. ⑥を繰り返す

こんな感じで、600枚の画像にひたすらラベルを付けていきます。

途中、ゲシュタルト崩壊をおこし、「ちょきってなんだっけ?」ってなりました。

ラベリングが終わったら、ラベルが正しく設定されているかを確認します。

# ラベルの順番を確認
$ cat classes.txt
goo    #これが0番
choki  #これが1番
par    #これが2番

# ラベル番号を確認 (1行目がラベル番号)
$ cat goo-00001.txt choki-00001.txt par-00001.txt
0 0.536719 0.659028 0.206250 0.395833
1 0.436719 0.600694 0.226562 0.659722
2 0.414062 0.515972 0.279687 0.548611

それと、モデル生成時に使うyamlファイルを同一ディレクトリに作成しておきます。

# 
train: /content/drive/MyDrive/goochokipar
val: /content/drive/MyDrive/goochokipar

nc: 3
names: ['goo', 'choki', 'par']

最後に、これらのデータをGoogleドライブにアップします。

「マイドライブ」直下に「goochokipar」というディレクトリを作り、そこに放ってやります。

これで学習データの準備が整いました。

モデル生成

先に言うと、モデルの生成に約2時間かかりました(有料枠でマシンのスペックを上げています)。

「そんな暇じゃねぇよ、、」という方は、私が生成したモデルを使ってやってください。

モデル生成の環境として、Google Colaboratoryを用います(無料枠でも十分に遊べるみたいです)。

登録が終わったら、

  1. 「ノートブックを新規作成」を選択
  2. メニューバーの「ランタイム」から「ランタイムタイプを変更」を選択
  3. 「ハードウェアアクセラレータ」から「GPU」を選択

あとは、ノートブックから操作していきます。

(実行するには、Ctrl + EnterShift + Enterを押下)

# Googleドライブをマウント
from google.colab import drive
drive.mount('/content/drive')

# マウントされているか確認
%ls -la /content/drive

# yolo v5をダウンロード
%cd /content
!git clone https://github.com/ultralytics/yolov5

# yolo v5に必要なライブラリをインストール
!pip install -r yolov5/requirements.txt

# モデル生成(マウント先のパスに合わせる)
!python /content/yolov5/train.py --batch 20 --epochs 300 --data '/content/drive/MyDrive/goochokipar/goochokipar.yaml' --name goochokipar

処理が終わるまで待ちます。

Google Colabのセッションが切れないように、こちらのスクリプトを実行しておくと安心です。

処理が終わりと、best.ptというようなファイルが生成されるので、これをローカルPCにダウンロードしておきます。

生成したモデルを使ってみる

まずは仮想端末の導入と、yolov5で既に用意されているモデルを使用してみます。

# yolov5という仮想端末を作成(任意の場所に)
$ python3 -m venv yolov5

# yolov5という仮想端末を起動
$ source yolov5/bin/activate

# yolov5ダウンロード
$ git clone https://github.com/ultralytics/yolov5.git; cd yolov5

# 必要なライブラリインストール
$ pip install -U -r requirements.txt

# 私の場合、これらもインストールしないと動かなかったです
pip install opencv-python seaborn matplotlib tqdm pyyaml requests pandas

# 既存の学習済みモデルを使用してみる(モジュールが足りない場合は適宜インストール)
python detect.py --source 0

こんな感じで、色々と認識されています。

いよいよ、生成したモデルを使っていきます。

$ python detect.py --source 0 --weight best.pt

ちゃんと認識されました。。

しかし、今回用意した学習用の素材は、背景が白地のものばかりだったので、背景が白じゃない場合には認識されづらいようでした。

様々な条件の素材を用意することが重要みたいですね。

絶対にじゃんけんに勝つマン

では、このモデルを使用して、絶対じゃんけんに勝つマンを簡単に作ってやろうと思います。

まずは、yolov5が吐くログを指定してあげます。

$ python detect.py --source 0 --weight best.pt 2>> goochokipar.log

上記を実行した状態で、以下のシェルを実行します。

#!/bin/bash

while true
do
        goo=$(tail -1 goochokipar.log |grep "goo" |wc -l)
        choki=$(tail -1 goochokipar.log |grep "choki" |wc -l)
        par=$(tail -1 goochokipar.log |grep "par" |wc -l)
        if [ $goo -gt 0 ]; then echo "(・3・)p ぱー"
        elif [ $choki -gt 0 ]; then echo "(・3・)o ぐー"
        elif [ $par -gt 0 ]; then echo "(・3・)v ちょき"
        else echo "(;-_-)v o(^-^ ) ジャンケン!!"
        fi
sleep 0.1
done

すると、、

(;-_-)v o(^-^ ) ジャンケン!!
(・3・)v ちょき
(・3・)v ちょき
(・3・)v ちょき
(・3・)v ちょき
(・3・)v ちょき
(・3・)v ちょき
(・3・)v ちょき
(;-_-)v o(^-^ ) ジャンケン!!
(・3・)v ちょき
(・3・)v ちょき
(・3・)v ちょき

という具合です。。