Javascriptで顔写真から個別にマッチングして顔認識して顔識別する(face-api.js使用)
※写真は「ぱたくそ」様(https://www.pakutaso.com/)より使用させていただいています。
以下2枚の顔写真を登録して、写真から個別に顔識別します
眼鏡の男性
サラリーマン
顔識別テスト1
顔識別テスト2
顔識別テスト3
ソースコード
<div style="display:flex;flex-wrap:wrap;">
<div>
<img src="./imgs/face-api/img1.jpg" id="img1" width="600" height="400">
<br>
<button onclick="descript('img1')">認識する</button>
</div>
<div>
<canvas id="preview_img1" style="width:400px;max-width:100%;height:auto;" width="600" height="600"></canvas>
</div>
</div>
<script>
var faceMatcher=[];//顔画像から特徴点を取り出した値を入れる
var detectImg=[];
var detectImgURL=["./imgs/face-api/face1.jpg","./imgs/face-api/face2.jpg"];
var detectImgLabel=["眼鏡の男性","サラリーマン"];
async function loadImage(src){
return new Promise(function(resolve,reject){
let img=new Image();
img.onload=function(){resolve(img);}
img.onerror=function(e){reject(e);}
img.src=src;
});
}
window.addEventListener('load',async function(event){
await Promise.all([
//SsdMobilenetv1Modelを使用する
faceapi.nets.ssdMobilenetv1.loadFromUri('./models'),
//faceLandmark68Netを使用する
faceapi.nets.faceLandmark68Net.loadFromUri("./models"),
//faceRecognitionNetを使用する
faceapi.nets.faceRecognitionNet.loadFromUri("./models")
]);
//顔識別させたい複数画像を登録する
detectImg=await Promise.all(detectImgURL.map(loadImage));
for(let i=0;i<detectImg.length;i++){
let singleResult=await faceapi.detectAllFaces(detectImg[i]).withFaceLandmarks().withFaceDescriptors();
if(singleResult.length>0){
const labeledDescriptors = [
new faceapi.LabeledFaceDescriptors(
detectImgLabel[i],//ラベルを設定する
[singleResult[0].descriptor]
),
];
faceMatcher[i] = new faceapi.FaceMatcher(labeledDescriptors);
}
}
});
function descript(id){
let img=document.getElementById(id);
faceapi.detectAllFaces(id, new faceapi.SsdMobilenetv1Options()).withFaceLandmarks().withFaceDescriptors().then(
function(result){
let can=document.getElementById("preview_"+id);
let ctx=can.getContext("2d",{willReadFrequently:true});
let family=
'Verdana,Roboto,"Droid Sans","游ゴシック",YuGothic,"メイリオ",Meiryo,'+
'"ヒラギノ角ゴ ProN W3","Hiragino Kaku Gothic ProN","MS Pゴシック",sans-serif';
ctx.font="bold 24px "+family;
ctx.fillStyle='rgba(0,0,255,1)';
ctx.drawImage(img,0,0);
if(faceMatcher!=null && result.length>0){
for(i=0;i<result.length;i++){
for(let j=0;j<faceMatcher.length;j++){
let bestMatch = faceMatcher[j].findBestMatch(result[i].descriptor);
if(bestMatch._distance<0.55){
//console.log(bestMatch);
ctx.lineWidth=4;
ctx.strokeStyle="#ff0000";
ctx.strokeRect(
result[i].detection.box.x,
result[i].detection.box.y,
result[i].detection.box.width,
result[i].detection.box.height
);
/*
ctx.moveTo(result[i].detection.box.x, result[i].detection.box.y);
ctx.lineTo(result[i].detection.box.x+0, result[i].detection.box.y+result[i].detection.box.height);
ctx.lineTo(result[i].detection.box.x+result[i].detection.box.width, result[i].detection.box.y+result[i].detection.box.height);
ctx.lineTo(result[i].detection.box.x+result[i].detection.box.width, result[i].detection.box.y+0);
ctx.lineTo(result[i].detection.box.x+0, result[i].detection.box.y+0);
ctx.stroke();
*/
//該当するラベルを表示する
ctx.fillText(
bestMatch.label,
result[i].detection.box.x,
result[i].detection.box.y+result[i].detection.box.height+20
);
}
}
}
}
}
);
}
</script>
使用したライブラリ
face-api.js(https://github.com/justadudewhohacks/face-api.js)を使用させていただきました。- face-api.jsのライセンス情報
-
MIT License
Copyright (c) 2018 Vincent Mühler

