mirror of https://github.com/vladmandic/human
10 lines
7.6 KiB
JavaScript
10 lines
7.6 KiB
JavaScript
/*
|
|
Human
|
|
homepage: <https://github.com/vladmandic/human>
|
|
author: <https://github.com/vladmandic>'
|
|
*/
|
|
|
|
import{Human as H}from"../../dist/human.esm.js";var l,R="human",p="person",g=(...t)=>console.log("indexdb",...t);async function v(){return l?!0:new Promise(t=>{let i=indexedDB.open(R,1);i.onerror=n=>g("error:",n),i.onupgradeneeded=n=>{g("create:",n.target),l=n.target.result,l.createObjectStore(p,{keyPath:"id",autoIncrement:!0})},i.onsuccess=n=>{l=n.target.result,g("open:",l),t(!0)}})}async function x(){let t=[];return l||await v(),new Promise(i=>{let n=l.transaction([p],"readwrite").objectStore(p).openCursor(null,"next");n.onerror=s=>g("load error:",s),n.onsuccess=s=>{s.target.result?(t.push(s.target.result.value),s.target.result.continue()):i(t)}})}async function y(){return l||await v(),new Promise(t=>{let i=l.transaction([p],"readwrite").objectStore(p).count();i.onerror=n=>g("count error:",n),i.onsuccess=()=>t(i.result)})}async function C(t){l||await v();let i={name:t.name,descriptor:t.descriptor,image:t.image};l.transaction([p],"readwrite").objectStore(p).put(i),g("save:",i)}async function D(t){l||await v(),l.transaction([p],"readwrite").objectStore(p).delete(t.id),g("delete:",t)}var b={modelBasePath:"../../models",filter:{equalization:!0},face:{enabled:!0,detector:{rotation:!0,return:!0,cropFactor:1.6,mask:!1},description:{enabled:!0},iris:{enabled:!0},emotion:{enabled:!1},antispoof:{enabled:!0},liveness:{enabled:!0}},body:{enabled:!1},hand:{enabled:!1},object:{enabled:!1},gesture:{enabled:!0}},I={order:2,multiplier:25,min:.2,max:.8},c={minConfidence:.6,minSize:224,maxTime:1e4,blinkMin:10,blinkMax:800,threshold:.5,mask:b.face.detector.mask,rotation:b.face.detector.rotation,cropFactor:b.face.detector.cropFactor,...I},o={faceCount:!1,faceConfidence:!1,facingCenter:!1,lookingCenter:!1,blinkDetected:!1,faceSize:!1,antispoofCheck:!1,livenessCheck:!1,elapsedMs:0},M=()=>o.faceCount&&o.faceSize&&o.blinkDetected&&o.facingCenter&&o.lookingCenter&&o.faceConfidence&&o.antispoofCheck&&o.livenessCheck,r={face:null,record:null},u={start:0,end:0,time:0},a=new H(b);a.env.perfadd=!1;a.draw.options.font='small-caps 18px "Lato"';a.draw.options.lineHeight=20;var e={video:document.getElementById("video"),canvas:document.getElementById("canvas"),log:document.getElementById("log"),fps:document.getElementById("fps"),match:document.getElementById("match"),name:document.getElementById("name"),save:document.getElementById("save"),delete:document.getElementById("delete"),retry:document.getElementById("retry"),source:document.getElementById("source"),ok:document.getElementById("ok")},w={detect:0,draw:0},h={detect:0,draw:0},E=0,m=(...t)=>{e.log.innerText+=t.join(" ")+`
|
|
`,console.log(...t)},k=t=>e.fps.innerText=t;async function S(){k("starting webcam...");let t={audio:!1,video:{facingMode:"user",resizeMode:"none",width:{ideal:document.body.clientWidth}}},i=await navigator.mediaDevices.getUserMedia(t),n=new Promise(s=>{e.video.onloadeddata=()=>s(!0)});e.video.srcObject=i,e.video.play(),await n,e.canvas.width=e.video.videoWidth,e.canvas.height=e.video.videoHeight,a.env.initial&&m("video:",e.video.videoWidth,e.video.videoHeight,"|",i.getVideoTracks()[0].label),e.canvas.onclick=()=>{e.video.paused?e.video.play():e.video.pause()}}async function T(){if(!e.video.paused){r.face&&r.face.tensor&&a.tf.dispose(r.face.tensor),await a.detect(e.video);let t=a.now();h.detect=1e3/(t-w.detect),w.detect=t,requestAnimationFrame(T)}}async function L(){let t=await a.next(a.result);await a.draw.canvas(e.video,e.canvas),await a.draw.all(e.canvas,t);let i=a.now();if(h.draw=1e3/(i-w.draw),w.draw=i,k(`fps: ${h.detect.toFixed(1).padStart(5," ")} detect | ${h.draw.toFixed(1).padStart(5," ")} draw`),o.faceCount=a.result.face.length===1,o.faceCount){let s=Object.values(a.result.gesture).map(f=>f.gesture);(s.includes("blink left eye")||s.includes("blink right eye"))&&(u.start=a.now()),u.start>0&&!s.includes("blink left eye")&&!s.includes("blink right eye")&&(u.end=a.now()),o.blinkDetected=o.blinkDetected||Math.abs(u.end-u.start)>c.blinkMin&&Math.abs(u.end-u.start)<c.blinkMax,o.blinkDetected&&u.time===0&&(u.time=Math.trunc(u.end-u.start)),o.facingCenter=s.includes("facing center"),o.lookingCenter=s.includes("looking center"),o.faceConfidence=(a.result.face[0].boxScore||0)>c.minConfidence&&(a.result.face[0].faceScore||0)>c.minConfidence,o.antispoofCheck=(a.result.face[0].real||0)>c.minConfidence,o.livenessCheck=(a.result.face[0].live||0)>c.minConfidence,o.faceSize=a.result.face[0].box[2]>=c.minSize&&a.result.face[0].box[3]>=c.minSize}let n=32;for(let[s,f]of Object.entries(o)){let d=document.getElementById(`ok-${s}`);d||(d=document.createElement("div"),d.innerText=s,d.className="ok",d.style.top=`${n}px`,e.ok.appendChild(d)),typeof f=="boolean"?d.style.backgroundColor=f?"lightgreen":"lightcoral":d.innerText=`${s}:${f}`,n+=28}return M()||o.elapsedMs>c.maxTime?(e.video.pause(),a.result.face[0]):(o.elapsedMs=Math.trunc(a.now()-E),new Promise(s=>{setTimeout(async()=>{await L()&&s(a.result.face[0])},30)}))}async function z(){var t,i,n,s;if(e.name.value.length>0){let f=(t=e.canvas.getContext("2d"))==null?void 0:t.getImageData(0,0,e.canvas.width,e.canvas.height),d={id:0,name:e.name.value,descriptor:(i=r.face)==null?void 0:i.embedding,image:f};await C(d),m("saved face record:",d.name,"descriptor length:",(s=(n=r.face)==null?void 0:n.embedding)==null?void 0:s.length),m("known face records:",await y())}else m("invalid name")}async function P(){r.record&&r.record.id>0&&await D(r.record)}async function j(){var s,f;if((s=e.canvas.getContext("2d"))==null||s.clearRect(0,0,c.minSize,c.minSize),!r.face||!r.face.tensor||!r.face.embedding)return!1;if(console.log("face record:",r.face),a.tf.browser.toPixels(r.face.tensor,e.canvas),await y()===0)return m("face database is empty"),document.body.style.background="black",e.delete.style.display="none",!1;let t=await x(),i=t.map(d=>d.descriptor).filter(d=>d.length>0),n=await a.match(r.face.embedding,i,I);return r.record=t[n.index]||null,r.record&&(m(`best match: ${r.record.name} | id: ${r.record.id} | similarity: ${Math.round(1e3*n.similarity)/10}%`),e.name.value=r.record.name,e.source.style.display="",(f=e.source.getContext("2d"))==null||f.putImageData(r.record.image,0,0)),document.body.style.background=n.similarity>c.threshold?"darkgreen":"maroon",n.similarity>c.threshold}async function B(){var t,i,n,s;return o.faceCount=!1,o.faceConfidence=!1,o.facingCenter=!1,o.blinkDetected=!1,o.faceSize=!1,o.antispoofCheck=!1,o.livenessCheck=!1,o.elapsedMs=0,e.match.style.display="none",e.retry.style.display="none",e.source.style.display="none",document.body.style.background="black",await S(),await T(),E=a.now(),r.face=await L(),e.canvas.width=((i=(t=r.face)==null?void 0:t.tensor)==null?void 0:i.shape[1])||c.minSize,e.canvas.height=((s=(n=r.face)==null?void 0:n.tensor)==null?void 0:s.shape[0])||c.minSize,e.source.width=e.canvas.width,e.source.height=e.canvas.height,e.canvas.style.width="",e.match.style.display="flex",e.save.style.display="flex",e.delete.style.display="flex",e.retry.style.display="block",M()?j():(m("did not find valid face"),!1)}async function q(){var t,i,n;m("human version:",a.version,"| tfjs version:",a.tf.version["tfjs-core"]),m("face embedding model:",(t=b.face.description)!=null&&t.enabled?"faceres":"",(i=b.face.mobilefacenet)!=null&&i.enabled?"mobilefacenet":"",(n=b.face.insightface)!=null&&n.enabled?"insightface":""),m("options:",JSON.stringify(c).replace(/{|}|"|\[|\]/g,"").replace(/,/g," ")),k("loading..."),m("known face records:",await y()),await S(),await a.load(),k("initializing..."),e.retry.addEventListener("click",B),e.save.addEventListener("click",z),e.delete.addEventListener("click",P),await a.warmup(),await B()}window.onload=q;
|
|
//# sourceMappingURL=index.js.map
|