diff --git a/.gitignore b/.gitignore
index ee89780..12b440b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
node_modules
pnpm-lock.yaml
+test
diff --git a/demo/index.js b/demo/index.js
index 3a0b7f3..887016c 100644
--- a/demo/index.js
+++ b/demo/index.js
@@ -20,8 +20,8 @@ function str(json) {
function log(...txt) {
// eslint-disable-next-line no-console
console.log(...txt);
- // @ts-ignore
- document.getElementById('log').innerHTML += `
${txt}`;
+ const div = document.getElementById('log');
+ if (div) div.innerHTML += `
${txt}`;
}
// helper function to draw detected faces
diff --git a/demo/webcam.js b/demo/webcam.js
index 7268440..b0ab210 100644
--- a/demo/webcam.js
+++ b/demo/webcam.js
@@ -19,8 +19,8 @@ function str(json) {
function log(...txt) {
// eslint-disable-next-line no-console
console.log(...txt);
- // @ts-ignore
- document.getElementById('log').innerHTML += `
${txt}`;
+ const div = document.getElementById('log');
+ if (div) div.innerHTML += `
${txt}`;
}
// helper function to draw detected faces
diff --git a/dist/face-api.esm-nobundle.js b/dist/face-api.esm-nobundle.js
index 0b19341..e46922e 100644
--- a/dist/face-api.esm-nobundle.js
+++ b/dist/face-api.esm-nobundle.js
@@ -5,5 +5,5 @@
author: '
*/
-var pn=Object.create,Ye=Object.defineProperty,dn=Object.getPrototypeOf,un=Object.prototype.hasOwnProperty,ln=Object.getOwnPropertyNames,fn=Object.getOwnPropertyDescriptor;var Dr=o=>Ye(o,"__esModule",{value:!0});var uo=(o,t)=>()=>(t||(t={exports:{}},o(t.exports,t)),t.exports),Er=(o,t)=>{for(var e in t)Ye(o,e,{get:t[e],enumerable:!0})},lt=(o,t,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ln(t))!un.call(o,r)&&r!=="default"&&Ye(o,r,{get:()=>t[r],enumerable:!(e=fn(t,r))||e.enumerable});return o},hn=o=>lt(Dr(Ye(o!=null?pn(dn(o)):{},"default",o&&o.__esModule&&"default"in o?{get:()=>o.default,enumerable:!0}:{value:o,enumerable:!0})),o);import*as Ca from"@tensorflow/tfjs/dist/index.js";import*as Na from"@tensorflow/tfjs-backend-wasm";var b=uo(xn=>{Dr(xn);lt(xn,Ca);lt(xn,Na)});var go=uo((_n,bo)=>{Dr(_n);Er(_n,{isNodejs:()=>wn});function wn(){return typeof global=="object"&&!0&&typeof bo!="undefined"&&typeof process!="undefined"&&!!process.version}});var ya=b();var Po={};Er(Po,{AnchorPosition:()=>pt,DrawBox:()=>Ue,DrawBoxOptions:()=>jr,DrawFaceLandmarks:()=>Zr,DrawFaceLandmarksOptions:()=>qr,DrawTextField:()=>Mt,DrawTextFieldOptions:()=>Ce,drawContour:()=>ft,drawDetections:()=>En,drawFaceExpressions:()=>kn,drawFaceLandmarks:()=>Ln});function ft(o,t,e=!1){if(o.beginPath(),t.slice(1).forEach(({x:r,y:n},a)=>{let s=t[a];o.moveTo(s.x,s.y),o.lineTo(r,n)}),e){let r=t[t.length-1],n=t[0];if(!r||!n)return;o.moveTo(r.x,r.y),o.lineTo(n.x,n.y)}o.stroke()}var lo={};Er(lo,{computeReshapedDimensions:()=>Nr,getCenterPoint:()=>$t,isDimensions:()=>ze,isEven:()=>Ge,isFloat:()=>Cr,isTensor:()=>Bt,isTensor1D:()=>bn,isTensor2D:()=>Mr,isTensor3D:()=>ht,isTensor4D:()=>G,isValidNumber:()=>et,isValidProbablitiy:()=>ee,range:()=>it,round:()=>Rt});var fo=b();var S=class{constructor(t,e){if(!et(t)||!et(e))throw new Error(`Dimensions.constructor - expected width and height to be valid numbers, instead have ${JSON.stringify({width:t,height:e})}`);this._width=t,this._height=e}get width(){return this._width}get height(){return this._height}reverse(){return new S(1/this.width,1/this.height)}};function Bt(o,t){return o instanceof fo.Tensor&&o.shape.length===t}function bn(o){return Bt(o,1)}function Mr(o){return Bt(o,2)}function ht(o){return Bt(o,3)}function G(o){return Bt(o,4)}function Cr(o){return o%1!=0}function Ge(o){return o%2==0}function Rt(o,t=2){let e=10**t;return Math.floor(o*e)/e}function ze(o){return o&&o.width&&o.height}function Nr({width:o,height:t},e){let r=e/Math.max(t,o);return new S(Math.round(o*r),Math.round(t*r))}function $t(o){return o.reduce((t,e)=>t.add(e),new x(0,0)).div(new x(o.length,o.length))}function it(o,t,e){return Array(o).fill(0).map((r,n)=>t+n*e)}function et(o){return!!o&&o!==Infinity&&o!==-Infinity&&!Number.isNaN(o)||o===0}function ee(o){return et(o)&&o>=0&&o<=1}var x=class{constructor(t,e){this._x=t,this._y=e}get x(){return this._x}get y(){return this._y}add(t){return new x(this.x+t.x,this.y+t.y)}sub(t){return new x(this.x-t.x,this.y-t.y)}mul(t){return new x(this.x*t.x,this.y*t.y)}div(t){return new x(this.x/t.x,this.y/t.y)}abs(){return new x(Math.abs(this.x),Math.abs(this.y))}magnitude(){return Math.sqrt(this.x**2+this.y**2)}floor(){return new x(Math.floor(this.x),Math.floor(this.y))}};var P=class{static isRect(t){return!!t&&[t.x,t.y,t.width,t.height].every(et)}static assertIsValidBox(t,e,r=!1){if(!P.isRect(t))throw new Error(`${e} - invalid box: ${JSON.stringify(t)}, expected object with properties x, y, width, height`);if(!r&&(t.width<0||t.height<0))throw new Error(`${e} - width (${t.width}) and height (${t.height}) must be positive numbers`)}constructor(t,e=!0){let r=t||{},n=[r.left,r.top,r.right,r.bottom].every(et),a=[r.x,r.y,r.width,r.height].every(et);if(!a&&!n)throw new Error(`Box.constructor - expected box to be IBoundingBox | IRect, instead have ${JSON.stringify(r)}`);let[s,i,c,m]=a?[r.x,r.y,r.width,r.height]:[r.left,r.top,r.right-r.left,r.bottom-r.top];P.assertIsValidBox({x:s,y:i,width:c,height:m},"Box.constructor",e),this._x=s,this._y=i,this._width=c,this._height=m}get x(){return this._x}get y(){return this._y}get width(){return this._width}get height(){return this._height}get left(){return this.x}get top(){return this.y}get right(){return this.x+this.width}get bottom(){return this.y+this.height}get area(){return this.width*this.height}get topLeft(){return new x(this.left,this.top)}get topRight(){return new x(this.right,this.top)}get bottomLeft(){return new x(this.left,this.bottom)}get bottomRight(){return new x(this.right,this.bottom)}round(){let[t,e,r,n]=[this.x,this.y,this.width,this.height].map(a=>Math.round(a));return new P({x:t,y:e,width:r,height:n})}floor(){let[t,e,r,n]=[this.x,this.y,this.width,this.height].map(a=>Math.floor(a));return new P({x:t,y:e,width:r,height:n})}toSquare(){let{x:t,y:e,width:r,height:n}=this,a=Math.abs(r-n);return re&&(i=-d+e+r,d=e),u>t&&(c=-u+t+n,u=t),m<1&&(c=2-m,m=1),p<1&&(c=2-p,p=1),{dy:s,edy:c,dx:a,edx:i,y:p,ey:u,x:m,ex:d,w:r,h:n}}calibrate(t){return new P({left:this.left+t.left*this.width,top:this.top+t.top*this.height,right:this.right+t.right*this.width,bottom:this.bottom+t.bottom*this.height}).toSquare().round()}};var re=class extends P{constructor(t,e,r,n,a=!1){super({left:t,top:e,right:r,bottom:n},a)}};var Dt=class{constructor(t,e,r,n,a){this._imageDims=new S(a.width,a.height),this._score=t,this._classScore=e,this._className=r,this._box=new P(n).rescale(this._imageDims)}get score(){return this._score}get classScore(){return this._classScore}get className(){return this._className}get box(){return this._box}get imageDims(){return this._imageDims}get imageWidth(){return this.imageDims.width}get imageHeight(){return this.imageDims.height}get relativeBox(){return new P(this._box).rescale(this.imageDims.reverse())}forSize(t,e){return new Dt(this.score,this.classScore,this.className,this.relativeBox,{width:t,height:e})}};var E=class extends Dt{constructor(t,e,r){super(t,t,"",e,r)}forSize(t,e){let{score:r,relativeBox:n,imageDims:a}=super.forSize(t,e);return new E(r,n,a)}};function kr(o,t,e=!0){let r=Math.max(0,Math.min(o.right,t.right)-Math.max(o.left,t.left)),n=Math.max(0,Math.min(o.bottom,t.bottom)-Math.max(o.top,t.top)),a=r*n;return e?a/(o.area+t.area-a):a/Math.min(o.area,t.area)}function Ir(o){let t=o.map(i=>i.x),e=o.map(i=>i.y),r=t.reduce((i,c)=>ccii({score:s,boxIndex:i})).sort((s,i)=>s.score-i.score).map(s=>s.boxIndex),a=[];for(;n.length>0;){let s=n.pop();a.push(s);let i=n,c=[];for(let m=0;mc[p]<=e)}return a}var ct=b();function rt(o,t){return ct.tidy(()=>{let[e,r,n]=t,a=ct.fill([...o.shape.slice(0,3),1],e,"float32"),s=ct.fill([...o.shape.slice(0,3),1],r,"float32"),i=ct.fill([...o.shape.slice(0,3),1],n,"float32"),c=ct.concat([a,s,i],3);return ct.sub(o,c)})}var Et=b();function Sr(o,t=!1){return Et.tidy(()=>{let[e,r]=o.shape.slice(1);if(e===r)return o;let n=Math.abs(e-r),a=Math.round(n*(t?.5:1)),s=e>r?2:1,i=u=>{let l=o.shape.slice();return l[s]=u,Et.fill(l,0,"float32")},c=i(a),m=n-c.shape[s],d=[t&&m?i(m):null,o,c].filter(u=>!!u).map(u=>Et.cast(u,"float32"));return Et.concat(d,s)})}function gn(o){let t=o.slice();for(let e=t.length-1;e>0;e--){let r=Math.floor(Math.random()*(e+1)),n=t[e];t[e]=t[r],t[r]=n}return t}function De(o){return 1/(1+Math.exp(-o))}function vn(o){return Math.log(o/(1-o))}var oe=class extends P{constructor(t,e,r,n,a=!1){super({x:t,y:e,width:r,height:n},a)}};var yn=.5,Fn=.43,Tn=.45,z=class{constructor(t,e,r=new x(0,0)){let{width:n,height:a}=e;this._imgDims=new S(n,a),this._shift=r,this._positions=t.map(s=>s.mul(new x(n,a)).add(r))}get shift(){return new x(this._shift.x,this._shift.y)}get imageWidth(){return this._imgDims.width}get imageHeight(){return this._imgDims.height}get positions(){return this._positions}get relativePositions(){return this._positions.map(t=>t.sub(this._shift).div(new x(this.imageWidth,this.imageHeight)))}forSize(t,e){return new this.constructor(this.relativePositions,{width:t,height:e})}shiftBy(t,e){return new this.constructor(this.relativePositions,this._imgDims,new x(t,e))}shiftByPoint(t){return this.shiftBy(t.x,t.y)}align(t,e={}){if(t){let a=t instanceof E?t.box.floor():new P(t);return this.shiftBy(a.x,a.y).align(null,e)}let{useDlibAlignment:r,minBoxPadding:n}={useDlibAlignment:!1,minBoxPadding:.2,...e};return r?this.alignDlib():this.alignMinBbox(n)}alignDlib(){let t=this.getRefPointsForAlignment(),[e,r,n]=t,a=d=>n.sub(d).magnitude(),s=(a(e)+a(r))/2,i=Math.floor(s/Tn),c=$t(t),m=Math.floor(Math.max(0,c.x-yn*i)),p=Math.floor(Math.max(0,c.y-Fn*i));return new oe(m,p,Math.min(i,this.imageWidth+m),Math.min(i,this.imageHeight+p))}alignMinBbox(t){let e=Ir(this.positions);return e.pad(e.width*t,e.height*t)}getRefPointsForAlignment(){throw new Error("getRefPointsForAlignment not implemented by base class")}};var ho=class extends z{getRefPointsForAlignment(){let t=this.positions;return[t[0],t[1],$t([t[3],t[4]])]}};var ne=class extends z{getJawOutline(){return this.positions.slice(0,17)}getLeftEyeBrow(){return this.positions.slice(17,22)}getRightEyeBrow(){return this.positions.slice(22,27)}getNose(){return this.positions.slice(27,36)}getLeftEye(){return this.positions.slice(36,42)}getRightEye(){return this.positions.slice(42,48)}getMouth(){return this.positions.slice(48,68)}getRefPointsForAlignment(){return[this.getLeftEye(),this.getRightEye(),this.getMouth()].map($t)}};var Ee=class{constructor(t,e){this._label=t,this._distance=e}get label(){return this._label}get distance(){return this._distance}toString(t=!0){return`${this.label}${t?` (${Rt(this.distance)})`:""}`}};var Me=class extends P{static assertIsValidLabeledBox(t,e){if(P.assertIsValidBox(t,e),!et(t.label))throw new Error(`${e} - expected property label (${t.label}) to be a number`)}constructor(t,e){super(t);this._label=e}get label(){return this._label}};var xt=class{constructor(t,e){if(typeof t!="string")throw new Error("LabeledFaceDescriptors - constructor expected label to be a string");if(!Array.isArray(e)||e.some(r=>!(r instanceof Float32Array)))throw new Error("LabeledFaceDescriptors - constructor expected descriptors to be an array of Float32Array");this._label=t,this._descriptors=e}get label(){return this._label}get descriptors(){return this._descriptors}toJSON(){return{label:this.label,descriptors:this.descriptors.map(t=>Array.from(t))}}static fromJSON(t){let e=t.descriptors.map(r=>new Float32Array(r));return new xt(t.label,e)}};var xo=class extends Me{static assertIsValidPredictedBox(t,e){if(Me.assertIsValidLabeledBox(t,e),!ee(t.score)||!ee(t.classScore))throw new Error(`${e} - expected properties score (${t.score}) and (${t.classScore}) to be a number between [0, 1]`)}constructor(t,e,r,n){super(t,e);this._score=r,this._classScore=n}get score(){return this._score}get classScore(){return this._classScore}};function mt(o){return o.detection instanceof E}function Ot(o,t){return{...o,...{detection:t}}}function Ar(){let o=window.fetch;if(!o)throw new Error("fetch - missing fetch implementation for browser environment");return{Canvas:HTMLCanvasElement,CanvasRenderingContext2D,Image:HTMLImageElement,ImageData,Video:HTMLVideoElement,createCanvasElement:()=>document.createElement("canvas"),createImageElement:()=>document.createElement("img"),fetch:o,readFile:()=>{throw new Error("readFile - filesystem not available for browser environment")}}}function Ve(o){let t="";if(!o)try{o=require("fs")}catch(r){t=r.toString()}return{readFile:o?r=>new Promise((n,a)=>{o.readFile(r,(s,i)=>s?a(s):n(i))}):()=>{throw new Error(`readFile - failed to require fs in nodejs environment with error: ${t}`)}}}function Wr(){let o=global.Canvas||global.HTMLCanvasElement,t=global.Image||global.HTMLImageElement,e=()=>{if(o)return new o;throw new Error("createCanvasElement - missing Canvas implementation for nodejs environment")},r=()=>{if(t)return new t;throw new Error("createImageElement - missing Image implementation for nodejs environment")},n=global.fetch,a=Ve();return{Canvas:o||class{},CanvasRenderingContext2D:global.CanvasRenderingContext2D||class{},Image:t||class{},ImageData:global.ImageData||class{},Video:global.HTMLVideoElement||class{},createCanvasElement:e,createImageElement:r,fetch:n,...a}}function Br(){return typeof window=="object"&&typeof document!="undefined"&&typeof HTMLImageElement!="undefined"&&typeof HTMLCanvasElement!="undefined"&&typeof HTMLVideoElement!="undefined"&&typeof ImageData!="undefined"&&typeof CanvasRenderingContext2D!="undefined"}var Rr=hn(go()),I;function Pn(){if(!I)throw new Error("getEnv - environment is not defined, check isNodejs() and isBrowser()");return I}function $r(o){I=o}function Or(){return Br()?$r(Ar()):(0,Rr.isNodejs)()?$r(Wr()):null}function Dn(o){if(I||Or(),!I)throw new Error("monkeyPatch - environment is not defined, check isNodejs() and isBrowser()");let{Canvas:t=I.Canvas,Image:e=I.Image}=o;I.Canvas=t,I.Image=e,I.createCanvasElement=o.createCanvasElement||(()=>new t),I.createImageElement=o.createImageElement||(()=>new e),I.ImageData=o.ImageData||I.ImageData,I.Video=o.Video||I.Video,I.fetch=o.fetch||I.fetch,I.readFile=o.readFile||I.readFile}var w={getEnv:Pn,setEnv:$r,initialize:Or,createBrowserEnv:Ar,createFileSystem:Ve,createNodejsEnv:Wr,monkeyPatch:Dn,isBrowser:Br,isNodejs:Rr.isNodejs};Or();function jt(o){return!w.isNodejs()&&typeof o=="string"?document.getElementById(o):o}function R(o){let{Canvas:t,CanvasRenderingContext2D:e}=w.getEnv();if(o instanceof e)return o;let r=jt(o);if(!(r instanceof t))throw new Error("resolveContext2d - expected canvas to be of instance of Canvas");let n=r.getContext("2d");if(!n)throw new Error("resolveContext2d - canvas 2d context is null");return n}var pt;(function(o){o.TOP_LEFT="TOP_LEFT",o.TOP_RIGHT="TOP_RIGHT",o.BOTTOM_LEFT="BOTTOM_LEFT",o.BOTTOM_RIGHT="BOTTOM_RIGHT"})(pt||(pt={}));var Ce=class{constructor(t={}){let{anchorPosition:e,backgroundColor:r,fontColor:n,fontSize:a,fontStyle:s,padding:i}=t;this.anchorPosition=e||pt.TOP_LEFT,this.backgroundColor=r||"rgba(0, 0, 0, 0.5)",this.fontColor=n||"rgba(255, 255, 255, 1)",this.fontSize=a||14,this.fontStyle=s||"Georgia",this.padding=i||4}},Mt=class{constructor(t,e,r={}){this.text=typeof t=="string"?[t]:t instanceof Mt?t.text:t,this.anchor=e,this.options=new Ce(r)}measureWidth(t){let{padding:e}=this.options;return this.text.map(r=>t.measureText(r).width).reduce((r,n)=>r{let g=c+d.x,_=c+d.y+(l+1)*s;r.fillText(u,g,_)})}};var jr=class{constructor(t={}){let{boxColor:e,lineWidth:r,label:n,drawLabelOptions:a}=t;this.boxColor=e||"rgba(0, 0, 255, 1)",this.lineWidth=r||2,this.label=n;let s={anchorPosition:pt.BOTTOM_LEFT,backgroundColor:this.boxColor};this.drawLabelOptions=new Ce({...s,...a})}},Ue=class{constructor(t,e={}){this.box=new P(t),this.options=new jr(e)}draw(t){let e=R(t),{boxColor:r,lineWidth:n}=this.options,{x:a,y:s,width:i,height:c}=this.box;e.strokeStyle=r,e.lineWidth=n,e.strokeRect(a,s,i,c);let{label:m}=this.options;m&&new Mt([m],{x:a-n/2,y:s},this.options.drawLabelOptions).draw(t)}};function En(o,t){(Array.isArray(t)?t:[t]).forEach(r=>{let n=r instanceof E?r.score:mt(r)?r.detection.score:void 0,a=r instanceof E?r.box:mt(r)?r.detection.box:new P(r),s=n?`${Rt(n)}`:void 0;new Ue(a,{label:s}).draw(o)})}var ue=b();function Ne(o){let{Image:t,Video:e}=w.getEnv();return o instanceof t&&o.complete||o instanceof e&&o.readyState>=3}function Hr(o){return new Promise((t,e)=>{if(o instanceof w.getEnv().Canvas||Ne(o))return t(null);function r(a){!a.currentTarget||(a.currentTarget.removeEventListener("load",n),a.currentTarget.removeEventListener("error",r),e(a))}function n(a){!a.currentTarget||(a.currentTarget.removeEventListener("load",n),a.currentTarget.removeEventListener("error",r),t(a))}o.addEventListener("load",n),o.addEventListener("error",r)})}function Yr(o){return new Promise((t,e)=>{o instanceof Blob||e(new Error("bufferToImage - expected buf to be of type: Blob"));let r=new FileReader;r.onload=()=>{typeof r.result!="string"&&e(new Error("bufferToImage - expected reader.result to be a string, in onload"));let n=w.getEnv().createImageElement();n.onload=()=>t(n),n.onerror=e,n.src=r.result},r.onerror=e,r.readAsDataURL(o)})}function Ht(o){let{Image:t,Video:e}=w.getEnv();return o instanceof t?new S(o.naturalWidth,o.naturalHeight):o instanceof e?new S(o.videoWidth,o.videoHeight):new S(o.width,o.height)}function Yt({width:o,height:t}){let{createCanvasElement:e}=w.getEnv(),r=e();return r.width=o,r.height=t,r}function ke(o,t){let{ImageData:e}=w.getEnv();if(!(o instanceof e)&&!Ne(o))throw new Error("createCanvasFromMedia - media has not finished loading yet");let{width:r,height:n}=t||Ht(o),a=Yt({width:r,height:n});return o instanceof e?R(a).putImageData(o,0,0):R(a).drawImage(o,0,0,r,n),a}var Xe=b();async function Gr(o,t){let e=t||w.getEnv().createCanvasElement(),[r,n,a]=o.shape.slice(G(o)?1:0),s=Xe.tidy(()=>o.as3D(r,n,a).toInt());return await Xe.browser.toPixels(s,e),s.dispose(),e}function Je(o){let{Image:t,Canvas:e,Video:r}=w.getEnv();return o instanceof t||o instanceof e||o instanceof r}var X=b();function zr(o,t,e=!1){let{Image:r,Canvas:n}=w.getEnv();if(!(o instanceof r||o instanceof n))throw new Error("imageToSquare - expected arg0 to be HTMLImageElement | HTMLCanvasElement");if(t<=0)return Yt({width:1,height:1});let a=Ht(o),s=t/Math.max(a.height,a.width),i=s*a.width,c=s*a.height,m=Yt({width:t,height:t}),p=o instanceof n?o:ke(o),d=Math.abs(i-c)/2,u=e&&i0&&p.height>0&&R(m).drawImage(p,u,l,i,c),m}var bt=class{constructor(t,e=!1){this._imageTensors=[];this._canvases=[];this._treatAsBatchInput=!1;this._inputDimensions=[];if(!Array.isArray(t))throw new Error(`NetInput.constructor - expected inputs to be an Array of TResolvedNetInput or to be instanceof tf.Tensor4D, instead have ${t}`);this._treatAsBatchInput=e,this._batchSize=t.length,t.forEach((r,n)=>{if(ht(r)){this._imageTensors[n]=r,this._inputDimensions[n]=r.shape;return}if(G(r)){let s=r.shape[0];if(s!==1)throw new Error(`NetInput - tf.Tensor4D with batchSize ${s} passed, but not supported in input array`);this._imageTensors[n]=r,this._inputDimensions[n]=r.shape.slice(1);return}let a=r instanceof w.getEnv().Canvas?r:ke(r);this._canvases[n]=a,this._inputDimensions[n]=[a.height,a.width,3]})}get imageTensors(){return this._imageTensors}get canvases(){return this._canvases}get isBatchInput(){return this.batchSize>1||this._treatAsBatchInput}get batchSize(){return this._batchSize}get inputDimensions(){return this._inputDimensions}get inputSize(){return this._inputSize}get reshapedInputDimensions(){return it(this.batchSize,0,1).map((t,e)=>this.getReshapedInputDimensions(e))}getInput(t){return this.canvases[t]||this.imageTensors[t]}getInputDimensions(t){return this._inputDimensions[t]}getInputHeight(t){return this._inputDimensions[t][0]}getInputWidth(t){return this._inputDimensions[t][1]}getReshapedInputDimensions(t){if(typeof this.inputSize!="number")throw new Error("getReshapedInputDimensions - inputSize not set, toBatchTensor has not been called yet");let e=this.getInputWidth(t),r=this.getInputHeight(t);return Nr({width:e,height:r},this.inputSize)}toBatchTensor(t,e=!0){return this._inputSize=t,X.tidy(()=>{let r=it(this.batchSize,0,1).map(a=>{let s=this.getInput(a);if(s instanceof X.Tensor){let i=G(s)?s:s.expandDims();return i=Sr(i,e),(i.shape[1]!==t||i.shape[2]!==t)&&(i=X.image.resizeBilinear(i,[t,t])),i.as3D(t,t,3)}if(s instanceof w.getEnv().Canvas)return X.browser.fromPixels(zr(s,t,e));throw new Error(`toBatchTensor - at batchIdx ${a}, expected input to be instanceof tf.Tensor or instanceof HTMLCanvasElement, instead have ${s}`)});return X.stack(r.map(a=>X.cast(a,"float32"))).as4D(this.batchSize,t,t,3)})}};async function D(o){if(o instanceof bt)return o;let t=Array.isArray(o)?o:[o];if(!t.length)throw new Error("toNetInput - empty array passed as input");let e=n=>Array.isArray(o)?` at input index ${n}:`:"",r=t.map(jt);return r.forEach((n,a)=>{if(!Je(n)&&!ht(n)&&!G(n))throw typeof t[a]=="string"?new Error(`toNetInput -${e(a)} string passed, but could not resolve HTMLElement for element id ${t[a]}`):new Error(`toNetInput -${e(a)} expected media to be of type HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | tf.Tensor3D, or to be an element id`);if(G(n)){let s=n.shape[0];if(s!==1)throw new Error(`toNetInput -${e(a)} tf.Tensor4D with batchSize ${s} passed, but not supported in input array`)}}),await Promise.all(r.map(n=>Je(n)&&Hr(n))),new bt(r,Array.isArray(o))}async function ae(o,t){let{Canvas:e}=w.getEnv(),r=o;if(!(o instanceof e)){let s=await D(o);if(s.batchSize>1)throw new Error("extractFaces - batchSize > 1 not supported");let i=s.getInput(0);r=i instanceof e?i:await Gr(i)}let n=R(r);return t.map(s=>s instanceof E?s.forSize(r.width,r.height).box.floor():s).map(s=>s.clipAtImageBorders(r.width,r.height)).map(({x:s,y:i,width:c,height:m})=>{let p=Yt({width:c,height:m});return c>0&&m>0&&R(p).putImageData(n.getImageData(s,i,c,m),0,0),p})}var qe=b();async function se(o,t){if(!ht(o)&&!G(o))throw new Error("extractFaceTensors - expected image tensor to be 3D or 4D");if(G(o)&&o.shape[0]>1)throw new Error("extractFaceTensors - batchSize > 1 not supported");return qe.tidy(()=>{let[e,r,n]=o.shape.slice(G(o)?1:0);return t.map(i=>i instanceof E?i.forSize(r,e).box:i).map(i=>i.clipAtImageBorders(r,e)).map(({x:i,y:c,width:m,height:p})=>qe.slice3d(o.as3D(e,r,n),[c,i,0],[p,m,n]))})}async function Gt(o,t){let{fetch:e}=w.getEnv(),r=await e(o,t);if(!(r.status<400))throw new Error(`failed to fetch: (${r.status}) ${r.statusText}, from url: ${r.url}`);return r}async function Mn(o){let t=await Gt(o),e=await t.blob();if(!e.type.startsWith("image/"))throw new Error(`fetchImage - expected blob type to be of type image/*, instead have: ${e.type}, for url: ${t.url}`);return Yr(e)}async function Vr(o){return(await Gt(o)).json()}async function Cn(o){return new Float32Array(await(await Gt(o)).arrayBuffer())}var vo=b();function Ze(o,t){let e=`${t}-weights_manifest.json`;if(!o)return{modelBaseUri:"",manifestUri:e};if(o==="/")return{modelBaseUri:"/",manifestUri:`/${e}`};let r=o.startsWith("http://")?"http://":o.startsWith("https://")?"https://":"";o=o.replace(r,"");let n=o.split("/").filter(i=>i),a=o.endsWith(".json")?n[n.length-1]:e,s=r+(o.endsWith(".json")?n.slice(0,n.length-1):n).join("/");return s=o.startsWith("/")?`/${s}`:s,{modelBaseUri:s,manifestUri:s==="/"?`/${a}`:`${s}/${a}`}}async function Ur(o,t){let{manifestUri:e,modelBaseUri:r}=Ze(o,t),n=await Vr(e);return vo.io.loadWeights(n,r)}function Nn(o,t,e=!1){let{width:r,height:n}=e?Ht(t):t;return o.width=r,o.height=n,{width:r,height:n}}var Nt=b();var gt=b();var L=class{constructor(t){this._params=void 0;this._paramMappings=[];this._name=t}get params(){return this._params}get paramMappings(){return this._paramMappings}get isLoaded(){return!!this.params}getParamFromPath(t){let{obj:e,objProp:r}=this.traversePropertyPath(t);return e[r]}reassignParamFromPath(t,e){let{obj:r,objProp:n}=this.traversePropertyPath(t);r[n].dispose(),r[n]=e}getParamList(){return this._paramMappings.map(({paramPath:t})=>({path:t,tensor:this.getParamFromPath(t)}))}getTrainableParams(){return this.getParamList().filter(t=>t.tensor instanceof gt.Variable)}getFrozenParams(){return this.getParamList().filter(t=>!(t.tensor instanceof gt.Variable))}variable(){this.getFrozenParams().forEach(({path:t,tensor:e})=>{this.reassignParamFromPath(t,e.variable())})}freeze(){this.getTrainableParams().forEach(({path:t,tensor:e})=>{let r=gt.tensor(e.dataSync());e.dispose(),this.reassignParamFromPath(t,r)})}dispose(t=!0){this.getParamList().forEach(e=>{if(t&&e.tensor.isDisposed)throw new Error(`param tensor has already been disposed for path ${e.path}`);e.tensor.dispose()}),this._params=void 0}serializeParams(){return new Float32Array(this.getParamList().map(({tensor:t})=>Array.from(t.dataSync())).reduce((t,e)=>t.concat(e)))}async load(t){if(t instanceof Float32Array){this.extractWeights(t);return}await this.loadFromUri(t)}async loadFromUri(t){if(t&&typeof t!="string")throw new Error(`${this._name}.loadFromUri - expected model uri`);let e=await Ur(t,this.getDefaultModelName());this.loadFromWeightMap(e)}async loadFromDisk(t){if(t&&typeof t!="string")throw new Error(`${this._name}.loadFromDisk - expected model file path`);let{readFile:e}=w.getEnv(),{manifestUri:r,modelBaseUri:n}=Ze(t,this.getDefaultModelName()),a=m=>Promise.all(m.map(p=>e(p).then(d=>d.buffer))),s=gt.io.weightsLoaderFactory(a),i=JSON.parse((await e(r)).toString()),c=await s(i,n);this.loadFromWeightMap(c)}loadFromWeightMap(t){let{paramMappings:e,params:r}=this.extractParamsFromWeightMap(t);this._paramMappings=e,this._params=r}extractWeights(t){let{paramMappings:e,params:r}=this.extractParams(t);this._paramMappings=e,this._params=r}traversePropertyPath(t){if(!this.params)throw new Error("traversePropertyPath - model has no loaded params");let e=t.split("/").reduce((a,s)=>{if(!a.nextObj.hasOwnProperty(s))throw new Error(`traversePropertyPath - object does not have property ${s}, for path ${t}`);return{obj:a.nextObj,objProp:s,nextObj:a.nextObj[s]}},{nextObj:this.params}),{obj:r,objProp:n}=e;if(!r||!n||!(r[n]instanceof gt.Tensor))throw new Error(`traversePropertyPath - parameter is not a tensor, for path ${t}`);return{obj:r,objProp:n}}};var M=b();var ie=b();function $(o,t,e){return ie.tidy(()=>{let r=ie.separableConv2d(o,t.depthwise_filter,t.pointwise_filter,e,"same");return r=ie.add(r,t.bias),r})}function Ke(o,t,e=!1){return M.tidy(()=>{let r=M.relu(e?M.add(M.conv2d(o,t.conv0.filters,[2,2],"same"),t.conv0.bias):$(o,t.conv0,[2,2])),n=$(r,t.conv1,[1,1]),a=M.relu(M.add(r,n)),s=$(a,t.conv2,[1,1]);return M.relu(M.add(r,M.add(n,s)))})}function Ie(o,t,e=!1,r=!0){return M.tidy(()=>{let n=M.relu(e?M.add(M.conv2d(o,t.conv0.filters,r?[2,2]:[1,1],"same"),t.conv0.bias):$(o,t.conv0,r?[2,2]:[1,1])),a=$(n,t.conv1,[1,1]),s=M.relu(M.add(n,a)),i=$(s,t.conv2,[1,1]),c=M.relu(M.add(n,M.add(a,i))),m=$(c,t.conv3,[1,1]);return M.relu(M.add(n,M.add(a,M.add(i,m))))})}var Ct=b();function zt(o,t,e="same",r=!1){return Ct.tidy(()=>{let n=Ct.add(Ct.conv2d(o,t.filters,[1,1],e),t.bias);return r?Ct.relu(n):n})}function A(o,t){Object.keys(o).forEach(e=>{t.some(r=>r.originalPath===e)||o[e].dispose()})}var Qe=b();function ce(o,t){return(e,r,n,a)=>{let s=Qe.tensor4d(o(e*r*n*n),[n,n,e,r]),i=Qe.tensor1d(o(r));return t.push({paramPath:`${a}/filters`},{paramPath:`${a}/bias`}),{filters:s,bias:i}}}var tr=b();function er(o,t){return(e,r,n)=>{let a=tr.tensor2d(o(e*r),[e,r]),s=tr.tensor1d(o(r));return t.push({paramPath:`${n}/weights`},{paramPath:`${n}/bias`}),{weights:a,bias:s}}}var Le=b();var rr=class{constructor(t,e,r){this.depthwise_filter=t;this.pointwise_filter=e;this.bias=r}};function me(o,t){return(e,r,n)=>{let a=Le.tensor4d(o(3*3*e),[3,3,e,1]),s=Le.tensor4d(o(e*r),[1,1,e,r]),i=Le.tensor1d(o(r));return t.push({paramPath:`${n}/depthwise_filter`},{paramPath:`${n}/pointwise_filter`},{paramPath:`${n}/bias`}),new rr(a,s,i)}}function pe(o){return t=>{let e=o(`${t}/depthwise_filter`,4),r=o(`${t}/pointwise_filter`,4),n=o(`${t}/bias`,1);return new rr(e,r,n)}}function O(o,t){return(e,r,n)=>{let a=o[e];if(!Bt(a,r))throw new Error(`expected weightMap[${e}] to be a Tensor${r}D, instead have ${a}`);return t.push({originalPath:e,paramPath:n||e}),a}}function W(o){let t=o;function e(n){let a=t.slice(0,n);return t=t.slice(n),a}function r(){return t}return{extractWeights:e,getRemainingWeights:r}}function or(o,t){let e=ce(o,t),r=me(o,t);function n(s,i,c,m=!1){let p=m?e(s,i,3,`${c}/conv0`):r(s,i,`${c}/conv0`),d=r(i,i,`${c}/conv1`),u=r(i,i,`${c}/conv2`);return{conv0:p,conv1:d,conv2:u}}function a(s,i,c,m=!1){let{conv0:p,conv1:d,conv2:u}=n(s,i,c,m),l=r(i,i,`${c}/conv3`);return{conv0:p,conv1:d,conv2:u,conv3:l}}return{extractDenseBlock3Params:n,extractDenseBlock4Params:a}}function yo(o){let t=[],{extractWeights:e,getRemainingWeights:r}=W(o),{extractDenseBlock4Params:n}=or(e,t),a=n(3,32,"dense0",!0),s=n(32,64,"dense1"),i=n(64,128,"dense2"),c=n(128,256,"dense3");if(r().length!==0)throw new Error(`weights remaing after extract: ${r().length}`);return{paramMappings:t,params:{dense0:a,dense1:s,dense2:i,dense3:c}}}function nr(o){return t=>{let e=o(`${t}/filters`,4),r=o(`${t}/bias`,1);return{filters:e,bias:r}}}function ar(o,t){let e=O(o,t),r=nr(e),n=pe(e);function a(i,c=!1){let m=c?r(`${i}/conv0`):n(`${i}/conv0`),p=n(`${i}/conv1`),d=n(`${i}/conv2`);return{conv0:m,conv1:p,conv2:d}}function s(i,c=!1){let m=c?r(`${i}/conv0`):n(`${i}/conv0`),p=n(`${i}/conv1`),d=n(`${i}/conv2`),u=n(`${i}/conv3`);return{conv0:m,conv1:p,conv2:d,conv3:u}}return{extractDenseBlock3Params:a,extractDenseBlock4Params:s}}function Fo(o){let t=[],{extractDenseBlock4Params:e}=ar(o,t),r={dense0:e("dense0",!0),dense1:e("dense1"),dense2:e("dense2"),dense3:e("dense3")};return A(o,t),{params:r,paramMappings:t}}var Se=class extends L{constructor(){super("FaceFeatureExtractor")}forwardInput(t){let{params:e}=this;if(!e)throw new Error("FaceFeatureExtractor - load model before inference");return Nt.tidy(()=>{let r=Nt.cast(t.toBatchTensor(112,!0),"float32"),a=rt(r,[122.782,117.001,104.298]).div(Nt.scalar(255)),s=Ie(a,e.dense0,!0);return s=Ie(s,e.dense1),s=Ie(s,e.dense2),s=Ie(s,e.dense3),s=Nt.avgPool(s,[7,7],[2,2],"valid"),s})}async forward(t){return this.forwardInput(await D(t))}getDefaultModelName(){return"face_feature_extractor_model"}extractParamsFromWeightMap(t){return Fo(t)}extractParams(t){return yo(t)}};var wo=b();var de=b();function Ae(o,t){return de.tidy(()=>de.add(de.matMul(o,t.weights),t.bias))}function To(o,t,e){let r=[],{extractWeights:n,getRemainingWeights:a}=W(o),i=er(n,r)(t,e,"fc");if(a().length!==0)throw new Error(`weights remaing after extract: ${a().length}`);return{paramMappings:r,params:{fc:i}}}function _o(o){let t=[],e=O(o,t);function r(a){let s=e(`${a}/weights`,2),i=e(`${a}/bias`,1);return{weights:s,bias:i}}let n={fc:r("fc")};return A(o,t),{params:n,paramMappings:t}}function sr(o){let t={},e={};return Object.keys(o).forEach(r=>{let n=r.startsWith("fc")?e:t;n[r]=o[r]}),{featureExtractorMap:t,classifierMap:e}}var We=class extends L{constructor(t,e){super(t);this._faceFeatureExtractor=e}get faceFeatureExtractor(){return this._faceFeatureExtractor}runNet(t){let{params:e}=this;if(!e)throw new Error(`${this._name} - load model before inference`);return wo.tidy(()=>{let r=t instanceof bt?this.faceFeatureExtractor.forwardInput(t):t;return Ae(r.as2D(r.shape[0],-1),e.fc)})}dispose(t=!0){this.faceFeatureExtractor.dispose(t),super.dispose(t)}loadClassifierParams(t){let{params:e,paramMappings:r}=this.extractClassifierParams(t);this._params=e,this._paramMappings=r}extractClassifierParams(t){return To(t,this.getClassifierChannelsIn(),this.getClassifierChannelsOut())}extractParamsFromWeightMap(t){let{featureExtractorMap:e,classifierMap:r}=sr(t);return this.faceFeatureExtractor.loadFromWeightMap(e),_o(r)}extractParams(t){let e=this.getClassifierChannelsIn(),r=this.getClassifierChannelsOut(),n=r*e+r,a=t.slice(0,t.length-n),s=t.slice(t.length-n);return this.faceFeatureExtractor.extractWeights(a),this.extractClassifierParams(s)}};var Xr=["neutral","happy","sad","angry","fearful","disgusted","surprised"],kt=class{constructor(t){if(t.length!==7)throw new Error(`FaceExpressions.constructor - expected probabilities.length to be 7, have: ${t.length}`);Xr.forEach((e,r)=>{this[e]=t[r]})}asSortedArray(){return Xr.map(t=>({expression:t,probability:this[t]})).sort((t,e)=>e.probability-t.probability)}};var ir=class extends We{constructor(t=new Se){super("FaceExpressionNet",t)}forwardInput(t){return ue.tidy(()=>ue.softmax(this.runNet(t)))}async forward(t){return this.forwardInput(await D(t))}async predictExpressions(t){let e=await D(t),r=await this.forwardInput(e),n=await Promise.all(ue.unstack(r).map(async s=>{let i=await s.data();return s.dispose(),i}));r.dispose();let a=n.map(s=>new kt(s));return e.isBatchInput?a:a[0]}getDefaultModelName(){return"face_expression_model"}getClassifierChannelsIn(){return 256}getClassifierChannelsOut(){return 7}};function Jr(o){return o.expressions instanceof kt}function cr(o,t){return{...o,...{expressions:t}}}function kn(o,t,e=.1,r){(Array.isArray(t)?t:[t]).forEach(a=>{let s=a instanceof kt?a:Jr(a)?a.expressions:void 0;if(!s)throw new Error("drawFaceExpressions - expected faceExpressions to be FaceExpressions | WithFaceExpressions<{}> or array thereof");let c=s.asSortedArray().filter(d=>d.probability>e),m=mt(a)?a.detection.box.bottomLeft:r||new x(0,0);new Mt(c.map(d=>`${d.expression} (${Rt(d.probability)})`),m).draw(o)})}function Vt(o){return mt(o)&&o.landmarks instanceof z&&o.unshiftedLandmarks instanceof z&&o.alignedRect instanceof E}function In(o){let t=(i,c,m,p)=>Math.atan2(p-c,m-i)%Math.PI,e=i=>i*180/Math.PI,r={roll:void 0,pitch:void 0,yaw:void 0};if(!o||!o._positions||o._positions.length!==68)return r;let n=o._positions;r.roll=-t(n[36]._x,n[36]._y,n[45]._x,n[45]._y),r.pitch=t(0,Math.abs(n[0]._x-n[30]._x)/n[30]._x,Math.PI,Math.abs(n[16]._x-n[30]._x)/n[30]._x);let a=n.reduce((i,c)=>ii>c._y?i:c._y,-Infinity);return r.yaw=Math.PI*(o._imgDims._height/(s-a)/1.4-1),r}function le(o,t){let{box:e}=o.detection,r=t.shiftBy(e.x,e.y),n=r.align(),{imageDims:a}=o.detection,s=new E(o.detection.score,n.rescale(a.reverse()),a),i=In(t);return{...o,...{landmarks:r,unshiftedLandmarks:t,alignedRect:s,angle:i}}}var qr=class{constructor(t={}){let{drawLines:e=!0,drawPoints:r=!0,lineWidth:n,lineColor:a,pointSize:s,pointColor:i}=t;this.drawLines=e,this.drawPoints=r,this.lineWidth=n||1,this.pointSize=s||2,this.lineColor=a||"rgba(0, 255, 255, 1)",this.pointColor=i||"rgba(255, 0, 255, 1)"}},Zr=class{constructor(t,e={}){this.faceLandmarks=t,this.options=new qr(e)}draw(t){let e=R(t),{drawLines:r,drawPoints:n,lineWidth:a,lineColor:s,pointSize:i,pointColor:c}=this.options;if(r&&this.faceLandmarks instanceof ne&&(e.strokeStyle=s,e.lineWidth=a,ft(e,this.faceLandmarks.getJawOutline()),ft(e,this.faceLandmarks.getLeftEyeBrow()),ft(e,this.faceLandmarks.getRightEyeBrow()),ft(e,this.faceLandmarks.getNose()),ft(e,this.faceLandmarks.getLeftEye(),!0),ft(e,this.faceLandmarks.getRightEye(),!0),ft(e,this.faceLandmarks.getMouth(),!0)),n){e.strokeStyle=c,e.fillStyle=c;let m=p=>{e.beginPath(),e.arc(p.x,p.y,i,0,2*Math.PI),e.fill()};this.faceLandmarks.positions.forEach(m)}}};function Ln(o,t){(Array.isArray(t)?t:[t]).forEach(r=>{let n=r instanceof z?r:Vt(r)?r.landmarks:void 0;if(!n)throw new Error("drawFaceLandmarks - expected faceExpressions to be FaceLandmarks | WithFaceLandmarks> or array thereof");new Zr(n).draw(o)})}var Do="1.1.3";var dt=b();var N=b();function Sn(o,t){let e=ce(o,t),r=me(o,t);function n(s,i,c){let m=r(s,i,`${c}/separable_conv0`),p=r(i,i,`${c}/separable_conv1`),d=e(s,i,1,`${c}/expansion_conv`);return{separable_conv0:m,separable_conv1:p,expansion_conv:d}}function a(s,i){let c=r(s,s,`${i}/separable_conv0`),m=r(s,s,`${i}/separable_conv1`),p=r(s,s,`${i}/separable_conv2`);return{separable_conv0:c,separable_conv1:m,separable_conv2:p}}return{extractConvParams:e,extractSeparableConvParams:r,extractReductionBlockParams:n,extractMainBlockParams:a}}function Eo(o,t){let e=[],{extractWeights:r,getRemainingWeights:n}=W(o),{extractConvParams:a,extractSeparableConvParams:s,extractReductionBlockParams:i,extractMainBlockParams:c}=Sn(r,e),m=a(3,32,3,"entry_flow/conv_in"),p=i(32,64,"entry_flow/reduction_block_0"),d=i(64,128,"entry_flow/reduction_block_1"),u={conv_in:m,reduction_block_0:p,reduction_block_1:d},l={};it(t,0,1).forEach(v=>{l[`main_block_${v}`]=c(128,`middle_flow/main_block_${v}`)});let g=i(128,256,"exit_flow/reduction_block"),_=s(256,512,"exit_flow/separable_conv"),h={reduction_block:g,separable_conv:_};if(n().length!==0)throw new Error(`weights remaing after extract: ${n().length}`);return{paramMappings:e,params:{entry_flow:u,middle_flow:l,exit_flow:h}}}function An(o,t){let e=O(o,t),r=nr(e),n=pe(e);function a(i){let c=n(`${i}/separable_conv0`),m=n(`${i}/separable_conv1`),p=r(`${i}/expansion_conv`);return{separable_conv0:c,separable_conv1:m,expansion_conv:p}}function s(i){let c=n(`${i}/separable_conv0`),m=n(`${i}/separable_conv1`),p=n(`${i}/separable_conv2`);return{separable_conv0:c,separable_conv1:m,separable_conv2:p}}return{extractConvParams:r,extractSeparableConvParams:n,extractReductionBlockParams:a,extractMainBlockParams:s}}function Mo(o,t){let e=[],{extractConvParams:r,extractSeparableConvParams:n,extractReductionBlockParams:a,extractMainBlockParams:s}=An(o,e),i=r("entry_flow/conv_in"),c=a("entry_flow/reduction_block_0"),m=a("entry_flow/reduction_block_1"),p={conv_in:i,reduction_block_0:c,reduction_block_1:m},d={};it(t,0,1).forEach(_=>{d[`main_block_${_}`]=s(`middle_flow/main_block_${_}`)});let u=a("exit_flow/reduction_block"),l=n("exit_flow/separable_conv"),g={reduction_block:u,separable_conv:l};return A(o,e),{params:{entry_flow:p,middle_flow:d,exit_flow:g},paramMappings:e}}function Co(o,t,e){return N.add(N.conv2d(o,t.filters,e,"same"),t.bias)}function Kr(o,t,e=!0){let r=e?N.relu(o):o;return r=$(r,t.separable_conv0,[1,1]),r=$(N.relu(r),t.separable_conv1,[1,1]),r=N.maxPool(r,[3,3],[2,2],"same"),r=N.add(r,Co(o,t.expansion_conv,[2,2])),r}function Wn(o,t){let e=$(N.relu(o),t.separable_conv0,[1,1]);return e=$(N.relu(e),t.separable_conv1,[1,1]),e=$(N.relu(e),t.separable_conv2,[1,1]),e=N.add(e,o),e}var Qr=class extends L{constructor(t){super("TinyXception");this._numMainBlocks=t}forwardInput(t){let{params:e}=this;if(!e)throw new Error("TinyXception - load model before inference");return N.tidy(()=>{let r=N.cast(t.toBatchTensor(112,!0),"float32"),a=rt(r,[122.782,117.001,104.298]).div(N.scalar(256)),s=N.relu(Co(a,e.entry_flow.conv_in,[2,2]));return s=Kr(s,e.entry_flow.reduction_block_0,!1),s=Kr(s,e.entry_flow.reduction_block_1),it(this._numMainBlocks,0,1).forEach(i=>{s=Wn(s,e.middle_flow[`main_block_${i}`])}),s=Kr(s,e.exit_flow.reduction_block),s=N.relu($(s,e.exit_flow.separable_conv,[1,1])),s})}async forward(t){return this.forwardInput(await D(t))}getDefaultModelName(){return"tiny_xception_model"}extractParamsFromWeightMap(t){return Mo(t,this._numMainBlocks)}extractParams(t){return Eo(t,this._numMainBlocks)}};function No(o){let t=[],{extractWeights:e,getRemainingWeights:r}=W(o),n=er(e,t),a=n(512,1,"fc/age"),s=n(512,2,"fc/gender");if(r().length!==0)throw new Error(`weights remaing after extract: ${r().length}`);return{paramMappings:t,params:{fc:{age:a,gender:s}}}}function ko(o){let t=[],e=O(o,t);function r(a){let s=e(`${a}/weights`,2),i=e(`${a}/bias`,1);return{weights:s,bias:i}}let n={fc:{age:r("fc/age"),gender:r("fc/gender")}};return A(o,t),{params:n,paramMappings:t}}var vt;(function(o){o.FEMALE="female",o.MALE="male"})(vt||(vt={}));var mr=class extends L{constructor(t=new Qr(2)){super("AgeGenderNet");this._faceFeatureExtractor=t}get faceFeatureExtractor(){return this._faceFeatureExtractor}runNet(t){let{params:e}=this;if(!e)throw new Error(`${this._name} - load model before inference`);return dt.tidy(()=>{let r=t instanceof bt?this.faceFeatureExtractor.forwardInput(t):t,n=dt.avgPool(r,[7,7],[2,2],"valid").as2D(r.shape[0],-1),a=Ae(n,e.fc.age).as1D(),s=Ae(n,e.fc.gender);return{age:a,gender:s}})}forwardInput(t){return dt.tidy(()=>{let{age:e,gender:r}=this.runNet(t);return{age:e,gender:dt.softmax(r)}})}async forward(t){return this.forwardInput(await D(t))}async predictAgeAndGender(t){let e=await D(t),r=await this.forwardInput(e),n=dt.unstack(r.age),a=dt.unstack(r.gender),s=n.map((c,m)=>({ageTensor:c,genderTensor:a[m]})),i=await Promise.all(s.map(async({ageTensor:c,genderTensor:m})=>{let p=(await c.data())[0],d=(await m.data())[0],u=d>.5,l=u?vt.MALE:vt.FEMALE,g=u?d:1-d;return c.dispose(),m.dispose(),{age:p,gender:l,genderProbability:g}}));return r.age.dispose(),r.gender.dispose(),e.isBatchInput?i:i[0]}getDefaultModelName(){return"age_gender_model"}dispose(t=!0){this.faceFeatureExtractor.dispose(t),super.dispose(t)}loadClassifierParams(t){let{params:e,paramMappings:r}=this.extractClassifierParams(t);this._params=e,this._paramMappings=r}extractClassifierParams(t){return No(t)}extractParamsFromWeightMap(t){let{featureExtractorMap:e,classifierMap:r}=sr(t);return this.faceFeatureExtractor.loadFromWeightMap(e),ko(r)}extractParams(t){let e=512*1+1+(512*2+2),r=t.slice(0,t.length-e),n=t.slice(t.length-e);return this.faceFeatureExtractor.extractWeights(r),this.extractClassifierParams(n)}};var j=b();var Be=class extends We{postProcess(t,e,r){let n=r.map(({width:s,height:i})=>{let c=e/Math.max(i,s);return{width:s*c,height:i*c}}),a=n.length;return j.tidy(()=>{let s=(d,u)=>j.stack([j.fill([68],d,"float32"),j.fill([68],u,"float32")],1).as2D(1,136).as1D(),i=(d,u)=>{let{width:l,height:g}=n[d];return u(l,g)?Math.abs(l-g)/2:0},c=d=>i(d,(u,l)=>ui(d,(u,l)=>ls(c(u),m(u))))).div(j.stack(Array.from(Array(a),(d,u)=>s(n[u].width,n[u].height))))})}forwardInput(t){return j.tidy(()=>{let e=this.runNet(t);return this.postProcess(e,t.inputSize,t.inputDimensions.map(([r,n])=>({height:r,width:n})))})}async forward(t){return this.forwardInput(await D(t))}async detectLandmarks(t){let e=await D(t),r=j.tidy(()=>j.unstack(this.forwardInput(e))),n=await Promise.all(r.map(async(a,s)=>{let i=Array.from(await a.data()),c=i.filter((p,d)=>Ge(d)),m=i.filter((p,d)=>!Ge(d));return new ne(Array(68).fill(0).map((p,d)=>new x(c[d],m[d])),{height:e.getInputHeight(s),width:e.getInputWidth(s)})}));return r.forEach(a=>a.dispose()),e.isBatchInput?n:n[0]}getClassifierChannelsOut(){return 136}};var fe=class extends Be{constructor(t=new Se){super("FaceLandmark68Net",t)}getDefaultModelName(){return"face_landmark_68_model"}getClassifierChannelsIn(){return 256}};var It=b();function Io(o){let t=[],{extractDenseBlock3Params:e}=ar(o,t),r={dense0:e("dense0",!0),dense1:e("dense1"),dense2:e("dense2")};return A(o,t),{params:r,paramMappings:t}}function Lo(o){let t=[],{extractWeights:e,getRemainingWeights:r}=W(o),{extractDenseBlock3Params:n}=or(e,t),a=n(3,32,"dense0",!0),s=n(32,64,"dense1"),i=n(64,128,"dense2");if(r().length!==0)throw new Error(`weights remaing after extract: ${r().length}`);return{paramMappings:t,params:{dense0:a,dense1:s,dense2:i}}}var to=class extends L{constructor(){super("TinyFaceFeatureExtractor")}forwardInput(t){let{params:e}=this;if(!e)throw new Error("TinyFaceFeatureExtractor - load model before inference");return It.tidy(()=>{let r=It.cast(t.toBatchTensor(112,!0),"float32"),a=rt(r,[122.782,117.001,104.298]).div(It.scalar(255)),s=Ke(a,e.dense0,!0);return s=Ke(s,e.dense1),s=Ke(s,e.dense2),s=It.avgPool(s,[14,14],[2,2],"valid"),s})}async forward(t){return this.forwardInput(await D(t))}getDefaultModelName(){return"face_feature_extractor_tiny_model"}extractParamsFromWeightMap(t){return Io(t)}extractParams(t){return Lo(t)}};var pr=class extends Be{constructor(t=new to){super("FaceLandmark68TinyNet",t)}getDefaultModelName(){return"face_landmark_68_tiny_model"}getClassifierChannelsIn(){return 128}};var So=class extends fe{};var V=b();var he=b();var dr=b();function Ao(o,t){return dr.add(dr.mul(o,t.weights),t.biases)}function eo(o,t,e,r,n="same"){let{filters:a,bias:s}=t.conv,i=he.conv2d(o,a,e,n);return i=he.add(i,s),i=Ao(i,t.scale),r?he.relu(i):i}function Wo(o,t){return eo(o,t,[1,1],!0)}function ro(o,t){return eo(o,t,[1,1],!1)}function ur(o,t){return eo(o,t,[2,2],!0,"valid")}var H=b();function Bn(o,t){function e(i,c,m){let p=o(i),d=p.length/(c*m*m);if(Cr(d))throw new Error(`depth has to be an integer: ${d}, weights.length: ${p.length}, numFilters: ${c}, filterSize: ${m}`);return H.tidy(()=>H.transpose(H.tensor4d(p,[c,d,m,m]),[2,3,1,0]))}function r(i,c,m,p){let d=e(i,c,m),u=H.tensor1d(o(c));return t.push({paramPath:`${p}/filters`},{paramPath:`${p}/bias`}),{filters:d,bias:u}}function n(i,c){let m=H.tensor1d(o(i)),p=H.tensor1d(o(i));return t.push({paramPath:`${c}/weights`},{paramPath:`${c}/biases`}),{weights:m,biases:p}}function a(i,c,m,p){let d=r(i,c,m,`${p}/conv`),u=n(c,`${p}/scale`);return{conv:d,scale:u}}function s(i,c,m,p,d=!1){let u=a((d?.5:1)*i,c,m,`${p}/conv1`),l=a(i,c,m,`${p}/conv2`);return{conv1:u,conv2:l}}return{extractConvLayerParams:a,extractResidualLayerParams:s}}function Bo(o){let{extractWeights:t,getRemainingWeights:e}=W(o),r=[],{extractConvLayerParams:n,extractResidualLayerParams:a}=Bn(t,r),s=n(4704,32,7,"conv32_down"),i=a(9216,32,3,"conv32_1"),c=a(9216,32,3,"conv32_2"),m=a(9216,32,3,"conv32_3"),p=a(36864,64,3,"conv64_down",!0),d=a(36864,64,3,"conv64_1"),u=a(36864,64,3,"conv64_2"),l=a(36864,64,3,"conv64_3"),g=a(147456,128,3,"conv128_down",!0),_=a(147456,128,3,"conv128_1"),h=a(147456,128,3,"conv128_2"),v=a(589824,256,3,"conv256_down",!0),F=a(589824,256,3,"conv256_1"),y=a(589824,256,3,"conv256_2"),k=a(589824,256,3,"conv256_down_out"),Y=H.tidy(()=>H.transpose(H.tensor2d(t(256*128),[128,256]),[1,0]));if(r.push({paramPath:"fc"}),e().length!==0)throw new Error(`weights remaing after extract: ${e().length}`);return{params:{conv32_down:s,conv32_1:i,conv32_2:c,conv32_3:m,conv64_down:p,conv64_1:d,conv64_2:u,conv64_3:l,conv128_down:g,conv128_1:_,conv128_2:h,conv256_down:v,conv256_1:F,conv256_2:y,conv256_down_out:k,fc:Y},paramMappings:r}}function Rn(o,t){let e=O(o,t);function r(s){let i=e(`${s}/scale/weights`,1),c=e(`${s}/scale/biases`,1);return{weights:i,biases:c}}function n(s){let i=e(`${s}/conv/filters`,4),c=e(`${s}/conv/bias`,1),m=r(s);return{conv:{filters:i,bias:c},scale:m}}function a(s){return{conv1:n(`${s}/conv1`),conv2:n(`${s}/conv2`)}}return{extractConvLayerParams:n,extractResidualLayerParams:a}}function Ro(o){let t=[],{extractConvLayerParams:e,extractResidualLayerParams:r}=Rn(o,t),n=e("conv32_down"),a=r("conv32_1"),s=r("conv32_2"),i=r("conv32_3"),c=r("conv64_down"),m=r("conv64_1"),p=r("conv64_2"),d=r("conv64_3"),u=r("conv128_down"),l=r("conv128_1"),g=r("conv128_2"),_=r("conv256_down"),h=r("conv256_1"),v=r("conv256_2"),F=r("conv256_down_out"),{fc:y}=o;if(t.push({originalPath:"fc",paramPath:"fc"}),!Mr(y))throw new Error(`expected weightMap[fc] to be a Tensor2D, instead have ${y}`);let k={conv32_down:n,conv32_1:a,conv32_2:s,conv32_3:i,conv64_down:c,conv64_1:m,conv64_2:p,conv64_3:d,conv128_down:u,conv128_1:l,conv128_2:g,conv256_down:_,conv256_1:h,conv256_2:v,conv256_down_out:F,fc:y};return A(o,t),{params:k,paramMappings:t}}var B=b();function ot(o,t){let e=Wo(o,t.conv1);return e=ro(e,t.conv2),e=B.add(e,o),e=B.relu(e),e}function Re(o,t){let e=ur(o,t.conv1);e=ro(e,t.conv2);let r=B.avgPool(o,2,2,"valid"),n=B.zeros(r.shape),a=r.shape[3]!==e.shape[3];if(r.shape[1]!==e.shape[1]||r.shape[2]!==e.shape[2]){let i=[...e.shape];i[1]=1;let c=B.zeros(i);e=B.concat([e,c],1);let m=[...e.shape];m[2]=1;let p=B.zeros(m);e=B.concat([e,p],2)}return r=a?B.concat([r,n],3):r,e=B.add(r,e),e=B.relu(e),e}var xe=class extends L{constructor(){super("FaceRecognitionNet")}forwardInput(t){let{params:e}=this;if(!e)throw new Error("FaceRecognitionNet - load model before inference");return V.tidy(()=>{let r=V.cast(t.toBatchTensor(150,!0),"float32"),a=rt(r,[122.782,117.001,104.298]).div(V.scalar(256)),s=ur(a,e.conv32_down);s=V.maxPool(s,3,2,"valid"),s=ot(s,e.conv32_1),s=ot(s,e.conv32_2),s=ot(s,e.conv32_3),s=Re(s,e.conv64_down),s=ot(s,e.conv64_1),s=ot(s,e.conv64_2),s=ot(s,e.conv64_3),s=Re(s,e.conv128_down),s=ot(s,e.conv128_1),s=ot(s,e.conv128_2),s=Re(s,e.conv256_down),s=ot(s,e.conv256_1),s=ot(s,e.conv256_2),s=Re(s,e.conv256_down_out);let i=s.mean([1,2]);return V.matMul(i,e.fc)})}async forward(t){return this.forwardInput(await D(t))}async computeFaceDescriptor(t){var a;if((a=t==null?void 0:t.shape)==null?void 0:a.some(s=>s<=0))return new Float32Array(128);let e=await D(t),r=V.tidy(()=>V.unstack(this.forwardInput(e))),n=await Promise.all(r.map(s=>s.data()));return r.forEach(s=>s.dispose()),e.isBatchInput?n:n[0]}getDefaultModelName(){return"face_recognition_model"}extractParamsFromWeightMap(t){return Ro(t)}extractParams(t){return Bo(t)}};function $n(o){let t=new xe;return t.extractWeights(o),t}function lr(o,t){return{...o,...{descriptor:t}}}function On(o){return typeof o.age=="number"}function fr(o,t){return{...o,...{age:t}}}function jn(o){return(o.gender===vt.MALE||o.gender===vt.FEMALE)&&ee(o.genderProbability)}function hr(o,t,e){return{...o,...{gender:t,genderProbability:e}}}var at=b();var nt=b();function Hn(o,t){function e(c,m){let p=nt.tensor4d(o(3*3*c),[3,3,c,1]),d=nt.tensor1d(o(c)),u=nt.tensor1d(o(c)),l=nt.tensor1d(o(c)),g=nt.tensor1d(o(c));return t.push({paramPath:`${m}/filters`},{paramPath:`${m}/batch_norm_scale`},{paramPath:`${m}/batch_norm_offset`},{paramPath:`${m}/batch_norm_mean`},{paramPath:`${m}/batch_norm_variance`}),{filters:p,batch_norm_scale:d,batch_norm_offset:u,batch_norm_mean:l,batch_norm_variance:g}}function r(c,m,p,d,u){let l=nt.tensor4d(o(c*m*p*p),[p,p,c,m]),g=nt.tensor1d(o(m));return t.push({paramPath:`${d}/filters`},{paramPath:`${d}/${u?"batch_norm_offset":"bias"}`}),{filters:l,bias:g}}function n(c,m,p,d){let{filters:u,bias:l}=r(c,m,p,d,!0);return{filters:u,batch_norm_offset:l}}function a(c,m,p){let d=e(c,`${p}/depthwise_conv`),u=n(c,m,1,`${p}/pointwise_conv`);return{depthwise_conv:d,pointwise_conv:u}}function s(){let c=n(3,32,3,"mobilenetv1/conv_0"),m=a(32,64,"mobilenetv1/conv_1"),p=a(64,128,"mobilenetv1/conv_2"),d=a(128,128,"mobilenetv1/conv_3"),u=a(128,256,"mobilenetv1/conv_4"),l=a(256,256,"mobilenetv1/conv_5"),g=a(256,512,"mobilenetv1/conv_6"),_=a(512,512,"mobilenetv1/conv_7"),h=a(512,512,"mobilenetv1/conv_8"),v=a(512,512,"mobilenetv1/conv_9"),F=a(512,512,"mobilenetv1/conv_10"),y=a(512,512,"mobilenetv1/conv_11"),k=a(512,1024,"mobilenetv1/conv_12"),Y=a(1024,1024,"mobilenetv1/conv_13");return{conv_0:c,conv_1:m,conv_2:p,conv_3:d,conv_4:u,conv_5:l,conv_6:g,conv_7:_,conv_8:h,conv_9:v,conv_10:F,conv_11:y,conv_12:k,conv_13:Y}}function i(){let c=n(1024,256,1,"prediction_layer/conv_0"),m=n(256,512,3,"prediction_layer/conv_1"),p=n(512,128,1,"prediction_layer/conv_2"),d=n(128,256,3,"prediction_layer/conv_3"),u=n(256,128,1,"prediction_layer/conv_4"),l=n(128,256,3,"prediction_layer/conv_5"),g=n(256,64,1,"prediction_layer/conv_6"),_=n(64,128,3,"prediction_layer/conv_7"),h=r(512,12,1,"prediction_layer/box_predictor_0/box_encoding_predictor"),v=r(512,9,1,"prediction_layer/box_predictor_0/class_predictor"),F=r(1024,24,1,"prediction_layer/box_predictor_1/box_encoding_predictor"),y=r(1024,18,1,"prediction_layer/box_predictor_1/class_predictor"),k=r(512,24,1,"prediction_layer/box_predictor_2/box_encoding_predictor"),Y=r(512,18,1,"prediction_layer/box_predictor_2/class_predictor"),tt=r(256,24,1,"prediction_layer/box_predictor_3/box_encoding_predictor"),st=r(256,18,1,"prediction_layer/box_predictor_3/class_predictor"),U=r(256,24,1,"prediction_layer/box_predictor_4/box_encoding_predictor"),_t=r(256,18,1,"prediction_layer/box_predictor_4/class_predictor"),wt=r(128,24,1,"prediction_layer/box_predictor_5/box_encoding_predictor"),Pt=r(128,18,1,"prediction_layer/box_predictor_5/class_predictor");return{conv_0:c,conv_1:m,conv_2:p,conv_3:d,conv_4:u,conv_5:l,conv_6:g,conv_7:_,box_predictor_0:{box_encoding_predictor:h,class_predictor:v},box_predictor_1:{box_encoding_predictor:F,class_predictor:y},box_predictor_2:{box_encoding_predictor:k,class_predictor:Y},box_predictor_3:{box_encoding_predictor:tt,class_predictor:st},box_predictor_4:{box_encoding_predictor:U,class_predictor:_t},box_predictor_5:{box_encoding_predictor:wt,class_predictor:Pt}}}return{extractMobilenetV1Params:s,extractPredictionLayerParams:i}}function $o(o){let t=[],{extractWeights:e,getRemainingWeights:r}=W(o),{extractMobilenetV1Params:n,extractPredictionLayerParams:a}=Hn(e,t),s=n(),i=a(),m={extra_dim:nt.tensor3d(e(5118*4),[1,5118,4])};if(t.push({paramPath:"output_layer/extra_dim"}),r().length!==0)throw new Error(`weights remaing after extract: ${r().length}`);return{params:{mobilenetv1:s,prediction_layer:i,output_layer:m},paramMappings:t}}function Yn(o,t){let e=O(o,t);function r(m,p,d){let u=e(`${m}/Conv2d_${p}_pointwise/weights`,4,`${d}/filters`),l=e(`${m}/Conv2d_${p}_pointwise/convolution_bn_offset`,1,`${d}/batch_norm_offset`);return{filters:u,batch_norm_offset:l}}function n(m){let p=`mobilenetv1/conv_${m}`,d=`MobilenetV1/Conv2d_${m}_depthwise`,u=`${p}/depthwise_conv`,l=`${p}/pointwise_conv`,g=e(`${d}/depthwise_weights`,4,`${u}/filters`),_=e(`${d}/BatchNorm/gamma`,1,`${u}/batch_norm_scale`),h=e(`${d}/BatchNorm/beta`,1,`${u}/batch_norm_offset`),v=e(`${d}/BatchNorm/moving_mean`,1,`${u}/batch_norm_mean`),F=e(`${d}/BatchNorm/moving_variance`,1,`${u}/batch_norm_variance`);return{depthwise_conv:{filters:g,batch_norm_scale:_,batch_norm_offset:h,batch_norm_mean:v,batch_norm_variance:F},pointwise_conv:r("MobilenetV1",m,l)}}function a(){return{conv_0:r("MobilenetV1",0,"mobilenetv1/conv_0"),conv_1:n(1),conv_2:n(2),conv_3:n(3),conv_4:n(4),conv_5:n(5),conv_6:n(6),conv_7:n(7),conv_8:n(8),conv_9:n(9),conv_10:n(10),conv_11:n(11),conv_12:n(12),conv_13:n(13)}}function s(m,p){let d=e(`${m}/weights`,4,`${p}/filters`),u=e(`${m}/biases`,1,`${p}/bias`);return{filters:d,bias:u}}function i(m){let p=s(`Prediction/BoxPredictor_${m}/BoxEncodingPredictor`,`prediction_layer/box_predictor_${m}/box_encoding_predictor`),d=s(`Prediction/BoxPredictor_${m}/ClassPredictor`,`prediction_layer/box_predictor_${m}/class_predictor`);return{box_encoding_predictor:p,class_predictor:d}}function c(){return{conv_0:r("Prediction",0,"prediction_layer/conv_0"),conv_1:r("Prediction",1,"prediction_layer/conv_1"),conv_2:r("Prediction",2,"prediction_layer/conv_2"),conv_3:r("Prediction",3,"prediction_layer/conv_3"),conv_4:r("Prediction",4,"prediction_layer/conv_4"),conv_5:r("Prediction",5,"prediction_layer/conv_5"),conv_6:r("Prediction",6,"prediction_layer/conv_6"),conv_7:r("Prediction",7,"prediction_layer/conv_7"),box_predictor_0:i(0),box_predictor_1:i(1),box_predictor_2:i(2),box_predictor_3:i(3),box_predictor_4:i(4),box_predictor_5:i(5)}}return{extractMobilenetV1Params:a,extractPredictionLayerParams:c}}function Oo(o){let t=[],{extractMobilenetV1Params:e,extractPredictionLayerParams:r}=Yn(o,t),n=o["Output/extra_dim"];if(t.push({originalPath:"Output/extra_dim",paramPath:"output_layer/extra_dim"}),!ht(n))throw new Error(`expected weightMap['Output/extra_dim'] to be a Tensor3D, instead have ${n}`);let a={mobilenetv1:e(),prediction_layer:r(),output_layer:{extra_dim:n}};return A(o,t),{params:a,paramMappings:t}}var yt=b();var Lt=b();function J(o,t,e){return Lt.tidy(()=>{let r=Lt.conv2d(o,t.filters,e,"same");return r=Lt.add(r,t.batch_norm_offset),Lt.clipByValue(r,0,6)})}var Gn=.0010000000474974513;function zn(o,t,e){return yt.tidy(()=>{let r=yt.depthwiseConv2d(o,t.filters,e,"same");return r=yt.batchNorm(r,t.batch_norm_mean,t.batch_norm_variance,t.batch_norm_offset,t.batch_norm_scale,Gn),yt.clipByValue(r,0,6)})}function Vn(o){return[2,4,6,12].some(t=>t===o)?[2,2]:[1,1]}function jo(o,t){return yt.tidy(()=>{let e,r=J(o,t.conv_0,[2,2]);if([t.conv_1,t.conv_2,t.conv_3,t.conv_4,t.conv_5,t.conv_6,t.conv_7,t.conv_8,t.conv_9,t.conv_10,t.conv_11,t.conv_12,t.conv_13].forEach((a,s)=>{let i=s+1,c=Vn(i);r=zn(r,a.depthwise_conv,c),r=J(r,a.pointwise_conv,[1,1]),i===11&&(e=r)}),e===null)throw new Error("mobileNetV1 - output of conv layer 11 is null");return{out:r,conv11:e}})}function Un(o,t,e){let r=o.arraySync(),n=Math.min(r[t][0],r[t][2]),a=Math.min(r[t][1],r[t][3]),s=Math.max(r[t][0],r[t][2]),i=Math.max(r[t][1],r[t][3]),c=Math.min(r[e][0],r[e][2]),m=Math.min(r[e][1],r[e][3]),p=Math.max(r[e][0],r[e][2]),d=Math.max(r[e][1],r[e][3]),u=(s-n)*(i-a),l=(p-c)*(d-m);if(u<=0||l<=0)return 0;let g=Math.max(n,c),_=Math.max(a,m),h=Math.min(s,p),v=Math.min(i,d),F=Math.max(h-g,0)*Math.max(v-_,0);return F/(u+l-F)}function Ho(o,t,e,r,n){let a=o.shape[0],s=Math.min(e,a),i=t.map((p,d)=>({score:p,boxIndex:d})).filter(p=>p.score>n).sort((p,d)=>d.score-p.score),c=p=>p<=r?1:0,m=[];return i.forEach(p=>{if(m.length>=s)return;let d=p.score;for(let u=m.length-1;u>=0;--u){let l=Un(o,p.boxIndex,m[u]);if(l!==0&&(p.score*=c(l),p.score<=n))break}d===p.score&&m.push(p.boxIndex)}),m}var f=b();function Xn(o){let t=f.unstack(f.transpose(o,[1,0])),e=[f.sub(t[2],t[0]),f.sub(t[3],t[1])],r=[f.add(t[0],f.div(e[0],f.scalar(2))),f.add(t[1],f.div(e[1],f.scalar(2)))];return{sizes:e,centers:r}}function Jn(o,t){let{sizes:e,centers:r}=Xn(o),n=f.unstack(f.transpose(t,[1,0])),a=f.div(f.mul(f.exp(f.div(n[2],f.scalar(5))),e[0]),f.scalar(2)),s=f.add(f.mul(f.div(n[0],f.scalar(10)),e[0]),r[0]),i=f.div(f.mul(f.exp(f.div(n[3],f.scalar(5))),e[1]),f.scalar(2)),c=f.add(f.mul(f.div(n[1],f.scalar(10)),e[1]),r[1]);return f.transpose(f.stack([f.sub(s,a),f.sub(c,i),f.add(s,a),f.add(c,i)]),[1,0])}function Yo(o,t,e){return f.tidy(()=>{let r=o.shape[0],n=Jn(f.reshape(f.tile(e.extra_dim,[r,1,1]),[-1,4]),f.reshape(o,[-1,4]));n=f.reshape(n,[r,n.shape[0]/r,4]);let a=f.sigmoid(f.slice(t,[0,0,1],[-1,-1,-1])),s=f.slice(a,[0,0,0],[-1,-1,1]);s=f.reshape(s,[r,s.shape[1]]);let i=f.unstack(n),c=f.unstack(s);return{boxes:i,scores:c}})}var Oe=b();var $e=b();function Ut(o,t){return $e.tidy(()=>{let e=o.shape[0],r=$e.reshape(zt(o,t.box_encoding_predictor),[e,-1,1,4]),n=$e.reshape(zt(o,t.class_predictor),[e,-1,3]);return{boxPredictionEncoding:r,classPrediction:n}})}function Go(o,t,e){return Oe.tidy(()=>{let r=J(o,e.conv_0,[1,1]),n=J(r,e.conv_1,[2,2]),a=J(n,e.conv_2,[1,1]),s=J(a,e.conv_3,[2,2]),i=J(s,e.conv_4,[1,1]),c=J(i,e.conv_5,[2,2]),m=J(c,e.conv_6,[1,1]),p=J(m,e.conv_7,[2,2]),d=Ut(t,e.box_predictor_0),u=Ut(o,e.box_predictor_1),l=Ut(n,e.box_predictor_2),g=Ut(s,e.box_predictor_3),_=Ut(c,e.box_predictor_4),h=Ut(p,e.box_predictor_5),v=Oe.concat([d.boxPredictionEncoding,u.boxPredictionEncoding,l.boxPredictionEncoding,g.boxPredictionEncoding,_.boxPredictionEncoding,h.boxPredictionEncoding],1),F=Oe.concat([d.classPrediction,u.classPrediction,l.classPrediction,g.classPrediction,_.classPrediction,h.classPrediction],1);return{boxPredictions:v,classPredictions:F}})}var q=class{constructor({minConfidence:t,maxResults:e}={}){this._name="SsdMobilenetv1Options";if(this._minConfidence=t||.5,this._maxResults=e||100,typeof this._minConfidence!="number"||this._minConfidence<=0||this._minConfidence>=1)throw new Error(`${this._name} - expected minConfidence to be a number between 0 and 1`);if(typeof this._maxResults!="number")throw new Error(`${this._name} - expected maxResults to be a number`)}get minConfidence(){return this._minConfidence}get maxResults(){return this._maxResults}};var Xt=class extends L{constructor(){super("SsdMobilenetv1")}forwardInput(t){let{params:e}=this;if(!e)throw new Error("SsdMobilenetv1 - load model before inference");return at.tidy(()=>{let r=at.cast(t.toBatchTensor(512,!1),"float32"),n=at.sub(at.mul(r,at.scalar(.007843137718737125)),at.scalar(1)),a=jo(n,e.mobilenetv1),{boxPredictions:s,classPredictions:i}=Go(a.out,a.conv11,e.prediction_layer);return Yo(s,i,e.output_layer)})}async forward(t){return this.forwardInput(await D(t))}async locateFaces(t,e={}){let{maxResults:r,minConfidence:n}=new q(e),a=await D(t),{boxes:s,scores:i}=this.forwardInput(a),c=s[0],m=i[0];for(let y=1;y{let[k,Y]=[Math.max(0,v[y][0]),Math.min(1,v[y][2])].map(U=>U*h),[tt,st]=[Math.max(0,v[y][1]),Math.min(1,v[y][3])].map(U=>U*_);return new E(p[y],new oe(tt,k,st-tt,Y-k),{height:a.getInputHeight(0),width:a.getInputWidth(0)})});return c.dispose(),m.dispose(),F}getDefaultModelName(){return"ssd_mobilenetv1_model"}extractParamsFromWeightMap(t){return Oo(t)}extractParams(t){return $o(t)}};function zo(o){let t=new Xt;return t.extractWeights(o),t}function qn(o){return zo(o)}var Vo=class extends Xt{};var Uo=.4,Xo=[new x(.738768,.874946),new x(2.42204,2.65704),new x(4.30971,7.04493),new x(10.246,4.59428),new x(12.6868,11.8741)],Jo=[new x(1.603231,2.094468),new x(6.041143,7.080126),new x(2.882459,3.518061),new x(4.266906,5.178857),new x(9.041765,10.66308)],qo=[117.001,114.697,97.404],Zo="tiny_yolov2_model",Ko="tiny_yolov2_separable_conv_model";var C=b();var xr=o=>typeof o=="number";function oo(o){if(!o)throw new Error(`invalid config: ${o}`);if(typeof o.withSeparableConvs!="boolean")throw new Error(`config.withSeparableConvs has to be a boolean, have: ${o.withSeparableConvs}`);if(!xr(o.iouThreshold)||o.iouThreshold<0||o.iouThreshold>1)throw new Error(`config.iouThreshold has to be a number between [0, 1], have: ${o.iouThreshold}`);if(!Array.isArray(o.classes)||!o.classes.length||!o.classes.every(t=>typeof t=="string"))throw new Error(`config.classes has to be an array class names: string[], have: ${JSON.stringify(o.classes)}`);if(!Array.isArray(o.anchors)||!o.anchors.length||!o.anchors.map(t=>t||{}).every(t=>xr(t.x)&&xr(t.y)))throw new Error(`config.anchors has to be an array of { x: number, y: number }, have: ${JSON.stringify(o.anchors)}`);if(o.meanRgb&&(!Array.isArray(o.meanRgb)||o.meanRgb.length!==3||!o.meanRgb.every(xr)))throw new Error(`config.meanRgb has to be an array of shape [number, number, number], have: ${JSON.stringify(o.meanRgb)}`)}var K=b();var Z=b();function be(o){return Z.tidy(()=>{let t=Z.mul(o,Z.scalar(.10000000149011612));return Z.add(Z.relu(Z.sub(o,t)),t)})}function Ft(o,t){return K.tidy(()=>{let e=K.pad(o,[[0,0],[1,1],[1,1],[0,0]]);return e=K.conv2d(e,t.conv.filters,[1,1],"valid"),e=K.sub(e,t.bn.sub),e=K.mul(e,t.bn.truediv),e=K.add(e,t.conv.bias),be(e)})}var St=b();function Tt(o,t){return St.tidy(()=>{let e=St.pad(o,[[0,0],[1,1],[1,1],[0,0]]);return e=St.separableConv2d(e,t.depthwise_filter,t.pointwise_filter,[1,1],"valid"),e=St.add(e,t.bias),be(e)})}var no=b();function Zn(o,t){let e=ce(o,t);function r(s,i){let c=no.tensor1d(o(s)),m=no.tensor1d(o(s));return t.push({paramPath:`${i}/sub`},{paramPath:`${i}/truediv`}),{sub:c,truediv:m}}function n(s,i,c){let m=e(s,i,3,`${c}/conv`),p=r(i,`${c}/bn`);return{conv:m,bn:p}}let a=me(o,t);return{extractConvParams:e,extractConvWithBatchNormParams:n,extractSeparableConvParams:a}}function Qo(o,t,e,r){let{extractWeights:n,getRemainingWeights:a}=W(o),s=[],{extractConvParams:i,extractConvWithBatchNormParams:c,extractSeparableConvParams:m}=Zn(n,s),p;if(t.withSeparableConvs){let[d,u,l,g,_,h,v,F,y]=r,k=t.isFirstLayerConv2d?i(d,u,3,"conv0"):m(d,u,"conv0"),Y=m(u,l,"conv1"),tt=m(l,g,"conv2"),st=m(g,_,"conv3"),U=m(_,h,"conv4"),_t=m(h,v,"conv5"),wt=F?m(v,F,"conv6"):void 0,Pt=y?m(F,y,"conv7"):void 0,te=i(y||F||v,5*e,1,"conv8");p={conv0:k,conv1:Y,conv2:tt,conv3:st,conv4:U,conv5:_t,conv6:wt,conv7:Pt,conv8:te}}else{let[d,u,l,g,_,h,v,F,y]=r,k=c(d,u,"conv0"),Y=c(u,l,"conv1"),tt=c(l,g,"conv2"),st=c(g,_,"conv3"),U=c(_,h,"conv4"),_t=c(h,v,"conv5"),wt=c(v,F,"conv6"),Pt=c(F,y,"conv7"),te=i(y,5*e,1,"conv8");p={conv0:k,conv1:Y,conv2:tt,conv3:st,conv4:U,conv5:_t,conv6:wt,conv7:Pt,conv8:te}}if(a().length!==0)throw new Error(`weights remaing after extract: ${a().length}`);return{params:p,paramMappings:s}}function Kn(o,t){let e=O(o,t);function r(i){let c=e(`${i}/sub`,1),m=e(`${i}/truediv`,1);return{sub:c,truediv:m}}function n(i){let c=e(`${i}/filters`,4),m=e(`${i}/bias`,1);return{filters:c,bias:m}}function a(i){let c=n(`${i}/conv`),m=r(`${i}/bn`);return{conv:c,bn:m}}let s=pe(e);return{extractConvParams:n,extractConvWithBatchNormParams:a,extractSeparableConvParams:s}}function tn(o,t){let e=[],{extractConvParams:r,extractConvWithBatchNormParams:n,extractSeparableConvParams:a}=Kn(o,e),s;if(t.withSeparableConvs){let i=t.filterSizes&&t.filterSizes.length||9;s={conv0:t.isFirstLayerConv2d?r("conv0"):a("conv0"),conv1:a("conv1"),conv2:a("conv2"),conv3:a("conv3"),conv4:a("conv4"),conv5:a("conv5"),conv6:i>7?a("conv6"):void 0,conv7:i>8?a("conv7"):void 0,conv8:r("conv8")}}else s={conv0:n("conv0"),conv1:n("conv1"),conv2:n("conv2"),conv3:n("conv3"),conv4:n("conv4"),conv5:n("conv5"),conv6:n("conv6"),conv7:n("conv7"),conv8:r("conv8")};return A(o,e),{params:s,paramMappings:e}}var ut=class{constructor({inputSize:t,scoreThreshold:e}={}){this._name="TinyYolov2Options";if(this._inputSize=t||416,this._scoreThreshold=e||.5,typeof this._inputSize!="number"||this._inputSize%32!=0)throw new Error(`${this._name} - expected inputSize to be a number divisible by 32`);if(typeof this._scoreThreshold!="number"||this._scoreThreshold<=0||this._scoreThreshold>=1)throw new Error(`${this._name} - expected scoreThreshold to be a number between 0 and 1`)}get inputSize(){return this._inputSize}get scoreThreshold(){return this._scoreThreshold}};var ao=class extends L{constructor(t){super("TinyYolov2");oo(t),this._config=t}get config(){return this._config}get withClassScores(){return this.config.withClassScores||this.config.classes.length>1}get boxEncodingSize(){return 5+(this.withClassScores?this.config.classes.length:0)}runTinyYolov2(t,e){let r=Ft(t,e.conv0);return r=C.maxPool(r,[2,2],[2,2],"same"),r=Ft(r,e.conv1),r=C.maxPool(r,[2,2],[2,2],"same"),r=Ft(r,e.conv2),r=C.maxPool(r,[2,2],[2,2],"same"),r=Ft(r,e.conv3),r=C.maxPool(r,[2,2],[2,2],"same"),r=Ft(r,e.conv4),r=C.maxPool(r,[2,2],[2,2],"same"),r=Ft(r,e.conv5),r=C.maxPool(r,[2,2],[1,1],"same"),r=Ft(r,e.conv6),r=Ft(r,e.conv7),zt(r,e.conv8,"valid",!1)}runMobilenet(t,e){let r=this.config.isFirstLayerConv2d?be(zt(t,e.conv0,"valid",!1)):Tt(t,e.conv0);return r=C.maxPool(r,[2,2],[2,2],"same"),r=Tt(r,e.conv1),r=C.maxPool(r,[2,2],[2,2],"same"),r=Tt(r,e.conv2),r=C.maxPool(r,[2,2],[2,2],"same"),r=Tt(r,e.conv3),r=C.maxPool(r,[2,2],[2,2],"same"),r=Tt(r,e.conv4),r=C.maxPool(r,[2,2],[2,2],"same"),r=Tt(r,e.conv5),r=C.maxPool(r,[2,2],[1,1],"same"),r=e.conv6?Tt(r,e.conv6):r,r=e.conv7?Tt(r,e.conv7):r,zt(r,e.conv8,"valid",!1)}forwardInput(t,e){let{params:r}=this;if(!r)throw new Error("TinyYolov2 - load model before inference");return C.tidy(()=>{let n=C.cast(t.toBatchTensor(e,!1),"float32");return n=this.config.meanRgb?rt(n,this.config.meanRgb):n,n=n.div(C.scalar(256)),this.config.withSeparableConvs?this.runMobilenet(n,r):this.runTinyYolov2(n,r)})}async forward(t,e){return this.forwardInput(await D(t),e)}async detect(t,e={}){let{inputSize:r,scoreThreshold:n}=new ut(e),a=await D(t),s=await this.forwardInput(a,r),i=C.tidy(()=>C.unstack(s)[0].expandDims()),c={width:a.getInputWidth(0),height:a.getInputHeight(0)},m=await this.extractBoxes(i,a.getReshapedInputDimensions(0),n);s.dispose(),i.dispose();let p=m.map(h=>h.box),d=m.map(h=>h.score),u=m.map(h=>h.classScore),l=m.map(h=>this.config.classes[h.label]);return Lr(p.map(h=>h.rescale(r)),d,this.config.iouThreshold,!0).map(h=>new Dt(d[h],u[h],l[h],p[h],c))}getDefaultModelName(){return""}extractParamsFromWeightMap(t){return tn(t,this.config)}extractParams(t){let e=this.config.filterSizes||ao.DEFAULT_FILTER_SIZES,r=e?e.length:void 0;if(r!==7&&r!==8&&r!==9)throw new Error(`TinyYolov2 - expected 7 | 8 | 9 convolutional filters, but found ${r} filterSizes in config`);return Qo(t,this.config,this.boxEncodingSize,e)}async extractBoxes(t,e,r){let{width:n,height:a}=e,s=Math.max(n,a),i=s/n,c=s/a,m=t.shape[1],p=this.config.anchors.length,[d,u,l]=C.tidy(()=>{let v=t.reshape([m,m,p,this.boxEncodingSize]),F=v.slice([0,0,0,0],[m,m,p,4]),y=v.slice([0,0,0,4],[m,m,p,1]),k=this.withClassScores?C.softmax(v.slice([0,0,0,5],[m,m,p,this.config.classes.length]),3):C.scalar(0);return[F,y,k]}),g=[],_=await u.array(),h=await d.array();for(let v=0;vr){let Y=(F+De(h[v][F][y][0]))/m*i,tt=(v+De(h[v][F][y][1]))/m*c,st=Math.exp(h[v][F][y][2])*this.config.anchors[y].x/m*i,U=Math.exp(h[v][F][y][3])*this.config.anchors[y].y/m*c,_t=Y-st/2,wt=tt-U/2,Pt={row:v,col:F,anchor:y},{classScore:te,label:po}=this.withClassScores?await this.extractPredictedClass(l,Pt):{classScore:1,label:0};g.push({box:new re(_t,wt,_t+st,wt+U),score:k,classScore:k*te,label:po,...Pt})}}return d.dispose(),u.dispose(),l.dispose(),g}async extractPredictedClass(t,e){let{row:r,col:n,anchor:a}=e,s=await t.array();return Array(this.config.classes.length).fill(0).map((i,c)=>s[r][n][a][c]).map((i,c)=>({classScore:i,label:c})).reduce((i,c)=>i.classScore>c.classScore?i:c)}},ge=ao;ge.DEFAULT_FILTER_SIZES=[3,16,32,64,128,256,512,1024,1024];var ve=class extends ge{constructor(t=!0){let e={withSeparableConvs:t,iouThreshold:Uo,classes:["face"],...t?{anchors:Jo,meanRgb:qo}:{anchors:Xo,withClassScores:!0}};super(e)}get withSeparableConvs(){return this.config.withSeparableConvs}get anchors(){return this.config.anchors}async locateFaces(t,e){return(await this.detect(t,e)).map(n=>new E(n.score,n.relativeBox,{width:n.imageWidth,height:n.imageHeight}))}getDefaultModelName(){return this.withSeparableConvs?Ko:Zo}extractParamsFromWeightMap(t){return super.extractParamsFromWeightMap(t)}};function Qn(o,t=!0){let e=new ve(t);return e.extractWeights(o),e}var br=class extends ut{constructor(){super(...arguments);this._name="TinyFaceDetectorOptions"}};var Q=class{async then(t){return t(await this.run())}async run(){throw new Error("ComposableTask - run is not implemented")}};var je=b();var so=b();async function Jt(o,t,e,r,n=({alignedRect:a})=>a){let a=o.map(c=>Vt(c)?n(c):c.detection),s=r||(t instanceof so.Tensor?await se(t,a):await ae(t,a)),i=await e(s);return s.forEach(c=>c instanceof so.Tensor&&c.dispose()),i}async function ye(o,t,e,r,n){return Jt([o],t,async a=>e(a[0]),r,n)}var en=.4,rn=[new x(1.603231,2.094468),new x(6.041143,7.080126),new x(2.882459,3.518061),new x(4.266906,5.178857),new x(9.041765,10.66308)],on=[117.001,114.697,97.404];var Fe=class extends ge{constructor(){let t={withSeparableConvs:!0,iouThreshold:en,classes:["face"],anchors:rn,meanRgb:on,isFirstLayerConv2d:!0,filterSizes:[3,16,32,64,128,256,512]};super(t)}get anchors(){return this.config.anchors}async locateFaces(t,e){return(await this.detect(t,e)).map(n=>new E(n.score,n.relativeBox,{width:n.imageWidth,height:n.imageHeight}))}getDefaultModelName(){return"tiny_face_detector_model"}extractParamsFromWeightMap(t){return super.extractParamsFromWeightMap(t)}};var T={ssdMobilenetv1:new Xt,tinyFaceDetector:new Fe,tinyYolov2:new ve,faceLandmark68Net:new fe,faceLandmark68TinyNet:new pr,faceRecognitionNet:new xe,faceExpressionNet:new ir,ageGenderNet:new mr},nn=(o,t)=>T.ssdMobilenetv1.locateFaces(o,t),ta=(o,t)=>T.tinyFaceDetector.locateFaces(o,t),ea=(o,t)=>T.tinyYolov2.locateFaces(o,t),an=o=>T.faceLandmark68Net.detectLandmarks(o),ra=o=>T.faceLandmark68TinyNet.detectLandmarks(o),oa=o=>T.faceRecognitionNet.computeFaceDescriptor(o),na=o=>T.faceExpressionNet.predictExpressions(o),aa=o=>T.ageGenderNet.predictAgeAndGender(o),sn=o=>T.ssdMobilenetv1.load(o),sa=o=>T.tinyFaceDetector.load(o),ia=o=>T.tinyYolov2.load(o),ca=o=>T.faceLandmark68Net.load(o),ma=o=>T.faceLandmark68TinyNet.load(o),pa=o=>T.faceRecognitionNet.load(o),da=o=>T.faceExpressionNet.load(o),ua=o=>T.ageGenderNet.load(o),la=sn,fa=nn,ha=an;var io=class extends Q{constructor(t,e,r){super();this.parentTask=t;this.input=e;this.extractedFaces=r}},we=class extends io{async run(){let t=await this.parentTask,e=await Jt(t,this.input,async r=>Promise.all(r.map(n=>T.faceExpressionNet.predictExpressions(n))),this.extractedFaces);return t.map((r,n)=>cr(r,e[n]))}withAgeAndGender(){return new Te(this,this.input)}},Pe=class extends io{async run(){let t=await this.parentTask;if(!t)return;let e=await ye(t,this.input,r=>T.faceExpressionNet.predictExpressions(r),this.extractedFaces);return cr(t,e)}withAgeAndGender(){return new _e(this,this.input)}},Kt=class extends we{withAgeAndGender(){return new qt(this,this.input)}withFaceDescriptors(){return new At(this,this.input)}},Qt=class extends Pe{withAgeAndGender(){return new Zt(this,this.input)}withFaceDescriptor(){return new Wt(this,this.input)}};var co=class extends Q{constructor(t,e,r){super();this.parentTask=t;this.input=e;this.extractedFaces=r}},Te=class extends co{async run(){let t=await this.parentTask,e=await Jt(t,this.input,async r=>Promise.all(r.map(n=>T.ageGenderNet.predictAgeAndGender(n))),this.extractedFaces);return t.map((r,n)=>{let{age:a,gender:s,genderProbability:i}=e[n];return fr(hr(r,s,i),a)})}withFaceExpressions(){return new we(this,this.input)}},_e=class extends co{async run(){let t=await this.parentTask;if(!t)return;let{age:e,gender:r,genderProbability:n}=await ye(t,this.input,a=>T.ageGenderNet.predictAgeAndGender(a),this.extractedFaces);return fr(hr(t,r,n),e)}withFaceExpressions(){return new Pe(this,this.input)}},qt=class extends Te{withFaceExpressions(){return new Kt(this,this.input)}withFaceDescriptors(){return new At(this,this.input)}},Zt=class extends _e{withFaceExpressions(){return new Qt(this,this.input)}withFaceDescriptor(){return new Wt(this,this.input)}};var gr=class extends Q{constructor(t,e){super();this.parentTask=t;this.input=e}},At=class extends gr{async run(){let t=await this.parentTask;return(await Jt(t,this.input,r=>Promise.all(r.map(n=>T.faceRecognitionNet.computeFaceDescriptor(n))),null,r=>r.landmarks.align(null,{useDlibAlignment:!0}))).map((r,n)=>lr(t[n],r))}withFaceExpressions(){return new Kt(this,this.input)}withAgeAndGender(){return new qt(this,this.input)}},Wt=class extends gr{async run(){let t=await this.parentTask;if(!t)return;let e=await ye(t,this.input,r=>T.faceRecognitionNet.computeFaceDescriptor(r),null,r=>r.landmarks.align(null,{useDlibAlignment:!0}));return lr(t,e)}withFaceExpressions(){return new Qt(this,this.input)}withAgeAndGender(){return new Zt(this,this.input)}};var vr=class extends Q{constructor(t,e,r){super();this.parentTask=t;this.input=e;this.useTinyLandmarkNet=r}get landmarkNet(){return this.useTinyLandmarkNet?T.faceLandmark68TinyNet:T.faceLandmark68Net}},yr=class extends vr{async run(){let t=await this.parentTask,e=t.map(a=>a.detection),r=this.input instanceof je.Tensor?await se(this.input,e):await ae(this.input,e),n=await Promise.all(r.map(a=>this.landmarkNet.detectLandmarks(a)));return r.forEach(a=>a instanceof je.Tensor&&a.dispose()),t.map((a,s)=>le(a,n[s]))}withFaceExpressions(){return new Kt(this,this.input)}withAgeAndGender(){return new qt(this,this.input)}withFaceDescriptors(){return new At(this,this.input)}},Fr=class extends vr{async run(){let t=await this.parentTask;if(!t)return;let{detection:e}=t,r=this.input instanceof je.Tensor?await se(this.input,[e]):await ae(this.input,[e]),n=await this.landmarkNet.detectLandmarks(r[0]);return r.forEach(a=>a instanceof je.Tensor&&a.dispose()),le(t,n)}withFaceExpressions(){return new Qt(this,this.input)}withAgeAndGender(){return new Zt(this,this.input)}withFaceDescriptor(){return new Wt(this,this.input)}};var Tr=class extends Q{constructor(t,e=new q){super();this.input=t;this.options=e}},He=class extends Tr{async run(){let{input:t,options:e}=this,r;if(e instanceof br)r=T.tinyFaceDetector.locateFaces(t,e);else if(e instanceof q)r=T.ssdMobilenetv1.locateFaces(t,e);else if(e instanceof ut)r=T.tinyYolov2.locateFaces(t,e);else throw new Error("detectFaces - expected options to be instance of TinyFaceDetectorOptions | SsdMobilenetv1Options | TinyYolov2Options");return r}runAndExtendWithFaceDetections(){return new Promise(async t=>{let e=await this.run();t(e.map(r=>Ot({},r)))})}withFaceLandmarks(t=!1){return new yr(this.runAndExtendWithFaceDetections(),this.input,t)}withFaceExpressions(){return new we(this.runAndExtendWithFaceDetections(),this.input)}withAgeAndGender(){return new Te(this.runAndExtendWithFaceDetections(),this.input)}},_r=class extends Tr{async run(){let t=await new He(this.input,this.options),e=t[0];return t.forEach(r=>{r.score>e.score&&(e=r)}),e}runAndExtendWithFaceDetection(){return new Promise(async t=>{let e=await this.run();t(e?Ot({},e):void 0)})}withFaceLandmarks(t=!1){return new Fr(this.runAndExtendWithFaceDetection(),this.input,t)}withFaceExpressions(){return new Pe(this.runAndExtendWithFaceDetection(),this.input)}withAgeAndGender(){return new _e(this.runAndExtendWithFaceDetection(),this.input)}};function xa(o,t=new q){return new _r(o,t)}function wr(o,t=new q){return new He(o,t)}async function cn(o,t){return wr(o,new q(t?{minConfidence:t}:{})).withFaceLandmarks().withFaceDescriptors()}async function ba(o,t={}){return wr(o,new ut(t)).withFaceLandmarks().withFaceDescriptors()}var ga=cn;function mo(o,t){if(o.length!==t.length)throw new Error("euclideanDistance: arr1.length !== arr2.length");let e=Array.from(o),r=Array.from(t);return Math.sqrt(e.map((n,a)=>n-r[a]).reduce((n,a)=>n+a**2,0))}var Pr=class{constructor(t,e=.6){this._distanceThreshold=e;let r=Array.isArray(t)?t:[t];if(!r.length)throw new Error("FaceRecognizer.constructor - expected atleast one input");let n=1,a=()=>`person ${n++}`;this._labeledDescriptors=r.map(s=>{if(s instanceof xt)return s;if(s instanceof Float32Array)return new xt(a(),[s]);if(s.descriptor&&s.descriptor instanceof Float32Array)return new xt(a(),[s.descriptor]);throw new Error("FaceRecognizer.constructor - expected inputs to be of type LabeledFaceDescriptors | WithFaceDescriptor | Float32Array | Array | Float32Array>")})}get labeledDescriptors(){return this._labeledDescriptors}get distanceThreshold(){return this._distanceThreshold}computeMeanDistance(t,e){return e.map(r=>mo(r,t)).reduce((r,n)=>r+n,0)/(e.length||1)}matchDescriptor(t){return this.labeledDescriptors.map(({descriptors:e,label:r})=>new Ee(r,this.computeMeanDistance(t,e))).reduce((e,r)=>e.distancet.toJSON())}}static fromJSON(t){let e=t.labeledDescriptors.map(r=>xt.fromJSON(r));return new Pr(e,t.distanceThreshold)}};function va(o){let t=new Fe;return t.extractWeights(o),t}function mn(o,t){let{width:e,height:r}=new S(t.width,t.height);if(e<=0||r<=0)throw new Error(`resizeResults - invalid dimensions: ${JSON.stringify({width:e,height:r})}`);if(Array.isArray(o))return o.map(n=>mn(n,{width:e,height:r}));if(Vt(o)){let n=o.detection.forSize(e,r),a=o.unshiftedLandmarks.forSize(n.box.width,n.box.height);return le(Ot(o,n),a)}return mt(o)?Ot(o,o.detection.forSize(e,r)):o instanceof z||o instanceof E?o.forSize(e,r):o}var Fa=typeof process!="undefined",Ta=typeof navigator!="undefined"&&typeof navigator.userAgent!="undefined",_a={faceapi:Do,node:Fa,browser:Ta};export{mr as AgeGenderNet,re as BoundingBox,P as Box,Q as ComposableTask,At as ComputeAllFaceDescriptorsTask,gr as ComputeFaceDescriptorsTaskBase,Wt as ComputeSingleFaceDescriptorTask,yr as DetectAllFaceLandmarksTask,He as DetectAllFacesTask,vr as DetectFaceLandmarksTaskBase,Tr as DetectFacesTaskBase,Fr as DetectSingleFaceLandmarksTask,_r as DetectSingleFaceTask,S as Dimensions,Xr as FACE_EXPRESSION_LABELS,E as FaceDetection,Vo as FaceDetectionNet,ir as FaceExpressionNet,kt as FaceExpressions,fe as FaceLandmark68Net,pr as FaceLandmark68TinyNet,So as FaceLandmarkNet,z as FaceLandmarks,ho as FaceLandmarks5,ne as FaceLandmarks68,Ee as FaceMatch,Pr as FaceMatcher,xe as FaceRecognitionNet,vt as Gender,Me as LabeledBox,xt as LabeledFaceDescriptors,bt as NetInput,L as NeuralNetwork,Dt as ObjectDetection,x as Point,xo as PredictedBox,oe as Rect,Xt as SsdMobilenetv1,q as SsdMobilenetv1Options,Fe as TinyFaceDetector,br as TinyFaceDetectorOptions,ve as TinyYolov2,ut as TinyYolov2Options,ga as allFaces,cn as allFacesSsdMobilenetv1,ba as allFacesTinyYolov2,Hr as awaitMediaLoaded,Yr as bufferToImage,oa as computeFaceDescriptor,Yt as createCanvas,ke as createCanvasFromMedia,qn as createFaceDetectionNet,$n as createFaceRecognitionNet,zo as createSsdMobilenetv1,va as createTinyFaceDetector,Qn as createTinyYolov2,wr as detectAllFaces,an as detectFaceLandmarks,ra as detectFaceLandmarksTiny,ha as detectLandmarks,xa as detectSingleFace,Po as draw,w as env,mo as euclideanDistance,fr as extendWithAge,lr as extendWithFaceDescriptor,Ot as extendWithFaceDetection,cr as extendWithFaceExpressions,le as extendWithFaceLandmarks,hr as extendWithGender,se as extractFaceTensors,ae as extractFaces,Mn as fetchImage,Vr as fetchJson,Cn as fetchNetWeights,Gt as fetchOrThrow,R as getContext2dOrThrow,Ht as getMediaDimensions,Gr as imageTensorToCanvas,zr as imageToSquare,vn as inverseSigmoid,kr as iou,Je as isMediaElement,Ne as isMediaLoaded,On as isWithAge,mt as isWithFaceDetection,Jr as isWithFaceExpressions,Vt as isWithFaceLandmarks,jn as isWithGender,ua as loadAgeGenderModel,la as loadFaceDetectionModel,da as loadFaceExpressionModel,ca as loadFaceLandmarkModel,ma as loadFaceLandmarkTinyModel,pa as loadFaceRecognitionModel,sn as loadSsdMobilenetv1Model,sa as loadTinyFaceDetectorModel,ia as loadTinyYolov2Model,Ur as loadWeightMap,fa as locateFaces,Nn as matchDimensions,Ir as minBbox,T as nets,Lr as nonMaxSuppression,rt as normalize,Sr as padToSquare,aa as predictAgeAndGender,na as recognizeFaceExpressions,mn as resizeResults,jt as resolveInput,gn as shuffleArray,De as sigmoid,nn as ssdMobilenetv1,ya as tf,ta as tinyFaceDetector,ea as tinyYolov2,D as toNetInput,lo as utils,oo as validateConfig,_a as version};
+var pn=Object.create,Ye=Object.defineProperty,dn=Object.getPrototypeOf,un=Object.prototype.hasOwnProperty,ln=Object.getOwnPropertyNames,fn=Object.getOwnPropertyDescriptor;var Dr=o=>Ye(o,"__esModule",{value:!0});var uo=(o,t)=>()=>(t||(t={exports:{}},o(t.exports,t)),t.exports),Er=(o,t)=>{for(var e in t)Ye(o,e,{get:t[e],enumerable:!0})},ut=(o,t,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ln(t))!un.call(o,r)&&r!=="default"&&Ye(o,r,{get:()=>t[r],enumerable:!(e=fn(t,r))||e.enumerable});return o},hn=o=>ut(Dr(Ye(o!=null?pn(dn(o)):{},"default",o&&o.__esModule&&"default"in o?{get:()=>o.default,enumerable:!0}:{value:o,enumerable:!0})),o);import*as Ca from"@tensorflow/tfjs/dist/index.js";import*as Na from"@tensorflow/tfjs-backend-wasm";var b=uo(xn=>{Dr(xn);ut(xn,Ca);ut(xn,Na)});var go=uo((_n,bo)=>{Dr(_n);Er(_n,{isNodejs:()=>wn});function wn(){return typeof global=="object"&&!0&&typeof bo!="undefined"&&typeof process!="undefined"&&!!process.version}});var ya=b();var Po={};Er(Po,{AnchorPosition:()=>mt,DrawBox:()=>Ue,DrawBoxOptions:()=>jr,DrawFaceLandmarks:()=>Zr,DrawFaceLandmarksOptions:()=>qr,DrawTextField:()=>Et,DrawTextFieldOptions:()=>Ce,drawContour:()=>lt,drawDetections:()=>En,drawFaceExpressions:()=>In,drawFaceLandmarks:()=>kn});function lt(o,t,e=!1){if(o.beginPath(),t.slice(1).forEach(({x:r,y:n},a)=>{let s=t[a];o.moveTo(s.x,s.y),o.lineTo(r,n)}),e){let r=t[t.length-1],n=t[0];if(!r||!n)return;o.moveTo(r.x,r.y),o.lineTo(n.x,n.y)}o.stroke()}var lo={};Er(lo,{computeReshapedDimensions:()=>Nr,getCenterPoint:()=>$t,isDimensions:()=>ze,isEven:()=>Ge,isFloat:()=>Cr,isTensor:()=>Bt,isTensor1D:()=>bn,isTensor2D:()=>Mr,isTensor3D:()=>ft,isTensor4D:()=>z,isValidNumber:()=>et,isValidProbablitiy:()=>ee,range:()=>st,round:()=>Rt});var fo=b();var S=class{constructor(t,e){if(!et(t)||!et(e))throw new Error(`Dimensions.constructor - expected width and height to be valid numbers, instead have ${JSON.stringify({width:t,height:e})}`);this._width=t,this._height=e}get width(){return this._width}get height(){return this._height}reverse(){return new S(1/this.width,1/this.height)}};function Bt(o,t){return o instanceof fo.Tensor&&o.shape.length===t}function bn(o){return Bt(o,1)}function Mr(o){return Bt(o,2)}function ft(o){return Bt(o,3)}function z(o){return Bt(o,4)}function Cr(o){return o%1!=0}function Ge(o){return o%2==0}function Rt(o,t=2){let e=10**t;return Math.floor(o*e)/e}function ze(o){return o&&o.width&&o.height}function Nr({width:o,height:t},e){let r=e/Math.max(t,o);return new S(Math.round(o*r),Math.round(t*r))}function $t(o){return o.reduce((t,e)=>t.add(e),new x(0,0)).div(new x(o.length,o.length))}function st(o,t,e){return Array(o).fill(0).map((r,n)=>t+n*e)}function et(o){return!!o&&o!==Infinity&&o!==-Infinity&&!Number.isNaN(o)||o===0}function ee(o){return et(o)&&o>=0&&o<=1}var x=class{constructor(t,e){this._x=t,this._y=e}get x(){return this._x}get y(){return this._y}add(t){return new x(this.x+t.x,this.y+t.y)}sub(t){return new x(this.x-t.x,this.y-t.y)}mul(t){return new x(this.x*t.x,this.y*t.y)}div(t){return new x(this.x/t.x,this.y/t.y)}abs(){return new x(Math.abs(this.x),Math.abs(this.y))}magnitude(){return Math.sqrt(this.x**2+this.y**2)}floor(){return new x(Math.floor(this.x),Math.floor(this.y))}};var P=class{static isRect(t){return!!t&&[t.x,t.y,t.width,t.height].every(et)}static assertIsValidBox(t,e,r=!1){if(!P.isRect(t))throw new Error(`${e} - invalid box: ${JSON.stringify(t)}, expected object with properties x, y, width, height`);if(!r&&(t.width<0||t.height<0))throw new Error(`${e} - width (${t.width}) and height (${t.height}) must be positive numbers`)}constructor(t,e=!0){let r=t||{},n=[r.left,r.top,r.right,r.bottom].every(et),a=[r.x,r.y,r.width,r.height].every(et);if(!a&&!n)throw new Error(`Box.constructor - expected box to be IBoundingBox | IRect, instead have ${JSON.stringify(r)}`);let[s,i,c,m]=a?[r.x,r.y,r.width,r.height]:[r.left,r.top,r.right-r.left,r.bottom-r.top];P.assertIsValidBox({x:s,y:i,width:c,height:m},"Box.constructor",e),this._x=s,this._y=i,this._width=c,this._height=m}get x(){return this._x}get y(){return this._y}get width(){return this._width}get height(){return this._height}get left(){return this.x}get top(){return this.y}get right(){return this.x+this.width}get bottom(){return this.y+this.height}get area(){return this.width*this.height}get topLeft(){return new x(this.left,this.top)}get topRight(){return new x(this.right,this.top)}get bottomLeft(){return new x(this.left,this.bottom)}get bottomRight(){return new x(this.right,this.bottom)}round(){let[t,e,r,n]=[this.x,this.y,this.width,this.height].map(a=>Math.round(a));return new P({x:t,y:e,width:r,height:n})}floor(){let[t,e,r,n]=[this.x,this.y,this.width,this.height].map(a=>Math.floor(a));return new P({x:t,y:e,width:r,height:n})}toSquare(){let{x:t,y:e,width:r,height:n}=this,a=Math.abs(r-n);return re&&(i=-d+e+r,d=e),u>t&&(c=-u+t+n,u=t),m<1&&(c=2-m,m=1),p<1&&(c=2-p,p=1),{dy:s,edy:c,dx:a,edx:i,y:p,ey:u,x:m,ex:d,w:r,h:n}}calibrate(t){return new P({left:this.left+t.left*this.width,top:this.top+t.top*this.height,right:this.right+t.right*this.width,bottom:this.bottom+t.bottom*this.height}).toSquare().round()}};var re=class extends P{constructor(t,e,r,n,a=!1){super({left:t,top:e,right:r,bottom:n},a)}};var Pt=class{constructor(t,e,r,n,a){this._imageDims=new S(a.width,a.height),this._score=t,this._classScore=e,this._className=r,this._box=new P(n).rescale(this._imageDims)}get score(){return this._score}get classScore(){return this._classScore}get className(){return this._className}get box(){return this._box}get imageDims(){return this._imageDims}get imageWidth(){return this.imageDims.width}get imageHeight(){return this.imageDims.height}get relativeBox(){return new P(this._box).rescale(this.imageDims.reverse())}forSize(t,e){return new Pt(this.score,this.classScore,this.className,this.relativeBox,{width:t,height:e})}};var E=class extends Pt{constructor(t,e,r){super(t,t,"",e,r)}forSize(t,e){let{score:r,relativeBox:n,imageDims:a}=super.forSize(t,e);return new E(r,n,a)}};function Ir(o,t,e=!0){let r=Math.max(0,Math.min(o.right,t.right)-Math.max(o.left,t.left)),n=Math.max(0,Math.min(o.bottom,t.bottom)-Math.max(o.top,t.top)),a=r*n;return e?a/(o.area+t.area-a):a/Math.min(o.area,t.area)}function Lr(o){let t=o.map(i=>i.x),e=o.map(i=>i.y),r=t.reduce((i,c)=>ccii({score:s,boxIndex:i})).sort((s,i)=>s.score-i.score).map(s=>s.boxIndex),a=[];for(;n.length>0;){let s=n.pop();a.push(s);let i=n,c=[];for(let m=0;mc[p]<=e)}return a}var it=b();function rt(o,t){return it.tidy(()=>{let[e,r,n]=t,a=it.fill([...o.shape.slice(0,3),1],e,"float32"),s=it.fill([...o.shape.slice(0,3),1],r,"float32"),i=it.fill([...o.shape.slice(0,3),1],n,"float32"),c=it.concat([a,s,i],3);return it.sub(o,c)})}var Dt=b();function Sr(o,t=!1){return Dt.tidy(()=>{let[e,r]=o.shape.slice(1);if(e===r)return o;let n=Math.abs(e-r),a=Math.round(n*(t?.5:1)),s=e>r?2:1,i=u=>{let l=o.shape.slice();return l[s]=u,Dt.fill(l,0,"float32")},c=i(a),m=n-c.shape[s],d=[t&&m?i(m):null,o,c].filter(u=>!!u).map(u=>Dt.cast(u,"float32"));return Dt.concat(d,s)})}function gn(o){let t=o.slice();for(let e=t.length-1;e>0;e--){let r=Math.floor(Math.random()*(e+1)),n=t[e];t[e]=t[r],t[r]=n}return t}function De(o){return 1/(1+Math.exp(-o))}function vn(o){return Math.log(o/(1-o))}var oe=class extends P{constructor(t,e,r,n,a=!1){super({x:t,y:e,width:r,height:n},a)}};var yn=.5,Fn=.43,Tn=.45,V=class{constructor(t,e,r=new x(0,0)){let{width:n,height:a}=e;this._imgDims=new S(n,a),this._shift=r,this._positions=t.map(s=>s.mul(new x(n,a)).add(r))}get shift(){return new x(this._shift.x,this._shift.y)}get imageWidth(){return this._imgDims.width}get imageHeight(){return this._imgDims.height}get positions(){return this._positions}get relativePositions(){return this._positions.map(t=>t.sub(this._shift).div(new x(this.imageWidth,this.imageHeight)))}forSize(t,e){return new this.constructor(this.relativePositions,{width:t,height:e})}shiftBy(t,e){return new this.constructor(this.relativePositions,this._imgDims,new x(t,e))}shiftByPoint(t){return this.shiftBy(t.x,t.y)}align(t,e={}){if(t){let a=t instanceof E?t.box.floor():new P(t);return this.shiftBy(a.x,a.y).align(null,e)}let{useDlibAlignment:r,minBoxPadding:n}={useDlibAlignment:!1,minBoxPadding:.2,...e};return r?this.alignDlib():this.alignMinBbox(n)}alignDlib(){let t=this.getRefPointsForAlignment(),[e,r,n]=t,a=d=>n.sub(d).magnitude(),s=(a(e)+a(r))/2,i=Math.floor(s/Tn),c=$t(t),m=Math.floor(Math.max(0,c.x-yn*i)),p=Math.floor(Math.max(0,c.y-Fn*i));return new oe(m,p,Math.min(i,this.imageWidth+m),Math.min(i,this.imageHeight+p))}alignMinBbox(t){let e=Lr(this.positions);return e.pad(e.width*t,e.height*t)}getRefPointsForAlignment(){throw new Error("getRefPointsForAlignment not implemented by base class")}};var ho=class extends V{getRefPointsForAlignment(){let t=this.positions;return[t[0],t[1],$t([t[3],t[4]])]}};var ne=class extends V{getJawOutline(){return this.positions.slice(0,17)}getLeftEyeBrow(){return this.positions.slice(17,22)}getRightEyeBrow(){return this.positions.slice(22,27)}getNose(){return this.positions.slice(27,36)}getLeftEye(){return this.positions.slice(36,42)}getRightEye(){return this.positions.slice(42,48)}getMouth(){return this.positions.slice(48,68)}getRefPointsForAlignment(){return[this.getLeftEye(),this.getRightEye(),this.getMouth()].map($t)}};var Ee=class{constructor(t,e){this._label=t,this._distance=e}get label(){return this._label}get distance(){return this._distance}toString(t=!0){return`${this.label}${t?` (${Rt(this.distance)})`:""}`}};var Me=class extends P{static assertIsValidLabeledBox(t,e){if(P.assertIsValidBox(t,e),!et(t.label))throw new Error(`${e} - expected property label (${t.label}) to be a number`)}constructor(t,e){super(t);this._label=e}get label(){return this._label}};var ht=class{constructor(t,e){if(typeof t!="string")throw new Error("LabeledFaceDescriptors - constructor expected label to be a string");if(!Array.isArray(e)||e.some(r=>!(r instanceof Float32Array)))throw new Error("LabeledFaceDescriptors - constructor expected descriptors to be an array of Float32Array");this._label=t,this._descriptors=e}get label(){return this._label}get descriptors(){return this._descriptors}toJSON(){return{label:this.label,descriptors:this.descriptors.map(t=>Array.from(t))}}static fromJSON(t){let e=t.descriptors.map(r=>new Float32Array(r));return new ht(t.label,e)}};var xo=class extends Me{static assertIsValidPredictedBox(t,e){if(Me.assertIsValidLabeledBox(t,e),!ee(t.score)||!ee(t.classScore))throw new Error(`${e} - expected properties score (${t.score}) and (${t.classScore}) to be a number between [0, 1]`)}constructor(t,e,r,n){super(t,e);this._score=r,this._classScore=n}get score(){return this._score}get classScore(){return this._classScore}};function ct(o){return o.detection instanceof E}function Ot(o,t){return{...o,...{detection:t}}}function Ar(){let o=window.fetch;if(!o)throw new Error("fetch - missing fetch implementation for browser environment");return{Canvas:HTMLCanvasElement,CanvasRenderingContext2D,Image:HTMLImageElement,ImageData,Video:HTMLVideoElement,createCanvasElement:()=>document.createElement("canvas"),createImageElement:()=>document.createElement("img"),fetch:o,readFile:()=>{throw new Error("readFile - filesystem not available for browser environment")}}}function Ve(o){let t="";if(!o)try{o=require("fs")}catch(r){t=r.toString()}return{readFile:o?r=>new Promise((n,a)=>{o.readFile(r,(s,i)=>s?a(s):n(i))}):()=>{throw new Error(`readFile - failed to require fs in nodejs environment with error: ${t}`)}}}function Wr(){let o=global.Canvas||global.HTMLCanvasElement,t=global.Image||global.HTMLImageElement,e=()=>{if(o)return new o;throw new Error("createCanvasElement - missing Canvas implementation for nodejs environment")},r=()=>{if(t)return new t;throw new Error("createImageElement - missing Image implementation for nodejs environment")},n=global.fetch,a=Ve();return{Canvas:o||class{},CanvasRenderingContext2D:global.CanvasRenderingContext2D||class{},Image:t||class{},ImageData:global.ImageData||class{},Video:global.HTMLVideoElement||class{},createCanvasElement:e,createImageElement:r,fetch:n,...a}}function Br(){return typeof window=="object"&&typeof document!="undefined"&&typeof HTMLImageElement!="undefined"&&typeof HTMLCanvasElement!="undefined"&&typeof HTMLVideoElement!="undefined"&&typeof ImageData!="undefined"&&typeof CanvasRenderingContext2D!="undefined"}var Rr=hn(go()),L;function Pn(){if(!L)throw new Error("getEnv - environment is not defined, check isNodejs() and isBrowser()");return L}function $r(o){L=o}function Or(){return Br()?$r(Ar()):(0,Rr.isNodejs)()?$r(Wr()):null}function Dn(o){if(L||Or(),!L)throw new Error("monkeyPatch - environment is not defined, check isNodejs() and isBrowser()");let{Canvas:t=L.Canvas,Image:e=L.Image}=o;L.Canvas=t,L.Image=e,L.createCanvasElement=o.createCanvasElement||(()=>new t),L.createImageElement=o.createImageElement||(()=>new e),L.ImageData=o.ImageData||L.ImageData,L.Video=o.Video||L.Video,L.fetch=o.fetch||L.fetch,L.readFile=o.readFile||L.readFile}var w={getEnv:Pn,setEnv:$r,initialize:Or,createBrowserEnv:Ar,createFileSystem:Ve,createNodejsEnv:Wr,monkeyPatch:Dn,isBrowser:Br,isNodejs:Rr.isNodejs};Or();function jt(o){return!w.isNodejs()&&typeof o=="string"?document.getElementById(o):o}function R(o){let{Canvas:t,CanvasRenderingContext2D:e}=w.getEnv();if(o instanceof e)return o;let r=jt(o);if(!(r instanceof t))throw new Error("resolveContext2d - expected canvas to be of instance of Canvas");let n=r.getContext("2d");if(!n)throw new Error("resolveContext2d - canvas 2d context is null");return n}var mt;(function(o){o.TOP_LEFT="TOP_LEFT",o.TOP_RIGHT="TOP_RIGHT",o.BOTTOM_LEFT="BOTTOM_LEFT",o.BOTTOM_RIGHT="BOTTOM_RIGHT"})(mt||(mt={}));var Ce=class{constructor(t={}){let{anchorPosition:e,backgroundColor:r,fontColor:n,fontSize:a,fontStyle:s,padding:i}=t;this.anchorPosition=e||mt.TOP_LEFT,this.backgroundColor=r||"rgba(0, 0, 0, 0.5)",this.fontColor=n||"rgba(255, 255, 255, 1)",this.fontSize=a||14,this.fontStyle=s||"Georgia",this.padding=i||4}},Et=class{constructor(t,e,r={}){this.text=typeof t=="string"?[t]:t instanceof Et?t.text:t,this.anchor=e,this.options=new Ce(r)}measureWidth(t){let{padding:e}=this.options;return this.text.map(r=>t.measureText(r).width).reduce((r,n)=>r{let g=c+d.x,_=c+d.y+(l+1)*s;r.fillText(u,g,_)})}};var jr=class{constructor(t={}){let{boxColor:e,lineWidth:r,label:n,drawLabelOptions:a}=t;this.boxColor=e||"rgba(0, 0, 255, 1)",this.lineWidth=r||2,this.label=n;let s={anchorPosition:mt.BOTTOM_LEFT,backgroundColor:this.boxColor};this.drawLabelOptions=new Ce({...s,...a})}},Ue=class{constructor(t,e={}){this.box=new P(t),this.options=new jr(e)}draw(t){let e=R(t),{boxColor:r,lineWidth:n}=this.options,{x:a,y:s,width:i,height:c}=this.box;e.strokeStyle=r,e.lineWidth=n,e.strokeRect(a,s,i,c);let{label:m}=this.options;m&&new Et([m],{x:a-n/2,y:s},this.options.drawLabelOptions).draw(t)}};function En(o,t){(Array.isArray(t)?t:[t]).forEach(r=>{let n=r instanceof E?r.score:ct(r)?r.detection.score:void 0,a=r instanceof E?r.box:ct(r)?r.detection.box:new P(r),s=n?`${Rt(n)}`:void 0;new Ue(a,{label:s}).draw(o)})}var ue=b();function Ne(o){let{Image:t,Video:e}=w.getEnv();return o instanceof t&&o.complete||o instanceof e&&o.readyState>=3}function Hr(o){return new Promise((t,e)=>{if(o instanceof w.getEnv().Canvas||Ne(o))return t(null);function r(a){!a.currentTarget||(a.currentTarget.removeEventListener("load",n),a.currentTarget.removeEventListener("error",r),e(a))}function n(a){!a.currentTarget||(a.currentTarget.removeEventListener("load",n),a.currentTarget.removeEventListener("error",r),t(a))}o.addEventListener("load",n),o.addEventListener("error",r)})}function Yr(o){return new Promise((t,e)=>{o instanceof Blob||e(new Error("bufferToImage - expected buf to be of type: Blob"));let r=new FileReader;r.onload=()=>{typeof r.result!="string"&&e(new Error("bufferToImage - expected reader.result to be a string, in onload"));let n=w.getEnv().createImageElement();n.onload=()=>t(n),n.onerror=e,n.src=r.result},r.onerror=e,r.readAsDataURL(o)})}function Ht(o){let{Image:t,Video:e}=w.getEnv();return o instanceof t?new S(o.naturalWidth,o.naturalHeight):o instanceof e?new S(o.videoWidth,o.videoHeight):new S(o.width,o.height)}function Yt({width:o,height:t}){let{createCanvasElement:e}=w.getEnv(),r=e();return r.width=o,r.height=t,r}function Ie(o,t){let{ImageData:e}=w.getEnv();if(!(o instanceof e)&&!Ne(o))throw new Error("createCanvasFromMedia - media has not finished loading yet");let{width:r,height:n}=t||Ht(o),a=Yt({width:r,height:n});return o instanceof e?R(a).putImageData(o,0,0):R(a).drawImage(o,0,0,r,n),a}var Xe=b();async function Gr(o,t){let e=t||w.getEnv().createCanvasElement(),[r,n,a]=o.shape.slice(z(o)?1:0),s=Xe.tidy(()=>o.as3D(r,n,a).toInt());return await Xe.browser.toPixels(s,e),s.dispose(),e}function Je(o){let{Image:t,Canvas:e,Video:r}=w.getEnv();return o instanceof t||o instanceof e||o instanceof r}var O=b();function zr(o,t,e=!1){let{Image:r,Canvas:n}=w.getEnv();if(!(o instanceof r||o instanceof n))throw new Error("imageToSquare - expected arg0 to be HTMLImageElement | HTMLCanvasElement");if(t<=0)return Yt({width:1,height:1});let a=Ht(o),s=t/Math.max(a.height,a.width),i=s*a.width,c=s*a.height,m=Yt({width:t,height:t}),p=o instanceof n?o:Ie(o),d=Math.abs(i-c)/2,u=e&&i0&&p.height>0&&R(m).drawImage(p,u,l,i,c),m}var xt=class{constructor(t,e=!1){this._imageTensors=[];this._canvases=[];this._treatAsBatchInput=!1;this._inputDimensions=[];if(!Array.isArray(t))throw new Error(`NetInput.constructor - expected inputs to be an Array of TResolvedNetInput or to be instanceof tf.Tensor4D, instead have ${t}`);this._treatAsBatchInput=e,this._batchSize=t.length,t.forEach((r,n)=>{if(ft(r)){this._imageTensors[n]=r,this._inputDimensions[n]=r.shape;return}if(z(r)){let s=r.shape[0];if(s!==1)throw new Error(`NetInput - tf.Tensor4D with batchSize ${s} passed, but not supported in input array`);this._imageTensors[n]=r,this._inputDimensions[n]=r.shape.slice(1);return}let a=r instanceof w.getEnv().Canvas?r:Ie(r);this._canvases[n]=a,this._inputDimensions[n]=[a.height,a.width,3]})}get imageTensors(){return this._imageTensors}get canvases(){return this._canvases}get isBatchInput(){return this.batchSize>1||this._treatAsBatchInput}get batchSize(){return this._batchSize}get inputDimensions(){return this._inputDimensions}get inputSize(){return this._inputSize}get reshapedInputDimensions(){return st(this.batchSize,0,1).map((t,e)=>this.getReshapedInputDimensions(e))}getInput(t){return this.canvases[t]||this.imageTensors[t]}getInputDimensions(t){return this._inputDimensions[t]}getInputHeight(t){return this._inputDimensions[t][0]}getInputWidth(t){return this._inputDimensions[t][1]}getReshapedInputDimensions(t){if(typeof this.inputSize!="number")throw new Error("getReshapedInputDimensions - inputSize not set, toBatchTensor has not been called yet");let e=this.getInputWidth(t),r=this.getInputHeight(t);return Nr({width:e,height:r},this.inputSize)}toBatchTensor(t,e=!0){return this._inputSize=t,O.tidy(()=>{let r=st(this.batchSize,0,1).map(a=>{let s=this.getInput(a);if(s instanceof O.Tensor){let i=z(s)?s:O.expandDims(s);return i=Sr(i,e),(i.shape[1]!==t||i.shape[2]!==t)&&(i=O.image.resizeBilinear(i,[t,t],!1,!1)),i.as3D(t,t,3)}if(s instanceof w.getEnv().Canvas)return O.browser.fromPixels(zr(s,t,e));throw new Error(`toBatchTensor - at batchIdx ${a}, expected input to be instanceof tf.Tensor or instanceof HTMLCanvasElement, instead have ${s}`)});return O.stack(r.map(a=>O.cast(a,"float32"))).as4D(this.batchSize,t,t,3)})}};async function D(o){if(o instanceof xt)return o;let t=Array.isArray(o)?o:[o];if(!t.length)throw new Error("toNetInput - empty array passed as input");let e=n=>Array.isArray(o)?` at input index ${n}:`:"",r=t.map(jt);return r.forEach((n,a)=>{if(!Je(n)&&!ft(n)&&!z(n))throw typeof t[a]=="string"?new Error(`toNetInput -${e(a)} string passed, but could not resolve HTMLElement for element id ${t[a]}`):new Error(`toNetInput -${e(a)} expected media to be of type HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | tf.Tensor3D, or to be an element id`);if(z(n)){let s=n.shape[0];if(s!==1)throw new Error(`toNetInput -${e(a)} tf.Tensor4D with batchSize ${s} passed, but not supported in input array`)}}),await Promise.all(r.map(n=>Je(n)&&Hr(n))),new xt(r,Array.isArray(o))}async function ae(o,t){let{Canvas:e}=w.getEnv(),r=o;if(!(o instanceof e)){let s=await D(o);if(s.batchSize>1)throw new Error("extractFaces - batchSize > 1 not supported");let i=s.getInput(0);r=i instanceof e?i:await Gr(i)}let n=R(r);return t.map(s=>s instanceof E?s.forSize(r.width,r.height).box.floor():s).map(s=>s.clipAtImageBorders(r.width,r.height)).map(({x:s,y:i,width:c,height:m})=>{let p=Yt({width:c,height:m});return c>0&&m>0&&R(p).putImageData(n.getImageData(s,i,c,m),0,0),p})}var qe=b();async function se(o,t){if(!ft(o)&&!z(o))throw new Error("extractFaceTensors - expected image tensor to be 3D or 4D");if(z(o)&&o.shape[0]>1)throw new Error("extractFaceTensors - batchSize > 1 not supported");return qe.tidy(()=>{let[e,r,n]=o.shape.slice(z(o)?1:0);return t.map(i=>i instanceof E?i.forSize(r,e).box:i).map(i=>i.clipAtImageBorders(r,e)).map(({x:i,y:c,width:m,height:p})=>qe.slice3d(o.as3D(e,r,n),[c,i,0],[p,m,n]))})}async function Gt(o,t){let{fetch:e}=w.getEnv(),r=await e(o,t);if(!(r.status<400))throw new Error(`failed to fetch: (${r.status}) ${r.statusText}, from url: ${r.url}`);return r}async function Mn(o){let t=await Gt(o),e=await t.blob();if(!e.type.startsWith("image/"))throw new Error(`fetchImage - expected blob type to be of type image/*, instead have: ${e.type}, for url: ${t.url}`);return Yr(e)}async function Vr(o){return(await Gt(o)).json()}async function Cn(o){return new Float32Array(await(await Gt(o)).arrayBuffer())}var vo=b();function Ze(o,t){let e=`${t}-weights_manifest.json`;if(!o)return{modelBaseUri:"",manifestUri:e};if(o==="/")return{modelBaseUri:"/",manifestUri:`/${e}`};let r=o.startsWith("http://")?"http://":o.startsWith("https://")?"https://":"";o=o.replace(r,"");let n=o.split("/").filter(i=>i),a=o.endsWith(".json")?n[n.length-1]:e,s=r+(o.endsWith(".json")?n.slice(0,n.length-1):n).join("/");return s=o.startsWith("/")?`/${s}`:s,{modelBaseUri:s,manifestUri:s==="/"?`/${a}`:`${s}/${a}`}}async function Ur(o,t){let{manifestUri:e,modelBaseUri:r}=Ze(o,t),n=await Vr(e);return vo.io.loadWeights(n,r)}function Nn(o,t,e=!1){let{width:r,height:n}=e?Ht(t):t;return o.width=r,o.height=n,{width:r,height:n}}var Ct=b();var bt=b();var k=class{constructor(t){this._params=void 0;this._paramMappings=[];this._name=t}get params(){return this._params}get paramMappings(){return this._paramMappings}get isLoaded(){return!!this.params}getParamFromPath(t){let{obj:e,objProp:r}=this.traversePropertyPath(t);return e[r]}reassignParamFromPath(t,e){let{obj:r,objProp:n}=this.traversePropertyPath(t);r[n].dispose(),r[n]=e}getParamList(){return this._paramMappings.map(({paramPath:t})=>({path:t,tensor:this.getParamFromPath(t)}))}getTrainableParams(){return this.getParamList().filter(t=>t.tensor instanceof bt.Variable)}getFrozenParams(){return this.getParamList().filter(t=>!(t.tensor instanceof bt.Variable))}variable(){this.getFrozenParams().forEach(({path:t,tensor:e})=>{this.reassignParamFromPath(t,e.variable())})}freeze(){this.getTrainableParams().forEach(({path:t,tensor:e})=>{let r=bt.tensor(e.dataSync());e.dispose(),this.reassignParamFromPath(t,r)})}dispose(t=!0){this.getParamList().forEach(e=>{if(t&&e.tensor.isDisposed)throw new Error(`param tensor has already been disposed for path ${e.path}`);e.tensor.dispose()}),this._params=void 0}serializeParams(){return new Float32Array(this.getParamList().map(({tensor:t})=>Array.from(t.dataSync())).reduce((t,e)=>t.concat(e)))}async load(t){if(t instanceof Float32Array){this.extractWeights(t);return}await this.loadFromUri(t)}async loadFromUri(t){if(t&&typeof t!="string")throw new Error(`${this._name}.loadFromUri - expected model uri`);let e=await Ur(t,this.getDefaultModelName());this.loadFromWeightMap(e)}async loadFromDisk(t){if(t&&typeof t!="string")throw new Error(`${this._name}.loadFromDisk - expected model file path`);let{readFile:e}=w.getEnv(),{manifestUri:r,modelBaseUri:n}=Ze(t,this.getDefaultModelName()),a=m=>Promise.all(m.map(p=>e(p).then(d=>d.buffer))),s=bt.io.weightsLoaderFactory(a),i=JSON.parse((await e(r)).toString()),c=await s(i,n);this.loadFromWeightMap(c)}loadFromWeightMap(t){let{paramMappings:e,params:r}=this.extractParamsFromWeightMap(t);this._paramMappings=e,this._params=r}extractWeights(t){let{paramMappings:e,params:r}=this.extractParams(t);this._paramMappings=e,this._params=r}traversePropertyPath(t){if(!this.params)throw new Error("traversePropertyPath - model has no loaded params");let e=t.split("/").reduce((a,s)=>{if(!a.nextObj.hasOwnProperty(s))throw new Error(`traversePropertyPath - object does not have property ${s}, for path ${t}`);return{obj:a.nextObj,objProp:s,nextObj:a.nextObj[s]}},{nextObj:this.params}),{obj:r,objProp:n}=e;if(!r||!n||!(r[n]instanceof bt.Tensor))throw new Error(`traversePropertyPath - parameter is not a tensor, for path ${t}`);return{obj:r,objProp:n}}};var M=b();var ie=b();function $(o,t,e){return ie.tidy(()=>{let r=ie.separableConv2d(o,t.depthwise_filter,t.pointwise_filter,e,"same");return r=ie.add(r,t.bias),r})}function Ke(o,t,e=!1){return M.tidy(()=>{let r=M.relu(e?M.add(M.conv2d(o,t.conv0.filters,[2,2],"same"),t.conv0.bias):$(o,t.conv0,[2,2])),n=$(r,t.conv1,[1,1]),a=M.relu(M.add(r,n)),s=$(a,t.conv2,[1,1]);return M.relu(M.add(r,M.add(n,s)))})}function Le(o,t,e=!1,r=!0){return M.tidy(()=>{let n=M.relu(e?M.add(M.conv2d(o,t.conv0.filters,r?[2,2]:[1,1],"same"),t.conv0.bias):$(o,t.conv0,r?[2,2]:[1,1])),a=$(n,t.conv1,[1,1]),s=M.relu(M.add(n,a)),i=$(s,t.conv2,[1,1]),c=M.relu(M.add(n,M.add(a,i))),m=$(c,t.conv3,[1,1]);return M.relu(M.add(n,M.add(a,M.add(i,m))))})}var Mt=b();function zt(o,t,e="same",r=!1){return Mt.tidy(()=>{let n=Mt.add(Mt.conv2d(o,t.filters,[1,1],e),t.bias);return r?Mt.relu(n):n})}function A(o,t){Object.keys(o).forEach(e=>{t.some(r=>r.originalPath===e)||o[e].dispose()})}var Qe=b();function ce(o,t){return(e,r,n,a)=>{let s=Qe.tensor4d(o(e*r*n*n),[n,n,e,r]),i=Qe.tensor1d(o(r));return t.push({paramPath:`${a}/filters`},{paramPath:`${a}/bias`}),{filters:s,bias:i}}}var tr=b();function er(o,t){return(e,r,n)=>{let a=tr.tensor2d(o(e*r),[e,r]),s=tr.tensor1d(o(r));return t.push({paramPath:`${n}/weights`},{paramPath:`${n}/bias`}),{weights:a,bias:s}}}var ke=b();var rr=class{constructor(t,e,r){this.depthwise_filter=t;this.pointwise_filter=e;this.bias=r}};function me(o,t){return(e,r,n)=>{let a=ke.tensor4d(o(3*3*e),[3,3,e,1]),s=ke.tensor4d(o(e*r),[1,1,e,r]),i=ke.tensor1d(o(r));return t.push({paramPath:`${n}/depthwise_filter`},{paramPath:`${n}/pointwise_filter`},{paramPath:`${n}/bias`}),new rr(a,s,i)}}function pe(o){return t=>{let e=o(`${t}/depthwise_filter`,4),r=o(`${t}/pointwise_filter`,4),n=o(`${t}/bias`,1);return new rr(e,r,n)}}function j(o,t){return(e,r,n)=>{let a=o[e];if(!Bt(a,r))throw new Error(`expected weightMap[${e}] to be a Tensor${r}D, instead have ${a}`);return t.push({originalPath:e,paramPath:n||e}),a}}function W(o){let t=o;function e(n){let a=t.slice(0,n);return t=t.slice(n),a}function r(){return t}return{extractWeights:e,getRemainingWeights:r}}function or(o,t){let e=ce(o,t),r=me(o,t);function n(s,i,c,m=!1){let p=m?e(s,i,3,`${c}/conv0`):r(s,i,`${c}/conv0`),d=r(i,i,`${c}/conv1`),u=r(i,i,`${c}/conv2`);return{conv0:p,conv1:d,conv2:u}}function a(s,i,c,m=!1){let{conv0:p,conv1:d,conv2:u}=n(s,i,c,m),l=r(i,i,`${c}/conv3`);return{conv0:p,conv1:d,conv2:u,conv3:l}}return{extractDenseBlock3Params:n,extractDenseBlock4Params:a}}function yo(o){let t=[],{extractWeights:e,getRemainingWeights:r}=W(o),{extractDenseBlock4Params:n}=or(e,t),a=n(3,32,"dense0",!0),s=n(32,64,"dense1"),i=n(64,128,"dense2"),c=n(128,256,"dense3");if(r().length!==0)throw new Error(`weights remaing after extract: ${r().length}`);return{paramMappings:t,params:{dense0:a,dense1:s,dense2:i,dense3:c}}}function nr(o){return t=>{let e=o(`${t}/filters`,4),r=o(`${t}/bias`,1);return{filters:e,bias:r}}}function ar(o,t){let e=j(o,t),r=nr(e),n=pe(e);function a(i,c=!1){let m=c?r(`${i}/conv0`):n(`${i}/conv0`),p=n(`${i}/conv1`),d=n(`${i}/conv2`);return{conv0:m,conv1:p,conv2:d}}function s(i,c=!1){let m=c?r(`${i}/conv0`):n(`${i}/conv0`),p=n(`${i}/conv1`),d=n(`${i}/conv2`),u=n(`${i}/conv3`);return{conv0:m,conv1:p,conv2:d,conv3:u}}return{extractDenseBlock3Params:a,extractDenseBlock4Params:s}}function Fo(o){let t=[],{extractDenseBlock4Params:e}=ar(o,t),r={dense0:e("dense0",!0),dense1:e("dense1"),dense2:e("dense2"),dense3:e("dense3")};return A(o,t),{params:r,paramMappings:t}}var Se=class extends k{constructor(){super("FaceFeatureExtractor")}forwardInput(t){let{params:e}=this;if(!e)throw new Error("FaceFeatureExtractor - load model before inference");return Ct.tidy(()=>{let r=Ct.cast(t.toBatchTensor(112,!0),"float32"),a=rt(r,[122.782,117.001,104.298]).div(Ct.scalar(255)),s=Le(a,e.dense0,!0);return s=Le(s,e.dense1),s=Le(s,e.dense2),s=Le(s,e.dense3),s=Ct.avgPool(s,[7,7],[2,2],"valid"),s})}async forward(t){return this.forwardInput(await D(t))}getDefaultModelName(){return"face_feature_extractor_model"}extractParamsFromWeightMap(t){return Fo(t)}extractParams(t){return yo(t)}};var wo=b();var de=b();function Ae(o,t){return de.tidy(()=>de.add(de.matMul(o,t.weights),t.bias))}function To(o,t,e){let r=[],{extractWeights:n,getRemainingWeights:a}=W(o),i=er(n,r)(t,e,"fc");if(a().length!==0)throw new Error(`weights remaing after extract: ${a().length}`);return{paramMappings:r,params:{fc:i}}}function _o(o){let t=[],e=j(o,t);function r(a){let s=e(`${a}/weights`,2),i=e(`${a}/bias`,1);return{weights:s,bias:i}}let n={fc:r("fc")};return A(o,t),{params:n,paramMappings:t}}function sr(o){let t={},e={};return Object.keys(o).forEach(r=>{let n=r.startsWith("fc")?e:t;n[r]=o[r]}),{featureExtractorMap:t,classifierMap:e}}var We=class extends k{constructor(t,e){super(t);this._faceFeatureExtractor=e}get faceFeatureExtractor(){return this._faceFeatureExtractor}runNet(t){let{params:e}=this;if(!e)throw new Error(`${this._name} - load model before inference`);return wo.tidy(()=>{let r=t instanceof xt?this.faceFeatureExtractor.forwardInput(t):t;return Ae(r.as2D(r.shape[0],-1),e.fc)})}dispose(t=!0){this.faceFeatureExtractor.dispose(t),super.dispose(t)}loadClassifierParams(t){let{params:e,paramMappings:r}=this.extractClassifierParams(t);this._params=e,this._paramMappings=r}extractClassifierParams(t){return To(t,this.getClassifierChannelsIn(),this.getClassifierChannelsOut())}extractParamsFromWeightMap(t){let{featureExtractorMap:e,classifierMap:r}=sr(t);return this.faceFeatureExtractor.loadFromWeightMap(e),_o(r)}extractParams(t){let e=this.getClassifierChannelsIn(),r=this.getClassifierChannelsOut(),n=r*e+r,a=t.slice(0,t.length-n),s=t.slice(t.length-n);return this.faceFeatureExtractor.extractWeights(a),this.extractClassifierParams(s)}};var Xr=["neutral","happy","sad","angry","fearful","disgusted","surprised"],Nt=class{constructor(t){if(t.length!==7)throw new Error(`FaceExpressions.constructor - expected probabilities.length to be 7, have: ${t.length}`);Xr.forEach((e,r)=>{this[e]=t[r]})}asSortedArray(){return Xr.map(t=>({expression:t,probability:this[t]})).sort((t,e)=>e.probability-t.probability)}};var ir=class extends We{constructor(t=new Se){super("FaceExpressionNet",t)}forwardInput(t){return ue.tidy(()=>ue.softmax(this.runNet(t)))}async forward(t){return this.forwardInput(await D(t))}async predictExpressions(t){let e=await D(t),r=await this.forwardInput(e),n=await Promise.all(ue.unstack(r).map(async s=>{let i=await s.data();return s.dispose(),i}));r.dispose();let a=n.map(s=>new Nt(s));return e.isBatchInput?a:a[0]}getDefaultModelName(){return"face_expression_model"}getClassifierChannelsIn(){return 256}getClassifierChannelsOut(){return 7}};function Jr(o){return o.expressions instanceof Nt}function cr(o,t){return{...o,...{expressions:t}}}function In(o,t,e=.1,r){(Array.isArray(t)?t:[t]).forEach(a=>{let s=a instanceof Nt?a:Jr(a)?a.expressions:void 0;if(!s)throw new Error("drawFaceExpressions - expected faceExpressions to be FaceExpressions | WithFaceExpressions<{}> or array thereof");let c=s.asSortedArray().filter(d=>d.probability>e),m=ct(a)?a.detection.box.bottomLeft:r||new x(0,0);new Et(c.map(d=>`${d.expression} (${Rt(d.probability)})`),m).draw(o)})}function Vt(o){return ct(o)&&o.landmarks instanceof V&&o.unshiftedLandmarks instanceof V&&o.alignedRect instanceof E}function Ln(o){let t=(i,c,m,p)=>Math.atan2(p-c,m-i)%Math.PI,e=i=>i*180/Math.PI,r={roll:void 0,pitch:void 0,yaw:void 0};if(!o||!o._positions||o._positions.length!==68)return r;let n=o._positions;r.roll=-t(n[36]._x,n[36]._y,n[45]._x,n[45]._y),r.pitch=t(0,Math.abs(n[0]._x-n[30]._x)/n[30]._x,Math.PI,Math.abs(n[16]._x-n[30]._x)/n[30]._x);let a=n.reduce((i,c)=>ii>c._y?i:c._y,-Infinity);return r.yaw=Math.PI*(o._imgDims._height/(s-a)/1.4-1),r}function le(o,t){let{box:e}=o.detection,r=t.shiftBy(e.x,e.y),n=r.align(),{imageDims:a}=o.detection,s=new E(o.detection.score,n.rescale(a.reverse()),a),i=Ln(t);return{...o,...{landmarks:r,unshiftedLandmarks:t,alignedRect:s,angle:i}}}var qr=class{constructor(t={}){let{drawLines:e=!0,drawPoints:r=!0,lineWidth:n,lineColor:a,pointSize:s,pointColor:i}=t;this.drawLines=e,this.drawPoints=r,this.lineWidth=n||1,this.pointSize=s||2,this.lineColor=a||"rgba(0, 255, 255, 1)",this.pointColor=i||"rgba(255, 0, 255, 1)"}},Zr=class{constructor(t,e={}){this.faceLandmarks=t,this.options=new qr(e)}draw(t){let e=R(t),{drawLines:r,drawPoints:n,lineWidth:a,lineColor:s,pointSize:i,pointColor:c}=this.options;if(r&&this.faceLandmarks instanceof ne&&(e.strokeStyle=s,e.lineWidth=a,lt(e,this.faceLandmarks.getJawOutline()),lt(e,this.faceLandmarks.getLeftEyeBrow()),lt(e,this.faceLandmarks.getRightEyeBrow()),lt(e,this.faceLandmarks.getNose()),lt(e,this.faceLandmarks.getLeftEye(),!0),lt(e,this.faceLandmarks.getRightEye(),!0),lt(e,this.faceLandmarks.getMouth(),!0)),n){e.strokeStyle=c,e.fillStyle=c;let m=p=>{e.beginPath(),e.arc(p.x,p.y,i,0,2*Math.PI),e.fill()};this.faceLandmarks.positions.forEach(m)}}};function kn(o,t){(Array.isArray(t)?t:[t]).forEach(r=>{let n=r instanceof V?r:Vt(r)?r.landmarks:void 0;if(!n)throw new Error("drawFaceLandmarks - expected faceExpressions to be FaceLandmarks | WithFaceLandmarks> or array thereof");new Zr(n).draw(o)})}var Do="1.1.4";var pt=b();var N=b();function Sn(o,t){let e=ce(o,t),r=me(o,t);function n(s,i,c){let m=r(s,i,`${c}/separable_conv0`),p=r(i,i,`${c}/separable_conv1`),d=e(s,i,1,`${c}/expansion_conv`);return{separable_conv0:m,separable_conv1:p,expansion_conv:d}}function a(s,i){let c=r(s,s,`${i}/separable_conv0`),m=r(s,s,`${i}/separable_conv1`),p=r(s,s,`${i}/separable_conv2`);return{separable_conv0:c,separable_conv1:m,separable_conv2:p}}return{extractConvParams:e,extractSeparableConvParams:r,extractReductionBlockParams:n,extractMainBlockParams:a}}function Eo(o,t){let e=[],{extractWeights:r,getRemainingWeights:n}=W(o),{extractConvParams:a,extractSeparableConvParams:s,extractReductionBlockParams:i,extractMainBlockParams:c}=Sn(r,e),m=a(3,32,3,"entry_flow/conv_in"),p=i(32,64,"entry_flow/reduction_block_0"),d=i(64,128,"entry_flow/reduction_block_1"),u={conv_in:m,reduction_block_0:p,reduction_block_1:d},l={};st(t,0,1).forEach(v=>{l[`main_block_${v}`]=c(128,`middle_flow/main_block_${v}`)});let g=i(128,256,"exit_flow/reduction_block"),_=s(256,512,"exit_flow/separable_conv"),h={reduction_block:g,separable_conv:_};if(n().length!==0)throw new Error(`weights remaing after extract: ${n().length}`);return{paramMappings:e,params:{entry_flow:u,middle_flow:l,exit_flow:h}}}function An(o,t){let e=j(o,t),r=nr(e),n=pe(e);function a(i){let c=n(`${i}/separable_conv0`),m=n(`${i}/separable_conv1`),p=r(`${i}/expansion_conv`);return{separable_conv0:c,separable_conv1:m,expansion_conv:p}}function s(i){let c=n(`${i}/separable_conv0`),m=n(`${i}/separable_conv1`),p=n(`${i}/separable_conv2`);return{separable_conv0:c,separable_conv1:m,separable_conv2:p}}return{extractConvParams:r,extractSeparableConvParams:n,extractReductionBlockParams:a,extractMainBlockParams:s}}function Mo(o,t){let e=[],{extractConvParams:r,extractSeparableConvParams:n,extractReductionBlockParams:a,extractMainBlockParams:s}=An(o,e),i=r("entry_flow/conv_in"),c=a("entry_flow/reduction_block_0"),m=a("entry_flow/reduction_block_1"),p={conv_in:i,reduction_block_0:c,reduction_block_1:m},d={};st(t,0,1).forEach(_=>{d[`main_block_${_}`]=s(`middle_flow/main_block_${_}`)});let u=a("exit_flow/reduction_block"),l=n("exit_flow/separable_conv"),g={reduction_block:u,separable_conv:l};return A(o,e),{params:{entry_flow:p,middle_flow:d,exit_flow:g},paramMappings:e}}function Co(o,t,e){return N.add(N.conv2d(o,t.filters,e,"same"),t.bias)}function Kr(o,t,e=!0){let r=e?N.relu(o):o;return r=$(r,t.separable_conv0,[1,1]),r=$(N.relu(r),t.separable_conv1,[1,1]),r=N.maxPool(r,[3,3],[2,2],"same"),r=N.add(r,Co(o,t.expansion_conv,[2,2])),r}function Wn(o,t){let e=$(N.relu(o),t.separable_conv0,[1,1]);return e=$(N.relu(e),t.separable_conv1,[1,1]),e=$(N.relu(e),t.separable_conv2,[1,1]),e=N.add(e,o),e}var Qr=class extends k{constructor(t){super("TinyXception");this._numMainBlocks=t}forwardInput(t){let{params:e}=this;if(!e)throw new Error("TinyXception - load model before inference");return N.tidy(()=>{let r=N.cast(t.toBatchTensor(112,!0),"float32"),a=rt(r,[122.782,117.001,104.298]).div(N.scalar(256)),s=N.relu(Co(a,e.entry_flow.conv_in,[2,2]));return s=Kr(s,e.entry_flow.reduction_block_0,!1),s=Kr(s,e.entry_flow.reduction_block_1),st(this._numMainBlocks,0,1).forEach(i=>{s=Wn(s,e.middle_flow[`main_block_${i}`])}),s=Kr(s,e.exit_flow.reduction_block),s=N.relu($(s,e.exit_flow.separable_conv,[1,1])),s})}async forward(t){return this.forwardInput(await D(t))}getDefaultModelName(){return"tiny_xception_model"}extractParamsFromWeightMap(t){return Mo(t,this._numMainBlocks)}extractParams(t){return Eo(t,this._numMainBlocks)}};function No(o){let t=[],{extractWeights:e,getRemainingWeights:r}=W(o),n=er(e,t),a=n(512,1,"fc/age"),s=n(512,2,"fc/gender");if(r().length!==0)throw new Error(`weights remaing after extract: ${r().length}`);return{paramMappings:t,params:{fc:{age:a,gender:s}}}}function Io(o){let t=[],e=j(o,t);function r(a){let s=e(`${a}/weights`,2),i=e(`${a}/bias`,1);return{weights:s,bias:i}}let n={fc:{age:r("fc/age"),gender:r("fc/gender")}};return A(o,t),{params:n,paramMappings:t}}var gt;(function(o){o.FEMALE="female",o.MALE="male"})(gt||(gt={}));var mr=class extends k{constructor(t=new Qr(2)){super("AgeGenderNet");this._faceFeatureExtractor=t}get faceFeatureExtractor(){return this._faceFeatureExtractor}runNet(t){let{params:e}=this;if(!e)throw new Error(`${this._name} - load model before inference`);return pt.tidy(()=>{let r=t instanceof xt?this.faceFeatureExtractor.forwardInput(t):t,n=pt.avgPool(r,[7,7],[2,2],"valid").as2D(r.shape[0],-1),a=Ae(n,e.fc.age).as1D(),s=Ae(n,e.fc.gender);return{age:a,gender:s}})}forwardInput(t){return pt.tidy(()=>{let{age:e,gender:r}=this.runNet(t);return{age:e,gender:pt.softmax(r)}})}async forward(t){return this.forwardInput(await D(t))}async predictAgeAndGender(t){let e=await D(t),r=await this.forwardInput(e),n=pt.unstack(r.age),a=pt.unstack(r.gender),s=n.map((c,m)=>({ageTensor:c,genderTensor:a[m]})),i=await Promise.all(s.map(async({ageTensor:c,genderTensor:m})=>{let p=(await c.data())[0],d=(await m.data())[0],u=d>.5,l=u?gt.MALE:gt.FEMALE,g=u?d:1-d;return c.dispose(),m.dispose(),{age:p,gender:l,genderProbability:g}}));return r.age.dispose(),r.gender.dispose(),e.isBatchInput?i:i[0]}getDefaultModelName(){return"age_gender_model"}dispose(t=!0){this.faceFeatureExtractor.dispose(t),super.dispose(t)}loadClassifierParams(t){let{params:e,paramMappings:r}=this.extractClassifierParams(t);this._params=e,this._paramMappings=r}extractClassifierParams(t){return No(t)}extractParamsFromWeightMap(t){let{featureExtractorMap:e,classifierMap:r}=sr(t);return this.faceFeatureExtractor.loadFromWeightMap(e),Io(r)}extractParams(t){let e=512*1+1+(512*2+2),r=t.slice(0,t.length-e),n=t.slice(t.length-e);return this.faceFeatureExtractor.extractWeights(r),this.extractClassifierParams(n)}};var H=b();var Be=class extends We{postProcess(t,e,r){let n=r.map(({width:s,height:i})=>{let c=e/Math.max(i,s);return{width:s*c,height:i*c}}),a=n.length;return H.tidy(()=>{let s=(d,u)=>H.stack([H.fill([68],d,"float32"),H.fill([68],u,"float32")],1).as2D(1,136).as1D(),i=(d,u)=>{let{width:l,height:g}=n[d];return u(l,g)?Math.abs(l-g)/2:0},c=d=>i(d,(u,l)=>ui(d,(u,l)=>ls(c(u),m(u))))).div(H.stack(Array.from(Array(a),(d,u)=>s(n[u].width,n[u].height))))})}forwardInput(t){return H.tidy(()=>{let e=this.runNet(t);return this.postProcess(e,t.inputSize,t.inputDimensions.map(([r,n])=>({height:r,width:n})))})}async forward(t){return this.forwardInput(await D(t))}async detectLandmarks(t){let e=await D(t),r=H.tidy(()=>H.unstack(this.forwardInput(e))),n=await Promise.all(r.map(async(a,s)=>{let i=Array.from(await a.data()),c=i.filter((p,d)=>Ge(d)),m=i.filter((p,d)=>!Ge(d));return new ne(Array(68).fill(0).map((p,d)=>new x(c[d],m[d])),{height:e.getInputHeight(s),width:e.getInputWidth(s)})}));return r.forEach(a=>a.dispose()),e.isBatchInput?n:n[0]}getClassifierChannelsOut(){return 136}};var fe=class extends Be{constructor(t=new Se){super("FaceLandmark68Net",t)}getDefaultModelName(){return"face_landmark_68_model"}getClassifierChannelsIn(){return 256}};var It=b();function Lo(o){let t=[],{extractDenseBlock3Params:e}=ar(o,t),r={dense0:e("dense0",!0),dense1:e("dense1"),dense2:e("dense2")};return A(o,t),{params:r,paramMappings:t}}function ko(o){let t=[],{extractWeights:e,getRemainingWeights:r}=W(o),{extractDenseBlock3Params:n}=or(e,t),a=n(3,32,"dense0",!0),s=n(32,64,"dense1"),i=n(64,128,"dense2");if(r().length!==0)throw new Error(`weights remaing after extract: ${r().length}`);return{paramMappings:t,params:{dense0:a,dense1:s,dense2:i}}}var to=class extends k{constructor(){super("TinyFaceFeatureExtractor")}forwardInput(t){let{params:e}=this;if(!e)throw new Error("TinyFaceFeatureExtractor - load model before inference");return It.tidy(()=>{let r=It.cast(t.toBatchTensor(112,!0),"float32"),a=rt(r,[122.782,117.001,104.298]).div(It.scalar(255)),s=Ke(a,e.dense0,!0);return s=Ke(s,e.dense1),s=Ke(s,e.dense2),s=It.avgPool(s,[14,14],[2,2],"valid"),s})}async forward(t){return this.forwardInput(await D(t))}getDefaultModelName(){return"face_feature_extractor_tiny_model"}extractParamsFromWeightMap(t){return Lo(t)}extractParams(t){return ko(t)}};var pr=class extends Be{constructor(t=new to){super("FaceLandmark68TinyNet",t)}getDefaultModelName(){return"face_landmark_68_tiny_model"}getClassifierChannelsIn(){return 128}};var So=class extends fe{};var U=b();var he=b();var dr=b();function Ao(o,t){return dr.add(dr.mul(o,t.weights),t.biases)}function eo(o,t,e,r,n="same"){let{filters:a,bias:s}=t.conv,i=he.conv2d(o,a,e,n);return i=he.add(i,s),i=Ao(i,t.scale),r?he.relu(i):i}function Wo(o,t){return eo(o,t,[1,1],!0)}function ro(o,t){return eo(o,t,[1,1],!1)}function ur(o,t){return eo(o,t,[2,2],!0,"valid")}var Y=b();function Bn(o,t){function e(i,c,m){let p=o(i),d=p.length/(c*m*m);if(Cr(d))throw new Error(`depth has to be an integer: ${d}, weights.length: ${p.length}, numFilters: ${c}, filterSize: ${m}`);return Y.tidy(()=>Y.transpose(Y.tensor4d(p,[c,d,m,m]),[2,3,1,0]))}function r(i,c,m,p){let d=e(i,c,m),u=Y.tensor1d(o(c));return t.push({paramPath:`${p}/filters`},{paramPath:`${p}/bias`}),{filters:d,bias:u}}function n(i,c){let m=Y.tensor1d(o(i)),p=Y.tensor1d(o(i));return t.push({paramPath:`${c}/weights`},{paramPath:`${c}/biases`}),{weights:m,biases:p}}function a(i,c,m,p){let d=r(i,c,m,`${p}/conv`),u=n(c,`${p}/scale`);return{conv:d,scale:u}}function s(i,c,m,p,d=!1){let u=a((d?.5:1)*i,c,m,`${p}/conv1`),l=a(i,c,m,`${p}/conv2`);return{conv1:u,conv2:l}}return{extractConvLayerParams:a,extractResidualLayerParams:s}}function Bo(o){let{extractWeights:t,getRemainingWeights:e}=W(o),r=[],{extractConvLayerParams:n,extractResidualLayerParams:a}=Bn(t,r),s=n(4704,32,7,"conv32_down"),i=a(9216,32,3,"conv32_1"),c=a(9216,32,3,"conv32_2"),m=a(9216,32,3,"conv32_3"),p=a(36864,64,3,"conv64_down",!0),d=a(36864,64,3,"conv64_1"),u=a(36864,64,3,"conv64_2"),l=a(36864,64,3,"conv64_3"),g=a(147456,128,3,"conv128_down",!0),_=a(147456,128,3,"conv128_1"),h=a(147456,128,3,"conv128_2"),v=a(589824,256,3,"conv256_down",!0),F=a(589824,256,3,"conv256_1"),y=a(589824,256,3,"conv256_2"),I=a(589824,256,3,"conv256_down_out"),G=Y.tidy(()=>Y.transpose(Y.tensor2d(t(256*128),[128,256]),[1,0]));if(r.push({paramPath:"fc"}),e().length!==0)throw new Error(`weights remaing after extract: ${e().length}`);return{params:{conv32_down:s,conv32_1:i,conv32_2:c,conv32_3:m,conv64_down:p,conv64_1:d,conv64_2:u,conv64_3:l,conv128_down:g,conv128_1:_,conv128_2:h,conv256_down:v,conv256_1:F,conv256_2:y,conv256_down_out:I,fc:G},paramMappings:r}}function Rn(o,t){let e=j(o,t);function r(s){let i=e(`${s}/scale/weights`,1),c=e(`${s}/scale/biases`,1);return{weights:i,biases:c}}function n(s){let i=e(`${s}/conv/filters`,4),c=e(`${s}/conv/bias`,1),m=r(s);return{conv:{filters:i,bias:c},scale:m}}function a(s){return{conv1:n(`${s}/conv1`),conv2:n(`${s}/conv2`)}}return{extractConvLayerParams:n,extractResidualLayerParams:a}}function Ro(o){let t=[],{extractConvLayerParams:e,extractResidualLayerParams:r}=Rn(o,t),n=e("conv32_down"),a=r("conv32_1"),s=r("conv32_2"),i=r("conv32_3"),c=r("conv64_down"),m=r("conv64_1"),p=r("conv64_2"),d=r("conv64_3"),u=r("conv128_down"),l=r("conv128_1"),g=r("conv128_2"),_=r("conv256_down"),h=r("conv256_1"),v=r("conv256_2"),F=r("conv256_down_out"),{fc:y}=o;if(t.push({originalPath:"fc",paramPath:"fc"}),!Mr(y))throw new Error(`expected weightMap[fc] to be a Tensor2D, instead have ${y}`);let I={conv32_down:n,conv32_1:a,conv32_2:s,conv32_3:i,conv64_down:c,conv64_1:m,conv64_2:p,conv64_3:d,conv128_down:u,conv128_1:l,conv128_2:g,conv256_down:_,conv256_1:h,conv256_2:v,conv256_down_out:F,fc:y};return A(o,t),{params:I,paramMappings:t}}var B=b();function ot(o,t){let e=Wo(o,t.conv1);return e=ro(e,t.conv2),e=B.add(e,o),e=B.relu(e),e}function Re(o,t){let e=ur(o,t.conv1);e=ro(e,t.conv2);let r=B.avgPool(o,2,2,"valid"),n=B.zeros(r.shape),a=r.shape[3]!==e.shape[3];if(r.shape[1]!==e.shape[1]||r.shape[2]!==e.shape[2]){let i=[...e.shape];i[1]=1;let c=B.zeros(i);e=B.concat([e,c],1);let m=[...e.shape];m[2]=1;let p=B.zeros(m);e=B.concat([e,p],2)}return r=a?B.concat([r,n],3):r,e=B.add(r,e),e=B.relu(e),e}var xe=class extends k{constructor(){super("FaceRecognitionNet")}forwardInput(t){let{params:e}=this;if(!e)throw new Error("FaceRecognitionNet - load model before inference");return U.tidy(()=>{let r=U.cast(t.toBatchTensor(150,!0),"float32"),a=rt(r,[122.782,117.001,104.298]).div(U.scalar(256)),s=ur(a,e.conv32_down);s=U.maxPool(s,3,2,"valid"),s=ot(s,e.conv32_1),s=ot(s,e.conv32_2),s=ot(s,e.conv32_3),s=Re(s,e.conv64_down),s=ot(s,e.conv64_1),s=ot(s,e.conv64_2),s=ot(s,e.conv64_3),s=Re(s,e.conv128_down),s=ot(s,e.conv128_1),s=ot(s,e.conv128_2),s=Re(s,e.conv256_down),s=ot(s,e.conv256_1),s=ot(s,e.conv256_2),s=Re(s,e.conv256_down_out);let i=s.mean([1,2]);return U.matMul(i,e.fc)})}async forward(t){return this.forwardInput(await D(t))}async computeFaceDescriptor(t){var a;if((a=t==null?void 0:t.shape)==null?void 0:a.some(s=>s<=0))return new Float32Array(128);let e=await D(t),r=U.tidy(()=>U.unstack(this.forwardInput(e))),n=await Promise.all(r.map(s=>s.data()));return r.forEach(s=>s.dispose()),e.isBatchInput?n:n[0]}getDefaultModelName(){return"face_recognition_model"}extractParamsFromWeightMap(t){return Ro(t)}extractParams(t){return Bo(t)}};function $n(o){let t=new xe;return t.extractWeights(o),t}function lr(o,t){return{...o,...{descriptor:t}}}function On(o){return typeof o.age=="number"}function fr(o,t){return{...o,...{age:t}}}function jn(o){return(o.gender===gt.MALE||o.gender===gt.FEMALE)&&ee(o.genderProbability)}function hr(o,t,e){return{...o,...{gender:t,genderProbability:e}}}var kt=b();var nt=b();function Hn(o,t){function e(c,m){let p=nt.tensor4d(o(3*3*c),[3,3,c,1]),d=nt.tensor1d(o(c)),u=nt.tensor1d(o(c)),l=nt.tensor1d(o(c)),g=nt.tensor1d(o(c));return t.push({paramPath:`${m}/filters`},{paramPath:`${m}/batch_norm_scale`},{paramPath:`${m}/batch_norm_offset`},{paramPath:`${m}/batch_norm_mean`},{paramPath:`${m}/batch_norm_variance`}),{filters:p,batch_norm_scale:d,batch_norm_offset:u,batch_norm_mean:l,batch_norm_variance:g}}function r(c,m,p,d,u){let l=nt.tensor4d(o(c*m*p*p),[p,p,c,m]),g=nt.tensor1d(o(m));return t.push({paramPath:`${d}/filters`},{paramPath:`${d}/${u?"batch_norm_offset":"bias"}`}),{filters:l,bias:g}}function n(c,m,p,d){let{filters:u,bias:l}=r(c,m,p,d,!0);return{filters:u,batch_norm_offset:l}}function a(c,m,p){let d=e(c,`${p}/depthwise_conv`),u=n(c,m,1,`${p}/pointwise_conv`);return{depthwise_conv:d,pointwise_conv:u}}function s(){let c=n(3,32,3,"mobilenetv1/conv_0"),m=a(32,64,"mobilenetv1/conv_1"),p=a(64,128,"mobilenetv1/conv_2"),d=a(128,128,"mobilenetv1/conv_3"),u=a(128,256,"mobilenetv1/conv_4"),l=a(256,256,"mobilenetv1/conv_5"),g=a(256,512,"mobilenetv1/conv_6"),_=a(512,512,"mobilenetv1/conv_7"),h=a(512,512,"mobilenetv1/conv_8"),v=a(512,512,"mobilenetv1/conv_9"),F=a(512,512,"mobilenetv1/conv_10"),y=a(512,512,"mobilenetv1/conv_11"),I=a(512,1024,"mobilenetv1/conv_12"),G=a(1024,1024,"mobilenetv1/conv_13");return{conv_0:c,conv_1:m,conv_2:p,conv_3:d,conv_4:u,conv_5:l,conv_6:g,conv_7:_,conv_8:h,conv_9:v,conv_10:F,conv_11:y,conv_12:I,conv_13:G}}function i(){let c=n(1024,256,1,"prediction_layer/conv_0"),m=n(256,512,3,"prediction_layer/conv_1"),p=n(512,128,1,"prediction_layer/conv_2"),d=n(128,256,3,"prediction_layer/conv_3"),u=n(256,128,1,"prediction_layer/conv_4"),l=n(128,256,3,"prediction_layer/conv_5"),g=n(256,64,1,"prediction_layer/conv_6"),_=n(64,128,3,"prediction_layer/conv_7"),h=r(512,12,1,"prediction_layer/box_predictor_0/box_encoding_predictor"),v=r(512,9,1,"prediction_layer/box_predictor_0/class_predictor"),F=r(1024,24,1,"prediction_layer/box_predictor_1/box_encoding_predictor"),y=r(1024,18,1,"prediction_layer/box_predictor_1/class_predictor"),I=r(512,24,1,"prediction_layer/box_predictor_2/box_encoding_predictor"),G=r(512,18,1,"prediction_layer/box_predictor_2/class_predictor"),tt=r(256,24,1,"prediction_layer/box_predictor_3/box_encoding_predictor"),at=r(256,18,1,"prediction_layer/box_predictor_3/class_predictor"),X=r(256,24,1,"prediction_layer/box_predictor_4/box_encoding_predictor"),Tt=r(256,18,1,"prediction_layer/box_predictor_4/class_predictor"),_t=r(128,24,1,"prediction_layer/box_predictor_5/box_encoding_predictor"),wt=r(128,18,1,"prediction_layer/box_predictor_5/class_predictor");return{conv_0:c,conv_1:m,conv_2:p,conv_3:d,conv_4:u,conv_5:l,conv_6:g,conv_7:_,box_predictor_0:{box_encoding_predictor:h,class_predictor:v},box_predictor_1:{box_encoding_predictor:F,class_predictor:y},box_predictor_2:{box_encoding_predictor:I,class_predictor:G},box_predictor_3:{box_encoding_predictor:tt,class_predictor:at},box_predictor_4:{box_encoding_predictor:X,class_predictor:Tt},box_predictor_5:{box_encoding_predictor:_t,class_predictor:wt}}}return{extractMobilenetV1Params:s,extractPredictionLayerParams:i}}function $o(o){let t=[],{extractWeights:e,getRemainingWeights:r}=W(o),{extractMobilenetV1Params:n,extractPredictionLayerParams:a}=Hn(e,t),s=n(),i=a(),m={extra_dim:nt.tensor3d(e(5118*4),[1,5118,4])};if(t.push({paramPath:"output_layer/extra_dim"}),r().length!==0)throw new Error(`weights remaing after extract: ${r().length}`);return{params:{mobilenetv1:s,prediction_layer:i,output_layer:m},paramMappings:t}}function Yn(o,t){let e=j(o,t);function r(m,p,d){let u=e(`${m}/Conv2d_${p}_pointwise/weights`,4,`${d}/filters`),l=e(`${m}/Conv2d_${p}_pointwise/convolution_bn_offset`,1,`${d}/batch_norm_offset`);return{filters:u,batch_norm_offset:l}}function n(m){let p=`mobilenetv1/conv_${m}`,d=`MobilenetV1/Conv2d_${m}_depthwise`,u=`${p}/depthwise_conv`,l=`${p}/pointwise_conv`,g=e(`${d}/depthwise_weights`,4,`${u}/filters`),_=e(`${d}/BatchNorm/gamma`,1,`${u}/batch_norm_scale`),h=e(`${d}/BatchNorm/beta`,1,`${u}/batch_norm_offset`),v=e(`${d}/BatchNorm/moving_mean`,1,`${u}/batch_norm_mean`),F=e(`${d}/BatchNorm/moving_variance`,1,`${u}/batch_norm_variance`);return{depthwise_conv:{filters:g,batch_norm_scale:_,batch_norm_offset:h,batch_norm_mean:v,batch_norm_variance:F},pointwise_conv:r("MobilenetV1",m,l)}}function a(){return{conv_0:r("MobilenetV1",0,"mobilenetv1/conv_0"),conv_1:n(1),conv_2:n(2),conv_3:n(3),conv_4:n(4),conv_5:n(5),conv_6:n(6),conv_7:n(7),conv_8:n(8),conv_9:n(9),conv_10:n(10),conv_11:n(11),conv_12:n(12),conv_13:n(13)}}function s(m,p){let d=e(`${m}/weights`,4,`${p}/filters`),u=e(`${m}/biases`,1,`${p}/bias`);return{filters:d,bias:u}}function i(m){let p=s(`Prediction/BoxPredictor_${m}/BoxEncodingPredictor`,`prediction_layer/box_predictor_${m}/box_encoding_predictor`),d=s(`Prediction/BoxPredictor_${m}/ClassPredictor`,`prediction_layer/box_predictor_${m}/class_predictor`);return{box_encoding_predictor:p,class_predictor:d}}function c(){return{conv_0:r("Prediction",0,"prediction_layer/conv_0"),conv_1:r("Prediction",1,"prediction_layer/conv_1"),conv_2:r("Prediction",2,"prediction_layer/conv_2"),conv_3:r("Prediction",3,"prediction_layer/conv_3"),conv_4:r("Prediction",4,"prediction_layer/conv_4"),conv_5:r("Prediction",5,"prediction_layer/conv_5"),conv_6:r("Prediction",6,"prediction_layer/conv_6"),conv_7:r("Prediction",7,"prediction_layer/conv_7"),box_predictor_0:i(0),box_predictor_1:i(1),box_predictor_2:i(2),box_predictor_3:i(3),box_predictor_4:i(4),box_predictor_5:i(5)}}return{extractMobilenetV1Params:a,extractPredictionLayerParams:c}}function Oo(o){let t=[],{extractMobilenetV1Params:e,extractPredictionLayerParams:r}=Yn(o,t),n=o["Output/extra_dim"];if(t.push({originalPath:"Output/extra_dim",paramPath:"output_layer/extra_dim"}),!ft(n))throw new Error(`expected weightMap['Output/extra_dim'] to be a Tensor3D, instead have ${n}`);let a={mobilenetv1:e(),prediction_layer:r(),output_layer:{extra_dim:n}};return A(o,t),{params:a,paramMappings:t}}var vt=b();var Lt=b();function J(o,t,e){return Lt.tidy(()=>{let r=Lt.conv2d(o,t.filters,e,"same");return r=Lt.add(r,t.batch_norm_offset),Lt.clipByValue(r,0,6)})}var Gn=.0010000000474974513;function zn(o,t,e){return vt.tidy(()=>{let r=vt.depthwiseConv2d(o,t.filters,e,"same");return r=vt.batchNorm(r,t.batch_norm_mean,t.batch_norm_variance,t.batch_norm_offset,t.batch_norm_scale,Gn),vt.clipByValue(r,0,6)})}function Vn(o){return[2,4,6,12].some(t=>t===o)?[2,2]:[1,1]}function jo(o,t){return vt.tidy(()=>{let e,r=J(o,t.conv_0,[2,2]);if([t.conv_1,t.conv_2,t.conv_3,t.conv_4,t.conv_5,t.conv_6,t.conv_7,t.conv_8,t.conv_9,t.conv_10,t.conv_11,t.conv_12,t.conv_13].forEach((a,s)=>{let i=s+1,c=Vn(i);r=zn(r,a.depthwise_conv,c),r=J(r,a.pointwise_conv,[1,1]),i===11&&(e=r)}),e===null)throw new Error("mobileNetV1 - output of conv layer 11 is null");return{out:r,conv11:e}})}function Un(o,t,e){let r=o.arraySync(),n=Math.min(r[t][0],r[t][2]),a=Math.min(r[t][1],r[t][3]),s=Math.max(r[t][0],r[t][2]),i=Math.max(r[t][1],r[t][3]),c=Math.min(r[e][0],r[e][2]),m=Math.min(r[e][1],r[e][3]),p=Math.max(r[e][0],r[e][2]),d=Math.max(r[e][1],r[e][3]),u=(s-n)*(i-a),l=(p-c)*(d-m);if(u<=0||l<=0)return 0;let g=Math.max(n,c),_=Math.max(a,m),h=Math.min(s,p),v=Math.min(i,d),F=Math.max(h-g,0)*Math.max(v-_,0);return F/(u+l-F)}function Ho(o,t,e,r,n){let a=o.shape[0],s=Math.min(e,a),i=t.map((p,d)=>({score:p,boxIndex:d})).filter(p=>p.score>n).sort((p,d)=>d.score-p.score),c=p=>p<=r?1:0,m=[];return i.forEach(p=>{if(m.length>=s)return;let d=p.score;for(let u=m.length-1;u>=0;--u){let l=Un(o,p.boxIndex,m[u]);if(l!==0&&(p.score*=c(l),p.score<=n))break}d===p.score&&m.push(p.boxIndex)}),m}var f=b();function Xn(o){let t=f.unstack(f.transpose(o,[1,0])),e=[f.sub(t[2],t[0]),f.sub(t[3],t[1])],r=[f.add(t[0],f.div(e[0],f.scalar(2))),f.add(t[1],f.div(e[1],f.scalar(2)))];return{sizes:e,centers:r}}function Jn(o,t){let{sizes:e,centers:r}=Xn(o),n=f.unstack(f.transpose(t,[1,0])),a=f.div(f.mul(f.exp(f.div(n[2],f.scalar(5))),e[0]),f.scalar(2)),s=f.add(f.mul(f.div(n[0],f.scalar(10)),e[0]),r[0]),i=f.div(f.mul(f.exp(f.div(n[3],f.scalar(5))),e[1]),f.scalar(2)),c=f.add(f.mul(f.div(n[1],f.scalar(10)),e[1]),r[1]);return f.transpose(f.stack([f.sub(s,a),f.sub(c,i),f.add(s,a),f.add(c,i)]),[1,0])}function Yo(o,t,e){return f.tidy(()=>{let r=o.shape[0],n=Jn(f.reshape(f.tile(e.extra_dim,[r,1,1]),[-1,4]),f.reshape(o,[-1,4]));n=f.reshape(n,[r,n.shape[0]/r,4]);let a=f.sigmoid(f.slice(t,[0,0,1],[-1,-1,-1])),s=f.slice(a,[0,0,0],[-1,-1,1]);s=f.reshape(s,[r,s.shape[1]]);let i=f.unstack(n),c=f.unstack(s);return{boxes:i,scores:c}})}var Oe=b();var $e=b();function Ut(o,t){return $e.tidy(()=>{let e=o.shape[0],r=$e.reshape(zt(o,t.box_encoding_predictor),[e,-1,1,4]),n=$e.reshape(zt(o,t.class_predictor),[e,-1,3]);return{boxPredictionEncoding:r,classPrediction:n}})}function Go(o,t,e){return Oe.tidy(()=>{let r=J(o,e.conv_0,[1,1]),n=J(r,e.conv_1,[2,2]),a=J(n,e.conv_2,[1,1]),s=J(a,e.conv_3,[2,2]),i=J(s,e.conv_4,[1,1]),c=J(i,e.conv_5,[2,2]),m=J(c,e.conv_6,[1,1]),p=J(m,e.conv_7,[2,2]),d=Ut(t,e.box_predictor_0),u=Ut(o,e.box_predictor_1),l=Ut(n,e.box_predictor_2),g=Ut(s,e.box_predictor_3),_=Ut(c,e.box_predictor_4),h=Ut(p,e.box_predictor_5),v=Oe.concat([d.boxPredictionEncoding,u.boxPredictionEncoding,l.boxPredictionEncoding,g.boxPredictionEncoding,_.boxPredictionEncoding,h.boxPredictionEncoding],1),F=Oe.concat([d.classPrediction,u.classPrediction,l.classPrediction,g.classPrediction,_.classPrediction,h.classPrediction],1);return{boxPredictions:v,classPredictions:F}})}var q=class{constructor({minConfidence:t,maxResults:e}={}){this._name="SsdMobilenetv1Options";if(this._minConfidence=t||.5,this._maxResults=e||100,typeof this._minConfidence!="number"||this._minConfidence<=0||this._minConfidence>=1)throw new Error(`${this._name} - expected minConfidence to be a number between 0 and 1`);if(typeof this._maxResults!="number")throw new Error(`${this._name} - expected maxResults to be a number`)}get minConfidence(){return this._minConfidence}get maxResults(){return this._maxResults}};var Xt=class extends k{constructor(){super("SsdMobilenetv1")}forwardInput(t){let{params:e}=this;if(!e)throw new Error("SsdMobilenetv1 - load model before inference");return kt.tidy(()=>{let r=kt.cast(t.toBatchTensor(512,!1),"float32"),n=kt.sub(kt.div(r,127.5),1),a=jo(n,e.mobilenetv1),{boxPredictions:s,classPredictions:i}=Go(a.out,a.conv11,e.prediction_layer);return Yo(s,i,e.output_layer)})}async forward(t){return this.forwardInput(await D(t))}async locateFaces(t,e={}){let{maxResults:r,minConfidence:n}=new q(e),a=await D(t),{boxes:s,scores:i}=this.forwardInput(a),c=s[0],m=i[0];for(let y=1;y{let[I,G]=[Math.max(0,v[y][0]),Math.min(1,v[y][2])].map(X=>X*h),[tt,at]=[Math.max(0,v[y][1]),Math.min(1,v[y][3])].map(X=>X*_);return new E(p[y],new oe(tt,I,at-tt,G-I),{height:a.getInputHeight(0),width:a.getInputWidth(0)})});return c.dispose(),m.dispose(),F}getDefaultModelName(){return"ssd_mobilenetv1_model"}extractParamsFromWeightMap(t){return Oo(t)}extractParams(t){return $o(t)}};function zo(o){let t=new Xt;return t.extractWeights(o),t}function qn(o){return zo(o)}var Vo=class extends Xt{};var Uo=.4,Xo=[new x(.738768,.874946),new x(2.42204,2.65704),new x(4.30971,7.04493),new x(10.246,4.59428),new x(12.6868,11.8741)],Jo=[new x(1.603231,2.094468),new x(6.041143,7.080126),new x(2.882459,3.518061),new x(4.266906,5.178857),new x(9.041765,10.66308)],qo=[117.001,114.697,97.404],Zo="tiny_yolov2_model",Ko="tiny_yolov2_separable_conv_model";var C=b();var xr=o=>typeof o=="number";function oo(o){if(!o)throw new Error(`invalid config: ${o}`);if(typeof o.withSeparableConvs!="boolean")throw new Error(`config.withSeparableConvs has to be a boolean, have: ${o.withSeparableConvs}`);if(!xr(o.iouThreshold)||o.iouThreshold<0||o.iouThreshold>1)throw new Error(`config.iouThreshold has to be a number between [0, 1], have: ${o.iouThreshold}`);if(!Array.isArray(o.classes)||!o.classes.length||!o.classes.every(t=>typeof t=="string"))throw new Error(`config.classes has to be an array class names: string[], have: ${JSON.stringify(o.classes)}`);if(!Array.isArray(o.anchors)||!o.anchors.length||!o.anchors.map(t=>t||{}).every(t=>xr(t.x)&&xr(t.y)))throw new Error(`config.anchors has to be an array of { x: number, y: number }, have: ${JSON.stringify(o.anchors)}`);if(o.meanRgb&&(!Array.isArray(o.meanRgb)||o.meanRgb.length!==3||!o.meanRgb.every(xr)))throw new Error(`config.meanRgb has to be an array of shape [number, number, number], have: ${JSON.stringify(o.meanRgb)}`)}var K=b();var Z=b();function be(o){return Z.tidy(()=>{let t=Z.mul(o,Z.scalar(.10000000149011612));return Z.add(Z.relu(Z.sub(o,t)),t)})}function yt(o,t){return K.tidy(()=>{let e=K.pad(o,[[0,0],[1,1],[1,1],[0,0]]);return e=K.conv2d(e,t.conv.filters,[1,1],"valid"),e=K.sub(e,t.bn.sub),e=K.mul(e,t.bn.truediv),e=K.add(e,t.conv.bias),be(e)})}var St=b();function Ft(o,t){return St.tidy(()=>{let e=St.pad(o,[[0,0],[1,1],[1,1],[0,0]]);return e=St.separableConv2d(e,t.depthwise_filter,t.pointwise_filter,[1,1],"valid"),e=St.add(e,t.bias),be(e)})}var no=b();function Zn(o,t){let e=ce(o,t);function r(s,i){let c=no.tensor1d(o(s)),m=no.tensor1d(o(s));return t.push({paramPath:`${i}/sub`},{paramPath:`${i}/truediv`}),{sub:c,truediv:m}}function n(s,i,c){let m=e(s,i,3,`${c}/conv`),p=r(i,`${c}/bn`);return{conv:m,bn:p}}let a=me(o,t);return{extractConvParams:e,extractConvWithBatchNormParams:n,extractSeparableConvParams:a}}function Qo(o,t,e,r){let{extractWeights:n,getRemainingWeights:a}=W(o),s=[],{extractConvParams:i,extractConvWithBatchNormParams:c,extractSeparableConvParams:m}=Zn(n,s),p;if(t.withSeparableConvs){let[d,u,l,g,_,h,v,F,y]=r,I=t.isFirstLayerConv2d?i(d,u,3,"conv0"):m(d,u,"conv0"),G=m(u,l,"conv1"),tt=m(l,g,"conv2"),at=m(g,_,"conv3"),X=m(_,h,"conv4"),Tt=m(h,v,"conv5"),_t=F?m(v,F,"conv6"):void 0,wt=y?m(F,y,"conv7"):void 0,te=i(y||F||v,5*e,1,"conv8");p={conv0:I,conv1:G,conv2:tt,conv3:at,conv4:X,conv5:Tt,conv6:_t,conv7:wt,conv8:te}}else{let[d,u,l,g,_,h,v,F,y]=r,I=c(d,u,"conv0"),G=c(u,l,"conv1"),tt=c(l,g,"conv2"),at=c(g,_,"conv3"),X=c(_,h,"conv4"),Tt=c(h,v,"conv5"),_t=c(v,F,"conv6"),wt=c(F,y,"conv7"),te=i(y,5*e,1,"conv8");p={conv0:I,conv1:G,conv2:tt,conv3:at,conv4:X,conv5:Tt,conv6:_t,conv7:wt,conv8:te}}if(a().length!==0)throw new Error(`weights remaing after extract: ${a().length}`);return{params:p,paramMappings:s}}function Kn(o,t){let e=j(o,t);function r(i){let c=e(`${i}/sub`,1),m=e(`${i}/truediv`,1);return{sub:c,truediv:m}}function n(i){let c=e(`${i}/filters`,4),m=e(`${i}/bias`,1);return{filters:c,bias:m}}function a(i){let c=n(`${i}/conv`),m=r(`${i}/bn`);return{conv:c,bn:m}}let s=pe(e);return{extractConvParams:n,extractConvWithBatchNormParams:a,extractSeparableConvParams:s}}function tn(o,t){let e=[],{extractConvParams:r,extractConvWithBatchNormParams:n,extractSeparableConvParams:a}=Kn(o,e),s;if(t.withSeparableConvs){let i=t.filterSizes&&t.filterSizes.length||9;s={conv0:t.isFirstLayerConv2d?r("conv0"):a("conv0"),conv1:a("conv1"),conv2:a("conv2"),conv3:a("conv3"),conv4:a("conv4"),conv5:a("conv5"),conv6:i>7?a("conv6"):void 0,conv7:i>8?a("conv7"):void 0,conv8:r("conv8")}}else s={conv0:n("conv0"),conv1:n("conv1"),conv2:n("conv2"),conv3:n("conv3"),conv4:n("conv4"),conv5:n("conv5"),conv6:n("conv6"),conv7:n("conv7"),conv8:r("conv8")};return A(o,e),{params:s,paramMappings:e}}var dt=class{constructor({inputSize:t,scoreThreshold:e}={}){this._name="TinyYolov2Options";if(this._inputSize=t||416,this._scoreThreshold=e||.5,typeof this._inputSize!="number"||this._inputSize%32!=0)throw new Error(`${this._name} - expected inputSize to be a number divisible by 32`);if(typeof this._scoreThreshold!="number"||this._scoreThreshold<=0||this._scoreThreshold>=1)throw new Error(`${this._name} - expected scoreThreshold to be a number between 0 and 1`)}get inputSize(){return this._inputSize}get scoreThreshold(){return this._scoreThreshold}};var ao=class extends k{constructor(t){super("TinyYolov2");oo(t),this._config=t}get config(){return this._config}get withClassScores(){return this.config.withClassScores||this.config.classes.length>1}get boxEncodingSize(){return 5+(this.withClassScores?this.config.classes.length:0)}runTinyYolov2(t,e){let r=yt(t,e.conv0);return r=C.maxPool(r,[2,2],[2,2],"same"),r=yt(r,e.conv1),r=C.maxPool(r,[2,2],[2,2],"same"),r=yt(r,e.conv2),r=C.maxPool(r,[2,2],[2,2],"same"),r=yt(r,e.conv3),r=C.maxPool(r,[2,2],[2,2],"same"),r=yt(r,e.conv4),r=C.maxPool(r,[2,2],[2,2],"same"),r=yt(r,e.conv5),r=C.maxPool(r,[2,2],[1,1],"same"),r=yt(r,e.conv6),r=yt(r,e.conv7),zt(r,e.conv8,"valid",!1)}runMobilenet(t,e){let r=this.config.isFirstLayerConv2d?be(zt(t,e.conv0,"valid",!1)):Ft(t,e.conv0);return r=C.maxPool(r,[2,2],[2,2],"same"),r=Ft(r,e.conv1),r=C.maxPool(r,[2,2],[2,2],"same"),r=Ft(r,e.conv2),r=C.maxPool(r,[2,2],[2,2],"same"),r=Ft(r,e.conv3),r=C.maxPool(r,[2,2],[2,2],"same"),r=Ft(r,e.conv4),r=C.maxPool(r,[2,2],[2,2],"same"),r=Ft(r,e.conv5),r=C.maxPool(r,[2,2],[1,1],"same"),r=e.conv6?Ft(r,e.conv6):r,r=e.conv7?Ft(r,e.conv7):r,zt(r,e.conv8,"valid",!1)}forwardInput(t,e){let{params:r}=this;if(!r)throw new Error("TinyYolov2 - load model before inference");return C.tidy(()=>{let n=C.cast(t.toBatchTensor(e,!1),"float32");return n=this.config.meanRgb?rt(n,this.config.meanRgb):n,n=n.div(C.scalar(256)),this.config.withSeparableConvs?this.runMobilenet(n,r):this.runTinyYolov2(n,r)})}async forward(t,e){return this.forwardInput(await D(t),e)}async detect(t,e={}){let{inputSize:r,scoreThreshold:n}=new dt(e),a=await D(t),s=await this.forwardInput(a,r),i=C.tidy(()=>C.unstack(s)[0].expandDims()),c={width:a.getInputWidth(0),height:a.getInputHeight(0)},m=await this.extractBoxes(i,a.getReshapedInputDimensions(0),n);s.dispose(),i.dispose();let p=m.map(h=>h.box),d=m.map(h=>h.score),u=m.map(h=>h.classScore),l=m.map(h=>this.config.classes[h.label]);return kr(p.map(h=>h.rescale(r)),d,this.config.iouThreshold,!0).map(h=>new Pt(d[h],u[h],l[h],p[h],c))}getDefaultModelName(){return""}extractParamsFromWeightMap(t){return tn(t,this.config)}extractParams(t){let e=this.config.filterSizes||ao.DEFAULT_FILTER_SIZES,r=e?e.length:void 0;if(r!==7&&r!==8&&r!==9)throw new Error(`TinyYolov2 - expected 7 | 8 | 9 convolutional filters, but found ${r} filterSizes in config`);return Qo(t,this.config,this.boxEncodingSize,e)}async extractBoxes(t,e,r){let{width:n,height:a}=e,s=Math.max(n,a),i=s/n,c=s/a,m=t.shape[1],p=this.config.anchors.length,[d,u,l]=C.tidy(()=>{let v=t.reshape([m,m,p,this.boxEncodingSize]),F=v.slice([0,0,0,0],[m,m,p,4]),y=v.slice([0,0,0,4],[m,m,p,1]),I=this.withClassScores?C.softmax(v.slice([0,0,0,5],[m,m,p,this.config.classes.length]),3):C.scalar(0);return[F,y,I]}),g=[],_=await u.array(),h=await d.array();for(let v=0;vr){let G=(F+De(h[v][F][y][0]))/m*i,tt=(v+De(h[v][F][y][1]))/m*c,at=Math.exp(h[v][F][y][2])*this.config.anchors[y].x/m*i,X=Math.exp(h[v][F][y][3])*this.config.anchors[y].y/m*c,Tt=G-at/2,_t=tt-X/2,wt={row:v,col:F,anchor:y},{classScore:te,label:po}=this.withClassScores?await this.extractPredictedClass(l,wt):{classScore:1,label:0};g.push({box:new re(Tt,_t,Tt+at,_t+X),score:I,classScore:I*te,label:po,...wt})}}return d.dispose(),u.dispose(),l.dispose(),g}async extractPredictedClass(t,e){let{row:r,col:n,anchor:a}=e,s=await t.array();return Array(this.config.classes.length).fill(0).map((i,c)=>s[r][n][a][c]).map((i,c)=>({classScore:i,label:c})).reduce((i,c)=>i.classScore>c.classScore?i:c)}},ge=ao;ge.DEFAULT_FILTER_SIZES=[3,16,32,64,128,256,512,1024,1024];var ve=class extends ge{constructor(t=!0){let e={withSeparableConvs:t,iouThreshold:Uo,classes:["face"],...t?{anchors:Jo,meanRgb:qo}:{anchors:Xo,withClassScores:!0}};super(e)}get withSeparableConvs(){return this.config.withSeparableConvs}get anchors(){return this.config.anchors}async locateFaces(t,e){return(await this.detect(t,e)).map(n=>new E(n.score,n.relativeBox,{width:n.imageWidth,height:n.imageHeight}))}getDefaultModelName(){return this.withSeparableConvs?Ko:Zo}extractParamsFromWeightMap(t){return super.extractParamsFromWeightMap(t)}};function Qn(o,t=!0){let e=new ve(t);return e.extractWeights(o),e}var br=class extends dt{constructor(){super(...arguments);this._name="TinyFaceDetectorOptions"}};var Q=class{async then(t){return t(await this.run())}async run(){throw new Error("ComposableTask - run is not implemented")}};var je=b();var so=b();async function Jt(o,t,e,r,n=({alignedRect:a})=>a){let a=o.map(c=>Vt(c)?n(c):c.detection),s=r||(t instanceof so.Tensor?await se(t,a):await ae(t,a)),i=await e(s);return s.forEach(c=>c instanceof so.Tensor&&c.dispose()),i}async function ye(o,t,e,r,n){return Jt([o],t,async a=>e(a[0]),r,n)}var en=.4,rn=[new x(1.603231,2.094468),new x(6.041143,7.080126),new x(2.882459,3.518061),new x(4.266906,5.178857),new x(9.041765,10.66308)],on=[117.001,114.697,97.404];var Fe=class extends ge{constructor(){let t={withSeparableConvs:!0,iouThreshold:en,classes:["face"],anchors:rn,meanRgb:on,isFirstLayerConv2d:!0,filterSizes:[3,16,32,64,128,256,512]};super(t)}get anchors(){return this.config.anchors}async locateFaces(t,e){return(await this.detect(t,e)).map(n=>new E(n.score,n.relativeBox,{width:n.imageWidth,height:n.imageHeight}))}getDefaultModelName(){return"tiny_face_detector_model"}extractParamsFromWeightMap(t){return super.extractParamsFromWeightMap(t)}};var T={ssdMobilenetv1:new Xt,tinyFaceDetector:new Fe,tinyYolov2:new ve,faceLandmark68Net:new fe,faceLandmark68TinyNet:new pr,faceRecognitionNet:new xe,faceExpressionNet:new ir,ageGenderNet:new mr},nn=(o,t)=>T.ssdMobilenetv1.locateFaces(o,t),ta=(o,t)=>T.tinyFaceDetector.locateFaces(o,t),ea=(o,t)=>T.tinyYolov2.locateFaces(o,t),an=o=>T.faceLandmark68Net.detectLandmarks(o),ra=o=>T.faceLandmark68TinyNet.detectLandmarks(o),oa=o=>T.faceRecognitionNet.computeFaceDescriptor(o),na=o=>T.faceExpressionNet.predictExpressions(o),aa=o=>T.ageGenderNet.predictAgeAndGender(o),sn=o=>T.ssdMobilenetv1.load(o),sa=o=>T.tinyFaceDetector.load(o),ia=o=>T.tinyYolov2.load(o),ca=o=>T.faceLandmark68Net.load(o),ma=o=>T.faceLandmark68TinyNet.load(o),pa=o=>T.faceRecognitionNet.load(o),da=o=>T.faceExpressionNet.load(o),ua=o=>T.ageGenderNet.load(o),la=sn,fa=nn,ha=an;var io=class extends Q{constructor(t,e,r){super();this.parentTask=t;this.input=e;this.extractedFaces=r}},we=class extends io{async run(){let t=await this.parentTask,e=await Jt(t,this.input,async r=>Promise.all(r.map(n=>T.faceExpressionNet.predictExpressions(n))),this.extractedFaces);return t.map((r,n)=>cr(r,e[n]))}withAgeAndGender(){return new Te(this,this.input)}},Pe=class extends io{async run(){let t=await this.parentTask;if(!t)return;let e=await ye(t,this.input,r=>T.faceExpressionNet.predictExpressions(r),this.extractedFaces);return cr(t,e)}withAgeAndGender(){return new _e(this,this.input)}},Kt=class extends we{withAgeAndGender(){return new qt(this,this.input)}withFaceDescriptors(){return new At(this,this.input)}},Qt=class extends Pe{withAgeAndGender(){return new Zt(this,this.input)}withFaceDescriptor(){return new Wt(this,this.input)}};var co=class extends Q{constructor(t,e,r){super();this.parentTask=t;this.input=e;this.extractedFaces=r}},Te=class extends co{async run(){let t=await this.parentTask,e=await Jt(t,this.input,async r=>Promise.all(r.map(n=>T.ageGenderNet.predictAgeAndGender(n))),this.extractedFaces);return t.map((r,n)=>{let{age:a,gender:s,genderProbability:i}=e[n];return fr(hr(r,s,i),a)})}withFaceExpressions(){return new we(this,this.input)}},_e=class extends co{async run(){let t=await this.parentTask;if(!t)return;let{age:e,gender:r,genderProbability:n}=await ye(t,this.input,a=>T.ageGenderNet.predictAgeAndGender(a),this.extractedFaces);return fr(hr(t,r,n),e)}withFaceExpressions(){return new Pe(this,this.input)}},qt=class extends Te{withFaceExpressions(){return new Kt(this,this.input)}withFaceDescriptors(){return new At(this,this.input)}},Zt=class extends _e{withFaceExpressions(){return new Qt(this,this.input)}withFaceDescriptor(){return new Wt(this,this.input)}};var gr=class extends Q{constructor(t,e){super();this.parentTask=t;this.input=e}},At=class extends gr{async run(){let t=await this.parentTask;return(await Jt(t,this.input,r=>Promise.all(r.map(n=>T.faceRecognitionNet.computeFaceDescriptor(n))),null,r=>r.landmarks.align(null,{useDlibAlignment:!0}))).map((r,n)=>lr(t[n],r))}withFaceExpressions(){return new Kt(this,this.input)}withAgeAndGender(){return new qt(this,this.input)}},Wt=class extends gr{async run(){let t=await this.parentTask;if(!t)return;let e=await ye(t,this.input,r=>T.faceRecognitionNet.computeFaceDescriptor(r),null,r=>r.landmarks.align(null,{useDlibAlignment:!0}));return lr(t,e)}withFaceExpressions(){return new Qt(this,this.input)}withAgeAndGender(){return new Zt(this,this.input)}};var vr=class extends Q{constructor(t,e,r){super();this.parentTask=t;this.input=e;this.useTinyLandmarkNet=r}get landmarkNet(){return this.useTinyLandmarkNet?T.faceLandmark68TinyNet:T.faceLandmark68Net}},yr=class extends vr{async run(){let t=await this.parentTask,e=t.map(a=>a.detection),r=this.input instanceof je.Tensor?await se(this.input,e):await ae(this.input,e),n=await Promise.all(r.map(a=>this.landmarkNet.detectLandmarks(a)));return r.forEach(a=>a instanceof je.Tensor&&a.dispose()),t.map((a,s)=>le(a,n[s]))}withFaceExpressions(){return new Kt(this,this.input)}withAgeAndGender(){return new qt(this,this.input)}withFaceDescriptors(){return new At(this,this.input)}},Fr=class extends vr{async run(){let t=await this.parentTask;if(!t)return;let{detection:e}=t,r=this.input instanceof je.Tensor?await se(this.input,[e]):await ae(this.input,[e]),n=await this.landmarkNet.detectLandmarks(r[0]);return r.forEach(a=>a instanceof je.Tensor&&a.dispose()),le(t,n)}withFaceExpressions(){return new Qt(this,this.input)}withAgeAndGender(){return new Zt(this,this.input)}withFaceDescriptor(){return new Wt(this,this.input)}};var Tr=class extends Q{constructor(t,e=new q){super();this.input=t;this.options=e}},He=class extends Tr{async run(){let{input:t,options:e}=this,r;if(e instanceof br)r=T.tinyFaceDetector.locateFaces(t,e);else if(e instanceof q)r=T.ssdMobilenetv1.locateFaces(t,e);else if(e instanceof dt)r=T.tinyYolov2.locateFaces(t,e);else throw new Error("detectFaces - expected options to be instance of TinyFaceDetectorOptions | SsdMobilenetv1Options | TinyYolov2Options");return r}runAndExtendWithFaceDetections(){return new Promise(async t=>{let e=await this.run();t(e.map(r=>Ot({},r)))})}withFaceLandmarks(t=!1){return new yr(this.runAndExtendWithFaceDetections(),this.input,t)}withFaceExpressions(){return new we(this.runAndExtendWithFaceDetections(),this.input)}withAgeAndGender(){return new Te(this.runAndExtendWithFaceDetections(),this.input)}},_r=class extends Tr{async run(){let t=await new He(this.input,this.options),e=t[0];return t.forEach(r=>{r.score>e.score&&(e=r)}),e}runAndExtendWithFaceDetection(){return new Promise(async t=>{let e=await this.run();t(e?Ot({},e):void 0)})}withFaceLandmarks(t=!1){return new Fr(this.runAndExtendWithFaceDetection(),this.input,t)}withFaceExpressions(){return new Pe(this.runAndExtendWithFaceDetection(),this.input)}withAgeAndGender(){return new _e(this.runAndExtendWithFaceDetection(),this.input)}};function xa(o,t=new q){return new _r(o,t)}function wr(o,t=new q){return new He(o,t)}async function cn(o,t){return wr(o,new q(t?{minConfidence:t}:{})).withFaceLandmarks().withFaceDescriptors()}async function ba(o,t={}){return wr(o,new dt(t)).withFaceLandmarks().withFaceDescriptors()}var ga=cn;function mo(o,t){if(o.length!==t.length)throw new Error("euclideanDistance: arr1.length !== arr2.length");let e=Array.from(o),r=Array.from(t);return Math.sqrt(e.map((n,a)=>n-r[a]).reduce((n,a)=>n+a**2,0))}var Pr=class{constructor(t,e=.6){this._distanceThreshold=e;let r=Array.isArray(t)?t:[t];if(!r.length)throw new Error("FaceRecognizer.constructor - expected atleast one input");let n=1,a=()=>`person ${n++}`;this._labeledDescriptors=r.map(s=>{if(s instanceof ht)return s;if(s instanceof Float32Array)return new ht(a(),[s]);if(s.descriptor&&s.descriptor instanceof Float32Array)return new ht(a(),[s.descriptor]);throw new Error("FaceRecognizer.constructor - expected inputs to be of type LabeledFaceDescriptors | WithFaceDescriptor | Float32Array | Array | Float32Array>")})}get labeledDescriptors(){return this._labeledDescriptors}get distanceThreshold(){return this._distanceThreshold}computeMeanDistance(t,e){return e.map(r=>mo(r,t)).reduce((r,n)=>r+n,0)/(e.length||1)}matchDescriptor(t){return this.labeledDescriptors.map(({descriptors:e,label:r})=>new Ee(r,this.computeMeanDistance(t,e))).reduce((e,r)=>e.distancet.toJSON())}}static fromJSON(t){let e=t.labeledDescriptors.map(r=>ht.fromJSON(r));return new Pr(e,t.distanceThreshold)}};function va(o){let t=new Fe;return t.extractWeights(o),t}function mn(o,t){let{width:e,height:r}=new S(t.width,t.height);if(e<=0||r<=0)throw new Error(`resizeResults - invalid dimensions: ${JSON.stringify({width:e,height:r})}`);if(Array.isArray(o))return o.map(n=>mn(n,{width:e,height:r}));if(Vt(o)){let n=o.detection.forSize(e,r),a=o.unshiftedLandmarks.forSize(n.box.width,n.box.height);return le(Ot(o,n),a)}return ct(o)?Ot(o,o.detection.forSize(e,r)):o instanceof V||o instanceof E?o.forSize(e,r):o}var Fa=typeof process!="undefined",Ta=typeof navigator!="undefined"&&typeof navigator.userAgent!="undefined",_a={faceapi:Do,node:Fa,browser:Ta};export{mr as AgeGenderNet,re as BoundingBox,P as Box,Q as ComposableTask,At as ComputeAllFaceDescriptorsTask,gr as ComputeFaceDescriptorsTaskBase,Wt as ComputeSingleFaceDescriptorTask,yr as DetectAllFaceLandmarksTask,He as DetectAllFacesTask,vr as DetectFaceLandmarksTaskBase,Tr as DetectFacesTaskBase,Fr as DetectSingleFaceLandmarksTask,_r as DetectSingleFaceTask,S as Dimensions,Xr as FACE_EXPRESSION_LABELS,E as FaceDetection,Vo as FaceDetectionNet,ir as FaceExpressionNet,Nt as FaceExpressions,fe as FaceLandmark68Net,pr as FaceLandmark68TinyNet,So as FaceLandmarkNet,V as FaceLandmarks,ho as FaceLandmarks5,ne as FaceLandmarks68,Ee as FaceMatch,Pr as FaceMatcher,xe as FaceRecognitionNet,gt as Gender,Me as LabeledBox,ht as LabeledFaceDescriptors,xt as NetInput,k as NeuralNetwork,Pt as ObjectDetection,x as Point,xo as PredictedBox,oe as Rect,Xt as SsdMobilenetv1,q as SsdMobilenetv1Options,Fe as TinyFaceDetector,br as TinyFaceDetectorOptions,ve as TinyYolov2,dt as TinyYolov2Options,ga as allFaces,cn as allFacesSsdMobilenetv1,ba as allFacesTinyYolov2,Hr as awaitMediaLoaded,Yr as bufferToImage,oa as computeFaceDescriptor,Yt as createCanvas,Ie as createCanvasFromMedia,qn as createFaceDetectionNet,$n as createFaceRecognitionNet,zo as createSsdMobilenetv1,va as createTinyFaceDetector,Qn as createTinyYolov2,wr as detectAllFaces,an as detectFaceLandmarks,ra as detectFaceLandmarksTiny,ha as detectLandmarks,xa as detectSingleFace,Po as draw,w as env,mo as euclideanDistance,fr as extendWithAge,lr as extendWithFaceDescriptor,Ot as extendWithFaceDetection,cr as extendWithFaceExpressions,le as extendWithFaceLandmarks,hr as extendWithGender,se as extractFaceTensors,ae as extractFaces,Mn as fetchImage,Vr as fetchJson,Cn as fetchNetWeights,Gt as fetchOrThrow,R as getContext2dOrThrow,Ht as getMediaDimensions,Gr as imageTensorToCanvas,zr as imageToSquare,vn as inverseSigmoid,Ir as iou,Je as isMediaElement,Ne as isMediaLoaded,On as isWithAge,ct as isWithFaceDetection,Jr as isWithFaceExpressions,Vt as isWithFaceLandmarks,jn as isWithGender,ua as loadAgeGenderModel,la as loadFaceDetectionModel,da as loadFaceExpressionModel,ca as loadFaceLandmarkModel,ma as loadFaceLandmarkTinyModel,pa as loadFaceRecognitionModel,sn as loadSsdMobilenetv1Model,sa as loadTinyFaceDetectorModel,ia as loadTinyYolov2Model,Ur as loadWeightMap,fa as locateFaces,Nn as matchDimensions,Lr as minBbox,T as nets,kr as nonMaxSuppression,rt as normalize,Sr as padToSquare,aa as predictAgeAndGender,na as recognizeFaceExpressions,mn as resizeResults,jt as resolveInput,gn as shuffleArray,De as sigmoid,nn as ssdMobilenetv1,ya as tf,ta as tinyFaceDetector,ea as tinyYolov2,D as toNetInput,lo as utils,oo as validateConfig,_a as version};
//# sourceMappingURL=face-api.esm-nobundle.js.map
diff --git a/dist/face-api.esm-nobundle.js.map b/dist/face-api.esm-nobundle.js.map
index 3dc4f2b..ff1f0bf 100644
--- a/dist/face-api.esm-nobundle.js.map
+++ b/dist/face-api.esm-nobundle.js.map
@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["../src/tfjs/tf-browser.ts", "../src/env/isNodejs.ts", "../src/index.ts", "../src/draw/index.ts", "../src/draw/drawContour.ts", "../src/utils/index.ts", "../src/classes/Dimensions.ts", "../src/classes/Point.ts", "../src/classes/Box.ts", "../src/classes/BoundingBox.ts", "../src/classes/ObjectDetection.ts", "../src/classes/FaceDetection.ts", "../src/ops/iou.ts", "../src/ops/minBbox.ts", "../src/ops/nonMaxSuppression.ts", "../src/ops/normalize.ts", "../src/ops/padToSquare.ts", "../src/ops/shuffleArray.ts", "../src/ops/index.ts", "../src/classes/Rect.ts", "../src/classes/FaceLandmarks.ts", "../src/classes/FaceLandmarks5.ts", "../src/classes/FaceLandmarks68.ts", "../src/classes/FaceMatch.ts", "../src/classes/LabeledBox.ts", "../src/classes/LabeledFaceDescriptors.ts", "../src/classes/PredictedBox.ts", "../src/factories/WithFaceDetection.ts", "../src/env/createBrowserEnv.ts", "../src/env/createFileSystem.ts", "../src/env/createNodejsEnv.ts", "../src/env/isBrowser.ts", "../src/env/index.ts", "../src/dom/resolveInput.ts", "../src/dom/getContext2dOrThrow.ts", "../src/draw/DrawTextField.ts", "../src/draw/DrawBox.ts", "../src/draw/drawDetections.ts", "../src/faceExpressionNet/FaceExpressionNet.ts", "../src/dom/isMediaLoaded.ts", "../src/dom/awaitMediaLoaded.ts", "../src/dom/bufferToImage.ts", "../src/dom/getMediaDimensions.ts", "../src/dom/createCanvas.ts", "../src/dom/imageTensorToCanvas.ts", "../src/dom/isMediaElement.ts", "../src/dom/NetInput.ts", "../src/dom/imageToSquare.ts", "../src/dom/toNetInput.ts", "../src/dom/extractFaces.ts", "../src/dom/extractFaceTensors.ts", "../src/dom/fetchOrThrow.ts", "../src/dom/fetchImage.ts", "../src/dom/fetchJson.ts", "../src/dom/fetchNetWeights.ts", "../src/dom/loadWeightMap.ts", "../src/common/getModelUris.ts", "../src/dom/matchDimensions.ts", "../src/faceFeatureExtractor/FaceFeatureExtractor.ts", "../src/NeuralNetwork.ts", "../src/faceFeatureExtractor/denseBlock.ts", "../src/common/depthwiseSeparableConv.ts", "../src/common/convLayer.ts", "../src/common/disposeUnusedWeightTensors.ts", "../src/common/extractConvParamsFactory.ts", "../src/common/extractFCParamsFactory.ts", "../src/common/extractSeparableConvParamsFactory.ts", "../src/common/types.ts", "../src/common/extractWeightEntryFactory.ts", "../src/common/extractWeightsFactory.ts", "../src/faceFeatureExtractor/extractorsFactory.ts", "../src/faceFeatureExtractor/extractParams.ts", "../src/common/loadConvParamsFactory.ts", "../src/faceFeatureExtractor/loadParamsFactory.ts", "../src/faceFeatureExtractor/extractParamsFromWeightMap.ts", "../src/faceProcessor/FaceProcessor.ts", "../src/common/fullyConnectedLayer.ts", "../src/faceProcessor/extractParams.ts", "../src/faceProcessor/extractParamsFromWeightMap.ts", "../src/faceProcessor/util.ts", "../src/faceExpressionNet/FaceExpressions.ts", "../src/factories/WithFaceExpressions.ts", "../src/draw/drawFaceExpressions.ts", "../src/factories/WithFaceLandmarks.ts", "../src/draw/DrawFaceLandmarks.ts", "../src/ageGenderNet/AgeGenderNet.ts", "../src/xception/TinyXception.ts", "../src/xception/extractParams.ts", "../src/xception/extractParamsFromWeightMap.ts", "../src/ageGenderNet/extractParams.ts", "../src/ageGenderNet/extractParamsFromWeightMap.ts", "../src/ageGenderNet/types.ts", "../src/faceLandmarkNet/FaceLandmark68NetBase.ts", "../src/faceLandmarkNet/FaceLandmark68Net.ts", "../src/faceFeatureExtractor/TinyFaceFeatureExtractor.ts", "../src/faceFeatureExtractor/extractParamsFromWeightMapTiny.ts", "../src/faceFeatureExtractor/extractParamsTiny.ts", "../src/faceLandmarkNet/FaceLandmark68TinyNet.ts", "../src/faceLandmarkNet/index.ts", "../src/faceRecognitionNet/FaceRecognitionNet.ts", "../src/faceRecognitionNet/convLayer.ts", "../src/faceRecognitionNet/scaleLayer.ts", "../src/faceRecognitionNet/extractParams.ts", "../src/faceRecognitionNet/extractParamsFromWeightMap.ts", "../src/faceRecognitionNet/residualLayer.ts", "../src/faceRecognitionNet/index.ts", "../src/factories/WithFaceDescriptor.ts", "../src/factories/WithAge.ts", "../src/factories/WithGender.ts", "../src/ssdMobilenetv1/SsdMobilenetv1.ts", "../src/ssdMobilenetv1/extractParams.ts", "../src/ssdMobilenetv1/extractParamsFromWeightMap.ts", "../src/ssdMobilenetv1/mobileNetV1.ts", "../src/ssdMobilenetv1/pointwiseConvLayer.ts", "../src/ssdMobilenetv1/nonMaxSuppression.ts", "../src/ssdMobilenetv1/outputLayer.ts", "../src/ssdMobilenetv1/predictionLayer.ts", "../src/ssdMobilenetv1/boxPredictionLayer.ts", "../src/ssdMobilenetv1/SsdMobilenetv1Options.ts", "../src/ssdMobilenetv1/index.ts", "../src/tinyYolov2/const.ts", "../src/tinyYolov2/TinyYolov2Base.ts", "../src/tinyYolov2/config.ts", "../src/tinyYolov2/convWithBatchNorm.ts", "../src/tinyYolov2/leaky.ts", "../src/tinyYolov2/depthwiseSeparableConv.ts", "../src/tinyYolov2/extractParams.ts", "../src/tinyYolov2/extractParamsFromWeightMap.ts", "../src/tinyYolov2/TinyYolov2Options.ts", "../src/tinyYolov2/TinyYolov2.ts", "../src/tinyYolov2/index.ts", "../src/tinyFaceDetector/TinyFaceDetectorOptions.ts", "../src/globalApi/ComposableTask.ts", "../src/globalApi/DetectFaceLandmarksTasks.ts", "../src/globalApi/extractFacesAndComputeResults.ts", "../src/tinyFaceDetector/const.ts", "../src/tinyFaceDetector/TinyFaceDetector.ts", "../src/globalApi/nets.ts", "../src/globalApi/PredictFaceExpressionsTask.ts", "../src/globalApi/PredictAgeAndGenderTask.ts", "../src/globalApi/ComputeFaceDescriptorsTasks.ts", "../src/globalApi/DetectFacesTasks.ts", "../src/globalApi/detectFaces.ts", "../src/globalApi/allFaces.ts", "../src/euclideanDistance.ts", "../src/globalApi/FaceMatcher.ts", "../src/tinyFaceDetector/index.ts", "../src/resizeResults.ts"],
- "sourcesContent": ["/* eslint-disable import/no-extraneous-dependencies */\n/* eslint-disable node/no-unpublished-import */\n\n// wrapper to load tfjs in a single place so version can be changed quickly\n\nexport * from '@tensorflow/tfjs/dist/index.js';\nexport * from '@tensorflow/tfjs-backend-wasm';\n", "export function isNodejs(): boolean {\n return typeof global === 'object'\n && typeof require === 'function'\n && typeof module !== 'undefined'\n // issues with gatsby.js: module.exports is undefined\n // && !!module.exports\n && typeof process !== 'undefined' && !!process.version;\n}\n", "import * as tf from '../dist/tfjs.esm';\nimport * as draw from './draw/index';\nimport * as utils from './utils/index';\nimport * as pkg from '../package.json';\n\nexport { tf, draw, utils };\n\nexport * from './ageGenderNet/index';\nexport * from './classes/index';\nexport * from './dom/index';\nexport * from './env/index';\nexport * from './faceExpressionNet/index';\nexport * from './faceLandmarkNet/index';\nexport * from './faceRecognitionNet/index';\nexport * from './factories/index';\nexport * from './globalApi/index';\nexport * from './ops/index';\nexport * from './ssdMobilenetv1/index';\nexport * from './tinyFaceDetector/index';\nexport * from './tinyYolov2/index';\nexport * from './euclideanDistance';\nexport * from './NeuralNetwork';\nexport * from './resizeResults';\n\nconst node = (typeof process !== 'undefined');\nconst browser = (typeof navigator !== 'undefined') && (typeof navigator.userAgent !== 'undefined');\nexport const version = { faceapi: pkg.version as string, node, browser };\n", "export * from './drawContour';\nexport * from './drawDetections';\nexport * from './drawFaceExpressions';\nexport * from './DrawBox';\nexport * from './DrawFaceLandmarks';\nexport * from './DrawTextField';\n", "import { Point } from '../classes/index';\n\nexport function drawContour(\n ctx: CanvasRenderingContext2D,\n points: Point[],\n isClosed: boolean = false,\n) {\n ctx.beginPath();\n\n points.slice(1).forEach(({ x, y }, prevIdx) => {\n const from = points[prevIdx];\n ctx.moveTo(from.x, from.y);\n ctx.lineTo(x, y);\n });\n\n if (isClosed) {\n const from = points[points.length - 1];\n const to = points[0];\n if (!from || !to) {\n return;\n }\n\n ctx.moveTo(from.x, from.y);\n ctx.lineTo(to.x, to.y);\n }\n\n ctx.stroke();\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { Point } from '../classes/index';\nimport { Dimensions, IDimensions } from '../classes/Dimensions';\n\nexport function isTensor(tensor: any, dim: number) {\n return tensor instanceof tf.Tensor && tensor.shape.length === dim;\n}\n\nexport function isTensor1D(tensor: any): tensor is tf.Tensor1D {\n return isTensor(tensor, 1);\n}\n\nexport function isTensor2D(tensor: any): tensor is tf.Tensor2D {\n return isTensor(tensor, 2);\n}\n\nexport function isTensor3D(tensor: any): tensor is tf.Tensor3D {\n return isTensor(tensor, 3);\n}\n\nexport function isTensor4D(tensor: any): tensor is tf.Tensor4D {\n return isTensor(tensor, 4);\n}\n\nexport function isFloat(num: number) {\n return num % 1 !== 0;\n}\n\nexport function isEven(num: number) {\n return num % 2 === 0;\n}\n\nexport function round(num: number, prec: number = 2) {\n const f = 10 ** prec;\n return Math.floor(num * f) / f;\n}\n\nexport function isDimensions(obj: any): boolean {\n return obj && obj.width && obj.height;\n}\n\nexport function computeReshapedDimensions({ width, height }: IDimensions, inputSize: number) {\n const scale = inputSize / Math.max(height, width);\n return new Dimensions(Math.round(width * scale), Math.round(height * scale));\n}\n\nexport function getCenterPoint(pts: Point[]): Point {\n return pts.reduce((sum, pt) => sum.add(pt), new Point(0, 0))\n .div(new Point(pts.length, pts.length));\n}\n\nexport function range(num: number, start: number, step: number): number[] {\n return Array(num).fill(0).map((_, i) => start + (i * step));\n}\n\nexport function isValidNumber(num: any) {\n return !!num && (num !== Infinity) && (num !== -Infinity) && !Number.isNaN(num) || num === 0;\n}\n\nexport function isValidProbablitiy(num: any) {\n return isValidNumber(num) && num >= 0 && num <= 1.0;\n}\n", "import { isValidNumber } from '../utils/index';\n\nexport interface IDimensions {\n width: number\n height: number\n}\n\nexport class Dimensions implements IDimensions {\n private _width: number\n\n private _height: number\n\n constructor(width: number, height: number) {\n if (!isValidNumber(width) || !isValidNumber(height)) {\n throw new Error(`Dimensions.constructor - expected width and height to be valid numbers, instead have ${JSON.stringify({ width, height })}`);\n }\n\n this._width = width;\n this._height = height;\n }\n\n public get width(): number { return this._width; }\n\n public get height(): number { return this._height; }\n\n public reverse(): Dimensions {\n return new Dimensions(1 / this.width, 1 / this.height);\n }\n}\n", "export interface IPoint {\n x: number\n y: number\n}\n\nexport class Point implements IPoint {\n private _x: number\n\n private _y: number\n\n constructor(x: number, y: number) {\n this._x = x;\n this._y = y;\n }\n\n get x(): number { return this._x; }\n\n get y(): number { return this._y; }\n\n public add(pt: IPoint): Point {\n return new Point(this.x + pt.x, this.y + pt.y);\n }\n\n public sub(pt: IPoint): Point {\n return new Point(this.x - pt.x, this.y - pt.y);\n }\n\n public mul(pt: IPoint): Point {\n return new Point(this.x * pt.x, this.y * pt.y);\n }\n\n public div(pt: IPoint): Point {\n return new Point(this.x / pt.x, this.y / pt.y);\n }\n\n public abs(): Point {\n return new Point(Math.abs(this.x), Math.abs(this.y));\n }\n\n public magnitude(): number {\n return Math.sqrt((this.x ** 2) + (this.y ** 2));\n }\n\n public floor(): Point {\n return new Point(Math.floor(this.x), Math.floor(this.y));\n }\n}\n", "import { isDimensions, isValidNumber } from '../utils/index';\nimport { IBoundingBox } from './BoundingBox';\nimport { IDimensions } from './Dimensions';\nimport { Point } from './Point';\nimport { IRect } from './Rect';\n\nexport class Box implements IBoundingBox, IRect {\n public static isRect(rect: any): boolean {\n return !!rect && [rect.x, rect.y, rect.width, rect.height].every(isValidNumber);\n }\n\n public static assertIsValidBox(box: any, callee: string, allowNegativeDimensions: boolean = false) {\n if (!Box.isRect(box)) {\n throw new Error(`${callee} - invalid box: ${JSON.stringify(box)}, expected object with properties x, y, width, height`);\n }\n\n if (!allowNegativeDimensions && (box.width < 0 || box.height < 0)) {\n throw new Error(`${callee} - width (${box.width}) and height (${box.height}) must be positive numbers`);\n }\n }\n\n private _x: number\n\n private _y: number\n\n private _width: number\n\n private _height: number\n\n constructor(_box: IBoundingBox | IRect, allowNegativeDimensions: boolean = true) {\n const box = (_box || {}) as any;\n\n const isBbox = [box.left, box.top, box.right, box.bottom].every(isValidNumber);\n const isRect = [box.x, box.y, box.width, box.height].every(isValidNumber);\n\n if (!isRect && !isBbox) {\n throw new Error(`Box.constructor - expected box to be IBoundingBox | IRect, instead have ${JSON.stringify(box)}`);\n }\n\n const [x, y, width, height] = isRect\n ? [box.x, box.y, box.width, box.height]\n : [box.left, box.top, box.right - box.left, box.bottom - box.top];\n\n Box.assertIsValidBox({\n x, y, width, height,\n }, 'Box.constructor', allowNegativeDimensions);\n\n this._x = x;\n this._y = y;\n this._width = width;\n this._height = height;\n }\n\n public get x(): number { return this._x; }\n\n public get y(): number { return this._y; }\n\n public get width(): number { return this._width; }\n\n public get height(): number { return this._height; }\n\n public get left(): number { return this.x; }\n\n public get top(): number { return this.y; }\n\n public get right(): number { return this.x + this.width; }\n\n public get bottom(): number { return this.y + this.height; }\n\n public get area(): number { return this.width * this.height; }\n\n public get topLeft(): Point { return new Point(this.left, this.top); }\n\n public get topRight(): Point { return new Point(this.right, this.top); }\n\n public get bottomLeft(): Point { return new Point(this.left, this.bottom); }\n\n public get bottomRight(): Point { return new Point(this.right, this.bottom); }\n\n public round(): Box {\n const [x, y, width, height] = [this.x, this.y, this.width, this.height]\n .map((val) => Math.round(val));\n return new Box({\n x, y, width, height,\n });\n }\n\n public floor(): Box {\n const [x, y, width, height] = [this.x, this.y, this.width, this.height]\n .map((val) => Math.floor(val));\n return new Box({\n x, y, width, height,\n });\n }\n\n public toSquare(): Box {\n let {\n x, y, width, height,\n } = this;\n const diff = Math.abs(width - height);\n if (width < height) {\n x -= (diff / 2);\n width += diff;\n }\n if (height < width) {\n y -= (diff / 2);\n height += diff;\n }\n\n return new Box({\n x, y, width, height,\n });\n }\n\n public rescale(s: IDimensions | number): Box {\n const scaleX = isDimensions(s) ? (s as IDimensions).width : s as number;\n const scaleY = isDimensions(s) ? (s as IDimensions).height : s as number;\n return new Box({\n x: this.x * scaleX,\n y: this.y * scaleY,\n width: this.width * scaleX,\n height: this.height * scaleY,\n });\n }\n\n public pad(padX: number, padY: number): Box {\n const [x, y, width, height] = [\n this.x - (padX / 2),\n this.y - (padY / 2),\n this.width + padX,\n this.height + padY,\n ];\n return new Box({\n x, y, width, height,\n });\n }\n\n public clipAtImageBorders(imgWidth: number, imgHeight: number): Box {\n const {\n x, y, right, bottom,\n } = this;\n const clippedX = Math.max(x, 0);\n const clippedY = Math.max(y, 0);\n\n const newWidth = right - clippedX;\n const newHeight = bottom - clippedY;\n const clippedWidth = Math.min(newWidth, imgWidth - clippedX);\n const clippedHeight = Math.min(newHeight, imgHeight - clippedY);\n\n return (new Box({\n x: clippedX, y: clippedY, width: clippedWidth, height: clippedHeight,\n })).floor();\n }\n\n public shift(sx: number, sy: number): Box {\n const { width, height } = this;\n const x = this.x + sx;\n const y = this.y + sy;\n\n return new Box({\n x, y, width, height,\n });\n }\n\n public padAtBorders(imageHeight: number, imageWidth: number) {\n const w = this.width + 1;\n const h = this.height + 1;\n\n const dx = 1;\n const dy = 1;\n let edx = w;\n let edy = h;\n\n let x = this.left;\n let y = this.top;\n let ex = this.right;\n let ey = this.bottom;\n\n if (ex > imageWidth) {\n edx = -ex + imageWidth + w;\n ex = imageWidth;\n }\n if (ey > imageHeight) {\n edy = -ey + imageHeight + h;\n ey = imageHeight;\n }\n if (x < 1) {\n edy = 2 - x;\n x = 1;\n }\n if (y < 1) {\n edy = 2 - y;\n y = 1;\n }\n\n return {\n dy, edy, dx, edx, y, ey, x, ex, w, h,\n };\n }\n\n public calibrate(region: Box) {\n return new Box({\n left: this.left + (region.left * this.width),\n top: this.top + (region.top * this.height),\n right: this.right + (region.right * this.width),\n bottom: this.bottom + (region.bottom * this.height),\n }).toSquare().round();\n }\n}\n", "import { Box } from './Box';\n\nexport interface IBoundingBox {\n left: number\n top: number\n right: number\n bottom: number\n}\n\nexport class BoundingBox extends Box implements IBoundingBox {\n constructor(left: number, top: number, right: number, bottom: number, allowNegativeDimensions: boolean = false) {\n super({\n left, top, right, bottom,\n }, allowNegativeDimensions);\n }\n}\n", "import { Box } from './Box';\nimport { Dimensions, IDimensions } from './Dimensions';\nimport { IRect, Rect } from './Rect';\n\nexport class ObjectDetection {\n private _score: number\n\n private _classScore: number\n\n private _className: string\n\n private _box: Rect\n\n private _imageDims: Dimensions\n\n constructor(\n score: number,\n classScore: number,\n className: string,\n relativeBox: IRect,\n imageDims: IDimensions,\n ) {\n this._imageDims = new Dimensions(imageDims.width, imageDims.height);\n this._score = score;\n this._classScore = classScore;\n this._className = className;\n this._box = new Box(relativeBox).rescale(this._imageDims);\n }\n\n public get score(): number { return this._score; }\n\n public get classScore(): number { return this._classScore; }\n\n public get className(): string { return this._className; }\n\n public get box(): Box { return this._box; }\n\n public get imageDims(): Dimensions { return this._imageDims; }\n\n public get imageWidth(): number { return this.imageDims.width; }\n\n public get imageHeight(): number { return this.imageDims.height; }\n\n public get relativeBox(): Box { return new Box(this._box).rescale(this.imageDims.reverse()); }\n\n public forSize(width: number, height: number): ObjectDetection {\n return new ObjectDetection(\n this.score,\n this.classScore,\n this.className,\n this.relativeBox,\n { width, height },\n );\n }\n}\n", "import { Box } from './Box';\nimport { IDimensions } from './Dimensions';\nimport { ObjectDetection } from './ObjectDetection';\nimport { Rect } from './Rect';\n\nexport interface IFaceDetecion {\n score: number\n box: Box\n}\n\nexport class FaceDetection extends ObjectDetection implements IFaceDetecion {\n constructor(\n score: number,\n relativeBox: Rect,\n imageDims: IDimensions,\n ) {\n super(score, score, '', relativeBox, imageDims);\n }\n\n public forSize(width: number, height: number): FaceDetection {\n const { score, relativeBox, imageDims } = super.forSize(width, height);\n return new FaceDetection(score, relativeBox, imageDims);\n }\n}\n", "import { Box } from '../classes/Box';\n\nexport function iou(box1: Box, box2: Box, isIOU: boolean = true) {\n const width = Math.max(0.0, Math.min(box1.right, box2.right) - Math.max(box1.left, box2.left));\n const height = Math.max(0.0, Math.min(box1.bottom, box2.bottom) - Math.max(box1.top, box2.top));\n const interSection = width * height;\n\n return isIOU\n ? interSection / (box1.area + box2.area - interSection)\n : interSection / Math.min(box1.area, box2.area);\n}\n", "import { BoundingBox, IPoint } from '../classes/index';\n\nexport function minBbox(pts: IPoint[]): BoundingBox {\n const xs = pts.map((pt) => pt.x);\n const ys = pts.map((pt) => pt.y);\n const minX = xs.reduce((min, x) => (x < min ? x : min), Infinity);\n const minY = ys.reduce((min, y) => (y < min ? y : min), Infinity);\n const maxX = xs.reduce((max, x) => (max < x ? x : max), 0);\n const maxY = ys.reduce((max, y) => (max < y ? y : max), 0);\n\n return new BoundingBox(minX, minY, maxX, maxY);\n}\n", "import { Box } from '../classes/Box';\nimport { iou } from './iou';\n\nexport function nonMaxSuppression(\n boxes: Box[],\n scores: number[],\n iouThreshold: number,\n isIOU: boolean = true,\n): number[] {\n let indicesSortedByScore = scores\n .map((score, boxIndex) => ({ score, boxIndex }))\n .sort((c1, c2) => c1.score - c2.score)\n .map((c) => c.boxIndex);\n\n const pick: number[] = [];\n\n while (indicesSortedByScore.length > 0) {\n const curr = indicesSortedByScore.pop() as number;\n pick.push(curr);\n\n const indices = indicesSortedByScore;\n\n const outputs: number[] = [];\n for (let i = 0; i < indices.length; i++) {\n const idx = indices[i];\n\n const currBox = boxes[curr];\n const idxBox = boxes[idx];\n\n outputs.push(iou(currBox, idxBox, isIOU));\n }\n\n indicesSortedByScore = indicesSortedByScore.filter(\n (_, j) => outputs[j] <= iouThreshold,\n );\n }\n\n return pick;\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nexport function normalize(x: tf.Tensor4D, meanRgb: number[]): tf.Tensor4D {\n return tf.tidy(() => {\n const [r, g, b] = meanRgb;\n const avg_r = tf.fill([...x.shape.slice(0, 3), 1], r, 'float32');\n const avg_g = tf.fill([...x.shape.slice(0, 3), 1], g, 'float32');\n const avg_b = tf.fill([...x.shape.slice(0, 3), 1], b, 'float32');\n const avg_rgb = tf.concat([avg_r, avg_g, avg_b], 3);\n\n return tf.sub(x, avg_rgb);\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\n/**\n * Pads the smaller dimension of an image tensor with zeros, such that width === height.\n *\n * @param imgTensor The image tensor.\n * @param isCenterImage (optional, default: false) If true, add an equal amount of padding on\n * both sides of the minor dimension oof the image.\n * @returns The padded tensor with width === height.\n */\nexport function padToSquare(\n imgTensor: tf.Tensor4D,\n isCenterImage: boolean = false,\n): tf.Tensor4D {\n return tf.tidy(() => {\n const [height, width] = imgTensor.shape.slice(1);\n if (height === width) {\n return imgTensor;\n }\n\n const dimDiff = Math.abs(height - width);\n const paddingAmount = Math.round(dimDiff * (isCenterImage ? 0.5 : 1));\n const paddingAxis = height > width ? 2 : 1;\n\n const createPaddingTensor = (paddingAmountLocal: number): tf.Tensor => {\n const paddingTensorShape = imgTensor.shape.slice();\n paddingTensorShape[paddingAxis] = paddingAmountLocal;\n return tf.fill(paddingTensorShape, 0, 'float32');\n };\n\n const paddingTensorAppend = createPaddingTensor(paddingAmount);\n const remainingPaddingAmount = dimDiff - (paddingTensorAppend.shape[paddingAxis] as number);\n\n const paddingTensorPrepend = isCenterImage && remainingPaddingAmount\n ? createPaddingTensor(remainingPaddingAmount)\n : null;\n\n const tensorsToStack = [\n paddingTensorPrepend,\n imgTensor,\n paddingTensorAppend,\n ]\n .filter((t) => !!t)\n // .map((t: tf.Tensor) => t.toFloat()) as tf.Tensor4D[]\n .map((t: tf.Tensor) => tf.cast(t, 'float32')) as tf.Tensor4D[];\n return tf.concat(tensorsToStack, paddingAxis);\n });\n}\n", "export function shuffleArray(inputArray: any[]) {\n const array = inputArray.slice();\n for (let i = array.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n const x = array[i];\n array[i] = array[j];\n array[j] = x;\n }\n return array;\n}\n", "export * from './iou';\nexport * from './minBbox';\nexport * from './nonMaxSuppression';\nexport * from './normalize';\nexport * from './padToSquare';\nexport * from './shuffleArray';\n\nexport function sigmoid(x: number) {\n return 1 / (1 + Math.exp(-x));\n}\n\nexport function inverseSigmoid(x: number) {\n return Math.log(x / (1 - x));\n}\n", "import { Box } from './Box';\n\nexport interface IRect {\n x: number\n y: number\n width: number\n height: number\n}\n\nexport class Rect extends Box implements IRect {\n constructor(x: number, y: number, width: number, height: number, allowNegativeDimensions: boolean = false) {\n super({\n x, y, width, height,\n }, allowNegativeDimensions);\n }\n}\n", "import { minBbox } from '../ops/index';\nimport { getCenterPoint } from '../utils/index';\nimport { IBoundingBox } from './BoundingBox';\nimport { Box } from './Box';\nimport { Dimensions, IDimensions } from './Dimensions';\nimport { FaceDetection } from './FaceDetection';\nimport { Point } from './Point';\nimport { IRect, Rect } from './Rect';\n\n// face alignment constants\nconst relX = 0.5;\nconst relY = 0.43;\nconst relScale = 0.45;\n\nexport interface IFaceLandmarks {\n positions: Point[]\n shift: Point\n}\n\nexport class FaceLandmarks implements IFaceLandmarks {\n protected _shift: Point\n\n protected _positions: Point[]\n\n protected _imgDims: Dimensions\n\n constructor(\n relativeFaceLandmarkPositions: Point[],\n imgDims: IDimensions,\n shift: Point = new Point(0, 0),\n ) {\n const { width, height } = imgDims;\n this._imgDims = new Dimensions(width, height);\n this._shift = shift;\n this._positions = relativeFaceLandmarkPositions.map(\n (pt) => pt.mul(new Point(width, height)).add(shift),\n );\n }\n\n public get shift(): Point { return new Point(this._shift.x, this._shift.y); }\n\n public get imageWidth(): number { return this._imgDims.width; }\n\n public get imageHeight(): number { return this._imgDims.height; }\n\n public get positions(): Point[] { return this._positions; }\n\n public get relativePositions(): Point[] {\n return this._positions.map(\n (pt) => pt.sub(this._shift).div(new Point(this.imageWidth, this.imageHeight)),\n );\n }\n\n public forSize(width: number, height: number): T {\n return new (this.constructor as any)(\n this.relativePositions,\n { width, height },\n );\n }\n\n public shiftBy(x: number, y: number): T {\n return new (this.constructor as any)(\n this.relativePositions,\n this._imgDims,\n new Point(x, y),\n );\n }\n\n public shiftByPoint(pt: Point): T {\n return this.shiftBy(pt.x, pt.y);\n }\n\n /**\n * Aligns the face landmarks after face detection from the relative positions of the faces\n * bounding box, or it's current shift. This function should be used to align the face images\n * after face detection has been performed, before they are passed to the face recognition net.\n * This will make the computed face descriptor more accurate.\n *\n * @param detection (optional) The bounding box of the face or the face detection result. If\n * no argument was passed the position of the face landmarks are assumed to be relative to\n * it's current shift.\n * @returns The bounding box of the aligned face.\n */\n public align(\n detection?: FaceDetection | IRect | IBoundingBox | null,\n options: { useDlibAlignment?: boolean, minBoxPadding?: number } = { },\n ): Box {\n if (detection) {\n const box = detection instanceof FaceDetection\n ? detection.box.floor()\n : new Box(detection);\n\n return this.shiftBy(box.x, box.y).align(null, options);\n }\n\n const { useDlibAlignment, minBoxPadding } = { useDlibAlignment: false, minBoxPadding: 0.2, ...options };\n\n if (useDlibAlignment) {\n return this.alignDlib();\n }\n\n return this.alignMinBbox(minBoxPadding);\n }\n\n private alignDlib(): Box {\n const centers = this.getRefPointsForAlignment();\n\n const [leftEyeCenter, rightEyeCenter, mouthCenter] = centers;\n const distToMouth = (pt: Point) => mouthCenter.sub(pt).magnitude();\n const eyeToMouthDist = (distToMouth(leftEyeCenter) + distToMouth(rightEyeCenter)) / 2;\n\n const size = Math.floor(eyeToMouthDist / relScale);\n\n const refPoint = getCenterPoint(centers);\n // TODO: pad in case rectangle is out of image bounds\n const x = Math.floor(Math.max(0, refPoint.x - (relX * size)));\n const y = Math.floor(Math.max(0, refPoint.y - (relY * size)));\n\n return new Rect(x, y, Math.min(size, this.imageWidth + x), Math.min(size, this.imageHeight + y));\n }\n\n private alignMinBbox(padding: number): Box {\n const box = minBbox(this.positions);\n return box.pad(box.width * padding, box.height * padding);\n }\n\n protected getRefPointsForAlignment(): Point[] {\n throw new Error('getRefPointsForAlignment not implemented by base class');\n }\n}\n", "import { getCenterPoint } from '../utils/index';\nimport { FaceLandmarks } from './FaceLandmarks';\nimport { Point } from './Point';\n\nexport class FaceLandmarks5 extends FaceLandmarks {\n protected getRefPointsForAlignment(): Point[] {\n const pts = this.positions;\n return [\n pts[0],\n pts[1],\n getCenterPoint([pts[3], pts[4]]),\n ];\n }\n}\n", "import { getCenterPoint } from '../utils/index';\nimport { FaceLandmarks } from './FaceLandmarks';\nimport { Point } from './Point';\n\nexport class FaceLandmarks68 extends FaceLandmarks {\n public getJawOutline(): Point[] {\n return this.positions.slice(0, 17);\n }\n\n public getLeftEyeBrow(): Point[] {\n return this.positions.slice(17, 22);\n }\n\n public getRightEyeBrow(): Point[] {\n return this.positions.slice(22, 27);\n }\n\n public getNose(): Point[] {\n return this.positions.slice(27, 36);\n }\n\n public getLeftEye(): Point[] {\n return this.positions.slice(36, 42);\n }\n\n public getRightEye(): Point[] {\n return this.positions.slice(42, 48);\n }\n\n public getMouth(): Point[] {\n return this.positions.slice(48, 68);\n }\n\n protected getRefPointsForAlignment(): Point[] {\n return [\n this.getLeftEye(),\n this.getRightEye(),\n this.getMouth(),\n ].map(getCenterPoint);\n }\n}\n", "import { round } from '../utils/index';\n\nexport interface IFaceMatch {\n label: string\n distance: number\n}\n\nexport class FaceMatch implements IFaceMatch {\n private _label: string\n\n private _distance: number\n\n constructor(label: string, distance: number) {\n this._label = label;\n this._distance = distance;\n }\n\n public get label(): string { return this._label; }\n\n public get distance(): number { return this._distance; }\n\n public toString(withDistance: boolean = true): string {\n return `${this.label}${withDistance ? ` (${round(this.distance)})` : ''}`;\n }\n}\n", "import { isValidNumber } from '../utils/index';\nimport { IBoundingBox } from './BoundingBox';\nimport { Box } from './Box';\nimport { IRect } from './Rect';\n\nexport class LabeledBox extends Box {\n public static assertIsValidLabeledBox(box: any, callee: string) {\n Box.assertIsValidBox(box, callee);\n\n if (!isValidNumber(box.label)) {\n throw new Error(`${callee} - expected property label (${box.label}) to be a number`);\n }\n }\n\n private _label: number\n\n constructor(box: IBoundingBox | IRect | any, label: number) {\n super(box);\n this._label = label;\n }\n\n public get label(): number { return this._label; }\n}\n", "export class LabeledFaceDescriptors {\n private _label: string\n\n private _descriptors: Float32Array[]\n\n constructor(label: string, descriptors: Float32Array[]) {\n if (!(typeof label === 'string')) {\n throw new Error('LabeledFaceDescriptors - constructor expected label to be a string');\n }\n\n if (!Array.isArray(descriptors) || descriptors.some((desc) => !(desc instanceof Float32Array))) {\n throw new Error('LabeledFaceDescriptors - constructor expected descriptors to be an array of Float32Array');\n }\n\n this._label = label;\n this._descriptors = descriptors;\n }\n\n public get label(): string { return this._label; }\n\n public get descriptors(): Float32Array[] { return this._descriptors; }\n\n public toJSON(): any {\n return {\n label: this.label,\n descriptors: this.descriptors.map((d) => Array.from(d)),\n };\n }\n\n public static fromJSON(json: any): LabeledFaceDescriptors {\n const descriptors = json.descriptors.map((d: any) => new Float32Array(d));\n return new LabeledFaceDescriptors(json.label, descriptors);\n }\n}\n", "import { isValidProbablitiy } from '../utils/index';\nimport { IBoundingBox } from './BoundingBox';\nimport { LabeledBox } from './LabeledBox';\nimport { IRect } from './Rect';\n\nexport class PredictedBox extends LabeledBox {\n public static assertIsValidPredictedBox(box: any, callee: string) {\n LabeledBox.assertIsValidLabeledBox(box, callee);\n\n if (\n !isValidProbablitiy(box.score)\n || !isValidProbablitiy(box.classScore)\n ) {\n throw new Error(`${callee} - expected properties score (${box.score}) and (${box.classScore}) to be a number between [0, 1]`);\n }\n }\n\n private _score: number\n\n private _classScore: number\n\n constructor(box: IBoundingBox | IRect | any, label: number, score: number, classScore: number) {\n super(box, label);\n this._score = score;\n this._classScore = classScore;\n }\n\n public get score(): number { return this._score; }\n\n public get classScore(): number { return this._classScore; }\n}\n", "import { FaceDetection } from '../classes/FaceDetection';\n\nexport type WithFaceDetection = TSource & {\n detection: FaceDetection\n}\n\nexport function isWithFaceDetection(obj: any): obj is WithFaceDetection<{}> {\n return obj.detection instanceof FaceDetection;\n}\n\nexport function extendWithFaceDetection<\n TSource\n>(\n sourceObj: TSource,\n detection: FaceDetection,\n): WithFaceDetection {\n const extension = { detection };\n return { ...sourceObj, ...extension };\n}\n", "import { Environment } from './types';\n\nexport function createBrowserEnv(): Environment {\n const fetch = window.fetch;\n if (!fetch) throw new Error('fetch - missing fetch implementation for browser environment');\n\n const readFile = () => {\n throw new Error('readFile - filesystem not available for browser environment');\n };\n\n return {\n Canvas: HTMLCanvasElement,\n CanvasRenderingContext2D,\n Image: HTMLImageElement,\n ImageData,\n Video: HTMLVideoElement,\n createCanvasElement: () => document.createElement('canvas'),\n createImageElement: () => document.createElement('img'),\n fetch,\n readFile,\n };\n}\n", "import { FileSystem } from './types';\n\nexport function createFileSystem(fs?: any): FileSystem {\n let requireFsError = '';\n\n if (!fs) {\n try {\n // eslint-disable-next-line global-require\n fs = require('fs');\n } catch (err) {\n requireFsError = err.toString();\n }\n }\n\n const readFile = fs\n ? (filePath: string) => new Promise((resolve, reject) => {\n fs.readFile(filePath, (err: any, buffer: Buffer) => (err ? reject(err) : resolve(buffer)));\n })\n : () => {\n throw new Error(`readFile - failed to require fs in nodejs environment with error: ${requireFsError}`);\n };\n\n return {\n readFile,\n };\n}\n", "/* eslint-disable max-classes-per-file */\nimport { createFileSystem } from './createFileSystem';\nimport { Environment } from './types';\n\nexport function createNodejsEnv(): Environment {\n // eslint-disable-next-line dot-notation\n const Canvas = global['Canvas'] || global.HTMLCanvasElement;\n const Image = global.Image || global.HTMLImageElement;\n\n const createCanvasElement = () => {\n if (Canvas) return new Canvas();\n throw new Error('createCanvasElement - missing Canvas implementation for nodejs environment');\n };\n\n const createImageElement = () => {\n if (Image) return new Image();\n throw new Error('createImageElement - missing Image implementation for nodejs environment');\n };\n\n const fetch = global.fetch;\n // if (!fetch) throw new Error('fetch - missing fetch implementation for nodejs environment');\n\n const fileSystem = createFileSystem();\n\n return {\n Canvas: Canvas || class {},\n CanvasRenderingContext2D: global.CanvasRenderingContext2D || class {},\n Image: Image || class {},\n ImageData: global.ImageData || class {},\n Video: global.HTMLVideoElement || class {},\n createCanvasElement,\n createImageElement,\n fetch,\n ...fileSystem,\n };\n}\n", "export function isBrowser(): boolean {\n return typeof window === 'object'\n && typeof document !== 'undefined'\n && typeof HTMLImageElement !== 'undefined'\n && typeof HTMLCanvasElement !== 'undefined'\n && typeof HTMLVideoElement !== 'undefined'\n && typeof ImageData !== 'undefined'\n && typeof CanvasRenderingContext2D !== 'undefined';\n}\n", "import { createBrowserEnv } from './createBrowserEnv';\nimport { createFileSystem } from './createFileSystem';\nimport { createNodejsEnv } from './createNodejsEnv';\nimport { isBrowser } from './isBrowser';\nimport { isNodejs } from './isNodejs';\nimport { Environment } from './types';\n\nlet environment: Environment | null;\n\nfunction getEnv(): Environment {\n if (!environment) {\n throw new Error('getEnv - environment is not defined, check isNodejs() and isBrowser()');\n }\n return environment;\n}\n\nfunction setEnv(env: Environment) {\n environment = env;\n}\n\nfunction initialize() {\n // check for isBrowser() first to prevent electron renderer process\n // to be initialized with wrong environment due to isNodejs() returning true\n if (isBrowser()) return setEnv(createBrowserEnv());\n if (isNodejs()) return setEnv(createNodejsEnv());\n return null;\n}\n\nfunction monkeyPatch(env: Partial) {\n if (!environment) {\n initialize();\n }\n\n if (!environment) {\n throw new Error('monkeyPatch - environment is not defined, check isNodejs() and isBrowser()');\n }\n\n const { Canvas = environment.Canvas, Image = environment.Image } = env;\n environment.Canvas = Canvas;\n environment.Image = Image;\n environment.createCanvasElement = env.createCanvasElement || (() => new Canvas());\n environment.createImageElement = env.createImageElement || (() => new Image());\n\n environment.ImageData = env.ImageData || environment.ImageData;\n environment.Video = env.Video || environment.Video;\n environment.fetch = env.fetch || environment.fetch;\n environment.readFile = env.readFile || environment.readFile;\n}\n\nexport const env = {\n getEnv,\n setEnv,\n initialize,\n createBrowserEnv,\n createFileSystem,\n createNodejsEnv,\n monkeyPatch,\n isBrowser,\n isNodejs,\n};\n\ninitialize();\n\nexport * from './types';\n", "import { env } from '../env/index';\n\nexport function resolveInput(arg: string | any) {\n if (!env.isNodejs() && typeof arg === 'string') {\n return document.getElementById(arg);\n }\n return arg;\n}\n", "import { env } from '../env/index';\nimport { resolveInput } from './resolveInput';\n\nexport function getContext2dOrThrow(canvasArg: string | HTMLCanvasElement | CanvasRenderingContext2D): CanvasRenderingContext2D {\n const { Canvas, CanvasRenderingContext2D } = env.getEnv();\n\n if (canvasArg instanceof CanvasRenderingContext2D) {\n return canvasArg;\n }\n\n const canvas = resolveInput(canvasArg);\n\n if (!(canvas instanceof Canvas)) {\n throw new Error('resolveContext2d - expected canvas to be of instance of Canvas');\n }\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('resolveContext2d - canvas 2d context is null');\n }\n\n return ctx;\n}\n", "/* eslint-disable max-classes-per-file */\nimport { IDimensions, IPoint } from '../classes/index';\nimport { getContext2dOrThrow } from '../dom/getContext2dOrThrow';\nimport { resolveInput } from '../dom/resolveInput';\n\n// eslint-disable-next-line no-shadow\nexport enum AnchorPosition {\n // eslint-disable-next-line no-unused-vars\n TOP_LEFT = 'TOP_LEFT',\n // eslint-disable-next-line no-unused-vars\n TOP_RIGHT = 'TOP_RIGHT',\n // eslint-disable-next-line no-unused-vars\n BOTTOM_LEFT = 'BOTTOM_LEFT',\n // eslint-disable-next-line no-unused-vars\n BOTTOM_RIGHT = 'BOTTOM_RIGHT'\n}\n\nexport interface IDrawTextFieldOptions {\n anchorPosition?: AnchorPosition\n backgroundColor?: string\n fontColor?: string\n fontSize?: number\n fontStyle?: string\n padding?: number\n}\n\nexport class DrawTextFieldOptions implements IDrawTextFieldOptions {\n public anchorPosition: AnchorPosition\n\n public backgroundColor: string\n\n public fontColor: string\n\n public fontSize: number\n\n public fontStyle: string\n\n public padding: number\n\n constructor(options: IDrawTextFieldOptions = {}) {\n const {\n anchorPosition, backgroundColor, fontColor, fontSize, fontStyle, padding,\n } = options;\n this.anchorPosition = anchorPosition || AnchorPosition.TOP_LEFT;\n this.backgroundColor = backgroundColor || 'rgba(0, 0, 0, 0.5)';\n this.fontColor = fontColor || 'rgba(255, 255, 255, 1)';\n this.fontSize = fontSize || 14;\n this.fontStyle = fontStyle || 'Georgia';\n this.padding = padding || 4;\n }\n}\n\nexport class DrawTextField {\n public text: string[]\n\n public anchor : IPoint\n\n public options: DrawTextFieldOptions\n\n constructor(\n text: string | string[] | DrawTextField,\n anchor: IPoint,\n options: IDrawTextFieldOptions = {},\n ) {\n // eslint-disable-next-line no-nested-ternary\n this.text = typeof text === 'string'\n ? [text]\n : (text instanceof DrawTextField ? text.text : text);\n this.anchor = anchor;\n this.options = new DrawTextFieldOptions(options);\n }\n\n measureWidth(ctx: CanvasRenderingContext2D): number {\n const { padding } = this.options;\n return this.text.map((l) => ctx.measureText(l).width).reduce((w0, w1) => (w0 < w1 ? w1 : w0), 0) + (2 * padding);\n }\n\n measureHeight(): number {\n const { fontSize, padding } = this.options;\n return this.text.length * fontSize + (2 * padding);\n }\n\n getUpperLeft(ctx: CanvasRenderingContext2D, canvasDims?: IDimensions): IPoint {\n const { anchorPosition } = this.options;\n const isShiftLeft = anchorPosition === AnchorPosition.BOTTOM_RIGHT || anchorPosition === AnchorPosition.TOP_RIGHT;\n const isShiftTop = anchorPosition === AnchorPosition.BOTTOM_LEFT || anchorPosition === AnchorPosition.BOTTOM_RIGHT;\n\n const textFieldWidth = this.measureWidth(ctx);\n const textFieldHeight = this.measureHeight();\n const x = (isShiftLeft ? this.anchor.x - textFieldWidth : this.anchor.x);\n const y = isShiftTop ? this.anchor.y - textFieldHeight : this.anchor.y;\n\n // adjust anchor if text box exceeds canvas borders\n if (canvasDims) {\n const { width, height } = canvasDims;\n const newX = Math.max(Math.min(x, width - textFieldWidth), 0);\n const newY = Math.max(Math.min(y, height - textFieldHeight), 0);\n return { x: newX, y: newY };\n }\n return { x, y };\n }\n\n draw(canvasArg: string | HTMLCanvasElement | CanvasRenderingContext2D) {\n const canvas = resolveInput(canvasArg);\n const ctx = getContext2dOrThrow(canvas);\n\n const {\n backgroundColor, fontColor, fontSize, fontStyle, padding,\n } = this.options;\n\n ctx.font = `${fontSize}px ${fontStyle}`;\n const maxTextWidth = this.measureWidth(ctx);\n const textHeight = this.measureHeight();\n\n ctx.fillStyle = backgroundColor;\n const upperLeft = this.getUpperLeft(ctx, canvas);\n ctx.fillRect(upperLeft.x, upperLeft.y, maxTextWidth, textHeight);\n\n ctx.fillStyle = fontColor;\n this.text.forEach((textLine, i) => {\n const x = padding + upperLeft.x;\n const y = padding + upperLeft.y + ((i + 1) * fontSize);\n ctx.fillText(textLine, x, y);\n });\n }\n}\n", "/* eslint-disable max-classes-per-file */\nimport { Box, IBoundingBox, IRect } from '../classes/index';\nimport { getContext2dOrThrow } from '../dom/getContext2dOrThrow';\nimport {\n AnchorPosition, DrawTextField, DrawTextFieldOptions, IDrawTextFieldOptions,\n} from './DrawTextField';\n\nexport interface IDrawBoxOptions {\n boxColor?: string\n lineWidth?: number\n drawLabelOptions?: IDrawTextFieldOptions\n label?: string\n}\n\nexport class DrawBoxOptions {\n public boxColor: string\n\n public lineWidth: number\n\n public drawLabelOptions: DrawTextFieldOptions\n\n public label?: string\n\n constructor(options: IDrawBoxOptions = {}) {\n const {\n boxColor, lineWidth, label, drawLabelOptions,\n } = options;\n this.boxColor = boxColor || 'rgba(0, 0, 255, 1)';\n this.lineWidth = lineWidth || 2;\n this.label = label;\n\n const defaultDrawLabelOptions = {\n anchorPosition: AnchorPosition.BOTTOM_LEFT,\n backgroundColor: this.boxColor,\n };\n this.drawLabelOptions = new DrawTextFieldOptions({ ...defaultDrawLabelOptions, ...drawLabelOptions });\n }\n}\n\nexport class DrawBox {\n public box: Box\n\n public options: DrawBoxOptions\n\n constructor(\n box: IBoundingBox | IRect,\n options: IDrawBoxOptions = {},\n ) {\n this.box = new Box(box);\n this.options = new DrawBoxOptions(options);\n }\n\n draw(canvasArg: string | HTMLCanvasElement | CanvasRenderingContext2D) {\n const ctx = getContext2dOrThrow(canvasArg);\n\n const { boxColor, lineWidth } = this.options;\n\n const {\n x, y, width, height,\n } = this.box;\n ctx.strokeStyle = boxColor;\n ctx.lineWidth = lineWidth;\n ctx.strokeRect(x, y, width, height);\n\n const { label } = this.options;\n if (label) {\n new DrawTextField([label], { x: x - (lineWidth / 2), y }, this.options.drawLabelOptions).draw(canvasArg);\n }\n }\n}\n", "import { Box, IBoundingBox, IRect } from '../classes/index';\nimport { FaceDetection } from '../classes/FaceDetection';\nimport { isWithFaceDetection, WithFaceDetection } from '../factories/WithFaceDetection';\nimport { round } from '../utils/index';\nimport { DrawBox } from './DrawBox';\n\nexport type TDrawDetectionsInput = IRect | IBoundingBox | FaceDetection | WithFaceDetection<{}>\n\nexport function drawDetections(\n canvasArg: string | HTMLCanvasElement,\n detections: TDrawDetectionsInput | Array,\n) {\n const detectionsArray = Array.isArray(detections) ? detections : [detections];\n\n detectionsArray.forEach((det) => {\n // eslint-disable-next-line no-nested-ternary\n const score = det instanceof FaceDetection\n ? det.score\n : (isWithFaceDetection(det) ? det.detection.score : undefined);\n\n // eslint-disable-next-line no-nested-ternary\n const box = det instanceof FaceDetection\n ? det.box\n : (isWithFaceDetection(det) ? det.detection.box : new Box(det));\n\n const label = score ? `${round(score)}` : undefined;\n new DrawBox(box, { label }).draw(canvasArg);\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { NetInput, TNetInput, toNetInput } from '../dom/index';\nimport { FaceFeatureExtractor } from '../faceFeatureExtractor/FaceFeatureExtractor';\nimport { FaceFeatureExtractorParams } from '../faceFeatureExtractor/types';\nimport { FaceProcessor } from '../faceProcessor/FaceProcessor';\nimport { FaceExpressions } from './FaceExpressions';\n\nexport class FaceExpressionNet extends FaceProcessor {\n constructor(faceFeatureExtractor: FaceFeatureExtractor = new FaceFeatureExtractor()) {\n super('FaceExpressionNet', faceFeatureExtractor);\n }\n\n public forwardInput(input: NetInput | tf.Tensor4D): tf.Tensor2D {\n return tf.tidy(() => tf.softmax(this.runNet(input)));\n }\n\n public async forward(input: TNetInput): Promise {\n return this.forwardInput(await toNetInput(input));\n }\n\n public async predictExpressions(input: TNetInput) {\n const netInput = await toNetInput(input);\n const out = await this.forwardInput(netInput);\n const probabilitesByBatch = await Promise.all(tf.unstack(out).map(async (t) => {\n const data = await t.data();\n t.dispose();\n return data;\n }));\n out.dispose();\n\n const predictionsByBatch = probabilitesByBatch\n .map((probabilites) => new FaceExpressions(probabilites as Float32Array));\n\n return netInput.isBatchInput\n ? predictionsByBatch\n : predictionsByBatch[0];\n }\n\n protected getDefaultModelName(): string {\n return 'face_expression_model';\n }\n\n protected getClassifierChannelsIn(): number {\n return 256;\n }\n\n protected getClassifierChannelsOut(): number {\n return 7;\n }\n}\n", "import { env } from '../env/index';\n\nexport function isMediaLoaded(media: HTMLImageElement | HTMLVideoElement) : boolean {\n const { Image, Video } = env.getEnv();\n\n return (media instanceof Image && media.complete)\n || (media instanceof Video && media.readyState >= 3);\n}\n", "import { env } from '../env/index';\nimport { isMediaLoaded } from './isMediaLoaded';\n\nexport function awaitMediaLoaded(media: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement) {\n // eslint-disable-next-line consistent-return\n return new Promise((resolve, reject) => {\n if (media instanceof env.getEnv().Canvas || isMediaLoaded(media)) {\n return resolve(null);\n }\n\n function onError(e: Event) {\n if (!e.currentTarget) return;\n // eslint-disable-next-line no-use-before-define\n e.currentTarget.removeEventListener('load', onLoad);\n e.currentTarget.removeEventListener('error', onError);\n reject(e);\n }\n\n function onLoad(e: Event) {\n if (!e.currentTarget) return;\n e.currentTarget.removeEventListener('load', onLoad);\n e.currentTarget.removeEventListener('error', onError);\n resolve(e);\n }\n\n media.addEventListener('load', onLoad);\n media.addEventListener('error', onError);\n });\n}\n", "import { env } from '../env/index';\n\nexport function bufferToImage(buf: Blob): Promise {\n return new Promise((resolve, reject) => {\n if (!(buf instanceof Blob)) reject(new Error('bufferToImage - expected buf to be of type: Blob'));\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result !== 'string') reject(new Error('bufferToImage - expected reader.result to be a string, in onload'));\n const img = env.getEnv().createImageElement();\n img.onload = () => resolve(img);\n img.onerror = reject;\n img.src = reader.result as string;\n };\n reader.onerror = reject;\n reader.readAsDataURL(buf);\n });\n}\n", "import { Dimensions, IDimensions } from '../classes/Dimensions';\nimport { env } from '../env/index';\n\nexport function getMediaDimensions(input: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | IDimensions): Dimensions {\n const { Image, Video } = env.getEnv();\n\n if (input instanceof Image) {\n return new Dimensions(input.naturalWidth, input.naturalHeight);\n }\n if (input instanceof Video) {\n return new Dimensions(input.videoWidth, input.videoHeight);\n }\n return new Dimensions(input.width, input.height);\n}\n", "import { IDimensions } from '../classes/Dimensions';\nimport { env } from '../env/index';\nimport { getContext2dOrThrow } from './getContext2dOrThrow';\nimport { getMediaDimensions } from './getMediaDimensions';\nimport { isMediaLoaded } from './isMediaLoaded';\n\nexport function createCanvas({ width, height }: IDimensions): HTMLCanvasElement {\n const { createCanvasElement } = env.getEnv();\n const canvas = createCanvasElement();\n canvas.width = width;\n canvas.height = height;\n return canvas;\n}\n\nexport function createCanvasFromMedia(media: HTMLImageElement | HTMLVideoElement | ImageData, dims?: IDimensions): HTMLCanvasElement {\n const { ImageData } = env.getEnv();\n\n if (!(media instanceof ImageData) && !isMediaLoaded(media)) {\n throw new Error('createCanvasFromMedia - media has not finished loading yet');\n }\n\n const { width, height } = dims || getMediaDimensions(media);\n const canvas = createCanvas({ width, height });\n\n if (media instanceof ImageData) {\n getContext2dOrThrow(canvas).putImageData(media, 0, 0);\n } else {\n getContext2dOrThrow(canvas).drawImage(media, 0, 0, width, height);\n }\n return canvas;\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { env } from '../env/index';\nimport { isTensor4D } from '../utils/index';\n\nexport async function imageTensorToCanvas(\n imgTensor: tf.Tensor,\n canvas?: HTMLCanvasElement,\n): Promise {\n const targetCanvas = canvas || env.getEnv().createCanvasElement();\n\n const [height, width, numChannels] = imgTensor.shape.slice(isTensor4D(imgTensor) ? 1 : 0);\n const imgTensor3D = tf.tidy(() => imgTensor.as3D(height, width, numChannels).toInt());\n await tf.browser.toPixels(imgTensor3D, targetCanvas);\n\n imgTensor3D.dispose();\n\n return targetCanvas;\n}\n", "import { env } from '../env/index';\n\nexport function isMediaElement(input: any) {\n const { Image, Canvas, Video } = env.getEnv();\n\n return input instanceof Image\n || input instanceof Canvas\n || input instanceof Video;\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { Dimensions } from '../classes/Dimensions';\nimport { env } from '../env/index';\nimport { padToSquare } from '../ops/padToSquare';\nimport {\n computeReshapedDimensions, isTensor3D, isTensor4D, range,\n} from '../utils/index';\nimport { createCanvasFromMedia } from './createCanvas';\nimport { imageToSquare } from './imageToSquare';\nimport { TResolvedNetInput } from './types';\n\nexport class NetInput {\n private _imageTensors: Array = []\n\n private _canvases: HTMLCanvasElement[] = []\n\n private _batchSize: number\n\n private _treatAsBatchInput: boolean = false\n\n private _inputDimensions: number[][] = []\n\n private _inputSize: number\n\n constructor(\n inputs: Array,\n treatAsBatchInput: boolean = false,\n ) {\n if (!Array.isArray(inputs)) {\n throw new Error(`NetInput.constructor - expected inputs to be an Array of TResolvedNetInput or to be instanceof tf.Tensor4D, instead have ${inputs}`);\n }\n\n this._treatAsBatchInput = treatAsBatchInput;\n this._batchSize = inputs.length;\n\n inputs.forEach((input, idx) => {\n if (isTensor3D(input)) {\n this._imageTensors[idx] = input;\n this._inputDimensions[idx] = input.shape;\n return;\n }\n\n if (isTensor4D(input)) {\n const batchSize = (input as any).shape[0];\n if (batchSize !== 1) {\n throw new Error(`NetInput - tf.Tensor4D with batchSize ${batchSize} passed, but not supported in input array`);\n }\n\n this._imageTensors[idx] = input;\n this._inputDimensions[idx] = (input as any).shape.slice(1);\n return;\n }\n\n const canvas = (input as any) instanceof env.getEnv().Canvas ? input : createCanvasFromMedia(input);\n this._canvases[idx] = canvas;\n this._inputDimensions[idx] = [canvas.height, canvas.width, 3];\n });\n }\n\n public get imageTensors(): Array {\n return this._imageTensors;\n }\n\n public get canvases(): HTMLCanvasElement[] {\n return this._canvases;\n }\n\n public get isBatchInput(): boolean {\n return this.batchSize > 1 || this._treatAsBatchInput;\n }\n\n public get batchSize(): number {\n return this._batchSize;\n }\n\n public get inputDimensions(): number[][] {\n return this._inputDimensions;\n }\n\n public get inputSize(): number | undefined {\n return this._inputSize;\n }\n\n public get reshapedInputDimensions(): Dimensions[] {\n return range(this.batchSize, 0, 1).map(\n (_, batchIdx) => this.getReshapedInputDimensions(batchIdx),\n );\n }\n\n public getInput(batchIdx: number): tf.Tensor3D | tf.Tensor4D | HTMLCanvasElement {\n return this.canvases[batchIdx] || this.imageTensors[batchIdx];\n }\n\n public getInputDimensions(batchIdx: number): number[] {\n return this._inputDimensions[batchIdx];\n }\n\n public getInputHeight(batchIdx: number): number {\n return this._inputDimensions[batchIdx][0];\n }\n\n public getInputWidth(batchIdx: number): number {\n return this._inputDimensions[batchIdx][1];\n }\n\n public getReshapedInputDimensions(batchIdx: number): Dimensions {\n if (typeof this.inputSize !== 'number') {\n throw new Error('getReshapedInputDimensions - inputSize not set, toBatchTensor has not been called yet');\n }\n\n const width = this.getInputWidth(batchIdx);\n const height = this.getInputHeight(batchIdx);\n return computeReshapedDimensions({ width, height }, this.inputSize);\n }\n\n /**\n * Create a batch tensor from all input canvases and tensors\n * with size [batchSize, inputSize, inputSize, 3].\n *\n * @param inputSize Height and width of the tensor.\n * @param isCenterImage (optional, default: false) If true, add an equal amount of padding on\n * both sides of the minor dimension oof the image.\n * @returns The batch tensor.\n */\n public toBatchTensor(inputSize: number, isCenterInputs: boolean = true): tf.Tensor4D {\n this._inputSize = inputSize;\n\n return tf.tidy(() => {\n const inputTensors = range(this.batchSize, 0, 1).map((batchIdx) => {\n const input = this.getInput(batchIdx);\n\n if (input instanceof tf.Tensor) {\n // @ts-ignore: error TS2344: Type 'Rank.R4' does not satisfy the constraint 'Tensor'.\n let imgTensor = isTensor4D(input) ? input : input.expandDims();\n // @ts-ignore: error TS2344: Type 'Rank.R4' does not satisfy the constraint 'Tensor'.\n imgTensor = padToSquare(imgTensor, isCenterInputs);\n\n if (imgTensor.shape[1] !== inputSize || imgTensor.shape[2] !== inputSize) {\n imgTensor = tf.image.resizeBilinear(imgTensor, [inputSize, inputSize]);\n }\n\n return imgTensor.as3D(inputSize, inputSize, 3);\n }\n\n if (input instanceof env.getEnv().Canvas) {\n return tf.browser.fromPixels(imageToSquare(input, inputSize, isCenterInputs));\n }\n\n throw new Error(`toBatchTensor - at batchIdx ${batchIdx}, expected input to be instanceof tf.Tensor or instanceof HTMLCanvasElement, instead have ${input}`);\n });\n\n // const batchTensor = tf.stack(inputTensors.map(t => t.toFloat())).as4D(this.batchSize, inputSize, inputSize, 3)\n const batchTensor = tf.stack(inputTensors.map((t) => tf.cast(t, 'float32'))).as4D(this.batchSize, inputSize, inputSize, 3);\n // const batchTensor = tf.stack(inputTensors.map(t => tf.Tensor.as4D(tf.cast(t, 'float32'))), this.batchSize, inputSize, inputSize, 3);\n\n return batchTensor;\n });\n }\n}\n", "import { env } from '../env/index';\nimport { createCanvas, createCanvasFromMedia } from './createCanvas';\nimport { getContext2dOrThrow } from './getContext2dOrThrow';\nimport { getMediaDimensions } from './getMediaDimensions';\n\nexport function imageToSquare(input: HTMLImageElement | HTMLCanvasElement, inputSize: number, centerImage: boolean = false) {\n const { Image, Canvas } = env.getEnv();\n\n if (!(input instanceof Image || input instanceof Canvas)) {\n throw new Error('imageToSquare - expected arg0 to be HTMLImageElement | HTMLCanvasElement');\n }\n\n if (inputSize <= 0) return createCanvas({ width: 1, height: 1 });\n const dims = getMediaDimensions(input);\n const scale = inputSize / Math.max(dims.height, dims.width);\n const width = scale * dims.width;\n const height = scale * dims.height;\n\n const targetCanvas = createCanvas({ width: inputSize, height: inputSize });\n const inputCanvas = input instanceof Canvas ? input : createCanvasFromMedia(input);\n\n const offset = Math.abs(width - height) / 2;\n const dx = centerImage && width < height ? offset : 0;\n const dy = centerImage && height < width ? offset : 0;\n if (inputCanvas.width > 0 && inputCanvas.height > 0) getContext2dOrThrow(targetCanvas).drawImage(inputCanvas, dx, dy, width, height);\n\n return targetCanvas;\n}\n", "import { isTensor3D, isTensor4D } from '../utils/index';\nimport { awaitMediaLoaded } from './awaitMediaLoaded';\nimport { isMediaElement } from './isMediaElement';\nimport { NetInput } from './NetInput';\nimport { resolveInput } from './resolveInput';\nimport { TNetInput } from './types';\n\n/**\n * Validates the input to make sure, they are valid net inputs and awaits all media elements\n * to be finished loading.\n *\n * @param input The input, which can be a media element or an array of different media elements.\n * @returns A NetInput instance, which can be passed into one of the neural networks.\n */\nexport async function toNetInput(inputs: TNetInput): Promise {\n if (inputs instanceof NetInput) {\n return inputs;\n }\n\n const inputArgArray = Array.isArray(inputs)\n ? inputs\n : [inputs];\n\n if (!inputArgArray.length) {\n throw new Error('toNetInput - empty array passed as input');\n }\n\n const getIdxHint = (idx: number) => (Array.isArray(inputs) ? ` at input index ${idx}:` : '');\n\n const inputArray = inputArgArray.map(resolveInput);\n\n inputArray.forEach((input, i) => {\n if (!isMediaElement(input) && !isTensor3D(input) && !isTensor4D(input)) {\n if (typeof inputArgArray[i] === 'string') {\n throw new Error(`toNetInput -${getIdxHint(i)} string passed, but could not resolve HTMLElement for element id ${inputArgArray[i]}`);\n }\n\n throw new Error(`toNetInput -${getIdxHint(i)} expected media to be of type HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | tf.Tensor3D, or to be an element id`);\n }\n\n if (isTensor4D(input)) {\n // if tf.Tensor4D is passed in the input array, the batch size has to be 1\n const batchSize = input.shape[0];\n if (batchSize !== 1) {\n throw new Error(`toNetInput -${getIdxHint(i)} tf.Tensor4D with batchSize ${batchSize} passed, but not supported in input array`);\n }\n }\n });\n\n // wait for all media elements being loaded\n await Promise.all(\n inputArray.map((input) => isMediaElement(input) && awaitMediaLoaded(input)),\n );\n\n return new NetInput(inputArray, Array.isArray(inputs));\n}\n", "import { FaceDetection } from '../classes/FaceDetection';\nimport { Rect } from '../classes/Rect';\nimport { env } from '../env/index';\nimport { createCanvas } from './createCanvas';\nimport { getContext2dOrThrow } from './getContext2dOrThrow';\nimport { imageTensorToCanvas } from './imageTensorToCanvas';\nimport { toNetInput } from './toNetInput';\nimport { TNetInput } from './types';\n\n/**\n * Extracts the image regions containing the detected faces.\n *\n * @param input The image that face detection has been performed on.\n * @param detections The face detection results or face bounding boxes for that image.\n * @returns The Canvases of the corresponding image region for each detected face.\n */\nexport async function extractFaces(\n input: TNetInput,\n detections: Array,\n): Promise {\n const { Canvas } = env.getEnv();\n\n let canvas = input as HTMLCanvasElement;\n\n if (!(input instanceof Canvas)) {\n const netInput = await toNetInput(input);\n\n if (netInput.batchSize > 1) {\n throw new Error('extractFaces - batchSize > 1 not supported');\n }\n\n const tensorOrCanvas = netInput.getInput(0);\n canvas = tensorOrCanvas instanceof Canvas\n ? tensorOrCanvas\n : await imageTensorToCanvas(tensorOrCanvas);\n }\n\n const ctx = getContext2dOrThrow(canvas);\n const boxes = detections.map(\n (det) => (det instanceof FaceDetection\n ? det.forSize(canvas.width, canvas.height).box.floor()\n : det),\n )\n .map((box) => box.clipAtImageBorders(canvas.width, canvas.height));\n\n return boxes.map(({\n x, y, width, height,\n }) => {\n const faceImg = createCanvas({ width, height });\n if (width > 0 && height > 0) getContext2dOrThrow(faceImg).putImageData(ctx.getImageData(x, y, width, height), 0, 0);\n return faceImg;\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { Rect } from '../classes/index';\nimport { FaceDetection } from '../classes/FaceDetection';\nimport { isTensor3D, isTensor4D } from '../utils/index';\n\n/**\n * Extracts the tensors of the image regions containing the detected faces.\n * Useful if you want to compute the face descriptors for the face images.\n * Using this method is faster then extracting a canvas for each face and\n * converting them to tensors individually.\n *\n * @param imageTensor The image tensor that face detection has been performed on.\n * @param detections The face detection results or face bounding boxes for that image.\n * @returns Tensors of the corresponding image region for each detected face.\n */\nexport async function extractFaceTensors(\n imageTensor: tf.Tensor3D | tf.Tensor4D,\n detections: Array,\n): Promise {\n if (!isTensor3D(imageTensor) && !isTensor4D(imageTensor)) {\n throw new Error('extractFaceTensors - expected image tensor to be 3D or 4D');\n }\n\n if (isTensor4D(imageTensor) && imageTensor.shape[0] > 1) {\n throw new Error('extractFaceTensors - batchSize > 1 not supported');\n }\n\n return tf.tidy(() => {\n const [imgHeight, imgWidth, numChannels] = imageTensor.shape.slice(isTensor4D(imageTensor) ? 1 : 0);\n\n const boxes = detections.map(\n (det) => (det instanceof FaceDetection\n ? det.forSize(imgWidth, imgHeight).box\n : det),\n )\n .map((box) => box.clipAtImageBorders(imgWidth, imgHeight));\n\n const faceTensors = boxes.map(({\n x, y, width, height,\n }) => tf.slice3d(imageTensor.as3D(imgHeight, imgWidth, numChannels), [y, x, 0], [height, width, numChannels]));\n\n return faceTensors;\n });\n}\n", "import { env } from '../env/index';\n\nexport async function fetchOrThrow(\n url: string,\n // eslint-disable-next-line no-undef\n init?: RequestInit,\n): Promise {\n const { fetch } = env.getEnv();\n const res = await fetch(url, init);\n if (!(res.status < 400)) {\n throw new Error(`failed to fetch: (${res.status}) ${res.statusText}, from url: ${res.url}`);\n }\n return res;\n}\n", "import { bufferToImage } from './bufferToImage';\nimport { fetchOrThrow } from './fetchOrThrow';\n\nexport async function fetchImage(uri: string): Promise {\n const res = await fetchOrThrow(uri);\n const blob = await (res).blob();\n\n if (!blob.type.startsWith('image/')) {\n throw new Error(`fetchImage - expected blob type to be of type image/*, instead have: ${blob.type}, for url: ${res.url}`);\n }\n return bufferToImage(blob);\n}\n", "import { fetchOrThrow } from './fetchOrThrow';\n\nexport async function fetchJson(uri: string): Promise {\n return (await fetchOrThrow(uri)).json();\n}\n", "import { fetchOrThrow } from './fetchOrThrow';\n\nexport async function fetchNetWeights(uri: string): Promise {\n return new Float32Array(await (await fetchOrThrow(uri)).arrayBuffer());\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { getModelUris } from '../common/getModelUris';\nimport { fetchJson } from './fetchJson';\n\nexport async function loadWeightMap(\n uri: string | undefined,\n defaultModelName: string,\n): Promise {\n const { manifestUri, modelBaseUri } = getModelUris(uri, defaultModelName);\n const manifest = await fetchJson(manifestUri);\n // if (manifest['weightsManifest']) manifest = manifest['weightsManifest'];\n return tf.io.loadWeights(manifest, modelBaseUri);\n}\n", "export function getModelUris(uri: string | undefined, defaultModelName: string) {\n const defaultManifestFilename = `${defaultModelName}-weights_manifest.json`;\n\n if (!uri) {\n return {\n modelBaseUri: '',\n manifestUri: defaultManifestFilename,\n };\n }\n\n if (uri === '/') {\n return {\n modelBaseUri: '/',\n manifestUri: `/${defaultManifestFilename}`,\n };\n }\n // eslint-disable-next-line no-nested-ternary\n const protocol = uri.startsWith('http://') ? 'http://' : uri.startsWith('https://') ? 'https://' : '';\n uri = uri.replace(protocol, '');\n\n const parts = uri.split('/').filter((s) => s);\n\n const manifestFile = uri.endsWith('.json')\n ? parts[parts.length - 1]\n : defaultManifestFilename;\n\n let modelBaseUri = protocol + (uri.endsWith('.json') ? parts.slice(0, parts.length - 1) : parts).join('/');\n modelBaseUri = uri.startsWith('/') ? `/${modelBaseUri}` : modelBaseUri;\n\n return {\n modelBaseUri,\n manifestUri: modelBaseUri === '/' ? `/${manifestFile}` : `${modelBaseUri}/${manifestFile}`,\n };\n}\n", "import { IDimensions } from '../classes/index';\nimport { getMediaDimensions } from './getMediaDimensions';\n\nexport function matchDimensions(input: IDimensions, reference: IDimensions, useMediaDimensions: boolean = false) {\n const { width, height } = useMediaDimensions\n ? getMediaDimensions(reference)\n : reference;\n input.width = width;\n input.height = height;\n return { width, height };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { NetInput, TNetInput, toNetInput } from '../dom/index';\nimport { NeuralNetwork } from '../NeuralNetwork';\nimport { normalize } from '../ops/index';\nimport { denseBlock4 } from './denseBlock';\nimport { extractParams } from './extractParams';\nimport { extractParamsFromWeightMap } from './extractParamsFromWeightMap';\nimport { FaceFeatureExtractorParams, IFaceFeatureExtractor } from './types';\n\nexport class FaceFeatureExtractor extends NeuralNetwork implements IFaceFeatureExtractor {\n constructor() {\n super('FaceFeatureExtractor');\n }\n\n public forwardInput(input: NetInput): tf.Tensor4D {\n const { params } = this;\n\n if (!params) {\n throw new Error('FaceFeatureExtractor - load model before inference');\n }\n\n return tf.tidy(() => {\n const batchTensor = tf.cast(input.toBatchTensor(112, true), 'float32');\n const meanRgb = [122.782, 117.001, 104.298];\n const normalized = normalize(batchTensor, meanRgb).div(tf.scalar(255)) as tf.Tensor4D;\n\n let out = denseBlock4(normalized, params.dense0, true);\n out = denseBlock4(out, params.dense1);\n out = denseBlock4(out, params.dense2);\n out = denseBlock4(out, params.dense3);\n out = tf.avgPool(out, [7, 7], [2, 2], 'valid');\n\n return out;\n });\n }\n\n public async forward(input: TNetInput): Promise {\n return this.forwardInput(await toNetInput(input));\n }\n\n protected getDefaultModelName(): string {\n return 'face_feature_extractor_model';\n }\n\n protected extractParamsFromWeightMap(weightMap: tf.NamedTensorMap) {\n return extractParamsFromWeightMap(weightMap);\n }\n\n protected extractParams(weights: Float32Array) {\n return extractParams(weights);\n }\n}\n", "import * as tf from '../dist/tfjs.esm';\n\nimport { ParamMapping } from './common/index';\nimport { getModelUris } from './common/getModelUris';\nimport { loadWeightMap } from './dom/index';\nimport { env } from './env/index';\n\nexport abstract class NeuralNetwork {\n constructor(name: string) {\n this._name = name;\n }\n\n protected _params: TNetParams | undefined = undefined\n\n protected _paramMappings: ParamMapping[] = []\n\n public _name: any;\n\n public get params(): TNetParams | undefined { return this._params; }\n\n public get paramMappings(): ParamMapping[] { return this._paramMappings; }\n\n public get isLoaded(): boolean { return !!this.params; }\n\n public getParamFromPath(paramPath: string): tf.Tensor {\n const { obj, objProp } = this.traversePropertyPath(paramPath);\n return obj[objProp];\n }\n\n public reassignParamFromPath(paramPath: string, tensor: tf.Tensor) {\n const { obj, objProp } = this.traversePropertyPath(paramPath);\n obj[objProp].dispose();\n obj[objProp] = tensor;\n }\n\n public getParamList() {\n return this._paramMappings.map(({ paramPath }) => ({\n path: paramPath,\n tensor: this.getParamFromPath(paramPath),\n }));\n }\n\n public getTrainableParams() {\n return this.getParamList().filter((param) => param.tensor instanceof tf.Variable);\n }\n\n public getFrozenParams() {\n return this.getParamList().filter((param) => !(param.tensor instanceof tf.Variable));\n }\n\n public variable() {\n this.getFrozenParams().forEach(({ path, tensor }) => {\n this.reassignParamFromPath(path, tensor.variable());\n });\n }\n\n public freeze() {\n this.getTrainableParams().forEach(({ path, tensor: variable }) => {\n const tensor = tf.tensor(variable.dataSync());\n variable.dispose();\n this.reassignParamFromPath(path, tensor);\n });\n }\n\n public dispose(throwOnRedispose: boolean = true) {\n this.getParamList().forEach((param) => {\n if (throwOnRedispose && param.tensor.isDisposed) {\n throw new Error(`param tensor has already been disposed for path ${param.path}`);\n }\n param.tensor.dispose();\n });\n this._params = undefined;\n }\n\n public serializeParams(): Float32Array {\n return new Float32Array(\n this.getParamList()\n .map(({ tensor }) => Array.from(tensor.dataSync()) as number[])\n .reduce((flat, arr) => flat.concat(arr)),\n );\n }\n\n public async load(weightsOrUrl: Float32Array | string | undefined): Promise {\n if (weightsOrUrl instanceof Float32Array) {\n this.extractWeights(weightsOrUrl);\n return;\n }\n await this.loadFromUri(weightsOrUrl);\n }\n\n public async loadFromUri(uri: string | undefined) {\n if (uri && typeof uri !== 'string') {\n throw new Error(`${this._name}.loadFromUri - expected model uri`);\n }\n const weightMap = await loadWeightMap(uri, this.getDefaultModelName());\n this.loadFromWeightMap(weightMap);\n }\n\n public async loadFromDisk(filePath: string | undefined) {\n if (filePath && typeof filePath !== 'string') {\n throw new Error(`${this._name}.loadFromDisk - expected model file path`);\n }\n const { readFile } = env.getEnv();\n const { manifestUri, modelBaseUri } = getModelUris(filePath, this.getDefaultModelName());\n const fetchWeightsFromDisk = (filePaths: string[]) => Promise.all(filePaths.map((fp) => readFile(fp).then((buf) => buf.buffer)));\n const loadWeights = tf.io.weightsLoaderFactory(fetchWeightsFromDisk);\n const manifest = JSON.parse((await readFile(manifestUri)).toString());\n const weightMap = await loadWeights(manifest, modelBaseUri);\n this.loadFromWeightMap(weightMap);\n }\n\n public loadFromWeightMap(weightMap: tf.NamedTensorMap) {\n const { paramMappings, params } = this.extractParamsFromWeightMap(weightMap);\n this._paramMappings = paramMappings;\n this._params = params;\n }\n\n public extractWeights(weights: Float32Array) {\n const { paramMappings, params } = this.extractParams(weights);\n this._paramMappings = paramMappings;\n this._params = params;\n }\n\n private traversePropertyPath(paramPath: string) {\n if (!this.params) {\n throw new Error('traversePropertyPath - model has no loaded params');\n }\n\n const result = paramPath.split('/').reduce((res: { nextObj: any, obj?: any, objProp?: string }, objProp) => {\n // eslint-disable-next-line no-prototype-builtins\n if (!res.nextObj.hasOwnProperty(objProp)) {\n throw new Error(`traversePropertyPath - object does not have property ${objProp}, for path ${paramPath}`);\n }\n return { obj: res.nextObj, objProp, nextObj: res.nextObj[objProp] };\n }, { nextObj: this.params });\n\n const { obj, objProp } = result;\n if (!obj || !objProp || !(obj[objProp] instanceof tf.Tensor)) {\n throw new Error(`traversePropertyPath - parameter is not a tensor, for path ${paramPath}`);\n }\n\n return { obj, objProp };\n }\n\n protected abstract getDefaultModelName(): string\n\n // eslint-disable-next-line no-unused-vars\n protected abstract extractParamsFromWeightMap(weightMap: tf.NamedTensorMap): { params: TNetParams, paramMappings: ParamMapping[] }\n\n // eslint-disable-next-line no-unused-vars\n protected abstract extractParams(weights: Float32Array): { params: TNetParams, paramMappings: ParamMapping[] }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { ConvParams, SeparableConvParams } from '../common/index';\nimport { depthwiseSeparableConv } from '../common/depthwiseSeparableConv';\nimport { DenseBlock3Params, DenseBlock4Params } from './types';\n\nexport function denseBlock3(\n x: tf.Tensor4D,\n denseBlockParams: DenseBlock3Params,\n isFirstLayer: boolean = false,\n): tf.Tensor4D {\n return tf.tidy(() => {\n const out1 = tf.relu(\n isFirstLayer\n ? tf.add(\n tf.conv2d(x, (denseBlockParams.conv0 as ConvParams).filters, [2, 2], 'same'),\n denseBlockParams.conv0.bias,\n )\n : depthwiseSeparableConv(x, denseBlockParams.conv0 as SeparableConvParams, [2, 2]),\n ) as tf.Tensor4D;\n const out2 = depthwiseSeparableConv(out1, denseBlockParams.conv1, [1, 1]);\n\n const in3 = tf.relu(tf.add(out1, out2)) as tf.Tensor4D;\n const out3 = depthwiseSeparableConv(in3, denseBlockParams.conv2, [1, 1]);\n\n return tf.relu(tf.add(out1, tf.add(out2, out3))) as tf.Tensor4D;\n });\n}\n\nexport function denseBlock4(\n x: tf.Tensor4D,\n denseBlockParams: DenseBlock4Params,\n isFirstLayer: boolean = false,\n isScaleDown: boolean = true,\n): tf.Tensor4D {\n return tf.tidy(() => {\n const out1 = tf.relu(\n isFirstLayer\n ? tf.add(\n tf.conv2d(x, (denseBlockParams.conv0 as ConvParams).filters, isScaleDown ? [2, 2] : [1, 1], 'same'),\n denseBlockParams.conv0.bias,\n )\n : depthwiseSeparableConv(x, denseBlockParams.conv0 as SeparableConvParams, isScaleDown ? [2, 2] : [1, 1]),\n ) as tf.Tensor4D;\n const out2 = depthwiseSeparableConv(out1, denseBlockParams.conv1, [1, 1]);\n\n const in3 = tf.relu(tf.add(out1, out2)) as tf.Tensor4D;\n const out3 = depthwiseSeparableConv(in3, denseBlockParams.conv2, [1, 1]);\n\n const in4 = tf.relu(tf.add(out1, tf.add(out2, out3))) as tf.Tensor4D;\n const out4 = depthwiseSeparableConv(in4, denseBlockParams.conv3, [1, 1]);\n\n return tf.relu(tf.add(out1, tf.add(out2, tf.add(out3, out4)))) as tf.Tensor4D;\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { SeparableConvParams } from './types';\n\nexport function depthwiseSeparableConv(\n x: tf.Tensor4D,\n params: SeparableConvParams,\n stride: [number, number],\n): tf.Tensor4D {\n return tf.tidy(() => {\n let out = tf.separableConv2d(x, params.depthwise_filter, params.pointwise_filter, stride, 'same');\n out = tf.add(out, params.bias);\n return out;\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { ConvParams } from './types';\n\nexport function convLayer(\n x: tf.Tensor4D,\n params: ConvParams,\n padding: 'valid' | 'same' = 'same',\n withRelu: boolean = false,\n): tf.Tensor4D {\n return tf.tidy(() => {\n const out = tf.add(\n tf.conv2d(x, params.filters, [1, 1], padding),\n params.bias,\n ) as tf.Tensor4D;\n\n return withRelu ? tf.relu(out) : out;\n });\n}\n", "import { ParamMapping } from './types';\n\nexport function disposeUnusedWeightTensors(weightMap: any, paramMappings: ParamMapping[]) {\n Object.keys(weightMap).forEach((path) => {\n if (!paramMappings.some((pm) => pm.originalPath === path)) {\n weightMap[path].dispose();\n }\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { ConvParams, ExtractWeightsFunction, ParamMapping } from './types';\n\nexport function extractConvParamsFactory(\n extractWeights: ExtractWeightsFunction,\n paramMappings: ParamMapping[],\n) {\n return (\n channelsIn: number,\n channelsOut: number,\n filterSize: number,\n mappedPrefix: string,\n ): ConvParams => {\n const filters = tf.tensor4d(\n extractWeights(channelsIn * channelsOut * filterSize * filterSize),\n [filterSize, filterSize, channelsIn, channelsOut],\n );\n const bias = tf.tensor1d(extractWeights(channelsOut));\n\n paramMappings.push(\n { paramPath: `${mappedPrefix}/filters` },\n { paramPath: `${mappedPrefix}/bias` },\n );\n\n return { filters, bias };\n };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { ExtractWeightsFunction, FCParams, ParamMapping } from './types';\n\nexport function extractFCParamsFactory(\n extractWeights: ExtractWeightsFunction,\n paramMappings: ParamMapping[],\n) {\n return (\n channelsIn: number,\n channelsOut: number,\n mappedPrefix: string,\n ): FCParams => {\n const fc_weights = tf.tensor2d(extractWeights(channelsIn * channelsOut), [channelsIn, channelsOut]);\n const fc_bias = tf.tensor1d(extractWeights(channelsOut));\n\n paramMappings.push(\n { paramPath: `${mappedPrefix}/weights` },\n { paramPath: `${mappedPrefix}/bias` },\n );\n\n return {\n weights: fc_weights,\n bias: fc_bias,\n };\n };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { ExtractWeightsFunction, ParamMapping, SeparableConvParams } from './types';\n\nexport function extractSeparableConvParamsFactory(\n extractWeights: ExtractWeightsFunction,\n paramMappings: ParamMapping[],\n) {\n return (channelsIn: number, channelsOut: number, mappedPrefix: string): SeparableConvParams => {\n const depthwise_filter = tf.tensor4d(extractWeights(3 * 3 * channelsIn), [3, 3, channelsIn, 1]);\n const pointwise_filter = tf.tensor4d(extractWeights(channelsIn * channelsOut), [1, 1, channelsIn, channelsOut]);\n const bias = tf.tensor1d(extractWeights(channelsOut));\n\n paramMappings.push(\n { paramPath: `${mappedPrefix}/depthwise_filter` },\n { paramPath: `${mappedPrefix}/pointwise_filter` },\n { paramPath: `${mappedPrefix}/bias` },\n );\n\n return new SeparableConvParams(\n depthwise_filter,\n pointwise_filter,\n bias,\n );\n };\n}\n\nexport function loadSeparableConvParamsFactory(\n // eslint-disable-next-line no-unused-vars\n extractWeightEntry: (originalPath: string, paramRank: number) => T,\n) {\n return (prefix: string): SeparableConvParams => {\n const depthwise_filter = extractWeightEntry(`${prefix}/depthwise_filter`, 4);\n const pointwise_filter = extractWeightEntry(`${prefix}/pointwise_filter`, 4);\n const bias = extractWeightEntry(`${prefix}/bias`, 1);\n\n return new SeparableConvParams(\n depthwise_filter,\n pointwise_filter,\n bias,\n );\n };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\n// eslint-disable-next-line no-unused-vars\nexport type ExtractWeightsFunction = (numWeights: number) => Float32Array\n\nexport type ParamMapping = {\n originalPath?: string\n paramPath: string\n}\n\nexport type ConvParams = {\n filters: tf.Tensor4D\n bias: tf.Tensor1D\n}\n\nexport type FCParams = {\n weights: tf.Tensor2D\n bias: tf.Tensor1D\n}\n\nexport class SeparableConvParams {\n // eslint-disable-next-line no-useless-constructor\n constructor(\n // eslint-disable-next-line no-unused-vars\n public depthwise_filter: tf.Tensor4D,\n // eslint-disable-next-line no-unused-vars\n public pointwise_filter: tf.Tensor4D,\n // eslint-disable-next-line no-unused-vars\n public bias: tf.Tensor1D,\n // eslint-disable-next-line no-empty-function\n ) {}\n}\n", "import { isTensor } from '../utils/index';\nimport { ParamMapping } from './types';\n\nexport function extractWeightEntryFactory(weightMap: any, paramMappings: ParamMapping[]) {\n return (originalPath: string, paramRank: number, mappedPath?: string) => {\n const tensor = weightMap[originalPath];\n\n if (!isTensor(tensor, paramRank)) {\n throw new Error(`expected weightMap[${originalPath}] to be a Tensor${paramRank}D, instead have ${tensor}`);\n }\n\n paramMappings.push(\n { originalPath, paramPath: mappedPath || originalPath },\n );\n\n return tensor;\n };\n}\n", "export function extractWeightsFactory(weights: Float32Array) {\n let remainingWeights = weights;\n\n function extractWeights(numWeights: number): Float32Array {\n const ret = remainingWeights.slice(0, numWeights);\n remainingWeights = remainingWeights.slice(numWeights);\n return ret;\n }\n\n function getRemainingWeights(): Float32Array {\n return remainingWeights;\n }\n\n return {\n extractWeights,\n getRemainingWeights,\n };\n}\n", "import {\n extractConvParamsFactory,\n extractSeparableConvParamsFactory,\n ExtractWeightsFunction,\n ParamMapping,\n} from '../common/index';\nimport { DenseBlock3Params, DenseBlock4Params } from './types';\n\nexport function extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings: ParamMapping[]) {\n const extractConvParams = extractConvParamsFactory(extractWeights, paramMappings);\n const extractSeparableConvParams = extractSeparableConvParamsFactory(extractWeights, paramMappings);\n\n function extractDenseBlock3Params(channelsIn: number, channelsOut: number, mappedPrefix: string, isFirstLayer: boolean = false): DenseBlock3Params {\n const conv0 = isFirstLayer\n ? extractConvParams(channelsIn, channelsOut, 3, `${mappedPrefix}/conv0`)\n : extractSeparableConvParams(channelsIn, channelsOut, `${mappedPrefix}/conv0`);\n const conv1 = extractSeparableConvParams(channelsOut, channelsOut, `${mappedPrefix}/conv1`);\n const conv2 = extractSeparableConvParams(channelsOut, channelsOut, `${mappedPrefix}/conv2`);\n\n return { conv0, conv1, conv2 };\n }\n\n function extractDenseBlock4Params(channelsIn: number, channelsOut: number, mappedPrefix: string, isFirstLayer: boolean = false): DenseBlock4Params {\n const { conv0, conv1, conv2 } = extractDenseBlock3Params(channelsIn, channelsOut, mappedPrefix, isFirstLayer);\n const conv3 = extractSeparableConvParams(channelsOut, channelsOut, `${mappedPrefix}/conv3`);\n\n return {\n conv0, conv1, conv2, conv3,\n };\n }\n\n return {\n extractDenseBlock3Params,\n extractDenseBlock4Params,\n };\n}\n", "import { extractWeightsFactory, ParamMapping } from '../common/index';\nimport { extractorsFactory } from './extractorsFactory';\nimport { FaceFeatureExtractorParams } from './types';\n\nexport function extractParams(weights: Float32Array): { params: FaceFeatureExtractorParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractWeights,\n getRemainingWeights,\n } = extractWeightsFactory(weights);\n\n const {\n extractDenseBlock4Params,\n } = extractorsFactory(extractWeights, paramMappings);\n\n const dense0 = extractDenseBlock4Params(3, 32, 'dense0', true);\n const dense1 = extractDenseBlock4Params(32, 64, 'dense1');\n const dense2 = extractDenseBlock4Params(64, 128, 'dense2');\n const dense3 = extractDenseBlock4Params(128, 256, 'dense3');\n\n if (getRemainingWeights().length !== 0) {\n throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`);\n }\n\n return {\n paramMappings,\n params: {\n dense0, dense1, dense2, dense3,\n },\n };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { ConvParams } from './types';\n\n// eslint-disable-next-line no-unused-vars\nexport function loadConvParamsFactory(extractWeightEntry: (originalPath: string, paramRank: number) => T) {\n return (prefix: string): ConvParams => {\n const filters = extractWeightEntry(`${prefix}/filters`, 4);\n const bias = extractWeightEntry(`${prefix}/bias`, 1);\n\n return { filters, bias };\n };\n}\n", "import { extractWeightEntryFactory, loadSeparableConvParamsFactory, ParamMapping } from '../common/index';\nimport { loadConvParamsFactory } from '../common/loadConvParamsFactory';\nimport { DenseBlock3Params, DenseBlock4Params } from './types';\n\nexport function loadParamsFactory(weightMap: any, paramMappings: ParamMapping[]) {\n const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings);\n\n const extractConvParams = loadConvParamsFactory(extractWeightEntry);\n const extractSeparableConvParams = loadSeparableConvParamsFactory(extractWeightEntry);\n\n function extractDenseBlock3Params(prefix: string, isFirstLayer: boolean = false): DenseBlock3Params {\n const conv0 = isFirstLayer\n ? extractConvParams(`${prefix}/conv0`)\n : extractSeparableConvParams(`${prefix}/conv0`);\n const conv1 = extractSeparableConvParams(`${prefix}/conv1`);\n const conv2 = extractSeparableConvParams(`${prefix}/conv2`);\n\n return { conv0, conv1, conv2 };\n }\n\n function extractDenseBlock4Params(prefix: string, isFirstLayer: boolean = false): DenseBlock4Params {\n const conv0 = isFirstLayer\n ? extractConvParams(`${prefix}/conv0`)\n : extractSeparableConvParams(`${prefix}/conv0`);\n const conv1 = extractSeparableConvParams(`${prefix}/conv1`);\n const conv2 = extractSeparableConvParams(`${prefix}/conv2`);\n const conv3 = extractSeparableConvParams(`${prefix}/conv3`);\n\n return {\n conv0, conv1, conv2, conv3,\n };\n }\n\n return {\n extractDenseBlock3Params,\n extractDenseBlock4Params,\n };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { disposeUnusedWeightTensors, ParamMapping } from '../common/index';\nimport { loadParamsFactory } from './loadParamsFactory';\nimport { FaceFeatureExtractorParams } from './types';\n\nexport function extractParamsFromWeightMap(\n weightMap: tf.NamedTensorMap,\n): { params: FaceFeatureExtractorParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractDenseBlock4Params,\n } = loadParamsFactory(weightMap, paramMappings);\n\n const params = {\n dense0: extractDenseBlock4Params('dense0', true),\n dense1: extractDenseBlock4Params('dense1'),\n dense2: extractDenseBlock4Params('dense2'),\n dense3: extractDenseBlock4Params('dense3'),\n };\n\n disposeUnusedWeightTensors(weightMap, paramMappings);\n\n return { params, paramMappings };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { fullyConnectedLayer } from '../common/fullyConnectedLayer';\nimport { NetInput } from '../dom/index';\nimport {\n FaceFeatureExtractorParams,\n IFaceFeatureExtractor,\n TinyFaceFeatureExtractorParams,\n} from '../faceFeatureExtractor/types';\nimport { NeuralNetwork } from '../NeuralNetwork';\nimport { extractParams } from './extractParams';\nimport { extractParamsFromWeightMap } from './extractParamsFromWeightMap';\nimport { NetParams } from './types';\nimport { seperateWeightMaps } from './util';\n\nexport abstract class FaceProcessor<\n TExtractorParams extends FaceFeatureExtractorParams | TinyFaceFeatureExtractorParams\n>\n extends NeuralNetwork {\n protected _faceFeatureExtractor: IFaceFeatureExtractor\n\n constructor(_name: string, faceFeatureExtractor: IFaceFeatureExtractor) {\n super(_name);\n this._faceFeatureExtractor = faceFeatureExtractor;\n }\n\n public get faceFeatureExtractor(): IFaceFeatureExtractor {\n return this._faceFeatureExtractor;\n }\n\n protected abstract getDefaultModelName(): string\n\n protected abstract getClassifierChannelsIn(): number\n\n protected abstract getClassifierChannelsOut(): number\n\n public runNet(input: NetInput | tf.Tensor4D): tf.Tensor2D {\n const { params } = this;\n\n if (!params) {\n throw new Error(`${this._name} - load model before inference`);\n }\n\n return tf.tidy(() => {\n const bottleneckFeatures = input instanceof NetInput\n ? this.faceFeatureExtractor.forwardInput(input)\n : input;\n return fullyConnectedLayer(bottleneckFeatures.as2D(bottleneckFeatures.shape[0], -1), params.fc);\n });\n }\n\n public dispose(throwOnRedispose: boolean = true) {\n this.faceFeatureExtractor.dispose(throwOnRedispose);\n super.dispose(throwOnRedispose);\n }\n\n public loadClassifierParams(weights: Float32Array) {\n const { params, paramMappings } = this.extractClassifierParams(weights);\n this._params = params;\n this._paramMappings = paramMappings;\n }\n\n public extractClassifierParams(weights: Float32Array) {\n return extractParams(weights, this.getClassifierChannelsIn(), this.getClassifierChannelsOut());\n }\n\n protected extractParamsFromWeightMap(weightMap: tf.NamedTensorMap) {\n const { featureExtractorMap, classifierMap } = seperateWeightMaps(weightMap);\n\n this.faceFeatureExtractor.loadFromWeightMap(featureExtractorMap);\n\n return extractParamsFromWeightMap(classifierMap);\n }\n\n protected extractParams(weights: Float32Array) {\n const cIn = this.getClassifierChannelsIn();\n const cOut = this.getClassifierChannelsOut();\n const classifierWeightSize = (cOut * cIn) + cOut;\n\n const featureExtractorWeights = weights.slice(0, weights.length - classifierWeightSize);\n const classifierWeights = weights.slice(weights.length - classifierWeightSize);\n\n this.faceFeatureExtractor.extractWeights(featureExtractorWeights);\n return this.extractClassifierParams(classifierWeights);\n }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { FCParams } from './types';\n\nexport function fullyConnectedLayer(\n x: tf.Tensor2D,\n params: FCParams,\n): tf.Tensor2D {\n return tf.tidy(() => tf.add(\n tf.matMul(x, params.weights),\n params.bias,\n ));\n}\n", "import { extractFCParamsFactory, extractWeightsFactory, ParamMapping } from '../common/index';\nimport { NetParams } from './types';\n\nexport function extractParams(weights: Float32Array, channelsIn: number, channelsOut: number): { params: NetParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractWeights,\n getRemainingWeights,\n } = extractWeightsFactory(weights);\n\n const extractFCParams = extractFCParamsFactory(extractWeights, paramMappings);\n\n const fc = extractFCParams(channelsIn, channelsOut, 'fc');\n\n if (getRemainingWeights().length !== 0) {\n throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`);\n }\n\n return {\n paramMappings,\n params: { fc },\n };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport {\n disposeUnusedWeightTensors, extractWeightEntryFactory, FCParams, ParamMapping,\n} from '../common/index';\nimport { NetParams } from './types';\n\nexport function extractParamsFromWeightMap(\n weightMap: tf.NamedTensorMap,\n): { params: NetParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings);\n\n function extractFcParams(prefix: string): FCParams {\n const weights = extractWeightEntry(`${prefix}/weights`, 2);\n const bias = extractWeightEntry(`${prefix}/bias`, 1);\n return { weights, bias };\n }\n\n const params = {\n fc: extractFcParams('fc'),\n };\n\n disposeUnusedWeightTensors(weightMap, paramMappings);\n\n return { params, paramMappings };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nexport function seperateWeightMaps(weightMap: tf.NamedTensorMap) {\n const featureExtractorMap: tf.NamedTensorMap = {};\n const classifierMap: tf.NamedTensorMap = {};\n\n Object.keys(weightMap).forEach((key) => {\n const map = key.startsWith('fc') ? classifierMap : featureExtractorMap;\n map[key] = weightMap[key];\n });\n\n return { featureExtractorMap, classifierMap };\n}\n", "export const FACE_EXPRESSION_LABELS = ['neutral', 'happy', 'sad', 'angry', 'fearful', 'disgusted', 'surprised'];\n\nexport class FaceExpressions {\n public neutral: number\n\n public happy: number\n\n public sad: number\n\n public angry: number\n\n public fearful: number\n\n public disgusted: number\n\n public surprised: number\n\n constructor(probabilities: number[] | Float32Array) {\n if (probabilities.length !== 7) {\n throw new Error(`FaceExpressions.constructor - expected probabilities.length to be 7, have: ${probabilities.length}`);\n }\n\n FACE_EXPRESSION_LABELS.forEach((expression, idx) => {\n this[expression] = probabilities[idx];\n });\n }\n\n asSortedArray() {\n return FACE_EXPRESSION_LABELS\n .map((expression) => ({ expression, probability: this[expression] as number }))\n .sort((e0, e1) => e1.probability - e0.probability);\n }\n}\n", "import { FaceExpressions } from '../faceExpressionNet/FaceExpressions';\n\nexport type WithFaceExpressions = TSource & {\n expressions: FaceExpressions\n}\n\nexport function isWithFaceExpressions(obj: any): obj is WithFaceExpressions<{}> {\n return obj.expressions instanceof FaceExpressions;\n}\n\nexport function extendWithFaceExpressions<\n TSource\n>(\n sourceObj: TSource,\n expressions: FaceExpressions,\n): WithFaceExpressions {\n const extension = { expressions };\n return { ...sourceObj, ...extension };\n}\n", "import { IPoint, Point } from '../classes/index';\nimport { FaceExpressions } from '../faceExpressionNet/index';\nimport { isWithFaceDetection } from '../factories/WithFaceDetection';\nimport { isWithFaceExpressions, WithFaceExpressions } from '../factories/WithFaceExpressions';\nimport { round } from '../utils/index';\nimport { DrawTextField } from './DrawTextField';\n\nexport type DrawFaceExpressionsInput = FaceExpressions | WithFaceExpressions<{}>\n\nexport function drawFaceExpressions(\n canvasArg: string | HTMLCanvasElement,\n faceExpressions: DrawFaceExpressionsInput | Array,\n minConfidence = 0.1,\n textFieldAnchor?: IPoint,\n) {\n const faceExpressionsArray = Array.isArray(faceExpressions) ? faceExpressions : [faceExpressions];\n\n faceExpressionsArray.forEach((e) => {\n // eslint-disable-next-line no-nested-ternary\n const expr = e instanceof FaceExpressions\n ? e\n : (isWithFaceExpressions(e) ? e.expressions : undefined);\n if (!expr) {\n throw new Error('drawFaceExpressions - expected faceExpressions to be FaceExpressions | WithFaceExpressions<{}> or array thereof');\n }\n\n const sorted = expr.asSortedArray();\n const resultsToDisplay = sorted.filter((exprLocal) => exprLocal.probability > minConfidence);\n\n const anchor = isWithFaceDetection(e)\n ? e.detection.box.bottomLeft\n : (textFieldAnchor || new Point(0, 0));\n\n const drawTextField = new DrawTextField(\n resultsToDisplay.map((exprLocal) => `${exprLocal.expression} (${round(exprLocal.probability)})`),\n anchor,\n );\n drawTextField.draw(canvasArg);\n });\n}\n", "import { FaceDetection } from '../classes/FaceDetection';\nimport { FaceLandmarks } from '../classes/FaceLandmarks';\nimport { FaceLandmarks68 } from '../classes/FaceLandmarks68';\nimport { isWithFaceDetection, WithFaceDetection } from './WithFaceDetection';\n\nexport type WithFaceLandmarks<\n TSource extends WithFaceDetection<{}>,\n TFaceLandmarks extends FaceLandmarks = FaceLandmarks68 > = TSource & {\n landmarks: TFaceLandmarks,\n unshiftedLandmarks: TFaceLandmarks,\n alignedRect: FaceDetection,\n angle: { roll: number | undefined, pitch: number | undefined, yaw: number | undefined },\n }\n\nexport function isWithFaceLandmarks(obj: any): obj is WithFaceLandmarks, FaceLandmarks> {\n return isWithFaceDetection(obj)\n // eslint-disable-next-line dot-notation\n && obj['landmarks'] instanceof FaceLandmarks\n // eslint-disable-next-line dot-notation\n && obj['unshiftedLandmarks'] instanceof FaceLandmarks\n // eslint-disable-next-line dot-notation\n && obj['alignedRect'] instanceof FaceDetection;\n}\n\nfunction calculateFaceAngle(mesh) {\n // returns the angle in the plane (in radians) between the positive x-axis and the ray from (0,0) to the point (x,y)\n const radians = (a1, a2, b1, b2) => (Math.atan2(b2 - a2, b1 - a1) % Math.PI);\n // convert radians to degrees\n // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars\n const degrees = (theta) => (theta * 180) / Math.PI;\n\n const angle = { roll: undefined, pitch: undefined, yaw: undefined };\n\n if (!mesh || !mesh._positions || mesh._positions.length !== 68) return angle;\n const pt = mesh._positions;\n\n // values are in radians in range of -pi/2 to pi/2 which is -90 to +90 degrees\n // value of 0 means center\n\n // roll is face lean from left to right\n // comparing x,y of outside corners of leftEye and rightEye\n angle.roll = -radians(pt[36]._x, pt[36]._y, pt[45]._x, pt[45]._y);\n\n // pitch is face turn from left right\n // comparing x distance of top of nose to left and right edge of face\n // precision is lacking since coordinates are not precise enough\n angle.pitch = radians(0, Math.abs(pt[0]._x - pt[30]._x) / pt[30]._x, Math.PI, Math.abs(pt[16]._x - pt[30]._x) / pt[30]._x);\n\n // yaw is face move from up to down\n // comparing size of the box around the face with top and bottom of detected landmarks\n // silly hack, but this gives us face compression on y-axis\n // e.g., tilting head up hides the forehead that doesn't have any landmarks so ratio drops\n const bottom = pt.reduce((prev, cur) => (prev < cur._y ? prev : cur._y), +Infinity);\n const top = pt.reduce((prev, cur) => (prev > cur._y ? prev : cur._y), -Infinity);\n angle.yaw = Math.PI * (mesh._imgDims._height / (top - bottom) / 1.40 - 1);\n\n return angle;\n}\n\nexport function extendWithFaceLandmarks<\n TSource extends WithFaceDetection<{}>,\n TFaceLandmarks extends FaceLandmarks = FaceLandmarks68 >(sourceObj: TSource, unshiftedLandmarks: TFaceLandmarks): WithFaceLandmarks {\n const { box: shift } = sourceObj.detection;\n const landmarks = unshiftedLandmarks.shiftBy(shift.x, shift.y);\n\n const rect = landmarks.align();\n const { imageDims } = sourceObj.detection;\n const alignedRect = new FaceDetection(sourceObj.detection.score, rect.rescale(imageDims.reverse()), imageDims);\n const angle = calculateFaceAngle(unshiftedLandmarks);\n\n const extension = {\n landmarks,\n unshiftedLandmarks,\n alignedRect,\n angle,\n };\n\n return { ...sourceObj, ...extension };\n}\n", "/* eslint-disable max-classes-per-file */\nimport { IPoint } from '../classes/index';\nimport { FaceLandmarks } from '../classes/FaceLandmarks';\nimport { FaceLandmarks68 } from '../classes/FaceLandmarks68';\nimport { getContext2dOrThrow } from '../dom/getContext2dOrThrow';\nimport { WithFaceDetection } from '../factories/WithFaceDetection';\nimport { isWithFaceLandmarks, WithFaceLandmarks } from '../factories/WithFaceLandmarks';\nimport { drawContour } from './drawContour';\n\nexport interface IDrawFaceLandmarksOptions {\n drawLines?: boolean\n drawPoints?: boolean\n lineWidth?: number\n pointSize?: number\n lineColor?: string\n pointColor?: string\n}\n\nexport class DrawFaceLandmarksOptions {\n public drawLines: boolean\n\n public drawPoints: boolean\n\n public lineWidth: number\n\n public pointSize: number\n\n public lineColor: string\n\n public pointColor: string\n\n constructor(options: IDrawFaceLandmarksOptions = {}) {\n const {\n drawLines = true, drawPoints = true, lineWidth, lineColor, pointSize, pointColor,\n } = options;\n this.drawLines = drawLines;\n this.drawPoints = drawPoints;\n this.lineWidth = lineWidth || 1;\n this.pointSize = pointSize || 2;\n this.lineColor = lineColor || 'rgba(0, 255, 255, 1)';\n this.pointColor = pointColor || 'rgba(255, 0, 255, 1)';\n }\n}\n\nexport class DrawFaceLandmarks {\n public faceLandmarks: FaceLandmarks\n\n public options: DrawFaceLandmarksOptions\n\n constructor(\n faceLandmarks: FaceLandmarks,\n options: IDrawFaceLandmarksOptions = {},\n ) {\n this.faceLandmarks = faceLandmarks;\n this.options = new DrawFaceLandmarksOptions(options);\n }\n\n draw(canvasArg: string | HTMLCanvasElement | CanvasRenderingContext2D) {\n const ctx = getContext2dOrThrow(canvasArg);\n\n const {\n drawLines, drawPoints, lineWidth, lineColor, pointSize, pointColor,\n } = this.options;\n\n if (drawLines && this.faceLandmarks instanceof FaceLandmarks68) {\n ctx.strokeStyle = lineColor;\n ctx.lineWidth = lineWidth;\n drawContour(ctx, this.faceLandmarks.getJawOutline());\n drawContour(ctx, this.faceLandmarks.getLeftEyeBrow());\n drawContour(ctx, this.faceLandmarks.getRightEyeBrow());\n drawContour(ctx, this.faceLandmarks.getNose());\n drawContour(ctx, this.faceLandmarks.getLeftEye(), true);\n drawContour(ctx, this.faceLandmarks.getRightEye(), true);\n drawContour(ctx, this.faceLandmarks.getMouth(), true);\n }\n\n if (drawPoints) {\n ctx.strokeStyle = pointColor;\n ctx.fillStyle = pointColor;\n\n const drawPoint = (pt: IPoint) => {\n ctx.beginPath();\n ctx.arc(pt.x, pt.y, pointSize, 0, 2 * Math.PI);\n ctx.fill();\n };\n this.faceLandmarks.positions.forEach(drawPoint);\n }\n }\n}\n\nexport type DrawFaceLandmarksInput = FaceLandmarks | WithFaceLandmarks>\n\nexport function drawFaceLandmarks(\n canvasArg: string | HTMLCanvasElement,\n faceLandmarks: DrawFaceLandmarksInput | Array,\n) {\n const faceLandmarksArray = Array.isArray(faceLandmarks) ? faceLandmarks : [faceLandmarks];\n faceLandmarksArray.forEach((f) => {\n // eslint-disable-next-line no-nested-ternary\n const landmarks = f instanceof FaceLandmarks\n ? f\n : (isWithFaceLandmarks(f) ? f.landmarks : undefined);\n if (!landmarks) {\n throw new Error('drawFaceLandmarks - expected faceExpressions to be FaceLandmarks | WithFaceLandmarks> or array thereof');\n }\n\n new DrawFaceLandmarks(landmarks).draw(canvasArg);\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { fullyConnectedLayer } from '../common/fullyConnectedLayer';\nimport { seperateWeightMaps } from '../faceProcessor/util';\nimport { TinyXception } from '../xception/TinyXception';\nimport { extractParams } from './extractParams';\nimport { extractParamsFromWeightMap } from './extractParamsFromWeightMap';\nimport {\n AgeAndGenderPrediction, Gender, NetOutput, NetParams,\n} from './types';\nimport { NeuralNetwork } from '../NeuralNetwork';\nimport { NetInput, TNetInput, toNetInput } from '../dom/index';\n\nexport class AgeGenderNet extends NeuralNetwork {\n private _faceFeatureExtractor: TinyXception\n\n constructor(faceFeatureExtractor: TinyXception = new TinyXception(2)) {\n super('AgeGenderNet');\n this._faceFeatureExtractor = faceFeatureExtractor;\n }\n\n public get faceFeatureExtractor(): TinyXception {\n return this._faceFeatureExtractor;\n }\n\n public runNet(input: NetInput | tf.Tensor4D): NetOutput {\n const { params } = this;\n\n if (!params) {\n throw new Error(`${this._name} - load model before inference`);\n }\n\n return tf.tidy(() => {\n const bottleneckFeatures = input instanceof NetInput\n ? this.faceFeatureExtractor.forwardInput(input)\n : input;\n\n const pooled = tf.avgPool(bottleneckFeatures, [7, 7], [2, 2], 'valid').as2D(bottleneckFeatures.shape[0], -1);\n const age = fullyConnectedLayer(pooled, params.fc.age).as1D();\n const gender = fullyConnectedLayer(pooled, params.fc.gender);\n return { age, gender };\n });\n }\n\n public forwardInput(input: NetInput | tf.Tensor4D): NetOutput {\n return tf.tidy(() => {\n const { age, gender } = this.runNet(input);\n return { age, gender: tf.softmax(gender) };\n });\n }\n\n public async forward(input: TNetInput): Promise {\n return this.forwardInput(await toNetInput(input));\n }\n\n public async predictAgeAndGender(input: TNetInput): Promise {\n const netInput = await toNetInput(input);\n const out = await this.forwardInput(netInput);\n\n const ages = tf.unstack(out.age);\n const genders = tf.unstack(out.gender);\n const ageAndGenderTensors = ages.map((ageTensor, i) => ({\n ageTensor,\n genderTensor: genders[i],\n }));\n\n const predictionsByBatch = await Promise.all(\n ageAndGenderTensors.map(async ({ ageTensor, genderTensor }) => {\n const age = (await ageTensor.data())[0];\n const probMale = (await genderTensor.data())[0];\n const isMale = probMale > 0.5;\n const gender = isMale ? Gender.MALE : Gender.FEMALE;\n const genderProbability = isMale ? probMale : (1 - probMale);\n\n ageTensor.dispose();\n genderTensor.dispose();\n return { age, gender, genderProbability };\n }),\n );\n out.age.dispose();\n out.gender.dispose();\n\n return netInput.isBatchInput ? predictionsByBatch as AgeAndGenderPrediction[] : predictionsByBatch[0] as AgeAndGenderPrediction;\n }\n\n protected getDefaultModelName(): string {\n return 'age_gender_model';\n }\n\n public dispose(throwOnRedispose: boolean = true) {\n this.faceFeatureExtractor.dispose(throwOnRedispose);\n super.dispose(throwOnRedispose);\n }\n\n public loadClassifierParams(weights: Float32Array) {\n const { params, paramMappings } = this.extractClassifierParams(weights);\n this._params = params;\n this._paramMappings = paramMappings;\n }\n\n public extractClassifierParams(weights: Float32Array) {\n return extractParams(weights);\n }\n\n protected extractParamsFromWeightMap(weightMap: tf.NamedTensorMap) {\n const { featureExtractorMap, classifierMap } = seperateWeightMaps(weightMap);\n\n this.faceFeatureExtractor.loadFromWeightMap(featureExtractorMap);\n\n return extractParamsFromWeightMap(classifierMap);\n }\n\n protected extractParams(weights: Float32Array) {\n const classifierWeightSize = (512 * 1 + 1) + (512 * 2 + 2);\n\n const featureExtractorWeights = weights.slice(0, weights.length - classifierWeightSize);\n const classifierWeights = weights.slice(weights.length - classifierWeightSize);\n\n this.faceFeatureExtractor.extractWeights(featureExtractorWeights);\n return this.extractClassifierParams(classifierWeights);\n }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { ConvParams, depthwiseSeparableConv } from '../common/index';\nimport { NetInput, TNetInput, toNetInput } from '../dom/index';\nimport { NeuralNetwork } from '../NeuralNetwork';\nimport { normalize } from '../ops/index';\nimport { range } from '../utils/index';\nimport { extractParams } from './extractParams';\nimport { extractParamsFromWeightMap } from './extractParamsFromWeightMap';\nimport { MainBlockParams, ReductionBlockParams, TinyXceptionParams } from './types';\n\nfunction conv(x: tf.Tensor4D, params: ConvParams, stride: [number, number]): tf.Tensor4D {\n return tf.add(tf.conv2d(x, params.filters, stride, 'same'), params.bias);\n}\n\nfunction reductionBlock(x: tf.Tensor4D, params: ReductionBlockParams, isActivateInput: boolean = true): tf.Tensor4D {\n let out = isActivateInput ? tf.relu(x) : x;\n out = depthwiseSeparableConv(out, params.separable_conv0, [1, 1]);\n out = depthwiseSeparableConv(tf.relu(out), params.separable_conv1, [1, 1]);\n out = tf.maxPool(out, [3, 3], [2, 2], 'same');\n out = tf.add(out, conv(x, params.expansion_conv, [2, 2]));\n return out;\n}\n\nfunction mainBlock(x: tf.Tensor4D, params: MainBlockParams): tf.Tensor4D {\n let out = depthwiseSeparableConv(tf.relu(x), params.separable_conv0, [1, 1]);\n out = depthwiseSeparableConv(tf.relu(out), params.separable_conv1, [1, 1]);\n out = depthwiseSeparableConv(tf.relu(out), params.separable_conv2, [1, 1]);\n out = tf.add(out, x);\n return out;\n}\n\nexport class TinyXception extends NeuralNetwork {\n private _numMainBlocks: number\n\n constructor(numMainBlocks: number) {\n super('TinyXception');\n this._numMainBlocks = numMainBlocks;\n }\n\n public forwardInput(input: NetInput): tf.Tensor4D {\n const { params } = this;\n if (!params) {\n throw new Error('TinyXception - load model before inference');\n }\n return tf.tidy(() => {\n const batchTensor = tf.cast(input.toBatchTensor(112, true), 'float32');\n const meanRgb = [122.782, 117.001, 104.298];\n const normalized = normalize(batchTensor, meanRgb).div(tf.scalar(256)) as tf.Tensor4D;\n let out = tf.relu(conv(normalized, params.entry_flow.conv_in, [2, 2]));\n out = reductionBlock(out, params.entry_flow.reduction_block_0, false);\n out = reductionBlock(out, params.entry_flow.reduction_block_1);\n range(this._numMainBlocks, 0, 1).forEach((idx) => {\n out = mainBlock(out, params.middle_flow[`main_block_${idx}`]);\n });\n out = reductionBlock(out, params.exit_flow.reduction_block);\n out = tf.relu(depthwiseSeparableConv(out, params.exit_flow.separable_conv, [1, 1]));\n return out;\n });\n }\n\n public async forward(input: TNetInput): Promise {\n return this.forwardInput(await toNetInput(input));\n }\n\n protected getDefaultModelName(): string {\n return 'tiny_xception_model';\n }\n\n protected extractParamsFromWeightMap(weightMap: tf.NamedTensorMap) {\n return extractParamsFromWeightMap(weightMap, this._numMainBlocks);\n }\n\n protected extractParams(weights: Float32Array) {\n return extractParams(weights, this._numMainBlocks);\n }\n}\n", "import { extractConvParamsFactory, extractSeparableConvParamsFactory, extractWeightsFactory } from '../common/index';\nimport { ExtractWeightsFunction, ParamMapping } from '../common/types';\nimport { range } from '../utils/index';\nimport { MainBlockParams, ReductionBlockParams, TinyXceptionParams } from './types';\n\nfunction extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings: ParamMapping[]) {\n const extractConvParams = extractConvParamsFactory(extractWeights, paramMappings);\n const extractSeparableConvParams = extractSeparableConvParamsFactory(extractWeights, paramMappings);\n\n function extractReductionBlockParams(channelsIn: number, channelsOut: number, mappedPrefix: string): ReductionBlockParams {\n const separable_conv0 = extractSeparableConvParams(channelsIn, channelsOut, `${mappedPrefix}/separable_conv0`);\n const separable_conv1 = extractSeparableConvParams(channelsOut, channelsOut, `${mappedPrefix}/separable_conv1`);\n const expansion_conv = extractConvParams(channelsIn, channelsOut, 1, `${mappedPrefix}/expansion_conv`);\n\n return { separable_conv0, separable_conv1, expansion_conv };\n }\n\n function extractMainBlockParams(channels: number, mappedPrefix: string): MainBlockParams {\n const separable_conv0 = extractSeparableConvParams(channels, channels, `${mappedPrefix}/separable_conv0`);\n const separable_conv1 = extractSeparableConvParams(channels, channels, `${mappedPrefix}/separable_conv1`);\n const separable_conv2 = extractSeparableConvParams(channels, channels, `${mappedPrefix}/separable_conv2`);\n\n return { separable_conv0, separable_conv1, separable_conv2 };\n }\n\n return {\n extractConvParams,\n extractSeparableConvParams,\n extractReductionBlockParams,\n extractMainBlockParams,\n };\n}\n\nexport function extractParams(weights: Float32Array, numMainBlocks: number): { params: TinyXceptionParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractWeights,\n getRemainingWeights,\n } = extractWeightsFactory(weights);\n\n const {\n extractConvParams,\n extractSeparableConvParams,\n extractReductionBlockParams,\n extractMainBlockParams,\n } = extractorsFactory(extractWeights, paramMappings);\n\n const entry_flow_conv_in = extractConvParams(3, 32, 3, 'entry_flow/conv_in');\n const entry_flow_reduction_block_0 = extractReductionBlockParams(32, 64, 'entry_flow/reduction_block_0');\n const entry_flow_reduction_block_1 = extractReductionBlockParams(64, 128, 'entry_flow/reduction_block_1');\n\n const entry_flow = {\n conv_in: entry_flow_conv_in,\n reduction_block_0: entry_flow_reduction_block_0,\n reduction_block_1: entry_flow_reduction_block_1,\n };\n\n const middle_flow = {};\n range(numMainBlocks, 0, 1).forEach((idx) => {\n middle_flow[`main_block_${idx}`] = extractMainBlockParams(128, `middle_flow/main_block_${idx}`);\n });\n\n const exit_flow_reduction_block = extractReductionBlockParams(128, 256, 'exit_flow/reduction_block');\n const exit_flow_separable_conv = extractSeparableConvParams(256, 512, 'exit_flow/separable_conv');\n\n const exit_flow = {\n reduction_block: exit_flow_reduction_block,\n separable_conv: exit_flow_separable_conv,\n };\n\n if (getRemainingWeights().length !== 0) {\n throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`);\n }\n\n return {\n paramMappings,\n params: { entry_flow, middle_flow, exit_flow },\n };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport {\n disposeUnusedWeightTensors,\n extractWeightEntryFactory,\n loadSeparableConvParamsFactory,\n ParamMapping,\n} from '../common/index';\nimport { loadConvParamsFactory } from '../common/loadConvParamsFactory';\nimport { range } from '../utils/index';\nimport { MainBlockParams, ReductionBlockParams, TinyXceptionParams } from './types';\n\nfunction loadParamsFactory(weightMap: any, paramMappings: ParamMapping[]) {\n const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings);\n\n const extractConvParams = loadConvParamsFactory(extractWeightEntry);\n const extractSeparableConvParams = loadSeparableConvParamsFactory(extractWeightEntry);\n\n function extractReductionBlockParams(mappedPrefix: string): ReductionBlockParams {\n const separable_conv0 = extractSeparableConvParams(`${mappedPrefix}/separable_conv0`);\n const separable_conv1 = extractSeparableConvParams(`${mappedPrefix}/separable_conv1`);\n const expansion_conv = extractConvParams(`${mappedPrefix}/expansion_conv`);\n\n return { separable_conv0, separable_conv1, expansion_conv };\n }\n\n function extractMainBlockParams(mappedPrefix: string): MainBlockParams {\n const separable_conv0 = extractSeparableConvParams(`${mappedPrefix}/separable_conv0`);\n const separable_conv1 = extractSeparableConvParams(`${mappedPrefix}/separable_conv1`);\n const separable_conv2 = extractSeparableConvParams(`${mappedPrefix}/separable_conv2`);\n\n return { separable_conv0, separable_conv1, separable_conv2 };\n }\n\n return {\n extractConvParams,\n extractSeparableConvParams,\n extractReductionBlockParams,\n extractMainBlockParams,\n };\n}\n\nexport function extractParamsFromWeightMap(\n weightMap: tf.NamedTensorMap,\n numMainBlocks: number,\n): { params: TinyXceptionParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractConvParams,\n extractSeparableConvParams,\n extractReductionBlockParams,\n extractMainBlockParams,\n } = loadParamsFactory(weightMap, paramMappings);\n\n const entry_flow_conv_in = extractConvParams('entry_flow/conv_in');\n const entry_flow_reduction_block_0 = extractReductionBlockParams('entry_flow/reduction_block_0');\n const entry_flow_reduction_block_1 = extractReductionBlockParams('entry_flow/reduction_block_1');\n\n const entry_flow = {\n conv_in: entry_flow_conv_in,\n reduction_block_0: entry_flow_reduction_block_0,\n reduction_block_1: entry_flow_reduction_block_1,\n };\n\n const middle_flow = {};\n range(numMainBlocks, 0, 1).forEach((idx) => {\n middle_flow[`main_block_${idx}`] = extractMainBlockParams(`middle_flow/main_block_${idx}`);\n });\n\n const exit_flow_reduction_block = extractReductionBlockParams('exit_flow/reduction_block');\n const exit_flow_separable_conv = extractSeparableConvParams('exit_flow/separable_conv');\n\n const exit_flow = {\n reduction_block: exit_flow_reduction_block,\n separable_conv: exit_flow_separable_conv,\n };\n\n disposeUnusedWeightTensors(weightMap, paramMappings);\n\n return { params: { entry_flow, middle_flow, exit_flow }, paramMappings };\n}\n", "import { extractFCParamsFactory, extractWeightsFactory, ParamMapping } from '../common/index';\nimport { NetParams } from './types';\n\nexport function extractParams(weights: Float32Array): { params: NetParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractWeights,\n getRemainingWeights,\n } = extractWeightsFactory(weights);\n\n const extractFCParams = extractFCParamsFactory(extractWeights, paramMappings);\n\n const age = extractFCParams(512, 1, 'fc/age');\n const gender = extractFCParams(512, 2, 'fc/gender');\n\n if (getRemainingWeights().length !== 0) {\n throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`);\n }\n\n return {\n paramMappings,\n params: { fc: { age, gender } },\n };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport {\n disposeUnusedWeightTensors, extractWeightEntryFactory, FCParams, ParamMapping,\n} from '../common/index';\nimport { NetParams } from './types';\n\nexport function extractParamsFromWeightMap(\n weightMap: tf.NamedTensorMap,\n): { params: NetParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings);\n\n function extractFcParams(prefix: string): FCParams {\n const weights = extractWeightEntry(`${prefix}/weights`, 2);\n const bias = extractWeightEntry(`${prefix}/bias`, 1);\n return { weights, bias };\n }\n\n const params = {\n fc: {\n age: extractFcParams('fc/age'),\n gender: extractFcParams('fc/gender'),\n },\n };\n\n disposeUnusedWeightTensors(weightMap, paramMappings);\n\n return { params, paramMappings };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { FCParams } from '../common/index';\n\n// eslint-disable-next-line no-shadow\nexport enum Gender {\n // eslint-disable-next-line no-unused-vars\n FEMALE = 'female',\n // eslint-disable-next-line no-unused-vars\n MALE = 'male'\n}\n\nexport type AgeAndGenderPrediction = {\n age: number\n gender: Gender\n genderProbability: number\n}\n\nexport type NetOutput = { age: tf.Tensor1D, gender: tf.Tensor2D }\n\nexport type NetParams = {\n fc: {\n age: FCParams\n gender: FCParams\n }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { IDimensions, Point } from '../classes/index';\nimport { FaceLandmarks68 } from '../classes/FaceLandmarks68';\nimport { NetInput, TNetInput, toNetInput } from '../dom/index';\nimport { FaceFeatureExtractorParams, TinyFaceFeatureExtractorParams } from '../faceFeatureExtractor/types';\nimport { FaceProcessor } from '../faceProcessor/FaceProcessor';\nimport { isEven } from '../utils/index';\n\nexport abstract class FaceLandmark68NetBase<\n TExtractorParams extends FaceFeatureExtractorParams | TinyFaceFeatureExtractorParams\n>\n extends FaceProcessor {\n public postProcess(output: tf.Tensor2D, inputSize: number, originalDimensions: IDimensions[]): tf.Tensor2D {\n const inputDimensions = originalDimensions.map(({ width, height }) => {\n const scale = inputSize / Math.max(height, width);\n return {\n width: width * scale,\n height: height * scale,\n };\n });\n\n const batchSize = inputDimensions.length;\n\n return tf.tidy(() => {\n const createInterleavedTensor = (fillX: number, fillY: number) => tf.stack([tf.fill([68], fillX, 'float32'), tf.fill([68], fillY, 'float32')], 1).as2D(1, 136).as1D();\n\n // eslint-disable-next-line no-unused-vars\n const getPadding = (batchIdx: number, cond: (w: number, h: number) => boolean): number => {\n const { width, height } = inputDimensions[batchIdx];\n return cond(width, height) ? Math.abs(width - height) / 2 : 0;\n };\n\n const getPaddingX = (batchIdx: number) => getPadding(batchIdx, (w, h) => w < h);\n const getPaddingY = (batchIdx: number) => getPadding(batchIdx, (w, h) => h < w);\n\n const landmarkTensors = output\n .mul(tf.fill([batchSize, 136], inputSize, 'float32'))\n .sub(tf.stack(Array.from(Array(batchSize), (_, batchIdx) => createInterleavedTensor(\n getPaddingX(batchIdx),\n getPaddingY(batchIdx),\n ))))\n .div(tf.stack(Array.from(Array(batchSize), (_, batchIdx) => createInterleavedTensor(\n inputDimensions[batchIdx].width,\n inputDimensions[batchIdx].height,\n ))));\n\n return landmarkTensors as tf.Tensor2D;\n });\n }\n\n public forwardInput(input: NetInput): tf.Tensor2D {\n return tf.tidy(() => {\n const out = this.runNet(input);\n return this.postProcess(\n out,\n input.inputSize as number,\n input.inputDimensions.map(([height, width]) => ({ height, width })),\n );\n });\n }\n\n public async forward(input: TNetInput): Promise {\n return this.forwardInput(await toNetInput(input));\n }\n\n public async detectLandmarks(input: TNetInput): Promise {\n const netInput = await toNetInput(input);\n const landmarkTensors = tf.tidy(\n () => tf.unstack(this.forwardInput(netInput)),\n );\n\n const landmarksForBatch = await Promise.all(landmarkTensors.map(\n async (landmarkTensor, batchIdx) => {\n const landmarksArray = Array.from(await landmarkTensor.data());\n const xCoords = landmarksArray.filter((_, i) => isEven(i));\n const yCoords = landmarksArray.filter((_, i) => !isEven(i));\n\n return new FaceLandmarks68(\n Array(68).fill(0).map((_, i) => new Point(xCoords[i] as number, yCoords[i] as number)),\n {\n height: netInput.getInputHeight(batchIdx),\n width: netInput.getInputWidth(batchIdx),\n },\n );\n },\n ));\n\n landmarkTensors.forEach((t) => t.dispose());\n\n return netInput.isBatchInput ? landmarksForBatch as FaceLandmarks68[] : landmarksForBatch[0] as FaceLandmarks68;\n }\n\n protected getClassifierChannelsOut(): number {\n return 136;\n }\n}\n", "import { FaceFeatureExtractor } from '../faceFeatureExtractor/FaceFeatureExtractor';\nimport { FaceFeatureExtractorParams } from '../faceFeatureExtractor/types';\nimport { FaceLandmark68NetBase } from './FaceLandmark68NetBase';\n\nexport class FaceLandmark68Net extends FaceLandmark68NetBase {\n constructor(faceFeatureExtractor: FaceFeatureExtractor = new FaceFeatureExtractor()) {\n super('FaceLandmark68Net', faceFeatureExtractor);\n }\n\n protected getDefaultModelName(): string {\n return 'face_landmark_68_model';\n }\n\n protected getClassifierChannelsIn(): number {\n return 256;\n }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { NetInput, TNetInput, toNetInput } from '../dom/index';\nimport { NeuralNetwork } from '../NeuralNetwork';\nimport { normalize } from '../ops/index';\nimport { denseBlock3 } from './denseBlock';\nimport { extractParamsFromWeightMapTiny } from './extractParamsFromWeightMapTiny';\nimport { extractParamsTiny } from './extractParamsTiny';\nimport { IFaceFeatureExtractor, TinyFaceFeatureExtractorParams } from './types';\n\nexport class TinyFaceFeatureExtractor extends NeuralNetwork implements IFaceFeatureExtractor {\n constructor() {\n super('TinyFaceFeatureExtractor');\n }\n\n public forwardInput(input: NetInput): tf.Tensor4D {\n const { params } = this;\n\n if (!params) {\n throw new Error('TinyFaceFeatureExtractor - load model before inference');\n }\n\n return tf.tidy(() => {\n const batchTensor = tf.cast(input.toBatchTensor(112, true), 'float32');\n const meanRgb = [122.782, 117.001, 104.298];\n const normalized = normalize(batchTensor, meanRgb).div(tf.scalar(255)) as tf.Tensor4D;\n\n let out = denseBlock3(normalized, params.dense0, true);\n out = denseBlock3(out, params.dense1);\n out = denseBlock3(out, params.dense2);\n out = tf.avgPool(out, [14, 14], [2, 2], 'valid');\n\n return out;\n });\n }\n\n public async forward(input: TNetInput): Promise {\n return this.forwardInput(await toNetInput(input));\n }\n\n protected getDefaultModelName(): string {\n return 'face_feature_extractor_tiny_model';\n }\n\n protected extractParamsFromWeightMap(weightMap: tf.NamedTensorMap) {\n return extractParamsFromWeightMapTiny(weightMap);\n }\n\n protected extractParams(weights: Float32Array) {\n return extractParamsTiny(weights);\n }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { disposeUnusedWeightTensors, ParamMapping } from '../common/index';\nimport { loadParamsFactory } from './loadParamsFactory';\nimport { TinyFaceFeatureExtractorParams } from './types';\n\nexport function extractParamsFromWeightMapTiny(\n weightMap: tf.NamedTensorMap,\n): { params: TinyFaceFeatureExtractorParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractDenseBlock3Params,\n } = loadParamsFactory(weightMap, paramMappings);\n\n const params = {\n dense0: extractDenseBlock3Params('dense0', true),\n dense1: extractDenseBlock3Params('dense1'),\n dense2: extractDenseBlock3Params('dense2'),\n };\n\n disposeUnusedWeightTensors(weightMap, paramMappings);\n\n return { params, paramMappings };\n}\n", "import { extractWeightsFactory, ParamMapping } from '../common/index';\nimport { extractorsFactory } from './extractorsFactory';\nimport { TinyFaceFeatureExtractorParams } from './types';\n\nexport function extractParamsTiny(weights: Float32Array): { params: TinyFaceFeatureExtractorParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractWeights,\n getRemainingWeights,\n } = extractWeightsFactory(weights);\n\n const {\n extractDenseBlock3Params,\n } = extractorsFactory(extractWeights, paramMappings);\n\n const dense0 = extractDenseBlock3Params(3, 32, 'dense0', true);\n const dense1 = extractDenseBlock3Params(32, 64, 'dense1');\n const dense2 = extractDenseBlock3Params(64, 128, 'dense2');\n\n if (getRemainingWeights().length !== 0) {\n throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`);\n }\n\n return {\n paramMappings,\n params: { dense0, dense1, dense2 },\n };\n}\n", "import { TinyFaceFeatureExtractor } from '../faceFeatureExtractor/TinyFaceFeatureExtractor';\nimport { TinyFaceFeatureExtractorParams } from '../faceFeatureExtractor/types';\nimport { FaceLandmark68NetBase } from './FaceLandmark68NetBase';\n\nexport class FaceLandmark68TinyNet extends FaceLandmark68NetBase {\n constructor(faceFeatureExtractor: TinyFaceFeatureExtractor = new TinyFaceFeatureExtractor()) {\n super('FaceLandmark68TinyNet', faceFeatureExtractor);\n }\n\n protected getDefaultModelName(): string {\n return 'face_landmark_68_tiny_model';\n }\n\n protected getClassifierChannelsIn(): number {\n return 128;\n }\n}\n", "import { FaceLandmark68Net } from './FaceLandmark68Net';\n\nexport * from './FaceLandmark68Net';\nexport * from './FaceLandmark68TinyNet';\nexport class FaceLandmarkNet extends FaceLandmark68Net {}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { NetInput, TNetInput, toNetInput } from '../dom/index';\nimport { NeuralNetwork } from '../NeuralNetwork';\nimport { normalize } from '../ops/index';\nimport { convDown } from './convLayer';\nimport { extractParams } from './extractParams';\nimport { extractParamsFromWeightMap } from './extractParamsFromWeightMap';\nimport { residual, residualDown } from './residualLayer';\nimport { NetParams } from './types';\n\nexport class FaceRecognitionNet extends NeuralNetwork {\n constructor() {\n super('FaceRecognitionNet');\n }\n\n public forwardInput(input: NetInput): tf.Tensor2D {\n const { params } = this;\n\n if (!params) {\n throw new Error('FaceRecognitionNet - load model before inference');\n }\n\n return tf.tidy(() => {\n const batchTensor = tf.cast(input.toBatchTensor(150, true), 'float32');\n\n const meanRgb = [122.782, 117.001, 104.298];\n const normalized = normalize(batchTensor, meanRgb).div(tf.scalar(256)) as tf.Tensor4D;\n\n let out = convDown(normalized, params.conv32_down);\n out = tf.maxPool(out, 3, 2, 'valid');\n\n out = residual(out, params.conv32_1);\n out = residual(out, params.conv32_2);\n out = residual(out, params.conv32_3);\n\n out = residualDown(out, params.conv64_down);\n out = residual(out, params.conv64_1);\n out = residual(out, params.conv64_2);\n out = residual(out, params.conv64_3);\n\n out = residualDown(out, params.conv128_down);\n out = residual(out, params.conv128_1);\n out = residual(out, params.conv128_2);\n\n out = residualDown(out, params.conv256_down);\n out = residual(out, params.conv256_1);\n out = residual(out, params.conv256_2);\n out = residualDown(out, params.conv256_down_out);\n\n const globalAvg = out.mean([1, 2]) as tf.Tensor2D;\n const fullyConnected = tf.matMul(globalAvg, params.fc);\n\n return fullyConnected;\n });\n }\n\n public async forward(input: TNetInput): Promise {\n return this.forwardInput(await toNetInput(input));\n }\n\n public async computeFaceDescriptor(input: TNetInput): Promise {\n if (input?.shape?.some((dim) => dim <= 0)) return new Float32Array(128);\n const netInput = await toNetInput(input);\n const faceDescriptorTensors = tf.tidy(\n () => tf.unstack(this.forwardInput(netInput)),\n );\n const faceDescriptorsForBatch = await Promise.all(faceDescriptorTensors.map((t) => t.data())) as Float32Array[];\n faceDescriptorTensors.forEach((t) => t.dispose());\n return netInput.isBatchInput ? faceDescriptorsForBatch : faceDescriptorsForBatch[0];\n }\n\n protected getDefaultModelName(): string {\n return 'face_recognition_model';\n }\n\n protected extractParamsFromWeightMap(weightMap: tf.NamedTensorMap) {\n return extractParamsFromWeightMap(weightMap);\n }\n\n protected extractParams(weights: Float32Array) {\n return extractParams(weights);\n }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { scale } from './scaleLayer';\nimport { ConvLayerParams } from './types';\n\nfunction convLayer(\n x: tf.Tensor4D,\n params: ConvLayerParams,\n strides: [number, number],\n withRelu: boolean,\n padding: 'valid' | 'same' = 'same',\n): tf.Tensor4D {\n const { filters, bias } = params.conv;\n\n let out = tf.conv2d(x, filters, strides, padding);\n out = tf.add(out, bias);\n out = scale(out, params.scale);\n return withRelu ? tf.relu(out) : out;\n}\n\nexport function conv(x: tf.Tensor4D, params: ConvLayerParams) {\n return convLayer(x, params, [1, 1], true);\n}\n\nexport function convNoRelu(x: tf.Tensor4D, params: ConvLayerParams) {\n return convLayer(x, params, [1, 1], false);\n}\n\nexport function convDown(x: tf.Tensor4D, params: ConvLayerParams) {\n return convLayer(x, params, [2, 2], true, 'valid');\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { ScaleLayerParams } from './types';\n\nexport function scale(x: tf.Tensor4D, params: ScaleLayerParams): tf.Tensor4D {\n return tf.add(tf.mul(x, params.weights), params.biases);\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport {\n ConvParams, extractWeightsFactory, ExtractWeightsFunction, ParamMapping,\n} from '../common/index';\nimport { isFloat } from '../utils/index';\nimport {\n ConvLayerParams, NetParams, ResidualLayerParams, ScaleLayerParams,\n} from './types';\n\nfunction extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings: ParamMapping[]) {\n function extractFilterValues(numFilterValues: number, numFilters: number, filterSize: number): tf.Tensor4D {\n const weights = extractWeights(numFilterValues);\n const depth = weights.length / (numFilters * filterSize * filterSize);\n\n if (isFloat(depth)) {\n throw new Error(`depth has to be an integer: ${depth}, weights.length: ${weights.length}, numFilters: ${numFilters}, filterSize: ${filterSize}`);\n }\n\n return tf.tidy(\n () => tf.transpose(\n tf.tensor4d(weights, [numFilters, depth, filterSize, filterSize]),\n [2, 3, 1, 0],\n ),\n );\n }\n\n function extractConvParams(\n numFilterValues: number,\n numFilters: number,\n filterSize: number,\n mappedPrefix: string,\n ): ConvParams {\n const filters = extractFilterValues(numFilterValues, numFilters, filterSize);\n const bias = tf.tensor1d(extractWeights(numFilters));\n\n paramMappings.push(\n { paramPath: `${mappedPrefix}/filters` },\n { paramPath: `${mappedPrefix}/bias` },\n );\n\n return { filters, bias };\n }\n\n function extractScaleLayerParams(numWeights: number, mappedPrefix: string): ScaleLayerParams {\n const weights = tf.tensor1d(extractWeights(numWeights));\n const biases = tf.tensor1d(extractWeights(numWeights));\n\n paramMappings.push(\n { paramPath: `${mappedPrefix}/weights` },\n { paramPath: `${mappedPrefix}/biases` },\n );\n\n return {\n weights,\n biases,\n };\n }\n\n function extractConvLayerParams(\n numFilterValues: number,\n numFilters: number,\n filterSize: number,\n mappedPrefix: string,\n ): ConvLayerParams {\n const conv = extractConvParams(numFilterValues, numFilters, filterSize, `${mappedPrefix}/conv`);\n const scale = extractScaleLayerParams(numFilters, `${mappedPrefix}/scale`);\n\n return { conv, scale };\n }\n\n function extractResidualLayerParams(\n numFilterValues: number,\n numFilters: number,\n filterSize: number,\n mappedPrefix: string,\n isDown: boolean = false,\n ): ResidualLayerParams {\n const conv1 = extractConvLayerParams((isDown ? 0.5 : 1) * numFilterValues, numFilters, filterSize, `${mappedPrefix}/conv1`);\n const conv2 = extractConvLayerParams(numFilterValues, numFilters, filterSize, `${mappedPrefix}/conv2`);\n\n return { conv1, conv2 };\n }\n\n return {\n extractConvLayerParams,\n extractResidualLayerParams,\n };\n}\n\nexport function extractParams(weights: Float32Array): { params: NetParams, paramMappings: ParamMapping[] } {\n const {\n extractWeights,\n getRemainingWeights,\n } = extractWeightsFactory(weights);\n\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractConvLayerParams,\n extractResidualLayerParams,\n } = extractorsFactory(extractWeights, paramMappings);\n\n const conv32_down = extractConvLayerParams(4704, 32, 7, 'conv32_down');\n const conv32_1 = extractResidualLayerParams(9216, 32, 3, 'conv32_1');\n const conv32_2 = extractResidualLayerParams(9216, 32, 3, 'conv32_2');\n const conv32_3 = extractResidualLayerParams(9216, 32, 3, 'conv32_3');\n\n const conv64_down = extractResidualLayerParams(36864, 64, 3, 'conv64_down', true);\n const conv64_1 = extractResidualLayerParams(36864, 64, 3, 'conv64_1');\n const conv64_2 = extractResidualLayerParams(36864, 64, 3, 'conv64_2');\n const conv64_3 = extractResidualLayerParams(36864, 64, 3, 'conv64_3');\n\n const conv128_down = extractResidualLayerParams(147456, 128, 3, 'conv128_down', true);\n const conv128_1 = extractResidualLayerParams(147456, 128, 3, 'conv128_1');\n const conv128_2 = extractResidualLayerParams(147456, 128, 3, 'conv128_2');\n\n const conv256_down = extractResidualLayerParams(589824, 256, 3, 'conv256_down', true);\n const conv256_1 = extractResidualLayerParams(589824, 256, 3, 'conv256_1');\n const conv256_2 = extractResidualLayerParams(589824, 256, 3, 'conv256_2');\n const conv256_down_out = extractResidualLayerParams(589824, 256, 3, 'conv256_down_out');\n\n const fc = tf.tidy(\n () => tf.transpose(tf.tensor2d(extractWeights(256 * 128), [128, 256]), [1, 0]),\n );\n paramMappings.push({ paramPath: 'fc' });\n\n if (getRemainingWeights().length !== 0) {\n throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`);\n }\n\n const params = {\n conv32_down,\n conv32_1,\n conv32_2,\n conv32_3,\n conv64_down,\n conv64_1,\n conv64_2,\n conv64_3,\n conv128_down,\n conv128_1,\n conv128_2,\n conv256_down,\n conv256_1,\n conv256_2,\n conv256_down_out,\n fc,\n };\n\n return { params, paramMappings };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { disposeUnusedWeightTensors, extractWeightEntryFactory, ParamMapping } from '../common/index';\nimport { isTensor2D } from '../utils/index';\nimport { ConvLayerParams, NetParams, ResidualLayerParams, ScaleLayerParams } from './types';\n\nfunction extractorsFactory(weightMap: any, paramMappings: ParamMapping[]) {\n const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings);\n\n function extractScaleLayerParams(prefix: string): ScaleLayerParams {\n const weights = extractWeightEntry(`${prefix}/scale/weights`, 1);\n const biases = extractWeightEntry(`${prefix}/scale/biases`, 1);\n\n return { weights, biases };\n }\n\n function extractConvLayerParams(prefix: string): ConvLayerParams {\n const filters = extractWeightEntry(`${prefix}/conv/filters`, 4);\n const bias = extractWeightEntry(`${prefix}/conv/bias`, 1);\n const scale = extractScaleLayerParams(prefix);\n\n return { conv: { filters, bias }, scale };\n }\n\n function extractResidualLayerParams(prefix: string): ResidualLayerParams {\n return {\n conv1: extractConvLayerParams(`${prefix}/conv1`),\n conv2: extractConvLayerParams(`${prefix}/conv2`),\n };\n }\n\n return {\n extractConvLayerParams,\n extractResidualLayerParams,\n };\n}\n\nexport function extractParamsFromWeightMap(\n weightMap: tf.NamedTensorMap,\n): { params: NetParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractConvLayerParams,\n extractResidualLayerParams,\n } = extractorsFactory(weightMap, paramMappings);\n\n const conv32_down = extractConvLayerParams('conv32_down');\n const conv32_1 = extractResidualLayerParams('conv32_1');\n const conv32_2 = extractResidualLayerParams('conv32_2');\n const conv32_3 = extractResidualLayerParams('conv32_3');\n\n const conv64_down = extractResidualLayerParams('conv64_down');\n const conv64_1 = extractResidualLayerParams('conv64_1');\n const conv64_2 = extractResidualLayerParams('conv64_2');\n const conv64_3 = extractResidualLayerParams('conv64_3');\n\n const conv128_down = extractResidualLayerParams('conv128_down');\n const conv128_1 = extractResidualLayerParams('conv128_1');\n const conv128_2 = extractResidualLayerParams('conv128_2');\n\n const conv256_down = extractResidualLayerParams('conv256_down');\n const conv256_1 = extractResidualLayerParams('conv256_1');\n const conv256_2 = extractResidualLayerParams('conv256_2');\n const conv256_down_out = extractResidualLayerParams('conv256_down_out');\n\n const { fc } = weightMap;\n paramMappings.push({ originalPath: 'fc', paramPath: 'fc' });\n\n if (!isTensor2D(fc)) {\n throw new Error(`expected weightMap[fc] to be a Tensor2D, instead have ${fc}`);\n }\n\n const params = {\n conv32_down,\n conv32_1,\n conv32_2,\n conv32_3,\n conv64_down,\n conv64_1,\n conv64_2,\n conv64_3,\n conv128_down,\n conv128_1,\n conv128_2,\n conv256_down,\n conv256_1,\n conv256_2,\n conv256_down_out,\n fc,\n };\n\n disposeUnusedWeightTensors(weightMap, paramMappings);\n\n return { params, paramMappings };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { conv, convDown, convNoRelu } from './convLayer';\nimport { ResidualLayerParams } from './types';\n\nexport function residual(x: tf.Tensor4D, params: ResidualLayerParams): tf.Tensor4D {\n let out = conv(x, params.conv1);\n out = convNoRelu(out, params.conv2);\n out = tf.add(out, x);\n out = tf.relu(out);\n return out;\n}\n\nexport function residualDown(x: tf.Tensor4D, params: ResidualLayerParams): tf.Tensor4D {\n let out = convDown(x, params.conv1);\n out = convNoRelu(out, params.conv2);\n\n let pooled = tf.avgPool(x, 2, 2, 'valid') as tf.Tensor4D;\n const zeros = tf.zeros(pooled.shape);\n const isPad = pooled.shape[3] !== out.shape[3];\n const isAdjustShape = pooled.shape[1] !== out.shape[1] || pooled.shape[2] !== out.shape[2];\n\n if (isAdjustShape) {\n const padShapeX = [...out.shape] as [number, number, number, number];\n padShapeX[1] = 1;\n const zerosW = tf.zeros(padShapeX);\n out = tf.concat([out, zerosW], 1);\n\n const padShapeY = [...out.shape] as [number, number, number, number];\n padShapeY[2] = 1;\n const zerosH = tf.zeros(padShapeY);\n out = tf.concat([out, zerosH], 2);\n }\n\n pooled = isPad ? tf.concat([pooled, zeros], 3) : pooled;\n out = tf.add(pooled, out) as tf.Tensor4D;\n\n out = tf.relu(out);\n return out;\n}\n", "import { FaceRecognitionNet } from './FaceRecognitionNet';\n\nexport * from './FaceRecognitionNet';\n\nexport function createFaceRecognitionNet(weights: Float32Array) {\n const net = new FaceRecognitionNet();\n net.extractWeights(weights);\n return net;\n}\n", "export type WithFaceDescriptor = TSource & {\n descriptor: Float32Array\n}\n\nexport function extendWithFaceDescriptor<\n TSource\n>(\n sourceObj: TSource,\n descriptor: Float32Array,\n): WithFaceDescriptor {\n const extension = { descriptor };\n return { ...sourceObj, ...extension };\n}\n", "export type WithAge = TSource & {\n age: number\n}\n\nexport function isWithAge(obj: any): obj is WithAge<{}> {\n return typeof obj.age === 'number';\n}\n\nexport function extendWithAge<\n TSource\n>(\n sourceObj: TSource,\n age: number,\n): WithAge {\n const extension = { age };\n return { ...sourceObj, ...extension };\n}\n", "import { Gender } from '../ageGenderNet/types';\nimport { isValidProbablitiy } from '../utils/index';\n\nexport type WithGender = TSource & {\n gender: Gender\n genderProbability: number\n}\n\nexport function isWithGender(obj: any): obj is WithGender<{}> {\n return (obj.gender === Gender.MALE || obj.gender === Gender.FEMALE)\n && isValidProbablitiy(obj.genderProbability);\n}\n\nexport function extendWithGender<\n TSource\n>(\n sourceObj: TSource,\n gender: Gender,\n genderProbability: number,\n): WithGender {\n const extension = { gender, genderProbability };\n return { ...sourceObj, ...extension };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { Rect } from '../classes/index';\nimport { FaceDetection } from '../classes/FaceDetection';\nimport { NetInput, TNetInput, toNetInput } from '../dom/index';\nimport { NeuralNetwork } from '../NeuralNetwork';\nimport { extractParams } from './extractParams';\nimport { extractParamsFromWeightMap } from './extractParamsFromWeightMap';\nimport { mobileNetV1 } from './mobileNetV1';\nimport { nonMaxSuppression } from './nonMaxSuppression';\nimport { outputLayer } from './outputLayer';\nimport { predictionLayer } from './predictionLayer';\nimport { ISsdMobilenetv1Options, SsdMobilenetv1Options } from './SsdMobilenetv1Options';\nimport { NetParams } from './types';\n\nexport class SsdMobilenetv1 extends NeuralNetwork {\n constructor() {\n super('SsdMobilenetv1');\n }\n\n public forwardInput(input: NetInput) {\n const { params } = this;\n\n if (!params) {\n throw new Error('SsdMobilenetv1 - load model before inference');\n }\n\n return tf.tidy(() => {\n const batchTensor = tf.cast(input.toBatchTensor(512, false), 'float32');\n const x = tf.sub(tf.mul(batchTensor, tf.scalar(0.007843137718737125)), tf.scalar(1)) as tf.Tensor4D;\n const features = mobileNetV1(x, params.mobilenetv1);\n\n const { boxPredictions, classPredictions } = predictionLayer(features.out, features.conv11, params.prediction_layer);\n\n return outputLayer(boxPredictions, classPredictions, params.output_layer);\n });\n }\n\n public async forward(input: TNetInput) {\n return this.forwardInput(await toNetInput(input));\n }\n\n public async locateFaces(\n input: TNetInput,\n options: ISsdMobilenetv1Options = {},\n ): Promise {\n const { maxResults, minConfidence } = new SsdMobilenetv1Options(options);\n\n const netInput = await toNetInput(input);\n\n const {\n boxes: _boxes,\n scores: _scores,\n } = this.forwardInput(netInput);\n\n const boxes = _boxes[0];\n const scores = _scores[0];\n for (let i = 1; i < _boxes.length; i++) {\n _boxes[i].dispose();\n _scores[i].dispose();\n }\n\n const scoresData = Array.from(await scores.data());\n const iouThreshold = 0.5;\n const indices = nonMaxSuppression(\n boxes,\n scoresData as number[],\n maxResults,\n iouThreshold,\n minConfidence,\n );\n\n const reshapedDims = netInput.getReshapedInputDimensions(0);\n const inputSize = netInput.inputSize as number;\n const padX = inputSize / reshapedDims.width;\n const padY = inputSize / reshapedDims.height;\n\n const boxesData = boxes.arraySync();\n const results = indices\n .map((idx) => {\n const [top, bottom] = [\n Math.max(0, boxesData[idx][0]),\n Math.min(1.0, boxesData[idx][2]),\n ].map((val) => val * padY);\n const [left, right] = [\n Math.max(0, boxesData[idx][1]),\n Math.min(1.0, boxesData[idx][3]),\n ].map((val) => val * padX);\n return new FaceDetection(\n scoresData[idx] as number,\n new Rect(\n left,\n top,\n right - left,\n bottom - top,\n ),\n {\n height: netInput.getInputHeight(0),\n width: netInput.getInputWidth(0),\n },\n );\n });\n\n boxes.dispose();\n scores.dispose();\n return results;\n }\n\n protected getDefaultModelName(): string {\n return 'ssd_mobilenetv1_model';\n }\n\n protected extractParamsFromWeightMap(weightMap: tf.NamedTensorMap) {\n return extractParamsFromWeightMap(weightMap);\n }\n\n protected extractParams(weights: Float32Array) {\n return extractParams(weights);\n }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport {\n ExtractWeightsFunction, ParamMapping, ConvParams, extractWeightsFactory,\n} from '../common/index';\nimport {\n MobileNetV1, NetParams, PointwiseConvParams, PredictionLayerParams,\n} from './types';\n\nfunction extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings: ParamMapping[]) {\n function extractDepthwiseConvParams(numChannels: number, mappedPrefix: string): MobileNetV1.DepthwiseConvParams {\n const filters = tf.tensor4d(extractWeights(3 * 3 * numChannels), [3, 3, numChannels, 1]);\n const batch_norm_scale = tf.tensor1d(extractWeights(numChannels));\n const batch_norm_offset = tf.tensor1d(extractWeights(numChannels));\n const batch_norm_mean = tf.tensor1d(extractWeights(numChannels));\n const batch_norm_variance = tf.tensor1d(extractWeights(numChannels));\n\n paramMappings.push(\n { paramPath: `${mappedPrefix}/filters` },\n { paramPath: `${mappedPrefix}/batch_norm_scale` },\n { paramPath: `${mappedPrefix}/batch_norm_offset` },\n { paramPath: `${mappedPrefix}/batch_norm_mean` },\n { paramPath: `${mappedPrefix}/batch_norm_variance` },\n );\n\n return {\n filters,\n batch_norm_scale,\n batch_norm_offset,\n batch_norm_mean,\n batch_norm_variance,\n };\n }\n\n function extractConvParams(\n channelsIn: number,\n channelsOut: number,\n filterSize: number,\n mappedPrefix: string,\n isPointwiseConv?: boolean,\n ): ConvParams {\n const filters = tf.tensor4d(\n extractWeights(channelsIn * channelsOut * filterSize * filterSize),\n [filterSize, filterSize, channelsIn, channelsOut],\n );\n const bias = tf.tensor1d(extractWeights(channelsOut));\n\n paramMappings.push(\n { paramPath: `${mappedPrefix}/filters` },\n { paramPath: `${mappedPrefix}/${isPointwiseConv ? 'batch_norm_offset' : 'bias'}` },\n );\n\n return { filters, bias };\n }\n\n function extractPointwiseConvParams(\n channelsIn: number,\n channelsOut: number,\n filterSize: number,\n mappedPrefix: string,\n ): PointwiseConvParams {\n const {\n filters,\n bias,\n } = extractConvParams(channelsIn, channelsOut, filterSize, mappedPrefix, true);\n\n return {\n filters,\n batch_norm_offset: bias,\n };\n }\n\n function extractConvPairParams(\n channelsIn: number,\n channelsOut: number,\n mappedPrefix: string,\n ): MobileNetV1.ConvPairParams {\n const depthwise_conv = extractDepthwiseConvParams(channelsIn, `${mappedPrefix}/depthwise_conv`);\n const pointwise_conv = extractPointwiseConvParams(channelsIn, channelsOut, 1, `${mappedPrefix}/pointwise_conv`);\n\n return { depthwise_conv, pointwise_conv };\n }\n\n function extractMobilenetV1Params(): MobileNetV1.Params {\n const conv_0 = extractPointwiseConvParams(3, 32, 3, 'mobilenetv1/conv_0');\n const conv_1 = extractConvPairParams(32, 64, 'mobilenetv1/conv_1');\n const conv_2 = extractConvPairParams(64, 128, 'mobilenetv1/conv_2');\n const conv_3 = extractConvPairParams(128, 128, 'mobilenetv1/conv_3');\n const conv_4 = extractConvPairParams(128, 256, 'mobilenetv1/conv_4');\n const conv_5 = extractConvPairParams(256, 256, 'mobilenetv1/conv_5');\n const conv_6 = extractConvPairParams(256, 512, 'mobilenetv1/conv_6');\n const conv_7 = extractConvPairParams(512, 512, 'mobilenetv1/conv_7');\n const conv_8 = extractConvPairParams(512, 512, 'mobilenetv1/conv_8');\n const conv_9 = extractConvPairParams(512, 512, 'mobilenetv1/conv_9');\n const conv_10 = extractConvPairParams(512, 512, 'mobilenetv1/conv_10');\n const conv_11 = extractConvPairParams(512, 512, 'mobilenetv1/conv_11');\n const conv_12 = extractConvPairParams(512, 1024, 'mobilenetv1/conv_12');\n const conv_13 = extractConvPairParams(1024, 1024, 'mobilenetv1/conv_13');\n return {\n conv_0,\n conv_1,\n conv_2,\n conv_3,\n conv_4,\n conv_5,\n conv_6,\n conv_7,\n conv_8,\n conv_9,\n conv_10,\n conv_11,\n conv_12,\n conv_13,\n };\n }\n\n function extractPredictionLayerParams(): PredictionLayerParams {\n const conv_0 = extractPointwiseConvParams(1024, 256, 1, 'prediction_layer/conv_0');\n const conv_1 = extractPointwiseConvParams(256, 512, 3, 'prediction_layer/conv_1');\n const conv_2 = extractPointwiseConvParams(512, 128, 1, 'prediction_layer/conv_2');\n const conv_3 = extractPointwiseConvParams(128, 256, 3, 'prediction_layer/conv_3');\n const conv_4 = extractPointwiseConvParams(256, 128, 1, 'prediction_layer/conv_4');\n const conv_5 = extractPointwiseConvParams(128, 256, 3, 'prediction_layer/conv_5');\n const conv_6 = extractPointwiseConvParams(256, 64, 1, 'prediction_layer/conv_6');\n const conv_7 = extractPointwiseConvParams(64, 128, 3, 'prediction_layer/conv_7');\n const box_encoding_0_predictor = extractConvParams(512, 12, 1, 'prediction_layer/box_predictor_0/box_encoding_predictor');\n const class_predictor_0 = extractConvParams(512, 9, 1, 'prediction_layer/box_predictor_0/class_predictor');\n const box_encoding_1_predictor = extractConvParams(1024, 24, 1, 'prediction_layer/box_predictor_1/box_encoding_predictor');\n const class_predictor_1 = extractConvParams(1024, 18, 1, 'prediction_layer/box_predictor_1/class_predictor');\n const box_encoding_2_predictor = extractConvParams(512, 24, 1, 'prediction_layer/box_predictor_2/box_encoding_predictor');\n const class_predictor_2 = extractConvParams(512, 18, 1, 'prediction_layer/box_predictor_2/class_predictor');\n const box_encoding_3_predictor = extractConvParams(256, 24, 1, 'prediction_layer/box_predictor_3/box_encoding_predictor');\n const class_predictor_3 = extractConvParams(256, 18, 1, 'prediction_layer/box_predictor_3/class_predictor');\n const box_encoding_4_predictor = extractConvParams(256, 24, 1, 'prediction_layer/box_predictor_4/box_encoding_predictor');\n const class_predictor_4 = extractConvParams(256, 18, 1, 'prediction_layer/box_predictor_4/class_predictor');\n const box_encoding_5_predictor = extractConvParams(128, 24, 1, 'prediction_layer/box_predictor_5/box_encoding_predictor');\n const class_predictor_5 = extractConvParams(128, 18, 1, 'prediction_layer/box_predictor_5/class_predictor');\n\n const box_predictor_0 = {\n box_encoding_predictor: box_encoding_0_predictor,\n class_predictor: class_predictor_0,\n };\n const box_predictor_1 = {\n box_encoding_predictor: box_encoding_1_predictor,\n class_predictor: class_predictor_1,\n };\n const box_predictor_2 = {\n box_encoding_predictor: box_encoding_2_predictor,\n class_predictor: class_predictor_2,\n };\n const box_predictor_3 = {\n box_encoding_predictor: box_encoding_3_predictor,\n class_predictor: class_predictor_3,\n };\n const box_predictor_4 = {\n box_encoding_predictor: box_encoding_4_predictor,\n class_predictor: class_predictor_4,\n };\n const box_predictor_5 = {\n box_encoding_predictor: box_encoding_5_predictor,\n class_predictor: class_predictor_5,\n };\n return {\n conv_0,\n conv_1,\n conv_2,\n conv_3,\n conv_4,\n conv_5,\n conv_6,\n conv_7,\n box_predictor_0,\n box_predictor_1,\n box_predictor_2,\n box_predictor_3,\n box_predictor_4,\n box_predictor_5,\n };\n }\n\n return {\n extractMobilenetV1Params,\n extractPredictionLayerParams,\n };\n}\n\nexport function extractParams(weights: Float32Array): { params: NetParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n const {\n extractWeights,\n getRemainingWeights,\n } = extractWeightsFactory(weights);\n const {\n extractMobilenetV1Params,\n extractPredictionLayerParams,\n } = extractorsFactory(extractWeights, paramMappings);\n const mobilenetv1 = extractMobilenetV1Params();\n const prediction_layer = extractPredictionLayerParams();\n const extra_dim = tf.tensor3d(\n extractWeights(5118 * 4),\n [1, 5118, 4],\n );\n const output_layer = {\n extra_dim,\n };\n paramMappings.push({ paramPath: 'output_layer/extra_dim' });\n if (getRemainingWeights().length !== 0) {\n throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`);\n }\n\n return {\n params: {\n mobilenetv1,\n prediction_layer,\n output_layer,\n },\n paramMappings,\n };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport {\n ConvParams, disposeUnusedWeightTensors, extractWeightEntryFactory, ParamMapping,\n} from '../common/index';\nimport { isTensor3D } from '../utils/index';\nimport {\n BoxPredictionParams, MobileNetV1, NetParams, PointwiseConvParams, PredictionLayerParams,\n} from './types';\n\nfunction extractorsFactory(weightMap: any, paramMappings: ParamMapping[]) {\n const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings);\n\n function extractPointwiseConvParams(prefix: string, idx: number, mappedPrefix: string): PointwiseConvParams {\n const filters = extractWeightEntry(`${prefix}/Conv2d_${idx}_pointwise/weights`, 4, `${mappedPrefix}/filters`);\n const batch_norm_offset = extractWeightEntry(`${prefix}/Conv2d_${idx}_pointwise/convolution_bn_offset`, 1, `${mappedPrefix}/batch_norm_offset`);\n return { filters, batch_norm_offset };\n }\n\n function extractConvPairParams(idx: number): MobileNetV1.ConvPairParams {\n const mappedPrefix = `mobilenetv1/conv_${idx}`;\n const prefixDepthwiseConv = `MobilenetV1/Conv2d_${idx}_depthwise`;\n const mappedPrefixDepthwiseConv = `${mappedPrefix}/depthwise_conv`;\n const mappedPrefixPointwiseConv = `${mappedPrefix}/pointwise_conv`;\n\n const filters = extractWeightEntry(`${prefixDepthwiseConv}/depthwise_weights`, 4, `${mappedPrefixDepthwiseConv}/filters`);\n const batch_norm_scale = extractWeightEntry(`${prefixDepthwiseConv}/BatchNorm/gamma`, 1, `${mappedPrefixDepthwiseConv}/batch_norm_scale`);\n const batch_norm_offset = extractWeightEntry(`${prefixDepthwiseConv}/BatchNorm/beta`, 1, `${mappedPrefixDepthwiseConv}/batch_norm_offset`);\n const batch_norm_mean = extractWeightEntry(`${prefixDepthwiseConv}/BatchNorm/moving_mean`, 1, `${mappedPrefixDepthwiseConv}/batch_norm_mean`);\n const batch_norm_variance = extractWeightEntry(`${prefixDepthwiseConv}/BatchNorm/moving_variance`, 1, `${mappedPrefixDepthwiseConv}/batch_norm_variance`);\n\n return {\n depthwise_conv: {\n filters,\n batch_norm_scale,\n batch_norm_offset,\n batch_norm_mean,\n batch_norm_variance,\n },\n pointwise_conv: extractPointwiseConvParams('MobilenetV1', idx, mappedPrefixPointwiseConv),\n };\n }\n\n function extractMobilenetV1Params(): MobileNetV1.Params {\n return {\n conv_0: extractPointwiseConvParams('MobilenetV1', 0, 'mobilenetv1/conv_0'),\n conv_1: extractConvPairParams(1),\n conv_2: extractConvPairParams(2),\n conv_3: extractConvPairParams(3),\n conv_4: extractConvPairParams(4),\n conv_5: extractConvPairParams(5),\n conv_6: extractConvPairParams(6),\n conv_7: extractConvPairParams(7),\n conv_8: extractConvPairParams(8),\n conv_9: extractConvPairParams(9),\n conv_10: extractConvPairParams(10),\n conv_11: extractConvPairParams(11),\n conv_12: extractConvPairParams(12),\n conv_13: extractConvPairParams(13),\n };\n }\n\n function extractConvParams(prefix: string, mappedPrefix: string): ConvParams {\n const filters = extractWeightEntry(`${prefix}/weights`, 4, `${mappedPrefix}/filters`);\n const bias = extractWeightEntry(`${prefix}/biases`, 1, `${mappedPrefix}/bias`);\n return { filters, bias };\n }\n\n function extractBoxPredictorParams(idx: number): BoxPredictionParams {\n const box_encoding_predictor = extractConvParams(\n `Prediction/BoxPredictor_${idx}/BoxEncodingPredictor`,\n `prediction_layer/box_predictor_${idx}/box_encoding_predictor`,\n );\n const class_predictor = extractConvParams(\n `Prediction/BoxPredictor_${idx}/ClassPredictor`,\n `prediction_layer/box_predictor_${idx}/class_predictor`,\n );\n return { box_encoding_predictor, class_predictor };\n }\n\n function extractPredictionLayerParams(): PredictionLayerParams {\n return {\n conv_0: extractPointwiseConvParams('Prediction', 0, 'prediction_layer/conv_0'),\n conv_1: extractPointwiseConvParams('Prediction', 1, 'prediction_layer/conv_1'),\n conv_2: extractPointwiseConvParams('Prediction', 2, 'prediction_layer/conv_2'),\n conv_3: extractPointwiseConvParams('Prediction', 3, 'prediction_layer/conv_3'),\n conv_4: extractPointwiseConvParams('Prediction', 4, 'prediction_layer/conv_4'),\n conv_5: extractPointwiseConvParams('Prediction', 5, 'prediction_layer/conv_5'),\n conv_6: extractPointwiseConvParams('Prediction', 6, 'prediction_layer/conv_6'),\n conv_7: extractPointwiseConvParams('Prediction', 7, 'prediction_layer/conv_7'),\n box_predictor_0: extractBoxPredictorParams(0),\n box_predictor_1: extractBoxPredictorParams(1),\n box_predictor_2: extractBoxPredictorParams(2),\n box_predictor_3: extractBoxPredictorParams(3),\n box_predictor_4: extractBoxPredictorParams(4),\n box_predictor_5: extractBoxPredictorParams(5),\n };\n }\n\n return {\n extractMobilenetV1Params,\n extractPredictionLayerParams,\n };\n}\n\nexport function extractParamsFromWeightMap(\n weightMap: tf.NamedTensorMap,\n): { params: NetParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n const {\n extractMobilenetV1Params,\n extractPredictionLayerParams,\n } = extractorsFactory(weightMap, paramMappings);\n const extra_dim = weightMap['Output/extra_dim'];\n paramMappings.push({ originalPath: 'Output/extra_dim', paramPath: 'output_layer/extra_dim' });\n if (!isTensor3D(extra_dim)) {\n throw new Error(`expected weightMap['Output/extra_dim'] to be a Tensor3D, instead have ${extra_dim}`);\n }\n\n const params = {\n mobilenetv1: extractMobilenetV1Params(),\n prediction_layer: extractPredictionLayerParams(),\n output_layer: {\n extra_dim,\n },\n };\n\n disposeUnusedWeightTensors(weightMap, paramMappings);\n return { params, paramMappings };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { pointwiseConvLayer } from './pointwiseConvLayer';\nimport { MobileNetV1 } from './types';\n\nconst epsilon = 0.0010000000474974513;\n\nfunction depthwiseConvLayer(\n x: tf.Tensor4D,\n params: MobileNetV1.DepthwiseConvParams,\n strides: [number, number],\n) {\n return tf.tidy(() => {\n let out = tf.depthwiseConv2d(x, params.filters, strides, 'same');\n out = tf.batchNorm(\n out,\n params.batch_norm_mean,\n params.batch_norm_variance,\n params.batch_norm_offset,\n params.batch_norm_scale,\n epsilon,\n );\n return tf.clipByValue(out, 0, 6);\n });\n}\n\nfunction getStridesForLayerIdx(layerIdx: number): [number, number] {\n return [2, 4, 6, 12].some((idx) => idx === layerIdx) ? [2, 2] : [1, 1];\n}\n\nexport function mobileNetV1(x: tf.Tensor4D, params: MobileNetV1.Params) {\n return tf.tidy(() => {\n let conv11;\n let out = pointwiseConvLayer(x, params.conv_0, [2, 2]);\n\n const convPairParams = [\n params.conv_1,\n params.conv_2,\n params.conv_3,\n params.conv_4,\n params.conv_5,\n params.conv_6,\n params.conv_7,\n params.conv_8,\n params.conv_9,\n params.conv_10,\n params.conv_11,\n params.conv_12,\n params.conv_13,\n ];\n\n convPairParams.forEach((param, i) => {\n const layerIdx = i + 1;\n const depthwiseConvStrides = getStridesForLayerIdx(layerIdx);\n out = depthwiseConvLayer(out, param.depthwise_conv, depthwiseConvStrides);\n out = pointwiseConvLayer(out, param.pointwise_conv, [1, 1]);\n if (layerIdx === 11) {\n conv11 = out;\n }\n });\n\n if (conv11 === null) {\n throw new Error('mobileNetV1 - output of conv layer 11 is null');\n }\n\n return {\n out,\n conv11: conv11 as any,\n };\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { PointwiseConvParams } from './types';\n\nexport function pointwiseConvLayer(\n x: tf.Tensor4D,\n params: PointwiseConvParams,\n strides: [number, number],\n) {\n return tf.tidy(() => {\n let out = tf.conv2d(x, params.filters, strides, 'same');\n out = tf.add(out, params.batch_norm_offset);\n return tf.clipByValue(out, 0, 6);\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nfunction IOU(boxes: tf.Tensor2D, i: number, j: number) {\n const boxesData = boxes.arraySync();\n const yminI = Math.min(boxesData[i][0], boxesData[i][2]);\n const xminI = Math.min(boxesData[i][1], boxesData[i][3]);\n const ymaxI = Math.max(boxesData[i][0], boxesData[i][2]);\n const xmaxI = Math.max(boxesData[i][1], boxesData[i][3]);\n const yminJ = Math.min(boxesData[j][0], boxesData[j][2]);\n const xminJ = Math.min(boxesData[j][1], boxesData[j][3]);\n const ymaxJ = Math.max(boxesData[j][0], boxesData[j][2]);\n const xmaxJ = Math.max(boxesData[j][1], boxesData[j][3]);\n const areaI = (ymaxI - yminI) * (xmaxI - xminI);\n const areaJ = (ymaxJ - yminJ) * (xmaxJ - xminJ);\n if (areaI <= 0 || areaJ <= 0) {\n return 0.0;\n }\n const intersectionYmin = Math.max(yminI, yminJ);\n const intersectionXmin = Math.max(xminI, xminJ);\n const intersectionYmax = Math.min(ymaxI, ymaxJ);\n const intersectionXmax = Math.min(xmaxI, xmaxJ);\n const intersectionArea = Math.max(intersectionYmax - intersectionYmin, 0.0)\n * Math.max(intersectionXmax - intersectionXmin, 0.0);\n return intersectionArea / (areaI + areaJ - intersectionArea);\n}\n\nexport function nonMaxSuppression(\n boxes: tf.Tensor2D,\n scores: number[],\n maxOutputSize: number,\n iouThreshold: number,\n scoreThreshold: number,\n): number[] {\n const numBoxes = boxes.shape[0];\n const outputSize = Math.min(\n maxOutputSize,\n numBoxes,\n );\n\n const candidates = scores\n .map((score, boxIndex) => ({ score, boxIndex }))\n .filter((c) => c.score > scoreThreshold)\n .sort((c1, c2) => c2.score - c1.score);\n\n const suppressFunc = (x: number) => (x <= iouThreshold ? 1 : 0);\n const selected: number[] = [];\n\n candidates.forEach((c) => {\n if (selected.length >= outputSize) return;\n const originalScore = c.score;\n for (let j = selected.length - 1; j >= 0; --j) {\n const iou = IOU(boxes, c.boxIndex, selected[j]);\n if (iou === 0.0) continue;\n c.score *= suppressFunc(iou);\n if (c.score <= scoreThreshold) break;\n }\n if (originalScore === c.score) {\n selected.push(c.boxIndex);\n }\n });\n return selected;\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { OutputLayerParams } from './types';\n\nfunction getCenterCoordinatesAndSizesLayer(x: tf.Tensor2D) {\n const vec = tf.unstack(tf.transpose(x, [1, 0]));\n\n const sizes = [\n tf.sub(vec[2], vec[0]),\n tf.sub(vec[3], vec[1]),\n ];\n const centers = [\n tf.add(vec[0], tf.div(sizes[0], tf.scalar(2))),\n tf.add(vec[1], tf.div(sizes[1], tf.scalar(2))),\n ];\n return {\n sizes,\n centers,\n };\n}\n\nfunction decodeBoxesLayer(x0: tf.Tensor2D, x1: tf.Tensor2D) {\n const {\n sizes,\n centers,\n } = getCenterCoordinatesAndSizesLayer(x0);\n\n const vec = tf.unstack(tf.transpose(x1, [1, 0]));\n const div0_out = tf.div(tf.mul(tf.exp(tf.div(vec[2], tf.scalar(5))), sizes[0]), tf.scalar(2));\n const add0_out = tf.add(tf.mul(tf.div(vec[0], tf.scalar(10)), sizes[0]), centers[0]);\n const div1_out = tf.div(tf.mul(tf.exp(tf.div(vec[3], tf.scalar(5))), sizes[1]), tf.scalar(2));\n const add1_out = tf.add(tf.mul(tf.div(vec[1], tf.scalar(10)), sizes[1]), centers[1]);\n\n return tf.transpose(\n tf.stack([\n tf.sub(add0_out, div0_out),\n tf.sub(add1_out, div1_out),\n tf.add(add0_out, div0_out),\n tf.add(add1_out, div1_out),\n ]),\n [1, 0],\n );\n}\n\nexport function outputLayer(\n boxPredictions: tf.Tensor4D,\n classPredictions: tf.Tensor4D,\n params: OutputLayerParams,\n) {\n return tf.tidy(() => {\n const batchSize = boxPredictions.shape[0];\n\n let boxes = decodeBoxesLayer(\n tf.reshape(tf.tile(params.extra_dim, [batchSize, 1, 1]), [-1, 4]) as tf.Tensor2D,\n tf.reshape(boxPredictions, [-1, 4]) as tf.Tensor2D,\n );\n boxes = tf.reshape(\n boxes,\n [batchSize, (boxes.shape[0] / batchSize), 4],\n );\n\n const scoresAndClasses = tf.sigmoid(tf.slice(classPredictions, [0, 0, 1], [-1, -1, -1]));\n let scores = tf.slice(scoresAndClasses, [0, 0, 0], [-1, -1, 1]) as tf.Tensor;\n\n scores = tf.reshape(\n scores,\n [batchSize, scores.shape[1] as number],\n );\n\n const boxesByBatch = tf.unstack(boxes) as tf.Tensor2D[];\n const scoresByBatch = tf.unstack(scores) as tf.Tensor1D[];\n\n return {\n boxes: boxesByBatch,\n scores: scoresByBatch,\n };\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { boxPredictionLayer } from './boxPredictionLayer';\nimport { pointwiseConvLayer } from './pointwiseConvLayer';\nimport { PredictionLayerParams } from './types';\n\nexport function predictionLayer(\n x: tf.Tensor4D,\n conv11: tf.Tensor4D,\n params: PredictionLayerParams,\n) {\n return tf.tidy(() => {\n const conv0 = pointwiseConvLayer(x, params.conv_0, [1, 1]);\n const conv1 = pointwiseConvLayer(conv0, params.conv_1, [2, 2]);\n const conv2 = pointwiseConvLayer(conv1, params.conv_2, [1, 1]);\n const conv3 = pointwiseConvLayer(conv2, params.conv_3, [2, 2]);\n const conv4 = pointwiseConvLayer(conv3, params.conv_4, [1, 1]);\n const conv5 = pointwiseConvLayer(conv4, params.conv_5, [2, 2]);\n const conv6 = pointwiseConvLayer(conv5, params.conv_6, [1, 1]);\n const conv7 = pointwiseConvLayer(conv6, params.conv_7, [2, 2]);\n\n const boxPrediction0 = boxPredictionLayer(conv11, params.box_predictor_0);\n const boxPrediction1 = boxPredictionLayer(x, params.box_predictor_1);\n const boxPrediction2 = boxPredictionLayer(conv1, params.box_predictor_2);\n const boxPrediction3 = boxPredictionLayer(conv3, params.box_predictor_3);\n const boxPrediction4 = boxPredictionLayer(conv5, params.box_predictor_4);\n const boxPrediction5 = boxPredictionLayer(conv7, params.box_predictor_5);\n\n const boxPredictions = tf.concat([\n boxPrediction0.boxPredictionEncoding,\n boxPrediction1.boxPredictionEncoding,\n boxPrediction2.boxPredictionEncoding,\n boxPrediction3.boxPredictionEncoding,\n boxPrediction4.boxPredictionEncoding,\n boxPrediction5.boxPredictionEncoding,\n ], 1) as tf.Tensor4D;\n\n const classPredictions = tf.concat([\n boxPrediction0.classPrediction,\n boxPrediction1.classPrediction,\n boxPrediction2.classPrediction,\n boxPrediction3.classPrediction,\n boxPrediction4.classPrediction,\n boxPrediction5.classPrediction,\n ], 1) as tf.Tensor4D;\n\n return {\n boxPredictions,\n classPredictions,\n };\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { convLayer } from '../common/index';\nimport { BoxPredictionParams } from './types';\n\nexport function boxPredictionLayer(\n x: tf.Tensor4D,\n params: BoxPredictionParams,\n) {\n return tf.tidy(() => {\n const batchSize = x.shape[0];\n const boxPredictionEncoding = tf.reshape(\n convLayer(x, params.box_encoding_predictor),\n [batchSize, -1, 1, 4],\n );\n const classPrediction = tf.reshape(\n convLayer(x, params.class_predictor),\n [batchSize, -1, 3],\n );\n return { boxPredictionEncoding, classPrediction };\n });\n}\n", "export interface ISsdMobilenetv1Options {\n minConfidence?: number\n maxResults?: number\n}\n\nexport class SsdMobilenetv1Options {\n protected _name: string = 'SsdMobilenetv1Options'\n\n private _minConfidence: number\n\n private _maxResults: number\n\n constructor({ minConfidence, maxResults }: ISsdMobilenetv1Options = {}) {\n this._minConfidence = minConfidence || 0.5;\n this._maxResults = maxResults || 100;\n\n if (typeof this._minConfidence !== 'number' || this._minConfidence <= 0 || this._minConfidence >= 1) {\n throw new Error(`${this._name} - expected minConfidence to be a number between 0 and 1`);\n }\n\n if (typeof this._maxResults !== 'number') {\n throw new Error(`${this._name} - expected maxResults to be a number`);\n }\n }\n\n get minConfidence(): number { return this._minConfidence; }\n\n get maxResults(): number { return this._maxResults; }\n}\n", "import { SsdMobilenetv1 } from './SsdMobilenetv1';\n\nexport * from './SsdMobilenetv1';\nexport * from './SsdMobilenetv1Options';\n\nexport function createSsdMobilenetv1(weights: Float32Array) {\n const net = new SsdMobilenetv1();\n net.extractWeights(weights);\n return net;\n}\n\nexport function createFaceDetectionNet(weights: Float32Array) {\n return createSsdMobilenetv1(weights);\n}\n\n// alias for backward compatibily\nexport class FaceDetectionNet extends SsdMobilenetv1 {}\n", "import { Point } from '../classes/index';\n\nexport const IOU_THRESHOLD = 0.4;\n\nexport const BOX_ANCHORS = [\n new Point(0.738768, 0.874946),\n new Point(2.42204, 2.65704),\n new Point(4.30971, 7.04493),\n new Point(10.246, 4.59428),\n new Point(12.6868, 11.8741),\n];\n\nexport const BOX_ANCHORS_SEPARABLE = [\n new Point(1.603231, 2.094468),\n new Point(6.041143, 7.080126),\n new Point(2.882459, 3.518061),\n new Point(4.266906, 5.178857),\n new Point(9.041765, 10.66308),\n];\n\nexport const MEAN_RGB_SEPARABLE: [number, number, number] = [117.001, 114.697, 97.404];\n\nexport const DEFAULT_MODEL_NAME = 'tiny_yolov2_model';\nexport const DEFAULT_MODEL_NAME_SEPARABLE_CONV = 'tiny_yolov2_separable_conv_model';\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { BoundingBox } from '../classes/BoundingBox';\nimport { Dimensions } from '../classes/Dimensions';\nimport { ObjectDetection } from '../classes/ObjectDetection';\nimport { convLayer } from '../common/index';\nimport { ConvParams, SeparableConvParams } from '../common/types';\nimport { toNetInput } from '../dom/index';\nimport { NetInput } from '../dom/NetInput';\nimport { TNetInput } from '../dom/types';\nimport { NeuralNetwork } from '../NeuralNetwork';\nimport { sigmoid } from '../ops/index';\nimport { nonMaxSuppression } from '../ops/nonMaxSuppression';\nimport { normalize } from '../ops/normalize';\nimport { TinyYolov2Config, validateConfig } from './config';\nimport { convWithBatchNorm } from './convWithBatchNorm';\nimport { depthwiseSeparableConv } from './depthwiseSeparableConv';\nimport { extractParams } from './extractParams';\nimport { extractParamsFromWeightMap } from './extractParamsFromWeightMap';\nimport { leaky } from './leaky';\nimport { ITinyYolov2Options, TinyYolov2Options } from './TinyYolov2Options';\nimport { DefaultTinyYolov2NetParams, MobilenetParams, TinyYolov2NetParams } from './types';\n\nexport class TinyYolov2Base extends NeuralNetwork {\n public static DEFAULT_FILTER_SIZES = [3, 16, 32, 64, 128, 256, 512, 1024, 1024];\n\n private _config: TinyYolov2Config\n\n constructor(config: TinyYolov2Config) {\n super('TinyYolov2');\n validateConfig(config);\n this._config = config;\n }\n\n public get config(): TinyYolov2Config {\n return this._config;\n }\n\n public get withClassScores(): boolean {\n return this.config.withClassScores || this.config.classes.length > 1;\n }\n\n public get boxEncodingSize(): number {\n return 5 + (this.withClassScores ? this.config.classes.length : 0);\n }\n\n public runTinyYolov2(x: tf.Tensor4D, params: DefaultTinyYolov2NetParams): tf.Tensor4D {\n let out = convWithBatchNorm(x, params.conv0);\n out = tf.maxPool(out, [2, 2], [2, 2], 'same');\n out = convWithBatchNorm(out, params.conv1);\n out = tf.maxPool(out, [2, 2], [2, 2], 'same');\n out = convWithBatchNorm(out, params.conv2);\n out = tf.maxPool(out, [2, 2], [2, 2], 'same');\n out = convWithBatchNorm(out, params.conv3);\n out = tf.maxPool(out, [2, 2], [2, 2], 'same');\n out = convWithBatchNorm(out, params.conv4);\n out = tf.maxPool(out, [2, 2], [2, 2], 'same');\n out = convWithBatchNorm(out, params.conv5);\n out = tf.maxPool(out, [2, 2], [1, 1], 'same');\n out = convWithBatchNorm(out, params.conv6);\n out = convWithBatchNorm(out, params.conv7);\n return convLayer(out, params.conv8, 'valid', false);\n }\n\n public runMobilenet(x: tf.Tensor4D, params: MobilenetParams): tf.Tensor4D {\n let out = this.config.isFirstLayerConv2d\n ? leaky(convLayer(x, params.conv0 as ConvParams, 'valid', false))\n : depthwiseSeparableConv(x, params.conv0 as SeparableConvParams);\n out = tf.maxPool(out, [2, 2], [2, 2], 'same');\n out = depthwiseSeparableConv(out, params.conv1);\n out = tf.maxPool(out, [2, 2], [2, 2], 'same');\n out = depthwiseSeparableConv(out, params.conv2);\n out = tf.maxPool(out, [2, 2], [2, 2], 'same');\n out = depthwiseSeparableConv(out, params.conv3);\n out = tf.maxPool(out, [2, 2], [2, 2], 'same');\n out = depthwiseSeparableConv(out, params.conv4);\n out = tf.maxPool(out, [2, 2], [2, 2], 'same');\n out = depthwiseSeparableConv(out, params.conv5);\n out = tf.maxPool(out, [2, 2], [1, 1], 'same');\n out = params.conv6 ? depthwiseSeparableConv(out, params.conv6) : out;\n out = params.conv7 ? depthwiseSeparableConv(out, params.conv7) : out;\n return convLayer(out, params.conv8, 'valid', false);\n }\n\n public forwardInput(input: NetInput, inputSize: number): tf.Tensor4D {\n const { params } = this;\n\n if (!params) {\n throw new Error('TinyYolov2 - load model before inference');\n }\n\n return tf.tidy(() => {\n let batchTensor = tf.cast(input.toBatchTensor(inputSize, false), 'float32');\n batchTensor = this.config.meanRgb\n ? normalize(batchTensor, this.config.meanRgb)\n : batchTensor;\n batchTensor = batchTensor.div(tf.scalar(256)) as tf.Tensor4D;\n return this.config.withSeparableConvs\n ? this.runMobilenet(batchTensor, params as MobilenetParams)\n : this.runTinyYolov2(batchTensor, params as DefaultTinyYolov2NetParams);\n });\n }\n\n public async forward(input: TNetInput, inputSize: number): Promise {\n return this.forwardInput(await toNetInput(input), inputSize);\n }\n\n public async detect(input: TNetInput, forwardParams: ITinyYolov2Options = {}): Promise {\n const { inputSize, scoreThreshold } = new TinyYolov2Options(forwardParams);\n const netInput = await toNetInput(input);\n const out = await this.forwardInput(netInput, inputSize);\n const out0 = tf.tidy(() => tf.unstack(out)[0].expandDims()) as tf.Tensor4D;\n const inputDimensions = {\n width: netInput.getInputWidth(0),\n height: netInput.getInputHeight(0),\n };\n\n const results = await this.extractBoxes(out0, netInput.getReshapedInputDimensions(0), scoreThreshold);\n out.dispose();\n out0.dispose();\n\n const boxes = results.map((res) => res.box);\n const scores = results.map((res) => res.score);\n const classScores = results.map((res) => res.classScore);\n const classNames = results.map((res) => this.config.classes[res.label]);\n\n const indices = nonMaxSuppression(\n boxes.map((box) => box.rescale(inputSize)),\n scores,\n this.config.iouThreshold,\n true,\n );\n\n const detections = indices.map((idx) => new ObjectDetection(\n scores[idx],\n classScores[idx],\n classNames[idx],\n boxes[idx],\n inputDimensions,\n ));\n return detections;\n }\n\n protected getDefaultModelName(): string {\n return '';\n }\n\n protected extractParamsFromWeightMap(weightMap: tf.NamedTensorMap) {\n return extractParamsFromWeightMap(weightMap, this.config);\n }\n\n protected extractParams(weights: Float32Array) {\n const filterSizes = this.config.filterSizes || TinyYolov2Base.DEFAULT_FILTER_SIZES;\n\n const numFilters = filterSizes ? filterSizes.length : undefined;\n if (numFilters !== 7 && numFilters !== 8 && numFilters !== 9) {\n throw new Error(`TinyYolov2 - expected 7 | 8 | 9 convolutional filters, but found ${numFilters} filterSizes in config`);\n }\n return extractParams(weights, this.config, this.boxEncodingSize, filterSizes);\n }\n\n protected async extractBoxes(\n outputTensor: tf.Tensor4D,\n inputBlobDimensions: Dimensions,\n scoreThreshold?: number,\n ) {\n const { width, height } = inputBlobDimensions;\n const inputSize = Math.max(width, height);\n const correctionFactorX = inputSize / width;\n const correctionFactorY = inputSize / height;\n\n const numCells = outputTensor.shape[1];\n const numBoxes = this.config.anchors.length;\n\n const [boxesTensor, scoresTensor, classScoresTensor] = tf.tidy(() => {\n const reshaped = outputTensor.reshape([numCells, numCells, numBoxes, this.boxEncodingSize]);\n\n const boxes = reshaped.slice([0, 0, 0, 0], [numCells, numCells, numBoxes, 4]);\n const scores = reshaped.slice([0, 0, 0, 4], [numCells, numCells, numBoxes, 1]);\n const classScores = this.withClassScores\n ? tf.softmax(reshaped.slice([0, 0, 0, 5], [numCells, numCells, numBoxes, this.config.classes.length]), 3)\n : tf.scalar(0);\n return [boxes, scores, classScores];\n });\n\n const results = [] as any;\n const scoresData = await scoresTensor.array();\n const boxesData = await boxesTensor.array();\n for (let row = 0; row < numCells; row++) {\n for (let col = 0; col < numCells; col++) {\n for (let anchor = 0; anchor < numBoxes; anchor++) {\n const score = sigmoid(scoresData[row][col][anchor][0]);\n if (!scoreThreshold || score > scoreThreshold) {\n const ctX = ((col + sigmoid(boxesData[row][col][anchor][0])) / numCells) * correctionFactorX;\n const ctY = ((row + sigmoid(boxesData[row][col][anchor][1])) / numCells) * correctionFactorY;\n const widthLocal = ((Math.exp(boxesData[row][col][anchor][2]) * this.config.anchors[anchor].x) / numCells) * correctionFactorX;\n const heightLocal = ((Math.exp(boxesData[row][col][anchor][3]) * this.config.anchors[anchor].y) / numCells) * correctionFactorY;\n const x = (ctX - (widthLocal / 2));\n const y = (ctY - (heightLocal / 2));\n const pos = { row, col, anchor };\n const { classScore, label } = this.withClassScores\n ? await this.extractPredictedClass(classScoresTensor as tf.Tensor4D, pos)\n : { classScore: 1, label: 0 };\n results.push({\n box: new BoundingBox(x, y, x + widthLocal, y + heightLocal),\n score,\n classScore: score * classScore,\n label,\n ...pos,\n });\n }\n }\n }\n }\n\n boxesTensor.dispose();\n scoresTensor.dispose();\n classScoresTensor.dispose();\n return results;\n }\n\n private async extractPredictedClass(classesTensor: tf.Tensor4D, pos: { row: number, col: number, anchor: number }) {\n const { row, col, anchor } = pos;\n const classesData = await classesTensor.array();\n return Array(this.config.classes.length).fill(0)\n .map((_, i) => classesData[row][col][anchor][i])\n .map((classScore, label) => ({\n classScore,\n label,\n }))\n .reduce((max, curr) => (max.classScore > curr.classScore ? max : curr));\n }\n}\n", "import { Point } from '../classes/Point';\n\nexport type TinyYolov2Config = {\n withSeparableConvs: boolean\n iouThreshold: number\n anchors: Point[]\n classes: string[]\n meanRgb?: [number, number, number]\n withClassScores?: boolean,\n filterSizes?: number[]\n isFirstLayerConv2d?: boolean\n}\n\nconst isNumber = (arg: any) => typeof arg === 'number';\n\nexport function validateConfig(config: any) {\n if (!config) {\n throw new Error(`invalid config: ${config}`);\n }\n\n if (typeof config.withSeparableConvs !== 'boolean') {\n throw new Error(`config.withSeparableConvs has to be a boolean, have: ${config.withSeparableConvs}`);\n }\n\n if (!isNumber(config.iouThreshold) || config.iouThreshold < 0 || config.iouThreshold > 1.0) {\n throw new Error(`config.iouThreshold has to be a number between [0, 1], have: ${config.iouThreshold}`);\n }\n\n if (\n !Array.isArray(config.classes)\n || !config.classes.length\n || !config.classes.every((c: any) => typeof c === 'string')\n ) {\n throw new Error(`config.classes has to be an array class names: string[], have: ${JSON.stringify(config.classes)}`);\n }\n\n if (\n !Array.isArray(config.anchors)\n || !config.anchors.length\n || !config.anchors.map((a: any) => a || {}).every((a: any) => isNumber(a.x) && isNumber(a.y))\n ) {\n throw new Error(`config.anchors has to be an array of { x: number, y: number }, have: ${JSON.stringify(config.anchors)}`);\n }\n\n if (config.meanRgb && (\n !Array.isArray(config.meanRgb)\n || config.meanRgb.length !== 3\n || !config.meanRgb.every(isNumber)\n )) {\n throw new Error(`config.meanRgb has to be an array of shape [number, number, number], have: ${JSON.stringify(config.meanRgb)}`);\n }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { leaky } from './leaky';\nimport { ConvWithBatchNorm } from './types';\n\nexport function convWithBatchNorm(x: tf.Tensor4D, params: ConvWithBatchNorm): tf.Tensor4D {\n return tf.tidy(() => {\n let out = tf.pad(x, [[0, 0], [1, 1], [1, 1], [0, 0]]) as tf.Tensor4D;\n out = tf.conv2d(out, params.conv.filters, [1, 1], 'valid');\n out = tf.sub(out, params.bn.sub);\n out = tf.mul(out, params.bn.truediv);\n out = tf.add(out, params.conv.bias);\n return leaky(out);\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nexport function leaky(x: tf.Tensor4D): tf.Tensor4D {\n return tf.tidy(() => {\n const min = tf.mul(x, tf.scalar(0.10000000149011612));\n return tf.add(tf.relu(tf.sub(x, min)), min);\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { SeparableConvParams } from '../common/types';\nimport { leaky } from './leaky';\n\nexport function depthwiseSeparableConv(x: tf.Tensor4D, params: SeparableConvParams): tf.Tensor4D {\n return tf.tidy(() => {\n let out = tf.pad(x, [[0, 0], [1, 1], [1, 1], [0, 0]]) as tf.Tensor4D;\n out = tf.separableConv2d(out, params.depthwise_filter, params.pointwise_filter, [1, 1], 'valid');\n out = tf.add(out, params.bias);\n return leaky(out);\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { extractConvParamsFactory } from '../common/index';\nimport { extractSeparableConvParamsFactory } from '../common/extractSeparableConvParamsFactory';\nimport { extractWeightsFactory } from '../common/extractWeightsFactory';\nimport { ExtractWeightsFunction, ParamMapping } from '../common/types';\nimport { TinyYolov2Config } from './config';\nimport { BatchNorm, ConvWithBatchNorm, TinyYolov2NetParams } from './types';\n\nfunction extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings: ParamMapping[]) {\n const extractConvParams = extractConvParamsFactory(extractWeights, paramMappings);\n\n function extractBatchNormParams(size: number, mappedPrefix: string): BatchNorm {\n const sub = tf.tensor1d(extractWeights(size));\n const truediv = tf.tensor1d(extractWeights(size));\n\n paramMappings.push(\n { paramPath: `${mappedPrefix}/sub` },\n { paramPath: `${mappedPrefix}/truediv` },\n );\n return { sub, truediv };\n }\n\n function extractConvWithBatchNormParams(channelsIn: number, channelsOut: number, mappedPrefix: string): ConvWithBatchNorm {\n const conv = extractConvParams(channelsIn, channelsOut, 3, `${mappedPrefix}/conv`);\n const bn = extractBatchNormParams(channelsOut, `${mappedPrefix}/bn`);\n return { conv, bn };\n }\n const extractSeparableConvParams = extractSeparableConvParamsFactory(extractWeights, paramMappings);\n\n return {\n extractConvParams,\n extractConvWithBatchNormParams,\n extractSeparableConvParams,\n };\n}\n\nexport function extractParams(\n weights: Float32Array,\n config: TinyYolov2Config,\n boxEncodingSize: number,\n filterSizes: number[],\n): { params: TinyYolov2NetParams, paramMappings: ParamMapping[] } {\n const {\n extractWeights,\n getRemainingWeights,\n } = extractWeightsFactory(weights);\n\n const paramMappings: ParamMapping[] = [];\n const {\n extractConvParams,\n extractConvWithBatchNormParams,\n extractSeparableConvParams,\n } = extractorsFactory(extractWeights, paramMappings);\n let params: TinyYolov2NetParams;\n\n if (config.withSeparableConvs) {\n const [s0, s1, s2, s3, s4, s5, s6, s7, s8] = filterSizes;\n const conv0 = config.isFirstLayerConv2d\n ? extractConvParams(s0, s1, 3, 'conv0')\n : extractSeparableConvParams(s0, s1, 'conv0');\n const conv1 = extractSeparableConvParams(s1, s2, 'conv1');\n const conv2 = extractSeparableConvParams(s2, s3, 'conv2');\n const conv3 = extractSeparableConvParams(s3, s4, 'conv3');\n const conv4 = extractSeparableConvParams(s4, s5, 'conv4');\n const conv5 = extractSeparableConvParams(s5, s6, 'conv5');\n const conv6 = s7 ? extractSeparableConvParams(s6, s7, 'conv6') : undefined;\n const conv7 = s8 ? extractSeparableConvParams(s7, s8, 'conv7') : undefined;\n const conv8 = extractConvParams(s8 || s7 || s6, 5 * boxEncodingSize, 1, 'conv8');\n params = {\n conv0, conv1, conv2, conv3, conv4, conv5, conv6, conv7, conv8,\n };\n } else {\n const [s0, s1, s2, s3, s4, s5, s6, s7, s8] = filterSizes;\n const conv0 = extractConvWithBatchNormParams(s0, s1, 'conv0');\n const conv1 = extractConvWithBatchNormParams(s1, s2, 'conv1');\n const conv2 = extractConvWithBatchNormParams(s2, s3, 'conv2');\n const conv3 = extractConvWithBatchNormParams(s3, s4, 'conv3');\n const conv4 = extractConvWithBatchNormParams(s4, s5, 'conv4');\n const conv5 = extractConvWithBatchNormParams(s5, s6, 'conv5');\n const conv6 = extractConvWithBatchNormParams(s6, s7, 'conv6');\n const conv7 = extractConvWithBatchNormParams(s7, s8, 'conv7');\n const conv8 = extractConvParams(s8, 5 * boxEncodingSize, 1, 'conv8');\n params = {\n conv0, conv1, conv2, conv3, conv4, conv5, conv6, conv7, conv8,\n };\n }\n if (getRemainingWeights().length !== 0) {\n throw new Error(`weights remaing after extract: ${getRemainingWeights().length}`);\n }\n return { params, paramMappings };\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { ConvParams } from '../common/index';\nimport { disposeUnusedWeightTensors } from '../common/disposeUnusedWeightTensors';\nimport { loadSeparableConvParamsFactory } from '../common/extractSeparableConvParamsFactory';\nimport { extractWeightEntryFactory } from '../common/extractWeightEntryFactory';\nimport { ParamMapping } from '../common/types';\nimport { TinyYolov2Config } from './config';\nimport { BatchNorm, ConvWithBatchNorm, TinyYolov2NetParams } from './types';\n\nfunction extractorsFactory(weightMap: any, paramMappings: ParamMapping[]) {\n const extractWeightEntry = extractWeightEntryFactory(weightMap, paramMappings);\n\n function extractBatchNormParams(prefix: string): BatchNorm {\n const sub = extractWeightEntry(`${prefix}/sub`, 1);\n const truediv = extractWeightEntry(`${prefix}/truediv`, 1);\n return { sub, truediv };\n }\n\n function extractConvParams(prefix: string): ConvParams {\n const filters = extractWeightEntry(`${prefix}/filters`, 4);\n const bias = extractWeightEntry(`${prefix}/bias`, 1);\n return { filters, bias };\n }\n\n function extractConvWithBatchNormParams(prefix: string): ConvWithBatchNorm {\n const conv = extractConvParams(`${prefix}/conv`);\n const bn = extractBatchNormParams(`${prefix}/bn`);\n return { conv, bn };\n }\n\n const extractSeparableConvParams = loadSeparableConvParamsFactory(extractWeightEntry);\n return {\n extractConvParams,\n extractConvWithBatchNormParams,\n extractSeparableConvParams,\n };\n}\n\nexport function extractParamsFromWeightMap(\n weightMap: tf.NamedTensorMap,\n config: TinyYolov2Config,\n): { params: TinyYolov2NetParams, paramMappings: ParamMapping[] } {\n const paramMappings: ParamMapping[] = [];\n\n const {\n extractConvParams,\n extractConvWithBatchNormParams,\n extractSeparableConvParams,\n } = extractorsFactory(weightMap, paramMappings);\n\n let params: TinyYolov2NetParams;\n\n if (config.withSeparableConvs) {\n // eslint-disable-next-line no-mixed-operators\n const numFilters = (config.filterSizes && config.filterSizes.length || 9);\n params = {\n conv0: config.isFirstLayerConv2d ? extractConvParams('conv0') : extractSeparableConvParams('conv0'),\n conv1: extractSeparableConvParams('conv1'),\n conv2: extractSeparableConvParams('conv2'),\n conv3: extractSeparableConvParams('conv3'),\n conv4: extractSeparableConvParams('conv4'),\n conv5: extractSeparableConvParams('conv5'),\n conv6: numFilters > 7 ? extractSeparableConvParams('conv6') : undefined,\n conv7: numFilters > 8 ? extractSeparableConvParams('conv7') : undefined,\n conv8: extractConvParams('conv8'),\n };\n } else {\n params = {\n conv0: extractConvWithBatchNormParams('conv0'),\n conv1: extractConvWithBatchNormParams('conv1'),\n conv2: extractConvWithBatchNormParams('conv2'),\n conv3: extractConvWithBatchNormParams('conv3'),\n conv4: extractConvWithBatchNormParams('conv4'),\n conv5: extractConvWithBatchNormParams('conv5'),\n conv6: extractConvWithBatchNormParams('conv6'),\n conv7: extractConvWithBatchNormParams('conv7'),\n conv8: extractConvParams('conv8'),\n };\n }\n\n disposeUnusedWeightTensors(weightMap, paramMappings);\n return { params, paramMappings };\n}\n", "export interface ITinyYolov2Options {\n inputSize?: number\n scoreThreshold?: number\n}\n\nexport class TinyYolov2Options {\n protected _name: string = 'TinyYolov2Options'\n\n private _inputSize: number\n\n private _scoreThreshold: number\n\n constructor({ inputSize, scoreThreshold }: ITinyYolov2Options = {}) {\n this._inputSize = inputSize || 416;\n this._scoreThreshold = scoreThreshold || 0.5;\n\n if (typeof this._inputSize !== 'number' || this._inputSize % 32 !== 0) {\n throw new Error(`${this._name} - expected inputSize to be a number divisible by 32`);\n }\n\n if (typeof this._scoreThreshold !== 'number' || this._scoreThreshold <= 0 || this._scoreThreshold >= 1) {\n throw new Error(`${this._name} - expected scoreThreshold to be a number between 0 and 1`);\n }\n }\n\n get inputSize(): number { return this._inputSize; }\n\n get scoreThreshold(): number { return this._scoreThreshold; }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { FaceDetection, Point } from '../classes/index';\nimport { ParamMapping } from '../common/types';\nimport { TNetInput } from '../dom/types';\nimport {\n BOX_ANCHORS,\n BOX_ANCHORS_SEPARABLE,\n DEFAULT_MODEL_NAME,\n DEFAULT_MODEL_NAME_SEPARABLE_CONV,\n IOU_THRESHOLD,\n MEAN_RGB_SEPARABLE,\n} from './const';\nimport { TinyYolov2Base } from './TinyYolov2Base';\nimport { ITinyYolov2Options } from './TinyYolov2Options';\nimport { TinyYolov2NetParams } from './types';\n\nexport class TinyYolov2 extends TinyYolov2Base {\n constructor(withSeparableConvs: boolean = true) {\n const config = {\n withSeparableConvs,\n iouThreshold: IOU_THRESHOLD,\n classes: ['face'],\n ...(withSeparableConvs\n ? {\n anchors: BOX_ANCHORS_SEPARABLE,\n meanRgb: MEAN_RGB_SEPARABLE,\n }\n : {\n anchors: BOX_ANCHORS,\n withClassScores: true,\n }),\n };\n\n super(config);\n }\n\n public get withSeparableConvs(): boolean {\n return this.config.withSeparableConvs;\n }\n\n public get anchors(): Point[] {\n return this.config.anchors;\n }\n\n public async locateFaces(input: TNetInput, forwardParams: ITinyYolov2Options): Promise {\n const objectDetections = await this.detect(input, forwardParams);\n return objectDetections.map((det) => new FaceDetection(det.score, det.relativeBox, { width: det.imageWidth, height: det.imageHeight }));\n }\n\n protected getDefaultModelName(): string {\n return this.withSeparableConvs ? DEFAULT_MODEL_NAME_SEPARABLE_CONV : DEFAULT_MODEL_NAME;\n }\n\n protected extractParamsFromWeightMap(weightMap: tf.NamedTensorMap): { params: TinyYolov2NetParams, paramMappings: ParamMapping[] } {\n return super.extractParamsFromWeightMap(weightMap);\n }\n}\n", "import { TinyYolov2 } from './TinyYolov2';\n\nexport * from './TinyYolov2Options';\nexport * from './config';\nexport * from './types';\nexport { TinyYolov2 };\n\nexport function createTinyYolov2(weights: Float32Array, withSeparableConvs: boolean = true) {\n const net = new TinyYolov2(withSeparableConvs);\n net.extractWeights(weights);\n return net;\n}\n", "import { ITinyYolov2Options, TinyYolov2Options } from '../tinyYolov2/index';\n\nexport interface ITinyFaceDetectorOptions extends ITinyYolov2Options {}\n\nexport class TinyFaceDetectorOptions extends TinyYolov2Options {\n protected _name: string = 'TinyFaceDetectorOptions'\n}\n", "export class ComposableTask {\n public async then(\n // eslint-disable-next-line no-unused-vars\n onfulfilled: (value: T) => T | PromiseLike,\n ): Promise {\n return onfulfilled(await this.run());\n }\n\n public async run(): Promise {\n throw new Error('ComposableTask - run is not implemented');\n }\n}\n", "/* eslint-disable max-classes-per-file */\nimport * as tf from '../../dist/tfjs.esm';\n\nimport { FaceLandmarks68 } from '../classes/FaceLandmarks68';\nimport { extractFaces, extractFaceTensors, TNetInput } from '../dom/index';\nimport { FaceLandmark68Net } from '../faceLandmarkNet/FaceLandmark68Net';\nimport { FaceLandmark68TinyNet } from '../faceLandmarkNet/FaceLandmark68TinyNet';\nimport { WithFaceDetection } from '../factories/WithFaceDetection';\nimport { extendWithFaceLandmarks, WithFaceLandmarks } from '../factories/WithFaceLandmarks';\nimport { ComposableTask } from './ComposableTask';\nimport { ComputeAllFaceDescriptorsTask, ComputeSingleFaceDescriptorTask } from './ComputeFaceDescriptorsTasks';\nimport { nets } from './nets';\nimport {\n PredictAllAgeAndGenderWithFaceAlignmentTask,\n PredictSingleAgeAndGenderWithFaceAlignmentTask,\n} from './PredictAgeAndGenderTask';\nimport {\n PredictAllFaceExpressionsWithFaceAlignmentTask,\n PredictSingleFaceExpressionsWithFaceAlignmentTask,\n} from './PredictFaceExpressionsTask';\n\nexport class DetectFaceLandmarksTaskBase extends ComposableTask {\n constructor(\n // eslint-disable-next-line no-unused-vars\n protected parentTask: ComposableTask | Promise,\n // eslint-disable-next-line no-unused-vars\n protected input: TNetInput,\n // eslint-disable-next-line no-unused-vars\n protected useTinyLandmarkNet: boolean,\n ) {\n super();\n }\n\n protected get landmarkNet(): FaceLandmark68Net | FaceLandmark68TinyNet {\n return this.useTinyLandmarkNet\n ? nets.faceLandmark68TinyNet\n : nets.faceLandmark68Net;\n }\n}\n\nexport class DetectAllFaceLandmarksTask<\n TSource extends WithFaceDetection<{}>\n> extends DetectFaceLandmarksTaskBase[], TSource[]> {\n public async run(): Promise[]> {\n const parentResults = await this.parentTask;\n const detections = parentResults.map((res) => res.detection);\n\n const faces: Array = this.input instanceof tf.Tensor\n ? await extractFaceTensors(this.input, detections)\n : await extractFaces(this.input, detections);\n\n const faceLandmarksByFace = await Promise.all(faces.map(\n (face) => this.landmarkNet.detectLandmarks(face),\n )) as FaceLandmarks68[];\n\n faces.forEach((f) => f instanceof tf.Tensor && f.dispose());\n\n return parentResults.map((parentResult, i) => extendWithFaceLandmarks(parentResult, faceLandmarksByFace[i]));\n }\n\n withFaceExpressions() {\n return new PredictAllFaceExpressionsWithFaceAlignmentTask(this, this.input);\n }\n\n withAgeAndGender() {\n return new PredictAllAgeAndGenderWithFaceAlignmentTask(this, this.input);\n }\n\n withFaceDescriptors() {\n return new ComputeAllFaceDescriptorsTask(this, this.input);\n }\n}\n\nexport class DetectSingleFaceLandmarksTask<\n TSource extends WithFaceDetection<{}>\n> extends DetectFaceLandmarksTaskBase | undefined, TSource | undefined> {\n public async run(): Promise | undefined> {\n const parentResult = await this.parentTask;\n if (!parentResult) {\n return undefined;\n }\n\n const { detection } = parentResult;\n const faces: Array = this.input instanceof tf.Tensor\n ? await extractFaceTensors(this.input, [detection])\n : await extractFaces(this.input, [detection]);\n\n const landmarks = await this.landmarkNet.detectLandmarks(faces[0]) as FaceLandmarks68;\n\n faces.forEach((f) => f instanceof tf.Tensor && f.dispose());\n\n return extendWithFaceLandmarks(parentResult, landmarks);\n }\n\n withFaceExpressions() {\n return new PredictSingleFaceExpressionsWithFaceAlignmentTask(this, this.input);\n }\n\n withAgeAndGender() {\n return new PredictSingleAgeAndGenderWithFaceAlignmentTask(this, this.input);\n }\n\n withFaceDescriptor() {\n return new ComputeSingleFaceDescriptorTask(this, this.input);\n }\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { FaceDetection } from '../classes/FaceDetection';\nimport { extractFaces, extractFaceTensors, TNetInput } from '../dom/index';\nimport { WithFaceDetection } from '../factories/WithFaceDetection';\nimport { isWithFaceLandmarks, WithFaceLandmarks } from '../factories/WithFaceLandmarks';\n\nexport async function extractAllFacesAndComputeResults, TResult>(\n parentResults: TSource[],\n input: TNetInput,\n // eslint-disable-next-line no-unused-vars\n computeResults: (faces: Array) => Promise,\n extractedFaces?: Array | null,\n // eslint-disable-next-line no-unused-vars\n getRectForAlignment: (parentResult: WithFaceLandmarks) => FaceDetection = ({ alignedRect }) => alignedRect,\n) {\n const faceBoxes = parentResults.map((parentResult) => (isWithFaceLandmarks(parentResult)\n ? getRectForAlignment(parentResult)\n : parentResult.detection));\n const faces: Array = extractedFaces || (\n input instanceof tf.Tensor\n ? await extractFaceTensors(input, faceBoxes)\n : await extractFaces(input, faceBoxes)\n );\n\n const results = await computeResults(faces);\n\n faces.forEach((f) => f instanceof tf.Tensor && f.dispose());\n\n return results;\n}\n\nexport async function extractSingleFaceAndComputeResult, TResult>(\n parentResult: TSource,\n input: TNetInput,\n // eslint-disable-next-line no-unused-vars\n computeResult: (face: HTMLCanvasElement | tf.Tensor3D) => Promise,\n extractedFaces?: Array | null,\n // eslint-disable-next-line no-unused-vars\n getRectForAlignment?: (parentResultLocal: WithFaceLandmarks) => FaceDetection,\n) {\n return extractAllFacesAndComputeResults(\n [parentResult],\n input,\n async (faces) => computeResult(faces[0]),\n extractedFaces,\n getRectForAlignment,\n );\n}\n", "import { Point } from '../classes/index';\n\nexport const IOU_THRESHOLD = 0.4;\n\nexport const BOX_ANCHORS = [\n new Point(1.603231, 2.094468),\n new Point(6.041143, 7.080126),\n new Point(2.882459, 3.518061),\n new Point(4.266906, 5.178857),\n new Point(9.041765, 10.66308),\n];\n\nexport const MEAN_RGB: [number, number, number] = [117.001, 114.697, 97.404];\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { FaceDetection, Point } from '../classes/index';\nimport { ParamMapping } from '../common/index';\nimport { TNetInput } from '../dom/index';\nimport { ITinyYolov2Options } from '../tinyYolov2/index';\nimport { TinyYolov2Base } from '../tinyYolov2/TinyYolov2Base';\nimport { TinyYolov2NetParams } from '../tinyYolov2/types';\nimport { BOX_ANCHORS, IOU_THRESHOLD, MEAN_RGB } from './const';\n\nexport class TinyFaceDetector extends TinyYolov2Base {\n constructor() {\n const config = {\n withSeparableConvs: true,\n iouThreshold: IOU_THRESHOLD,\n classes: ['face'],\n anchors: BOX_ANCHORS,\n meanRgb: MEAN_RGB,\n isFirstLayerConv2d: true,\n filterSizes: [3, 16, 32, 64, 128, 256, 512],\n };\n\n super(config);\n }\n\n public get anchors(): Point[] {\n return this.config.anchors;\n }\n\n public async locateFaces(input: TNetInput, forwardParams: ITinyYolov2Options): Promise {\n const objectDetections = await this.detect(input, forwardParams);\n return objectDetections.map((det) => new FaceDetection(det.score, det.relativeBox, { width: det.imageWidth, height: det.imageHeight }));\n }\n\n protected getDefaultModelName(): string {\n return 'tiny_face_detector_model';\n }\n\n protected extractParamsFromWeightMap(weightMap: tf.NamedTensorMap): { params: TinyYolov2NetParams, paramMappings: ParamMapping[] } {\n return super.extractParamsFromWeightMap(weightMap);\n }\n}\n", "import { AgeGenderNet } from '../ageGenderNet/AgeGenderNet';\nimport { AgeAndGenderPrediction } from '../ageGenderNet/types';\nimport { FaceDetection } from '../classes/FaceDetection';\nimport { FaceLandmarks68 } from '../classes/FaceLandmarks68';\nimport { TNetInput } from '../dom/index';\nimport { FaceExpressionNet } from '../faceExpressionNet/FaceExpressionNet';\nimport { FaceExpressions } from '../faceExpressionNet/FaceExpressions';\nimport { FaceLandmark68Net } from '../faceLandmarkNet/FaceLandmark68Net';\nimport { FaceLandmark68TinyNet } from '../faceLandmarkNet/FaceLandmark68TinyNet';\nimport { FaceRecognitionNet } from '../faceRecognitionNet/FaceRecognitionNet';\nimport { SsdMobilenetv1 } from '../ssdMobilenetv1/SsdMobilenetv1';\nimport { SsdMobilenetv1Options } from '../ssdMobilenetv1/SsdMobilenetv1Options';\nimport { TinyFaceDetector } from '../tinyFaceDetector/TinyFaceDetector';\nimport { TinyFaceDetectorOptions } from '../tinyFaceDetector/TinyFaceDetectorOptions';\nimport { ITinyYolov2Options, TinyYolov2 } from '../tinyYolov2/index';\n\nexport const nets = {\n ssdMobilenetv1: new SsdMobilenetv1(),\n tinyFaceDetector: new TinyFaceDetector(),\n tinyYolov2: new TinyYolov2(),\n faceLandmark68Net: new FaceLandmark68Net(),\n faceLandmark68TinyNet: new FaceLandmark68TinyNet(),\n faceRecognitionNet: new FaceRecognitionNet(),\n faceExpressionNet: new FaceExpressionNet(),\n ageGenderNet: new AgeGenderNet(),\n};\n\n/**\n * Attempts to detect all faces in an image using SSD Mobilenetv1 Network.\n *\n * @param input The input image.\n * @param options (optional, default: see SsdMobilenetv1Options constructor for default parameters).\n * @returns Bounding box of each face with score.\n */\nexport const ssdMobilenetv1 = (input: TNetInput, options: SsdMobilenetv1Options): Promise => nets.ssdMobilenetv1.locateFaces(input, options);\n\n/**\n * Attempts to detect all faces in an image using the Tiny Face Detector.\n *\n * @param input The input image.\n * @param options (optional, default: see TinyFaceDetectorOptions constructor for default parameters).\n * @returns Bounding box of each face with score.\n */\nexport const tinyFaceDetector = (input: TNetInput, options: TinyFaceDetectorOptions): Promise => nets.tinyFaceDetector.locateFaces(input, options);\n\n/**\n * Attempts to detect all faces in an image using the Tiny Yolov2 Network.\n *\n * @param input The input image.\n * @param options (optional, default: see TinyYolov2Options constructor for default parameters).\n * @returns Bounding box of each face with score.\n */\nexport const tinyYolov2 = (input: TNetInput, options: ITinyYolov2Options): Promise => nets.tinyYolov2.locateFaces(input, options);\n\n/**\n * Detects the 68 point face landmark positions of the face shown in an image.\n *\n * @param inputs The face image extracted from the bounding box of a face. Can\n * also be an array of input images, which will be batch processed.\n * @returns 68 point face landmarks or array thereof in case of batch input.\n */\nexport const detectFaceLandmarks = (input: TNetInput): Promise => nets.faceLandmark68Net.detectLandmarks(input);\n\n/**\n * Detects the 68 point face landmark positions of the face shown in an image\n * using a tinier version of the 68 point face landmark model, which is slightly\n * faster at inference, but also slightly less accurate.\n *\n * @param inputs The face image extracted from the bounding box of a face. Can\n * also be an array of input images, which will be batch processed.\n * @returns 68 point face landmarks or array thereof in case of batch input.\n */\nexport const detectFaceLandmarksTiny = (input: TNetInput): Promise => nets.faceLandmark68TinyNet.detectLandmarks(input);\n\n/**\n * Computes a 128 entry vector (face descriptor / face embeddings) from the face shown in an image,\n * which uniquely represents the features of that persons face. The computed face descriptor can\n * be used to measure the similarity between faces, by computing the euclidean distance of two\n * face descriptors.\n *\n * @param inputs The face image extracted from the aligned bounding box of a face. Can\n * also be an array of input images, which will be batch processed.\n * @returns Face descriptor with 128 entries or array thereof in case of batch input.\n */\nexport const computeFaceDescriptor = (input: TNetInput): Promise => nets.faceRecognitionNet.computeFaceDescriptor(input);\n\n/**\n * Recognizes the facial expressions from a face image.\n *\n * @param inputs The face image extracted from the bounding box of a face. Can\n * also be an array of input images, which will be batch processed.\n * @returns Facial expressions with corresponding probabilities or array thereof in case of batch input.\n */\nexport const recognizeFaceExpressions = (input: TNetInput): Promise => nets.faceExpressionNet.predictExpressions(input);\n\n/**\n * Predicts age and gender from a face image.\n *\n * @param inputs The face image extracted from the bounding box of a face. Can\n * also be an array of input images, which will be batch processed.\n * @returns Predictions with age, gender and gender probability or array thereof in case of batch input.\n */\nexport const predictAgeAndGender = (input: TNetInput): Promise => nets.ageGenderNet.predictAgeAndGender(input);\n\nexport const loadSsdMobilenetv1Model = (url: string) => nets.ssdMobilenetv1.load(url);\nexport const loadTinyFaceDetectorModel = (url: string) => nets.tinyFaceDetector.load(url);\nexport const loadTinyYolov2Model = (url: string) => nets.tinyYolov2.load(url);\nexport const loadFaceLandmarkModel = (url: string) => nets.faceLandmark68Net.load(url);\nexport const loadFaceLandmarkTinyModel = (url: string) => nets.faceLandmark68TinyNet.load(url);\nexport const loadFaceRecognitionModel = (url: string) => nets.faceRecognitionNet.load(url);\nexport const loadFaceExpressionModel = (url: string) => nets.faceExpressionNet.load(url);\nexport const loadAgeGenderModel = (url: string) => nets.ageGenderNet.load(url);\n\n// backward compatibility\nexport const loadFaceDetectionModel = loadSsdMobilenetv1Model;\nexport const locateFaces = ssdMobilenetv1;\nexport const detectLandmarks = detectFaceLandmarks;\n", "/* eslint-disable max-classes-per-file */\nimport * as tf from '../../dist/tfjs.esm';\n\nimport { TNetInput } from '../dom/index';\nimport { FaceExpressions } from '../faceExpressionNet/FaceExpressions';\nimport { WithFaceDetection } from '../factories/WithFaceDetection';\nimport { extendWithFaceExpressions, WithFaceExpressions } from '../factories/WithFaceExpressions';\nimport { WithFaceLandmarks } from '../factories/WithFaceLandmarks';\nimport { ComposableTask } from './ComposableTask';\nimport { ComputeAllFaceDescriptorsTask, ComputeSingleFaceDescriptorTask } from './ComputeFaceDescriptorsTasks';\nimport { extractAllFacesAndComputeResults, extractSingleFaceAndComputeResult } from './extractFacesAndComputeResults';\nimport { nets } from './nets';\nimport {\n PredictAllAgeAndGenderTask,\n PredictAllAgeAndGenderWithFaceAlignmentTask,\n PredictSingleAgeAndGenderTask,\n PredictSingleAgeAndGenderWithFaceAlignmentTask,\n} from './PredictAgeAndGenderTask';\n\nexport class PredictFaceExpressionsTaskBase extends ComposableTask {\n constructor(\n // eslint-disable-next-line no-unused-vars\n protected parentTask: ComposableTask | Promise,\n // eslint-disable-next-line no-unused-vars\n protected input: TNetInput,\n // eslint-disable-next-line no-unused-vars\n protected extractedFaces?: Array,\n ) {\n super();\n }\n}\n\nexport class PredictAllFaceExpressionsTask<\n TSource extends WithFaceDetection<{}>\n> extends PredictFaceExpressionsTaskBase[], TSource[]> {\n public async run(): Promise[]> {\n const parentResults = await this.parentTask;\n\n const faceExpressionsByFace = await extractAllFacesAndComputeResults(\n parentResults,\n this.input,\n async (faces) => Promise.all(faces.map(\n (face) => nets.faceExpressionNet.predictExpressions(face) as Promise,\n )),\n this.extractedFaces,\n );\n\n return parentResults.map(\n (parentResult, i) => extendWithFaceExpressions(parentResult, faceExpressionsByFace[i]),\n );\n }\n\n withAgeAndGender() {\n return new PredictAllAgeAndGenderTask(this, this.input);\n }\n}\n\nexport class PredictSingleFaceExpressionsTask<\n TSource extends WithFaceDetection<{}>\n> extends PredictFaceExpressionsTaskBase | undefined, TSource | undefined> {\n public async run(): Promise | undefined> {\n const parentResult = await this.parentTask;\n if (!parentResult) {\n return undefined;\n }\n\n const faceExpressions = await extractSingleFaceAndComputeResult(\n parentResult,\n this.input,\n (face) => nets.faceExpressionNet.predictExpressions(face) as Promise,\n this.extractedFaces,\n );\n\n return extendWithFaceExpressions(parentResult, faceExpressions);\n }\n\n withAgeAndGender() {\n return new PredictSingleAgeAndGenderTask(this, this.input);\n }\n}\n\nexport class PredictAllFaceExpressionsWithFaceAlignmentTask<\n TSource extends WithFaceLandmarks>\n> extends PredictAllFaceExpressionsTask {\n withAgeAndGender() {\n return new PredictAllAgeAndGenderWithFaceAlignmentTask(this, this.input);\n }\n\n withFaceDescriptors() {\n return new ComputeAllFaceDescriptorsTask(this, this.input);\n }\n}\n\nexport class PredictSingleFaceExpressionsWithFaceAlignmentTask<\n TSource extends WithFaceLandmarks>\n> extends PredictSingleFaceExpressionsTask {\n withAgeAndGender() {\n return new PredictSingleAgeAndGenderWithFaceAlignmentTask(this, this.input);\n }\n\n withFaceDescriptor() {\n return new ComputeSingleFaceDescriptorTask(this, this.input);\n }\n}\n", "/* eslint-disable max-classes-per-file */\nimport * as tf from '../../dist/tfjs.esm';\n\nimport { AgeAndGenderPrediction } from '../ageGenderNet/types';\nimport { TNetInput } from '../dom/index';\nimport { extendWithAge, WithAge } from '../factories/WithAge';\nimport { WithFaceDetection } from '../factories/WithFaceDetection';\nimport { WithFaceLandmarks } from '../factories/WithFaceLandmarks';\nimport { extendWithGender, WithGender } from '../factories/WithGender';\nimport { ComposableTask } from './ComposableTask';\nimport { ComputeAllFaceDescriptorsTask, ComputeSingleFaceDescriptorTask } from './ComputeFaceDescriptorsTasks';\nimport { extractAllFacesAndComputeResults, extractSingleFaceAndComputeResult } from './extractFacesAndComputeResults';\nimport { nets } from './nets';\nimport {\n PredictAllFaceExpressionsTask,\n PredictAllFaceExpressionsWithFaceAlignmentTask,\n PredictSingleFaceExpressionsTask,\n PredictSingleFaceExpressionsWithFaceAlignmentTask,\n} from './PredictFaceExpressionsTask';\n\nexport class PredictAgeAndGenderTaskBase extends ComposableTask {\n constructor(\n // eslint-disable-next-line no-unused-vars\n protected parentTask: ComposableTask | Promise,\n // eslint-disable-next-line no-unused-vars\n protected input: TNetInput,\n // eslint-disable-next-line no-unused-vars\n protected extractedFaces?: Array,\n ) {\n super();\n }\n}\n\nexport class PredictAllAgeAndGenderTask<\n TSource extends WithFaceDetection<{}>\n> extends PredictAgeAndGenderTaskBase>[], TSource[]> {\n public async run(): Promise>[]> {\n const parentResults = await this.parentTask;\n\n const ageAndGenderByFace = await extractAllFacesAndComputeResults(\n parentResults,\n this.input,\n async (faces) => Promise.all(faces.map(\n (face) => nets.ageGenderNet.predictAgeAndGender(face) as Promise,\n )),\n this.extractedFaces,\n );\n\n return parentResults.map((parentResult, i) => {\n const { age, gender, genderProbability } = ageAndGenderByFace[i];\n return extendWithAge(extendWithGender(parentResult, gender, genderProbability), age);\n });\n }\n\n withFaceExpressions() {\n return new PredictAllFaceExpressionsTask(this, this.input);\n }\n}\n\nexport class PredictSingleAgeAndGenderTask<\n TSource extends WithFaceDetection<{}>\n> extends PredictAgeAndGenderTaskBase> | undefined, TSource | undefined> {\n public async run(): Promise> | undefined> {\n const parentResult = await this.parentTask;\n if (!parentResult) {\n return undefined;\n }\n\n const { age, gender, genderProbability } = await extractSingleFaceAndComputeResult(\n parentResult,\n this.input,\n (face) => nets.ageGenderNet.predictAgeAndGender(face) as Promise,\n this.extractedFaces,\n );\n\n return extendWithAge(extendWithGender(parentResult, gender, genderProbability), age);\n }\n\n withFaceExpressions() {\n return new PredictSingleFaceExpressionsTask(this, this.input);\n }\n}\n\nexport class PredictAllAgeAndGenderWithFaceAlignmentTask<\n TSource extends WithFaceLandmarks>\n> extends PredictAllAgeAndGenderTask {\n withFaceExpressions() {\n return new PredictAllFaceExpressionsWithFaceAlignmentTask(this, this.input);\n }\n\n withFaceDescriptors() {\n return new ComputeAllFaceDescriptorsTask(this, this.input);\n }\n}\n\nexport class PredictSingleAgeAndGenderWithFaceAlignmentTask<\n TSource extends WithFaceLandmarks>\n> extends PredictSingleAgeAndGenderTask {\n withFaceExpressions() {\n return new PredictSingleFaceExpressionsWithFaceAlignmentTask(this, this.input);\n }\n\n withFaceDescriptor() {\n return new ComputeSingleFaceDescriptorTask(this, this.input);\n }\n}\n", "/* eslint-disable max-classes-per-file */\nimport { TNetInput } from '../dom/index';\nimport { extendWithFaceDescriptor, WithFaceDescriptor } from '../factories/WithFaceDescriptor';\nimport { WithFaceDetection } from '../factories/WithFaceDetection';\nimport { WithFaceLandmarks } from '../factories/WithFaceLandmarks';\nimport { ComposableTask } from './ComposableTask';\nimport { extractAllFacesAndComputeResults, extractSingleFaceAndComputeResult } from './extractFacesAndComputeResults';\nimport { nets } from './nets';\nimport {\n PredictAllAgeAndGenderWithFaceAlignmentTask,\n PredictSingleAgeAndGenderWithFaceAlignmentTask,\n} from './PredictAgeAndGenderTask';\nimport {\n PredictAllFaceExpressionsWithFaceAlignmentTask,\n PredictSingleFaceExpressionsWithFaceAlignmentTask,\n} from './PredictFaceExpressionsTask';\n\nexport class ComputeFaceDescriptorsTaskBase extends ComposableTask {\n constructor(\n // eslint-disable-next-line no-unused-vars\n protected parentTask: ComposableTask | Promise,\n // eslint-disable-next-line no-unused-vars\n protected input: TNetInput,\n ) {\n super();\n }\n}\n\nexport class ComputeAllFaceDescriptorsTask<\n TSource extends WithFaceLandmarks>\n> extends ComputeFaceDescriptorsTaskBase[], TSource[]> {\n public async run(): Promise[]> {\n const parentResults = await this.parentTask;\n\n const descriptors = await extractAllFacesAndComputeResults(\n parentResults,\n this.input,\n (faces) => Promise.all(faces.map((face) => nets.faceRecognitionNet.computeFaceDescriptor(face) as Promise)),\n null,\n (parentResult) => parentResult.landmarks.align(null, { useDlibAlignment: true }),\n );\n\n return descriptors.map((descriptor, i) => extendWithFaceDescriptor(parentResults[i], descriptor));\n }\n\n withFaceExpressions() {\n return new PredictAllFaceExpressionsWithFaceAlignmentTask(this, this.input);\n }\n\n withAgeAndGender() {\n return new PredictAllAgeAndGenderWithFaceAlignmentTask(this, this.input);\n }\n}\n\nexport class ComputeSingleFaceDescriptorTask<\n TSource extends WithFaceLandmarks>\n> extends ComputeFaceDescriptorsTaskBase | undefined, TSource | undefined> {\n public async run(): Promise | undefined> {\n const parentResult = await this.parentTask;\n if (!parentResult) {\n return undefined;\n }\n const descriptor = await extractSingleFaceAndComputeResult(\n parentResult,\n this.input,\n (face) => nets.faceRecognitionNet.computeFaceDescriptor(face) as Promise,\n null,\n // eslint-disable-next-line no-shadow\n (parentResult) => parentResult.landmarks.align(null, { useDlibAlignment: true }),\n );\n\n return extendWithFaceDescriptor(parentResult, descriptor);\n }\n\n withFaceExpressions() {\n return new PredictSingleFaceExpressionsWithFaceAlignmentTask(this, this.input);\n }\n\n withAgeAndGender() {\n return new PredictSingleAgeAndGenderWithFaceAlignmentTask(this, this.input);\n }\n}\n", "/* eslint-disable max-classes-per-file */\nimport { FaceDetection } from '../classes/FaceDetection';\nimport { TNetInput } from '../dom/index';\nimport { extendWithFaceDetection, WithFaceDetection } from '../factories/WithFaceDetection';\nimport { SsdMobilenetv1Options } from '../ssdMobilenetv1/SsdMobilenetv1Options';\nimport { TinyFaceDetectorOptions } from '../tinyFaceDetector/TinyFaceDetectorOptions';\nimport { TinyYolov2Options } from '../tinyYolov2/index';\nimport { ComposableTask } from './ComposableTask';\nimport { DetectAllFaceLandmarksTask, DetectSingleFaceLandmarksTask } from './DetectFaceLandmarksTasks';\nimport { nets } from './nets';\nimport { PredictAllAgeAndGenderTask, PredictSingleAgeAndGenderTask } from './PredictAgeAndGenderTask';\nimport { PredictAllFaceExpressionsTask, PredictSingleFaceExpressionsTask } from './PredictFaceExpressionsTask';\nimport { FaceDetectionOptions } from './types';\n\nexport class DetectFacesTaskBase extends ComposableTask {\n constructor(\n // eslint-disable-next-line no-unused-vars\n protected input: TNetInput,\n // eslint-disable-next-line no-unused-vars\n protected options: FaceDetectionOptions = new SsdMobilenetv1Options(),\n ) {\n super();\n }\n}\n\nexport class DetectAllFacesTask extends DetectFacesTaskBase {\n public async run(): Promise {\n const { input, options } = this;\n\n let result;\n if (options instanceof TinyFaceDetectorOptions) result = nets.tinyFaceDetector.locateFaces(input, options);\n else if (options instanceof SsdMobilenetv1Options) result = nets.ssdMobilenetv1.locateFaces(input, options);\n else if (options instanceof TinyYolov2Options) result = nets.tinyYolov2.locateFaces(input, options);\n else throw new Error('detectFaces - expected options to be instance of TinyFaceDetectorOptions | SsdMobilenetv1Options | TinyYolov2Options');\n\n return result;\n }\n\n private runAndExtendWithFaceDetections(): Promise[]> {\n // eslint-disable-next-line no-async-promise-executor\n return new Promise[]>(async (resolve) => {\n const detections = await this.run();\n resolve(detections.map((detection) => extendWithFaceDetection({}, detection)));\n });\n }\n\n withFaceLandmarks(useTinyLandmarkNet: boolean = false) {\n return new DetectAllFaceLandmarksTask(\n this.runAndExtendWithFaceDetections(),\n this.input,\n useTinyLandmarkNet,\n );\n }\n\n withFaceExpressions() {\n return new PredictAllFaceExpressionsTask(\n this.runAndExtendWithFaceDetections(),\n this.input,\n );\n }\n\n withAgeAndGender() {\n return new PredictAllAgeAndGenderTask(\n this.runAndExtendWithFaceDetections(),\n this.input,\n );\n }\n}\n\nexport class DetectSingleFaceTask extends DetectFacesTaskBase {\n public async run(): Promise {\n const faceDetections = await new DetectAllFacesTask(this.input, this.options);\n let faceDetectionWithHighestScore = faceDetections[0];\n faceDetections.forEach((faceDetection) => {\n if (faceDetection.score > faceDetectionWithHighestScore.score) faceDetectionWithHighestScore = faceDetection;\n });\n return faceDetectionWithHighestScore;\n }\n\n private runAndExtendWithFaceDetection(): Promise | undefined> {\n // eslint-disable-next-line no-async-promise-executor\n return new Promise | undefined>(async (resolve) => {\n const detection = await this.run();\n resolve(detection ? extendWithFaceDetection<{}>({}, detection) : undefined);\n });\n }\n\n withFaceLandmarks(useTinyLandmarkNet: boolean = false) {\n return new DetectSingleFaceLandmarksTask(\n this.runAndExtendWithFaceDetection(),\n this.input,\n useTinyLandmarkNet,\n );\n }\n\n withFaceExpressions() {\n return new PredictSingleFaceExpressionsTask(\n this.runAndExtendWithFaceDetection(),\n this.input,\n );\n }\n\n withAgeAndGender() {\n return new PredictSingleAgeAndGenderTask(\n this.runAndExtendWithFaceDetection(),\n this.input,\n );\n }\n}\n", "import { TNetInput } from '../dom/index';\nimport { SsdMobilenetv1Options } from '../ssdMobilenetv1/SsdMobilenetv1Options';\nimport { DetectAllFacesTask, DetectSingleFaceTask } from './DetectFacesTasks';\nimport { FaceDetectionOptions } from './types';\n\nexport function detectSingleFace(input: TNetInput, options: FaceDetectionOptions = new SsdMobilenetv1Options()): DetectSingleFaceTask {\n return new DetectSingleFaceTask(input, options);\n}\n\nexport function detectAllFaces(input: TNetInput, options: FaceDetectionOptions = new SsdMobilenetv1Options()): DetectAllFacesTask {\n return new DetectAllFacesTask(input, options);\n}\n", "import { TNetInput } from '../dom/index';\nimport { WithFaceDescriptor, WithFaceDetection, WithFaceLandmarks } from '../factories/index';\nimport { SsdMobilenetv1Options } from '../ssdMobilenetv1/index';\nimport { ITinyYolov2Options, TinyYolov2Options } from '../tinyYolov2/index';\nimport { detectAllFaces } from './detectFaces';\n\n// export allFaces API for backward compatibility\n\nexport async function allFacesSsdMobilenetv1(\n input: TNetInput,\n minConfidence?: number,\n): Promise>>[]> {\n return detectAllFaces(input, new SsdMobilenetv1Options(minConfidence ? { minConfidence } : {}))\n .withFaceLandmarks()\n .withFaceDescriptors();\n}\n\nexport async function allFacesTinyYolov2(\n input: TNetInput,\n forwardParams: ITinyYolov2Options = {},\n): Promise>>[]> {\n return detectAllFaces(input, new TinyYolov2Options(forwardParams))\n .withFaceLandmarks()\n .withFaceDescriptors();\n}\n\nexport const allFaces = allFacesSsdMobilenetv1;\n", "export function euclideanDistance(arr1: number[] | Float32Array, arr2: number[] | Float32Array) {\n if (arr1.length !== arr2.length) throw new Error('euclideanDistance: arr1.length !== arr2.length');\n\n const desc1 = Array.from(arr1);\n const desc2 = Array.from(arr2);\n\n return Math.sqrt(\n desc1\n .map((val, i) => val - desc2[i])\n .reduce((res, diff) => res + (diff ** 2), 0),\n );\n}\n", "import { FaceMatch } from '../classes/FaceMatch';\nimport { LabeledFaceDescriptors } from '../classes/LabeledFaceDescriptors';\nimport { euclideanDistance } from '../euclideanDistance';\nimport { WithFaceDescriptor } from '../factories/index';\n\nexport class FaceMatcher {\n private _labeledDescriptors: LabeledFaceDescriptors[]\n\n private _distanceThreshold: number\n\n constructor(\n inputs: LabeledFaceDescriptors | WithFaceDescriptor | Float32Array | Array | Float32Array>,\n distanceThreshold: number = 0.6,\n ) {\n this._distanceThreshold = distanceThreshold;\n\n const inputArray = Array.isArray(inputs) ? inputs : [inputs];\n\n if (!inputArray.length) {\n throw new Error('FaceRecognizer.constructor - expected atleast one input');\n }\n\n let count = 1;\n const createUniqueLabel = () => `person ${count++}`;\n\n this._labeledDescriptors = inputArray.map((desc) => {\n if (desc instanceof LabeledFaceDescriptors) {\n return desc;\n }\n\n if (desc instanceof Float32Array) {\n return new LabeledFaceDescriptors(createUniqueLabel(), [desc]);\n }\n\n if (desc.descriptor && desc.descriptor instanceof Float32Array) {\n return new LabeledFaceDescriptors(createUniqueLabel(), [desc.descriptor]);\n }\n\n throw new Error('FaceRecognizer.constructor - expected inputs to be of type LabeledFaceDescriptors | WithFaceDescriptor | Float32Array | Array | Float32Array>');\n });\n }\n\n public get labeledDescriptors(): LabeledFaceDescriptors[] { return this._labeledDescriptors; }\n\n public get distanceThreshold(): number { return this._distanceThreshold; }\n\n public computeMeanDistance(queryDescriptor: Float32Array, descriptors: Float32Array[]): number {\n return descriptors\n .map((d) => euclideanDistance(d, queryDescriptor))\n .reduce((d1, d2) => d1 + d2, 0)\n / (descriptors.length || 1);\n }\n\n public matchDescriptor(queryDescriptor: Float32Array): FaceMatch {\n return this.labeledDescriptors\n .map(({ descriptors, label }) => new FaceMatch(\n label,\n this.computeMeanDistance(queryDescriptor, descriptors),\n ))\n .reduce((best, curr) => (best.distance < curr.distance ? best : curr));\n }\n\n public findBestMatch(queryDescriptor: Float32Array): FaceMatch {\n const bestMatch = this.matchDescriptor(queryDescriptor);\n return bestMatch.distance < this.distanceThreshold\n ? bestMatch\n : new FaceMatch('unknown', bestMatch.distance);\n }\n\n public toJSON(): any {\n return {\n distanceThreshold: this.distanceThreshold,\n labeledDescriptors: this.labeledDescriptors.map((ld) => ld.toJSON()),\n };\n }\n\n public static fromJSON(json: any): FaceMatcher {\n const labeledDescriptors = json.labeledDescriptors\n .map((ld: any) => LabeledFaceDescriptors.fromJSON(ld));\n return new FaceMatcher(labeledDescriptors, json.distanceThreshold);\n }\n}\n", "import { TinyFaceDetector } from './TinyFaceDetector';\n\nexport * from './TinyFaceDetector';\nexport * from './TinyFaceDetectorOptions';\n\nexport function createTinyFaceDetector(weights: Float32Array) {\n const net = new TinyFaceDetector();\n net.extractWeights(weights);\n return net;\n}\n", "import { Dimensions, IDimensions } from './classes/index';\nimport { FaceDetection } from './classes/FaceDetection';\nimport { FaceLandmarks } from './classes/FaceLandmarks';\nimport { extendWithFaceDetection, isWithFaceDetection } from './factories/WithFaceDetection';\nimport { extendWithFaceLandmarks, isWithFaceLandmarks } from './factories/WithFaceLandmarks';\n\nexport function resizeResults(results: T, dimensions: IDimensions): T {\n const { width, height } = new Dimensions(dimensions.width, dimensions.height);\n\n if (width <= 0 || height <= 0) {\n throw new Error(`resizeResults - invalid dimensions: ${JSON.stringify({ width, height })}`);\n }\n\n if (Array.isArray(results)) {\n // return results.map(obj => resizeResults(obj, { width, height })) as any as T\n return (results as Array).map((obj) => resizeResults(obj, { width, height } as IDimensions)) as any as T;\n }\n\n if (isWithFaceLandmarks(results)) {\n const resizedDetection = results.detection.forSize(width, height);\n const resizedLandmarks = results.unshiftedLandmarks.forSize(resizedDetection.box.width, resizedDetection.box.height);\n return extendWithFaceLandmarks(extendWithFaceDetection(results, resizedDetection), resizedLandmarks);\n }\n\n if (isWithFaceDetection(results)) {\n return extendWithFaceDetection(results, results.detection.forSize(width, height));\n }\n\n if (results instanceof FaceLandmarks || results instanceof FaceDetection) {\n return (results as any).forSize(width, height);\n }\n\n return results;\n}\n"],
- "mappings": "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",
+ "sourcesContent": ["/* eslint-disable import/no-extraneous-dependencies */\n/* eslint-disable node/no-unpublished-import */\n\n// wrapper to load tfjs in a single place so version can be changed quickly\n\nexport * from '@tensorflow/tfjs/dist/index.js';\nexport * from '@tensorflow/tfjs-backend-wasm';\n", "export function isNodejs(): boolean {\n return typeof global === 'object'\n && typeof require === 'function'\n && typeof module !== 'undefined'\n && typeof process !== 'undefined' && !!process.version;\n}\n", "import * as tf from '../dist/tfjs.esm';\nimport * as draw from './draw/index';\nimport * as utils from './utils/index';\nimport * as pkg from '../package.json';\n\nexport { tf, draw, utils };\n\nexport * from './ageGenderNet/index';\nexport * from './classes/index';\nexport * from './dom/index';\nexport * from './env/index';\nexport * from './faceExpressionNet/index';\nexport * from './faceLandmarkNet/index';\nexport * from './faceRecognitionNet/index';\nexport * from './factories/index';\nexport * from './globalApi/index';\nexport * from './ops/index';\nexport * from './ssdMobilenetv1/index';\nexport * from './tinyFaceDetector/index';\nexport * from './tinyYolov2/index';\nexport * from './euclideanDistance';\nexport * from './NeuralNetwork';\nexport * from './resizeResults';\n\nconst node = (typeof process !== 'undefined');\nconst browser = (typeof navigator !== 'undefined') && (typeof navigator.userAgent !== 'undefined');\nexport const version = { faceapi: pkg.version as string, node, browser };\n", "export * from './drawContour';\nexport * from './drawDetections';\nexport * from './drawFaceExpressions';\nexport * from './DrawBox';\nexport * from './DrawFaceLandmarks';\nexport * from './DrawTextField';\n", "import { Point } from '../classes/index';\n\nexport function drawContour(\n ctx: CanvasRenderingContext2D,\n points: Point[],\n isClosed: boolean = false,\n) {\n ctx.beginPath();\n\n points.slice(1).forEach(({ x, y }, prevIdx) => {\n const from = points[prevIdx];\n ctx.moveTo(from.x, from.y);\n ctx.lineTo(x, y);\n });\n\n if (isClosed) {\n const from = points[points.length - 1];\n const to = points[0];\n if (!from || !to) {\n return;\n }\n\n ctx.moveTo(from.x, from.y);\n ctx.lineTo(to.x, to.y);\n }\n\n ctx.stroke();\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nimport { Point } from '../classes/index';\nimport { Dimensions, IDimensions } from '../classes/Dimensions';\n\nexport function isTensor(tensor: any, dim: number) {\n return tensor instanceof tf.Tensor && tensor.shape.length === dim;\n}\n\nexport function isTensor1D(tensor: any): tensor is tf.Tensor1D {\n return isTensor(tensor, 1);\n}\n\nexport function isTensor2D(tensor: any): tensor is tf.Tensor2D {\n return isTensor(tensor, 2);\n}\n\nexport function isTensor3D(tensor: any): tensor is tf.Tensor3D {\n return isTensor(tensor, 3);\n}\n\nexport function isTensor4D(tensor: any): tensor is tf.Tensor4D {\n return isTensor(tensor, 4);\n}\n\nexport function isFloat(num: number) {\n return num % 1 !== 0;\n}\n\nexport function isEven(num: number) {\n return num % 2 === 0;\n}\n\nexport function round(num: number, prec: number = 2) {\n const f = 10 ** prec;\n return Math.floor(num * f) / f;\n}\n\nexport function isDimensions(obj: any): boolean {\n return obj && obj.width && obj.height;\n}\n\nexport function computeReshapedDimensions({ width, height }: IDimensions, inputSize: number) {\n const scale = inputSize / Math.max(height, width);\n return new Dimensions(Math.round(width * scale), Math.round(height * scale));\n}\n\nexport function getCenterPoint(pts: Point[]): Point {\n return pts.reduce((sum, pt) => sum.add(pt), new Point(0, 0))\n .div(new Point(pts.length, pts.length));\n}\n\nexport function range(num: number, start: number, step: number): number[] {\n return Array(num).fill(0).map((_, i) => start + (i * step));\n}\n\nexport function isValidNumber(num: any) {\n return !!num && (num !== Infinity) && (num !== -Infinity) && !Number.isNaN(num) || num === 0;\n}\n\nexport function isValidProbablitiy(num: any) {\n return isValidNumber(num) && num >= 0 && num <= 1.0;\n}\n", "import { isValidNumber } from '../utils/index';\n\nexport interface IDimensions {\n width: number\n height: number\n}\n\nexport class Dimensions implements IDimensions {\n private _width: number\n\n private _height: number\n\n constructor(width: number, height: number) {\n if (!isValidNumber(width) || !isValidNumber(height)) {\n throw new Error(`Dimensions.constructor - expected width and height to be valid numbers, instead have ${JSON.stringify({ width, height })}`);\n }\n\n this._width = width;\n this._height = height;\n }\n\n public get width(): number { return this._width; }\n\n public get height(): number { return this._height; }\n\n public reverse(): Dimensions {\n return new Dimensions(1 / this.width, 1 / this.height);\n }\n}\n", "export interface IPoint {\n x: number\n y: number\n}\n\nexport class Point implements IPoint {\n private _x: number\n\n private _y: number\n\n constructor(x: number, y: number) {\n this._x = x;\n this._y = y;\n }\n\n get x(): number { return this._x; }\n\n get y(): number { return this._y; }\n\n public add(pt: IPoint): Point {\n return new Point(this.x + pt.x, this.y + pt.y);\n }\n\n public sub(pt: IPoint): Point {\n return new Point(this.x - pt.x, this.y - pt.y);\n }\n\n public mul(pt: IPoint): Point {\n return new Point(this.x * pt.x, this.y * pt.y);\n }\n\n public div(pt: IPoint): Point {\n return new Point(this.x / pt.x, this.y / pt.y);\n }\n\n public abs(): Point {\n return new Point(Math.abs(this.x), Math.abs(this.y));\n }\n\n public magnitude(): number {\n return Math.sqrt((this.x ** 2) + (this.y ** 2));\n }\n\n public floor(): Point {\n return new Point(Math.floor(this.x), Math.floor(this.y));\n }\n}\n", "import { isDimensions, isValidNumber } from '../utils/index';\nimport { IBoundingBox } from './BoundingBox';\nimport { IDimensions } from './Dimensions';\nimport { Point } from './Point';\nimport { IRect } from './Rect';\n\nexport class Box implements IBoundingBox, IRect {\n public static isRect(rect: any): boolean {\n return !!rect && [rect.x, rect.y, rect.width, rect.height].every(isValidNumber);\n }\n\n public static assertIsValidBox(box: any, callee: string, allowNegativeDimensions: boolean = false) {\n if (!Box.isRect(box)) {\n throw new Error(`${callee} - invalid box: ${JSON.stringify(box)}, expected object with properties x, y, width, height`);\n }\n\n if (!allowNegativeDimensions && (box.width < 0 || box.height < 0)) {\n throw new Error(`${callee} - width (${box.width}) and height (${box.height}) must be positive numbers`);\n }\n }\n\n private _x: number\n\n private _y: number\n\n private _width: number\n\n private _height: number\n\n constructor(_box: IBoundingBox | IRect, allowNegativeDimensions: boolean = true) {\n const box = (_box || {}) as any;\n\n const isBbox = [box.left, box.top, box.right, box.bottom].every(isValidNumber);\n const isRect = [box.x, box.y, box.width, box.height].every(isValidNumber);\n\n if (!isRect && !isBbox) {\n throw new Error(`Box.constructor - expected box to be IBoundingBox | IRect, instead have ${JSON.stringify(box)}`);\n }\n\n const [x, y, width, height] = isRect\n ? [box.x, box.y, box.width, box.height]\n : [box.left, box.top, box.right - box.left, box.bottom - box.top];\n\n Box.assertIsValidBox({\n x, y, width, height,\n }, 'Box.constructor', allowNegativeDimensions);\n\n this._x = x;\n this._y = y;\n this._width = width;\n this._height = height;\n }\n\n public get x(): number { return this._x; }\n\n public get y(): number { return this._y; }\n\n public get width(): number { return this._width; }\n\n public get height(): number { return this._height; }\n\n public get left(): number { return this.x; }\n\n public get top(): number { return this.y; }\n\n public get right(): number { return this.x + this.width; }\n\n public get bottom(): number { return this.y + this.height; }\n\n public get area(): number { return this.width * this.height; }\n\n public get topLeft(): Point { return new Point(this.left, this.top); }\n\n public get topRight(): Point { return new Point(this.right, this.top); }\n\n public get bottomLeft(): Point { return new Point(this.left, this.bottom); }\n\n public get bottomRight(): Point { return new Point(this.right, this.bottom); }\n\n public round(): Box {\n const [x, y, width, height] = [this.x, this.y, this.width, this.height]\n .map((val) => Math.round(val));\n return new Box({\n x, y, width, height,\n });\n }\n\n public floor(): Box {\n const [x, y, width, height] = [this.x, this.y, this.width, this.height]\n .map((val) => Math.floor(val));\n return new Box({\n x, y, width, height,\n });\n }\n\n public toSquare(): Box {\n let {\n x, y, width, height,\n } = this;\n const diff = Math.abs(width - height);\n if (width < height) {\n x -= (diff / 2);\n width += diff;\n }\n if (height < width) {\n y -= (diff / 2);\n height += diff;\n }\n\n return new Box({ x, y, width, height });\n }\n\n public rescale(s: IDimensions | number): Box {\n const scaleX = isDimensions(s) ? (s as IDimensions).width : s as number;\n const scaleY = isDimensions(s) ? (s as IDimensions).height : s as number;\n return new Box({\n x: this.x * scaleX,\n y: this.y * scaleY,\n width: this.width * scaleX,\n height: this.height * scaleY,\n });\n }\n\n public pad(padX: number, padY: number): Box {\n const [x, y, width, height] = [\n this.x - (padX / 2),\n this.y - (padY / 2),\n this.width + padX,\n this.height + padY,\n ];\n return new Box({\n x, y, width, height,\n });\n }\n\n public clipAtImageBorders(imgWidth: number, imgHeight: number): Box {\n const { x, y, right, bottom } = this;\n const clippedX = Math.max(x, 0);\n const clippedY = Math.max(y, 0);\n\n const newWidth = right - clippedX;\n const newHeight = bottom - clippedY;\n const clippedWidth = Math.min(newWidth, imgWidth - clippedX);\n const clippedHeight = Math.min(newHeight, imgHeight - clippedY);\n\n return (new Box({\n x: clippedX, y: clippedY, width: clippedWidth, height: clippedHeight,\n })).floor();\n }\n\n public shift(sx: number, sy: number): Box {\n const { width, height } = this;\n const x = this.x + sx;\n const y = this.y + sy;\n\n return new Box({\n x, y, width, height,\n });\n }\n\n public padAtBorders(imageHeight: number, imageWidth: number) {\n const w = this.width + 1;\n const h = this.height + 1;\n\n const dx = 1;\n const dy = 1;\n let edx = w;\n let edy = h;\n\n let x = this.left;\n let y = this.top;\n let ex = this.right;\n let ey = this.bottom;\n\n if (ex > imageWidth) {\n edx = -ex + imageWidth + w;\n ex = imageWidth;\n }\n if (ey > imageHeight) {\n edy = -ey + imageHeight + h;\n ey = imageHeight;\n }\n if (x < 1) {\n edy = 2 - x;\n x = 1;\n }\n if (y < 1) {\n edy = 2 - y;\n y = 1;\n }\n\n return {\n dy, edy, dx, edx, y, ey, x, ex, w, h,\n };\n }\n\n public calibrate(region: Box) {\n return new Box({\n left: this.left + (region.left * this.width),\n top: this.top + (region.top * this.height),\n right: this.right + (region.right * this.width),\n bottom: this.bottom + (region.bottom * this.height),\n }).toSquare().round();\n }\n}\n", "import { Box } from './Box';\n\nexport interface IBoundingBox {\n left: number\n top: number\n right: number\n bottom: number\n}\n\nexport class BoundingBox extends Box implements IBoundingBox {\n constructor(left: number, top: number, right: number, bottom: number, allowNegativeDimensions: boolean = false) {\n super({\n left, top, right, bottom,\n }, allowNegativeDimensions);\n }\n}\n", "import { Box } from './Box';\nimport { Dimensions, IDimensions } from './Dimensions';\nimport { IRect, Rect } from './Rect';\n\nexport class ObjectDetection {\n private _score: number\n\n private _classScore: number\n\n private _className: string\n\n private _box: Rect\n\n private _imageDims: Dimensions\n\n constructor(\n score: number,\n classScore: number,\n className: string,\n relativeBox: IRect,\n imageDims: IDimensions,\n ) {\n this._imageDims = new Dimensions(imageDims.width, imageDims.height);\n this._score = score;\n this._classScore = classScore;\n this._className = className;\n this._box = new Box(relativeBox).rescale(this._imageDims);\n }\n\n public get score(): number { return this._score; }\n\n public get classScore(): number { return this._classScore; }\n\n public get className(): string { return this._className; }\n\n public get box(): Box { return this._box; }\n\n public get imageDims(): Dimensions { return this._imageDims; }\n\n public get imageWidth(): number { return this.imageDims.width; }\n\n public get imageHeight(): number { return this.imageDims.height; }\n\n public get relativeBox(): Box { return new Box(this._box).rescale(this.imageDims.reverse()); }\n\n public forSize(width: number, height: number): ObjectDetection {\n return new ObjectDetection(\n this.score,\n this.classScore,\n this.className,\n this.relativeBox,\n { width, height },\n );\n }\n}\n", "import { Box } from './Box';\nimport { IDimensions } from './Dimensions';\nimport { ObjectDetection } from './ObjectDetection';\nimport { Rect } from './Rect';\n\nexport interface IFaceDetecion {\n score: number\n box: Box\n}\n\nexport class FaceDetection extends ObjectDetection implements IFaceDetecion {\n constructor(\n score: number,\n relativeBox: Rect,\n imageDims: IDimensions,\n ) {\n super(score, score, '', relativeBox, imageDims);\n }\n\n public forSize(width: number, height: number): FaceDetection {\n const { score, relativeBox, imageDims } = super.forSize(width, height);\n return new FaceDetection(score, relativeBox, imageDims);\n }\n}\n", "import { Box } from '../classes/Box';\n\nexport function iou(box1: Box, box2: Box, isIOU: boolean = true) {\n const width = Math.max(0.0, Math.min(box1.right, box2.right) - Math.max(box1.left, box2.left));\n const height = Math.max(0.0, Math.min(box1.bottom, box2.bottom) - Math.max(box1.top, box2.top));\n const interSection = width * height;\n\n return isIOU\n ? interSection / (box1.area + box2.area - interSection)\n : interSection / Math.min(box1.area, box2.area);\n}\n", "import { BoundingBox, IPoint } from '../classes/index';\n\nexport function minBbox(pts: IPoint[]): BoundingBox {\n const xs = pts.map((pt) => pt.x);\n const ys = pts.map((pt) => pt.y);\n const minX = xs.reduce((min, x) => (x < min ? x : min), Infinity);\n const minY = ys.reduce((min, y) => (y < min ? y : min), Infinity);\n const maxX = xs.reduce((max, x) => (max < x ? x : max), 0);\n const maxY = ys.reduce((max, y) => (max < y ? y : max), 0);\n\n return new BoundingBox(minX, minY, maxX, maxY);\n}\n", "import { Box } from '../classes/Box';\nimport { iou } from './iou';\n\nexport function nonMaxSuppression(\n boxes: Box[],\n scores: number[],\n iouThreshold: number,\n isIOU: boolean = true,\n): number[] {\n let indicesSortedByScore = scores\n .map((score, boxIndex) => ({ score, boxIndex }))\n .sort((c1, c2) => c1.score - c2.score)\n .map((c) => c.boxIndex);\n\n const pick: number[] = [];\n\n while (indicesSortedByScore.length > 0) {\n const curr = indicesSortedByScore.pop() as number;\n pick.push(curr);\n\n const indices = indicesSortedByScore;\n\n const outputs: number[] = [];\n for (let i = 0; i < indices.length; i++) {\n const idx = indices[i];\n\n const currBox = boxes[curr];\n const idxBox = boxes[idx];\n\n outputs.push(iou(currBox, idxBox, isIOU));\n }\n\n indicesSortedByScore = indicesSortedByScore.filter(\n (_, j) => outputs[j] <= iouThreshold,\n );\n }\n\n return pick;\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\nexport function normalize(x: tf.Tensor4D, meanRgb: number[]): tf.Tensor4D {\n return tf.tidy(() => {\n const [r, g, b] = meanRgb;\n const avg_r = tf.fill([...x.shape.slice(0, 3), 1], r, 'float32');\n const avg_g = tf.fill([...x.shape.slice(0, 3), 1], g, 'float32');\n const avg_b = tf.fill([...x.shape.slice(0, 3), 1], b, 'float32');\n const avg_rgb = tf.concat([avg_r, avg_g, avg_b], 3);\n\n return tf.sub(x, avg_rgb);\n });\n}\n", "import * as tf from '../../dist/tfjs.esm';\n\n/**\n * Pads the smaller dimension of an image tensor with zeros, such that width === height.\n *\n * @param imgTensor The image tensor.\n * @param isCenterImage (optional, default: false) If true, add an equal amount of padding on\n * both sides of the minor dimension oof the image.\n * @returns The padded tensor with width === height.\n */\nexport function padToSquare(\n imgTensor: tf.Tensor4D,\n isCenterImage: boolean = false,\n): tf.Tensor4D {\n return tf.tidy(() => {\n const [height, width] = imgTensor.shape.slice(1);\n if (height === width) {\n return imgTensor;\n }\n\n const dimDiff = Math.abs(height - width);\n const paddingAmount = Math.round(dimDiff * (isCenterImage ? 0.5 : 1));\n const paddingAxis = height > width ? 2 : 1;\n\n const createPaddingTensor = (paddingAmountLocal: number): tf.Tensor => {\n const paddingTensorShape = imgTensor.shape.slice();\n paddingTensorShape[paddingAxis] = paddingAmountLocal;\n return tf.fill(paddingTensorShape, 0, 'float32');\n };\n\n const paddingTensorAppend = createPaddingTensor(paddingAmount);\n const remainingPaddingAmount = dimDiff - (paddingTensorAppend.shape[paddingAxis] as number);\n\n const paddingTensorPrepend = isCenterImage && remainingPaddingAmount\n ? createPaddingTensor(remainingPaddingAmount)\n : null;\n\n const tensorsToStack = [\n paddingTensorPrepend,\n imgTensor,\n paddingTensorAppend,\n ]\n .filter((t) => !!t)\n .map((t: tf.Tensor) => tf.cast(t, 'float32')) as tf.Tensor4D[];\n return tf.concat(tensorsToStack, paddingAxis);\n });\n}\n", "export function shuffleArray(inputArray: any[]) {\n const array = inputArray.slice();\n for (let i = array.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n const x = array[i];\n array[i] = array[j];\n array[j] = x;\n }\n return array;\n}\n", "export * from './iou';\nexport * from './minBbox';\nexport * from './nonMaxSuppression';\nexport * from './normalize';\nexport * from './padToSquare';\nexport * from './shuffleArray';\n\nexport function sigmoid(x: number) {\n return 1 / (1 + Math.exp(-x));\n}\n\nexport function inverseSigmoid(x: number) {\n return Math.log(x / (1 - x));\n}\n", "import { Box } from './Box';\n\nexport interface IRect {\n x: number\n y: number\n width: number\n height: number\n}\n\nexport class Rect extends Box implements IRect {\n constructor(x: number, y: number, width: number, height: number, allowNegativeDimensions: boolean = false) {\n super({\n x, y, width, height,\n }, allowNegativeDimensions);\n }\n}\n", "import { minBbox } from '../ops/index';\nimport { getCenterPoint } from '../utils/index';\nimport { IBoundingBox } from './BoundingBox';\nimport { Box } from './Box';\nimport { Dimensions, IDimensions } from './Dimensions';\nimport { FaceDetection } from './FaceDetection';\nimport { Point } from './Point';\nimport { IRect, Rect } from './Rect';\n\n// face alignment constants\nconst relX = 0.5;\nconst relY = 0.43;\nconst relScale = 0.45;\n\nexport interface IFaceLandmarks {\n positions: Point[]\n shift: Point\n}\n\nexport class FaceLandmarks implements IFaceLandmarks {\n protected _shift: Point\n\n protected _positions: Point[]\n\n protected _imgDims: Dimensions\n\n constructor(\n relativeFaceLandmarkPositions: Point[],\n imgDims: IDimensions,\n shift: Point = new Point(0, 0),\n ) {\n const { width, height } = imgDims;\n this._imgDims = new Dimensions(width, height);\n this._shift = shift;\n this._positions = relativeFaceLandmarkPositions.map(\n (pt) => pt.mul(new Point(width, height)).add(shift),\n );\n }\n\n public get shift(): Point { return new Point(this._shift.x, this._shift.y); }\n\n public get imageWidth(): number { return this._imgDims.width; }\n\n public get imageHeight(): number { return this._imgDims.height; }\n\n public get positions(): Point[] { return this._positions; }\n\n public get relativePositions(): Point[] {\n return this._positions.map(\n (pt) => pt.sub(this._shift).div(new Point(this.imageWidth, this.imageHeight)),\n );\n }\n\n public forSize(width: number, height: number): T {\n return new (this.constructor as any)(\n this.relativePositions,\n { width, height },\n );\n }\n\n public shiftBy(x: number, y: number): T {\n return new (this.constructor as any)(\n this.relativePositions,\n this._imgDims,\n new Point(x, y),\n );\n }\n\n public shiftByPoint(pt: Point): T {\n return this.shiftBy(pt.x, pt.y);\n }\n\n /**\n * Aligns the face landmarks after face detection from the relative positions of the faces\n * bounding box, or it's current shift. This function should be used to align the face images\n * after face detection has been performed, before they are passed to the face recognition net.\n * This will make the computed face descriptor more accurate.\n *\n * @param detection (optional) The bounding box of the face or the face detection result. If\n * no argument was passed the position of the face landmarks are assumed to be relative to\n * it's current shift.\n * @returns The bounding box of the aligned face.\n */\n public align(\n detection?: FaceDetection | IRect | IBoundingBox | null,\n options: { useDlibAlignment?: boolean, minBoxPadding?: number } = { },\n ): Box {\n if (detection) {\n const box = detection instanceof FaceDetection\n ? detection.box.floor()\n : new Box(detection);\n\n return this.shiftBy(box.x, box.y).align(null, options);\n }\n\n const { useDlibAlignment, minBoxPadding } = { useDlibAlignment: false, minBoxPadding: 0.2, ...options };\n\n if (useDlibAlignment) {\n return this.alignDlib();\n }\n\n return this.alignMinBbox(minBoxPadding);\n }\n\n private alignDlib(): Box {\n const centers = this.getRefPointsForAlignment();\n\n const [leftEyeCenter, rightEyeCenter, mouthCenter] = centers;\n const distToMouth = (pt: Point) => mouthCenter.sub(pt).magnitude();\n const eyeToMouthDist = (distToMouth(leftEyeCenter) + distToMouth(rightEyeCenter)) / 2;\n\n const size = Math.floor(eyeToMouthDist / relScale);\n\n const refPoint = getCenterPoint(centers);\n // TODO: pad in case rectangle is out of image bounds\n const x = Math.floor(Math.max(0, refPoint.x - (relX * size)));\n const y = Math.floor(Math.max(0, refPoint.y - (relY * size)));\n\n return new Rect(x, y, Math.min(size, this.imageWidth + x), Math.min(size, this.imageHeight + y));\n }\n\n private alignMinBbox(padding: number): Box {\n const box = minBbox(this.positions);\n return box.pad(box.width * padding, box.height * padding);\n }\n\n protected getRefPointsForAlignment(): Point[] {\n throw new Error('getRefPointsForAlignment not implemented by base class');\n }\n}\n", "import { getCenterPoint } from '../utils/index';\nimport { FaceLandmarks } from './FaceLandmarks';\nimport { Point } from './Point';\n\nexport class FaceLandmarks5 extends FaceLandmarks {\n protected getRefPointsForAlignment(): Point[] {\n const pts = this.positions;\n return [\n pts[0],\n pts[1],\n getCenterPoint([pts[3], pts[4]]),\n ];\n }\n}\n", "import { getCenterPoint } from '../utils/index';\nimport { FaceLandmarks } from './FaceLandmarks';\nimport { Point } from './Point';\n\nexport class FaceLandmarks68 extends FaceLandmarks {\n public getJawOutline(): Point[] {\n return this.positions.slice(0, 17);\n }\n\n public getLeftEyeBrow(): Point[] {\n return this.positions.slice(17, 22);\n }\n\n public getRightEyeBrow(): Point[] {\n return this.positions.slice(22, 27);\n }\n\n public getNose(): Point[] {\n return this.positions.slice(27, 36);\n }\n\n public getLeftEye(): Point[] {\n return this.positions.slice(36, 42);\n }\n\n public getRightEye(): Point[] {\n return this.positions.slice(42, 48);\n }\n\n public getMouth(): Point[] {\n return this.positions.slice(48, 68);\n }\n\n protected getRefPointsForAlignment(): Point[] {\n return [\n this.getLeftEye(),\n this.getRightEye(),\n this.getMouth(),\n ].map(getCenterPoint);\n }\n}\n", "import { round } from '../utils/index';\n\nexport interface IFaceMatch {\n label: string\n distance: number\n}\n\nexport class FaceMatch implements IFaceMatch {\n private _label: string\n\n private _distance: number\n\n constructor(label: string, distance: number) {\n this._label = label;\n this._distance = distance;\n }\n\n public get label(): string { return this._label; }\n\n public get distance(): number { return this._distance; }\n\n public toString(withDistance: boolean = true): string {\n return `${this.label}${withDistance ? ` (${round(this.distance)})` : ''}`;\n }\n}\n", "import { isValidNumber } from '../utils/index';\nimport { IBoundingBox } from './BoundingBox';\nimport { Box } from './Box';\nimport { IRect } from './Rect';\n\nexport class LabeledBox extends Box {\n public static assertIsValidLabeledBox(box: any, callee: string) {\n Box.assertIsValidBox(box, callee);\n\n if (!isValidNumber(box.label)) {\n throw new Error(`${callee} - expected property label (${box.label}) to be a number`);\n }\n }\n\n private _label: number\n\n constructor(box: IBoundingBox | IRect | any, label: number) {\n super(box);\n this._label = label;\n }\n\n public get label(): number { return this._label; }\n}\n", "export class LabeledFaceDescriptors {\n private _label: string\n\n private _descriptors: Float32Array[]\n\n constructor(label: string, descriptors: Float32Array[]) {\n if (!(typeof label === 'string')) {\n throw new Error('LabeledFaceDescriptors - constructor expected label to be a string');\n }\n\n if (!Array.isArray(descriptors) || descriptors.some((desc) => !(desc instanceof Float32Array))) {\n throw new Error('LabeledFaceDescriptors - constructor expected descriptors to be an array of Float32Array');\n }\n\n this._label = label;\n this._descriptors = descriptors;\n }\n\n public get label(): string { return this._label; }\n\n public get descriptors(): Float32Array[] { return this._descriptors; }\n\n public toJSON(): any {\n return {\n label: this.label,\n descriptors: this.descriptors.map((d) => Array.from(d)),\n };\n }\n\n public static fromJSON(json: any): LabeledFaceDescriptors {\n const descriptors = json.descriptors.map((d: any) => new Float32Array(d));\n return new LabeledFaceDescriptors(json.label, descriptors);\n }\n}\n", "import { isValidProbablitiy } from '../utils/index';\nimport { IBoundingBox } from './BoundingBox';\nimport { LabeledBox } from './LabeledBox';\nimport { IRect } from './Rect';\n\nexport class PredictedBox extends LabeledBox {\n public static assertIsValidPredictedBox(box: any, callee: string) {\n LabeledBox.assertIsValidLabeledBox(box, callee);\n\n if (\n !isValidProbablitiy(box.score)\n || !isValidProbablitiy(box.classScore)\n ) {\n throw new Error(`${callee} - expected properties score (${box.score}) and (${box.classScore}) to be a number between [0, 1]`);\n }\n }\n\n private _score: number\n\n private _classScore: number\n\n constructor(box: IBoundingBox | IRect | any, label: number, score: number, classScore: number) {\n super(box, label);\n this._score = score;\n this._classScore = classScore;\n }\n\n public get score(): number { return this._score; }\n\n public get classScore(): number { return this._classScore; }\n}\n", "import { FaceDetection } from '../classes/FaceDetection';\n\nexport type WithFaceDetection