Node.jsでAzure Face APIを使ってみる


写真から顔を認識して、その人の性別や年齢、どういった感情なのか、などを抽出してみます。

せっかくの岩手県立大学アドベントカレンダーなので例の写真でも試してみます。

<img src="https://i.gyazo.com/8931d2c79902bc012aac58264a27f64b.png" width="200">

[@isseiumさんのnote](https://note.mu/isseium)は今年の岩手県立大学アドベントカレンダーのMVPに違いありません。

では、やっていき。

## Microsoft Azure Face API

まず、今回はこのAPIを使ってます。

https://azure.microsoft.com/ja-jp/services/cognitive-services/face/

![](https://i.gyazo.com/975c06354508de5c216eae876a91f277.jpg)

写真を送るとその写真の中に写ってる人の情報を教えてくれるAPIです。
結構色々な情報が分かります。

> [Face APIとは?](https://docs.microsoft.com/ja-jp/azure/cognitive-services/face/overview)

## 無料で試していく

トップページの試すから進みます。

<img src="https://i.gyazo.com/24fea510a32cbb5759eec9b2e97ce416.png" width="300">

とりまゲストで無料でやります。

<img src="https://i.gyazo.com/29f87fa9824e43a4fc80403b76f488c0.png" width="300">

進むとAPIキーを取得できます。

![スクリーンショット 2018-12-22 15.55.16.png](https://qiita-image-store.s3.amazonaws.com/0/35387/7db3d31b-cead-c75e-e6a2-ebea53a27660.png "スクリーンショット 2018-12-22 15.55.16.png")

このキーをメモっておいてください。そのままクイックスタートガイドに行くとこの画面見つけにくいので別タブで開いたりがいいかも。

## サンプルを試す

サンプルを試す際にはrequestモジュールを利用するみたいなのでインストールします。

```
$ npm i request
```

```app.js
'use strict';

const request = require('request');
const subscriptionKey = 'ここにキーを指定'; //キーを指定
const uriBase = 'https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect';

const imageUrl = 'https://upload.wikimedia.org/wikipedia/commons/3/37/Dagestani_man_and_woman.jpg';

// Request parameters.
const params = {
    'returnFaceId': 'true',
    'returnFaceLandmarks': 'false',
    'returnFaceAttributes': 'age,gender,headPose,smile,facialHair,glasses,' +
    'emotion,hair,makeup,occlusion,accessories,blur,exposure,noise'
};

const options = {
    uri: uriBase,
    qs: params,
    body: '{"url": ' + '"' + imageUrl + '"}',
    headers: {
        'Content-Type': 'application/json',
        'Ocp-Apim-Subscription-Key' : subscriptionKey
    }
};

request.post(options, (error, response, body) => {
  if (error) {
    console.log('Error: ', error);
    return;
  }
  let jsonResponse = JSON.stringify(JSON.parse(body), null, '  ');
  console.log('JSON Response\n');
  console.log(jsonResponse);
});
```

実行してみましょう。このサンプルコードは特定の画像のパスを渡すと顔情報を教えてくれるといった内容です。

<img src="https://upload.wikimedia.org/wikipedia/commons/3/37/Dagestani_man_and_woman.jpg" width="300">

```bash
$ node app.js
JSON Response

[
  {
    "faceId": "d39b53cb-a188-4c7c-a791-40e4158e4c97",
    "faceRectangle": {
      "top": 621,
      "left": 616,
      "width": 195,
      "height": 195
    },
    "faceAttributes": {
      "smile": 0,
      "headPose": {
        "pitch": 0,
        "roll": 6.8,
        "yaw": 3.7
      },
      "gender": "male",
      "age": 37,
      "facialHair": {
        "moustache": 0.4,
        "beard": 0.4,
        "sideburns": 0.1
      },
      "glasses": "NoGlasses",
      "emotion": {
        "anger": 0,
        "contempt": 0,
        "disgust": 0,
        "fear": 0,
        "happiness": 0,
        "neutral": 0.999,
        "sadness": 0.001,
        "surprise": 0
      },
      "blur": {
        "blurLevel": "high",
        "value": 0.89
      },
      "exposure": {
        "exposureLevel": "goodExposure",
        "value": 0.51
      },
      "noise": {
        "noiseLevel": "medium",
        "value": 0.59
      },
      "makeup": {
        "eyeMakeup": true,
        "lipMakeup": false
      },
      "accessories": [],
      "occlusion": {
        "foreheadOccluded": false,
        "eyeOccluded": false,
        "mouthOccluded": false
      },
      "hair": {
        "bald": 0.04,
        "invisible": false,
        "hairColor": [
          {
            "color": "black",
            "confidence": 0.98
          },
          {
            "color": "brown",
            "confidence": 0.87
          },
          {
            "color": "gray",
            "confidence": 0.85
          },
          {
            "color": "other",
            "confidence": 0.25
          },
          {
            "color": "blond",
            "confidence": 0.07
          },
          {
            "color": "red",
            "confidence": 0.02
          }
        ]
      }
    }
  },
  {
    "faceId": "9ec32093-cb72-47d8-929d-aef5868f1b50",
    "faceRectangle": {
      "top": 693,
      "left": 1503,
      "width": 180,
      "height": 180
    },
    "faceAttributes": {
      "smile": 0.003,
      "headPose": {
        "pitch": 0,
        "roll": 2,
        "yaw": -2.2
      },
      "gender": "female",
      "age": 56,
      "facialHair": {
        "moustache": 0,
        "beard": 0,
        "sideburns": 0
      },
      "glasses": "NoGlasses",
      "emotion": {
        "anger": 0,
        "contempt": 0.001,
        "disgust": 0,
        "fear": 0,
        "happiness": 0.003,
        "neutral": 0.984,
        "sadness": 0.011,
        "surprise": 0
      },
      "blur": {
        "blurLevel": "high",
        "value": 0.83
      },
      "exposure": {
        "exposureLevel": "goodExposure",
        "value": 0.41
      },
      "noise": {
        "noiseLevel": "high",
        "value": 0.76
      },
      "makeup": {
        "eyeMakeup": false,
        "lipMakeup": false
      },
      "accessories": [],
      "occlusion": {
        "foreheadOccluded": false,
        "eyeOccluded": false,
        "mouthOccluded": false
      },
      "hair": {
        "bald": 0.06,
        "invisible": false,
        "hairColor": [
          {
            "color": "black",
            "confidence": 0.99
          },
          {
            "color": "gray",
            "confidence": 0.89
          },
          {
            "color": "other",
            "confidence": 0.64
          },
          {
            "color": "brown",
            "confidence": 0.34
          },
          {
            "color": "blond",
            "confidence": 0.07
          },
          {
            "color": "red",
            "confidence": 0.03
          }
        ]
      }
    }
  }
]
```

REST APIで使えるの良いですね。

## axiosで書き直してみる

axios派閥としてはこっちで試したいところですね。

```
npm i axios
```

```app.js
'use strict';

const axios = require('axios');
const subscriptionKey = 'ここにキーを指定'; //キーを指定
const uriBase = 'https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect';
const imageUrl = 'https://upload.wikimedia.org/wikipedia/commons/3/37/Dagestani_man_and_woman.jpg';

// Request parameters.
const params = {
    'returnFaceId': 'true',
    'returnFaceLandmarks': 'false',
    'returnFaceAttributes': 'age,gender,headPose,smile,facialHair,glasses,' +
    'emotion,hair,makeup,occlusion,accessories,blur,exposure,noise'
};

const config = {
    baseURL: uriBase,
    method: 'post',
    headers: {
        'Content-Type': 'application/json',
        'Ocp-Apim-Subscription-Key': subscriptionKey
    },
    data: '{"url": ' + '"' + imageUrl + '"}',
    params: params,
}

axios.request(config)
.then(res => {
    const jsonResponse = JSON.stringify(res.data, null, '  ');
    console.log('JSON Response\n');
    console.log(jsonResponse);
})

.catch(error => console.log(error.response.data));
```

## 例の写真をAPIに食わせてみる

* インプット

<img src="https://i.gyazo.com/8931d2c79902bc012aac58264a27f64b.png" width="200">

* アウトプット

```json
[
  {
    "faceId": "3b0b0aa7-cc43-4f8f-9d8c-e143b89f1621",
    "faceRectangle": {
      "top": 142,
      "left": 340,
      "width": 77,
      "height": 77
    },
    "faceAttributes": {
      "smile": 0.196,
      "headPose": {
        "pitch": 0,
        "roll": 12.4,
        "yaw": -25.8
      },
      "gender": "male",
      "age": 35,
      "facialHair": {
        "moustache": 0.1,
        "beard": 0.1,
        "sideburns": 0.1
      },
      "glasses": "NoGlasses",
      "emotion": {
        "anger": 0,
        "contempt": 0,
        "disgust": 0,
        "fear": 0,
        "happiness": 0.196,
        "neutral": 0.8,
        "sadness": 0.004,
        "surprise": 0
      },
      "blur": {
        "blurLevel": "low",
        "value": 0
      },
      "exposure": {
        "exposureLevel": "goodExposure",
        "value": 0.62
      },
      "noise": {
        "noiseLevel": "medium",
        "value": 0.38
      },
      "makeup": {
        "eyeMakeup": false,
        "lipMakeup": true
      },
      "accessories": [],
      "occlusion": {
        "foreheadOccluded": false,
        "eyeOccluded": false,
        "mouthOccluded": false
      },
      "hair": {
        "bald": 0.12,
        "invisible": false,
        "hairColor": [
          {
            "color": "black",
            "confidence": 1
          },
          {
            "color": "brown",
            "confidence": 0.85
          },
          {
            "color": "other",
            "confidence": 0.42
          },
          {
            "color": "gray",
            "confidence": 0.23
          },
          {
            "color": "red",
            "confidence": 0.03
          },
          {
            "color": "blond",
            "confidence": 0.03
          }
        ]
      }
    }
  }
]
```

この辺のパラメータの意味は[こちらのサイトの解説](https://azure-recipe.kc-cloud.jp/2017/12/face_api_2017adcal/)が分かりやすいです。

* 年齢: 35歳 ( `faceAttributes.age` -> 35 )
* 性別: 男性 ( `faceAttributes.gender` -> "male" )
* 感情: 無表情 ( `faceAttributes.emotion.neutral` -> 0.8 )
* 笑顔: 笑顔ではない ( `faceAttributes.smile` -> 0.196 )
* メガネ: メガネ無し　（ `faceAttributes.glasses` -> "NoGlasses" ）
* 髪色: 茶髪っぽい（`faceAttributes.hair.Color` -> `{"color": "brown","confidence": 0.85`）

年齢はちょっと違いますが、それ以外はだいたい正確な気がしています。

## 所感

正面向いてるわけでもないこれくらいの画像でもちゃんと結果が返ってくるのは素晴らしいですね。

これをもっと面白いことに活用していく予定です！