Azureの管理ポータルでの設定は省略。
HTMLファイルのサンプル。
カメラつき端末のHTML5対応ブラウザの利用が前提。
httpdのドキュメントルート下の /cognitive/ に配置される前提。
なお、ここで利用するPHPファイルは「
Azure Face APIサンプル」を参照。
face_api2.html
----- ここから -----
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="robots" content="noindex,nofollow" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Face API (with camera)</title>
<link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous" />
<style>
<!--
@media all {
.page-title {
color: #555555;
font-size: x-large;
font-weight: bold;
text-shadow: 1px 1px 1px #999999;
}
#canvas {
display: none;
}
#result {
font-size: large;
font-weight: bold;
text-shadow: 1px 1px 1px #333333;
}
}
@media screen and (max-width: 480px) {
#player {
width: 90%;
width: 90vw;
}
#canvas {
display: none;
width: 90%;
width: 90vw;
}
}
-->
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-12">
<nav class="navbar navbar-expand-sm navbar-dark bg-dark">
<a class="navbar-brand" href="/cognitive/">Cognitive Services Examples</a>
</nav>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<h3 class="page-title">Face API (with camera)</h3>
</div>
</div>
<br />
<div class="row">
<div class="col-sm-12">
<strong> カメラのある端末でかつHTML5対応ブラウザでこのページを表示し、カメラに顔を向け「カメラで撮影」ボタンをクリックしてください。</strong>
<div class="card">
<div class="card-body">
<button type="button" id="submit-btn" class="btn btn-primary">カメラで撮影</button>
<button type="button" id="reset-btn" class="btn btn-info">リセット</button>
</div>
</div>
</div>
</div>
<br />
<div class="row">
<div class="col-sm-12">
<div class="mx-auto" style="width: 100%;">
<video id="player" controls playsinline muted autoplay></video>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<canvas id="canvas"></canvas>
</div>
</div>
<br />
<div class="row">
<div class="col-sm-5">
<div id="result"></div>
</div>
</div>
<br />
</div>
<!-- template -->
<script type="text/template" id="result-table-template">
<table class="table table-bordered">
<tr>
<td colspan="2">性別</td><td><div class="float-sm-right"><%= gender %></div></td>
</tr>
<tr>
<td colspan="2">年齢</td><td><div class="float-sm-right"><%= age %></div></td>
</tr>
<tr>
<td colspan="2">眼鏡</td><td><div class="float-sm-right"><%= glasses %></div></td>
</tr>
<tr>
<td rowspan="8">感情</td><td>Anger (怒り)</td><td><div class="float-sm-right"><%= anger %></div></td>
</tr>
<tr>
<td>Contempt (軽蔑)</td><td><div class="float-sm-right"><%= contempt %></div></td>
</tr>
<tr>
<td>Disgust (嫌悪)</td><td><div class="float-sm-right"><%= disgust %></div></td>
</tr>
<tr>
<td>Fear (恐怖)</td><td><div class="float-sm-right"><%= fear %></div></td>
</tr>
<tr>
<td>Happiness (幸福)</td><td><div class="float-sm-right"><%= happiness %></div></td>
</tr>
<tr>
<td>Neutral (ニュートラル)</td><td><div class="float-sm-right"><%= neutral %></div></td>
</tr>
<tr>
<td>Sadness (悲しみ)</td><td><div class="float-sm-right"><%= sadness %></div></td>
</tr>
<tr>
<td>Surprise (驚き)</td><td><div class="float-sm-right"><%= surprise %></div></td>
</tr>
<tr>
<td rowspan="2">化粧</td><td>目</td><td><div class="float-sm-right"><%= eyeMakeup %></div></td>
</tr>
<tr>
<td>口</td><td><div class="float-sm-right"><%= lipMakeup %></div></td>
</tr>
</table>
</script>
<!-- javascript -->
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js" integrity="sha256-G7A4JrJjJlFqP0yamznwPjAApIKPkadeHfyIwiaa9e0=" crossorigin="anonymous"></script>
<script src="//code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" integrity="sha256-9wRM03dUw6ABCs+AU69WbK33oktrlXamEXMvxUaF+KU=" crossorigin="anonymous"></script>
<script>
(function() {
"use strict";
const root = this;
const _ = root._;
const $ = root.jQuery;
const apiUrl = '/cognitive/face_api.php';
const resultTableTemplate
= _.template($('#result-table-template').html());
const mathRound = function(val) {
return (val * 100).toFixed(2);
};
const toBlob = function(base64, type) {
const bin = atob(base64.replace(/^.*,/, ''));
const buffer = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; i++) {
buffer[i] = bin.charCodeAt(i);
}
const blob = new Blob([buffer.buffer], {
type: type
});
return blob;
};
$(function() {
const player = document.getElementById('player');
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
const fd = new FormData();
const maxPixels = 4096;
navigator.mediaDevices.getUserMedia({
audio: false,
video: {
facingMode: 'user'
}
}).then(function(stream) {
player.srcObject = stream;
});
$('#reset-btn').on('click', function() {
$('#result').html("");
$('#canvas').hide();
$('#player').show();
});
$('#submit-btn').on('click', function() {
$('#result').html("");
$('#player').hide();
$('#canvas').show();
const date = new Date();
const fileName = date.getTime() + '.jpg';
let scale = 1;
if (player.videoWidth > player.videoHeight && player.videoWidth > maxPixels) {
scale = maxPixels / player.videoWidth;
}
else if (player.videoWidth < player.videoHeight && player.videoHeight > maxPixels) {
scale = maxPixels / player.videoHeight;
}
canvas.width = player.videoWidth * scale;
canvas.height = player.videoHeight * scale;
context.drawImage(player, 0, 0, player.videoWidth, player.videoHeight, 0, 0, canvas.width, canvas.height);
fd.append("img-file", toBlob(canvas.toDataURL('image/jpeg'), 'image/jpeg'), fileName);
$.blockUI({
message : '<img src="/common/img/gif-load.gif" />',
css : {
color : '',
border : '',
backgroundColor : ''
},
overlayCSS : {
backgroundColor: '#FFFFFF'
}
});
$.ajax({
url : apiUrl + '?api_type=detect&returnFaceAttributes=age,gender,smile,facialHair,glasses,headPose,emotion,hair,makeup,accessories',
type : "POST",
data: fd,
processData: false,
contentType : false,
dataType : "json"
}).done(function(data, status, xhr) {
for (let i in data) {
$('#result').append(
'<span id="result' + (i + 1) + '">'
+ resultTableTemplate({
gender : data[i].faceAttributes.gender === 'male' ? '男性' : '女性',
age : data[i].faceAttributes.age,
glasses : data[i].faceAttributes.glasses === 'NoGlasses' ? 'なし' : 'あり',
anger : mathRound(data[i].faceAttributes.emotion.anger),
contempt : mathRound(data[i].faceAttributes.emotion.contempt),
disgust : mathRound(data[i].faceAttributes.emotion.disgust),
fear : mathRound(data[i].faceAttributes.emotion.fear),
happiness : mathRound(data[i].faceAttributes.emotion.happiness),
neutral : mathRound(data[i].faceAttributes.emotion.neutral),
sadness : mathRound(data[i].faceAttributes.emotion.sadness),
surprise : mathRound(data[i].faceAttributes.emotion.surprise),
eyeMakeup : data[i].faceAttributes.makeup.eyeMakeup === true ? 'あり' : 'なし',
lipMakeup : data[i].faceAttributes.makeup.lipMakeup === true ? 'あり' : 'なし',
})
+ '</span><br />'
);
context.beginPath();
if (i % 7 === 0) {
context.strokeStyle = 'rgb(255, 0, 0)';
$('#result' + (i + 1)).css('color', '#FF0000');
}
else if (i % 7 === 1) {
context.strokeStyle = 'rgb(0, 255, 0)';
$('#result' + (i + 1)).css('color', '#00FF00');
}
else if (i % 7 === 2) {
context.strokeStyle = 'rgb(0, 0, 255)';
$('#result' + (i + 1)).css('color', '#0000FF');
}
else if (i % 7 === 3) {
context.strokeStyle = 'rgb(0, 255, 255)';
$('#result' + (i + 1)).css('color', '#00FFFF');
}
else if (i % 7 === 4) {
context.strokeStyle = 'rgb(255, 255, 0)';
$('#result' + (i + 1)).css('color', '#FFFF00');
}
else if (i % 7 === 5) {
context.strokeStyle = 'rgb(255, 0, 255)';
$('#result' + (i + 1)).css('color', '#FF00FF');
}
else if (i % 7 === 6) {
context.strokeStyle = 'rgb(0, 0, 0)';
$('#result' + (i + 1)).css('color', '#000000');
}
context.strokeRect(data[i].faceRectangle.left, data[i].faceRectangle.top, data[i].faceRectangle.width, data[i].faceRectangle.height);
}
}).fail(function(xhr, status, error) {
console.log(JSON.stringify(xhr));
console.log(status);
console.log(error);
}).always(function() {
$(document).ajaxStop($.unblockUI);
});
});
});
}).call(this);
</script>
</body>
</html>
----- ここまで -----