update & fix posenet

pull/134/head
Vladimir Mandic 2021-05-05 10:07:44 -04:00
parent 17e851bc2a
commit 733ffc8b2b
25 changed files with 1119 additions and 2460 deletions

View File

@ -1,6 +1,6 @@
# @vladmandic/human
Version: **1.8.2**
Version: **1.8.3**
Description: **Human: AI-powered 3D Face Detection & Rotation Tracking, Face Description & Recognition, Body Pose Tracking, 3D Hand & Finger Tracking, Iris Analysis, Age & Gender & Emotion Prediction, Gesture Recognition**
Author: **Vladimir Mandic <mandic00@live.com>**
@ -9,7 +9,10 @@ Repository: **<git+https://github.com/vladmandic/human.git>**
## Changelog
### **HEAD -> main** 2021/05/04 mandic00@live.com
### **1.8.3** 2021/05/05 mandic00@live.com
### **origin/main** 2021/05/04 mandic00@live.com
### **1.8.2** 2021/05/04 mandic00@live.com

View File

@ -9,11 +9,10 @@ import webRTC from './helpers/webrtc.js';
let human;
const userConfig = {
warmup: 'full',
warmup: 'none',
/*
backend: 'webgl',
async: true,
videoOptimized: false,
filter: {
enabled: false,
@ -36,10 +35,12 @@ const userConfig = {
// ui options
const ui = {
baseBackground: 'rgba(50, 50, 50, 1)', // 'grey'
// configurable items
console: true, // log messages to browser console
crop: true, // video mode crop to size or leave full frame
columns: 2, // when processing sample images create this many columns
facing: true, // camera facing front or back
baseBackground: 'rgba(50, 50, 50, 1)', // 'grey'
columns: 2, // when processing sample images create this many columns
useWorker: false, // use web workers for processing
worker: 'index-worker.js',
samples: ['../assets/sample6.jpg', '../assets/sample1.jpg', '../assets/sample4.jpg', '../assets/sample5.jpg', '../assets/sample3.jpg', '../assets/sample2.jpg'],
@ -47,10 +48,10 @@ const ui = {
useWebRTC: false, // use webrtc as camera source instead of local webcam
webRTCServer: 'http://localhost:8002',
webRTCStream: 'reowhite',
console: true, // log messages to browser console
maxFPSframes: 10, // keep fps history for how many frames
modelsPreload: true, // preload human models on startup
modelsWarmup: true, // warmup human models on startup
// internal variables
busy: false, // internal camera busy flag
menuWidth: 0, // internal
menuHeight: 0, // internal
@ -58,7 +59,7 @@ const ui = {
detectFPS: [], // internal, holds fps values for detection performance
drawFPS: [], // internal, holds fps values for draw performance
buffered: true, // should output be buffered between frames
drawWarmup: true, // debug only, should warmup image processing be displayed on startup
drawWarmup: false, // debug only, should warmup image processing be displayed on startup
drawThread: null, // internl, perform draw operations in a separate thread
detectThread: null, // internl, perform detect operations in a separate thread
framesDraw: 0, // internal, statistics on frames drawn

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

160
dist/human.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

160
dist/human.js vendored

File diff suppressed because one or more lines are too long

6
dist/human.js.map vendored

File diff suppressed because one or more lines are too long

318
dist/human.node-gpu.js vendored
View File

@ -106,6 +106,103 @@ function mergeDeep(...objects) {
}, {});
}
// src/config.ts
var config = {
backend: "webgl",
modelBasePath: "../models/",
wasmPath: "../assets/",
debug: true,
async: true,
videoOptimized: true,
warmup: "full",
filter: {
enabled: true,
width: 0,
height: 0,
flip: false,
return: true,
brightness: 0,
contrast: 0,
sharpness: 0,
blur: 0,
saturation: 0,
hue: 0,
negative: false,
sepia: false,
vintage: false,
kodachrome: false,
technicolor: false,
polaroid: false,
pixelate: 0
},
gesture: {
enabled: true
},
face: {
enabled: true,
detector: {
modelPath: "blazeface.json",
rotation: false,
maxDetected: 10,
skipFrames: 21,
skipInitial: false,
minConfidence: 0.2,
iouThreshold: 0.1,
return: false
},
mesh: {
enabled: true,
modelPath: "facemesh.json"
},
iris: {
enabled: true,
modelPath: "iris.json"
},
description: {
enabled: true,
modelPath: "faceres.json",
skipFrames: 31,
minConfidence: 0.1
},
emotion: {
enabled: true,
minConfidence: 0.1,
skipFrames: 32,
modelPath: "emotion.json"
}
},
body: {
enabled: true,
modelPath: "posenet.json",
maxDetected: 1,
minConfidence: 0.1
},
hand: {
enabled: true,
rotation: false,
skipFrames: 12,
skipInitial: false,
minConfidence: 0.1,
iouThreshold: 0.1,
maxDetected: 2,
landmarks: true,
detector: {
modelPath: "handdetect.json"
},
skeleton: {
modelPath: "handskeleton.json"
}
},
object: {
enabled: false,
modelPath: "nanodet.json",
minConfidence: 0.2,
iouThreshold: 0.4,
maxDetected: 10,
skipFrames: 41
}
};
// src/sysinfo.ts
function info() {
let platform;
@ -132,7 +229,7 @@ var tf16 = __toModule(require_tfjs_esm());
// src/tfjs/backend.ts
var tf = __toModule(require_tfjs_esm());
var config = {
var config2 = {
name: "humangl",
priority: 99,
canvas: null,
@ -151,29 +248,29 @@ var config = {
}
};
function register() {
if (!tf.findBackend(config.name)) {
log("backend registration:", config.name);
if (!tf.findBackend(config2.name)) {
log("backend registration:", config2.name);
try {
config.canvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(config.width, config.height) : document.createElement("canvas");
config2.canvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(config2.width, config2.height) : document.createElement("canvas");
} catch (err) {
log("error: cannot create canvas:", err);
return;
}
try {
config.gl = config.canvas.getContext("webgl2", config.webGLattr);
config2.gl = config2.canvas.getContext("webgl2", config2.webGLattr);
} catch (err) {
log("error: cannot get WebGL2 context:", err);
return;
}
try {
tf.setWebGLContext(2, config.gl);
tf.setWebGLContext(2, config2.gl);
} catch (err) {
log("error: cannot set WebGL2 context:", err);
return;
}
try {
const ctx = new tf.GPGPUContext(config.gl);
tf.registerBackend(config.name, () => new tf.MathBackendWebGL(ctx), config.priority);
const ctx = new tf.GPGPUContext(config2.gl);
tf.registerBackend(config2.name, () => new tf.MathBackendWebGL(ctx), config2.priority);
} catch (err) {
log("error: cannot register WebGL backend:", err);
return;
@ -181,7 +278,7 @@ function register() {
try {
const kernels = tf.getKernelsForBackend("webgl");
kernels.forEach((kernelConfig) => {
const newKernelConfig = {...kernelConfig, backendName: config.name};
const newKernelConfig = {...kernelConfig, backendName: config2.name};
tf.registerKernel(newKernelConfig);
});
} catch (err) {
@ -194,7 +291,7 @@ function register() {
log("error: cannot set WebGL backend flags:", err);
return;
}
log("backend registered:", config.name);
log("backend registered:", config2.name);
}
}
@ -4561,7 +4658,7 @@ function addVectors(a, b) {
var localMaximumRadius = 1;
var outputStride = 16;
var squaredNmsRadius = 50 ** 2;
function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scoresBuffer, offsets, displacements, offsetRefineStep = 2) {
function traverse(edgeId, sourceKeypoint, targetId, scores, offsets, displacements, offsetRefineStep = 2) {
const getDisplacement = (point2) => ({
y: displacements.get(point2.y, point2.x, edgeId),
x: displacements.get(point2.y, point2.x, displacements.shape[2] / 2 + edgeId)
@ -4570,51 +4667,48 @@ function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scor
y: clamp(Math.round(point2.y / outputStride), 0, height2 - 1),
x: clamp(Math.round(point2.x / outputStride), 0, width2 - 1)
});
const [height, width] = scoresBuffer.shape;
const [height, width] = scores.shape;
const sourceKeypointIndices = getStridedIndexNearPoint(sourceKeypoint.position, height, width);
const displacement = getDisplacement(sourceKeypointIndices);
const displacedPoint = addVectors(sourceKeypoint.position, displacement);
let targetKeypoint = displacedPoint;
for (let i = 0; i < offsetRefineStep; i++) {
const targetKeypointIndices = getStridedIndexNearPoint(targetKeypoint, height, width);
const offsetPoint = getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetKeypointId, offsets);
targetKeypoint = addVectors({
x: targetKeypointIndices.x * outputStride,
y: targetKeypointIndices.y * outputStride
}, {x: offsetPoint.x, y: offsetPoint.y});
const offsetPoint = getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetId, offsets);
targetKeypoint = addVectors({x: targetKeypointIndices.x * outputStride, y: targetKeypointIndices.y * outputStride}, {x: offsetPoint.x, y: offsetPoint.y});
}
const targetKeyPointIndices = getStridedIndexNearPoint(targetKeypoint, height, width);
const score = scoresBuffer.get(targetKeyPointIndices.y, targetKeyPointIndices.x, targetKeypointId);
return {position: targetKeypoint, part: partNames[targetKeypointId], score};
const score = scores.get(targetKeyPointIndices.y, targetKeyPointIndices.x, targetId);
return {position: targetKeypoint, part: partNames[targetId], score};
}
function decodePose(root, scores, offsets, displacementsFwd, displacementsBwd) {
const parentChildrenTuples = poseChain.map(([parentJoinName, childJoinName]) => [partIds[parentJoinName], partIds[childJoinName]]);
const parentToChildEdges = parentChildrenTuples.map(([, childJointId]) => childJointId);
const childToParentEdges = parentChildrenTuples.map(([parentJointId]) => parentJointId);
const tuples = poseChain.map(([parentJoinName, childJoinName]) => [partIds[parentJoinName], partIds[childJoinName]]);
const edgesFwd = tuples.map(([, childJointId]) => childJointId);
const edgesBwd = tuples.map(([parentJointId]) => parentJointId);
const numParts = scores.shape[2];
const numEdges = parentToChildEdges.length;
const instanceKeypoints = new Array(numParts);
const numEdges = edgesFwd.length;
const keypoints = new Array(numParts);
const rootPoint = getImageCoords(root.part, outputStride, offsets);
instanceKeypoints[root.part.id] = {
keypoints[root.part.id] = {
score: root.score,
part: partNames[root.part.id],
position: rootPoint
};
for (let edge = numEdges - 1; edge >= 0; --edge) {
const sourceKeypointId = parentToChildEdges[edge];
const targetKeypointId = childToParentEdges[edge];
if (instanceKeypoints[sourceKeypointId] && !instanceKeypoints[targetKeypointId]) {
instanceKeypoints[targetKeypointId] = traverseToTargetKeypoint(edge, instanceKeypoints[sourceKeypointId], targetKeypointId, scores, offsets, displacementsBwd);
const sourceId = edgesFwd[edge];
const targetId = edgesBwd[edge];
if (keypoints[sourceId] && !keypoints[targetId]) {
keypoints[targetId] = traverse(edge, keypoints[sourceId], targetId, scores, offsets, displacementsBwd);
}
}
for (let edge = 0; edge < numEdges; ++edge) {
const sourceKeypointId = childToParentEdges[edge];
const targetKeypointId = parentToChildEdges[edge];
if (instanceKeypoints[sourceKeypointId] && !instanceKeypoints[targetKeypointId]) {
instanceKeypoints[targetKeypointId] = traverseToTargetKeypoint(edge, instanceKeypoints[sourceKeypointId], targetKeypointId, scores, offsets, displacementsFwd);
const sourceId = edgesBwd[edge];
const targetId = edgesFwd[edge];
if (keypoints[sourceId] && !keypoints[targetId]) {
keypoints[targetId] = traverse(edge, keypoints[sourceId], targetId, scores, offsets, displacementsFwd);
}
}
return instanceKeypoints;
return keypoints;
}
function scoreIsMaximumInLocalWindow(keypointId, score, heatmapY, heatmapX, scores) {
const [height, width] = scores.shape;
@ -4653,27 +4747,30 @@ function buildPartWithScoreQueue(minConfidence, scores) {
}
function withinRadius(poses2, {x, y}, keypointId) {
return poses2.some(({keypoints}) => {
const correspondingKeypoint = keypoints[keypointId].position;
var _a;
const correspondingKeypoint = (_a = keypoints[keypointId]) == null ? void 0 : _a.position;
if (!correspondingKeypoint)
return false;
return squaredDistance(y, x, correspondingKeypoint.y, correspondingKeypoint.x) <= squaredNmsRadius;
});
}
function getInstanceScore(existingPoses, instanceKeypoints) {
const notOverlappedKeypointScores = instanceKeypoints.reduce((result, {position, score}, keypointId) => {
function getInstanceScore(existingPoses, keypoints) {
const notOverlappedKeypointScores = keypoints.reduce((result, {position, score}, keypointId) => {
if (!withinRadius(existingPoses, position, keypointId))
result += score;
return result;
}, 0);
return notOverlappedKeypointScores / instanceKeypoints.length;
return notOverlappedKeypointScores / keypoints.length;
}
function decode(offsetsBuffer, scoresBuffer, displacementsFwdBuffer, displacementsBwdBuffer, maxDetected, minConfidence) {
function decode(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence) {
const poses2 = [];
const queue = buildPartWithScoreQueue(minConfidence, scoresBuffer);
const queue = buildPartWithScoreQueue(minConfidence, scores);
while (poses2.length < maxDetected && !queue.empty()) {
const root = queue.dequeue();
const rootImageCoords = getImageCoords(root.part, outputStride, offsetsBuffer);
const rootImageCoords = getImageCoords(root.part, outputStride, offsets);
if (withinRadius(poses2, rootImageCoords, root.part.id))
continue;
let keypoints = decodePose(root, scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer);
let keypoints = decodePose(root, scores, offsets, displacementsFwd, displacementsBwd);
keypoints = keypoints.filter((a) => a.score > minConfidence);
const score = getInstanceScore(poses2, keypoints);
const box4 = getBoundingBox(keypoints);
@ -16701,11 +16798,11 @@ function rotatePoint2(homogeneousCoordinate, rotationMatrix) {
}
// src/handpose/handpipeline.ts
var PALM_BOX_ENLARGE_FACTOR = 5;
var HAND_BOX_ENLARGE_FACTOR = 1.65;
var PALM_LANDMARK_IDS = [0, 5, 9, 13, 17, 1, 2];
var PALM_LANDMARKS_INDEX_OF_PALM_BASE = 0;
var PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE = 2;
var palmBoxEnlargeFactor = 5;
var handBoxEnlargeFactor = 1.65;
var palmLandmarkIds = [0, 5, 9, 13, 17, 1, 2];
var palmLandmarksPalmBase = 0;
var palmLandmarksMiddleFingerBase = 2;
var HandPipeline = class {
constructor(handDetector, landmarkDetector) {
var _a;
@ -16716,17 +16813,24 @@ var HandPipeline = class {
this.skipped = 0;
this.detectedHands = 0;
}
calculateLandmarksBoundingBox(landmarks) {
const xs = landmarks.map((d) => d[0]);
const ys = landmarks.map((d) => d[1]);
const startPoint = [Math.min(...xs), Math.min(...ys)];
const endPoint = [Math.max(...xs), Math.max(...ys)];
return {startPoint, endPoint};
}
getBoxForPalmLandmarks(palmLandmarks, rotationMatrix) {
const rotatedPalmLandmarks = palmLandmarks.map((coord) => rotatePoint2([...coord, 1], rotationMatrix));
const boxAroundPalm = this.calculateLandmarksBoundingBox(rotatedPalmLandmarks);
return enlargeBox2(squarifyBox2(boxAroundPalm), PALM_BOX_ENLARGE_FACTOR);
return enlargeBox2(squarifyBox2(boxAroundPalm), palmBoxEnlargeFactor);
}
getBoxForHandLandmarks(landmarks) {
const boundingBox = this.calculateLandmarksBoundingBox(landmarks);
const boxAroundHand = enlargeBox2(squarifyBox2(boundingBox), HAND_BOX_ENLARGE_FACTOR);
const boxAroundHand = enlargeBox2(squarifyBox2(boundingBox), handBoxEnlargeFactor);
boxAroundHand.palmLandmarks = [];
for (let i = 0; i < PALM_LANDMARK_IDS.length; i++) {
boxAroundHand.palmLandmarks.push(landmarks[PALM_LANDMARK_IDS[i]].slice(0, 2));
for (let i = 0; i < palmLandmarkIds.length; i++) {
boxAroundHand.palmLandmarks.push(landmarks[palmLandmarkIds[i]].slice(0, 2));
}
return boxAroundHand;
}
@ -16778,7 +16882,7 @@ var HandPipeline = class {
if (!currentBox)
continue;
if (config3.hand.landmarks) {
const angle = config3.hand.rotation ? computeRotation2(currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_PALM_BASE], currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE]) : 0;
const angle = config3.hand.rotation ? computeRotation2(currentBox.palmLandmarks[palmLandmarksPalmBase], currentBox.palmLandmarks[palmLandmarksMiddleFingerBase]) : 0;
const palmCenter = getBoxCenter2(currentBox);
const palmCenterNormalized = [palmCenter[0] / image11.shape[2], palmCenter[1] / image11.shape[1]];
const rotatedImage = config3.hand.rotation ? tf11.image.rotateWithOffset(image11, angle, 0, palmCenterNormalized) : image11.clone();
@ -16811,7 +16915,7 @@ var HandPipeline = class {
}
keypoints.dispose();
} else {
const enlarged = enlargeBox2(squarifyBox2(currentBox), HAND_BOX_ENLARGE_FACTOR);
const enlarged = enlargeBox2(squarifyBox2(currentBox), handBoxEnlargeFactor);
const result = {
confidence: currentBox.confidence,
box: {topLeft: enlarged.startPoint, bottomRight: enlarged.endPoint}
@ -16823,13 +16927,6 @@ var HandPipeline = class {
this.detectedHands = hands.length;
return hands;
}
calculateLandmarksBoundingBox(landmarks) {
const xs = landmarks.map((d) => d[0]);
const ys = landmarks.map((d) => d[1]);
const startPoint = [Math.min(...xs), Math.min(...ys)];
const endPoint = [Math.max(...xs), Math.max(...ys)];
return {startPoint, endPoint};
}
};
// src/handpose/handpose.ts
@ -18691,103 +18788,6 @@ async function all(inCanvas2, result, drawOptions) {
object(inCanvas2, result.object, localOptions);
}
// src/config.ts
var config2 = {
backend: "webgl",
modelBasePath: "../models/",
wasmPath: "../assets/",
debug: true,
async: true,
videoOptimized: true,
warmup: "full",
filter: {
enabled: true,
width: 0,
height: 0,
flip: false,
return: true,
brightness: 0,
contrast: 0,
sharpness: 0,
blur: 0,
saturation: 0,
hue: 0,
negative: false,
sepia: false,
vintage: false,
kodachrome: false,
technicolor: false,
polaroid: false,
pixelate: 0
},
gesture: {
enabled: true
},
face: {
enabled: true,
detector: {
modelPath: "blazeface.json",
rotation: false,
maxDetected: 10,
skipFrames: 21,
skipInitial: false,
minConfidence: 0.2,
iouThreshold: 0.1,
return: false
},
mesh: {
enabled: true,
modelPath: "facemesh.json"
},
iris: {
enabled: true,
modelPath: "iris.json"
},
description: {
enabled: true,
modelPath: "faceres.json",
skipFrames: 31,
minConfidence: 0.1
},
emotion: {
enabled: true,
minConfidence: 0.1,
skipFrames: 32,
modelPath: "emotion.json"
}
},
body: {
enabled: true,
modelPath: "posenet.json",
maxDetected: 1,
minConfidence: 0.1
},
hand: {
enabled: true,
rotation: false,
skipFrames: 12,
skipInitial: false,
minConfidence: 0.1,
iouThreshold: 0.1,
maxDetected: 1,
landmarks: true,
detector: {
modelPath: "handdetect.json"
},
skeleton: {
modelPath: "handskeleton.json"
}
},
object: {
enabled: false,
modelPath: "nanodet.json",
minConfidence: 0.2,
iouThreshold: 0.4,
maxDetected: 10,
skipFrames: 41
}
};
// src/sample.ts
var face3 = `
/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUA
@ -19512,7 +19512,7 @@ lBhEMohlFerLlBjEMohMVTEARDKCITsAk2AEgAAAkAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAD/
2Q==`;
// package.json
var version = "1.8.2";
var version = "1.8.3";
// src/human.ts
var _numTensors, _analyzeMemoryLeaks, _checkSanity, _firstRun, _sanity, _checkBackend, _warmupBitmap, _warmupCanvas, _warmupNode;
@ -19675,7 +19675,7 @@ var Human = class {
this.tf = tf16;
this.draw = draw_exports;
this.version = version;
this.config = mergeDeep(config2, userConfig);
this.config = mergeDeep(config, userConfig);
this.state = "idle";
__privateSet(this, _numTensors, 0);
__privateSet(this, _analyzeMemoryLeaks, false);

View File

@ -107,6 +107,103 @@ function mergeDeep(...objects) {
}, {});
}
// src/config.ts
var config = {
backend: "webgl",
modelBasePath: "../models/",
wasmPath: "../assets/",
debug: true,
async: true,
videoOptimized: true,
warmup: "full",
filter: {
enabled: true,
width: 0,
height: 0,
flip: false,
return: true,
brightness: 0,
contrast: 0,
sharpness: 0,
blur: 0,
saturation: 0,
hue: 0,
negative: false,
sepia: false,
vintage: false,
kodachrome: false,
technicolor: false,
polaroid: false,
pixelate: 0
},
gesture: {
enabled: true
},
face: {
enabled: true,
detector: {
modelPath: "blazeface.json",
rotation: false,
maxDetected: 10,
skipFrames: 21,
skipInitial: false,
minConfidence: 0.2,
iouThreshold: 0.1,
return: false
},
mesh: {
enabled: true,
modelPath: "facemesh.json"
},
iris: {
enabled: true,
modelPath: "iris.json"
},
description: {
enabled: true,
modelPath: "faceres.json",
skipFrames: 31,
minConfidence: 0.1
},
emotion: {
enabled: true,
minConfidence: 0.1,
skipFrames: 32,
modelPath: "emotion.json"
}
},
body: {
enabled: true,
modelPath: "posenet.json",
maxDetected: 1,
minConfidence: 0.1
},
hand: {
enabled: true,
rotation: false,
skipFrames: 12,
skipInitial: false,
minConfidence: 0.1,
iouThreshold: 0.1,
maxDetected: 2,
landmarks: true,
detector: {
modelPath: "handdetect.json"
},
skeleton: {
modelPath: "handskeleton.json"
}
},
object: {
enabled: false,
modelPath: "nanodet.json",
minConfidence: 0.2,
iouThreshold: 0.4,
maxDetected: 10,
skipFrames: 41
}
};
// src/sysinfo.ts
function info() {
let platform;
@ -133,7 +230,7 @@ var tf16 = __toModule(require_tfjs_esm());
// src/tfjs/backend.ts
var tf = __toModule(require_tfjs_esm());
var config = {
var config2 = {
name: "humangl",
priority: 99,
canvas: null,
@ -152,29 +249,29 @@ var config = {
}
};
function register() {
if (!tf.findBackend(config.name)) {
log("backend registration:", config.name);
if (!tf.findBackend(config2.name)) {
log("backend registration:", config2.name);
try {
config.canvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(config.width, config.height) : document.createElement("canvas");
config2.canvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(config2.width, config2.height) : document.createElement("canvas");
} catch (err) {
log("error: cannot create canvas:", err);
return;
}
try {
config.gl = config.canvas.getContext("webgl2", config.webGLattr);
config2.gl = config2.canvas.getContext("webgl2", config2.webGLattr);
} catch (err) {
log("error: cannot get WebGL2 context:", err);
return;
}
try {
tf.setWebGLContext(2, config.gl);
tf.setWebGLContext(2, config2.gl);
} catch (err) {
log("error: cannot set WebGL2 context:", err);
return;
}
try {
const ctx = new tf.GPGPUContext(config.gl);
tf.registerBackend(config.name, () => new tf.MathBackendWebGL(ctx), config.priority);
const ctx = new tf.GPGPUContext(config2.gl);
tf.registerBackend(config2.name, () => new tf.MathBackendWebGL(ctx), config2.priority);
} catch (err) {
log("error: cannot register WebGL backend:", err);
return;
@ -182,7 +279,7 @@ function register() {
try {
const kernels = tf.getKernelsForBackend("webgl");
kernels.forEach((kernelConfig) => {
const newKernelConfig = {...kernelConfig, backendName: config.name};
const newKernelConfig = {...kernelConfig, backendName: config2.name};
tf.registerKernel(newKernelConfig);
});
} catch (err) {
@ -195,7 +292,7 @@ function register() {
log("error: cannot set WebGL backend flags:", err);
return;
}
log("backend registered:", config.name);
log("backend registered:", config2.name);
}
}
@ -4562,7 +4659,7 @@ function addVectors(a, b) {
var localMaximumRadius = 1;
var outputStride = 16;
var squaredNmsRadius = 50 ** 2;
function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scoresBuffer, offsets, displacements, offsetRefineStep = 2) {
function traverse(edgeId, sourceKeypoint, targetId, scores, offsets, displacements, offsetRefineStep = 2) {
const getDisplacement = (point2) => ({
y: displacements.get(point2.y, point2.x, edgeId),
x: displacements.get(point2.y, point2.x, displacements.shape[2] / 2 + edgeId)
@ -4571,51 +4668,48 @@ function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scor
y: clamp(Math.round(point2.y / outputStride), 0, height2 - 1),
x: clamp(Math.round(point2.x / outputStride), 0, width2 - 1)
});
const [height, width] = scoresBuffer.shape;
const [height, width] = scores.shape;
const sourceKeypointIndices = getStridedIndexNearPoint(sourceKeypoint.position, height, width);
const displacement = getDisplacement(sourceKeypointIndices);
const displacedPoint = addVectors(sourceKeypoint.position, displacement);
let targetKeypoint = displacedPoint;
for (let i = 0; i < offsetRefineStep; i++) {
const targetKeypointIndices = getStridedIndexNearPoint(targetKeypoint, height, width);
const offsetPoint = getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetKeypointId, offsets);
targetKeypoint = addVectors({
x: targetKeypointIndices.x * outputStride,
y: targetKeypointIndices.y * outputStride
}, {x: offsetPoint.x, y: offsetPoint.y});
const offsetPoint = getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetId, offsets);
targetKeypoint = addVectors({x: targetKeypointIndices.x * outputStride, y: targetKeypointIndices.y * outputStride}, {x: offsetPoint.x, y: offsetPoint.y});
}
const targetKeyPointIndices = getStridedIndexNearPoint(targetKeypoint, height, width);
const score = scoresBuffer.get(targetKeyPointIndices.y, targetKeyPointIndices.x, targetKeypointId);
return {position: targetKeypoint, part: partNames[targetKeypointId], score};
const score = scores.get(targetKeyPointIndices.y, targetKeyPointIndices.x, targetId);
return {position: targetKeypoint, part: partNames[targetId], score};
}
function decodePose(root, scores, offsets, displacementsFwd, displacementsBwd) {
const parentChildrenTuples = poseChain.map(([parentJoinName, childJoinName]) => [partIds[parentJoinName], partIds[childJoinName]]);
const parentToChildEdges = parentChildrenTuples.map(([, childJointId]) => childJointId);
const childToParentEdges = parentChildrenTuples.map(([parentJointId]) => parentJointId);
const tuples = poseChain.map(([parentJoinName, childJoinName]) => [partIds[parentJoinName], partIds[childJoinName]]);
const edgesFwd = tuples.map(([, childJointId]) => childJointId);
const edgesBwd = tuples.map(([parentJointId]) => parentJointId);
const numParts = scores.shape[2];
const numEdges = parentToChildEdges.length;
const instanceKeypoints = new Array(numParts);
const numEdges = edgesFwd.length;
const keypoints = new Array(numParts);
const rootPoint = getImageCoords(root.part, outputStride, offsets);
instanceKeypoints[root.part.id] = {
keypoints[root.part.id] = {
score: root.score,
part: partNames[root.part.id],
position: rootPoint
};
for (let edge = numEdges - 1; edge >= 0; --edge) {
const sourceKeypointId = parentToChildEdges[edge];
const targetKeypointId = childToParentEdges[edge];
if (instanceKeypoints[sourceKeypointId] && !instanceKeypoints[targetKeypointId]) {
instanceKeypoints[targetKeypointId] = traverseToTargetKeypoint(edge, instanceKeypoints[sourceKeypointId], targetKeypointId, scores, offsets, displacementsBwd);
const sourceId = edgesFwd[edge];
const targetId = edgesBwd[edge];
if (keypoints[sourceId] && !keypoints[targetId]) {
keypoints[targetId] = traverse(edge, keypoints[sourceId], targetId, scores, offsets, displacementsBwd);
}
}
for (let edge = 0; edge < numEdges; ++edge) {
const sourceKeypointId = childToParentEdges[edge];
const targetKeypointId = parentToChildEdges[edge];
if (instanceKeypoints[sourceKeypointId] && !instanceKeypoints[targetKeypointId]) {
instanceKeypoints[targetKeypointId] = traverseToTargetKeypoint(edge, instanceKeypoints[sourceKeypointId], targetKeypointId, scores, offsets, displacementsFwd);
const sourceId = edgesBwd[edge];
const targetId = edgesFwd[edge];
if (keypoints[sourceId] && !keypoints[targetId]) {
keypoints[targetId] = traverse(edge, keypoints[sourceId], targetId, scores, offsets, displacementsFwd);
}
}
return instanceKeypoints;
return keypoints;
}
function scoreIsMaximumInLocalWindow(keypointId, score, heatmapY, heatmapX, scores) {
const [height, width] = scores.shape;
@ -4654,27 +4748,30 @@ function buildPartWithScoreQueue(minConfidence, scores) {
}
function withinRadius(poses2, {x, y}, keypointId) {
return poses2.some(({keypoints}) => {
const correspondingKeypoint = keypoints[keypointId].position;
var _a;
const correspondingKeypoint = (_a = keypoints[keypointId]) == null ? void 0 : _a.position;
if (!correspondingKeypoint)
return false;
return squaredDistance(y, x, correspondingKeypoint.y, correspondingKeypoint.x) <= squaredNmsRadius;
});
}
function getInstanceScore(existingPoses, instanceKeypoints) {
const notOverlappedKeypointScores = instanceKeypoints.reduce((result, {position, score}, keypointId) => {
function getInstanceScore(existingPoses, keypoints) {
const notOverlappedKeypointScores = keypoints.reduce((result, {position, score}, keypointId) => {
if (!withinRadius(existingPoses, position, keypointId))
result += score;
return result;
}, 0);
return notOverlappedKeypointScores / instanceKeypoints.length;
return notOverlappedKeypointScores / keypoints.length;
}
function decode(offsetsBuffer, scoresBuffer, displacementsFwdBuffer, displacementsBwdBuffer, maxDetected, minConfidence) {
function decode(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence) {
const poses2 = [];
const queue = buildPartWithScoreQueue(minConfidence, scoresBuffer);
const queue = buildPartWithScoreQueue(minConfidence, scores);
while (poses2.length < maxDetected && !queue.empty()) {
const root = queue.dequeue();
const rootImageCoords = getImageCoords(root.part, outputStride, offsetsBuffer);
const rootImageCoords = getImageCoords(root.part, outputStride, offsets);
if (withinRadius(poses2, rootImageCoords, root.part.id))
continue;
let keypoints = decodePose(root, scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer);
let keypoints = decodePose(root, scores, offsets, displacementsFwd, displacementsBwd);
keypoints = keypoints.filter((a) => a.score > minConfidence);
const score = getInstanceScore(poses2, keypoints);
const box4 = getBoundingBox(keypoints);
@ -16702,11 +16799,11 @@ function rotatePoint2(homogeneousCoordinate, rotationMatrix) {
}
// src/handpose/handpipeline.ts
var PALM_BOX_ENLARGE_FACTOR = 5;
var HAND_BOX_ENLARGE_FACTOR = 1.65;
var PALM_LANDMARK_IDS = [0, 5, 9, 13, 17, 1, 2];
var PALM_LANDMARKS_INDEX_OF_PALM_BASE = 0;
var PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE = 2;
var palmBoxEnlargeFactor = 5;
var handBoxEnlargeFactor = 1.65;
var palmLandmarkIds = [0, 5, 9, 13, 17, 1, 2];
var palmLandmarksPalmBase = 0;
var palmLandmarksMiddleFingerBase = 2;
var HandPipeline = class {
constructor(handDetector, landmarkDetector) {
var _a;
@ -16717,17 +16814,24 @@ var HandPipeline = class {
this.skipped = 0;
this.detectedHands = 0;
}
calculateLandmarksBoundingBox(landmarks) {
const xs = landmarks.map((d) => d[0]);
const ys = landmarks.map((d) => d[1]);
const startPoint = [Math.min(...xs), Math.min(...ys)];
const endPoint = [Math.max(...xs), Math.max(...ys)];
return {startPoint, endPoint};
}
getBoxForPalmLandmarks(palmLandmarks, rotationMatrix) {
const rotatedPalmLandmarks = palmLandmarks.map((coord) => rotatePoint2([...coord, 1], rotationMatrix));
const boxAroundPalm = this.calculateLandmarksBoundingBox(rotatedPalmLandmarks);
return enlargeBox2(squarifyBox2(boxAroundPalm), PALM_BOX_ENLARGE_FACTOR);
return enlargeBox2(squarifyBox2(boxAroundPalm), palmBoxEnlargeFactor);
}
getBoxForHandLandmarks(landmarks) {
const boundingBox = this.calculateLandmarksBoundingBox(landmarks);
const boxAroundHand = enlargeBox2(squarifyBox2(boundingBox), HAND_BOX_ENLARGE_FACTOR);
const boxAroundHand = enlargeBox2(squarifyBox2(boundingBox), handBoxEnlargeFactor);
boxAroundHand.palmLandmarks = [];
for (let i = 0; i < PALM_LANDMARK_IDS.length; i++) {
boxAroundHand.palmLandmarks.push(landmarks[PALM_LANDMARK_IDS[i]].slice(0, 2));
for (let i = 0; i < palmLandmarkIds.length; i++) {
boxAroundHand.palmLandmarks.push(landmarks[palmLandmarkIds[i]].slice(0, 2));
}
return boxAroundHand;
}
@ -16779,7 +16883,7 @@ var HandPipeline = class {
if (!currentBox)
continue;
if (config3.hand.landmarks) {
const angle = config3.hand.rotation ? computeRotation2(currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_PALM_BASE], currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE]) : 0;
const angle = config3.hand.rotation ? computeRotation2(currentBox.palmLandmarks[palmLandmarksPalmBase], currentBox.palmLandmarks[palmLandmarksMiddleFingerBase]) : 0;
const palmCenter = getBoxCenter2(currentBox);
const palmCenterNormalized = [palmCenter[0] / image11.shape[2], palmCenter[1] / image11.shape[1]];
const rotatedImage = config3.hand.rotation ? tf11.image.rotateWithOffset(image11, angle, 0, palmCenterNormalized) : image11.clone();
@ -16812,7 +16916,7 @@ var HandPipeline = class {
}
keypoints.dispose();
} else {
const enlarged = enlargeBox2(squarifyBox2(currentBox), HAND_BOX_ENLARGE_FACTOR);
const enlarged = enlargeBox2(squarifyBox2(currentBox), handBoxEnlargeFactor);
const result = {
confidence: currentBox.confidence,
box: {topLeft: enlarged.startPoint, bottomRight: enlarged.endPoint}
@ -16824,13 +16928,6 @@ var HandPipeline = class {
this.detectedHands = hands.length;
return hands;
}
calculateLandmarksBoundingBox(landmarks) {
const xs = landmarks.map((d) => d[0]);
const ys = landmarks.map((d) => d[1]);
const startPoint = [Math.min(...xs), Math.min(...ys)];
const endPoint = [Math.max(...xs), Math.max(...ys)];
return {startPoint, endPoint};
}
};
// src/handpose/handpose.ts
@ -18692,103 +18789,6 @@ async function all(inCanvas2, result, drawOptions) {
object(inCanvas2, result.object, localOptions);
}
// src/config.ts
var config2 = {
backend: "webgl",
modelBasePath: "../models/",
wasmPath: "../assets/",
debug: true,
async: true,
videoOptimized: true,
warmup: "full",
filter: {
enabled: true,
width: 0,
height: 0,
flip: false,
return: true,
brightness: 0,
contrast: 0,
sharpness: 0,
blur: 0,
saturation: 0,
hue: 0,
negative: false,
sepia: false,
vintage: false,
kodachrome: false,
technicolor: false,
polaroid: false,
pixelate: 0
},
gesture: {
enabled: true
},
face: {
enabled: true,
detector: {
modelPath: "blazeface.json",
rotation: false,
maxDetected: 10,
skipFrames: 21,
skipInitial: false,
minConfidence: 0.2,
iouThreshold: 0.1,
return: false
},
mesh: {
enabled: true,
modelPath: "facemesh.json"
},
iris: {
enabled: true,
modelPath: "iris.json"
},
description: {
enabled: true,
modelPath: "faceres.json",
skipFrames: 31,
minConfidence: 0.1
},
emotion: {
enabled: true,
minConfidence: 0.1,
skipFrames: 32,
modelPath: "emotion.json"
}
},
body: {
enabled: true,
modelPath: "posenet.json",
maxDetected: 1,
minConfidence: 0.1
},
hand: {
enabled: true,
rotation: false,
skipFrames: 12,
skipInitial: false,
minConfidence: 0.1,
iouThreshold: 0.1,
maxDetected: 1,
landmarks: true,
detector: {
modelPath: "handdetect.json"
},
skeleton: {
modelPath: "handskeleton.json"
}
},
object: {
enabled: false,
modelPath: "nanodet.json",
minConfidence: 0.2,
iouThreshold: 0.4,
maxDetected: 10,
skipFrames: 41
}
};
// src/sample.ts
var face3 = `
/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUA
@ -19513,7 +19513,7 @@ lBhEMohlFerLlBjEMohMVTEARDKCITsAk2AEgAAAkAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAD/
2Q==`;
// package.json
var version = "1.8.2";
var version = "1.8.3";
// src/human.ts
var _numTensors, _analyzeMemoryLeaks, _checkSanity, _firstRun, _sanity, _checkBackend, _warmupBitmap, _warmupCanvas, _warmupNode;
@ -19676,7 +19676,7 @@ var Human = class {
this.tf = tf16;
this.draw = draw_exports;
this.version = version;
this.config = mergeDeep(config2, userConfig);
this.config = mergeDeep(config, userConfig);
this.state = "idle";
__privateSet(this, _numTensors, 0);
__privateSet(this, _analyzeMemoryLeaks, false);

318
dist/human.node.js vendored
View File

@ -106,6 +106,103 @@ function mergeDeep(...objects) {
}, {});
}
// src/config.ts
var config = {
backend: "webgl",
modelBasePath: "../models/",
wasmPath: "../assets/",
debug: true,
async: true,
videoOptimized: true,
warmup: "full",
filter: {
enabled: true,
width: 0,
height: 0,
flip: false,
return: true,
brightness: 0,
contrast: 0,
sharpness: 0,
blur: 0,
saturation: 0,
hue: 0,
negative: false,
sepia: false,
vintage: false,
kodachrome: false,
technicolor: false,
polaroid: false,
pixelate: 0
},
gesture: {
enabled: true
},
face: {
enabled: true,
detector: {
modelPath: "blazeface.json",
rotation: false,
maxDetected: 10,
skipFrames: 21,
skipInitial: false,
minConfidence: 0.2,
iouThreshold: 0.1,
return: false
},
mesh: {
enabled: true,
modelPath: "facemesh.json"
},
iris: {
enabled: true,
modelPath: "iris.json"
},
description: {
enabled: true,
modelPath: "faceres.json",
skipFrames: 31,
minConfidence: 0.1
},
emotion: {
enabled: true,
minConfidence: 0.1,
skipFrames: 32,
modelPath: "emotion.json"
}
},
body: {
enabled: true,
modelPath: "posenet.json",
maxDetected: 1,
minConfidence: 0.1
},
hand: {
enabled: true,
rotation: false,
skipFrames: 12,
skipInitial: false,
minConfidence: 0.1,
iouThreshold: 0.1,
maxDetected: 2,
landmarks: true,
detector: {
modelPath: "handdetect.json"
},
skeleton: {
modelPath: "handskeleton.json"
}
},
object: {
enabled: false,
modelPath: "nanodet.json",
minConfidence: 0.2,
iouThreshold: 0.4,
maxDetected: 10,
skipFrames: 41
}
};
// src/sysinfo.ts
function info() {
let platform;
@ -132,7 +229,7 @@ var tf16 = __toModule(require_tfjs_esm());
// src/tfjs/backend.ts
var tf = __toModule(require_tfjs_esm());
var config = {
var config2 = {
name: "humangl",
priority: 99,
canvas: null,
@ -151,29 +248,29 @@ var config = {
}
};
function register() {
if (!tf.findBackend(config.name)) {
log("backend registration:", config.name);
if (!tf.findBackend(config2.name)) {
log("backend registration:", config2.name);
try {
config.canvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(config.width, config.height) : document.createElement("canvas");
config2.canvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(config2.width, config2.height) : document.createElement("canvas");
} catch (err) {
log("error: cannot create canvas:", err);
return;
}
try {
config.gl = config.canvas.getContext("webgl2", config.webGLattr);
config2.gl = config2.canvas.getContext("webgl2", config2.webGLattr);
} catch (err) {
log("error: cannot get WebGL2 context:", err);
return;
}
try {
tf.setWebGLContext(2, config.gl);
tf.setWebGLContext(2, config2.gl);
} catch (err) {
log("error: cannot set WebGL2 context:", err);
return;
}
try {
const ctx = new tf.GPGPUContext(config.gl);
tf.registerBackend(config.name, () => new tf.MathBackendWebGL(ctx), config.priority);
const ctx = new tf.GPGPUContext(config2.gl);
tf.registerBackend(config2.name, () => new tf.MathBackendWebGL(ctx), config2.priority);
} catch (err) {
log("error: cannot register WebGL backend:", err);
return;
@ -181,7 +278,7 @@ function register() {
try {
const kernels = tf.getKernelsForBackend("webgl");
kernels.forEach((kernelConfig) => {
const newKernelConfig = {...kernelConfig, backendName: config.name};
const newKernelConfig = {...kernelConfig, backendName: config2.name};
tf.registerKernel(newKernelConfig);
});
} catch (err) {
@ -194,7 +291,7 @@ function register() {
log("error: cannot set WebGL backend flags:", err);
return;
}
log("backend registered:", config.name);
log("backend registered:", config2.name);
}
}
@ -4561,7 +4658,7 @@ function addVectors(a, b) {
var localMaximumRadius = 1;
var outputStride = 16;
var squaredNmsRadius = 50 ** 2;
function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scoresBuffer, offsets, displacements, offsetRefineStep = 2) {
function traverse(edgeId, sourceKeypoint, targetId, scores, offsets, displacements, offsetRefineStep = 2) {
const getDisplacement = (point2) => ({
y: displacements.get(point2.y, point2.x, edgeId),
x: displacements.get(point2.y, point2.x, displacements.shape[2] / 2 + edgeId)
@ -4570,51 +4667,48 @@ function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scor
y: clamp(Math.round(point2.y / outputStride), 0, height2 - 1),
x: clamp(Math.round(point2.x / outputStride), 0, width2 - 1)
});
const [height, width] = scoresBuffer.shape;
const [height, width] = scores.shape;
const sourceKeypointIndices = getStridedIndexNearPoint(sourceKeypoint.position, height, width);
const displacement = getDisplacement(sourceKeypointIndices);
const displacedPoint = addVectors(sourceKeypoint.position, displacement);
let targetKeypoint = displacedPoint;
for (let i = 0; i < offsetRefineStep; i++) {
const targetKeypointIndices = getStridedIndexNearPoint(targetKeypoint, height, width);
const offsetPoint = getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetKeypointId, offsets);
targetKeypoint = addVectors({
x: targetKeypointIndices.x * outputStride,
y: targetKeypointIndices.y * outputStride
}, {x: offsetPoint.x, y: offsetPoint.y});
const offsetPoint = getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetId, offsets);
targetKeypoint = addVectors({x: targetKeypointIndices.x * outputStride, y: targetKeypointIndices.y * outputStride}, {x: offsetPoint.x, y: offsetPoint.y});
}
const targetKeyPointIndices = getStridedIndexNearPoint(targetKeypoint, height, width);
const score = scoresBuffer.get(targetKeyPointIndices.y, targetKeyPointIndices.x, targetKeypointId);
return {position: targetKeypoint, part: partNames[targetKeypointId], score};
const score = scores.get(targetKeyPointIndices.y, targetKeyPointIndices.x, targetId);
return {position: targetKeypoint, part: partNames[targetId], score};
}
function decodePose(root, scores, offsets, displacementsFwd, displacementsBwd) {
const parentChildrenTuples = poseChain.map(([parentJoinName, childJoinName]) => [partIds[parentJoinName], partIds[childJoinName]]);
const parentToChildEdges = parentChildrenTuples.map(([, childJointId]) => childJointId);
const childToParentEdges = parentChildrenTuples.map(([parentJointId]) => parentJointId);
const tuples = poseChain.map(([parentJoinName, childJoinName]) => [partIds[parentJoinName], partIds[childJoinName]]);
const edgesFwd = tuples.map(([, childJointId]) => childJointId);
const edgesBwd = tuples.map(([parentJointId]) => parentJointId);
const numParts = scores.shape[2];
const numEdges = parentToChildEdges.length;
const instanceKeypoints = new Array(numParts);
const numEdges = edgesFwd.length;
const keypoints = new Array(numParts);
const rootPoint = getImageCoords(root.part, outputStride, offsets);
instanceKeypoints[root.part.id] = {
keypoints[root.part.id] = {
score: root.score,
part: partNames[root.part.id],
position: rootPoint
};
for (let edge = numEdges - 1; edge >= 0; --edge) {
const sourceKeypointId = parentToChildEdges[edge];
const targetKeypointId = childToParentEdges[edge];
if (instanceKeypoints[sourceKeypointId] && !instanceKeypoints[targetKeypointId]) {
instanceKeypoints[targetKeypointId] = traverseToTargetKeypoint(edge, instanceKeypoints[sourceKeypointId], targetKeypointId, scores, offsets, displacementsBwd);
const sourceId = edgesFwd[edge];
const targetId = edgesBwd[edge];
if (keypoints[sourceId] && !keypoints[targetId]) {
keypoints[targetId] = traverse(edge, keypoints[sourceId], targetId, scores, offsets, displacementsBwd);
}
}
for (let edge = 0; edge < numEdges; ++edge) {
const sourceKeypointId = childToParentEdges[edge];
const targetKeypointId = parentToChildEdges[edge];
if (instanceKeypoints[sourceKeypointId] && !instanceKeypoints[targetKeypointId]) {
instanceKeypoints[targetKeypointId] = traverseToTargetKeypoint(edge, instanceKeypoints[sourceKeypointId], targetKeypointId, scores, offsets, displacementsFwd);
const sourceId = edgesBwd[edge];
const targetId = edgesFwd[edge];
if (keypoints[sourceId] && !keypoints[targetId]) {
keypoints[targetId] = traverse(edge, keypoints[sourceId], targetId, scores, offsets, displacementsFwd);
}
}
return instanceKeypoints;
return keypoints;
}
function scoreIsMaximumInLocalWindow(keypointId, score, heatmapY, heatmapX, scores) {
const [height, width] = scores.shape;
@ -4653,27 +4747,30 @@ function buildPartWithScoreQueue(minConfidence, scores) {
}
function withinRadius(poses2, {x, y}, keypointId) {
return poses2.some(({keypoints}) => {
const correspondingKeypoint = keypoints[keypointId].position;
var _a;
const correspondingKeypoint = (_a = keypoints[keypointId]) == null ? void 0 : _a.position;
if (!correspondingKeypoint)
return false;
return squaredDistance(y, x, correspondingKeypoint.y, correspondingKeypoint.x) <= squaredNmsRadius;
});
}
function getInstanceScore(existingPoses, instanceKeypoints) {
const notOverlappedKeypointScores = instanceKeypoints.reduce((result, {position, score}, keypointId) => {
function getInstanceScore(existingPoses, keypoints) {
const notOverlappedKeypointScores = keypoints.reduce((result, {position, score}, keypointId) => {
if (!withinRadius(existingPoses, position, keypointId))
result += score;
return result;
}, 0);
return notOverlappedKeypointScores / instanceKeypoints.length;
return notOverlappedKeypointScores / keypoints.length;
}
function decode(offsetsBuffer, scoresBuffer, displacementsFwdBuffer, displacementsBwdBuffer, maxDetected, minConfidence) {
function decode(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence) {
const poses2 = [];
const queue = buildPartWithScoreQueue(minConfidence, scoresBuffer);
const queue = buildPartWithScoreQueue(minConfidence, scores);
while (poses2.length < maxDetected && !queue.empty()) {
const root = queue.dequeue();
const rootImageCoords = getImageCoords(root.part, outputStride, offsetsBuffer);
const rootImageCoords = getImageCoords(root.part, outputStride, offsets);
if (withinRadius(poses2, rootImageCoords, root.part.id))
continue;
let keypoints = decodePose(root, scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer);
let keypoints = decodePose(root, scores, offsets, displacementsFwd, displacementsBwd);
keypoints = keypoints.filter((a) => a.score > minConfidence);
const score = getInstanceScore(poses2, keypoints);
const box4 = getBoundingBox(keypoints);
@ -16701,11 +16798,11 @@ function rotatePoint2(homogeneousCoordinate, rotationMatrix) {
}
// src/handpose/handpipeline.ts
var PALM_BOX_ENLARGE_FACTOR = 5;
var HAND_BOX_ENLARGE_FACTOR = 1.65;
var PALM_LANDMARK_IDS = [0, 5, 9, 13, 17, 1, 2];
var PALM_LANDMARKS_INDEX_OF_PALM_BASE = 0;
var PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE = 2;
var palmBoxEnlargeFactor = 5;
var handBoxEnlargeFactor = 1.65;
var palmLandmarkIds = [0, 5, 9, 13, 17, 1, 2];
var palmLandmarksPalmBase = 0;
var palmLandmarksMiddleFingerBase = 2;
var HandPipeline = class {
constructor(handDetector, landmarkDetector) {
var _a;
@ -16716,17 +16813,24 @@ var HandPipeline = class {
this.skipped = 0;
this.detectedHands = 0;
}
calculateLandmarksBoundingBox(landmarks) {
const xs = landmarks.map((d) => d[0]);
const ys = landmarks.map((d) => d[1]);
const startPoint = [Math.min(...xs), Math.min(...ys)];
const endPoint = [Math.max(...xs), Math.max(...ys)];
return {startPoint, endPoint};
}
getBoxForPalmLandmarks(palmLandmarks, rotationMatrix) {
const rotatedPalmLandmarks = palmLandmarks.map((coord) => rotatePoint2([...coord, 1], rotationMatrix));
const boxAroundPalm = this.calculateLandmarksBoundingBox(rotatedPalmLandmarks);
return enlargeBox2(squarifyBox2(boxAroundPalm), PALM_BOX_ENLARGE_FACTOR);
return enlargeBox2(squarifyBox2(boxAroundPalm), palmBoxEnlargeFactor);
}
getBoxForHandLandmarks(landmarks) {
const boundingBox = this.calculateLandmarksBoundingBox(landmarks);
const boxAroundHand = enlargeBox2(squarifyBox2(boundingBox), HAND_BOX_ENLARGE_FACTOR);
const boxAroundHand = enlargeBox2(squarifyBox2(boundingBox), handBoxEnlargeFactor);
boxAroundHand.palmLandmarks = [];
for (let i = 0; i < PALM_LANDMARK_IDS.length; i++) {
boxAroundHand.palmLandmarks.push(landmarks[PALM_LANDMARK_IDS[i]].slice(0, 2));
for (let i = 0; i < palmLandmarkIds.length; i++) {
boxAroundHand.palmLandmarks.push(landmarks[palmLandmarkIds[i]].slice(0, 2));
}
return boxAroundHand;
}
@ -16778,7 +16882,7 @@ var HandPipeline = class {
if (!currentBox)
continue;
if (config3.hand.landmarks) {
const angle = config3.hand.rotation ? computeRotation2(currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_PALM_BASE], currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE]) : 0;
const angle = config3.hand.rotation ? computeRotation2(currentBox.palmLandmarks[palmLandmarksPalmBase], currentBox.palmLandmarks[palmLandmarksMiddleFingerBase]) : 0;
const palmCenter = getBoxCenter2(currentBox);
const palmCenterNormalized = [palmCenter[0] / image11.shape[2], palmCenter[1] / image11.shape[1]];
const rotatedImage = config3.hand.rotation ? tf11.image.rotateWithOffset(image11, angle, 0, palmCenterNormalized) : image11.clone();
@ -16811,7 +16915,7 @@ var HandPipeline = class {
}
keypoints.dispose();
} else {
const enlarged = enlargeBox2(squarifyBox2(currentBox), HAND_BOX_ENLARGE_FACTOR);
const enlarged = enlargeBox2(squarifyBox2(currentBox), handBoxEnlargeFactor);
const result = {
confidence: currentBox.confidence,
box: {topLeft: enlarged.startPoint, bottomRight: enlarged.endPoint}
@ -16823,13 +16927,6 @@ var HandPipeline = class {
this.detectedHands = hands.length;
return hands;
}
calculateLandmarksBoundingBox(landmarks) {
const xs = landmarks.map((d) => d[0]);
const ys = landmarks.map((d) => d[1]);
const startPoint = [Math.min(...xs), Math.min(...ys)];
const endPoint = [Math.max(...xs), Math.max(...ys)];
return {startPoint, endPoint};
}
};
// src/handpose/handpose.ts
@ -18691,103 +18788,6 @@ async function all(inCanvas2, result, drawOptions) {
object(inCanvas2, result.object, localOptions);
}
// src/config.ts
var config2 = {
backend: "webgl",
modelBasePath: "../models/",
wasmPath: "../assets/",
debug: true,
async: true,
videoOptimized: true,
warmup: "full",
filter: {
enabled: true,
width: 0,
height: 0,
flip: false,
return: true,
brightness: 0,
contrast: 0,
sharpness: 0,
blur: 0,
saturation: 0,
hue: 0,
negative: false,
sepia: false,
vintage: false,
kodachrome: false,
technicolor: false,
polaroid: false,
pixelate: 0
},
gesture: {
enabled: true
},
face: {
enabled: true,
detector: {
modelPath: "blazeface.json",
rotation: false,
maxDetected: 10,
skipFrames: 21,
skipInitial: false,
minConfidence: 0.2,
iouThreshold: 0.1,
return: false
},
mesh: {
enabled: true,
modelPath: "facemesh.json"
},
iris: {
enabled: true,
modelPath: "iris.json"
},
description: {
enabled: true,
modelPath: "faceres.json",
skipFrames: 31,
minConfidence: 0.1
},
emotion: {
enabled: true,
minConfidence: 0.1,
skipFrames: 32,
modelPath: "emotion.json"
}
},
body: {
enabled: true,
modelPath: "posenet.json",
maxDetected: 1,
minConfidence: 0.1
},
hand: {
enabled: true,
rotation: false,
skipFrames: 12,
skipInitial: false,
minConfidence: 0.1,
iouThreshold: 0.1,
maxDetected: 1,
landmarks: true,
detector: {
modelPath: "handdetect.json"
},
skeleton: {
modelPath: "handskeleton.json"
}
},
object: {
enabled: false,
modelPath: "nanodet.json",
minConfidence: 0.2,
iouThreshold: 0.4,
maxDetected: 10,
skipFrames: 41
}
};
// src/sample.ts
var face3 = `
/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUA
@ -19512,7 +19512,7 @@ lBhEMohlFerLlBjEMohMVTEARDKCITsAk2AEgAAAkAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAD/
2Q==`;
// package.json
var version = "1.8.2";
var version = "1.8.3";
// src/human.ts
var _numTensors, _analyzeMemoryLeaks, _checkSanity, _firstRun, _sanity, _checkBackend, _warmupBitmap, _warmupCanvas, _warmupNode;
@ -19675,7 +19675,7 @@ var Human = class {
this.tf = tf16;
this.draw = draw_exports;
this.version = version;
this.config = mergeDeep(config2, userConfig);
this.config = mergeDeep(config, userConfig);
this.state = "idle";
__privateSet(this, _numTensors, 0);
__privateSet(this, _analyzeMemoryLeaks, false);

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,493 +1,17 @@
2021-04-15 09:36:00 INFO:  @vladmandic/human version 1.5.2
2021-04-15 09:36:00 INFO:  User: vlado Platform: linux Arch: x64 Node: v15.7.0
2021-04-15 09:36:00 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-15 09:36:00 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-15 09:36:00 STATE: Build for: node type: node: {"imports":46,"importBytes":545147,"outputBytes":304326,"outputFiles":"dist/human.node.js"}
2021-04-15 09:36:00 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-15 09:36:00 STATE: Build for: nodeGPU type: node: {"imports":46,"importBytes":545151,"outputBytes":304334,"outputFiles":"dist/human.node-gpu.js"}
2021-04-15 09:36:00 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-15 09:36:00 STATE: Build for: nodeWASM type: node: {"imports":46,"importBytes":545197,"outputBytes":304378,"outputFiles":"dist/human.node-wasm.js"}
2021-04-15 09:36:00 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-15 09:36:00 STATE: Build for: browserNoBundle type: esm: {"imports":46,"importBytes":545808,"outputBytes":304324,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-15 09:36:01 STATE: Build for: browserBundle type: tfjs: {"modules":1262,"moduleBytes":4068263,"imports":7,"importBytes":2488,"outputBytes":1097287,"outputFiles":"dist/tfjs.esm.js"}
2021-04-15 09:36:01 STATE: Build for: browserBundle type: iife: {"imports":46,"importBytes":1641701,"outputBytes":1397747,"outputFiles":"dist/human.js"}
2021-04-15 09:36:02 STATE: Build for: browserBundle type: esm: {"imports":46,"importBytes":1641701,"outputBytes":1397705,"outputFiles":"dist/human.esm.js"}
2021-04-15 09:36:02 INFO:  Generate types: ["src/human.ts"]
2021-04-15 09:36:07 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-15 09:36:07 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-15 09:40:34 INFO:  @vladmandic/human version 1.5.2
2021-04-15 09:40:34 INFO:  User: vlado Platform: linux Arch: x64 Node: v15.7.0
2021-04-15 09:40:34 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-15 09:40:34 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-15 09:40:34 STATE: Build for: node type: node: {"imports":46,"importBytes":545147,"outputBytes":304326,"outputFiles":"dist/human.node.js"}
2021-04-15 09:40:34 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-15 09:40:35 STATE: Build for: nodeGPU type: node: {"imports":46,"importBytes":545151,"outputBytes":304334,"outputFiles":"dist/human.node-gpu.js"}
2021-04-15 09:40:35 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-15 09:40:35 STATE: Build for: nodeWASM type: node: {"imports":46,"importBytes":545197,"outputBytes":304378,"outputFiles":"dist/human.node-wasm.js"}
2021-04-15 09:40:35 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-15 09:40:35 STATE: Build for: browserNoBundle type: esm: {"imports":46,"importBytes":545808,"outputBytes":304324,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-15 09:40:35 STATE: Build for: browserBundle type: tfjs: {"modules":1262,"moduleBytes":4068263,"imports":7,"importBytes":2488,"outputBytes":1097287,"outputFiles":"dist/tfjs.esm.js"}
2021-04-15 09:40:36 STATE: Build for: browserBundle type: iife: {"imports":46,"importBytes":1641701,"outputBytes":1397747,"outputFiles":"dist/human.js"}
2021-04-15 09:40:36 STATE: Build for: browserBundle type: esm: {"imports":46,"importBytes":1641701,"outputBytes":1397705,"outputFiles":"dist/human.esm.js"}
2021-04-15 09:40:36 INFO:  Generate types: ["src/human.ts"]
2021-04-15 09:40:41 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-15 09:40:41 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-16 18:02:35 INFO:  @vladmandic/human version 1.5.2
2021-04-16 18:02:35 INFO:  User: vlado Platform: linux Arch: x64 Node: v15.7.0
2021-04-16 18:02:35 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-16 18:02:36 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-16 18:02:36 STATE: Build for: node type: node: {"imports":46,"importBytes":545147,"outputBytes":304326,"outputFiles":"dist/human.node.js"}
2021-04-16 18:02:36 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-16 18:02:36 STATE: Build for: nodeGPU type: node: {"imports":46,"importBytes":545151,"outputBytes":304334,"outputFiles":"dist/human.node-gpu.js"}
2021-04-16 18:02:36 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-16 18:02:36 STATE: Build for: nodeWASM type: node: {"imports":46,"importBytes":545197,"outputBytes":304378,"outputFiles":"dist/human.node-wasm.js"}
2021-04-16 18:02:36 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-16 18:02:36 STATE: Build for: browserNoBundle type: esm: {"imports":46,"importBytes":545808,"outputBytes":304324,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-16 18:02:36 STATE: Build for: browserBundle type: tfjs: {"modules":1262,"moduleBytes":4068263,"imports":7,"importBytes":2488,"outputBytes":1097287,"outputFiles":"dist/tfjs.esm.js"}
2021-04-16 18:02:37 STATE: Build for: browserBundle type: iife: {"imports":46,"importBytes":1641701,"outputBytes":1397747,"outputFiles":"dist/human.js"}
2021-04-16 18:02:37 STATE: Build for: browserBundle type: esm: {"imports":46,"importBytes":1641701,"outputBytes":1397705,"outputFiles":"dist/human.esm.js"}
2021-04-16 18:02:37 INFO:  Generate types: ["src/human.ts"]
2021-04-16 18:02:43 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-16 18:02:43 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-18 19:33:07 INFO:  @vladmandic/human version 1.6.0
2021-04-18 19:33:07 INFO:  User: vlado Platform: linux Arch: x64 Node: v15.7.0
2021-04-18 19:33:07 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-18 19:33:07 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-18 19:33:07 STATE: Build for: node type: node: {"imports":46,"importBytes":546322,"outputBytes":304931,"outputFiles":"dist/human.node.js"}
2021-04-18 19:33:07 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-18 19:33:07 STATE: Build for: nodeGPU type: node: {"imports":46,"importBytes":546326,"outputBytes":304939,"outputFiles":"dist/human.node-gpu.js"}
2021-04-18 19:33:07 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-18 19:33:07 STATE: Build for: nodeWASM type: node: {"imports":46,"importBytes":546372,"outputBytes":304983,"outputFiles":"dist/human.node-wasm.js"}
2021-04-18 19:33:07 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-18 19:33:07 STATE: Build for: browserNoBundle type: esm: {"imports":46,"importBytes":546983,"outputBytes":304929,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-18 19:33:08 STATE: Build for: browserBundle type: tfjs: {"modules":1262,"moduleBytes":4068263,"imports":7,"importBytes":2488,"outputBytes":1097287,"outputFiles":"dist/tfjs.esm.js"}
2021-04-18 19:33:08 STATE: Build for: browserBundle type: iife: {"imports":46,"importBytes":1642876,"outputBytes":1398352,"outputFiles":"dist/human.js"}
2021-04-18 19:33:09 STATE: Build for: browserBundle type: esm: {"imports":46,"importBytes":1642876,"outputBytes":1398310,"outputFiles":"dist/human.esm.js"}
2021-04-18 19:33:09 INFO:  Generate types: ["src/human.ts"]
2021-04-18 19:33:14 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-18 19:33:14 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-19 09:25:22 INFO:  @vladmandic/human version 1.6.0
2021-04-19 09:25:22 INFO:  User: vlado Platform: linux Arch: x64 Node: v15.7.0
2021-04-19 09:25:22 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-19 09:25:22 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-19 09:25:22 STATE: Build for: node type: node: {"imports":46,"importBytes":547188,"outputBytes":305386,"outputFiles":"dist/human.node.js"}
2021-04-19 09:25:22 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-19 09:25:22 STATE: Build for: nodeGPU type: node: {"imports":46,"importBytes":547192,"outputBytes":305394,"outputFiles":"dist/human.node-gpu.js"}
2021-04-19 09:25:22 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-19 09:25:23 STATE: Build for: nodeWASM type: node: {"imports":46,"importBytes":547238,"outputBytes":305438,"outputFiles":"dist/human.node-wasm.js"}
2021-04-19 09:25:23 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-19 09:25:23 STATE: Build for: browserNoBundle type: esm: {"imports":46,"importBytes":547849,"outputBytes":305385,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-19 09:25:23 STATE: Build for: browserBundle type: tfjs: {"modules":1262,"moduleBytes":4068263,"imports":7,"importBytes":2488,"outputBytes":1097287,"outputFiles":"dist/tfjs.esm.js"}
2021-04-19 09:25:24 STATE: Build for: browserBundle type: iife: {"imports":46,"importBytes":1643742,"outputBytes":1398814,"outputFiles":"dist/human.js"}
2021-04-19 09:25:24 STATE: Build for: browserBundle type: esm: {"imports":46,"importBytes":1643742,"outputBytes":1398772,"outputFiles":"dist/human.esm.js"}
2021-04-19 09:25:24 INFO:  Generate types: ["src/human.ts"]
2021-04-19 09:25:30 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-19 09:25:30 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-19 16:18:26 INFO:  @vladmandic/human version 1.6.0
2021-04-19 16:18:26 INFO:  User: vlado Platform: linux Arch: x64 Node: v15.7.0
2021-04-19 16:18:26 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-19 16:18:26 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-19 16:18:27 STATE: Build for: node type: node: {"imports":46,"importBytes":548010,"outputBytes":305576,"outputFiles":"dist/human.node.js"}
2021-04-19 16:18:27 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-19 16:18:27 STATE: Build for: nodeGPU type: node: {"imports":46,"importBytes":548014,"outputBytes":305584,"outputFiles":"dist/human.node-gpu.js"}
2021-04-19 16:18:27 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-19 16:18:27 STATE: Build for: nodeWASM type: node: {"imports":46,"importBytes":548060,"outputBytes":305628,"outputFiles":"dist/human.node-wasm.js"}
2021-04-19 16:18:27 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-19 16:18:27 STATE: Build for: browserNoBundle type: esm: {"imports":46,"importBytes":548671,"outputBytes":305575,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-19 16:18:27 STATE: Build for: browserBundle type: tfjs: {"modules":1262,"moduleBytes":4068263,"imports":7,"importBytes":2488,"outputBytes":1097287,"outputFiles":"dist/tfjs.esm.js"}
2021-04-19 16:18:28 STATE: Build for: browserBundle type: iife: {"imports":46,"importBytes":1644564,"outputBytes":1399008,"outputFiles":"dist/human.js"}
2021-04-19 16:18:28 STATE: Build for: browserBundle type: esm: {"imports":46,"importBytes":1644564,"outputBytes":1398966,"outputFiles":"dist/human.esm.js"}
2021-04-19 16:18:28 INFO:  Generate types: ["src/human.ts"]
2021-04-19 16:18:32 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-19 16:18:32 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-22 19:41:11 INFO:  @vladmandic/human version 1.6.0
2021-04-22 19:41:11 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-22 19:41:11 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-22 19:41:11 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-22 19:41:11 STATE: Build for: node type: node: {"imports":46,"importBytes":547988,"outputBytes":305576,"outputFiles":"dist/human.node.js"}
2021-04-22 19:41:11 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-22 19:41:11 STATE: Build for: nodeGPU type: node: {"imports":46,"importBytes":547992,"outputBytes":305584,"outputFiles":"dist/human.node-gpu.js"}
2021-04-22 19:41:11 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-22 19:41:11 STATE: Build for: nodeWASM type: node: {"imports":46,"importBytes":548038,"outputBytes":305628,"outputFiles":"dist/human.node-wasm.js"}
2021-04-22 19:41:11 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-22 19:41:12 STATE: Build for: browserNoBundle type: esm: {"imports":46,"importBytes":548649,"outputBytes":305575,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-22 19:41:12 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-22 19:41:13 STATE: Build for: browserBundle type: iife: {"imports":46,"importBytes":1648983,"outputBytes":1403464,"outputFiles":"dist/human.js"}
2021-04-22 19:41:13 STATE: Build for: browserBundle type: esm: {"imports":46,"importBytes":1648983,"outputBytes":1403422,"outputFiles":"dist/human.esm.js"}
2021-04-22 19:41:13 INFO:  Generate types: ["src/human.ts"]
2021-04-22 19:41:18 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-22 19:41:18 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-22 19:46:35 INFO:  @vladmandic/human version 1.6.1
2021-04-22 19:46:35 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-22 19:46:35 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-22 19:46:35 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-22 19:46:35 STATE: Build for: node type: node: {"imports":46,"importBytes":547988,"outputBytes":305576,"outputFiles":"dist/human.node.js"}
2021-04-22 19:46:35 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-22 19:46:35 STATE: Build for: nodeGPU type: node: {"imports":46,"importBytes":547992,"outputBytes":305584,"outputFiles":"dist/human.node-gpu.js"}
2021-04-22 19:46:35 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-22 19:46:35 STATE: Build for: nodeWASM type: node: {"imports":46,"importBytes":548038,"outputBytes":305628,"outputFiles":"dist/human.node-wasm.js"}
2021-04-22 19:46:35 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-22 19:46:35 STATE: Build for: browserNoBundle type: esm: {"imports":46,"importBytes":548649,"outputBytes":305575,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-22 19:46:36 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-22 19:46:36 STATE: Build for: browserBundle type: iife: {"imports":46,"importBytes":1648983,"outputBytes":1403464,"outputFiles":"dist/human.js"}
2021-04-22 19:46:37 STATE: Build for: browserBundle type: esm: {"imports":46,"importBytes":1648983,"outputBytes":1403422,"outputFiles":"dist/human.esm.js"}
2021-04-22 19:46:37 INFO:  Generate types: ["src/human.ts"]
2021-04-22 19:46:41 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-22 19:46:41 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-24 11:48:49 INFO:  @vladmandic/human version 1.6.1
2021-04-24 11:48:49 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-24 11:48:49 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-24 11:48:49 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 11:48:49 STATE: Build for: node type: node: {"imports":43,"importBytes":547909,"outputBytes":306333,"outputFiles":"dist/human.node.js"}
2021-04-24 11:48:49 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 11:48:49 STATE: Build for: nodeGPU type: node: {"imports":43,"importBytes":547913,"outputBytes":306341,"outputFiles":"dist/human.node-gpu.js"}
2021-04-24 11:48:49 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 11:48:49 STATE: Build for: nodeWASM type: node: {"imports":43,"importBytes":547959,"outputBytes":306385,"outputFiles":"dist/human.node-wasm.js"}
2021-04-24 11:48:49 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 11:48:49 STATE: Build for: browserNoBundle type: esm: {"imports":43,"importBytes":548570,"outputBytes":306337,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-24 11:48:50 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 11:48:51 STATE: Build for: browserBundle type: iife: {"imports":43,"importBytes":1648904,"outputBytes":1404224,"outputFiles":"dist/human.js"}
2021-04-24 11:48:51 STATE: Build for: browserBundle type: esm: {"imports":43,"importBytes":1648904,"outputBytes":1404182,"outputFiles":"dist/human.esm.js"}
2021-04-24 11:48:51 INFO:  Generate types: ["src/human.ts"]
2021-04-24 11:48:56 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-24 11:48:56 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-24 16:00:49 INFO:  @vladmandic/human version 1.6.1
2021-04-24 16:00:49 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-24 16:00:49 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-24 16:00:49 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 16:00:49 STATE: Build for: node type: node: {"imports":40,"importBytes":542104,"outputBytes":304213,"outputFiles":"dist/human.node.js"}
2021-04-24 16:00:49 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 16:00:49 STATE: Build for: nodeGPU type: node: {"imports":40,"importBytes":542108,"outputBytes":304221,"outputFiles":"dist/human.node-gpu.js"}
2021-04-24 16:00:49 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 16:00:49 STATE: Build for: nodeWASM type: node: {"imports":40,"importBytes":542154,"outputBytes":304265,"outputFiles":"dist/human.node-wasm.js"}
2021-04-24 16:00:49 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 16:00:49 STATE: Build for: browserNoBundle type: esm: {"imports":40,"importBytes":542765,"outputBytes":304246,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-24 16:00:50 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 16:00:51 STATE: Build for: browserBundle type: iife: {"imports":40,"importBytes":1643099,"outputBytes":1402155,"outputFiles":"dist/human.js"}
2021-04-24 16:00:51 STATE: Build for: browserBundle type: esm: {"imports":40,"importBytes":1643099,"outputBytes":1402113,"outputFiles":"dist/human.esm.js"}
2021-04-24 16:00:51 INFO:  Generate types: ["src/human.ts"]
2021-04-24 16:00:57 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-24 16:00:57 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-24 16:03:56 INFO:  @vladmandic/human version 1.6.1
2021-04-24 16:03:56 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-24 16:03:56 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-24 16:03:56 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 16:03:56 STATE: Build for: node type: node: {"imports":40,"importBytes":542082,"outputBytes":304213,"outputFiles":"dist/human.node.js"}
2021-04-24 16:03:56 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 16:03:57 STATE: Build for: nodeGPU type: node: {"imports":40,"importBytes":542086,"outputBytes":304221,"outputFiles":"dist/human.node-gpu.js"}
2021-04-24 16:03:57 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 16:03:57 STATE: Build for: nodeWASM type: node: {"imports":40,"importBytes":542132,"outputBytes":304265,"outputFiles":"dist/human.node-wasm.js"}
2021-04-24 16:03:57 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 16:03:57 STATE: Build for: browserNoBundle type: esm: {"imports":40,"importBytes":542743,"outputBytes":304246,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-24 16:03:57 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 16:03:58 STATE: Build for: browserBundle type: iife: {"imports":40,"importBytes":1643077,"outputBytes":1402155,"outputFiles":"dist/human.js"}
2021-04-24 16:03:58 STATE: Build for: browserBundle type: esm: {"imports":40,"importBytes":1643077,"outputBytes":1402113,"outputFiles":"dist/human.esm.js"}
2021-04-24 16:03:58 INFO:  Generate types: ["src/human.ts"]
2021-04-24 16:04:03 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-24 16:04:03 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-24 18:43:24 INFO:  @vladmandic/human version 1.7.0
2021-04-24 18:43:24 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-24 18:43:24 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-24 18:43:24 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 18:43:24 STATE: Build for: node type: node: {"imports":36,"importBytes":521048,"outputBytes":296170,"outputFiles":"dist/human.node.js"}
2021-04-24 18:43:24 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 18:43:24 STATE: Build for: nodeGPU type: node: {"imports":36,"importBytes":521052,"outputBytes":296178,"outputFiles":"dist/human.node-gpu.js"}
2021-04-24 18:43:24 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 18:43:24 STATE: Build for: nodeWASM type: node: {"imports":36,"importBytes":521098,"outputBytes":296222,"outputFiles":"dist/human.node-wasm.js"}
2021-04-24 18:43:24 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 18:43:24 STATE: Build for: browserNoBundle type: esm: {"imports":36,"importBytes":521709,"outputBytes":296317,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-24 18:43:25 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 18:43:25 STATE: Build for: browserBundle type: iife: {"imports":36,"importBytes":1622043,"outputBytes":1394426,"outputFiles":"dist/human.js"}
2021-04-24 18:43:26 STATE: Build for: browserBundle type: esm: {"imports":36,"importBytes":1622043,"outputBytes":1394384,"outputFiles":"dist/human.esm.js"}
2021-04-24 18:43:26 INFO:  Generate types: ["src/human.ts"]
2021-04-24 18:43:31 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-24 18:43:31 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-25 07:49:35 INFO:  @vladmandic/human version 1.7.0
2021-04-25 07:49:35 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-25 07:49:35 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-25 07:49:36 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 07:49:36 STATE: Build for: node type: node: {"imports":36,"importBytes":521379,"outputBytes":296354,"outputFiles":"dist/human.node.js"}
2021-04-25 07:49:36 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 07:49:36 STATE: Build for: nodeGPU type: node: {"imports":36,"importBytes":521383,"outputBytes":296362,"outputFiles":"dist/human.node-gpu.js"}
2021-04-25 07:49:36 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 07:49:36 STATE: Build for: nodeWASM type: node: {"imports":36,"importBytes":521429,"outputBytes":296406,"outputFiles":"dist/human.node-wasm.js"}
2021-04-25 07:49:36 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 07:49:36 STATE: Build for: browserNoBundle type: esm: {"imports":36,"importBytes":522040,"outputBytes":296501,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-25 07:49:37 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 07:49:37 STATE: Build for: browserBundle type: iife: {"imports":36,"importBytes":1622374,"outputBytes":1394611,"outputFiles":"dist/human.js"}
2021-04-25 07:49:38 STATE: Build for: browserBundle type: esm: {"imports":36,"importBytes":1622374,"outputBytes":1394569,"outputFiles":"dist/human.esm.js"}
2021-04-25 07:49:38 INFO:  Generate types: ["src/human.ts"]
2021-04-25 07:49:43 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-25 07:49:43 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-25 07:50:15 INFO:  @vladmandic/human version 1.7.1
2021-04-25 07:50:15 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-25 07:50:15 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-25 07:50:15 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 07:50:15 STATE: Build for: node type: node: {"imports":36,"importBytes":521379,"outputBytes":296354,"outputFiles":"dist/human.node.js"}
2021-04-25 07:50:15 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 07:50:15 STATE: Build for: nodeGPU type: node: {"imports":36,"importBytes":521383,"outputBytes":296362,"outputFiles":"dist/human.node-gpu.js"}
2021-04-25 07:50:15 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 07:50:15 STATE: Build for: nodeWASM type: node: {"imports":36,"importBytes":521429,"outputBytes":296406,"outputFiles":"dist/human.node-wasm.js"}
2021-04-25 07:50:15 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 07:50:15 STATE: Build for: browserNoBundle type: esm: {"imports":36,"importBytes":522040,"outputBytes":296501,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-25 07:50:16 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 07:50:16 STATE: Build for: browserBundle type: iife: {"imports":36,"importBytes":1622374,"outputBytes":1394611,"outputFiles":"dist/human.js"}
2021-04-25 07:50:17 STATE: Build for: browserBundle type: esm: {"imports":36,"importBytes":1622374,"outputBytes":1394569,"outputFiles":"dist/human.esm.js"}
2021-04-25 07:50:17 INFO:  Generate types: ["src/human.ts"]
2021-04-25 07:50:22 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-25 07:50:22 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-25 13:08:21 INFO:  @vladmandic/human version 1.7.1
2021-04-25 13:08:21 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-25 13:08:21 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-25 13:08:21 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:08:21 STATE: Build for: node type: node: {"imports":35,"importBytes":514895,"outputBytes":294872,"outputFiles":"dist/human.node.js"}
2021-04-25 13:08:21 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:08:21 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":514899,"outputBytes":294880,"outputFiles":"dist/human.node-gpu.js"}
2021-04-25 13:08:21 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:08:21 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":514945,"outputBytes":294924,"outputFiles":"dist/human.node-wasm.js"}
2021-04-25 13:08:21 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:08:21 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":515556,"outputBytes":295030,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-25 13:08:22 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:08:23 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1615890,"outputBytes":1393163,"outputFiles":"dist/human.js"}
2021-04-25 13:08:23 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1615890,"outputBytes":1393121,"outputFiles":"dist/human.esm.js"}
2021-04-25 13:08:23 INFO:  Generate types: ["src/human.ts"]
2021-04-25 13:08:28 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-25 13:08:28 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-25 13:13:05 INFO:  @vladmandic/human version 1.8.0
2021-04-25 13:13:05 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-25 13:13:05 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-25 13:13:05 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:13:05 STATE: Build for: node type: node: {"imports":35,"importBytes":514858,"outputBytes":294833,"outputFiles":"dist/human.node.js"}
2021-04-25 13:13:05 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:13:05 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":514862,"outputBytes":294837,"outputFiles":"dist/human.node-gpu.js"}
2021-04-25 13:13:05 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:13:06 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":514908,"outputBytes":294880,"outputFiles":"dist/human.node-wasm.js"}
2021-04-25 13:13:06 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:13:06 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":515556,"outputBytes":295030,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-25 13:13:06 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:13:07 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1615890,"outputBytes":1393163,"outputFiles":"dist/human.js"}
2021-04-25 13:13:08 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1615890,"outputBytes":1393121,"outputFiles":"dist/human.esm.js"}
2021-04-25 13:13:08 INFO:  Generate types: ["src/human.ts"]
2021-04-25 13:13:12 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-25 13:13:12 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-25 13:58:37 INFO:  @vladmandic/human version 1.8.0
2021-04-25 13:58:37 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-25 13:58:37 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-25 13:58:37 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:58:37 STATE: Build for: node type: node: {"imports":35,"importBytes":514853,"outputBytes":294828,"outputFiles":"dist/human.node.js"}
2021-04-25 13:58:37 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:58:37 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":514857,"outputBytes":294832,"outputFiles":"dist/human.node-gpu.js"}
2021-04-25 13:58:37 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:58:37 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":514903,"outputBytes":294875,"outputFiles":"dist/human.node-wasm.js"}
2021-04-25 13:58:37 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:58:37 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":515551,"outputBytes":295025,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-25 13:58:38 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 13:58:39 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1615885,"outputBytes":1393158,"outputFiles":"dist/human.js"}
2021-04-25 13:58:40 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1615885,"outputBytes":1393116,"outputFiles":"dist/human.esm.js"}
2021-04-25 13:58:40 INFO:  Generate types: ["src/human.ts"]
2021-04-25 13:58:44 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-25 13:58:44 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-25 14:02:03 INFO:  @vladmandic/human version 1.8.0
2021-04-25 14:02:03 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-25 14:02:03 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-04-25 14:02:03 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:02:03 STATE: Build for: node type: node: {"imports":35,"importBytes":514853,"outputBytes":474171,"outputFiles":"dist/human.node.js"}
2021-04-25 14:02:03 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:02:03 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":514857,"outputBytes":474175,"outputFiles":"dist/human.node-gpu.js"}
2021-04-25 14:02:03 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:02:03 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":514903,"outputBytes":474225,"outputFiles":"dist/human.node-wasm.js"}
2021-04-25 14:02:03 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:02:03 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":515551,"outputBytes":295025,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-25 14:02:04 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:02:04 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1615885,"outputBytes":1393158,"outputFiles":"dist/human.js"}
2021-04-25 14:02:05 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1615885,"outputBytes":1393116,"outputFiles":"dist/human.esm.js"}
2021-04-25 14:02:05 INFO:  Generate types: ["src/human.ts"]
2021-04-25 14:02:09 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-25 14:02:09 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-25 14:09:15 INFO:  @vladmandic/human version 1.8.0
2021-04-25 14:09:15 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-25 14:09:15 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-04-25 14:09:15 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:09:15 STATE: Build for: node type: node: {"imports":35,"importBytes":514853,"outputBytes":474171,"outputFiles":"dist/human.node.js"}
2021-04-25 14:09:15 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:09:15 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":514857,"outputBytes":474175,"outputFiles":"dist/human.node-gpu.js"}
2021-04-25 14:09:15 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:09:15 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":514903,"outputBytes":474225,"outputFiles":"dist/human.node-wasm.js"}
2021-04-25 14:09:15 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:09:15 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":515551,"outputBytes":295025,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-25 14:09:16 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:09:16 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1615885,"outputBytes":1393158,"outputFiles":"dist/human.js"}
2021-04-25 14:09:17 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1615885,"outputBytes":1393116,"outputFiles":"dist/human.esm.js"}
2021-04-25 14:09:17 INFO:  Generate types: ["src/human.ts"]
2021-04-25 14:09:21 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-25 14:09:21 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-25 14:28:38 INFO:  @vladmandic/human version 1.8.0
2021-04-25 14:28:38 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-25 14:28:38 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-04-25 14:28:38 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:28:38 STATE: Build for: node type: node: {"imports":35,"importBytes":514853,"outputBytes":474171,"outputFiles":"dist/human.node.js"}
2021-04-25 14:28:38 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:28:38 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":514857,"outputBytes":474175,"outputFiles":"dist/human.node-gpu.js"}
2021-04-25 14:28:38 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:28:38 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":514903,"outputBytes":474225,"outputFiles":"dist/human.node-wasm.js"}
2021-04-25 14:28:38 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:28:39 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":515551,"outputBytes":295025,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-25 14:28:39 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 14:28:40 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1615885,"outputBytes":1393158,"outputFiles":"dist/human.js"}
2021-04-25 14:28:40 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1615885,"outputBytes":1393116,"outputFiles":"dist/human.esm.js"}
2021-04-25 14:28:40 INFO:  Generate types: ["src/human.ts"]
2021-04-25 14:28:45 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-25 14:28:45 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-25 16:54:54 INFO:  @vladmandic/human version 1.8.0
2021-04-25 16:54:54 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-25 16:54:54 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-04-25 16:54:54 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 16:54:54 STATE: Build for: node type: node: {"imports":35,"importBytes":414277,"outputBytes":373298,"outputFiles":"dist/human.node.js"}
2021-04-25 16:54:54 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 16:54:54 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":414281,"outputBytes":373302,"outputFiles":"dist/human.node-gpu.js"}
2021-04-25 16:54:54 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 16:54:54 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":414327,"outputBytes":373352,"outputFiles":"dist/human.node-wasm.js"}
2021-04-25 16:54:54 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 16:54:54 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":414975,"outputBytes":229880,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-25 16:54:55 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-25 16:54:56 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1515309,"outputBytes":1328044,"outputFiles":"dist/human.js"}
2021-04-25 16:54:56 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1515309,"outputBytes":1328002,"outputFiles":"dist/human.esm.js"}
2021-04-25 16:54:56 INFO:  Generate types: ["src/human.ts"]
2021-04-25 16:55:01 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-25 16:55:01 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-26 07:18:22 INFO:  @vladmandic/human version 1.8.0
2021-04-26 07:18:22 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-26 07:18:22 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-04-26 07:18:22 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-26 07:18:22 STATE: Build for: node type: node: {"imports":35,"importBytes":414277,"outputBytes":373298,"outputFiles":"dist/human.node.js"}
2021-04-26 07:18:22 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-26 07:18:22 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":414281,"outputBytes":373302,"outputFiles":"dist/human.node-gpu.js"}
2021-04-26 07:18:22 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-26 07:18:22 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":414327,"outputBytes":373352,"outputFiles":"dist/human.node-wasm.js"}
2021-04-26 07:18:22 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-26 07:18:22 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":414975,"outputBytes":229880,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-26 07:18:23 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-26 07:18:24 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1515309,"outputBytes":1328044,"outputFiles":"dist/human.js"}
2021-04-26 07:18:24 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1515309,"outputBytes":1328002,"outputFiles":"dist/human.esm.js"}
2021-04-26 07:18:24 INFO:  Generate types: ["src/human.ts"]
2021-04-26 07:18:30 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-26 07:18:30 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-26 07:36:49 INFO:  @vladmandic/human version 1.8.0
2021-04-26 07:36:49 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-26 07:36:49 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-04-26 07:36:49 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-26 07:36:50 STATE: Build for: node type: node: {"imports":35,"importBytes":415008,"outputBytes":374028,"outputFiles":"dist/human.node.js"}
2021-04-26 07:36:50 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-26 07:36:50 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":415012,"outputBytes":374032,"outputFiles":"dist/human.node-gpu.js"}
2021-04-26 07:36:50 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-26 07:36:50 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":415058,"outputBytes":374082,"outputFiles":"dist/human.node-wasm.js"}
2021-04-26 07:36:50 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-26 07:36:50 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":415706,"outputBytes":230290,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-26 07:36:51 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-26 07:36:51 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1516040,"outputBytes":1328454,"outputFiles":"dist/human.js"}
2021-04-26 07:36:52 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1516040,"outputBytes":1328412,"outputFiles":"dist/human.esm.js"}
2021-04-26 07:36:52 INFO:  Generate types: ["src/human.ts"]
2021-04-26 07:36:56 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-26 07:36:56 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-28 08:55:38 INFO:  @vladmandic/human version 1.8.0
2021-04-28 08:55:39 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-28 08:55:39 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-04-28 08:55:39 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-28 08:55:39 STATE: Build for: node type: node: {"imports":35,"importBytes":414922,"outputBytes":373580,"outputFiles":"dist/human.node.js"}
2021-04-28 08:55:39 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-28 08:55:39 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":414926,"outputBytes":373584,"outputFiles":"dist/human.node-gpu.js"}
2021-04-28 08:55:39 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-28 08:55:39 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":414972,"outputBytes":373634,"outputFiles":"dist/human.node-wasm.js"}
2021-04-28 08:55:39 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-28 08:55:39 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":415620,"outputBytes":230233,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-28 08:55:40 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-28 08:55:40 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1515954,"outputBytes":1328406,"outputFiles":"dist/human.js"}
2021-04-28 08:55:41 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1515954,"outputBytes":1328364,"outputFiles":"dist/human.esm.js"}
2021-04-28 08:55:41 INFO:  Generate types: ["src/human.ts"]
2021-04-28 08:55:46 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-28 08:55:46 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-28 08:57:43 INFO:  @vladmandic/human version 1.8.0
2021-04-28 08:57:43 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-28 08:57:43 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-04-28 08:57:43 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-28 08:57:43 STATE: Build for: node type: node: {"imports":35,"importBytes":414920,"outputBytes":373580,"outputFiles":"dist/human.node.js"}
2021-04-28 08:57:43 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-28 08:57:43 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":414924,"outputBytes":373584,"outputFiles":"dist/human.node-gpu.js"}
2021-04-28 08:57:43 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-28 08:57:44 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":414970,"outputBytes":373634,"outputFiles":"dist/human.node-wasm.js"}
2021-04-28 08:57:44 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-28 08:57:44 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":415618,"outputBytes":230233,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-28 08:57:44 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-28 08:57:45 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1515952,"outputBytes":1328406,"outputFiles":"dist/human.js"}
2021-04-28 08:57:45 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1515952,"outputBytes":1328364,"outputFiles":"dist/human.esm.js"}
2021-04-28 08:57:45 INFO:  Generate types: ["src/human.ts"]
2021-04-28 08:57:51 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-28 08:57:51 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-30 11:54:11 INFO:  @vladmandic/human version 1.8.1
2021-04-30 11:54:11 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-30 11:54:11 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-04-30 11:54:11 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-04-30 11:54:11 STATE: Build for: node type: node: {"imports":35,"importBytes":414920,"outputBytes":373580,"outputFiles":"dist/human.node.js"}
2021-04-30 11:54:11 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-04-30 11:54:11 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":414924,"outputBytes":373584,"outputFiles":"dist/human.node-gpu.js"}
2021-04-30 11:54:11 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-04-30 11:54:11 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":414970,"outputBytes":373634,"outputFiles":"dist/human.node-wasm.js"}
2021-04-30 11:54:11 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-30 11:54:11 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":415618,"outputBytes":230233,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-30 11:54:12 STATE: Build for: browserBundle type: tfjs: {"modules":1274,"moduleBytes":4114813,"imports":7,"importBytes":2488,"outputBytes":1111306,"outputFiles":"dist/tfjs.esm.js"}
2021-04-30 11:54:13 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1525530,"outputBytes":1337943,"outputFiles":"dist/human.js"}
2021-04-30 11:54:13 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1525530,"outputBytes":1337901,"outputFiles":"dist/human.esm.js"}
2021-04-30 11:54:13 INFO:  Generate types: ["src/human.ts"]
2021-04-30 11:54:17 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-30 11:54:17 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-05-04 11:17:13 INFO:  @vladmandic/human version 1.8.1
2021-05-04 11:17:13 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-05-04 11:17:13 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-05-04 11:17:13 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 11:17:14 STATE: Build for: node type: node: {"imports":35,"importBytes":414920,"outputBytes":373580,"outputFiles":"dist/human.node.js"}
2021-05-04 11:17:14 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 11:17:14 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":414924,"outputBytes":373584,"outputFiles":"dist/human.node-gpu.js"}
2021-05-04 11:17:14 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 11:17:14 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":414970,"outputBytes":373634,"outputFiles":"dist/human.node-wasm.js"}
2021-05-04 11:17:14 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 11:17:14 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":415618,"outputBytes":230233,"outputFiles":"dist/human.esm-nobundle.js"}
2021-05-04 11:17:15 STATE: Build for: browserBundle type: tfjs: {"modules":1274,"moduleBytes":4114813,"imports":7,"importBytes":2488,"outputBytes":1111306,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 11:17:16 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1525530,"outputBytes":1337943,"outputFiles":"dist/human.js"}
2021-05-04 11:17:16 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1525530,"outputBytes":1337901,"outputFiles":"dist/human.esm.js"}
2021-05-04 11:17:16 INFO:  Generate types: ["src/human.ts"]
2021-05-04 11:17:23 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-05-04 11:17:23 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-05-04 11:17:53 INFO:  @vladmandic/human version 1.8.2
2021-05-04 11:17:53 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-05-04 11:17:53 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-05-04 11:17:53 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 11:17:53 STATE: Build for: node type: node: {"imports":35,"importBytes":414920,"outputBytes":373580,"outputFiles":"dist/human.node.js"}
2021-05-04 11:17:53 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 11:17:53 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":414924,"outputBytes":373584,"outputFiles":"dist/human.node-gpu.js"}
2021-05-04 11:17:53 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 11:17:53 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":414970,"outputBytes":373634,"outputFiles":"dist/human.node-wasm.js"}
2021-05-04 11:17:53 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 11:17:53 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":415618,"outputBytes":230233,"outputFiles":"dist/human.esm-nobundle.js"}
2021-05-04 11:17:54 STATE: Build for: browserBundle type: tfjs: {"modules":1274,"moduleBytes":4114813,"imports":7,"importBytes":2488,"outputBytes":1111306,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 11:17:55 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1525530,"outputBytes":1337943,"outputFiles":"dist/human.js"}
2021-05-04 11:17:56 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1525530,"outputBytes":1337901,"outputFiles":"dist/human.esm.js"}
2021-05-04 11:17:56 INFO:  Generate types: ["src/human.ts"]
2021-05-04 11:18:01 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-05-04 11:18:01 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-05-04 20:45:53 INFO:  @vladmandic/human version 1.8.2
2021-05-04 20:45:53 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-05-04 20:45:53 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-05-04 20:45:53 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 20:45:53 STATE: Build for: node type: node: {"imports":35,"importBytes":413741,"outputBytes":372378,"outputFiles":"dist/human.node.js"}
2021-05-04 20:45:53 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 20:45:53 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":413745,"outputBytes":372382,"outputFiles":"dist/human.node-gpu.js"}
2021-05-04 20:45:53 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 20:45:53 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":413791,"outputBytes":372432,"outputFiles":"dist/human.node-wasm.js"}
2021-05-04 20:45:53 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 20:45:53 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":414439,"outputBytes":229511,"outputFiles":"dist/human.esm-nobundle.js"}
2021-05-04 20:45:54 STATE: Build for: browserBundle type: tfjs: {"modules":1274,"moduleBytes":4114813,"imports":7,"importBytes":2488,"outputBytes":1111306,"outputFiles":"dist/tfjs.esm.js"}
2021-05-04 20:45:55 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1524351,"outputBytes":1337203,"outputFiles":"dist/human.js"}
2021-05-04 20:45:55 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1524351,"outputBytes":1337161,"outputFiles":"dist/human.esm.js"}
2021-05-04 20:45:55 INFO:  Generate types: ["src/human.ts"]
2021-05-04 20:46:01 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-05-04 20:46:01 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-05-05 10:06:54 INFO:  @vladmandic/human version 1.8.3
2021-05-05 10:06:54 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-05-05 10:06:54 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-05-05 10:06:54 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":696,"outputFiles":"dist/tfjs.esm.js"}
2021-05-05 10:06:54 STATE: Build for: node type: node: {"imports":35,"importBytes":412756,"outputBytes":371901,"outputFiles":"dist/human.node.js"}
2021-05-05 10:06:54 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":700,"outputFiles":"dist/tfjs.esm.js"}
2021-05-05 10:06:54 STATE: Build for: nodeGPU type: node: {"imports":35,"importBytes":412760,"outputBytes":371905,"outputFiles":"dist/human.node-gpu.js"}
2021-05-05 10:06:54 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":746,"outputFiles":"dist/tfjs.esm.js"}
2021-05-05 10:06:54 STATE: Build for: nodeWASM type: node: {"imports":35,"importBytes":412806,"outputBytes":371955,"outputFiles":"dist/human.node-wasm.js"}
2021-05-05 10:06:55 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-05-05 10:06:55 STATE: Build for: browserNoBundle type: esm: {"imports":35,"importBytes":413454,"outputBytes":229541,"outputFiles":"dist/human.esm-nobundle.js"}
2021-05-05 10:06:55 STATE: Build for: browserBundle type: tfjs: {"modules":1274,"moduleBytes":4114813,"imports":7,"importBytes":2488,"outputBytes":1111306,"outputFiles":"dist/tfjs.esm.js"}
2021-05-05 10:06:56 STATE: Build for: browserBundle type: iife: {"imports":35,"importBytes":1523366,"outputBytes":1337233,"outputFiles":"dist/human.js"}
2021-05-05 10:06:57 STATE: Build for: browserBundle type: esm: {"imports":35,"importBytes":1523366,"outputBytes":1337191,"outputFiles":"dist/human.esm.js"}
2021-05-05 10:06:57 INFO:  Generate types: ["src/human.ts"]
2021-05-05 10:07:01 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-05-05 10:07:01 INFO:  Generate TypeDocs: ["src/human.ts"]

95
server/signature.js Normal file
View File

@ -0,0 +1,95 @@
#!/usr/bin/env -S node --no-deprecation --trace-warnings
const fs = require('fs');
const path = require('path');
const log = require('@vladmandic/pilogger');
const tf = require('@tensorflow/tfjs-node');
async function analyzeGraph(modelPath) {
const model = await tf.loadGraphModel(`file://${modelPath}`);
log.info('graph model:', path.resolve(modelPath));
log.info('size:', tf.engine().memory());
const inputs = [];
if (model.modelSignature && model.modelSignature['inputs']) {
log.info('model inputs based on signature');
for (const [key, val] of Object.entries(model.modelSignature['inputs'])) {
const shape = val.tensorShape.dim.map((a) => parseInt(a.size));
inputs.push({ name: key, dtype: val.dtype, shape });
}
// @ts-ignore
} else if (model.executor.graph['inputs']) {
log.info('model inputs based on executor');
// @ts-ignore
for (const t of model.executor.graph['inputs']) {
inputs.push({ name: t.name, dtype: t.attrParams.dtype.value, shape: t.attrParams.shape.value });
}
} else {
log.warn('model inputs: cannot determine');
}
const outputs = [];
let i = 0;
if (model.modelSignature && model.modelSignature['outputs'] && Object.values(model.modelSignature['outputs'])[0].dtype) {
log.info('model outputs based on signature');
for (const [key, val] of Object.entries(model.modelSignature['outputs'])) {
const shape = val.tensorShape?.dim.map((a) => parseInt(a.size));
outputs.push({ id: i++, name: key, dytpe: val.dtype, shape });
}
// @ts-ignore
} else if (model.executor.graph['outputs']) {
log.info('model outputs based on executor');
// @ts-ignore
for (const t of model.executor.graph['outputs']) {
outputs.push({ id: i++, name: t.name, dtype: t.attrParams.dtype?.value || t.rawAttrs.T.type, shape: t.attrParams.shape?.value });
}
} else {
log.warn('model outputs: cannot determine');
}
log.data('inputs:', inputs);
log.data('outputs:', outputs);
}
async function analyzeSaved(modelPath) {
const meta = await tf.node.getMetaGraphsFromSavedModel(modelPath);
log.info('saved model:', path.resolve(modelPath));
const sign = Object.values(meta[0].signatureDefs)[0];
log.data('tags:', meta[0].tags);
log.data('signature:', Object.keys(meta[0].signatureDefs));
const inputs = Object.values(sign.inputs)[0];
// @ts-ignore
const inputShape = inputs.shape?.map((a) => a.array[0]);
log.data('inputs:', { name: inputs.name, dtype: inputs.dtype, shape: inputShape });
const outputs = [];
let i = 0;
for (const [key, val] of Object.entries(sign.outputs)) {
// @ts-ignore
const shape = val.shape?.map((a) => a.array[0]);
outputs.push({ id: i++, name: key, dytpe: val.dtype, shape });
}
log.data('outputs:', outputs);
}
async function main() {
log.header();
const param = process.argv[2];
if (process.argv.length !== 3) {
log.error('path required');
process.exit(0);
} else if (!fs.existsSync(param)) {
log.error(`path does not exist: ${param}`);
process.exit(0);
}
const stat = fs.statSync(param);
log.data('created on:', stat.birthtime);
if (stat.isFile()) {
if (param.endsWith('.json')) analyzeGraph(param);
}
if (stat.isDirectory()) {
if (fs.existsSync(path.join(param, '/saved_model.pb'))) analyzeSaved(param);
if (fs.existsSync(path.join(param, '/model.json'))) analyzeGraph(path.join(param, '/model.json'));
}
}
main();

View File

@ -318,7 +318,7 @@ const config: Config = {
// should skipFrames be reset immediately to force new detection cycle
minConfidence: 0.1, // threshold for discarding a prediction
iouThreshold: 0.1, // ammount of overlap between two detected objects before one object is removed
maxDetected: 1, // maximum number of hands detected in the input
maxDetected: 2, // maximum number of hands detected in the input
// should be set to the minimum number for performance
landmarks: true, // detect hand landmarks or just hand boundary box
detector: {

View File

@ -2,13 +2,11 @@ import * as tf from '../../dist/tfjs.esm.js';
import * as box from './box';
import * as util from './util';
// const PALM_BOX_SHIFT_VECTOR = [0, -0.4];
const PALM_BOX_ENLARGE_FACTOR = 5; // default 3
// const HAND_BOX_SHIFT_VECTOR = [0, -0.1]; // move detected hand box by x,y to ease landmark detection
const HAND_BOX_ENLARGE_FACTOR = 1.65; // default 1.65
const PALM_LANDMARK_IDS = [0, 5, 9, 13, 17, 1, 2];
const PALM_LANDMARKS_INDEX_OF_PALM_BASE = 0;
const PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE = 2;
const palmBoxEnlargeFactor = 5; // default 3
const handBoxEnlargeFactor = 1.65; // default 1.65
const palmLandmarkIds = [0, 5, 9, 13, 17, 1, 2];
const palmLandmarksPalmBase = 0;
const palmLandmarksMiddleFingerBase = 2;
export class HandPipeline {
handDetector: any;
@ -27,20 +25,27 @@ export class HandPipeline {
this.detectedHands = 0;
}
// eslint-disable-next-line class-methods-use-this
calculateLandmarksBoundingBox(landmarks) {
const xs = landmarks.map((d) => d[0]);
const ys = landmarks.map((d) => d[1]);
const startPoint = [Math.min(...xs), Math.min(...ys)];
const endPoint = [Math.max(...xs), Math.max(...ys)];
return { startPoint, endPoint };
}
getBoxForPalmLandmarks(palmLandmarks, rotationMatrix) {
const rotatedPalmLandmarks = palmLandmarks.map((coord) => util.rotatePoint([...coord, 1], rotationMatrix));
const boxAroundPalm = this.calculateLandmarksBoundingBox(rotatedPalmLandmarks);
// return box.enlargeBox(box.squarifyBox(box.shiftBox(boxAroundPalm, PALM_BOX_SHIFT_VECTOR)), PALM_BOX_ENLARGE_FACTOR);
return box.enlargeBox(box.squarifyBox(boxAroundPalm), PALM_BOX_ENLARGE_FACTOR);
return box.enlargeBox(box.squarifyBox(boxAroundPalm), palmBoxEnlargeFactor);
}
getBoxForHandLandmarks(landmarks) {
const boundingBox = this.calculateLandmarksBoundingBox(landmarks);
// const boxAroundHand = box.enlargeBox(box.squarifyBox(box.shiftBox(boundingBox, HAND_BOX_SHIFT_VECTOR)), HAND_BOX_ENLARGE_FACTOR);
const boxAroundHand = box.enlargeBox(box.squarifyBox(boundingBox), HAND_BOX_ENLARGE_FACTOR);
const boxAroundHand = box.enlargeBox(box.squarifyBox(boundingBox), handBoxEnlargeFactor);
boxAroundHand.palmLandmarks = [];
for (let i = 0; i < PALM_LANDMARK_IDS.length; i++) {
boxAroundHand.palmLandmarks.push(landmarks[PALM_LANDMARK_IDS[i]].slice(0, 2));
for (let i = 0; i < palmLandmarkIds.length; i++) {
boxAroundHand.palmLandmarks.push(landmarks[palmLandmarkIds[i]].slice(0, 2));
}
return boxAroundHand;
}
@ -98,7 +103,7 @@ export class HandPipeline {
const currentBox = this.storedBoxes[i];
if (!currentBox) continue;
if (config.hand.landmarks) {
const angle = config.hand.rotation ? util.computeRotation(currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_PALM_BASE], currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE]) : 0;
const angle = config.hand.rotation ? util.computeRotation(currentBox.palmLandmarks[palmLandmarksPalmBase], currentBox.palmLandmarks[palmLandmarksMiddleFingerBase]) : 0;
const palmCenter = box.getBoxCenter(currentBox);
const palmCenterNormalized = [palmCenter[0] / image.shape[2], palmCenter[1] / image.shape[1]];
const rotatedImage = config.hand.rotation ? tf.image.rotateWithOffset(image, angle, 0, palmCenterNormalized) : image.clone();
@ -131,8 +136,8 @@ export class HandPipeline {
}
keypoints.dispose();
} else {
// const enlarged = box.enlargeBox(box.squarifyBox(box.shiftBox(currentBox, HAND_BOX_SHIFT_VECTOR)), HAND_BOX_ENLARGE_FACTOR);
const enlarged = box.enlargeBox(box.squarifyBox(currentBox), HAND_BOX_ENLARGE_FACTOR);
// const enlarged = box.enlargeBox(box.squarifyBox(box.shiftBox(currentBox, HAND_BOX_SHIFT_VECTOR)), handBoxEnlargeFactor);
const enlarged = box.enlargeBox(box.squarifyBox(currentBox), handBoxEnlargeFactor);
const result = {
confidence: currentBox.confidence,
box: { topLeft: enlarged.startPoint, bottomRight: enlarged.endPoint },
@ -144,13 +149,4 @@ export class HandPipeline {
this.detectedHands = hands.length;
return hands;
}
// eslint-disable-next-line class-methods-use-this
calculateLandmarksBoundingBox(landmarks) {
const xs = landmarks.map((d) => d[0]);
const ys = landmarks.map((d) => d[1]);
const startPoint = [Math.min(...xs), Math.min(...ys)];
const endPoint = [Math.max(...xs), Math.max(...ys)];
return { startPoint, endPoint };
}
}

View File

@ -1,4 +1,6 @@
import { log, now, mergeDeep } from './helpers';
import { Config, defaults } from './config';
import { Result } from './result';
import * as sysinfo from './sysinfo';
import * as tf from '../dist/tfjs.esm.js';
import * as backend from './tfjs/backend';
@ -13,8 +15,6 @@ import * as nanodet from './nanodet/nanodet';
import * as gesture from './gesture/gesture';
import * as image from './image/image';
import * as draw from './draw/draw';
import { Config, defaults } from './config';
import { Result } from './result';
import * as sample from './sample';
import * as app from '../package.json';

View File

@ -5,7 +5,7 @@ const localMaximumRadius = 1;
const outputStride = 16;
const squaredNmsRadius = 50 ** 2;
function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scoresBuffer, offsets, displacements, offsetRefineStep = 2) {
function traverse(edgeId, sourceKeypoint, targetId, scores, offsets, displacements, offsetRefineStep = 2) {
const getDisplacement = (point) => ({
y: displacements.get(point.y, point.x, edgeId),
x: displacements.get(point.y, point.x, (displacements.shape[2] / 2) + edgeId),
@ -15,7 +15,7 @@ function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scor
x: utils.clamp(Math.round(point.x / outputStride), 0, width - 1),
});
const [height, width] = scoresBuffer.shape;
const [height, width] = scores.shape;
// Nearest neighbor interpolation for the source->target displacements.
const sourceKeypointIndices = getStridedIndexNearPoint(sourceKeypoint.position, height, width);
const displacement = getDisplacement(sourceKeypointIndices);
@ -23,49 +23,48 @@ function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scor
let targetKeypoint = displacedPoint;
for (let i = 0; i < offsetRefineStep; i++) {
const targetKeypointIndices = getStridedIndexNearPoint(targetKeypoint, height, width);
const offsetPoint = utils.getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetKeypointId, offsets);
targetKeypoint = utils.addVectors({
x: targetKeypointIndices.x * outputStride,
y: targetKeypointIndices.y * outputStride,
}, { x: offsetPoint.x, y: offsetPoint.y });
const offsetPoint = utils.getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetId, offsets);
targetKeypoint = utils.addVectors(
{ x: targetKeypointIndices.x * outputStride, y: targetKeypointIndices.y * outputStride },
{ x: offsetPoint.x, y: offsetPoint.y },
);
}
const targetKeyPointIndices = getStridedIndexNearPoint(targetKeypoint, height, width);
const score = scoresBuffer.get(targetKeyPointIndices.y, targetKeyPointIndices.x, targetKeypointId);
return { position: targetKeypoint, part: kpt.partNames[targetKeypointId], score };
const score = scores.get(targetKeyPointIndices.y, targetKeyPointIndices.x, targetId);
return { position: targetKeypoint, part: kpt.partNames[targetId], score };
}
export function decodePose(root, scores, offsets, displacementsFwd, displacementsBwd) {
const parentChildrenTuples = kpt.poseChain.map(([parentJoinName, childJoinName]) => ([kpt.partIds[parentJoinName], kpt.partIds[childJoinName]]));
const parentToChildEdges = parentChildrenTuples.map(([, childJointId]) => childJointId);
const childToParentEdges = parentChildrenTuples.map(([parentJointId]) => parentJointId);
const tuples = kpt.poseChain.map(([parentJoinName, childJoinName]) => ([kpt.partIds[parentJoinName], kpt.partIds[childJoinName]]));
const edgesFwd = tuples.map(([, childJointId]) => childJointId);
const edgesBwd = tuples.map(([parentJointId]) => parentJointId);
const numParts = scores.shape[2]; // [21,21,17]
const numEdges = parentToChildEdges.length;
const instanceKeypoints = new Array(numParts);
const numEdges = edgesFwd.length;
const keypoints = new Array(numParts);
// Start a new detection instance at the position of the root.
// const { part: rootPart, score: rootScore } = root;
const rootPoint = utils.getImageCoords(root.part, outputStride, offsets);
instanceKeypoints[root.part.id] = {
keypoints[root.part.id] = {
score: root.score,
part: kpt.partNames[root.part.id],
position: rootPoint,
};
// Decode the part positions upwards in the tree, following the backward displacements.
for (let edge = numEdges - 1; edge >= 0; --edge) {
const sourceKeypointId = parentToChildEdges[edge];
const targetKeypointId = childToParentEdges[edge];
if (instanceKeypoints[sourceKeypointId] && !instanceKeypoints[targetKeypointId]) {
instanceKeypoints[targetKeypointId] = traverseToTargetKeypoint(edge, instanceKeypoints[sourceKeypointId], targetKeypointId, scores, offsets, displacementsBwd);
const sourceId = edgesFwd[edge];
const targetId = edgesBwd[edge];
if (keypoints[sourceId] && !keypoints[targetId]) {
keypoints[targetId] = traverse(edge, keypoints[sourceId], targetId, scores, offsets, displacementsBwd);
}
}
// Decode the part positions downwards in the tree, following the forward displacements.
for (let edge = 0; edge < numEdges; ++edge) {
const sourceKeypointId = childToParentEdges[edge];
const targetKeypointId = parentToChildEdges[edge];
if (instanceKeypoints[sourceKeypointId] && !instanceKeypoints[targetKeypointId]) {
instanceKeypoints[targetKeypointId] = traverseToTargetKeypoint(edge, instanceKeypoints[sourceKeypointId], targetKeypointId, scores, offsets, displacementsFwd);
const sourceId = edgesBwd[edge];
const targetId = edgesFwd[edge];
if (keypoints[sourceId] && !keypoints[targetId]) {
keypoints[targetId] = traverse(edge, keypoints[sourceId], targetId, scores, offsets, displacementsFwd);
}
}
return instanceKeypoints;
return keypoints;
}
function scoreIsMaximumInLocalWindow(keypointId, score, heatmapY, heatmapX, scores) {
@ -106,31 +105,32 @@ export function buildPartWithScoreQueue(minConfidence, scores) {
function withinRadius(poses, { x, y }, keypointId) {
return poses.some(({ keypoints }) => {
const correspondingKeypoint = keypoints[keypointId].position;
const correspondingKeypoint = keypoints[keypointId]?.position;
if (!correspondingKeypoint) return false;
return utils.squaredDistance(y, x, correspondingKeypoint.y, correspondingKeypoint.x) <= squaredNmsRadius;
});
}
function getInstanceScore(existingPoses, instanceKeypoints) {
const notOverlappedKeypointScores = instanceKeypoints.reduce((result, { position, score }, keypointId) => {
function getInstanceScore(existingPoses, keypoints) {
const notOverlappedKeypointScores = keypoints.reduce((result, { position, score }, keypointId) => {
if (!withinRadius(existingPoses, position, keypointId)) result += score;
return result;
}, 0.0);
return notOverlappedKeypointScores / instanceKeypoints.length;
return notOverlappedKeypointScores / keypoints.length;
}
export function decode(offsetsBuffer, scoresBuffer, displacementsFwdBuffer, displacementsBwdBuffer, maxDetected, minConfidence) {
export function decode(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence) {
const poses: Array<{ keypoints: any, box: any, score: number }> = [];
const queue = buildPartWithScoreQueue(minConfidence, scoresBuffer);
const queue = buildPartWithScoreQueue(minConfidence, scores);
// Generate at most maxDetected object instances per image in decreasing root part score order.
while (poses.length < maxDetected && !queue.empty()) {
// The top element in the queue is the next root candidate.
const root = queue.dequeue();
// Part-based non-maximum suppression: We reject a root candidate if it is within a disk of `nmsRadius` pixels from the corresponding part of a previously detected instance.
const rootImageCoords = utils.getImageCoords(root.part, outputStride, offsetsBuffer);
const rootImageCoords = utils.getImageCoords(root.part, outputStride, offsets);
if (withinRadius(poses, rootImageCoords, root.part.id)) continue;
// Else start a new detection instance at the position of the root.
let keypoints = decodePose(root, scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer);
let keypoints = decodePose(root, scores, offsets, displacementsFwd, displacementsBwd);
keypoints = keypoints.filter((a) => a.score > minConfidence);
const score = getInstanceScore(poses, keypoints);
const box = utils.getBoundingBox(keypoints);

View File

@ -39,7 +39,6 @@ export function scalePoses(poses, [height, width], [inputResolutionHeight, input
position: { x: Math.trunc(position.x * scaleX), y: Math.trunc(position.y * scaleY) },
})),
});
const scaledPoses = poses.map((pose) => scalePose(pose, height / inputResolutionHeight, width / inputResolutionWidth));
return scaledPoses;
}

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,10 @@ export declare class HandPipeline {
skipped: number;
detectedHands: number;
constructor(handDetector: any, landmarkDetector: any);
calculateLandmarksBoundingBox(landmarks: any): {
startPoint: number[];
endPoint: number[];
};
getBoxForPalmLandmarks(palmLandmarks: any, rotationMatrix: any): {
startPoint: number[];
endPoint: any[];
@ -18,8 +22,4 @@ export declare class HandPipeline {
};
transformRawCoords(rawCoords: any, box2: any, angle: any, rotationMatrix: any): any;
estimateHands(image: any, config: any): Promise<{}[]>;
calculateLandmarksBoundingBox(landmarks: any): {
startPoint: number[];
endPoint: number[];
};
}

4
types/human.d.ts vendored
View File

@ -1,3 +1,5 @@
import { Config } from './config';
import { Result } from './result';
import * as tf from '../dist/tfjs.esm.js';
import * as facemesh from './blazeface/facemesh';
import * as faceres from './faceres/faceres';
@ -7,8 +9,6 @@ import * as handpose from './handpose/handpose';
import * as blazepose from './blazepose/blazepose';
import * as nanodet from './nanodet/nanodet';
import * as draw from './draw/draw';
import { Config } from './config';
import { Result } from './result';
/** Generic Tensor object type */
export declare type Tensor = typeof tf.Tensor;
export type { Config } from './config';

View File

@ -1,7 +1,7 @@
import * as utils from './utils';
export declare function decodePose(root: any, scores: any, offsets: any, displacementsFwd: any, displacementsBwd: any): any[];
export declare function buildPartWithScoreQueue(minConfidence: any, scores: any): utils.MaxHeap;
export declare function decode(offsetsBuffer: any, scoresBuffer: any, displacementsFwdBuffer: any, displacementsBwdBuffer: any, maxDetected: any, minConfidence: any): {
export declare function decode(offsets: any, scores: any, displacementsFwd: any, displacementsBwd: any, maxDetected: any, minConfidence: any): {
keypoints: any;
box: any;
score: number;

2
wiki

@ -1 +1 @@
Subproject commit f9fc859622290183712e7f984db59e3c8494afe9
Subproject commit 981e14523d86586926d9d1141b04e652decafe5f