LoginSignup
9
11

More than 5 years have passed since last update.

Vue.js + Face APIで感情情報を取得する

Last updated at Posted at 2019-03-21

Microsoft AzureのFace APIを利用して感情情報を取得します。
今回はオープンソースのJavaScriptフレームワークであるVue.jsで実装してみます。

Face APIとは?

Microsoft Azureの顔認識APIです。
年齢、感情、性別などの特徴を抽出することができます。

感情については、怒り、軽蔑、嫌悪感、恐怖、喜び、中立、哀しみ、驚きの
8種類を判定することができます。

詳細は以下のページに記載されています。
https://azure.microsoft.com/ja-jp/services/cognitive-services/face/

今回は、こちらのように感情情報をコンソール上に出力します。
TFlXkreA.jpg

今回実施したこと

1.準備 (Vue.jsのプロジェクト環境構築)
2.カメラを起動し、リアルタイムの映像をvideoタグ内に表示する
3.感情分析する

準備

vue-cliを使って、Vue.jsのプロジェクト環境を構築します。
こちらについては、以下のページの「プロジェクトを作成する」まで
進めて見てください。

Vue.js を vue-cli を使ってシンプルにはじめてみる

カメラを起動し、リアルタイムの映像をvideoタグに表示する

次に、PCのフロントカメラを起動し、リアルタイムの映像をvideoタグに表示します。
videoタグに表示された映像は、定期的に静止画としてcanvasに表示します。
(具体的な処理は「感情分析する」の項目を参照してください)

HelloWorld.vue
<template id="main">
  <div id="app">
    <canvas ref="canvas" id="emo_canvas" width="400" height="400"></canvas>
    <div>
      <video ref="video" id="video" width="400" height="400" playsinline muted autoplay></video>
    </div>
  </div>
</template>
HelloWorld.vue

mounted() {
  //PCのフロントカメラを起動し、リアルタイムの映像をvideoタグに表示する
    this.video = this.$refs.video
    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
      navigator.mediaDevices.getUserMedia({audio: false, video: true})
      .then(stream => {
        this.video.srcObject = stream
        this.video.play()
      })
    }

    console.log(this.$refs.canvas)
    // console.log(this.$refs.canvas)

    this.canvas = this.$refs.canvas 

感情分析する

以下のサイトで会員登録し、APIキーを取得します。

その後、canvasに静止画を表示し、画像データをbase64に
変換した上で(makeblobメソッドの処理を参照してください)、
AxiosでFace APIに画像データを送信します。

HelloWorld.vue

this.testTimer = setInterval(() => {
      // console.log(this.$refs.canvas)
      let context = this.canvas.getContext("2d").drawImage(this.video, 0, 0, 400, 240)
    //撮った画像をcaptures配列に格納する
      this.captures.push(this.canvas.toDataURL("image/png")) 
      let subscriptionKey = "取得したキーをここに入力する";
      let uriBase = "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect";
      let params = {
        "returnFaceId": "true",
        "returnFaceLandmarks": "false",
        "returnFaceAttributes":
          "emotion"
      };
      //配列最後に追加された画像のフォーマットを変換し、imgURL変数に代入する
      const imgURL = this.makeblob(this.captures[this.captures.length - 1])
      //imgURLの画像をFaceAPIに送信
      Axios.post(
        uriBase + "?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,emotion",
        imgURL,
        {
          headers: {
            "Content-Type": "application/octet-stream",
            "Ocp-Apim-Subscription-Key": subscriptionKey,
          }
        },
      )
      .then(response => {
        console.log(response.data[0].faceAttributes.emotion)

      })
      .catch(error => {
        // console.log(error.response)
      });
    }, 5000);

Axiosで画像をPostするために、画像データをbase64に変換します。

HelloWorld.vue

methods: {     
    makeblob: function (dataURL) {
      let BASE64_MARKER = ';base64,';
      if (dataURL.indexOf(BASE64_MARKER) == -1) {
        let parts = dataURL.split(',');
        let contentType = parts[0].split(':')[1];
        let raw = decodeURIComponent(parts[1]);
        return new Blob([raw], {type: contentType});
      }
      let parts = dataURL.split(BASE64_MARKER);
      let contentType = parts[0].split(':')[1];
      let raw = window.atob(parts[1]);
      let rawLength = raw.length;
      let uInt8Array = new Uint8Array(rawLength);
      for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
      }
      return new Blob([uInt8Array], {type: contentType})
    }
  }

axiosを利用するため、以下のコマンドでnpm installします。

npm install --save-dev vue-axios axios

コード全体

今回コーディングしたコード全体は以下の通りです。

HelloWorld.vue


<template id="main">
  <div id="app">
    <canvas ref="canvas" id="emo_canvas" width="400" height="400"></canvas>
    <div>
      <video ref="video" id="video" width="400" height="400" playsinline muted autoplay></video>
    </div>
  </div>
</template>

<script>
import Vue from 'vue';
import Axios from 'axios';
import VueAxios from 'vue-axios'

Vue.use(VueAxios, Axios)

export default ({
  template: '#main',
  data() {
    return {
      video: {},
      canvas: {},
      captures: [],
      testTimer: '',
    };
  },
  mounted() {
  //カメラを起動し、映像をvideoタグ内に表示
    this.video = this.$refs.video
    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
      navigator.mediaDevices.getUserMedia({audio: false, video: true})
      .then(stream => {
        this.video.srcObject = stream
        this.video.play()
      })
    }

    console.log(this.$refs.canvas)
    // console.log(this.$refs.canvas)

    this.canvas = this.$refs.canvas 
    this.testTimer = setInterval(() => {
      // console.log(this.$refs.canvas)
      let context = this.canvas.getContext("2d").drawImage(this.video, 0, 0, 400, 240)
      this.captures.push(this.canvas.toDataURL("image/png")) //撮った画像をcaptures配列に格納する
      let subscriptionKey = "取得したキーをここに入力する";
      let uriBase = "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect";
      let params = {
        "returnFaceId": "true",
        "returnFaceLandmarks": "false",
        "returnFaceAttributes":
          "emotion"
      };
      //配列最後に追加された画像のフォーマットを変換し、imgURL変数に代入する
      const imgURL = this.makeblob(this.captures[this.captures.length - 1])
      //imgURLの画像をFaceAPIに送信
      Axios.post(
        uriBase + "?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,emotion",
        imgURL,
        {
          headers: {
            "Content-Type": "application/octet-stream",
            "Ocp-Apim-Subscription-Key": subscriptionKey,
          }
        },
      )
      .then(response => {
        console.log(response.data[0].faceAttributes.emotion)

      })
      .catch(error => {
        // console.log(error.response)
      });
    }, 5000);
  },
  methods: {     
    makeblob: function (dataURL) {
      let BASE64_MARKER = ';base64,';
      if (dataURL.indexOf(BASE64_MARKER) == -1) {
        let parts = dataURL.split(',');
        let contentType = parts[0].split(':')[1];
        let raw = decodeURIComponent(parts[1]);
        return new Blob([raw], {type: contentType});
      }
      let parts = dataURL.split(BASE64_MARKER);
      let contentType = parts[0].split(':')[1];
      let raw = window.atob(parts[1]);
      let rawLength = raw.length;
      let uInt8Array = new Uint8Array(rawLength);
      for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
      }
      return new Blob([uInt8Array], {type: contentType})
    }
  }
});

参考にさせて頂いたサイト

FaceAPIを使った感情分析
Vue.js を vue-cli を使ってシンプルにはじめてみる
Vue.jsでもjQueryと同じような ajax postを実装したい

9
11
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
9
11