JavaScriptで顔認識+年齢推定|Webカメラ×face-api.jsの実装例付き
JavaScriptとface-api.jsを使って、Webカメラからリアルタイムに顔認識し、AIが年齢を推定するブラウザアプリを構築する方法を紹介します。
このページでは、クライアントサイドのみで動作する実装例を掲載しており、顔検出・年齢推定・描画処理までをJavaScriptで完結させています。
「顔認識で年齢を表示するサイトを作りたい」「AIで顔年齢を推定したい」という方におすすめです。
カメラ使用を許可してください。しばらくすると、カメラ映像が表示されます
カメラに顔を映してください。顔を認識してAIが推定した年齢を表示します。マスクは外してください。
(カメラ映像が正しく映らない場合は、リロードしてみてください)
ソースコード
<div class="wait"><img src="./imgs/loading.gif" width="64" height="64"><p>ロード中</p></div>
<div><canvas id="preview"></canvas></div>
<script src="./models/face-api.min.js"></script>
<script>
//TinyFaceDetectorModelを使用する
faceapi.nets.tinyFaceDetector.loadFromUri('./models');
//AgeGenderを使用する
faceapi.nets.ageGenderNet.loadFromUri("./models");
//Expressionを使用する
faceapi.nets.faceExpressionNet.loadFromUri("./models");
window.addEventListener('DOMContentLoaded',function(){
ShowWait();
});
var video,prev,prev_ctx,w,h,nw,nh,img;
window.addEventListener('load',function(event){
glassimg=new Image();
glassimg.addEventListener("load",function(){
nw=glassimg.naturalWidth;
nh=glassimg.naturalHeight;
});
video=document.createElement('video');
video.setAttribute("autoplay","");
video.setAttribute("muted","");
video.setAttribute("playsinline","");
video.onloadedmetadata = function(e){video.play();};
prev=document.getElementById("preview");
prev_ctx=prev.getContext("2d", {willReadFrequently:true});
//左右反転表示させる
prev.style.transform="scaleX(-1)";
//カメラ使用の許可ダイアログが表示される
navigator.mediaDevices.getUserMedia(
//マイクはオフ, カメラの設定 前面カメラを希望する 640×480を希望する
{"audio":false,"video":{"facingMode":"user","width":{"ideal":640},"height":{"ideal":480}}}
).then( //許可された場合
function(stream){
video.srcObject = stream;
//1.0秒後にスキャンする
setTimeout(Scan,1000,true);
}
).catch(
//許可されなかった場合
function(){
HideWait(1);
}
);
function Scan(first){
if(first){
//選択された幅高さ
w=video.videoWidth;
h=video.videoHeight;
//画面上の表示サイズ
prev.style.width="100%";
prev.style.maxWidth="640px";
//内部のサイズ
prev.setAttribute("width",w);
prev.setAttribute("height",h);
HideWait(1);
}
detect()
.then(
function(result){
prev_ctx.drawImage(video,0,0,w,h);
for(i=0;i<result.length;i++){
if(result[i].age&&result[i].expressions){
prev_ctx.beginPath();
prev_ctx.lineWidth=4;
prev_ctx.strokeStyle="#ff0000";
prev_ctx.moveTo(result[i].detection.box.x, result[i].detection.box.y);
prev_ctx.lineTo(result[i].detection.box.x+0, result[i].detection.box.y+result[i].detection.box.height);
prev_ctx.lineTo(result[i].detection.box.x+result[i].detection.box.width, result[i].detection.box.y+result[i].detection.box.height);
prev_ctx.lineTo(result[i].detection.box.x+result[i].detection.box.width, result[i].detection.box.y+0);
prev_ctx.lineTo(result[i].detection.box.x+0, result[i].detection.box.y+0);
prev_ctx.stroke();
prev_ctx.scale(-1, 1);
prev_ctx.font="36px 'MS ゴシック'";
prev_ctx.fillStyle="pink";
let age=Math.round(result[i].age)+"歳 ";
let gender="";
//if(result[i].gender="male"){gender="男性";}
//if(result[i].gender="female"){gender="女性";}
let exps=result[i].expressions.angry;
let expstr="怒り";
if(result[i].expressions.disgusted>exps){
exps=result[i].expressions.disgusted;
expstr="うんざり";
}
if(result[i].expressions.fearful>exps){
exps=result[i].expressions.fearful;
expstr="怯え";
}
if(result[i].expressions.happy>exps){
exps=result[i].expressions.happy;
expstr="幸せ";
}
if(result[i].expressions.neutral>exps){
exps=result[i].expressions.neutral;
expstr="普通";
}
if(result[i].expressions.sad>exps){
exps=result[i].expressions.sad;
expstr="悲しい";
}
if(result[i].expressions.surprised>exps){
exps=result[i].expressions.surprised;
expstr="驚き";
}
prev_ctx.fillText(age+gender+expstr,-result[i].detection.box.x-result[i].detection.box.width, result[i].detection.box.y-4);
prev_ctx.setTransform(1,0,0,1,0,0);
}
}
setTimeout(Scan,10,false);
}
)
}
async function detect(){
return faceapi.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions()).withAgeAndGender().withFaceExpressions();
}
});
function ShowWait(){
document.querySelector(".wait").style.display="block";
}
function HideWait(interval){
setTimeout(function(){
document.querySelector(".wait").style.display="none";
},interval);
}
</script>
使用したライブラリ
face-api.js(https://github.com/justadudewhohacks/face-api.js)を使用させていただきました。- face-api.jsのライセンス情報
-
MIT License
Copyright (c) 2018 Vincent Mühler

