JavaScript
Node.js
Azure
機械学習
axios

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

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

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

@isseiumさんのnoteは今年の岩手県立大学アドベントカレンダーのMVPに違いありません。

では、やっていき。


Microsoft Azure Face API

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

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

写真を送るとその写真の中に写ってる人の情報を教えてくれるAPIです。

結構色々な情報が分かります。


Face APIとは?



無料で試していく

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

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

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

スクリーンショット 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);
});


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

$ 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に食わせてみる


  • インプット


  • アウトプット

[

{
"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
}
]
}
}
}
]

この辺のパラメータの意味はこちらのサイトの解説が分かりやすいです。


  • 年齢: 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

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


所感

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

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