#■はじめに:Azure Cognitive Service - Face
Azure Cognitive Service の中の Face という面白いクラウドAIサービスがあります。公式サイトの紹介文では、
アプリに顔認識を埋め込んで、高度なセキュリティで保護されたシームレスなユーザー エクスペリエンスを実現できます。機械学習に関する専門知識は不要です。画像内の顔と属性を認識する顔検出、最大 100 万人のプライベート リポジトリ内の人物と照合する個人識別、さまざまな表情 (喜び、軽蔑、中立、恐怖など) を検出する感情認識、画像内での似た顔の認識とグループ化などの機能があります。
とあります。
普段、WordPressでは、素材画像や記事作成時に画像を登録することが多く、結構、顔の画像もあったりするので、Faceサービスで登録された顔画像を解析してみると、結構、面白そうな感じがしたので、早速、WordPressに実装してみました。
注:WordPress環境は、既に構築済みという前提での記事となります。WordPressとは何ぞや?という方は、下記リンクをご参照ください。
・Wikipedia:WordPress
・WordPress公式サイト
#■類似のCognitive Service
Faceの公式ドキュメントには、
注意:顔検出機能は Computer Vision サービスでもご利用いただけます。 ただし、顔のデータを使ってさらに操作を行いたい場合は、代わりにこのサービスを使用する必要があります。
とあります。
●Computer Vision:こちらのサービスでも顔の検出は可能なのですが、
・年齢
・性別
・顔の位置
のみ検出してくれるのですが、Faceサービスは、顔画像から、
・メガネをかけているか
・笑顔 or 怒り顔
などなど、色々な特徴を検出してくれるスグレモノです。
●Content Moderator:こちらのサービスでも画像から色々と検出してくれるのですが、公式ドキュメントによると、
Content Moderator のコンピューター支援型画像モデレーションとレビュー ツールを使用して、成人向けコンテンツとわいせつなコンテンツの画像をモデレートします。 テキスト コンテンツの画像をスキャンしてそのテキストを抽出し、顔を検出します。 カスタム リストと画像を照合し、さらにアクションを実行できます。
と記載がありますが、こちらも試してみたいですが、xxxxxxxxな画像はストックしておりませんので・・・・・。
#■Face APIで検出してくれる項目
公式ドキュメントでは、Face APIで検出してくれる項目の一覧が記載されています。
項目 | 概要 | 詳細 |
---|---|---|
年齢 | 特定の顔の推定年齢 | |
ぼかし | 画像内の顔のぼかしの程度 | この属性は、0 から 1 までの間の値と、非公式の評価 (低、中、または高) を返します |
感情 | 感情のリストと特定の顔に対する検出の信頼度 | 信頼度スコアは正規化され、すべての感情スコアの合計は 1 になります。返される感情は、喜び、悲しみ、中立、怒り、軽蔑、嫌悪感、驚き、恐怖です |
露出 | 画像内の顔の露出の程度 | この属性は、0 から 1 までの間の値と、非公式の評価 (underExposure、goodExposure、または overExposure) を返します |
顔ひげ | 特定の顔について推定される顔ひげの有無と長さ | |
性別 | 特定の顔について推定される性別 | 可能な値は、男性、女性、および性別なしです |
眼鏡 | 特定の顔に眼鏡があるかどうか | 可能な値は、NoGlasses、ReadingGlasses、Sunglasses、および Swimming Goggles です |
髪の毛 | 顔の髪質 | この属性は、髪の毛が見えるかどうか、はげが検出されたかどうか、どのような髪の色が検出されたかを示します |
頭部姿勢 | 3次元空間での顔の向き | この属性は、ピッチ、ロール、およびヨー角度 (度数) で表現されます。 値の範囲は、それぞれ -90 度から 90 度、- 90 度から 90 度、-90 度から 90 度です |
化粧 | 顔に化粧があるかどうか | この属性は eyeMakeup および lipMakeup についてのブール値を返します |
ノイズ | 顔の画像で検出された視覚ノイズ | この属性は、0 から 1 までの間の値と、非公式の評価 (低、中、または高) を返します |
オクルージョン | 顔のパーツをブロックするオブジェクトがあるかどうか | この属性は、eyeOccluded、foreheadOccluded、および mouthOccluded についてのブール値を返します |
笑顔 | 特定の顔の笑顔表現 | この値は、0 (笑顔なし) から 1 (鮮明な笑顔) までです |
#■注意点
公式ドキュメントに注意点が記載されています。
重要:顔属性は統計的アルゴリズムを使用して予測されます。 必ずしも正確とは限りません。 属性データに基づいて意思決定を行う場合は、注意が必要です。
#■WordPress実装時の検討事項
FaceサービスをWordPressに実装するにあたり、WordPressからFace APIを叩く際の検討事項についてです。
●WordPress側
1.デザインテンプレートにFace APIを叩く処理を実装して固定ページに実装
2.WordPress管理画面に機能追加
3.プラグインを独自開発してWordPress上のどこでも使えるように実装
の選択肢がありますが、今回は1と2で実装することにしました。
●Face APIを叩く選択肢
1.公式サイトのクイックスタートで紹介されているPHPのサンプルを参考にFace APIを叩く
2.公式サイトのクイックスタートで紹介されているJavascriptのサンプルを参考にFace APIを叩く
3.cURLでFace APIを叩く
の選択肢がありますが、PHPのサンプルを見ると、PearのHTTP_Request2が必要だったり、JavascriptのサンプルだとJqueryが必要だったりするのと、1つの画像に対してFace APIを叩くだけのサンプルでしたので、今回は、WordPressに登録されている画像全部に対して、cURLでFace APIを叩くことにしました。
●Face APIに投げる画像
公式ドキュメントには、
・サポートされている入力画像形式は、JPEG、PNG、GIF (最初のフレーム)、BMP です。
・画像ファイル サイズは 6 MB 以内であることが必要です。
・検出可能な顔のサイズの範囲は、36 x 36 ~ 4096 x 4096 ピクセルです。 この範囲に含まれない顔は検出されません。
・技術的な課題のために、一部の顔を検出できない場合があります。 顔の角度 (頭部姿勢) や顔のオクルージョン (顔のパーツをブロックするサングラスや手などの物体) が極端に大きい場合、検出に影響することがあります。 顔が正面または正面に近い方向を向いているときに、最善の結果が得られます。
と記載されていますので、画像ファイルのサイズや天地サイズに注意する必要があります。
#■作業手順01:Azureリソース作成
●Azure Faceのリソース作成
まずは、AzureポータルでFaceリソースを作成します。
●キーとエンドポイント
cURLで必要なのでメモしておきます。
#■作業手順02:WordPressに実装:1.デザインテンプレートにFace APIを叩く処理を実装して固定ページに実装
WordPressへの組み込み方法は、色々ありますが、今回は使っているデザインテーマにデザインテンプレートを1つ追加、そこにFace APIを叩くPHPコードを記述していきます。(2020/12/12:WordPress管理画面への追加方法を【追記】しました)
●デザインテンプレート作成:
最初に、azure-face-api.phpというファイル名で作成し、SFTPなどを使って、WordPressが稼働しているサーバの
・/wp-content/themes/xxxxxx/azure-face-api.php
にアップロードしておきます。なお、デザインテンプレートですので、下記の内容を記述しておきます。
<?php
//Template Name:Azure Face API
/**
*
* The template for displaying all azure-face-api
*
*/
get_header();
?>
//ここにコードを記述します
<?php
get_footer();
WordPress管理画面でテンプレートが読み込まれていることを確認します。
●固定ページを作成してデザインテンプレートを適用
次に、WordPress管理画面->固定ページ->新規追加で、固定ページを作成します。赤枠の[ページ属性]の設定ウィジェットで、作成したデザインテンプレートを適用します。
#■cURL書式
####●Request URL
基本の書式です。
Request URL:
https://{endpoint}/face/v1.0/detect[?returnFaceId][&returnFaceLandmarks][&returnFaceAttributes][&recognitionModel][&returnRecognitionModel][&detectionModel]
####●cURL書式
公式サイトに掲載されています(エンドポイントが古いママです)。
curl -v -X POST "https://xxxxxxxxxx.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes={string}&recognitionModel=recognition_03&returnRecognitionModel=false&detectionModel=detection_02" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: {subscription key}" --data-ascii "{body}"
####●今回のFace APIに投げる予定のcURL
curl -H "Ocp-Apim-Subscription-Key: xxxxxxxxxxxxxxxxxxxxx" "https://xxxxxxxxxxxx.xxxxxxxxxx.azure.com/face/v1.0/detect?detectionModel=detection_02&returnFaceId=true&returnFaceLandmarks=false" -H "Content-Type: application/json" --data-ascii "{\"url\":\"https://xxxxxxxxxxx/xxxxxxxxxx.jpg\"}"
curl -H "Ocp-Apim-Subscription-Key: xxxxxxxxxxxxxxxxxxxxx" "https://xxxxxxxxxxxx.xxxxxxxxxx.azure.com/face/v1.0/detect?detectionModel=detection_01&returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise" -H "Content-Type: application/json" --data-ascii "{\"url\":\"https://xxxxxxxxxxx/xxxxxxxxxx.jpg\"}"
#■PHPコード
●デザインテンプレート上にコーディング
次に、WordPress管理画面->外観->テーマエディタ画面に遷移、先程作成したデザインテンプレートにコードを埋め込みます。
●PHPコード
今回、WordPressに実装したPHPのコードですが、
・Face APIのエンドポイントやキーを登録
・WordPressに登録されている画像をお好みの件数を取得
・ループで一覧表示
・各画像に対してFaceサービスAPIを叩く処理
・JSONを見やすく整形
という内容になっています。
<?php
//Template Name:Azure Face API
/**
*
* The template for displaying all azure-face-api
*
*/
get_header();
?>
<div id="content" class="site-content">
<div class="container">
<?php
$endpoint = "https://xxxxxxxxxxxxxxxxxxx.azure.com";
$baseurl01 = $endpoint . "/face/v1.0/detect?detectionModel=detection_02&returnFaceId=true&returnFaceLandmarks=false"; //顔の情報取得
$baseurl02 = $endpoint . "/face/v1.0/detect?detectionModel=detection_01&returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise"; //顔の属性抽出
$api_headers = array(
"Ocp-Apim-Subscription-Key: xxxxxxxxxxxxxxxxx",
"Content-Type: application/json; --data-ascii"
);
$args = array(
'post_type' => 'attachment',
'post_status' =>'inherit',
'post_mime_type' => 'image',
'posts_per_page' => 4 //値を小さくします
);
$image = new WP_Query($args);
?>
<h1>Face API Demo</h1>
<section>
<table border="1">
<tr>
<th>File Name</th><th>Image</th><th>Face API Response</th>
</tr>
<?php if ($image->have_posts()) : ?>
<?php while ($image->have_posts()) : $image->the_post(); ?>
<tr>
<td width="30%"><?php the_title(); ?></td>
<td width="20%"><?php echo the_attachment_link(key($images)); ?></td>
<td>
<div align="left">
<?php
$image_url = wp_get_attachment_url(post_custom('image'));
$facecurl = curl_init();
$faceparams = array();
$faceparams["url"] = $image_url;
$json = json_encode($faceparams);
curl_setopt($facecurl, CURLOPT_URL, $baseurl01);
curl_setopt($facecurl, CURLINFO_HEADER_OUT, true);
curl_setopt($facecurl, CURLOPT_HTTPHEADER, $api_headers);
curl_setopt($facecurl, CURLOPT_POSTFIELDS, $json);
curl_setopt($facecurl, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($facecurl);
curl_close($facecurl);
echo "<pre>".json_encode(json_decode($res), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
?>
</div>
</td>
</tr>
<?php endwhile; ?>
<?php endif; ?>
</table>
</section>
<?php wp_reset_postdata(); ?>
</div>
</div>
<?php
get_footer();
注:posts_per_pageの値を大きくし過ぎると、大量の画像に対して一気にFaceサービスAPIを叩くことになってしまい、怒られます(後述)
#■レスポンス01:顔検出
curl_setoptをbaseurl01にしてAPIを叩いています。いい感じに応答がありますね。
●レスポンスについて
一番上の画像(ポーズを決めた執刀医)の他、二番目の画像(歯の治療中の顔)は顔検出が難しそうですが、きちんとレスポンスが返却されますね。さらに、三番目の画像(歯科医と患者)の複数の人物が写っている画像も、きちんと人数分の顔検出のレスポンスが返却されますね。
[
{
"faceId": "e58726bc-651d-421e-836a-b68e668590b5",
"faceRectangle": {
"top": 218,
"left": 473,
"width": 128,
"height": 128
}
},
{
"faceId": "21e6477a-6ccb-41ad-bd83-5faa27ad4ece",
"faceRectangle": {
"top": 58,
"left": 419,
"width": 106,
"height": 142
}
}
]
#■レスポンス02:顔の属性抽出
curl_setoptをbaseurl02に変更してAPIを叩いています。いい感じに応答がありますね。
[
{
"faceId": "7c5ca8a0-fa5b-4440-9b3a-f81bd8806a47",
"faceRectangle": {
"top": 36,
"left": 48,
"width": 40,
"height": 40
},
"faceAttributes": {
"smile": 0.017,
"headPose": {
"pitch": 1,
"roll": -2.1,
"yaw": -39.9
},
"gender": "male",
"age": 37,
"facialHair": {
"moustache": 0.4,
"beard": 0.4,
"sideburns": 0.1
},
"glasses": "NoGlasses",
"emotion": {
"anger": 0,
"contempt": 0.001,
"disgust": 0,
"fear": 0,
"happiness": 0.017,
"neutral": 0.979,
"sadness": 0.002,
"surprise": 0
},
"blur": {
"blurLevel": "low",
"value": 0
},
"exposure": {
"exposureLevel": "overExposure",
"value": 0.9
},
"noise": {
"noiseLevel": "low",
"value": 0
},
"makeup": {
"eyeMakeup": false,
"lipMakeup": false
},
"accessories": [
{
"type": "headwear",
"confidence": 0.99
}
],
"occlusion": {
"foreheadOccluded": true,
"eyeOccluded": false,
"mouthOccluded": false
},
"hair": {
"bald": 0,
"invisible": true,
"hairColor": []
}
}
}
]
#■レスポンス03:検出できない事象
問題発生です。一番目の執刀医の画像の顔の検出と特徴抽出はOKだったのですが、
・二番目の口を開けている歯の治療中の患者の画像:顔の検出と特徴抽出NG
・歯科医と患者の複数の人物の画像:顔の検出と特徴抽出NG
・ポーズを決めたベテラン医師の画像:顔の検出と特徴抽出NG
という結果になりました。
Facen 公式ドキュメントにも注意書きがありますが、
技術的な課題のために、一部の顔を検出できない場合があります。 顔の角度 (頭部姿勢) や顔のオクルージョン (顔のパーツをブロックするサングラスや手などの物体) が極端に大きい場合、検出に影響することがあります。 顔が正面または正面に近い方向を向いているときに、最善の結果が得られます。
ポーズを決めたベテラン医師の画像は、顔のパーツをブロックするサングラスや手などの物体なので、特徴抽出NGなのですね・・・・・。
#■怒られた
posts_per_pageの値を大きくして実行したところ、大量の画像に対して一気にFaceサービスAPIを叩いてしまい、怒られてしまいました。
Response 429
application/json
{
"error": {
"code": 429,
"message": "Request to the Face - Detect Operation under Face API - v1.0 have exceeded rate limit of your current Face F0 pricing tier. Please retry after 14 seconds. To increase your rate limit switch to a paid tier."
}
}
F0で稼働させているので、チビチビ消費しないと・・・・・。
#■まとめ
cURLでAPIを叩くことができるので、お手軽に実装出来ました。時間があれば、APIから返却されたJSONレスポンスから各種データを切り出して、CSSを生成して顔画像に顔位置の枠を表示させたりしたいですね。
つかいどころ:IoT関連
Raspberry Piに小型カメラをセットして、定期的に撮影して画像を投稿としてWordPressにrest apiで送信して、Face APIで解析できそうですね。
#■謝辞:顔検出に利用した画像について
顔検出に利用した画像はWordPressの無料デザインテーマに付属している画像を使用しました。この場を借りてお礼申し上げます。
・WordPressテーマ:Gutener Medical
・作者: keonthemes
#■追記:実装する場所(2020/12/12追記)
WordPressにFace APIを実装する場所ですが、
●公開エリアに実装する場合:
・WordPressの固定ページに実装:Ultimate Memberプラグインを利用して認証して、ログインした特定ユーザのみ実行可能としましょう
●非公開エリアに実装する場合:
・WordPressの管理画面内に実装、管理画面にアクセス可能なユーザのみ実行可能にしましょう。
こちらもやっておきましょう:エンドポイントへのアクセス制限:
・[Cognitive Services のエンドポイントへのアクセス制限 ~ ファイアウォール機能を試す]
(https://qiita.com/annie/items/9dc39785a429d713327f)
#■追記:WordPress管理画面に機能追加(2020/12/12追記)
WordPress管理画面への追加方法ですが、利用しているデザインテーマのfunctions.phpにPHPコードを記述します。
●WordPress管理画面への実装結果:左メニューの赤枠の箇所に追加されています。
●デザインテーマのfunctions.phpに実装:右メニューの赤枠のfunctions.phpを選択してPHPコードを記述します。
// add azure face api menu
add_action( 'admin_menu', 'azure_face_api_menu_page' );
function azure_face_api_menu_page() {
add_menu_page('Azure Face API', 'Azure Face API', 'manage_options', 'azurefaceapi', 'add_azure_face_api_page', 'dashicons-admin-generic','2');
}
// add azure face api page
function add_azure_face_api_page() {
$endpoint = "https://xxxxxxxxxx.azure.com";
$baseurl01 = $endpoint . "/face/v1.0/detect?detectionModel=detection_02&returnFaceId=true&returnFaceLandmarks=false"; //顔の情報取得
$baseurl02 = $endpoint . "/face/v1.0/detect?detectionModel=detection_01&returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise"; //顔の属性抽出
$api_headers = array(
"Ocp-Apim-Subscription-Key: xxxxxxxxxx",
"Content-Type: application/json; --data-ascii"
);
$args = array(
'post_type' => 'attachment',
'post_status' =>'inherit',
'post_mime_type' => 'image',
'posts_per_page' => 4
);
$image = new WP_Query( $args );
echo '
<h1>Azure Face API</h1>
<table border="1">
<tr>
<th>File Name</th><th>Image</th><th>Face API Response</th>';
if ( $image->have_posts() ) :
while ( $image->have_posts() ) : $image->the_post();
echo '<tr>';
echo '<td width="30%">'; the_title(); echo '</td>';
echo '<td width="20%">'; echo the_attachment_link(key($images)); echo '</td>';
echo '<td><div align="left">';
$image_url = wp_get_attachment_url(post_custom('image'));
$facecurl = curl_init();
$faceparams = array();
$faceparams["url"] = $image_url;
$json = json_encode($faceparams);
curl_setopt($facecurl, CURLOPT_URL, $baseurl02); // If you want to change ENDPOINT
curl_setopt($facecurl, CURLINFO_HEADER_OUT, true);
curl_setopt($facecurl, CURLOPT_HTTPHEADER, $api_headers);
curl_setopt($facecurl, CURLOPT_POSTFIELDS, $json);
curl_setopt($facecurl, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($facecurl);
curl_close($facecurl);
echo "<pre>".json_encode(json_decode($res), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
echo '</div></td>';
echo '</tr>';
endwhile;
endif;
echo '</table>';
wp_reset_postdata();
}
#■リソース
・[クイック スタート:REST API と PHP を使用して画像内の顔を検出する]
(https://docs.microsoft.com/ja-jp/azure/cognitive-services/face/quickstarts/php)
・[クイック スタート:REST API と JavaScript を使用して画像内の顔を検出する]
(https://docs.microsoft.com/ja-jp/azure/cognitive-services/face/quickstarts/javascript)
・[クイック スタート :Face REST API と cURL を使用して画像から顔を検出する]
(https://docs.microsoft.com/ja-jp/azure/cognitive-services/face/quickstarts/curl)
(何故かデッドリンクというか別ページにリダイレクトされます)
・Cognitive Service API Reference:CURLのコードサンプル