mirror of https://github.com/vladmandic/human
initial version of facerecognition demo
parent
b16bb2e8ac
commit
148391fe1c
12
.build.json
12
.build.json
|
@ -143,13 +143,21 @@
|
|||
"typedoc": "typedoc"
|
||||
},
|
||||
{
|
||||
"name": "demo/browser",
|
||||
"name": "demo/typescript",
|
||||
"platform": "browser",
|
||||
"format": "esm",
|
||||
"input": "demo/typescript/index.ts",
|
||||
"output": "demo/typescript/index.js",
|
||||
"sourcemap": true,
|
||||
"minify": false,
|
||||
"external": ["*/human.esm.js"]
|
||||
},
|
||||
{
|
||||
"name": "demo/facerecognition",
|
||||
"platform": "browser",
|
||||
"format": "esm",
|
||||
"input": "demo/facerecognition/index.ts",
|
||||
"output": "demo/facerecognition/index.js",
|
||||
"sourcemap": true,
|
||||
"external": ["*/human.esm.js"]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
"assets",
|
||||
"demo/helpers/*.js",
|
||||
"demo/typescript/*.js",
|
||||
"demo/facerecognition/*.js",
|
||||
"dist",
|
||||
"media",
|
||||
"models",
|
||||
|
@ -60,6 +61,7 @@
|
|||
"no-bitwise": "off",
|
||||
"no-case-declarations":"off",
|
||||
"no-continue": "off",
|
||||
"no-else-return": "off",
|
||||
"no-lonely-if": "off",
|
||||
"no-loop-func": "off",
|
||||
"no-mixed-operators": "off",
|
||||
|
|
|
@ -11,9 +11,8 @@
|
|||
|
||||
### **HEAD -> main** 2021/11/08 mandic00@live.com
|
||||
|
||||
|
||||
### **origin/main** 2021/11/08 mandic00@live.com
|
||||
|
||||
- add type defs when working with relative path imports
|
||||
- disable humangl backend if webgl 1.0 is detected
|
||||
|
||||
### **release: 2.5.1** 2021/11/08 mandic00@live.com
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Human: Face Recognition</title>
|
||||
<meta name="viewport" content="width=device-width" id="viewport">
|
||||
<meta name="keywords" content="Human">
|
||||
<meta name="application-name" content="Human">
|
||||
<meta name="description" content="Human: 3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction, Emotion Prediction & Gesture Recognition; Author: Vladimir Mandic <https://github.com/vladmandic>">
|
||||
<meta name="msapplication-tooltip" content="Human: 3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction, Emotion Prediction & Gesture Recognition; Author: Vladimir Mandic <https://github.com/vladmandic>">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<link rel="manifest" href="../manifest.webmanifest">
|
||||
<link rel="shortcut icon" href="../../favicon.ico" type="image/x-icon">
|
||||
<link rel="apple-touch-icon" href="../../assets/icon.png">
|
||||
<script src="./index.js" type="module"></script>
|
||||
<style>
|
||||
@font-face { font-family: 'Lato'; font-display: swap; font-style: normal; font-weight: 100; src: local('Lato'), url('../../assets/lato-light.woff2') }
|
||||
html { font-family: 'Lato', 'Segoe UI'; font-size: 16px; font-variant: small-caps; }
|
||||
body { margin: 0; background: black; color: white; overflow-x: hidden; width: 100vw; height: 100vh; }
|
||||
body::-webkit-scrollbar { display: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" style="margin: 0 auto; width: 100%"></canvas>
|
||||
<video id="video" playsinline style="display: none"></video>
|
||||
<pre id="fps" style="position: absolute; top: 12px; right: 20px; background-color: grey; padding: 8px; box-shadow: 2px 2px black"></pre>
|
||||
<pre id="log" style="padding: 8px"></pre>
|
||||
<div id="status" style="position: absolute; bottom: 0; width: 100%; padding: 8px; font-size: 0.8rem;"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
Human
|
||||
homepage: <https://github.com/vladmandic/human>
|
||||
author: <https://github.com/vladmandic>'
|
||||
*/
|
||||
|
||||
// demo/facerecognition/index.ts
|
||||
import { Human } from "../../dist/human.esm.js";
|
||||
var humanConfig = {
|
||||
modelBasePath: "../../models",
|
||||
filter: { equalization: true },
|
||||
face: {
|
||||
enabled: true,
|
||||
detector: { rotation: true, return: true },
|
||||
description: { enabled: true },
|
||||
iris: { enabled: true },
|
||||
emotion: { enabled: false },
|
||||
antispoof: { enabled: true }
|
||||
},
|
||||
body: { enabled: false },
|
||||
hand: { enabled: false },
|
||||
object: { enabled: false },
|
||||
gesture: { enabled: true }
|
||||
};
|
||||
var options = {
|
||||
minConfidence: 0.6,
|
||||
minSize: 224,
|
||||
maxTime: 1e4
|
||||
};
|
||||
var human = new Human(humanConfig);
|
||||
human.env["perfadd"] = false;
|
||||
human.draw.options.font = 'small-caps 18px "Lato"';
|
||||
human.draw.options.lineHeight = 20;
|
||||
var dom = {
|
||||
video: document.getElementById("video"),
|
||||
canvas: document.getElementById("canvas"),
|
||||
log: document.getElementById("log"),
|
||||
fps: document.getElementById("fps"),
|
||||
status: document.getElementById("status")
|
||||
};
|
||||
var timestamp = { detect: 0, draw: 0 };
|
||||
var fps = { detect: 0, draw: 0 };
|
||||
var startTime = 0;
|
||||
var log = (...msg) => {
|
||||
dom.log.innerText += msg.join(" ") + "\n";
|
||||
console.log(...msg);
|
||||
};
|
||||
var printFPS = (msg) => dom.fps.innerText = msg;
|
||||
var printStatus = (msg) => dom.status.innerText = "status: " + JSON.stringify(msg).replace(/"|{|}/g, "").replace(/,/g, " | ");
|
||||
async function webCam() {
|
||||
printFPS("starting webcam...");
|
||||
const cameraOptions = { audio: false, video: { facingMode: "user", resizeMode: "none", width: { ideal: document.body.clientWidth } } };
|
||||
const stream = await navigator.mediaDevices.getUserMedia(cameraOptions);
|
||||
const ready = new Promise((resolve) => {
|
||||
dom.video.onloadeddata = () => resolve(true);
|
||||
});
|
||||
dom.video.srcObject = stream;
|
||||
dom.video.play();
|
||||
await ready;
|
||||
dom.canvas.width = dom.video.videoWidth;
|
||||
dom.canvas.height = dom.video.videoHeight;
|
||||
const track = stream.getVideoTracks()[0];
|
||||
const capabilities = track.getCapabilities ? track.getCapabilities() : "";
|
||||
const settings = track.getSettings ? track.getSettings() : "";
|
||||
const constraints = track.getConstraints ? track.getConstraints() : "";
|
||||
log("video:", dom.video.videoWidth, dom.video.videoHeight, track.label, { stream, track, settings, constraints, capabilities });
|
||||
dom.canvas.onclick = () => {
|
||||
if (dom.video.paused)
|
||||
dom.video.play();
|
||||
else
|
||||
dom.video.pause();
|
||||
};
|
||||
}
|
||||
async function detectionLoop() {
|
||||
if (!dom.video.paused) {
|
||||
await human.detect(dom.video);
|
||||
const now = human.now();
|
||||
fps.detect = 1e3 / (now - timestamp.detect);
|
||||
timestamp.detect = now;
|
||||
requestAnimationFrame(detectionLoop);
|
||||
}
|
||||
}
|
||||
var ok = {
|
||||
faceCount: false,
|
||||
faceConfidence: false,
|
||||
facingCenter: false,
|
||||
eyesOpen: false,
|
||||
blinkDetected: false,
|
||||
faceSize: false,
|
||||
antispoofCheck: false,
|
||||
livenessCheck: false,
|
||||
elapsedMs: 0
|
||||
};
|
||||
var allOk = () => ok.faceCount && ok.faceSize && ok.blinkDetected && ok.facingCenter && ok.faceConfidence && ok.antispoofCheck;
|
||||
async function validationLoop() {
|
||||
const interpolated = await human.next(human.result);
|
||||
await human.draw.canvas(dom.video, dom.canvas);
|
||||
await human.draw.all(dom.canvas, interpolated);
|
||||
const now = human.now();
|
||||
fps.draw = 1e3 / (now - timestamp.draw);
|
||||
timestamp.draw = now;
|
||||
printFPS(`fps: ${fps.detect.toFixed(1).padStart(5, " ")} detect | ${fps.draw.toFixed(1).padStart(5, " ")} draw`);
|
||||
const gestures = Object.values(human.result.gesture).map((gesture) => gesture.gesture);
|
||||
ok.faceCount = human.result.face.length === 1;
|
||||
ok.eyesOpen = ok.eyesOpen || !(gestures.includes("blink left eye") || gestures.includes("blink right eye"));
|
||||
ok.blinkDetected = ok.eyesOpen && ok.blinkDetected || gestures.includes("blink left eye") || gestures.includes("blink right eye");
|
||||
ok.facingCenter = gestures.includes("facing center") && gestures.includes("looking center");
|
||||
ok.faceConfidence = (human.result.face[0].boxScore || 0) > options.minConfidence && (human.result.face[0].faceScore || 0) > options.minConfidence && (human.result.face[0].genderScore || 0) > options.minConfidence;
|
||||
ok.antispoofCheck = (human.result.face[0].real || 0) > options.minConfidence;
|
||||
ok.faceSize = human.result.face[0].box[2] >= options.minSize && human.result.face[0].box[3] >= options.minSize;
|
||||
printStatus(ok);
|
||||
if (allOk()) {
|
||||
dom.video.pause();
|
||||
return human.result.face;
|
||||
} else {
|
||||
human.tf.dispose(human.result.face[0].tensor);
|
||||
}
|
||||
if (ok.elapsedMs > options.maxTime) {
|
||||
dom.video.pause();
|
||||
return human.result.face;
|
||||
} else {
|
||||
ok.elapsedMs = Math.trunc(human.now() - startTime);
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(async () => {
|
||||
const res = await validationLoop();
|
||||
if (res)
|
||||
resolve(human.result.face);
|
||||
}, 30);
|
||||
});
|
||||
}
|
||||
}
|
||||
async function detectFace(face) {
|
||||
dom.canvas.width = face.tensor.shape[2];
|
||||
dom.canvas.height = face.tensor.shape[1];
|
||||
dom.canvas.style.width = "";
|
||||
human.tf.browser.toPixels(face.tensor, dom.canvas);
|
||||
human.tf.dispose(face.tensor);
|
||||
}
|
||||
async function main() {
|
||||
log("human version:", human.version, "| tfjs version:", human.tf.version_core);
|
||||
printFPS("loading...");
|
||||
await human.load();
|
||||
printFPS("initializing...");
|
||||
await human.warmup();
|
||||
await webCam();
|
||||
await detectionLoop();
|
||||
startTime = human.now();
|
||||
const face = await validationLoop();
|
||||
if (!allOk())
|
||||
log("did not find valid input", face);
|
||||
else {
|
||||
log("found valid face", face);
|
||||
await detectFace(face[0]);
|
||||
}
|
||||
dom.fps.style.display = "none";
|
||||
}
|
||||
window.onload = main;
|
||||
/**
|
||||
* Human demo for browsers
|
||||
* @default Human Library
|
||||
* @summary <https://github.com/vladmandic/human>
|
||||
* @author <https://github.com/vladmandic>
|
||||
* @copyright <https://github.com/vladmandic>
|
||||
* @license MIT
|
||||
*/
|
||||
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,175 @@
|
|||
/**
|
||||
* Human demo for browsers
|
||||
* @default Human Library
|
||||
* @summary <https://github.com/vladmandic/human>
|
||||
* @author <https://github.com/vladmandic>
|
||||
* @copyright <https://github.com/vladmandic>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { Human } from '../../dist/human.esm.js'; // equivalent of @vladmandic/Human
|
||||
|
||||
const humanConfig = { // user configuration for human, used to fine-tune behavior
|
||||
modelBasePath: '../../models',
|
||||
filter: { equalization: true }, // lets run with histogram equilizer
|
||||
face: {
|
||||
enabled: true,
|
||||
detector: { rotation: true, return: true }, // return tensor is not really needed except to draw detected face
|
||||
description: { enabled: true },
|
||||
iris: { enabled: true }, // needed to determine gaze direction
|
||||
emotion: { enabled: false }, // not needed
|
||||
antispoof: { enabled: true }, // enable optional antispoof as well
|
||||
},
|
||||
body: { enabled: false },
|
||||
hand: { enabled: false },
|
||||
object: { enabled: false },
|
||||
gesture: { enabled: true },
|
||||
};
|
||||
|
||||
const options = {
|
||||
minConfidence: 0.6, // overal face confidence for box, face, gender, real
|
||||
minSize: 224, // min input to face descriptor model before degradation
|
||||
maxTime: 10000, // max time before giving up
|
||||
};
|
||||
|
||||
const human = new Human(humanConfig); // create instance of human with overrides from user configuration
|
||||
|
||||
human.env['perfadd'] = false; // is performance data showing instant or total values
|
||||
human.draw.options.font = 'small-caps 18px "Lato"'; // set font used to draw labels when using draw methods
|
||||
human.draw.options.lineHeight = 20;
|
||||
|
||||
const dom = { // grab instances of dom objects so we dont have to look them up later
|
||||
video: document.getElementById('video') as HTMLVideoElement,
|
||||
canvas: document.getElementById('canvas') as HTMLCanvasElement,
|
||||
log: document.getElementById('log') as HTMLPreElement,
|
||||
fps: document.getElementById('fps') as HTMLPreElement,
|
||||
status: document.getElementById('status') as HTMLPreElement,
|
||||
};
|
||||
const timestamp = { detect: 0, draw: 0 }; // holds information used to calculate performance and possible memory leaks
|
||||
const fps = { detect: 0, draw: 0 }; // holds calculated fps information for both detect and screen refresh
|
||||
let startTime = 0;
|
||||
|
||||
const log = (...msg) => { // helper method to output messages
|
||||
dom.log.innerText += msg.join(' ') + '\n';
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(...msg);
|
||||
};
|
||||
const printFPS = (msg) => dom.fps.innerText = msg; // print status element
|
||||
const printStatus = (msg) => dom.status.innerText = 'status: ' + JSON.stringify(msg).replace(/"|{|}/g, '').replace(/,/g, ' | '); // print status element
|
||||
|
||||
async function webCam() { // initialize webcam
|
||||
printFPS('starting webcam...');
|
||||
// @ts-ignore resizeMode is not yet defined in tslib
|
||||
const cameraOptions: MediaStreamConstraints = { audio: false, video: { facingMode: 'user', resizeMode: 'none', width: { ideal: document.body.clientWidth } } };
|
||||
const stream: MediaStream = await navigator.mediaDevices.getUserMedia(cameraOptions);
|
||||
const ready = new Promise((resolve) => { dom.video.onloadeddata = () => resolve(true); });
|
||||
dom.video.srcObject = stream;
|
||||
dom.video.play();
|
||||
await ready;
|
||||
dom.canvas.width = dom.video.videoWidth;
|
||||
dom.canvas.height = dom.video.videoHeight;
|
||||
const track: MediaStreamTrack = stream.getVideoTracks()[0];
|
||||
const capabilities: MediaTrackCapabilities | string = track.getCapabilities ? track.getCapabilities() : '';
|
||||
const settings: MediaTrackSettings | string = track.getSettings ? track.getSettings() : '';
|
||||
const constraints: MediaTrackConstraints | string = track.getConstraints ? track.getConstraints() : '';
|
||||
log('video:', dom.video.videoWidth, dom.video.videoHeight, track.label, { stream, track, settings, constraints, capabilities });
|
||||
dom.canvas.onclick = () => { // pause when clicked on screen and resume on next click
|
||||
if (dom.video.paused) dom.video.play();
|
||||
else dom.video.pause();
|
||||
};
|
||||
}
|
||||
|
||||
async function detectionLoop() { // main detection loop
|
||||
if (!dom.video.paused) {
|
||||
await human.detect(dom.video); // actual detection; were not capturing output in a local variable as it can also be reached via human.result
|
||||
const now = human.now();
|
||||
fps.detect = 1000 / (now - timestamp.detect);
|
||||
timestamp.detect = now;
|
||||
requestAnimationFrame(detectionLoop); // start new frame immediately
|
||||
}
|
||||
}
|
||||
|
||||
const ok = { // must meet all rules
|
||||
faceCount: false,
|
||||
faceConfidence: false,
|
||||
facingCenter: false,
|
||||
eyesOpen: false,
|
||||
blinkDetected: false,
|
||||
faceSize: false,
|
||||
antispoofCheck: false,
|
||||
livenessCheck: false,
|
||||
elapsedMs: 0,
|
||||
};
|
||||
const allOk = () => ok.faceCount && ok.faceSize && ok.blinkDetected && ok.facingCenter && ok.faceConfidence && ok.antispoofCheck;
|
||||
|
||||
async function validationLoop(): Promise<typeof human.result.face> { // main screen refresh loop
|
||||
const interpolated = await human.next(human.result); // smoothen result using last-known results
|
||||
await human.draw.canvas(dom.video, dom.canvas); // draw canvas to screen
|
||||
await human.draw.all(dom.canvas, interpolated); // draw labels, boxes, lines, etc.
|
||||
const now = human.now();
|
||||
fps.draw = 1000 / (now - timestamp.draw);
|
||||
timestamp.draw = now;
|
||||
printFPS(`fps: ${fps.detect.toFixed(1).padStart(5, ' ')} detect | ${fps.draw.toFixed(1).padStart(5, ' ')} draw`); // write status
|
||||
|
||||
const gestures: string[] = Object.values(human.result.gesture).map((gesture) => gesture.gesture); // flatten all gestures
|
||||
ok.faceCount = human.result.face.length === 1; // must be exactly detected face
|
||||
ok.eyesOpen = ok.eyesOpen || !(gestures.includes('blink left eye') || gestures.includes('blink right eye')); // blink validation is only ok once both eyes are open
|
||||
ok.blinkDetected = ok.eyesOpen && ok.blinkDetected || gestures.includes('blink left eye') || gestures.includes('blink right eye'); // need to detect blink only once
|
||||
ok.facingCenter = gestures.includes('facing center') && gestures.includes('looking center'); // must face camera and look at camera
|
||||
ok.faceConfidence = (human.result.face[0].boxScore || 0) > options.minConfidence && (human.result.face[0].faceScore || 0) > options.minConfidence && (human.result.face[0].genderScore || 0) > options.minConfidence;
|
||||
ok.antispoofCheck = (human.result.face[0].real || 0) > options.minConfidence;
|
||||
ok.faceSize = human.result.face[0].box[2] >= options.minSize && human.result.face[0].box[3] >= options.minSize;
|
||||
|
||||
printStatus(ok);
|
||||
|
||||
if (allOk()) { // all criteria met
|
||||
dom.video.pause();
|
||||
return human.result.face;
|
||||
} else {
|
||||
human.tf.dispose(human.result.face[0].tensor); // results are not ok, so lets dispose tensor
|
||||
}
|
||||
if (ok.elapsedMs > options.maxTime) { // give up
|
||||
dom.video.pause();
|
||||
return human.result.face;
|
||||
} else { // run again
|
||||
ok.elapsedMs = Math.trunc(human.now() - startTime);
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(async () => {
|
||||
const res = await validationLoop(); // run validation loop until conditions are met
|
||||
if (res) resolve(human.result.face); // recursive promise resolve
|
||||
}, 30); // use to slow down refresh from max refresh rate to target of 30 fps
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function detectFace(face) {
|
||||
// draw face and dispose face tensor immediatey afterwards
|
||||
dom.canvas.width = face.tensor.shape[2];
|
||||
dom.canvas.height = face.tensor.shape[1];
|
||||
dom.canvas.style.width = '';
|
||||
human.tf.browser.toPixels(face.tensor, dom.canvas);
|
||||
human.tf.dispose(face.tensor);
|
||||
|
||||
// run detection using human.match and use face.embedding as input descriptor
|
||||
// tbd
|
||||
}
|
||||
|
||||
async function main() { // main entry point
|
||||
log('human version:', human.version, '| tfjs version:', human.tf.version_core);
|
||||
printFPS('loading...');
|
||||
await human.load(); // preload all models
|
||||
printFPS('initializing...');
|
||||
await human.warmup(); // warmup function to initialize backend for future faster detection
|
||||
await webCam(); // start webcam
|
||||
await detectionLoop(); // start detection loop
|
||||
startTime = human.now();
|
||||
const face = await validationLoop(); // start validation loop
|
||||
if (!allOk()) log('did not find valid input', face);
|
||||
else {
|
||||
log('found valid face', face);
|
||||
await detectFace(face[0]);
|
||||
}
|
||||
dom.fps.style.display = 'none';
|
||||
}
|
||||
|
||||
window.onload = main;
|
|
@ -26,6 +26,5 @@
|
|||
<pre id="status" style="position: absolute; top: 12px; right: 20px; background-color: grey; padding: 8px; box-shadow: 2px 2px black"></pre>
|
||||
<pre id="log" style="padding: 8px"></pre>
|
||||
<div id="performance" style="position: absolute; bottom: 0; width: 100%; padding: 8px; font-size: 0.8rem;"></div>
|
||||
<canvas id="test" style="position: absolute; bottom: 0; right: 0; width: 30%"></canvas>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1003,7 +1003,7 @@ async function process2(input, config3, getTensor = true) {
|
|||
if (input["isDisposedInternal"]) {
|
||||
throw new Error("input tensor is disposed");
|
||||
} else if (!input.shape || input.shape.length !== 4 || input.shape[0] !== 1 || input.shape[3] !== 3) {
|
||||
throw new Error(`input tensor shape must be [1, height, width, 3] and instead was ${input["shape"]}`);
|
||||
throw new Error("input tensor shape must be [1, height, width, 3] and instead was" + (input["shape"] ? input["shape"].toString() : "unknown"));
|
||||
} else {
|
||||
return { tensor: tfjs_esm_exports.clone(input), canvas: config3.filter.return ? outCanvas : null };
|
||||
}
|
||||
|
@ -5654,7 +5654,6 @@ async function predict6(input, config3) {
|
|||
if (!((_e = config3.face.mesh) == null ? void 0 : _e.enabled)) {
|
||||
face5.box = getClampedBox(box4, input);
|
||||
face5.boxRaw = getRawBox(box4, input);
|
||||
face5.boxScore = Math.round(100 * box4.confidence || 0) / 100;
|
||||
face5.score = face5.boxScore;
|
||||
face5.mesh = box4.landmarks.map((pt) => [
|
||||
(box4.startPoint[0] + box4.endPoint[0]) / 2 + (box4.endPoint[0] + box4.startPoint[0]) * pt[0] / size(),
|
||||
|
@ -5682,7 +5681,7 @@ async function predict6(input, config3) {
|
|||
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
||||
for (const key of Object.keys(meshAnnotations))
|
||||
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
||||
box4 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox(face5.mesh), enlargeFact));
|
||||
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), enlargeFact), confidence: box4.confidence });
|
||||
face5.box = getClampedBox(box4, input);
|
||||
face5.boxRaw = getRawBox(box4, input);
|
||||
face5.score = face5.faceScore;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -71328,7 +71328,7 @@ async function process2(input2, config3, getTensor2 = true) {
|
|||
if (input2["isDisposedInternal"]) {
|
||||
throw new Error("input tensor is disposed");
|
||||
} else if (!input2.shape || input2.shape.length !== 4 || input2.shape[0] !== 1 || input2.shape[3] !== 3) {
|
||||
throw new Error(`input tensor shape must be [1, height, width, 3] and instead was ${input2["shape"]}`);
|
||||
throw new Error("input tensor shape must be [1, height, width, 3] and instead was" + (input2["shape"] ? input2["shape"].toString() : "unknown"));
|
||||
} else {
|
||||
return { tensor: clone(input2), canvas: config3.filter.return ? outCanvas : null };
|
||||
}
|
||||
|
@ -75979,7 +75979,6 @@ async function predict6(input2, config3) {
|
|||
if (!((_e = config3.face.mesh) == null ? void 0 : _e.enabled)) {
|
||||
face5.box = getClampedBox(box4, input2);
|
||||
face5.boxRaw = getRawBox(box4, input2);
|
||||
face5.boxScore = Math.round(100 * box4.confidence || 0) / 100;
|
||||
face5.score = face5.boxScore;
|
||||
face5.mesh = box4.landmarks.map((pt) => [
|
||||
(box4.startPoint[0] + box4.endPoint[0]) / 2 + (box4.endPoint[0] + box4.startPoint[0]) * pt[0] / size(),
|
||||
|
@ -76007,7 +76006,7 @@ async function predict6(input2, config3) {
|
|||
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input2.shape[2] || 0), pt[1] / (input2.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
||||
for (const key of Object.keys(meshAnnotations))
|
||||
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
||||
box4 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox(face5.mesh), enlargeFact));
|
||||
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), enlargeFact), confidence: box4.confidence });
|
||||
face5.box = getClampedBox(box4, input2);
|
||||
face5.boxRaw = getRawBox(box4, input2);
|
||||
face5.score = face5.faceScore;
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1013,7 +1013,7 @@ async function process2(input, config3, getTensor = true) {
|
|||
if (input["isDisposedInternal"]) {
|
||||
throw new Error("input tensor is disposed");
|
||||
} else if (!input.shape || input.shape.length !== 4 || input.shape[0] !== 1 || input.shape[3] !== 3) {
|
||||
throw new Error(`input tensor shape must be [1, height, width, 3] and instead was ${input["shape"]}`);
|
||||
throw new Error("input tensor shape must be [1, height, width, 3] and instead was" + (input["shape"] ? input["shape"].toString() : "unknown"));
|
||||
} else {
|
||||
return { tensor: tf2.clone(input), canvas: config3.filter.return ? outCanvas : null };
|
||||
}
|
||||
|
@ -5692,7 +5692,6 @@ async function predict6(input, config3) {
|
|||
if (!((_e = config3.face.mesh) == null ? void 0 : _e.enabled)) {
|
||||
face5.box = getClampedBox(box4, input);
|
||||
face5.boxRaw = getRawBox(box4, input);
|
||||
face5.boxScore = Math.round(100 * box4.confidence || 0) / 100;
|
||||
face5.score = face5.boxScore;
|
||||
face5.mesh = box4.landmarks.map((pt) => [
|
||||
(box4.startPoint[0] + box4.endPoint[0]) / 2 + (box4.endPoint[0] + box4.startPoint[0]) * pt[0] / size(),
|
||||
|
@ -5720,7 +5719,7 @@ async function predict6(input, config3) {
|
|||
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
||||
for (const key of Object.keys(meshAnnotations))
|
||||
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
||||
box4 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox(face5.mesh), enlargeFact));
|
||||
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), enlargeFact), confidence: box4.confidence });
|
||||
face5.box = getClampedBox(box4, input);
|
||||
face5.boxRaw = getRawBox(box4, input);
|
||||
face5.score = face5.faceScore;
|
||||
|
|
|
@ -1014,7 +1014,7 @@ async function process2(input, config3, getTensor = true) {
|
|||
if (input["isDisposedInternal"]) {
|
||||
throw new Error("input tensor is disposed");
|
||||
} else if (!input.shape || input.shape.length !== 4 || input.shape[0] !== 1 || input.shape[3] !== 3) {
|
||||
throw new Error(`input tensor shape must be [1, height, width, 3] and instead was ${input["shape"]}`);
|
||||
throw new Error("input tensor shape must be [1, height, width, 3] and instead was" + (input["shape"] ? input["shape"].toString() : "unknown"));
|
||||
} else {
|
||||
return { tensor: tf2.clone(input), canvas: config3.filter.return ? outCanvas : null };
|
||||
}
|
||||
|
@ -5693,7 +5693,6 @@ async function predict6(input, config3) {
|
|||
if (!((_e = config3.face.mesh) == null ? void 0 : _e.enabled)) {
|
||||
face5.box = getClampedBox(box4, input);
|
||||
face5.boxRaw = getRawBox(box4, input);
|
||||
face5.boxScore = Math.round(100 * box4.confidence || 0) / 100;
|
||||
face5.score = face5.boxScore;
|
||||
face5.mesh = box4.landmarks.map((pt) => [
|
||||
(box4.startPoint[0] + box4.endPoint[0]) / 2 + (box4.endPoint[0] + box4.startPoint[0]) * pt[0] / size(),
|
||||
|
@ -5721,7 +5720,7 @@ async function predict6(input, config3) {
|
|||
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
||||
for (const key of Object.keys(meshAnnotations))
|
||||
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
||||
box4 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox(face5.mesh), enlargeFact));
|
||||
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), enlargeFact), confidence: box4.confidence });
|
||||
face5.box = getClampedBox(box4, input);
|
||||
face5.boxRaw = getRawBox(box4, input);
|
||||
face5.score = face5.faceScore;
|
||||
|
|
|
@ -1013,7 +1013,7 @@ async function process2(input, config3, getTensor = true) {
|
|||
if (input["isDisposedInternal"]) {
|
||||
throw new Error("input tensor is disposed");
|
||||
} else if (!input.shape || input.shape.length !== 4 || input.shape[0] !== 1 || input.shape[3] !== 3) {
|
||||
throw new Error(`input tensor shape must be [1, height, width, 3] and instead was ${input["shape"]}`);
|
||||
throw new Error("input tensor shape must be [1, height, width, 3] and instead was" + (input["shape"] ? input["shape"].toString() : "unknown"));
|
||||
} else {
|
||||
return { tensor: tf2.clone(input), canvas: config3.filter.return ? outCanvas : null };
|
||||
}
|
||||
|
@ -5692,7 +5692,6 @@ async function predict6(input, config3) {
|
|||
if (!((_e = config3.face.mesh) == null ? void 0 : _e.enabled)) {
|
||||
face5.box = getClampedBox(box4, input);
|
||||
face5.boxRaw = getRawBox(box4, input);
|
||||
face5.boxScore = Math.round(100 * box4.confidence || 0) / 100;
|
||||
face5.score = face5.boxScore;
|
||||
face5.mesh = box4.landmarks.map((pt) => [
|
||||
(box4.startPoint[0] + box4.endPoint[0]) / 2 + (box4.endPoint[0] + box4.startPoint[0]) * pt[0] / size(),
|
||||
|
@ -5720,7 +5719,7 @@ async function predict6(input, config3) {
|
|||
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
||||
for (const key of Object.keys(meshAnnotations))
|
||||
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
||||
box4 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox(face5.mesh), enlargeFact));
|
||||
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), enlargeFact), confidence: box4.confidence });
|
||||
face5.box = getClampedBox(box4, input);
|
||||
face5.boxRaw = getRawBox(box4, input);
|
||||
face5.score = face5.faceScore;
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
"format": "graph-model",
|
||||
"generatedBy": "https://github.com/leokwu/livenessnet",
|
||||
"convertedBy": "https://github.com/vladmandic",
|
||||
"signature":
|
||||
{
|
||||
"inputs":
|
||||
{
|
||||
"conv2d_1_input": {"name":"conv2d_1_input:0","dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"-1"},{"size":"32"},{"size":"32"},{"size":"3"}]}}
|
||||
},
|
||||
"outputs":
|
||||
{
|
||||
"activation_6": {"name":"Identity:0","dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"-1"},{"size":"2"}]}}
|
||||
}
|
||||
},
|
||||
"modelTopology":
|
||||
{
|
||||
"node":
|
||||
[
|
||||
{"name":"StatefulPartitionedCall/sequential_1/conv2d_1/Conv2D/ReadVariableOp","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"3"},{"size":"16"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/conv2d_1/BiasAdd/ReadVariableOp","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"16"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/conv2d_2/Conv2D/ReadVariableOp","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"16"},{"size":"16"}]}}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/conv2d_2/BiasAdd/ReadVariableOp","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"16"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/conv2d_3/Conv2D/ReadVariableOp","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"16"},{"size":"32"}]}}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/conv2d_3/BiasAdd/ReadVariableOp","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"32"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/conv2d_4/Conv2D/ReadVariableOp","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"32"},{"size":"32"}]}}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/conv2d_4/BiasAdd/ReadVariableOp","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"32"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/flatten_1/Const","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_INT32","tensorShape":{"dim":[{"size":"2"}]}}},"dtype":{"type":"DT_INT32"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/dense_1/MatMul/ReadVariableOp","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"2048"},{"size":"64"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/dense_1/BiasAdd/ReadVariableOp","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"64"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_5/batchnorm/mul","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"64"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_5/batchnorm/sub","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"64"}]}}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/dense_2/MatMul/ReadVariableOp","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"64"},{"size":"2"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/dense_2/BiasAdd/ReadVariableOp","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"2"}]}}}}},
|
||||
{"name":"conv2d_1_input","op":"Placeholder","attr":{"shape":{"shape":{"dim":[{"size":"-1"},{"size":"32"},{"size":"32"},{"size":"3"}]}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_2/FusedBatchNormV3/Scaled","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"16"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_2/FusedBatchNormV3/Offset","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"16"}]}}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_1/FusedBatchNormV3/Scaled","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"16"}]}}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_1/FusedBatchNormV3/Offset","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"16"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_4/FusedBatchNormV3/Scaled","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"32"}]}}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_4/FusedBatchNormV3/Offset","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"32"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_3/FusedBatchNormV3/Scaled","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"32"}]}}},"dtype":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_3/FusedBatchNormV3/Offset","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"32"}]}}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/activation_1/Relu","op":"_FusedConv2D","input":["conv2d_1_input","StatefulPartitionedCall/sequential_1/conv2d_1/Conv2D/ReadVariableOp","StatefulPartitionedCall/sequential_1/conv2d_1/BiasAdd/ReadVariableOp"],"device":"/device:CPU:0","attr":{"dilations":{"list":{"i":["1","1","1","1"]}},"T":{"type":"DT_FLOAT"},"explicit_paddings":{"list":{}},"use_cudnn_on_gpu":{"b":true},"data_format":{"s":"TkhXQw=="},"num_args":{"i":"1"},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","UmVsdQ=="]}},"strides":{"list":{"i":["1","1","1","1"]}},"epsilon":{"f":0},"padding":{"s":"U0FNRQ=="}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_1/FusedBatchNormV3/Mul","op":"Mul","input":["StatefulPartitionedCall/sequential_1/activation_1/Relu","StatefulPartitionedCall/sequential_1/batch_normalization_1/FusedBatchNormV3/Scaled"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_1/FusedBatchNormV3","op":"Add","input":["StatefulPartitionedCall/sequential_1/batch_normalization_1/FusedBatchNormV3/Mul","StatefulPartitionedCall/sequential_1/batch_normalization_1/FusedBatchNormV3/Offset"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/activation_2/Relu","op":"_FusedConv2D","input":["StatefulPartitionedCall/sequential_1/batch_normalization_1/FusedBatchNormV3","StatefulPartitionedCall/sequential_1/conv2d_2/Conv2D/ReadVariableOp","StatefulPartitionedCall/sequential_1/conv2d_2/BiasAdd/ReadVariableOp"],"device":"/device:CPU:0","attr":{"epsilon":{"f":0},"explicit_paddings":{"list":{}},"T":{"type":"DT_FLOAT"},"dilations":{"list":{"i":["1","1","1","1"]}},"strides":{"list":{"i":["1","1","1","1"]}},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","UmVsdQ=="]}},"data_format":{"s":"TkhXQw=="},"num_args":{"i":"1"},"padding":{"s":"U0FNRQ=="},"use_cudnn_on_gpu":{"b":true}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_2/FusedBatchNormV3/Mul","op":"Mul","input":["StatefulPartitionedCall/sequential_1/activation_2/Relu","StatefulPartitionedCall/sequential_1/batch_normalization_2/FusedBatchNormV3/Scaled"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_2/FusedBatchNormV3","op":"Add","input":["StatefulPartitionedCall/sequential_1/batch_normalization_2/FusedBatchNormV3/Mul","StatefulPartitionedCall/sequential_1/batch_normalization_2/FusedBatchNormV3/Offset"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/max_pooling2d_1/MaxPool","op":"MaxPool","input":["StatefulPartitionedCall/sequential_1/batch_normalization_2/FusedBatchNormV3"],"attr":{"T":{"type":"DT_FLOAT"},"data_format":{"s":"TkhXQw=="},"padding":{"s":"VkFMSUQ="},"ksize":{"list":{"i":["1","2","2","1"]}},"explicit_paddings":{"list":{}},"strides":{"list":{"i":["1","2","2","1"]}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/activation_3/Relu","op":"_FusedConv2D","input":["StatefulPartitionedCall/sequential_1/max_pooling2d_1/MaxPool","StatefulPartitionedCall/sequential_1/conv2d_3/Conv2D/ReadVariableOp","StatefulPartitionedCall/sequential_1/conv2d_3/BiasAdd/ReadVariableOp"],"device":"/device:CPU:0","attr":{"use_cudnn_on_gpu":{"b":true},"padding":{"s":"U0FNRQ=="},"T":{"type":"DT_FLOAT"},"explicit_paddings":{"list":{}},"strides":{"list":{"i":["1","1","1","1"]}},"data_format":{"s":"TkhXQw=="},"num_args":{"i":"1"},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","UmVsdQ=="]}},"dilations":{"list":{"i":["1","1","1","1"]}},"epsilon":{"f":0}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_3/FusedBatchNormV3/Mul","op":"Mul","input":["StatefulPartitionedCall/sequential_1/activation_3/Relu","StatefulPartitionedCall/sequential_1/batch_normalization_3/FusedBatchNormV3/Scaled"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_3/FusedBatchNormV3","op":"Add","input":["StatefulPartitionedCall/sequential_1/batch_normalization_3/FusedBatchNormV3/Mul","StatefulPartitionedCall/sequential_1/batch_normalization_3/FusedBatchNormV3/Offset"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/activation_4/Relu","op":"_FusedConv2D","input":["StatefulPartitionedCall/sequential_1/batch_normalization_3/FusedBatchNormV3","StatefulPartitionedCall/sequential_1/conv2d_4/Conv2D/ReadVariableOp","StatefulPartitionedCall/sequential_1/conv2d_4/BiasAdd/ReadVariableOp"],"device":"/device:CPU:0","attr":{"num_args":{"i":"1"},"padding":{"s":"U0FNRQ=="},"use_cudnn_on_gpu":{"b":true},"data_format":{"s":"TkhXQw=="},"T":{"type":"DT_FLOAT"},"strides":{"list":{"i":["1","1","1","1"]}},"epsilon":{"f":0},"explicit_paddings":{"list":{}},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","UmVsdQ=="]}},"dilations":{"list":{"i":["1","1","1","1"]}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_4/FusedBatchNormV3/Mul","op":"Mul","input":["StatefulPartitionedCall/sequential_1/activation_4/Relu","StatefulPartitionedCall/sequential_1/batch_normalization_4/FusedBatchNormV3/Scaled"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_4/FusedBatchNormV3","op":"Add","input":["StatefulPartitionedCall/sequential_1/batch_normalization_4/FusedBatchNormV3/Mul","StatefulPartitionedCall/sequential_1/batch_normalization_4/FusedBatchNormV3/Offset"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/max_pooling2d_2/MaxPool","op":"MaxPool","input":["StatefulPartitionedCall/sequential_1/batch_normalization_4/FusedBatchNormV3"],"attr":{"explicit_paddings":{"list":{}},"T":{"type":"DT_FLOAT"},"data_format":{"s":"TkhXQw=="},"padding":{"s":"VkFMSUQ="},"ksize":{"list":{"i":["1","2","2","1"]}},"strides":{"list":{"i":["1","2","2","1"]}}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/flatten_1/Reshape","op":"Reshape","input":["StatefulPartitionedCall/sequential_1/max_pooling2d_2/MaxPool","StatefulPartitionedCall/sequential_1/flatten_1/Const"],"attr":{"T":{"type":"DT_FLOAT"},"Tshape":{"type":"DT_INT32"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/activation_5/Relu","op":"_FusedMatMul","input":["StatefulPartitionedCall/sequential_1/flatten_1/Reshape","StatefulPartitionedCall/sequential_1/dense_1/MatMul/ReadVariableOp","StatefulPartitionedCall/sequential_1/dense_1/BiasAdd/ReadVariableOp"],"device":"/device:CPU:0","attr":{"fused_ops":{"list":{"s":["Qmlhc0FkZA==","UmVsdQ=="]}},"T":{"type":"DT_FLOAT"},"epsilon":{"f":0},"transpose_b":{"b":false},"num_args":{"i":"1"},"transpose_a":{"b":false}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_5/batchnorm/mul_1","op":"Mul","input":["StatefulPartitionedCall/sequential_1/activation_5/Relu","StatefulPartitionedCall/sequential_1/batch_normalization_5/batchnorm/mul"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_5/batchnorm/add_1","op":"AddV2","input":["StatefulPartitionedCall/sequential_1/batch_normalization_5/batchnorm/mul_1","StatefulPartitionedCall/sequential_1/batch_normalization_5/batchnorm/sub"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/dense_2/BiasAdd","op":"_FusedMatMul","input":["StatefulPartitionedCall/sequential_1/batch_normalization_5/batchnorm/add_1","StatefulPartitionedCall/sequential_1/dense_2/MatMul/ReadVariableOp","StatefulPartitionedCall/sequential_1/dense_2/BiasAdd/ReadVariableOp"],"device":"/device:CPU:0","attr":{"fused_ops":{"list":{"s":["Qmlhc0FkZA=="]}},"transpose_a":{"b":false},"epsilon":{"f":0},"transpose_b":{"b":false},"num_args":{"i":"1"},"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"StatefulPartitionedCall/sequential_1/activation_6/Softmax","op":"Softmax","input":["StatefulPartitionedCall/sequential_1/dense_2/BiasAdd"],"attr":{"T":{"type":"DT_FLOAT"}}},
|
||||
{"name":"Identity","op":"Identity","input":["StatefulPartitionedCall/sequential_1/activation_6/Softmax"],"attr":{"T":{"type":"DT_FLOAT"}}}
|
||||
],
|
||||
"library": {},
|
||||
"versions":
|
||||
{
|
||||
"producer": 808
|
||||
}
|
||||
},
|
||||
"weightsManifest":
|
||||
[
|
||||
{
|
||||
"paths": ["liveness.bin"],
|
||||
"weights": [{"name":"StatefulPartitionedCall/sequential_1/conv2d_1/Conv2D/ReadVariableOp","shape":[3,3,3,16],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/conv2d_1/BiasAdd/ReadVariableOp","shape":[16],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/conv2d_2/Conv2D/ReadVariableOp","shape":[3,3,16,16],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/conv2d_2/BiasAdd/ReadVariableOp","shape":[16],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/conv2d_3/Conv2D/ReadVariableOp","shape":[3,3,16,32],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/conv2d_3/BiasAdd/ReadVariableOp","shape":[32],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/conv2d_4/Conv2D/ReadVariableOp","shape":[3,3,32,32],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/conv2d_4/BiasAdd/ReadVariableOp","shape":[32],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/flatten_1/Const","shape":[2],"dtype":"int32"},{"name":"StatefulPartitionedCall/sequential_1/dense_1/MatMul/ReadVariableOp","shape":[2048,64],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/dense_1/BiasAdd/ReadVariableOp","shape":[64],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_5/batchnorm/mul","shape":[64],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_5/batchnorm/sub","shape":[64],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/dense_2/MatMul/ReadVariableOp","shape":[64,2],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/dense_2/BiasAdd/ReadVariableOp","shape":[2],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_2/FusedBatchNormV3/Scaled","shape":[16],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_2/FusedBatchNormV3/Offset","shape":[16],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_1/FusedBatchNormV3/Scaled","shape":[16],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_1/FusedBatchNormV3/Offset","shape":[16],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_4/FusedBatchNormV3/Scaled","shape":[32],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_4/FusedBatchNormV3/Offset","shape":[32],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_3/FusedBatchNormV3/Scaled","shape":[32],"dtype":"float32"},{"name":"StatefulPartitionedCall/sequential_1/batch_normalization_3/FusedBatchNormV3/Offset","shape":[32],"dtype":"float32"}]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -78,7 +78,6 @@ export async function predict(input: Tensor, config: Config): Promise<FaceResult
|
|||
if (!config.face.mesh?.enabled) { // mesh not enabled, return resuts from detector only
|
||||
face.box = util.getClampedBox(box, input);
|
||||
face.boxRaw = util.getRawBox(box, input);
|
||||
face.boxScore = Math.round(100 * box.confidence || 0) / 100;
|
||||
face.score = face.boxScore;
|
||||
face.mesh = box.landmarks.map((pt) => [
|
||||
((box.startPoint[0] + box.endPoint[0])) / 2 + ((box.endPoint[0] + box.startPoint[0]) * pt[0] / blazeface.size()),
|
||||
|
@ -102,7 +101,7 @@ export async function predict(input: Tensor, config: Config): Promise<FaceResult
|
|||
face.mesh = util.transformRawCoords(rawCoords, box, angle, rotationMatrix, inputSize); // get processed mesh
|
||||
face.meshRaw = face.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize]);
|
||||
for (const key of Object.keys(coords.meshAnnotations)) face.annotations[key] = coords.meshAnnotations[key].map((index) => face.mesh[index]); // add annotations
|
||||
box = util.squarifyBox(util.enlargeBox(util.calculateLandmarksBoundingBox(face.mesh), enlargeFact)); // redefine box with mesh calculated one
|
||||
box = util.squarifyBox({ ...util.enlargeBox(util.calculateLandmarksBoundingBox(face.mesh), enlargeFact), confidence: box.confidence }); // redefine box with mesh calculated one
|
||||
face.box = util.getClampedBox(box, input); // update detected box with box around the face mesh
|
||||
face.boxRaw = util.getRawBox(box, input);
|
||||
face.score = face.faceScore;
|
||||
|
|
|
@ -82,7 +82,7 @@ export async function process(input: Input, config: Config, getTensor: boolean =
|
|||
if ((input)['isDisposedInternal']) {
|
||||
throw new Error('input tensor is disposed');
|
||||
} else if (!(input as Tensor).shape || (input as Tensor).shape.length !== 4 || (input as Tensor).shape[0] !== 1 || (input as Tensor).shape[3] !== 3) {
|
||||
throw new Error(`input tensor shape must be [1, height, width, 3] and instead was ${input['shape']}`);
|
||||
throw new Error('input tensor shape must be [1, height, width, 3] and instead was' + (input['shape'] ? input['shape'].toString() : 'unknown'));
|
||||
} else {
|
||||
return { tensor: tf.clone(input), canvas: (config.filter.return ? outCanvas : null) };
|
||||
}
|
||||
|
|
|
@ -1,25 +1,26 @@
|
|||
2021-11-08 16:36:28 [36mINFO: [39m @vladmandic/human version 2.5.1
|
||||
2021-11-08 16:36:28 [36mINFO: [39m User: vlado Platform: linux Arch: x64 Node: v17.0.1
|
||||
2021-11-08 16:36:28 [36mINFO: [39m Application: {"name":"@vladmandic/human","version":"2.5.1"}
|
||||
2021-11-08 16:36:28 [36mINFO: [39m Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
|
||||
2021-11-08 16:36:28 [36mINFO: [39m Toolchain: {"build":"0.6.3","esbuild":"0.13.12","typescript":"4.4.4","typedoc":"0.22.8","eslint":"8.2.0"}
|
||||
2021-11-08 16:36:28 [36mINFO: [39m Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
|
||||
2021-11-08 16:36:28 [35mSTATE:[39m Clean: {"locations":["dist/*","types/*","typedoc/*"]}
|
||||
2021-11-08 16:36:28 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":102,"outputBytes":1275}
|
||||
2021-11-08 16:36:28 [35mSTATE:[39m Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":56,"inputBytes":523123,"outputBytes":441937}
|
||||
2021-11-08 16:36:28 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":1283}
|
||||
2021-11-08 16:36:28 [35mSTATE:[39m Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":56,"inputBytes":523131,"outputBytes":441941}
|
||||
2021-11-08 16:36:28 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":149,"outputBytes":1350}
|
||||
2021-11-08 16:36:28 [35mSTATE:[39m Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":56,"inputBytes":523198,"outputBytes":442013}
|
||||
2021-11-08 16:36:28 [35mSTATE:[39m Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1063,"outputBytes":1652}
|
||||
2021-11-08 16:36:28 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":2326,"outputBytes":912}
|
||||
2021-11-08 16:36:28 [35mSTATE:[39m Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":56,"inputBytes":522760,"outputBytes":443927}
|
||||
2021-11-08 16:36:29 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/custom","format":"esm","platform":"browser","input":"tfjs/tf-custom.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":2562703,"outputBytes":2497652}
|
||||
2021-11-08 16:36:29 [35mSTATE:[39m Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":56,"inputBytes":3019500,"outputBytes":1612928}
|
||||
2021-11-08 16:36:30 [35mSTATE:[39m Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":56,"inputBytes":3019500,"outputBytes":2947346}
|
||||
2021-11-08 16:36:52 [35mSTATE:[39m Typings: {"input":"src/human.ts","output":"types","files":49}
|
||||
2021-11-08 16:36:59 [35mSTATE:[39m TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":48,"generated":true}
|
||||
2021-11-08 16:36:59 [35mSTATE:[39m Compile: {"name":"demo/browser","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":5801,"outputBytes":3822}
|
||||
2021-11-08 16:37:37 [35mSTATE:[39m Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":90,"errors":0,"warnings":0}
|
||||
2021-11-08 16:37:38 [35mSTATE:[39m ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
|
||||
2021-11-08 16:37:38 [36mINFO: [39m Done...
|
||||
2021-11-09 10:37:39 [36mINFO: [39m @vladmandic/human version 2.5.1
|
||||
2021-11-09 10:37:39 [36mINFO: [39m User: vlado Platform: linux Arch: x64 Node: v17.0.1
|
||||
2021-11-09 10:37:39 [36mINFO: [39m Application: {"name":"@vladmandic/human","version":"2.5.1"}
|
||||
2021-11-09 10:37:39 [36mINFO: [39m Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
|
||||
2021-11-09 10:37:39 [36mINFO: [39m Toolchain: {"build":"0.6.3","esbuild":"0.13.12","typescript":"4.4.4","typedoc":"0.22.8","eslint":"8.2.0"}
|
||||
2021-11-09 10:37:39 [36mINFO: [39m Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
|
||||
2021-11-09 10:37:39 [35mSTATE:[39m Clean: {"locations":["dist/*","types/*","typedoc/*"]}
|
||||
2021-11-09 10:37:39 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":102,"outputBytes":1275}
|
||||
2021-11-09 10:37:39 [35mSTATE:[39m Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":56,"inputBytes":523132,"outputBytes":441945}
|
||||
2021-11-09 10:37:39 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":1283}
|
||||
2021-11-09 10:37:39 [35mSTATE:[39m Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":56,"inputBytes":523140,"outputBytes":441949}
|
||||
2021-11-09 10:37:39 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":149,"outputBytes":1350}
|
||||
2021-11-09 10:37:39 [35mSTATE:[39m Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":56,"inputBytes":523207,"outputBytes":442021}
|
||||
2021-11-09 10:37:39 [35mSTATE:[39m Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1063,"outputBytes":1652}
|
||||
2021-11-09 10:37:39 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":2326,"outputBytes":912}
|
||||
2021-11-09 10:37:39 [35mSTATE:[39m Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":56,"inputBytes":522769,"outputBytes":443935}
|
||||
2021-11-09 10:37:40 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/custom","format":"esm","platform":"browser","input":"tfjs/tf-custom.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":2562703,"outputBytes":2497652}
|
||||
2021-11-09 10:37:40 [35mSTATE:[39m Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":56,"inputBytes":3019509,"outputBytes":1612938}
|
||||
2021-11-09 10:37:41 [35mSTATE:[39m Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":56,"inputBytes":3019509,"outputBytes":2947355}
|
||||
2021-11-09 10:38:03 [35mSTATE:[39m Typings: {"input":"src/human.ts","output":"types","files":49}
|
||||
2021-11-09 10:38:10 [35mSTATE:[39m TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":48,"generated":true}
|
||||
2021-11-09 10:38:10 [35mSTATE:[39m Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":5801,"outputBytes":3822}
|
||||
2021-11-09 10:38:10 [35mSTATE:[39m Compile: {"name":"demo/facerecognition","format":"esm","platform":"browser","input":"demo/facerecognition/index.ts","output":"demo/facerecognition/index.js","files":1,"inputBytes":8148,"outputBytes":5851}
|
||||
2021-11-09 10:38:48 [35mSTATE:[39m Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":90,"errors":0,"warnings":0}
|
||||
2021-11-09 10:38:49 [35mSTATE:[39m ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
|
||||
2021-11-09 10:38:49 [36mINFO: [39m Done...
|
||||
|
|
Loading…
Reference in New Issue