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