LoginSignup
0
2

More than 5 years have passed since last update.

Firebaseでfrontendの構築- カメラでEmotionAPI

Last updated at Posted at 2016-12-05

GYAOのtsです。
我々のチームは、オールパブリッククラウドで、Microservice Architectureを採用した次期バックエンドを設計中です。

経緯

ずっとバックエンドのことばかり書いてきて、frontendのことを何も書いていなかったので、書いてみる。
バックエンドを構築していくチームだが、構築した複数のAPIを使用して、

ひらめき→実装→リリース→測定
のライフサイクルを短い時間で回していくのが目標なので、楽にfrontendを構築できるようにインフラ構築とナレッジを蓄積していく。
ちょうど、別プロジェクトでカメラ画像→emotionAPIのプロト作成があったのでちょうどいい
今回やることは

  1. firebase hostingを使用
  2. HTML5でカメラの起動と撮影
  3. 定期的にカメラ映像のキャプチャを取ってemotionAPIにpost
  4. 結果を画面に表示

Firebase

今回はFirebaseを使用する。
storage・remote config・hosting、reporting等々、様々な機能が提供されている。
基本的なアプローチとしてはHTML5 + jsのページをhostingして、js経由で様々なアセット(storage等)にアクセスする。

Firebase CLI

  • install

CLI等のtoolをインストールします。

sudo npm install -g firebase-tools
  • login

まずはlogin

firebase login
  • init

プロジェクトディレクトリを作成してinitします。

firebase init

今回は1ページのみで構成されたサイトを作ってみた。
スクリーンショット 2016-12-05 19.39.10.png
あとはこれを修正してdeployするのみ

  • deploy
firebase deploy

カメラ起動

    function startVideo() {
        navigator.mediaDevices.getUserMedia({video: true, audio: false})
        // success
        .then(function (stream) {
            localStream = stream;
            localVideo.src = window.URL.createObjectURL(localStream);
            setInterval("capture()", 10000);
        })
        // error
        .catch(function (error) { 
            console.error("navigator.mediaDevices.getUserMedia() error:", error);
            return;
        });
    }

capture

    function capture() {
        capture_canvas = document.getElementById('capture_canvas');
        var ctx = capture_canvas.getContext('2d');
        var w = localVideo.offsetWidth;
        var h = localVideo.offsetHeight;
        capture_canvas.setAttribute("width", w);
        capture_canvas.setAttribute("height", h);
        ctx.drawImage(localVideo, 0, 0, w, h);
        sendImage();
    }

emotionAPI

画像データを一旦バイナリに変換しなければならないのでこうなった。。。

    makeblobdata = function (dataURL) {
        var BASE64_MARKER = ';base64,';
        if (dataURL.indexOf(BASE64_MARKER) == -1) {
            var parts = dataURL.split(',');
            var contentType = parts[0].split(':')[1];
            var raw = decodeURIComponent(parts[1]);
            return new Blob([raw], { type: contentType });
        }
        var parts = dataURL.split(BASE64_MARKER);
        var contentType = parts[0].split(':')[1];
        var raw = window.atob(parts[1]);
        var rawLength = raw.length;

        var uInt8Array = new Uint8Array(rawLength);

        for (var i = 0; i < rawLength; ++i) {
            uInt8Array[i] = raw.charCodeAt(i);
        }

        return new Blob([uInt8Array], { type: contentType });
    }

    var api_key = 'xxxxxxxxxxx'; 
    function sendImage() {
        var request =  $.ajax({
        url: "https://api.projectoxford.ai/emotion/v1.0/recognize",
        processData: false,
        beforeSend: function(xhrObj){
            // Request headers
            xhrObj.setRequestHeader("Content-Type","application/octet-stream");
            xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", api_key);
        },
        type: "POST",
        // Request body
        data: makeblobdata(capture_canvas.toDataURL())
    })
    .done(function(data) {
        var res = document.getElementById('res');
        res.innerHTML = JSON.stringify(data);
    })
    .fail(function() {
        alert("error");
    });
    }

result

汚いが、プロトだからまあいいか。下記のように出力できる。

スクリーンショット 2016-12-05 20.12.25.png

上がカメラ撮影その下がキャプチャ
スクリーンショット 2016-12-05 20.15.21.png

0
2
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
0
2