Edited at

「笑顔が素敵かどうか」をAIに診断してもらうアプリを作ってみた(Emotion API)

More than 1 year has passed since last update.

この記事は

です。

人に会う仕事、接客する仕事に携わる人たちは、表情にとても気を使っています。

毎日鏡に向かって笑顔を作り、良い笑顔ができているかどうか、チェックする人も多いと聞きます。

しかし、自分が作った笑顔が魅力的かどうか、自分自身ではなかなか判断がつかないもの。

そこで、MS AzureCognitive Services の一つ、Emotion API を利用して

「あなたの笑顔が魅力的かどうか、AIに判断してもらおう!」

という (お遊び) アプリを作ってみました。


実際の挙動

フォームから、自分の表情を写真で撮影し、アプリにアップロードします。

(ここではサンプルの写真を利用。「ぱくたそ」「フォト蔵」さんからお借りしました。)


サンプル1

sc_1.jpg

最初の写真。とても素敵な笑顔です。

sc_2.jpg

AIも、「最高の笑顔です」と認識してくれました。


サンプル2

sc_3.jpg

ややアルカイックスマイル気味ですが、素敵な笑顔です。

sc_4.jpg

やはり良い笑顔と判定してくれたようです。


サンプル3

sc_5.jpg

どうすれば人々は苦しみから開放されるのか、悩んでいるのでしょうか。

憂いを秘めた表情です。

sc_6.jpg

AIは「お疲れのご様子ですね」と判断したようです。

このように、素敵な笑顔を作れているかどうか、アプリ が診断してくれます。


仕様

Emotion API に対して、人間の表情が写っている写真を投げると、JSONのレスポンスデータが返って来ます。

emotion_top.png

画像は、Emotion API のページからキャプチャしたものです。サンプルの写真と、写真に対する返り値のJSONが表示されています。このJSONデータには、表情から感情を読み取り、各種の感情をパラメーター化した結果が含まれています。

 JSON:

[
{
"faceRectangle": {
"top": 114,
"left": 212,
"width": 65,
"height": 65
},
"scores": {
"anger": 1.0570484E-08,
"contempt": 1.52679547E-09,
"disgust": 1.60232943E-07,
"fear": 6.00660363E-12,
"happiness": 0.9999998,
"neutral": 9.449728E-09,
"sadness": 1.23025981E-08,
"surprise": 9.91396E-10
}
},

レスポンスデータの「scores」には、怒り(anger)、恐れ(fear)、幸せ(hapiness)などの各種パラメーターが、最低値0-最高値1の間の値で付与されています。

今回のスマイルチェッカーでは


  • 良い笑顔 = 幸せ度数が高い笑顔

と定義して、返り値のJSONから「hapiness」の値を抽出。hapiness値が高い= 素敵な笑顔、として判断するようにしました。


Emotion API の準備

まず最初に、Emotion API を利用できるよう、Azure からAPIキーを発行します。Azure のダッシュボードから

「新規」を選び、検索から「emotion」と入力。Emotion API を選択します。

emo_1.png

Emotion API を選択して、作成ボタンをクリックします。

emo_2.png

各設定項目を入力、選択します。

emo_3.png

Emotions API がデプロイされたら、APIキーを取得します。

emo_4.png

Emotion API の使い方は以下に詳しく記述されています。


実際のコード

先程取得したAPIキーを利用して、コードを書きます。

今回のサンプルではシンプルに


  • html5 のFile APIで、写真を取得(撮影)

  • 取得した写真を、Emotion API に送信

  • 返り値からhapinessの値を取得

  • 条件分岐で、出力するメッセージを変更

としました。Azure への画層送信やサムネイルの表示など、画像の各種処理には jQueryを使ってます。

※サンプル実装ということで、APIキーを直接html内に書く形にしましたが、APIキーが視認できる状態は危険ですのでご注意ください。第三者に勝手に使われてしまいます

<!DOCTYPE html>

<html lang="ja">
<head>
<title>スマイルチェッカー</title>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1" name="viewport">
</head>
<body>
<div class="container" id="container">
<h2>スマイルチェッカー</h2>
<div id="message"></div>
<div id="content">
<p><input id="fileToUpload" name="upload" type="file"></p>
</div>
</div>
<script src="https://code.jquery.com/jquery-2.1.4.min.js">
</script>
<script>

var html = '';

$(function() {

$('input[type=file]').after('<span id=\"image\"><\/span>');

$('input[type=file]').change(function() {

var file = $(this).prop('files')[0];

if (!file.type.match('image.*')) {
$(this).val('');
$('span').html('');
return;
}

var reader = new FileReader();

reader.onload = function() {
var img_src = $('<br><img height=\"300\">').attr('src', reader.result);
$('span').html(img_src);
}
reader.readAsDataURL(file);

$.ajax({
url: "https://westus.api.cognitive.microsoft.com/emotion/v1.0/recognize",
beforeSend: function(xhrObj){
// Request headers
xhrObj.setRequestHeader("Content-Type","application/octet-stream");
xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key","APIキーを記述する");
},
type: "POST",
data: file,
processData: false,
})
.done(function(data) {

var smileScore = data["0"].scores.happiness;

if(smileScore > 0.99) {
var message = "最高の笑顔です!あなたの笑顔はすべての人を幸せにすることでしょう。";
}

if(0.7 <= smileScore && smileScore <= 0.99) {
var message = "良い笑顔です!あなたの笑顔はみんなをホッとさせることでしょう。";
}

if(smileScore < 0.7) {
var message = "疲れているのかな?早めに睡眠を取って、明日に備えましょう。";
}

alert(message);

})
.fail(function() {
alert("error");
});
});
});
</script>
</body>
</html>


Monacaでスマホアプリ用にアレンジする

上記のコードを元に、Monacaでスマホアプリ用に整形します。

Monacaは、スマートフォンアプリ開発のフレームワークです。

sc_7.png

ちょっとだけ Onsen UI を使いました。

<!DOCTYPE html>

<html>
<head>
<title>スマイルチェッカー</title>
</head>
<body>
-
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1" name="viewport">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<meta content="default-src * data: gap: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'" http-equiv="Content-Security-Policy">
<script src="components/loader.js">
</script>
<script src="lib/onsenui/js/onsenui.min.js">
</script>
<link href="components/loader.css" rel="stylesheet">
<link href="lib/onsenui/css/onsenui.css" rel="stylesheet">
<link href="lib/onsenui/css/onsen-css-components.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="stylesheet">
<div class="center">
スマイルチェッカー
</div>
<div class="container" id="container">
<div id="message"></div>
<div id="content">
<div class="form-group">
<input class="form-control-file" id="diletoUpload" name="upload" type="file">
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-2.1.4.min.js">
</script>
<script>

$(function() {

$('input[type=file]').after('<span id=\"image\"><\/span>');

$('input[type=file]').change(function() {

var file = $(this).prop('files')[0];

if (!file.type.match('image.*')) {
$(this).val('');
$('span').html('');
return;
}

var reader = new FileReader();

reader.onload = function() {
var img_src = $('<br><img width=\"300\">').attr('src', reader.result);
$('span').html(img_src);
}
reader.readAsDataURL(file);

$.ajax({
url: "https://westus.api.cognitive.microsoft.com/emotion/v1.0/recognize",
beforeSend: function(xhrObj){
// Request headers
xhrObj.setRequestHeader("Content-Type","application/octet-stream");
xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key","APIキーを記述する");
},
type: "POST",
data: file,
processData: false,
})
.done(function(data) {

var smileScore = data["0"].scores.happiness;

if(smileScore > 0.99) {
var message = "最高の笑顔です!あなたの笑顔はすべての人を幸せにすることでしょう。";
}

if(0.7 <= smileScore && smileScore <= 0.99) {
var message = "良い笑顔です!あなたの笑顔はみんなをホッとさせることでしょう。";
}

if(smileScore < 0.7) {
var message = "疲れているのかな?早めに睡眠を取って、明日に備えましょう。";
}

alert(message);

})
.fail(function() {
alert("error");
});

});

});

</script>
</body>
</html>


応用

今回は単純にEmotion API の「hapiness」の値だけを使って条件分岐しました。より複雑に判断するなら、angerなど、他のパラメーターも考慮して判断するのも良いかもしれません。

また、写真と同時に、一言コメントを記述して、Movable Type やmBaaS系のサービスに笑顔+コメント付きで投稿する「笑顔日記」的なサービスも面白いかも。

他にもビジネスになりそうなアイディアはいくつかあるのですが、事業化をご希望の方はご連絡ください(嘘)