prototype global fetch handler

Vladimir Mandic 2022-01-16 09:49:55 -05:00
parent dfc44ccbd9
commit 0c2bd1a4c1
33 changed files with 2578 additions and 1752 deletions

25
demo/nodejs/node-fetch.js Normal file
View File

@ -0,0 +1,25 @@
const fs = require('fs');
// eslint-disable-next-line import/no-extraneous-dependencies, no-unused-vars, @typescript-eslint/no-unused-vars
const tf = require('@tensorflow/tfjs-node'); // in nodejs environments tfjs-node is required to be loaded before human
// const faceapi = require('@vladmandic/face-api'); // use this when human is installed as module (majority of use cases)
const Human = require('../../dist/human.node.js'); // use this when using human in dev mode
const humanConfig = {
modelBasePath: 'https://vladmandic.github.io/human/models/',
};
async function main(inputFile) {
// @ts-ignore
global.fetch = (await import('node-fetch')).default;
const human = new Human.Human(humanConfig); // create instance of human using default configuration
await human.load(); // optional as models would be loaded on-demand first time they are required
await human.warmup(); // optional as model warmup is performed on-demand first time its executed
const buffer = fs.readFileSync(inputFile); // read file data into buffer
const tensor = human.tf.node.decodeImage(buffer); // decode jpg data
const result = await human.detect(tensor); // run detection; will initialize backend and on-demand load models
// eslint-disable-next-line no-console
console.log(result.gesture);
}
main('samples/in/ai-body.jpg');

View File

@ -1350,6 +1350,43 @@ var env = new Env();
// package.json
var version10 = "2.5.8";
// src/tfjs/load.ts
var options = {
appName: "human",
autoSave: true,
verbose: true
};
async function httpHandler(url, init2) {
if (options.fetchFunc)
return options.fetchFunc(url, init2);
else
log("error: fetch function is not defined");
return null;
}
var tfLoadOptions = {
onProgress: (...args) => {
if (options.onProgress)
options.onProgress(...args);
else if (options.verbose)
log("load model progress:", ...args);
},
fetchFunc: (url, init2) => {
if (options.verbose)
log("load model fetch:", url, init2);
if (url.toString().toLowerCase().startsWith("http"))
return httpHandler(url, init2);
return null;
}
};
async function loadModel2(modelUrl, loadOptions) {
if (loadOptions)
options = mergeDeep(loadOptions);
if (!options.fetchFunc && typeof globalThis.fetch !== "undefined")
options.fetchFunc = globalThis.fetch;
const model18 = await tfjs_esm_exports.loadGraphModel(modelUrl, tfLoadOptions);
return model18;
}
// src/gear/gear.ts
var model;
var last2 = [];
@ -1362,7 +1399,7 @@ async function load(config3) {
if (env.initial)
model = null;
if (!model) {
model = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.face["gear"].modelPath));
model = await loadModel2(join(config3.modelBasePath, config3.face["gear"].modelPath));
if (!model || !model["modelUrl"])
log("load model failed:", config3.face["gear"].modelPath);
else if (config3.debug)
@ -1443,7 +1480,7 @@ async function load2(config3) {
if (env.initial)
model2 = null;
if (!model2) {
model2 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.face["ssrnet"].modelPathAge));
model2 = await loadModel2(join(config3.modelBasePath, config3.face["ssrnet"].modelPathAge));
if (!model2 || !model2["modelUrl"])
log("load model failed:", config3.face["ssrnet"].modelPathAge);
else if (config3.debug)
@ -1497,7 +1534,7 @@ async function load3(config3) {
if (env.initial)
model3 = null;
if (!model3) {
model3 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.face["ssrnet"].modelPathGender));
model3 = await loadModel2(join(config3.modelBasePath, config3.face["ssrnet"].modelPathGender));
if (!model3 || !model3["modelUrl"])
log("load model failed:", config3.face["ssrnet"].modelPathGender);
else if (config3.debug)
@ -1556,7 +1593,7 @@ async function load4(config3) {
if (env.initial)
model4 = null;
if (!model4) {
model4 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.antispoof) == null ? void 0 : _a.modelPath) || ""));
model4 = await loadModel2(join(config3.modelBasePath, ((_a = config3.face.antispoof) == null ? void 0 : _a.modelPath) || ""));
if (!model4 || !model4["modelUrl"])
log("load model failed:", (_b = config3.face.antispoof) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -5048,7 +5085,7 @@ async function load5(config3) {
if (env.initial)
model5 = null;
if (!model5) {
model5 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.detector) == null ? void 0 : _a.modelPath) || ""));
model5 = await loadModel2(join(config3.modelBasePath, ((_a = config3.face.detector) == null ? void 0 : _a.modelPath) || ""));
if (!model5 || !model5["modelUrl"])
log("load model failed:", (_b = config3.face.detector) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -5282,7 +5319,7 @@ async function loadDetect(config3) {
if (env3.initial)
models.detector = null;
if (!models.detector && config3.body["detector"] && config3.body["detector"]["modelPath"] || "") {
models.detector = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.body["detector"]["modelPath"] || ""));
models.detector = await loadModel2(join(config3.modelBasePath, config3.body["detector"]["modelPath"] || ""));
const inputs = Object.values(models.detector.modelSignature["inputs"]);
inputSize3.detector[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize3.detector[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
@ -5299,7 +5336,7 @@ async function loadPose(config3) {
if (env3.initial)
models.landmarks = null;
if (!models.landmarks) {
models.landmarks = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.body.modelPath || ""));
models.landmarks = await loadModel2(join(config3.modelBasePath, config3.body.modelPath || ""));
const inputs = Object.values(models.landmarks.modelSignature["inputs"]);
inputSize3.landmarks[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize3.landmarks[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
@ -5531,7 +5568,7 @@ async function load6(config3) {
if (env.initial)
model6 = null;
if (!model6) {
model6 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.object.modelPath || ""));
model6 = await loadModel2(join(config3.modelBasePath, config3.object.modelPath || ""));
const inputs = Object.values(model6.modelSignature["inputs"]);
inputSize4 = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!model6 || !model6["modelUrl"])
@ -5645,7 +5682,7 @@ async function load7(config3) {
if (env.initial)
model7 = null;
if (!model7) {
model7 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.body.modelPath || ""));
model7 = await loadModel2(join(config3.modelBasePath, config3.body.modelPath || ""));
if (!model7 || !model7["modelUrl"])
log("load model failed:", config3.body.modelPath);
else if (config3.debug)
@ -5762,7 +5799,7 @@ async function load8(config3) {
if (env.initial)
model8 = null;
if (!model8) {
model8 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.emotion) == null ? void 0 : _a.modelPath) || ""));
model8 = await loadModel2(join(config3.modelBasePath, ((_a = config3.face.emotion) == null ? void 0 : _a.modelPath) || ""));
if (!model8 || !model8["modelUrl"])
log("load model failed:", (_b = config3.face.emotion) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -5820,7 +5857,7 @@ async function load9(config3) {
if (env.initial)
model9 = null;
if (!model9) {
model9 = await tfjs_esm_exports.loadGraphModel(modelUrl);
model9 = await loadModel2(modelUrl);
if (!model9)
log("load model failed:", config3.face["mobilefacenet"].modelPath);
else if (config3.debug)
@ -5877,7 +5914,7 @@ async function load10(config3) {
if (env.initial)
model10 = null;
if (!model10) {
model10 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.iris) == null ? void 0 : _a.modelPath) || ""));
model10 = await loadModel2(join(config3.modelBasePath, ((_a = config3.face.iris) == null ? void 0 : _a.modelPath) || ""));
if (!model10 || !model10["modelUrl"])
log("load model failed:", (_b = config3.face.iris) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -6082,7 +6119,7 @@ async function load11(config3) {
if (env.initial)
model11 = null;
if (!model11) {
model11 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.mesh) == null ? void 0 : _a.modelPath) || ""));
model11 = await loadModel2(join(config3.modelBasePath, ((_a = config3.face.mesh) == null ? void 0 : _a.modelPath) || ""));
if (!model11 || !model11["modelUrl"])
log("load model failed:", (_b = config3.face.mesh) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -6107,7 +6144,7 @@ async function load12(config3) {
if (env.initial)
model12 = null;
if (!model12) {
model12 = await tfjs_esm_exports.loadGraphModel(modelUrl);
model12 = await loadModel2(modelUrl);
if (!model12)
log("load model failed:", ((_b = config3.face.description) == null ? void 0 : _b.modelPath) || "");
else if (config3.debug)
@ -9616,7 +9653,7 @@ var fingergesture_default = [ThumbsUp, Victory, Point, MiddleFinger, OpenPalm];
// src/hand/fingerpose.ts
var minConfidence = 0.7;
var options = {
var options2 = {
HALF_CURL_START_LIMIT: 60,
NO_CURL_START_LIMIT: 130,
DISTANCE_VOTE_POWER: 1.1,
@ -9674,9 +9711,9 @@ function estimateFingerCurl(startPoint, midPoint, endPoint) {
let angleOfCurve = Math.acos(cos_in);
angleOfCurve = 57.2958 * angleOfCurve % 180;
let fingerCurl;
if (angleOfCurve > options.NO_CURL_START_LIMIT)
if (angleOfCurve > options2.NO_CURL_START_LIMIT)
fingerCurl = FingerCurl.none;
else if (angleOfCurve > options.HALF_CURL_START_LIMIT)
else if (angleOfCurve > options2.HALF_CURL_START_LIMIT)
fingerCurl = FingerCurl.half;
else
fingerCurl = FingerCurl.full;
@ -9753,11 +9790,11 @@ function calculateFingerDirection(startPoint, midPoint, endPoint, fingerSlopes)
let voteHorizontal = 0;
const start_end_x_y_dist_ratio = max_dist_y / (max_dist_x + 1e-5);
if (start_end_x_y_dist_ratio > 1.5)
voteVertical += options.DISTANCE_VOTE_POWER;
voteVertical += options2.DISTANCE_VOTE_POWER;
else if (start_end_x_y_dist_ratio > 0.66)
voteDiagonal += options.DISTANCE_VOTE_POWER;
voteDiagonal += options2.DISTANCE_VOTE_POWER;
else
voteHorizontal += options.DISTANCE_VOTE_POWER;
voteHorizontal += options2.DISTANCE_VOTE_POWER;
const start_mid_dist = Math.sqrt(start_mid_x_dist * start_mid_x_dist + start_mid_y_dist * start_mid_y_dist);
const start_end_dist = Math.sqrt(start_end_x_dist * start_end_x_dist + start_end_y_dist * start_end_y_dist);
const mid_end_dist = Math.sqrt(mid_end_x_dist * mid_end_x_dist + mid_end_y_dist * mid_end_y_dist);
@ -9776,12 +9813,12 @@ function calculateFingerDirection(startPoint, midPoint, endPoint, fingerSlopes)
const calcStartPoint = [calc_start_point_x, calc_start_point_y];
const calcEndPoint = [calc_end_point_x, calc_end_point_y];
const totalAngle = getSlopes(calcStartPoint, calcEndPoint);
const votes = angleOrientationAt(totalAngle, options.TOTAL_ANGLE_VOTE_POWER);
const votes = angleOrientationAt(totalAngle, options2.TOTAL_ANGLE_VOTE_POWER);
voteVertical += votes[0];
voteDiagonal += votes[1];
voteHorizontal += votes[2];
for (const fingerSlope of fingerSlopes) {
const fingerVotes = angleOrientationAt(fingerSlope, options.SINGLE_ANGLE_VOTE_POWER);
const fingerVotes = angleOrientationAt(fingerSlope, options2.SINGLE_ANGLE_VOTE_POWER);
voteVertical += fingerVotes[0];
voteDiagonal += fingerVotes[1];
voteHorizontal += fingerVotes[2];
@ -9930,23 +9967,23 @@ async function predict12(input, config3) {
return hands;
}
async function load13(config3) {
var _a, _b, _c, _d, _e, _f;
var _a, _b, _c, _d;
if (env.initial) {
handDetectorModel = null;
handPoseModel = null;
}
if (!handDetectorModel || !handPoseModel) {
[handDetectorModel, handPoseModel] = await Promise.all([
config3.hand.enabled ? tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""), { fromTFHub: (((_b = config3.hand.detector) == null ? void 0 : _b.modelPath) || "").includes("tfhub.dev") }) : null,
config3.hand.landmarks ? tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_c = config3.hand.skeleton) == null ? void 0 : _c.modelPath) || ""), { fromTFHub: (((_d = config3.hand.skeleton) == null ? void 0 : _d.modelPath) || "").includes("tfhub.dev") }) : null
config3.hand.enabled ? loadModel2(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || "")) : null,
config3.hand.landmarks ? loadModel2(join(config3.modelBasePath, ((_b = config3.hand.skeleton) == null ? void 0 : _b.modelPath) || "")) : null
]);
if (config3.hand.enabled) {
if (!handDetectorModel || !handDetectorModel["modelUrl"])
log("load model failed:", ((_e = config3.hand.detector) == null ? void 0 : _e.modelPath) || "");
log("load model failed:", ((_c = config3.hand.detector) == null ? void 0 : _c.modelPath) || "");
else if (config3.debug)
log("load model:", handDetectorModel["modelUrl"]);
if (!handPoseModel || !handPoseModel["modelUrl"])
log("load model failed:", ((_f = config3.hand.skeleton) == null ? void 0 : _f.modelPath) || "");
log("load model failed:", ((_d = config3.hand.skeleton) == null ? void 0 : _d.modelPath) || "");
else if (config3.debug)
log("load model:", handPoseModel["modelUrl"]);
}
@ -9992,7 +10029,7 @@ async function loadDetect2(config3) {
models2[0] = null;
if (!models2[0]) {
fakeOps(["tensorlistreserve", "enter", "tensorlistfromtensor", "merge", "loopcond", "switch", "exit", "tensorliststack", "nextiteration", "tensorlistsetitem", "tensorlistgetitem", "reciprocal", "shape", "split", "where"], config3);
models2[0] = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""));
models2[0] = await loadModel2(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""));
const inputs = Object.values(models2[0].modelSignature["inputs"]);
inputSize7[0][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize7[0][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
@ -10009,7 +10046,7 @@ async function loadSkeleton(config3) {
if (env.initial)
models2[1] = null;
if (!models2[1]) {
models2[1] = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.skeleton) == null ? void 0 : _a.modelPath) || ""));
models2[1] = await loadModel2(join(config3.modelBasePath, ((_a = config3.hand.skeleton) == null ? void 0 : _a.modelPath) || ""));
const inputs = Object.values(models2[1].modelSignature["inputs"]);
inputSize7[1][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize7[1][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
@ -10157,7 +10194,7 @@ async function load14(config3) {
if (env.initial)
model13 = null;
if (!model13) {
model13 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.liveness) == null ? void 0 : _a.modelPath) || ""));
model13 = await loadModel(join(config3.modelBasePath, ((_a = config3.face.liveness) == null ? void 0 : _a.modelPath) || ""));
if (!model13 || !model13["modelUrl"])
log("load model failed:", (_b = config3.face.liveness) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -10358,7 +10395,7 @@ async function load15(config3) {
model14 = null;
if (!model14) {
fakeOps(["size"], config3);
model14 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.body.modelPath || ""));
model14 = await loadModel2(join(config3.modelBasePath, config3.body.modelPath || ""));
if (!model14 || !model14["modelUrl"])
log("load model failed:", config3.body.modelPath);
else if (config3.debug)
@ -10486,7 +10523,7 @@ var inputSize9 = 0;
var scaleBox = 2.5;
async function load16(config3) {
if (!model15 || env.initial) {
model15 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.object.modelPath || ""));
model15 = await loadModel2(join(config3.modelBasePath, config3.object.modelPath || ""));
const inputs = Object.values(model15.modelSignature["inputs"]);
inputSize9 = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!model15 || !model15["modelUrl"])
@ -10916,7 +10953,7 @@ async function predict17(input, config3) {
}
async function load17(config3) {
if (!model16 || env.initial) {
model16 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.body.modelPath || ""));
model16 = await loadModel2(join(config3.modelBasePath, config3.body.modelPath || ""));
if (!model16 || !model16["modelUrl"])
log("load model failed:", config3.body.modelPath);
else if (config3.debug)
@ -10931,7 +10968,7 @@ var model17;
var busy = false;
async function load18(config3) {
if (!model17 || env.initial) {
model17 = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, config3.segmentation.modelPath || ""));
model17 = await loadModel2(join(config3.modelBasePath, config3.segmentation.modelPath || ""));
if (!model17 || !model17["modelUrl"])
log("load model failed:", config3.segmentation.modelPath);
else if (config3.debug)
@ -11361,7 +11398,7 @@ function fakeOps(kernelNames, config3) {
}
// src/util/draw.ts
var options2 = {
var options3 = {
color: "rgba(173, 216, 230, 0.6)",
labelColor: "rgba(173, 216, 230, 1)",
shadowColor: "black",
@ -11486,7 +11523,7 @@ function arrow(ctx, from, to, radius = 5) {
ctx.fill();
}
async function gesture(inCanvas2, result, drawOptions) {
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
if (localOptions.drawGestures) {
@ -11516,7 +11553,7 @@ async function gesture(inCanvas2, result, drawOptions) {
}
async function face(inCanvas2, result, drawOptions) {
var _a, _b, _c, _d, _e;
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
const ctx = getCanvasContext(inCanvas2);
@ -11649,7 +11686,7 @@ async function face(inCanvas2, result, drawOptions) {
}
async function body(inCanvas2, result, drawOptions) {
var _a;
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
const ctx = getCanvasContext(inCanvas2);
@ -11698,7 +11735,7 @@ async function body(inCanvas2, result, drawOptions) {
}
}
async function hand(inCanvas2, result, drawOptions) {
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
const ctx = getCanvasContext(inCanvas2);
@ -11768,7 +11805,7 @@ async function hand(inCanvas2, result, drawOptions) {
}
}
async function object(inCanvas2, result, drawOptions) {
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
const ctx = getCanvasContext(inCanvas2);
@ -11795,7 +11832,7 @@ async function object(inCanvas2, result, drawOptions) {
}
}
async function person(inCanvas2, result, drawOptions) {
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
const ctx = getCanvasContext(inCanvas2);
@ -11833,7 +11870,7 @@ async function all(inCanvas2, result, drawOptions) {
if (!result || !result.performance || !result || !inCanvas2)
return null;
const timeStamp = now();
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
const promise = Promise.all([
face(inCanvas2, result.face, localOptions),
body(inCanvas2, result.body, localOptions),
@ -12414,13 +12451,13 @@ function calc2(newResult, config3) {
}
// src/face/match.ts
function distance(descriptor1, descriptor2, options3 = { order: 2, multiplier: 25 }) {
function distance(descriptor1, descriptor2, options4 = { order: 2, multiplier: 25 }) {
let sum3 = 0;
for (let i = 0; i < descriptor1.length; i++) {
const diff = !options3.order || options3.order === 2 ? descriptor1[i] - descriptor2[i] : Math.abs(descriptor1[i] - descriptor2[i]);
sum3 += !options3.order || options3.order === 2 ? diff * diff : diff ** options3.order;
const diff = !options4.order || options4.order === 2 ? descriptor1[i] - descriptor2[i] : Math.abs(descriptor1[i] - descriptor2[i]);
sum3 += !options4.order || options4.order === 2 ? diff * diff : diff ** options4.order;
}
return (options3.multiplier || 20) * sum3;
return (options4.multiplier || 20) * sum3;
}
var normalizeDistance = (dist, order, min2, max4) => {
if (dist === 0)
@ -12430,26 +12467,26 @@ var normalizeDistance = (dist, order, min2, max4) => {
const clamp2 = Math.max(Math.min(norm, 1), 0);
return clamp2;
};
function similarity(descriptor1, descriptor2, options3 = { order: 2, multiplier: 25, min: 0.2, max: 0.8 }) {
const dist = distance(descriptor1, descriptor2, options3);
return normalizeDistance(dist, options3.order || 2, options3.min || 0, options3.max || 1);
function similarity(descriptor1, descriptor2, options4 = { order: 2, multiplier: 25, min: 0.2, max: 0.8 }) {
const dist = distance(descriptor1, descriptor2, options4);
return normalizeDistance(dist, options4.order || 2, options4.min || 0, options4.max || 1);
}
function match2(descriptor, descriptors, options3 = { order: 2, multiplier: 25, threshold: 0, min: 0.2, max: 0.8 }) {
function match2(descriptor, descriptors, options4 = { order: 2, multiplier: 25, threshold: 0, min: 0.2, max: 0.8 }) {
if (!Array.isArray(descriptor) || !Array.isArray(descriptors) || descriptor.length < 64 || descriptors.length === 0 || descriptor.length !== descriptors[0].length) {
return { index: -1, distance: Number.POSITIVE_INFINITY, similarity: 0 };
}
let lowestDistance = Number.MAX_SAFE_INTEGER;
let index2 = -1;
for (let i = 0; i < descriptors.length; i++) {
const res = distance(descriptor, descriptors[i], options3);
const res = distance(descriptor, descriptors[i], options4);
if (res < lowestDistance) {
lowestDistance = res;
index2 = i;
}
if (lowestDistance < (options3.threshold || 0))
if (lowestDistance < (options4.threshold || 0))
break;
}
const normalizedSimilarity = normalizeDistance(lowestDistance, options3.order || 2, options3.min || 0, options3.max || 1);
const normalizedSimilarity = normalizeDistance(lowestDistance, options4.order || 2, options4.min || 0, options4.max || 1);
return { index: index2, distance: lowestDistance, similarity: normalizedSimilarity };
}
@ -13414,15 +13451,15 @@ var Human = class {
this.events = typeof EventTarget !== "undefined" ? new EventTarget() : void 0;
this.models = new Models();
this.draw = {
options: options2,
options: options3,
canvas: (input, output) => canvas2(input, output),
face: (output, result, options3) => face(output, result, options3),
body: (output, result, options3) => body(output, result, options3),
hand: (output, result, options3) => hand(output, result, options3),
gesture: (output, result, options3) => gesture(output, result, options3),
object: (output, result, options3) => object(output, result, options3),
person: (output, result, options3) => person(output, result, options3),
all: (output, result, options3) => all(output, result, options3)
face: (output, result, options4) => face(output, result, options4),
body: (output, result, options4) => body(output, result, options4),
hand: (output, result, options4) => hand(output, result, options4),
gesture: (output, result, options4) => gesture(output, result, options4),
object: (output, result, options4) => object(output, result, options4),
person: (output, result, options4) => person(output, result, options4),
all: (output, result, options4) => all(output, result, options4)
};
this.result = { face: [], body: [], hand: [], gesture: [], object: [], performance: {}, timestamp: 0, persons: [], error: null };
this.process = { tensor: null, canvas: null };

File diff suppressed because one or more lines are too long

239
dist/human.esm.js vendored
View File

@ -2060,10 +2060,10 @@ var require_seedrandom = __commonJS({
"src/node_modules/seedrandom/seedrandom.js"(exports, module) {
(function(global2, pool3, math) {
var width = 256, chunks = 6, digits = 52, rngname = "random", startdenom = math.pow(width, chunks), significance = math.pow(2, digits), overflow = significance * 2, mask2 = width - 1, nodecrypto;
function seedrandom5(seed, options3, callback) {
function seedrandom5(seed, options4, callback) {
var key = [];
options3 = options3 == true ? { entropy: true } : options3 || {};
var shortseed = mixkey(flatten4(options3.entropy ? [seed, tostring(pool3)] : seed == null ? autoseed() : seed, 3), key);
options4 = options4 == true ? { entropy: true } : options4 || {};
var shortseed = mixkey(flatten4(options4.entropy ? [seed, tostring(pool3)] : seed == null ? autoseed() : seed, 3), key);
var arc4 = new ARC4(key);
var prng = function() {
var n = arc4.g(chunks), d = startdenom, x = 0;
@ -2087,7 +2087,7 @@ var require_seedrandom = __commonJS({
};
prng.double = prng;
mixkey(tostring(arc4.S), pool3);
return (options3.pass || callback || function(prng2, seed2, is_math_call, state) {
return (options4.pass || callback || function(prng2, seed2, is_math_call, state) {
if (state) {
if (state.S) {
copy2(state, arc4);
@ -2101,7 +2101,7 @@ var require_seedrandom = __commonJS({
return seed2;
} else
return prng2;
})(prng, shortseed, "global" in options3 ? options3.global : this == math, options3.state);
})(prng, shortseed, "global" in options4 ? options4.global : this == math, options4.state);
}
function ARC4(key) {
var t, keylen = key.length, me = this, i = 0, j = me.i = me.j = 0, s = me.S = [];
@ -5641,7 +5641,7 @@ var KernelBackend = class {
readSync(dataId) {
return notYetImplemented("readSync");
}
readToGPU(dataId, options3) {
readToGPU(dataId, options4) {
return notYetImplemented("readToGPU");
}
numDataIds() {
@ -7193,9 +7193,9 @@ var Tensor = class {
}
return data;
}
dataToGPU(options3) {
dataToGPU(options4) {
this.throwIfDisposed();
return trackerFn().readToGPU(this.dataId, options3);
return trackerFn().readToGPU(this.dataId, options4);
}
dataSync() {
this.throwIfDisposed();
@ -8084,9 +8084,9 @@ var _Engine = class {
const info = this.state.tensorInfo.get(dataId);
return info.backend.read(dataId);
}
readToGPU(dataId, options3) {
readToGPU(dataId, options4) {
const info = this.state.tensorInfo.get(dataId);
return info.backend.readToGPU(dataId, options3);
return info.backend.readToGPU(dataId, options4);
}
async time(query) {
const start = now2();
@ -23354,24 +23354,24 @@ async function modelFromJSON(modelAndWeightsConfig, customObjects) {
}
return model22;
}
async function loadLayersModelInternal(pathOrIOHandler, options3) {
if (options3 == null) {
options3 = {};
async function loadLayersModelInternal(pathOrIOHandler, options4) {
if (options4 == null) {
options4 = {};
}
if (typeof pathOrIOHandler === "string") {
const handlers = io_exports.getLoadHandlers(pathOrIOHandler, options3);
const handlers = io_exports.getLoadHandlers(pathOrIOHandler, options4);
if (handlers.length === 0) {
handlers.push(io_exports.browserHTTPRequest(pathOrIOHandler, options3));
handlers.push(io_exports.browserHTTPRequest(pathOrIOHandler, options4));
} else if (handlers.length > 1) {
throw new ValueError(`Found more than one (${handlers.length}) load handlers for URL '${pathOrIOHandler}'`);
}
pathOrIOHandler = handlers[0];
}
return loadLayersModelFromIOHandler(pathOrIOHandler, void 0, options3);
return loadLayersModelFromIOHandler(pathOrIOHandler, void 0, options4);
}
async function loadLayersModelFromIOHandler(handler, customObjects, options3) {
if (options3 == null) {
options3 = {};
async function loadLayersModelFromIOHandler(handler, customObjects, options4) {
if (options4 == null) {
options4 = {};
}
if (handler.load == null) {
throw new ValueError("Cannot proceed with model loading because the IOHandler provided does not have the `load` method implemented.");
@ -23381,7 +23381,7 @@ async function loadLayersModelFromIOHandler(handler, customObjects, options3) {
if (modelTopology["model_config"] != null) {
modelTopology = modelTopology["model_config"];
}
const strict = options3.strict == null ? true : options3.strict;
const strict = options4.strict == null ? true : options4.strict;
const fastWeightInit = artifacts.weightData != null && artifacts.weightSpecs != null && strict;
const model22 = deserialize(convertPythonicToTs(modelTopology), customObjects, fastWeightInit);
const trainingConfig = artifacts.trainingConfig;
@ -23681,11 +23681,11 @@ function model(args) {
function sequential(config3) {
return new Sequential(config3);
}
function loadLayersModel(pathOrIOHandler, options3) {
if (options3 == null) {
options3 = {};
function loadLayersModel(pathOrIOHandler, options4) {
if (options4 == null) {
options4 = {};
}
return loadLayersModelInternal(pathOrIOHandler, options3);
return loadLayersModelInternal(pathOrIOHandler, options4);
}
function input(config3) {
return Input(config3);
@ -37916,14 +37916,14 @@ var GraphModel = class {
this.resourceManager.dispose();
}
};
async function loadGraphModel(modelUrl, options3 = {}) {
async function loadGraphModel(modelUrl, options4 = {}) {
if (modelUrl == null) {
throw new Error("modelUrl in loadGraphModel() cannot be null. Please provide a url or an IOHandler that loads the model");
}
if (options3 == null) {
options3 = {};
if (options4 == null) {
options4 = {};
}
if (options3.fromTFHub) {
if (options4.fromTFHub) {
if (modelUrl.load == null) {
if (!modelUrl.endsWith("/")) {
modelUrl = modelUrl + "/";
@ -37931,7 +37931,7 @@ async function loadGraphModel(modelUrl, options3 = {}) {
modelUrl = `${modelUrl}${DEFAULT_MODEL_NAME}${TFHUB_SEARCH_PARAM}`;
}
}
const model22 = new GraphModel(modelUrl, options3);
const model22 = new GraphModel(modelUrl, options4);
await model22.load();
return model22;
}
@ -39545,13 +39545,13 @@ var Utf8IteratorImpl = class extends OneToManyIterator {
}
};
var FileChunkIterator = class extends ByteChunkIterator {
constructor(file, options3 = {}) {
constructor(file, options4 = {}) {
super();
this.file = file;
this.options = options3;
this.options = options4;
util_exports.assert(file instanceof Uint8Array || (env().get("IS_BROWSER") ? file instanceof File || file instanceof Blob : false), () => "FileChunkIterator only supports File, Blob and Uint8Array right now.");
this.offset = options3.offset || 0;
this.chunkSize = options3.chunkSize || 1024 * 1024;
this.offset = options4.offset || 0;
this.chunkSize = options4.chunkSize || 1024 * 1024;
}
summary() {
return `FileChunks ${this.file}`;
@ -39590,7 +39590,7 @@ var FileChunkIterator = class extends ByteChunkIterator {
return { value: await chunk, done: false };
}
};
async function urlChunkIterator(url, options3 = {}, fetchFunc) {
async function urlChunkIterator(url, options4 = {}, fetchFunc) {
let urlString;
let requestInit;
if (typeof url === "string") {
@ -39602,7 +39602,7 @@ async function urlChunkIterator(url, options3 = {}, fetchFunc) {
const response = await (fetchFunc || util_exports.fetch)(urlString, requestInit);
if (response.ok) {
const uint8Array = new Uint8Array(await response.arrayBuffer());
return new FileChunkIterator(uint8Array, options3);
return new FileChunkIterator(uint8Array, options4);
} else {
throw new Error(response.statusText);
}
@ -39625,10 +39625,10 @@ function isLocalPath(source) {
return typeof source === "string" && source.substr(0, 7) === "file://";
}
var FileDataSource = class extends DataSource {
constructor(input2, options3 = {}) {
constructor(input2, options4 = {}) {
super();
this.input = input2;
this.options = options3;
this.options = options4;
}
async iterator() {
if (isLocalPath(this.input) && env().get("IS_NODE")) {
@ -50141,7 +50141,7 @@ var _MathBackendWebGL = class extends KernelBackend {
}
return dTypeVals;
}
readToGPU(dataId, options3 = {}) {
readToGPU(dataId, options4 = {}) {
const texData = this.texData.get(dataId);
const { values, shape, slice: slice6, dtype, isPacked, texture } = texData;
if (dtype === "complex64") {
@ -50155,7 +50155,7 @@ var _MathBackendWebGL = class extends KernelBackend {
program = new UnaryOpProgram(shape, CLONE);
}
const res = this.runWebGLProgram(program, [{ dataId, shape, dtype }], dtype);
const gpuResouorce = this.readToGPU(res, options3);
const gpuResouorce = this.readToGPU(res, options4);
this.disposeIntermediateTensorInfo(res);
return gpuResouorce;
}
@ -50166,7 +50166,7 @@ var _MathBackendWebGL = class extends KernelBackend {
throw new Error("There is no data on GPU or CPU.");
}
}
const tmpTarget = this.decode(dataId, options3.customTexShape);
const tmpTarget = this.decode(dataId, options4.customTexShape);
const tensorRef = engine().makeTensorFromDataId(tmpTarget.dataId, tmpTarget.shape, tmpTarget.dtype);
const tmpData = this.texData.get(tmpTarget.dataId);
return { tensorRef, ...tmpData.texture };
@ -72185,6 +72185,43 @@ var env2 = new Env();
// package.json
var version9 = "2.5.8";
// src/tfjs/load.ts
var options = {
appName: "human",
autoSave: true,
verbose: true
};
async function httpHandler(url, init3) {
if (options.fetchFunc)
return options.fetchFunc(url, init3);
else
log("error: fetch function is not defined");
return null;
}
var tfLoadOptions = {
onProgress: (...args) => {
if (options.onProgress)
options.onProgress(...args);
else if (options.verbose)
log("load model progress:", ...args);
},
fetchFunc: (url, init3) => {
if (options.verbose)
log("load model fetch:", url, init3);
if (url.toString().toLowerCase().startsWith("http"))
return httpHandler(url, init3);
return null;
}
};
async function loadModel2(modelUrl, loadOptions) {
if (loadOptions)
options = mergeDeep(loadOptions);
if (!options.fetchFunc && typeof globalThis.fetch !== "undefined")
options.fetchFunc = globalThis.fetch;
const model19 = await loadGraphModel(modelUrl, tfLoadOptions);
return model19;
}
// src/gear/gear.ts
var model2;
var last2 = [];
@ -72197,7 +72234,7 @@ async function load(config3) {
if (env2.initial)
model2 = null;
if (!model2) {
model2 = await loadGraphModel(join(config3.modelBasePath, config3.face["gear"].modelPath));
model2 = await loadModel2(join(config3.modelBasePath, config3.face["gear"].modelPath));
if (!model2 || !model2["modelUrl"])
log("load model failed:", config3.face["gear"].modelPath);
else if (config3.debug)
@ -72278,7 +72315,7 @@ async function load2(config3) {
if (env2.initial)
model3 = null;
if (!model3) {
model3 = await loadGraphModel(join(config3.modelBasePath, config3.face["ssrnet"].modelPathAge));
model3 = await loadModel2(join(config3.modelBasePath, config3.face["ssrnet"].modelPathAge));
if (!model3 || !model3["modelUrl"])
log("load model failed:", config3.face["ssrnet"].modelPathAge);
else if (config3.debug)
@ -72332,7 +72369,7 @@ async function load3(config3) {
if (env2.initial)
model4 = null;
if (!model4) {
model4 = await loadGraphModel(join(config3.modelBasePath, config3.face["ssrnet"].modelPathGender));
model4 = await loadModel2(join(config3.modelBasePath, config3.face["ssrnet"].modelPathGender));
if (!model4 || !model4["modelUrl"])
log("load model failed:", config3.face["ssrnet"].modelPathGender);
else if (config3.debug)
@ -72391,7 +72428,7 @@ async function load4(config3) {
if (env2.initial)
model5 = null;
if (!model5) {
model5 = await loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.antispoof) == null ? void 0 : _a.modelPath) || ""));
model5 = await loadModel2(join(config3.modelBasePath, ((_a = config3.face.antispoof) == null ? void 0 : _a.modelPath) || ""));
if (!model5 || !model5["modelUrl"])
log("load model failed:", (_b = config3.face.antispoof) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -75883,7 +75920,7 @@ async function load5(config3) {
if (env2.initial)
model6 = null;
if (!model6) {
model6 = await loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.detector) == null ? void 0 : _a.modelPath) || ""));
model6 = await loadModel2(join(config3.modelBasePath, ((_a = config3.face.detector) == null ? void 0 : _a.modelPath) || ""));
if (!model6 || !model6["modelUrl"])
log("load model failed:", (_b = config3.face.detector) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -76117,7 +76154,7 @@ async function loadDetect(config3) {
if (env3.initial)
models.detector = null;
if (!models.detector && config3.body["detector"] && config3.body["detector"]["modelPath"] || "") {
models.detector = await loadGraphModel(join(config3.modelBasePath, config3.body["detector"]["modelPath"] || ""));
models.detector = await loadModel2(join(config3.modelBasePath, config3.body["detector"]["modelPath"] || ""));
const inputs = Object.values(models.detector.modelSignature["inputs"]);
inputSize3.detector[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize3.detector[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
@ -76134,7 +76171,7 @@ async function loadPose(config3) {
if (env3.initial)
models.landmarks = null;
if (!models.landmarks) {
models.landmarks = await loadGraphModel(join(config3.modelBasePath, config3.body.modelPath || ""));
models.landmarks = await loadModel2(join(config3.modelBasePath, config3.body.modelPath || ""));
const inputs = Object.values(models.landmarks.modelSignature["inputs"]);
inputSize3.landmarks[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize3.landmarks[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
@ -76366,7 +76403,7 @@ async function load6(config3) {
if (env2.initial)
model7 = null;
if (!model7) {
model7 = await loadGraphModel(join(config3.modelBasePath, config3.object.modelPath || ""));
model7 = await loadModel2(join(config3.modelBasePath, config3.object.modelPath || ""));
const inputs = Object.values(model7.modelSignature["inputs"]);
inputSize4 = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!model7 || !model7["modelUrl"])
@ -76480,7 +76517,7 @@ async function load7(config3) {
if (env2.initial)
model8 = null;
if (!model8) {
model8 = await loadGraphModel(join(config3.modelBasePath, config3.body.modelPath || ""));
model8 = await loadModel2(join(config3.modelBasePath, config3.body.modelPath || ""));
if (!model8 || !model8["modelUrl"])
log("load model failed:", config3.body.modelPath);
else if (config3.debug)
@ -76597,7 +76634,7 @@ async function load8(config3) {
if (env2.initial)
model9 = null;
if (!model9) {
model9 = await loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.emotion) == null ? void 0 : _a.modelPath) || ""));
model9 = await loadModel2(join(config3.modelBasePath, ((_a = config3.face.emotion) == null ? void 0 : _a.modelPath) || ""));
if (!model9 || !model9["modelUrl"])
log("load model failed:", (_b = config3.face.emotion) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -76655,7 +76692,7 @@ async function load9(config3) {
if (env2.initial)
model10 = null;
if (!model10) {
model10 = await loadGraphModel(modelUrl);
model10 = await loadModel2(modelUrl);
if (!model10)
log("load model failed:", config3.face["mobilefacenet"].modelPath);
else if (config3.debug)
@ -76712,7 +76749,7 @@ async function load10(config3) {
if (env2.initial)
model11 = null;
if (!model11) {
model11 = await loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.iris) == null ? void 0 : _a.modelPath) || ""));
model11 = await loadModel2(join(config3.modelBasePath, ((_a = config3.face.iris) == null ? void 0 : _a.modelPath) || ""));
if (!model11 || !model11["modelUrl"])
log("load model failed:", (_b = config3.face.iris) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -76917,7 +76954,7 @@ async function load11(config3) {
if (env2.initial)
model12 = null;
if (!model12) {
model12 = await loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.mesh) == null ? void 0 : _a.modelPath) || ""));
model12 = await loadModel2(join(config3.modelBasePath, ((_a = config3.face.mesh) == null ? void 0 : _a.modelPath) || ""));
if (!model12 || !model12["modelUrl"])
log("load model failed:", (_b = config3.face.mesh) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -76942,7 +76979,7 @@ async function load12(config3) {
if (env2.initial)
model13 = null;
if (!model13) {
model13 = await loadGraphModel(modelUrl);
model13 = await loadModel2(modelUrl);
if (!model13)
log("load model failed:", ((_b = config3.face.description) == null ? void 0 : _b.modelPath) || "");
else if (config3.debug)
@ -80451,7 +80488,7 @@ var fingergesture_default = [ThumbsUp, Victory, Point, MiddleFinger, OpenPalm];
// src/hand/fingerpose.ts
var minConfidence = 0.7;
var options = {
var options2 = {
HALF_CURL_START_LIMIT: 60,
NO_CURL_START_LIMIT: 130,
DISTANCE_VOTE_POWER: 1.1,
@ -80509,9 +80546,9 @@ function estimateFingerCurl(startPoint, midPoint, endPoint) {
let angleOfCurve = Math.acos(cos_in);
angleOfCurve = 57.2958 * angleOfCurve % 180;
let fingerCurl;
if (angleOfCurve > options.NO_CURL_START_LIMIT)
if (angleOfCurve > options2.NO_CURL_START_LIMIT)
fingerCurl = FingerCurl.none;
else if (angleOfCurve > options.HALF_CURL_START_LIMIT)
else if (angleOfCurve > options2.HALF_CURL_START_LIMIT)
fingerCurl = FingerCurl.half;
else
fingerCurl = FingerCurl.full;
@ -80588,11 +80625,11 @@ function calculateFingerDirection(startPoint, midPoint, endPoint, fingerSlopes)
let voteHorizontal = 0;
const start_end_x_y_dist_ratio = max_dist_y / (max_dist_x + 1e-5);
if (start_end_x_y_dist_ratio > 1.5)
voteVertical += options.DISTANCE_VOTE_POWER;
voteVertical += options2.DISTANCE_VOTE_POWER;
else if (start_end_x_y_dist_ratio > 0.66)
voteDiagonal += options.DISTANCE_VOTE_POWER;
voteDiagonal += options2.DISTANCE_VOTE_POWER;
else
voteHorizontal += options.DISTANCE_VOTE_POWER;
voteHorizontal += options2.DISTANCE_VOTE_POWER;
const start_mid_dist = Math.sqrt(start_mid_x_dist * start_mid_x_dist + start_mid_y_dist * start_mid_y_dist);
const start_end_dist = Math.sqrt(start_end_x_dist * start_end_x_dist + start_end_y_dist * start_end_y_dist);
const mid_end_dist = Math.sqrt(mid_end_x_dist * mid_end_x_dist + mid_end_y_dist * mid_end_y_dist);
@ -80611,12 +80648,12 @@ function calculateFingerDirection(startPoint, midPoint, endPoint, fingerSlopes)
const calcStartPoint = [calc_start_point_x, calc_start_point_y];
const calcEndPoint = [calc_end_point_x, calc_end_point_y];
const totalAngle = getSlopes(calcStartPoint, calcEndPoint);
const votes = angleOrientationAt(totalAngle, options.TOTAL_ANGLE_VOTE_POWER);
const votes = angleOrientationAt(totalAngle, options2.TOTAL_ANGLE_VOTE_POWER);
voteVertical += votes[0];
voteDiagonal += votes[1];
voteHorizontal += votes[2];
for (const fingerSlope of fingerSlopes) {
const fingerVotes = angleOrientationAt(fingerSlope, options.SINGLE_ANGLE_VOTE_POWER);
const fingerVotes = angleOrientationAt(fingerSlope, options2.SINGLE_ANGLE_VOTE_POWER);
voteVertical += fingerVotes[0];
voteDiagonal += fingerVotes[1];
voteHorizontal += fingerVotes[2];
@ -80765,23 +80802,23 @@ async function predict12(input2, config3) {
return hands;
}
async function load13(config3) {
var _a, _b, _c, _d, _e, _f;
var _a, _b, _c, _d;
if (env2.initial) {
handDetectorModel = null;
handPoseModel = null;
}
if (!handDetectorModel || !handPoseModel) {
[handDetectorModel, handPoseModel] = await Promise.all([
config3.hand.enabled ? loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""), { fromTFHub: (((_b = config3.hand.detector) == null ? void 0 : _b.modelPath) || "").includes("tfhub.dev") }) : null,
config3.hand.landmarks ? loadGraphModel(join(config3.modelBasePath, ((_c = config3.hand.skeleton) == null ? void 0 : _c.modelPath) || ""), { fromTFHub: (((_d = config3.hand.skeleton) == null ? void 0 : _d.modelPath) || "").includes("tfhub.dev") }) : null
config3.hand.enabled ? loadModel2(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || "")) : null,
config3.hand.landmarks ? loadModel2(join(config3.modelBasePath, ((_b = config3.hand.skeleton) == null ? void 0 : _b.modelPath) || "")) : null
]);
if (config3.hand.enabled) {
if (!handDetectorModel || !handDetectorModel["modelUrl"])
log("load model failed:", ((_e = config3.hand.detector) == null ? void 0 : _e.modelPath) || "");
log("load model failed:", ((_c = config3.hand.detector) == null ? void 0 : _c.modelPath) || "");
else if (config3.debug)
log("load model:", handDetectorModel["modelUrl"]);
if (!handPoseModel || !handPoseModel["modelUrl"])
log("load model failed:", ((_f = config3.hand.skeleton) == null ? void 0 : _f.modelPath) || "");
log("load model failed:", ((_d = config3.hand.skeleton) == null ? void 0 : _d.modelPath) || "");
else if (config3.debug)
log("load model:", handPoseModel["modelUrl"]);
}
@ -80827,7 +80864,7 @@ async function loadDetect2(config3) {
models2[0] = null;
if (!models2[0]) {
fakeOps(["tensorlistreserve", "enter", "tensorlistfromtensor", "merge", "loopcond", "switch", "exit", "tensorliststack", "nextiteration", "tensorlistsetitem", "tensorlistgetitem", "reciprocal", "shape", "split", "where"], config3);
models2[0] = await loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""));
models2[0] = await loadModel2(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""));
const inputs = Object.values(models2[0].modelSignature["inputs"]);
inputSize7[0][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize7[0][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
@ -80844,7 +80881,7 @@ async function loadSkeleton(config3) {
if (env2.initial)
models2[1] = null;
if (!models2[1]) {
models2[1] = await loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.skeleton) == null ? void 0 : _a.modelPath) || ""));
models2[1] = await loadModel2(join(config3.modelBasePath, ((_a = config3.hand.skeleton) == null ? void 0 : _a.modelPath) || ""));
const inputs = Object.values(models2[1].modelSignature["inputs"]);
inputSize7[1][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize7[1][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
@ -80992,7 +81029,7 @@ async function load14(config3) {
if (env2.initial)
model14 = null;
if (!model14) {
model14 = await loadGraphModel(join(config3.modelBasePath, ((_a = config3.face.liveness) == null ? void 0 : _a.modelPath) || ""));
model14 = await loadModel(join(config3.modelBasePath, ((_a = config3.face.liveness) == null ? void 0 : _a.modelPath) || ""));
if (!model14 || !model14["modelUrl"])
log("load model failed:", (_b = config3.face.liveness) == null ? void 0 : _b.modelPath);
else if (config3.debug)
@ -81193,7 +81230,7 @@ async function load15(config3) {
model15 = null;
if (!model15) {
fakeOps(["size"], config3);
model15 = await loadGraphModel(join(config3.modelBasePath, config3.body.modelPath || ""));
model15 = await loadModel2(join(config3.modelBasePath, config3.body.modelPath || ""));
if (!model15 || !model15["modelUrl"])
log("load model failed:", config3.body.modelPath);
else if (config3.debug)
@ -81321,7 +81358,7 @@ var inputSize9 = 0;
var scaleBox = 2.5;
async function load16(config3) {
if (!model16 || env2.initial) {
model16 = await loadGraphModel(join(config3.modelBasePath, config3.object.modelPath || ""));
model16 = await loadModel2(join(config3.modelBasePath, config3.object.modelPath || ""));
const inputs = Object.values(model16.modelSignature["inputs"]);
inputSize9 = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!model16 || !model16["modelUrl"])
@ -81751,7 +81788,7 @@ async function predict17(input2, config3) {
}
async function load17(config3) {
if (!model17 || env2.initial) {
model17 = await loadGraphModel(join(config3.modelBasePath, config3.body.modelPath || ""));
model17 = await loadModel2(join(config3.modelBasePath, config3.body.modelPath || ""));
if (!model17 || !model17["modelUrl"])
log("load model failed:", config3.body.modelPath);
else if (config3.debug)
@ -81766,7 +81803,7 @@ var model18;
var busy = false;
async function load18(config3) {
if (!model18 || env2.initial) {
model18 = await loadGraphModel(join(config3.modelBasePath, config3.segmentation.modelPath || ""));
model18 = await loadModel2(join(config3.modelBasePath, config3.segmentation.modelPath || ""));
if (!model18 || !model18["modelUrl"])
log("load model failed:", config3.segmentation.modelPath);
else if (config3.debug)
@ -82196,7 +82233,7 @@ function fakeOps(kernelNames, config3) {
}
// src/util/draw.ts
var options2 = {
var options3 = {
color: "rgba(173, 216, 230, 0.6)",
labelColor: "rgba(173, 216, 230, 1)",
shadowColor: "black",
@ -82321,7 +82358,7 @@ function arrow(ctx, from, to, radius = 5) {
ctx.fill();
}
async function gesture(inCanvas2, result, drawOptions) {
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
if (localOptions.drawGestures) {
@ -82351,7 +82388,7 @@ async function gesture(inCanvas2, result, drawOptions) {
}
async function face(inCanvas2, result, drawOptions) {
var _a, _b, _c, _d, _e;
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
const ctx = getCanvasContext(inCanvas2);
@ -82484,7 +82521,7 @@ async function face(inCanvas2, result, drawOptions) {
}
async function body(inCanvas2, result, drawOptions) {
var _a;
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
const ctx = getCanvasContext(inCanvas2);
@ -82533,7 +82570,7 @@ async function body(inCanvas2, result, drawOptions) {
}
}
async function hand(inCanvas2, result, drawOptions) {
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
const ctx = getCanvasContext(inCanvas2);
@ -82603,7 +82640,7 @@ async function hand(inCanvas2, result, drawOptions) {
}
}
async function object(inCanvas2, result, drawOptions) {
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
const ctx = getCanvasContext(inCanvas2);
@ -82630,7 +82667,7 @@ async function object(inCanvas2, result, drawOptions) {
}
}
async function person(inCanvas2, result, drawOptions) {
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
if (!result || !inCanvas2)
return;
const ctx = getCanvasContext(inCanvas2);
@ -82668,7 +82705,7 @@ async function all5(inCanvas2, result, drawOptions) {
if (!result || !result.performance || !result || !inCanvas2)
return null;
const timeStamp = now();
const localOptions = mergeDeep(options2, drawOptions);
const localOptions = mergeDeep(options3, drawOptions);
const promise = Promise.all([
face(inCanvas2, result.face, localOptions),
body(inCanvas2, result.body, localOptions),
@ -83249,13 +83286,13 @@ function calc2(newResult, config3) {
}
// src/face/match.ts
function distance(descriptor1, descriptor2, options3 = { order: 2, multiplier: 25 }) {
function distance(descriptor1, descriptor2, options4 = { order: 2, multiplier: 25 }) {
let sum7 = 0;
for (let i = 0; i < descriptor1.length; i++) {
const diff = !options3.order || options3.order === 2 ? descriptor1[i] - descriptor2[i] : Math.abs(descriptor1[i] - descriptor2[i]);
sum7 += !options3.order || options3.order === 2 ? diff * diff : diff ** options3.order;
const diff = !options4.order || options4.order === 2 ? descriptor1[i] - descriptor2[i] : Math.abs(descriptor1[i] - descriptor2[i]);
sum7 += !options4.order || options4.order === 2 ? diff * diff : diff ** options4.order;
}
return (options3.multiplier || 20) * sum7;
return (options4.multiplier || 20) * sum7;
}
var normalizeDistance = (dist, order, min7, max7) => {
if (dist === 0)
@ -83265,26 +83302,26 @@ var normalizeDistance = (dist, order, min7, max7) => {
const clamp3 = Math.max(Math.min(norm2, 1), 0);
return clamp3;
};
function similarity(descriptor1, descriptor2, options3 = { order: 2, multiplier: 25, min: 0.2, max: 0.8 }) {
const dist = distance(descriptor1, descriptor2, options3);
return normalizeDistance(dist, options3.order || 2, options3.min || 0, options3.max || 1);
function similarity(descriptor1, descriptor2, options4 = { order: 2, multiplier: 25, min: 0.2, max: 0.8 }) {
const dist = distance(descriptor1, descriptor2, options4);
return normalizeDistance(dist, options4.order || 2, options4.min || 0, options4.max || 1);
}
function match2(descriptor, descriptors, options3 = { order: 2, multiplier: 25, threshold: 0, min: 0.2, max: 0.8 }) {
function match2(descriptor, descriptors, options4 = { order: 2, multiplier: 25, threshold: 0, min: 0.2, max: 0.8 }) {
if (!Array.isArray(descriptor) || !Array.isArray(descriptors) || descriptor.length < 64 || descriptors.length === 0 || descriptor.length !== descriptors[0].length) {
return { index: -1, distance: Number.POSITIVE_INFINITY, similarity: 0 };
}
let lowestDistance = Number.MAX_SAFE_INTEGER;
let index2 = -1;
for (let i = 0; i < descriptors.length; i++) {
const res = distance(descriptor, descriptors[i], options3);
const res = distance(descriptor, descriptors[i], options4);
if (res < lowestDistance) {
lowestDistance = res;
index2 = i;
}
if (lowestDistance < (options3.threshold || 0))
if (lowestDistance < (options4.threshold || 0))
break;
}
const normalizedSimilarity = normalizeDistance(lowestDistance, options3.order || 2, options3.min || 0, options3.max || 1);
const normalizedSimilarity = normalizeDistance(lowestDistance, options4.order || 2, options4.min || 0, options4.max || 1);
return { index: index2, distance: lowestDistance, similarity: normalizedSimilarity };
}
@ -84249,15 +84286,15 @@ var Human = class {
this.events = typeof EventTarget !== "undefined" ? new EventTarget() : void 0;
this.models = new Models();
this.draw = {
options: options2,
options: options3,
canvas: (input2, output) => canvas2(input2, output),
face: (output, result, options3) => face(output, result, options3),
body: (output, result, options3) => body(output, result, options3),
hand: (output, result, options3) => hand(output, result, options3),
gesture: (output, result, options3) => gesture(output, result, options3),
object: (output, result, options3) => object(output, result, options3),
person: (output, result, options3) => person(output, result, options3),
all: (output, result, options3) => all5(output, result, options3)
face: (output, result, options4) => face(output, result, options4),
body: (output, result, options4) => body(output, result, options4),
hand: (output, result, options4) => hand(output, result, options4),
gesture: (output, result, options4) => gesture(output, result, options4),
object: (output, result, options4) => object(output, result, options4),
person: (output, result, options4) => person(output, result, options4),
all: (output, result, options4) => all5(output, result, options4)
};
this.result = { face: [], body: [], hand: [], gesture: [], object: [], performance: {}, timestamp: 0, persons: [], error: null };
this.process = { tensor: null, canvas: null };

File diff suppressed because one or more lines are too long

1618
dist/human.js vendored

File diff suppressed because one or more lines are too long

535
dist/human.node-gpu.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

535
dist/human.node.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
*/
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import { constants } from '../tfjs/constants';
import { log, join, now } from '../util/util';
import type { BodyKeypoint, BodyResult, BodyLandmark, Box, Point, BodyAnnotation } from '../result';
@ -32,7 +33,7 @@ const sigmoid = (x) => (1 - (1 / (1 + Math.exp(x))));
export async function loadDetect(config: Config): Promise<GraphModel> {
if (env.initial) models.detector = null;
if (!models.detector && config.body['detector'] && config.body['detector']['modelPath'] || '') {
models.detector = await tf.loadGraphModel(join(config.modelBasePath, config.body['detector']['modelPath'] || '')) as unknown as GraphModel;
models.detector = await loadModel(join(config.modelBasePath, config.body['detector']['modelPath'] || '')) as unknown as GraphModel;
const inputs = Object.values(models.detector.modelSignature['inputs']);
inputSize.detector[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize.detector[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
@ -46,7 +47,7 @@ export async function loadDetect(config: Config): Promise<GraphModel> {
export async function loadPose(config: Config): Promise<GraphModel> {
if (env.initial) models.landmarks = null;
if (!models.landmarks) {
models.landmarks = await tf.loadGraphModel(join(config.modelBasePath, config.body.modelPath || '')) as unknown as GraphModel;
models.landmarks = await loadModel(join(config.modelBasePath, config.body.modelPath || '')) as unknown as GraphModel;
const inputs = Object.values(models.landmarks.modelSignature['inputs']);
inputSize.landmarks[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize.landmarks[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;

View File

@ -6,6 +6,7 @@
import { log, join, now } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import * as coords from './efficientposecoords';
import { constants } from '../tfjs/constants';
import type { BodyResult, Point, BodyLandmark, BodyAnnotation } from '../result';
@ -26,7 +27,7 @@ let skipped = Number.MAX_SAFE_INTEGER;
export async function load(config: Config): Promise<GraphModel> {
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.body.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.body.modelPath || '')) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.body.modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -9,6 +9,7 @@ import * as box from '../util/box';
import * as tf from '../../dist/tfjs.esm.js';
import * as coords from './movenetcoords';
import * as fix from './movenetfix';
import { loadModel } from '../tfjs/load';
import type { BodyKeypoint, BodyResult, BodyLandmark, BodyAnnotation, Box, Point } from '../result';
import type { GraphModel, Tensor } from '../tfjs/types';
import type { Config } from '../config';
@ -34,7 +35,7 @@ export async function load(config: Config): Promise<GraphModel> {
if (env.initial) model = null;
if (!model) {
fakeOps(['size'], config);
model = await tf.loadGraphModel(join(config.modelBasePath, config.body.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.body.modelPath || '')) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.body.modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -6,6 +6,7 @@
import { log, join } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import type { BodyResult, BodyLandmark, Box } from '../result';
import type { Tensor, GraphModel } from '../tfjs/types';
import type { Config } from '../config';
@ -179,7 +180,7 @@ export async function predict(input: Tensor, config: Config): Promise<BodyResult
export async function load(config: Config): Promise<GraphModel> {
if (!model || env.initial) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.body.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.body.modelPath || '')) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.body.modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -6,6 +6,7 @@ import { log, join, now } from '../util/util';
import type { Config } from '../config';
import type { GraphModel, Tensor } from '../tfjs/types';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import { env } from '../util/env';
let model: GraphModel | null;
@ -17,7 +18,7 @@ let lastTime = 0;
export async function load(config: Config): Promise<GraphModel> {
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.antispoof?.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.face.antispoof?.modelPath || '')) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.face.antispoof?.modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -6,6 +6,7 @@
import { log, join } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import * as util from './facemeshutil';
import { loadModel } from '../tfjs/load';
import { constants } from '../tfjs/constants';
import type { Config } from '../config';
import type { Tensor, GraphModel } from '../tfjs/types';
@ -26,7 +27,7 @@ export const size = () => inputSize;
export async function load(config: Config): Promise<GraphModel> {
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.detector?.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.face.detector?.modelPath || '')) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.face.detector?.modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -8,6 +8,7 @@
*/
import { log, join, now } from '../util/util';
import { loadModel } from '../tfjs/load';
import * as tf from '../../dist/tfjs.esm.js';
import * as blazeface from './blazeface';
import * as util from './facemeshutil';
@ -111,7 +112,7 @@ export async function predict(input: Tensor, config: Config): Promise<FaceResult
export async function load(config: Config): Promise<GraphModel> {
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.mesh?.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.face.mesh?.modelPath || '')) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.face.mesh?.modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -10,6 +10,7 @@
import { log, join, now } from '../util/util';
import { env } from '../util/env';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import { constants } from '../tfjs/constants';
import type { Tensor, GraphModel } from '../tfjs/types';
import type { Config } from '../config';
@ -33,7 +34,7 @@ export async function load(config: Config): Promise<GraphModel> {
const modelUrl = join(config.modelBasePath, config.face.description?.modelPath || '');
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(modelUrl) as unknown as GraphModel;
model = await loadModel(modelUrl) as unknown as GraphModel;
if (!model) log('load model failed:', config.face.description?.modelPath || '');
else if (config.debug) log('load model:', modelUrl);
} else if (config.debug) log('cached model:', modelUrl);

View File

@ -4,6 +4,7 @@ import * as tf from '../../dist/tfjs.esm.js';
import type { Tensor, GraphModel } from '../tfjs/types';
import { env } from '../util/env';
import { log, join } from '../util/util';
import { loadModel } from '../tfjs/load';
import type { Config } from '../config';
import type { Point } from '../result';
@ -30,7 +31,7 @@ const irisLandmarks = {
export async function load(config: Config): Promise<GraphModel> {
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.iris?.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.face.iris?.modelPath || ''));
if (!model || !model['modelUrl']) log('load model failed:', config.face.iris?.modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -17,7 +17,7 @@ let lastTime = 0;
export async function load(config: Config): Promise<GraphModel> {
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.liveness?.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.face.liveness?.modelPath || '')) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.face.liveness?.modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -8,6 +8,7 @@
import { log, join, now } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import type { Tensor, GraphModel } from '../tfjs/types';
import type { Config } from '../config';
import { env } from '../util/env';
@ -22,7 +23,7 @@ export async function load(config: Config): Promise<GraphModel> {
const modelUrl = join(config.modelBasePath, config.face['mobilefacenet'].modelPath);
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(modelUrl) as unknown as GraphModel;
model = await loadModel(modelUrl) as unknown as GraphModel;
if (!model) log('load model failed:', config.face['mobilefacenet'].modelPath);
else if (config.debug) log('load model:', modelUrl);
} else if (config.debug) log('cached model:', modelUrl);

View File

@ -9,6 +9,7 @@ import { log, join, now } from '../util/util';
import type { Config } from '../config';
import type { GraphModel, Tensor } from '../tfjs/types';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import { env } from '../util/env';
import { constants } from '../tfjs/constants';
@ -22,7 +23,7 @@ let skipped = Number.MAX_SAFE_INTEGER;
export async function load(config: Config): Promise<GraphModel> {
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.emotion?.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.face.emotion?.modelPath || '')) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.face.emotion?.modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -6,6 +6,7 @@
import { log, join, now } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import type { Gender, Race } from '../result';
import type { Config } from '../config';
import type { GraphModel, Tensor } from '../tfjs/types';
@ -24,7 +25,7 @@ let skipped = Number.MAX_SAFE_INTEGER;
export async function load(config: Config) {
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.face['gear'].modelPath)) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.face['gear'].modelPath)) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.face['gear'].modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -6,6 +6,7 @@
import { log, join, now } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import { env } from '../util/env';
import { constants } from '../tfjs/constants';
import type { Config } from '../config';
@ -21,7 +22,7 @@ let skipped = Number.MAX_SAFE_INTEGER;
export async function load(config: Config) {
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.face['ssrnet'].modelPathAge)) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.face['ssrnet'].modelPathAge)) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.face['ssrnet'].modelPathAge);
else if (config.debug) log('load model:', model['modelUrl']);
} else {

View File

@ -6,6 +6,7 @@
import { log, join, now } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import { constants } from '../tfjs/constants';
import type { Gender } from '../result';
import type { Config } from '../config';
@ -25,7 +26,7 @@ const rgb = [0.2989, 0.5870, 0.1140]; // factors for red/green/blue colors when
export async function load(config: Config | any) {
if (env.initial) model = null;
if (!model) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.face['ssrnet'].modelPathGender)) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.face['ssrnet'].modelPathGender)) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.face['ssrnet'].modelPathGender);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

View File

@ -5,10 +5,10 @@
*/
import { log, join } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import * as handdetector from './handposedetector';
import * as handpipeline from './handposepipeline';
import * as fingerPose from './fingerpose';
import { loadModel } from '../tfjs/load';
import type { HandResult, Box, Point } from '../result';
import type { Tensor, GraphModel } from '../tfjs/types';
import type { Config } from '../config';
@ -89,8 +89,8 @@ export async function load(config: Config): Promise<[GraphModel | null, GraphMod
}
if (!handDetectorModel || !handPoseModel) {
[handDetectorModel, handPoseModel] = await Promise.all([
config.hand.enabled ? tf.loadGraphModel(join(config.modelBasePath, config.hand.detector?.modelPath || ''), { fromTFHub: (config.hand.detector?.modelPath || '').includes('tfhub.dev') }) as unknown as GraphModel : null,
config.hand.landmarks ? tf.loadGraphModel(join(config.modelBasePath, config.hand.skeleton?.modelPath || ''), { fromTFHub: (config.hand.skeleton?.modelPath || '').includes('tfhub.dev') }) as unknown as GraphModel : null,
config.hand.enabled ? loadModel(join(config.modelBasePath, config.hand.detector?.modelPath || '')) as unknown as GraphModel : null,
config.hand.landmarks ? loadModel(join(config.modelBasePath, config.hand.skeleton?.modelPath || '')) as unknown as GraphModel : null,
]);
if (config.hand.enabled) {
if (!handDetectorModel || !handDetectorModel['modelUrl']) log('load model failed:', config.hand.detector?.modelPath || '');

View File

@ -9,6 +9,7 @@
import { log, join, now } from '../util/util';
import * as box from '../util/box';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import type { HandResult, HandType, Box, Point } from '../result';
import type { GraphModel, Tensor } from '../tfjs/types';
import type { Config } from '../config';
@ -74,7 +75,7 @@ export async function loadDetect(config: Config): Promise<GraphModel> {
// handtrack model has some kernel ops defined in model but those are never referenced and non-existent in tfjs
// ideally need to prune the model itself
fakeOps(['tensorlistreserve', 'enter', 'tensorlistfromtensor', 'merge', 'loopcond', 'switch', 'exit', 'tensorliststack', 'nextiteration', 'tensorlistsetitem', 'tensorlistgetitem', 'reciprocal', 'shape', 'split', 'where'], config);
models[0] = await tf.loadGraphModel(join(config.modelBasePath, config.hand.detector?.modelPath || '')) as unknown as GraphModel;
models[0] = await loadModel(join(config.modelBasePath, config.hand.detector?.modelPath || '')) as unknown as GraphModel;
const inputs = Object.values(models[0].modelSignature['inputs']);
inputSize[0][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[0][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
@ -87,7 +88,7 @@ export async function loadDetect(config: Config): Promise<GraphModel> {
export async function loadSkeleton(config: Config): Promise<GraphModel> {
if (env.initial) models[1] = null;
if (!models[1]) {
models[1] = await tf.loadGraphModel(join(config.modelBasePath, config.hand.skeleton?.modelPath || '')) as unknown as GraphModel;
models[1] = await loadModel(join(config.modelBasePath, config.hand.skeleton?.modelPath || '')) as unknown as GraphModel;
const inputs = Object.values(models[1].modelSignature['inputs']);
inputSize[1][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[1][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;

View File

@ -6,6 +6,7 @@
import { log, join, now } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import { labels } from './labels';
import type { ObjectResult, ObjectType, Box } from '../result';
import type { GraphModel, Tensor } from '../tfjs/types';
@ -22,7 +23,7 @@ export async function load(config: Config): Promise<GraphModel> {
if (env.initial) model = null;
if (!model) {
// fakeOps(['floormod'], config);
model = await tf.loadGraphModel(join(config.modelBasePath, config.object.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.object.modelPath || '')) as unknown as GraphModel;
const inputs = Object.values(model.modelSignature['inputs']);
inputSize = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!model || !model['modelUrl']) log('load model failed:', config.object.modelPath);

View File

@ -6,6 +6,7 @@
import { log, join, now } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import { constants } from '../tfjs/constants';
import { labels } from './labels';
import type { ObjectResult, ObjectType, Box } from '../result';
@ -23,7 +24,7 @@ const scaleBox = 2.5; // increase box size
export async function load(config: Config): Promise<GraphModel> {
if (!model || env.initial) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.object.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.object.modelPath || '')) as unknown as GraphModel;
const inputs = Object.values(model.modelSignature['inputs']);
inputSize = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!model || !model['modelUrl']) log('load model failed:', config.object.modelPath);

View File

@ -8,6 +8,7 @@
import { log, join } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import { loadModel } from '../tfjs/load';
import * as image from '../image/image';
import { constants } from '../tfjs/constants';
import type { GraphModel, Tensor } from '../tfjs/types';
@ -20,7 +21,7 @@ let busy = false;
export async function load(config: Config): Promise<GraphModel> {
if (!model || env.initial) {
model = await tf.loadGraphModel(join(config.modelBasePath, config.segmentation.modelPath || '')) as unknown as GraphModel;
model = await loadModel(join(config.modelBasePath, config.segmentation.modelPath || '')) as unknown as GraphModel;
if (!model || !model['modelUrl']) log('load model failed:', config.segmentation.modelPath);
else if (config.debug) log('load model:', model['modelUrl']);
} else if (config.debug) log('cached model:', model['modelUrl']);

45
src/tfjs/load.ts Normal file
View File

@ -0,0 +1,45 @@
import { log, mergeDeep } from '../util/util';
import * as tf from '../../dist/tfjs.esm.js';
import type { GraphModel } from './types';
type FetchFunc = (url: RequestInfo, init?: RequestInit) => Promise<Response>;
type ProgressFunc = (...args) => void;
export type LoadOptions = {
appName: string,
autoSave: boolean,
verbose: boolean,
fetchFunc?: FetchFunc,
onProgress?: ProgressFunc,
}
let options: LoadOptions = {
appName: 'human',
autoSave: true,
verbose: true,
};
async function httpHandler(url: RequestInfo, init?: RequestInit): Promise<Response | null> {
if (options.fetchFunc) return options.fetchFunc(url, init);
else log('error: fetch function is not defined');
return null;
}
const tfLoadOptions = {
onProgress: (...args) => {
if (options.onProgress) options.onProgress(...args);
else if (options.verbose) log('load model progress:', ...args);
},
fetchFunc: (url: RequestInfo, init?: RequestInit) => {
if (options.verbose) log('load model fetch:', url, init);
if (url.toString().toLowerCase().startsWith('http')) return httpHandler(url, init);
return null;
},
};
export async function loadModel(modelUrl: string, loadOptions?: LoadOptions): Promise<GraphModel> {
if (loadOptions) options = mergeDeep(loadOptions);
if (!options.fetchFunc && (typeof globalThis.fetch !== 'undefined')) options.fetchFunc = globalThis.fetch;
const model = await tf.loadGraphModel(modelUrl, tfLoadOptions) as unknown as GraphModel;
return model;
}

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,7 @@
SavedModel GraphDef and allows inference execution.</p>
</div><div><p>A <code>tf.GraphModel</code> can only be created by loading from a model converted from
a <a href="https://www.tensorflow.org/guide/saved_model">TensorFlow SavedModel</a> using
the command line converter tool and loaded via <code>tf.loadGraphModel</code>.</p>
the command line converter tool and loaded via <code>loadModel</code>.</p>
</div><dl class="tsd-comment-tags"><dt>doc</dt><dd><p>{heading: &#39;Models&#39;, subheading: &#39;Classes&#39;}</p>
</dd></dl></div></section><section class="tsd-panel tsd-hierarchy"><h3>Hierarchy</h3><ul class="tsd-hierarchy"><li><span class="target">GraphModel</span></li></ul></section><section class="tsd-panel"><h3>Implements</h3><ul class="tsd-hierarchy"><li><span class="tsd-signature-type">InferenceModel</span></li></ul></section><section class="tsd-panel-group tsd-index-group"><h2>Index</h2><section class="tsd-panel tsd-index-panel"><div class="tsd-index-content"><section class="tsd-index-section "><h3>Constructors</h3><ul class="tsd-index-list"><li class="tsd-kind-constructor tsd-parent-kind-class"><a href="GraphModel.html#constructor" class="tsd-kind-icon">constructor</a></li></ul></section><section class="tsd-index-section "><h3>Properties</h3><ul class="tsd-index-list"><li class="tsd-kind-property tsd-parent-kind-class"><a href="GraphModel.html#inputNodes" class="tsd-kind-icon">input<wbr/>Nodes</a></li><li class="tsd-kind-property tsd-parent-kind-class"><a href="GraphModel.html#inputs" class="tsd-kind-icon">inputs</a></li><li class="tsd-kind-property tsd-parent-kind-class"><a href="GraphModel.html#metadata" class="tsd-kind-icon">metadata</a></li><li class="tsd-kind-property tsd-parent-kind-class"><a href="GraphModel.html#modelSignature" class="tsd-kind-icon">model<wbr/>Signature</a></li><li class="tsd-kind-property tsd-parent-kind-class"><a href="GraphModel.html#modelVersion" class="tsd-kind-icon">model<wbr/>Version</a></li><li class="tsd-kind-property tsd-parent-kind-class"><a href="GraphModel.html#outputNodes" class="tsd-kind-icon">output<wbr/>Nodes</a></li><li class="tsd-kind-property tsd-parent-kind-class"><a href="GraphModel.html#outputs" class="tsd-kind-icon">outputs</a></li><li class="tsd-kind-property tsd-parent-kind-class"><a href="GraphModel.html#weights" class="tsd-kind-icon">weights</a></li></ul></section><section class="tsd-index-section "><h3>Methods</h3><ul class="tsd-index-list"><li class="tsd-kind-method tsd-parent-kind-class"><a href="GraphModel.html#dispose" class="tsd-kind-icon">dispose</a></li><li class="tsd-kind-method tsd-parent-kind-class"><a href="GraphModel.html#disposeIntermediateTensors" class="tsd-kind-icon">dispose<wbr/>Intermediate<wbr/>Tensors</a></li><li class="tsd-kind-method tsd-parent-kind-class"><a href="GraphModel.html#execute" class="tsd-kind-icon">execute</a></li><li class="tsd-kind-method tsd-parent-kind-class"><a href="GraphModel.html#executeAsync" class="tsd-kind-icon">execute<wbr/>Async</a></li><li class="tsd-kind-method tsd-parent-kind-class"><a href="GraphModel.html#getIntermediateTensors" class="tsd-kind-icon">get<wbr/>Intermediate<wbr/>Tensors</a></li><li class="tsd-kind-method tsd-parent-kind-class"><a href="GraphModel.html#load" class="tsd-kind-icon">load</a></li><li class="tsd-kind-method tsd-parent-kind-class"><a href="GraphModel.html#loadSync" class="tsd-kind-icon">load<wbr/>Sync</a></li><li class="tsd-kind-method tsd-parent-kind-class"><a href="GraphModel.html#predict" class="tsd-kind-icon">predict</a></li><li class="tsd-kind-method tsd-parent-kind-class"><a href="GraphModel.html#save" class="tsd-kind-icon">save</a></li></ul></section></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Constructors</h2><section class="tsd-panel tsd-member tsd-kind-constructor tsd-parent-kind-class"><a id="constructor" class="tsd-anchor"></a><h3>constructor</h3><ul class="tsd-signatures tsd-kind-constructor tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">new <wbr/>Graph<wbr/>Model<span class="tsd-signature-symbol">(</span>modelUrl<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">IOHandler</span>, loadOptions<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">LoadOptions</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><a href="GraphModel.html" class="tsd-signature-type" data-tsd-kind="Class">GraphModel</a></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in node_modules/.pnpm/@tensorflow+tfjs-converter@3.13.0_@tensorflow+tfjs-core@3.13.0/node_modules/@tensorflow/tfjs-converter/dist/executor/graph_model.d.ts:59</li></ul></aside><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5>modelUrl: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">IOHandler</span></h5><div class="tsd-comment tsd-typography"><div class="lead">
<p>url for the model, or an <code>io.IOHandler</code>.</p>

6
types/human.d.ts vendored
View File

@ -778,7 +778,7 @@ declare interface GPUData {
*
* A `tf.GraphModel` can only be created by loading from a model converted from
* a [TensorFlow SavedModel](https://www.tensorflow.org/guide/saved_model) using
* the command line converter tool and loaded via `tf.loadGraphModel`.
* the command line converter tool and loaded via `loadModel`.
*
* @doc {heading: 'Models', subheading: 'Classes'}
*/
@ -847,13 +847,13 @@ export declare class GraphModel implements InferenceModel {
* ```js
* const modelUrl =
* 'https://storage.googleapis.com/tfjs-models/savedmodel/mobilenet_v2_1.0_224/model.json';
* const model = await tf.loadGraphModel(modelUrl);
* const model = await loadModel(modelUrl);
* const zeros = tf.zeros([1, 224, 224, 3]);
* model.predict(zeros).print();
*
* const saveResults = await model.save('localstorage://my-model-1');
*
* const loadedModel = await tf.loadGraphModel('localstorage://my-model-1');
* const loadedModel = await loadModel('localstorage://my-model-1');
* console.log('Prediction from loaded model:');
* model.predict(zeros).print();
* ```