LoginSignup
3
3

More than 1 year has passed since last update.

機械学習「Face-Api」を使って、顔パーツにピカチュウを表示する

Last updated at Posted at 2021-06-05

機械学習(Face-Api)

数日前に「機械学習」を習ったので、ポケモンネタで何かを作ろうと試行錯誤した話です。
"モンスターボールから、ピカチュウが飛び出してくるイメージ"のものを作ろうとしたのですが、果たしてどのモデルで実現できるのかが分からず・・・。
そこで、試しにml5.jsの「Face-Api」を使ってみました。
結果、無事にピカチュウは表示できたものの、イメージどおりにはなりませんでした・・・。
ですが、いつか使える日が来るかも?と思い、ちょっとおもしろかったので記事にしておきます。

試作品

両目の位置が特定されると、その上にピカチュウが表示されます。(何だかイメージしてたのと違う・・・)
ピカチュウ画像は、PokeAPIから取ってきたものをイメージファイルとして呼び出しています。
image.png

ソースコード

作成にあたっては、以下の記事を大変参考にさせていただきました。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ピカチュウeyes</title>
  </head>
  <body>
    <h1>ピカチュウeyes</h1>
    <!-- CDNの読み込み -->
    <script src="https://unpkg.com/ml5@latest/dist/ml5.min.js"></script>
    <!-- <script src="https://cdn.jsdelivr.net/npm/p5@0.10.2/lib/p5.js"></script> -->

    <script>
        let faceapi;
        let video;
        let width = 640;
        let height = 480;
        let ctx;
        let img;

        // Face-Apiのオプション設定
        const detection_options = {
            withLandmarks: true,
            withDescriptors: false,
        }

        // メイン処理
        async function make(){
            img = new Image();
            img.src = 'https://cdn-ak.f.st-hatena.com/images/fotolife/K/Kokano23/20210508/20210508184830.png';
            video = await getVideo();
            let canvas = createCanvas(width, height);
            ctx = canvas.getContext('2d');
            // faceapiモデルのオブジェクト生成
            faceapi = await ml5.faceApi(video, detection_options, modelReady)
        }

        // DOMの読み込み
        window.addEventListener('DOMContentLoaded', function() {
            make();
        });

        // Face-Apiモデルの読み込み
        function modelReady() {
            console.log('ready!')
            faceapi.detect(gotResults)
        }

        // Face-Api呼び出し関数
        function gotResults(err, result) {
            if (err) {
                console.log(err)
                return
            }
        // 自分の映像の情報を取得
         let detections = result;

        // 描画キャンパスを初期化
         ctx.fillStyle = "#000000"
         ctx.fillRect(0,0, width, height);
         ctx.drawImage(video, 0,0, width, height);

        // 自分の映像に描画する処理
          if (detections) {
           if(detections.length > 0){
               drawLandmarks(detections)
                }
            }
        // Face-Apiの再呼び出し
           faceapi.detect(gotResults)
        }

        // Face-Apiで取得した目の位置を特定する処理
        function drawLandmarks(detections){
            for(let i = 0; i < detections.length; i++){
                const leftEye = detections[i].parts.leftEye;
                const rightEye = detections[i].parts.rightEye;
                // 目に画像を描画
                ctx.drawImage(img, leftEye[0].x -10, leftEye[0].y -25, 50, 50);
                ctx.drawImage(img, rightEye[0].x -10, rightEye[0].y -25, 50, 50);
            }
        }

        // Helper Functions
        async function getVideo(){
            // 要素の取得、設定の作成など
            const videoElement = document.createElement('video');
            videoElement.setAttribute("style", "display: none;");
            videoElement.width = width;
            videoElement.height = height;
            document.body.appendChild(videoElement);
            // Webカメラのキャプチャを作成
            const capture = await navigator.mediaDevices.getUserMedia({ video: true })
            videoElement.srcObject = capture;
            videoElement.play();
            return videoElement
        }
        // キャンパスの作成
        function createCanvas(w, h){
            const canvas = document.createElement("canvas");
            canvas.width  = w;
            canvas.height = h;
            document.body.appendChild(canvas);
            return canvas;
        }
    </script>
  </body>
</html>

最後に

  • 本当にやりたいのは、「Teachable Machine」で機械学習したモンスターボールを検知した場合、モンスターボール上にピカチュウを表示させることです。
  • 上記を実現するには、「Handpose」を使って、モンスターボールを持つ手の関節にピカチュウを表示させる、という方法がよさそうです。(実現できたら、別記事にする予定です)
  • 今回の試作品は、想像していたものとは大分違ったのですが、これはこれで子どもに「おもしろい!」と言ってもらえました。
  • 試しにマスクを着用してみたところ、うまく座標位置が認識されませんでした。(勉強になりました)
  • ポケモン好きのお子さんがいらっしゃる方など、ぜひ遊んでみてください!
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3