機械学習を使って、PCのカメラでザクを補足して撃てるようにしてみた。


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ザク撃ったらポイント貰えるようにした。<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a><a href="https://twitter.com/hashtag/%E3%82%AC%E3%83%B3%E3%83%80%E3%83%A0?src=hash&amp;ref_src=twsrc%5Etfw">#ガンダム</a> <a href="https://t.co/dN2bqzuZQb">pic.twitter.com/dN2bqzuZQb</a></p>&mdash; sawa (@sawakoshi_yy) <a href="https://twitter.com/sawakoshi_yy/status/1325375130713776129?ref_src=twsrc%5Etfw">November 8, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#クラウドファンディングでシューティングゲームを作る予定なので、カメラで敵を補足して撃てるようにしてみた。

ポケモンGOやドラクエウォークのような、現実世界を利用したシューティングゲームを企画しています。
肝心のシューティング部分を現在検討中で、センサで検知するのかカメラで検知するのか、検知する対象物は何か等を考えているところです。
今回は機械学習でザク（敵）を学習し、カメラにザクが映ったときに射撃ボタンを押すとLINENotifyから通知が送られるようにしてみました。


#構成
<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737363/19b23796-f32d-23d6-2f45-6195bb0ace8e.png">

#Teachable Machineで画像認識のモデルを作成する

Teachable Machineの使い方は↓のリンクを参照
[【10分で出来る】Teachable Machineを使って簡単なじゃんけん判別アプリを作ってみた]
(https://qiita.com/sasao3/items/becdf981d8e9dea496e5)

<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737363/d4cf948c-3abf-d659-54e4-109d33b9a606.png">

#integromatでwebhooks→LINENotifyのシナリオを作成する

Integromatの使い方は↓のリンクを参照
[Integromatの使い方]
(https://qiita.com/nendocode/items/b3f9f9810a0dfd744dcf)
<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737363/c76a008f-44ea-ee4d-97b4-776a4567206c.png">


#コード(HTML)

```html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>射撃ボタンクリックしたら、LINENotifyに通知するアプリ</title>
  </head>

  <body>
    <h1>ザクを撃て！！</h1>

    <!-- このapp内のみVue.jsの管理範囲です -->
    <div id="app">
      <p>{{ modelState }}</p>
      <p>{{ detectedName }}</p>
      <p><button v-on:click="onButtonClicked">射撃</button></p>
      <video id="myvideo" width="640" height="480" muted autoplay playsinline></video>
    </div>

    <!-- ml5.jsとVue.jsをCDNから読み込みます -->
    <script src="https://unpkg.com/ml5@latest/dist/ml5.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<script>
      // 作成したモデルのURL
      const imageModelURL = 'Teachable Machineで作成したモデルのURL';
      let classifier;

      const app = new Vue({
        el: '#app',
        data: {
          modelState: 'モデルのロード中…',
          detectedName: '',
        },

        async mounted() {
          // カメラからの映像取得
          const stream = await navigator.mediaDevices.getUserMedia({
            audio: true,
            video: true,
          });

          // IDが"myvideo"であるDOMを取得
          const video = document.getElementById('myvideo');

          // videoにカメラ映像をセット
          video.srcObject = stream;

          // 自作モデルのロード
          classifier = ml5.imageClassifier(imageModelURL + 'model.json', video, () => {
            // ロード完了
            app.modelState = 'ロード完了！';
            console.log('Model Loaded!');
          });
        },

        methods: {
          onButtonClicked: function() {
            classifier.classify((err, results) => {
              console.log(results);
              if (results[0]) {
                if(results[0].label=='ザク'){
                  try {
                    const address = axios.get('integromatのwebhookのURL' + results[0].label + '&text=' + '10ポイント獲得！');
                  } catch (e){
                    console.log('integromat連携に失敗');
                    console.error(e);
                  }
                } else {
                  try {
                    const address = axios.get('integromatのwebhookのURL' + results[0].label + '&text=' + '味方を撃つなあああ！');
                  } catch (e){
                    console.log('integromat連携に失敗');
                    console.error(e);
                  } 
                }
                app.detectedName = "君が撃ったのは" + results[0].label + "だ！！";
              } else {
                app.detectedName = 'わからない...';
              }
            });
          },
        },

      });
      
    </script>
  </body>
</html>
```

#考察
・スマホでの実装方法を調べる必要がある
・学習データの集め方が難しい
　→プラモデル作って撮影すればサンプルたくさん取れそう。
　　→プラモデル、、作るか。