連載
» 2017年06月27日 05時00分 UPDATE

Dev Basics/Keyword:Face API

Face APIはマイクロソフトのCognitive Servicesに含まれるAPIの1つで、顔検出/画像のグループ化/人物の特定などの機能を提供する。

[かわさきしんじ,Insider.NET編集部]
「Dev Basics/Keyword」のインデックス

連載目次

 Face APIは、マイクロソフトのCognitive Servicesに含まれるAPIの1つで、画像ファイルから顔を検出したり、グループ化したりといった処理を簡単なAPI呼び出しで実現できる。

Face APIでできること

 Face APIは主に以下の機能を提供する。

  • 顔検出
  • 顔識別

 ここでいう「顔検出」とは、APIに与えた画像から最大で64人までの(人の)顔を検出すること。このとき、検出した顔の画像内での位置に加えて、性別、年齢などの情報も抽出してくれる。

 もう一方の「顔識別」は、複数の画像の中から指定した顔と似た顔を含む画像を識別したり、同じく複数の画像を与えると、顔が似ているかどうかを基にそれらをグループ化したりする機能である。

 これらの機能が以下のAPIで提供されている。

  • Detect
  • Find Similar
  • Group
  • Identify
  • Verify

 また、顔の一覧(リスト)を作成したり、識別用に個人個人の顔を登録したりするためのAPIも用意されている。Face APIが提供する全APIは「Face API - V1.0」ページで一覧できるので、詳しくはそちらを参照されたい。

 Face APIを利用するには、Azureでのサブスクリプションの追加が必要となる。また、2017年6月26日現在、Face APIは「West US」「East US 2」「West Central US」「West Europe」「Southeast Asia」など、Azureのリージョンの一部でのみ利用可能となっていて、リクエストURLもリージョンごとに異なるものとなる。

 Face APIの価格については「Cognitive Services の価格 - Face API」ページを参照のこと。簡単にまとめると、20トランザクション/分、30,000トランザクション/月までは無料で利用できるFree、最大で10トランザクション/秒、1000トランザクションごとに課金が発生するStandardの2つの価格レベルがあり、それとは別に画像を保存するために使用する「フェースストレージ」を使用する場合には、そのための料金が別途発生する。

 以下では、AzureでFace APIのサブスクリプションを追加し、APIの利用に必要なアクセスキーを取得したものとして、幾つかのAPIを実際に使ってみよう。サブスクリプションの追加/アクセスキーの取得の手順については「Dev Basics/Keyword: Microsoft Translator Text API」などを参考にしてほしい(本稿では割愛する。なお、Microsoft Translator Text APIではアクセスに必要なトークンを作成しているが、Face APIではトークンの作成は不要だ)。

Detect APIを使ってみる

 ここでは、最もシンプルに顔を検出するDetect APIを使用してみよう。テストをするだけであれば、Detect APIのドキュメントページで、APIのテストコンソールを開き、必要な情報を入力して[Send]ボタンをクリックすればよい。詳しい手順は割愛するが、以下にこれを行っている様子を示す。

Face APIのテスト Face APIのテスト

 Detect APIのドキュメントを見ると、このAPIを呼び出す際には次のような情報を与えることが分かる。

  • リクエストURL: リージョン.api.cognitive.microsoft.com
  • メソッドの種類: POST
  • returnFaceIdパラメーター: 検出された顔に関連付けられたIDを返すか。オプション(既定値はtrue)
  • returnFaceLandmarksパラメーター: 検出された顔に含まれる目や鼻の位置を返すか。オプション(既定値はfalse)
  • returnFaceAttributesパラメーター: 検出された顔を解析して、年齢や性別などの情報のうち、返送するものを指定する。オプション。指定可能な値にはage/gender/headPose/smile/facialHair/glasses/emotionなどがある(カンマ区切りで複数を指定可能)

 これらの情報を基にリクエストURLを組み立て、リクエストボディーには画像ファイルのURLもしくは画像そのものを含める。

 JavaScriptでこれを行うコード例を以下に示す。ここではreturnFaceIdパラメーターとreturnFaceLandmarksパラメーターについては既定値(それぞれ、true=IDを返送する、false=目や鼻の位置を返送しない)を利用するようにして、returnFaceAttributesパラメーターにはage(年齢)、gender(性別)、smile(笑顔かどうかを0〜1の数値で示す)を指定している。画像ファイルのURLを指定するコードに加えて、リクエストに画像ファイルをそのまま含めるコードも用意してある。

const request = require("request");
const fs = require("fs");
const key = "アクセスキー";
const url = "https://westus.api.cognitive.microsoft.com/face/v1.0/detect";

const body = {
  url: "https://insidernetpictures.blob.core.windows.net/pictures/face3.png"
};

const attrib="age,gender,smile";
const param=`?returnFaceAttributes=${attrib}`;

var opt = {
  url: url + param,
  headers: {
    "Ocp-Apim-Subscription-Key": key,
    "Content-Type": "application/json"
  },
  body: JSON.stringify(body)
};

request.post(opt, (err, res, body) => {
  console.log("URL");
  console.log(JSON.parse(body));
});

// ローカルの画像ファイルを渡す場合
const image = fs.readFileSync("face3.png");

opt = {
  url: url + param,
  headers: {
    "Ocp-Apim-Subscription-Key": key,
    "Content-Type": "application/octet-stream"
  },
  body: image
};

request.post(opt, (err, res, body) => {
  console.log("local file");
  console.log(JSON.parse(body));
});

Detect APIを使用するコード例(JavaScript)

 実際に利用した画像を以下に示す(以下ではぼかしを入れてあるが、実際にはぼかしなしの画像を使用)。

検出に使用した画像 検出に使用した画像

 検出結果はJSON形式のデータとして返送される。以下に上のコードを実行した結果を示す。

> node facedetect.js
URL
[ { faceId: '4e3690d7-6220-4039-b2fd-fb591347ed8c',
    faceRectangle: { top: 418, left: 491, width: 239, height: 239 },
    faceAttributes: { smile: 0.001, gender: 'male', age: 37 } } ]
local file
[ { faceId: 'e67ae29b-0e89-4197-ad82-ce99e22cf0d2',
    faceRectangle: { top: 418, left: 491, width: 239, height: 239 },
    faceAttributes: { smile: 0.001, gender: 'male', age: 37 } } ]


呼び出し結果

 どちらも同じファイルなので、笑顔ではない(smile=0.001)、男性、37歳という結果になっている。

Find Similar APIを使用してみる

 Find Similar APIは、複数の画像ファイルのグループ化するものだ。グループ化にはDetect APIの呼び出しで返送されるfaceIdの値が用いられる。faceId値の配列をAPIに渡すと、それらの値を利用して、画像のグループ化を行い、それがfaceId値の配列として返送される。詳細は割愛するが、実際にこのAPIを呼び出すコードを以下に示す。

const request = require("request");
const key = "アクセスキー";
const detectUrl = "https://westus.api.cognitive.microsoft.com/face/v1.0/detect";
const groupUrl = "https://westus.api.cognitive.microsoft.com/face/v1.0/group";

var opt = {
  headers: {
    "Ocp-Apim-Subscription-Key": key,
    "Content-Type": "application/json"
  }
};

function callDetectAPI(image) {
  return new Promise(function(resolve, reject) {
    opt.url = detectUrl;
    opt.body = JSON.stringify({
      url: image
    });
    request.post(opt, (err, res, body) => {
      var tmp = JSON.parse(body);
      resolve(tmp[0].faceId);
    });
  })
}

function callGroupAPI(ids) {
  return new Promise(function(resolve, reject) {
    opt.url = groupUrl;
    opt.body = JSON.stringify({
      faceIds: ids
    });
    request.post(opt, (err, res, body) => {
      resolve(body);
    })
  })
}
const images = [
  "https://insidernetpictures.blob.core.windows.net/pictures/face2.png",
  "https://insidernetpictures.blob.core.windows.net/pictures/face3.png",
  "https://insidernetpictures.blob.core.windows.net/pictures/face4.png",
  "https://insidernetpictures.blob.core.windows.net/pictures/face5.png",
  "https://insidernetpictures.blob.core.windows.net/pictures/face6.png"
];

var promiselist = images.map(callDetectAPI);
Promise.all(promiselist)
.then(result => {
  console.log(result);
  return callGroupAPI(result);
})
.then(group => console.log(JSON.parse(group)));

Detect APIを呼び出して、faceId値を取得し、それを用いてGroup APIを呼び出すコード(JavaScript)

 簡単にコードの説明をしておこう。まず、ここでは画像ファイルのURLを含んだ配列を用意して(face1.pngが配列にないのは、うまく顔検出ができなかったため)、それにcallDetectAPI関数を適用している。callDetectAPI関数はJavaScriptのPromiseオブジェクトを返すようになっていて、呼び出し完了時にはfaceId値が得られるようになっている。そして、Promise.allメソッドを使って、配列の全要素のfaceId値が得られるのを待機する。

 全てのfaceId値がそろったら、callGroupAPI関数を呼び出す。Group APIの詳細な仕様はドキュメントをご覧いただくとして、簡単にいえば、リクエストボディーにfaceId値を格納した配列を指定して、呼び出せばよい。返送される値は例えば、次のようなものになる。

{
  "groups": [
    [
      "faceIdその1",
      "faceIdその2",
    ],
    [
      "faceIdその3",
      "faceIdその4",
    ]
  ],
  "messyGroup": [
    "faceIdその5",
  ]
}


Group APIが返す値

 groupsプロパティには、グループ化された画像が配列の配列として格納される。判断できなかったものはmessyGroupプロパティに格納される。上の例であれば、2つのグループに画像がグループ化されたということになる。

 実際に上のコードを実行した結果を以下に示す。

> node facegrouping.js
[ '37a06702-e803-48b6-a768-61b21dc6ac62',
  '642e6bc2-6368-4859-a738-7000d21b582e',
  '5e9269e9-075f-40df-83ea-6721fbb73352',
  '9cdc5a92-4484-419c-aa7f-69239fc49c3f',
  '74c865ee-4995-4430-857a-cd45f41ba503' ]
{ groups:
   [ [ '5e9269e9-075f-40df-83ea-6721fbb73352',
       '74c865ee-4995-4430-857a-cd45f41ba503',
       '37a06702-e803-48b6-a768-61b21dc6ac62' ] ],
  messyGroup:
   [ '642e6bc2-6368-4859-a738-7000d21b582e',
     '9cdc5a92-4484-419c-aa7f-69239fc49c3f' ] }


実行結果

 最初の出力は、得られた画像ファイルのfaceId値だ(24時間有効)。その次が、グループ化の結果である。出力結果を見ると分かるが、groupsプロパティに配列が1つしかないことから、うまくグループ化ができていない。上のコードで画像ファイルのURLの配列に、同じURLを含めるようにすると、次のように複数のグループが得られたので、おそらくは画像ファイルの選定がよくなかったのだと思われる(つまり、Group APIの動作自体に問題はなさそうだ)。

> node facegrouping.js
[ '37a06702-e803-48b6-a768-61b21dc6ac62',
  '642e6bc2-6368-4859-a738-7000d21b582e',
  '5e9269e9-075f-40df-83ea-6721fbb73352',
  '9cdc5a92-4484-419c-aa7f-69239fc49c3f',
  '74c865ee-4995-4430-857a-cd45f41ba503',
  '37a06702-e803-48b6-a768-61b21dc6ac62',
  '642e6bc2-6368-4859-a738-7000d21b582e',
  '5e9269e9-075f-40df-83ea-6721fbb73352',
  '9cdc5a92-4484-419c-aa7f-69239fc49c3f',
  '74c865ee-4995-4430-857a-cd45f41ba503' ]
{ groups:
   [ [ '5e9269e9-075f-40df-83ea-6721fbb73352',
       '5e9269e9-075f-40df-83ea-6721fbb73352',
       '74c865ee-4995-4430-857a-cd45f41ba503',
       '74c865ee-4995-4430-857a-cd45f41ba503',
       '37a06702-e803-48b6-a768-61b21dc6ac62',
       '37a06702-e803-48b6-a768-61b21dc6ac62' ],
     [ '642e6bc2-6368-4859-a738-7000d21b582e',
       '642e6bc2-6368-4859-a738-7000d21b582e' ],
     [ '9cdc5a92-4484-419c-aa7f-69239fc49c3f',
       '9cdc5a92-4484-419c-aa7f-69239fc49c3f' ] ],
  messyGroup: [] }


今度はグループ化がうまくいった

 興味のある方は、上のコードを利用して、ご自分でも画像ファイルのグループ化をしてみよう。


 Face APIは画像ファイルから顔を検出したり、グループ化したりできる。本稿では触れなかったが、faceId値あるいは画像ファイルを保存した「フェースリスト」から、指定した顔をよく似たものを選別したり、「これは誰それの顔」と個人を特定したりもできる。簡単なAPI呼び出しでこうした処理を行えるので、興味のある方はぜひ使ってみよう。

参考資料

  • Face API: Face APIのトップページ
  • Face API JavaScript Quick Starts: クイックスタートページ。JavaScriptだけではなく、さまざまな言語でFace APIを使うための基本が説明されている
  • Face API - V1.0: Face APIが提供するAPIの一覧とドキュメント

「Dev Basics/Keyword」のインデックス

Dev Basics/Keyword

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。