mirror of https://github.com/vladmandic/human
fix bug in async ops and change imports
parent
42e17606d6
commit
5807fb1bfa
|
@ -2,10 +2,10 @@ import Human from '../dist/human.esm.js';
|
|||
import draw from './draw.js';
|
||||
import Menu from './menu.js';
|
||||
|
||||
const human = new Human();
|
||||
|
||||
const userConfig = {}; // add any user configuration overrides
|
||||
|
||||
const human = new Human(userConfig);
|
||||
|
||||
// ui options
|
||||
const ui = {
|
||||
baseColor: 'rgba(173, 216, 230, 0.3)', // 'lightblue' with light alpha channel
|
||||
|
@ -134,7 +134,7 @@ async function setupCamera() {
|
|||
const constraints = {
|
||||
audio: false,
|
||||
video: {
|
||||
facingMode: (ui.facing ? 'user' : 'environment'),
|
||||
facingMode: ui.facing ? 'user' : 'environment',
|
||||
resizeMode: ui.crop ? 'crop-and-scale' : 'none',
|
||||
width: { ideal: window.innerWidth },
|
||||
height: { ideal: window.innerHeight },
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"inputs": {
|
||||
"demo/browser.js": {
|
||||
"bytes": 18516,
|
||||
"bytes": 18524,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/human.esm.js"
|
||||
|
@ -23,7 +23,7 @@
|
|||
"imports": []
|
||||
},
|
||||
"dist/human.esm.js": {
|
||||
"bytes": 3442260,
|
||||
"bytes": 3441681,
|
||||
"imports": []
|
||||
}
|
||||
},
|
||||
|
@ -31,13 +31,13 @@
|
|||
"dist/demo-browser-index.js.map": {
|
||||
"imports": [],
|
||||
"inputs": {},
|
||||
"bytes": 5419827
|
||||
"bytes": 5406858
|
||||
},
|
||||
"dist/demo-browser-index.js": {
|
||||
"imports": [],
|
||||
"inputs": {
|
||||
"dist/human.esm.js": {
|
||||
"bytesInOutput": 3431560
|
||||
"bytesInOutput": 3430970
|
||||
},
|
||||
"demo/draw.js": {
|
||||
"bytesInOutput": 8898
|
||||
|
@ -46,10 +46,10 @@
|
|||
"bytesInOutput": 13813
|
||||
},
|
||||
"demo/browser.js": {
|
||||
"bytesInOutput": 16215
|
||||
"bytesInOutput": 16241
|
||||
}
|
||||
},
|
||||
"bytes": 3470608
|
||||
"bytes": 3470044
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,21 +28,6 @@ var __toModule = (module) => {
|
|||
};
|
||||
|
||||
// src/face/blazeface.js
|
||||
import {
|
||||
add,
|
||||
concat,
|
||||
concat2d,
|
||||
div,
|
||||
image as image3,
|
||||
loadGraphModel,
|
||||
mul,
|
||||
sigmoid,
|
||||
slice,
|
||||
sub,
|
||||
tensor1d,
|
||||
tensor2d,
|
||||
tidy
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_blazeface = __commonJS((exports) => {
|
||||
const NUM_LANDMARKS = 6;
|
||||
function generateAnchors(inputSize) {
|
||||
|
@ -72,31 +57,31 @@ var require_blazeface = __commonJS((exports) => {
|
|||
};
|
||||
const createBox = (startEndTensor) => ({
|
||||
startEndTensor,
|
||||
startPoint: slice(startEndTensor, [0, 0], [-1, 2]),
|
||||
endPoint: slice(startEndTensor, [0, 2], [-1, 2])
|
||||
startPoint: tf.slice(startEndTensor, [0, 0], [-1, 2]),
|
||||
endPoint: tf.slice(startEndTensor, [0, 2], [-1, 2])
|
||||
});
|
||||
const scaleBox = (box, factors) => {
|
||||
const starts = mul(box.startPoint, factors);
|
||||
const ends = mul(box.endPoint, factors);
|
||||
const newCoordinates = concat2d([starts, ends], 1);
|
||||
const starts = tf.mul(box.startPoint, factors);
|
||||
const ends = tf.mul(box.endPoint, factors);
|
||||
const newCoordinates = tf.concat2d([starts, ends], 1);
|
||||
return createBox(newCoordinates);
|
||||
};
|
||||
function decodeBounds(boxOutputs, anchors, inputSize) {
|
||||
const boxStarts = slice(boxOutputs, [0, 1], [-1, 2]);
|
||||
const centers = add(boxStarts, anchors);
|
||||
const boxSizes = slice(boxOutputs, [0, 3], [-1, 2]);
|
||||
const boxSizesNormalized = div(boxSizes, inputSize);
|
||||
const centersNormalized = div(centers, inputSize);
|
||||
const halfBoxSize = div(boxSizesNormalized, 2);
|
||||
const starts = sub(centersNormalized, halfBoxSize);
|
||||
const ends = add(centersNormalized, halfBoxSize);
|
||||
const startNormalized = mul(starts, inputSize);
|
||||
const endNormalized = mul(ends, inputSize);
|
||||
const boxStarts = tf.slice(boxOutputs, [0, 1], [-1, 2]);
|
||||
const centers = tf.add(boxStarts, anchors);
|
||||
const boxSizes = tf.slice(boxOutputs, [0, 3], [-1, 2]);
|
||||
const boxSizesNormalized = tf.div(boxSizes, inputSize);
|
||||
const centersNormalized = tf.div(centers, inputSize);
|
||||
const halfBoxSize = tf.div(boxSizesNormalized, 2);
|
||||
const starts = tf.sub(centersNormalized, halfBoxSize);
|
||||
const ends = tf.add(centersNormalized, halfBoxSize);
|
||||
const startNormalized = tf.mul(starts, inputSize);
|
||||
const endNormalized = tf.mul(ends, inputSize);
|
||||
const concatAxis = 1;
|
||||
return concat2d([startNormalized, endNormalized], concatAxis);
|
||||
return tf.concat2d([startNormalized, endNormalized], concatAxis);
|
||||
}
|
||||
function scaleBoxFromPrediction(face2, scaleFactor) {
|
||||
return tidy(() => {
|
||||
return tf.tidy(() => {
|
||||
const box = face2["box"] ? face2["box"] : face2;
|
||||
return scaleBox(box, scaleFactor).startEndTensor.squeeze();
|
||||
});
|
||||
|
@ -107,37 +92,37 @@ var require_blazeface = __commonJS((exports) => {
|
|||
this.width = config2.detector.inputSize;
|
||||
this.height = config2.detector.inputSize;
|
||||
this.anchorsData = generateAnchors(config2.detector.inputSize);
|
||||
this.anchors = tensor2d(this.anchorsData);
|
||||
this.inputSize = tensor1d([this.width, this.height]);
|
||||
this.anchors = tf.tensor2d(this.anchorsData);
|
||||
this.inputSize = tf.tensor1d([this.width, this.height]);
|
||||
this.config = config2;
|
||||
this.scaleFaces = 0.8;
|
||||
}
|
||||
async getBoundingBoxes(inputImage) {
|
||||
if (!inputImage || inputImage.isDisposedInternal || inputImage.shape.length !== 4 || inputImage.shape[1] < 1 || inputImage.shape[2] < 1)
|
||||
return null;
|
||||
const [detectedOutputs, boxes, scores] = tidy(() => {
|
||||
const [detectedOutputs, boxes, scores] = tf.tidy(() => {
|
||||
const resizedImage = inputImage.resizeBilinear([this.width, this.height]);
|
||||
const normalizedImage = sub(resizedImage.div(127.5), 1);
|
||||
const normalizedImage = tf.sub(resizedImage.div(127.5), 1);
|
||||
const batchedPrediction = this.blazeFaceModel.predict(normalizedImage);
|
||||
let prediction;
|
||||
if (Array.isArray(batchedPrediction)) {
|
||||
const sorted = batchedPrediction.sort((a, b) => a.size - b.size);
|
||||
const concat384 = concat([sorted[0], sorted[2]], 2);
|
||||
const concat512 = concat([sorted[1], sorted[3]], 2);
|
||||
const concat2 = concat([concat512, concat384], 1);
|
||||
prediction = concat2.squeeze(0);
|
||||
const concat384 = tf.concat([sorted[0], sorted[2]], 2);
|
||||
const concat512 = tf.concat([sorted[1], sorted[3]], 2);
|
||||
const concat = tf.concat([concat512, concat384], 1);
|
||||
prediction = concat.squeeze(0);
|
||||
} else {
|
||||
prediction = batchedPrediction.squeeze();
|
||||
}
|
||||
const decodedBounds = decodeBounds(prediction, this.anchors, this.inputSize);
|
||||
const logits = slice(prediction, [0, 0], [-1, 1]);
|
||||
const scoresOut = sigmoid(logits).squeeze();
|
||||
const logits = tf.slice(prediction, [0, 0], [-1, 1]);
|
||||
const scoresOut = tf.sigmoid(logits).squeeze();
|
||||
return [prediction, decodedBounds, scoresOut];
|
||||
});
|
||||
const boxIndicesTensor = await image3.nonMaxSuppressionAsync(boxes, scores, this.config.detector.maxFaces, this.config.detector.iouThreshold, this.config.detector.scoreThreshold);
|
||||
const boxIndicesTensor = await tf.image.nonMaxSuppressionAsync(boxes, scores, this.config.detector.maxFaces, this.config.detector.iouThreshold, this.config.detector.scoreThreshold);
|
||||
const boxIndices = boxIndicesTensor.arraySync();
|
||||
boxIndicesTensor.dispose();
|
||||
const boundingBoxesMap = boxIndices.map((boxIndex) => slice(boxes, [boxIndex, 0], [1, -1]));
|
||||
const boundingBoxesMap = boxIndices.map((boxIndex) => tf.slice(boxes, [boxIndex, 0], [1, -1]));
|
||||
const boundingBoxes = boundingBoxesMap.map((boundingBox) => {
|
||||
const vals = boundingBox.arraySync();
|
||||
boundingBox.dispose();
|
||||
|
@ -151,7 +136,7 @@ var require_blazeface = __commonJS((exports) => {
|
|||
if (confidence > this.config.detector.minConfidence) {
|
||||
const box = createBox(boundingBoxes[i]);
|
||||
const anchor = this.anchorsData[boxIndex];
|
||||
const landmarks = tidy(() => slice(detectedOutputs, [boxIndex, NUM_LANDMARKS - 1], [1, -1]).squeeze().reshape([NUM_LANDMARKS, -1]));
|
||||
const landmarks = tf.tidy(() => tf.slice(detectedOutputs, [boxIndex, NUM_LANDMARKS - 1], [1, -1]).squeeze().reshape([NUM_LANDMARKS, -1]));
|
||||
annotatedBoxes.push({box, landmarks, anchor, confidence});
|
||||
}
|
||||
}
|
||||
|
@ -291,9 +276,6 @@ var require_keypoints = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/face/box.js
|
||||
import {
|
||||
image as image3
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_box = __commonJS((exports) => {
|
||||
function scaleBoxCoordinates2(box, factor) {
|
||||
const startPoint = [box.startPoint[0] * factor[0], box.startPoint[1] * factor[1]];
|
||||
|
@ -315,16 +297,16 @@ var require_box = __commonJS((exports) => {
|
|||
];
|
||||
}
|
||||
exports.getBoxCenter = getBoxCenter2;
|
||||
function cutBoxFromImageAndResize2(box, image4, cropSize) {
|
||||
const h = image4.shape[1];
|
||||
const w = image4.shape[2];
|
||||
function cutBoxFromImageAndResize2(box, image2, cropSize) {
|
||||
const h = image2.shape[1];
|
||||
const w = image2.shape[2];
|
||||
const boxes = [[
|
||||
box.startPoint[1] / h,
|
||||
box.startPoint[0] / w,
|
||||
box.endPoint[1] / h,
|
||||
box.endPoint[0] / w
|
||||
]];
|
||||
return image3.cropAndResize(image4, boxes, [0], cropSize);
|
||||
return tf.image.cropAndResize(image2, boxes, [0], cropSize);
|
||||
}
|
||||
exports.cutBoxFromImageAndResize = cutBoxFromImageAndResize2;
|
||||
function enlargeBox2(box, factor = 1.5) {
|
||||
|
@ -432,14 +414,6 @@ var require_util = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/face/facepipeline.js
|
||||
import {
|
||||
concat,
|
||||
dispose,
|
||||
image as image3,
|
||||
reshape,
|
||||
tensor2d,
|
||||
tidy
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_facepipeline = __commonJS((exports) => {
|
||||
const bounding = __toModule(require_box());
|
||||
const keypoints = __toModule(require_keypoints());
|
||||
|
@ -519,14 +493,14 @@ var require_facepipeline = __commonJS((exports) => {
|
|||
getEyeBox(rawCoords, face2, eyeInnerCornerIndex, eyeOuterCornerIndex, flip = false) {
|
||||
const box = bounding.squarifyBox(bounding.enlargeBox(this.calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), this.irisEnlarge));
|
||||
const boxSize = bounding.getBoxSize(box);
|
||||
let crop = image3.cropAndResize(face2, [[
|
||||
let crop = tf.image.cropAndResize(face2, [[
|
||||
box.startPoint[1] / this.meshHeight,
|
||||
box.startPoint[0] / this.meshWidth,
|
||||
box.endPoint[1] / this.meshHeight,
|
||||
box.endPoint[0] / this.meshWidth
|
||||
]], [0], [this.irisSize, this.irisSize]);
|
||||
if (flip) {
|
||||
crop = image3.flipLeftRight(crop);
|
||||
crop = tf.image.flipLeftRight(crop);
|
||||
}
|
||||
return {box, boxSize, crop};
|
||||
}
|
||||
|
@ -598,7 +572,7 @@ var require_facepipeline = __commonJS((exports) => {
|
|||
prediction.landmarks.dispose();
|
||||
});
|
||||
}
|
||||
let results = tidy(() => this.storedBoxes.map((box, i) => {
|
||||
let results = tf.tidy(() => this.storedBoxes.map((box, i) => {
|
||||
let angle = 0;
|
||||
const boxLandmarksFromMeshModel = box.landmarks.length >= LANDMARKS_COUNT;
|
||||
let [indexOfMouth, indexOfForehead] = MESH_KEYPOINTS_LINE_OF_SYMMETRY_INDICES;
|
||||
|
@ -611,7 +585,7 @@ var require_facepipeline = __commonJS((exports) => {
|
|||
let rotatedImage = input;
|
||||
let rotationMatrix = util.IDENTITY_MATRIX;
|
||||
if (angle !== 0) {
|
||||
rotatedImage = image3.rotateWithOffset(input, angle, 0, faceCenterNormalized);
|
||||
rotatedImage = tf.image.rotateWithOffset(input, angle, 0, faceCenterNormalized);
|
||||
rotationMatrix = util.buildRotationMatrix(-angle, faceCenter);
|
||||
}
|
||||
const boxCPU = {startPoint: box.startPoint, endPoint: box.endPoint};
|
||||
|
@ -633,12 +607,12 @@ var require_facepipeline = __commonJS((exports) => {
|
|||
coords.dispose();
|
||||
return null;
|
||||
}
|
||||
const coordsReshaped = reshape(coords, [-1, 3]);
|
||||
const coordsReshaped = tf.reshape(coords, [-1, 3]);
|
||||
let rawCoords = coordsReshaped.arraySync();
|
||||
if (config2.iris.enabled) {
|
||||
const {box: leftEyeBox, boxSize: leftEyeBoxSize, crop: leftEyeCrop} = this.getEyeBox(rawCoords, face2, LEFT_EYE_BOUNDS[0], LEFT_EYE_BOUNDS[1], true);
|
||||
const {box: rightEyeBox, boxSize: rightEyeBoxSize, crop: rightEyeCrop} = this.getEyeBox(rawCoords, face2, RIGHT_EYE_BOUNDS[0], RIGHT_EYE_BOUNDS[1]);
|
||||
const eyePredictions = this.irisModel.predict(concat([leftEyeCrop, rightEyeCrop]));
|
||||
const eyePredictions = this.irisModel.predict(tf.concat([leftEyeCrop, rightEyeCrop]));
|
||||
const eyePredictionsData = eyePredictions.dataSync();
|
||||
eyePredictions.dispose();
|
||||
const leftEyeData = eyePredictionsData.slice(0, IRIS_NUM_COORDINATES * 3);
|
||||
|
@ -659,9 +633,9 @@ var require_facepipeline = __commonJS((exports) => {
|
|||
rawCoords = rawCoords.concat(adjustedLeftIrisCoords).concat(adjustedRightIrisCoords);
|
||||
}
|
||||
const transformedCoordsData = this.transformRawCoords(rawCoords, box, angle, rotationMatrix);
|
||||
dispose(rawCoords);
|
||||
tf.dispose(rawCoords);
|
||||
const landmarksBox = bounding.enlargeBox(this.calculateLandmarksBoundingBox(transformedCoordsData));
|
||||
const transformedCoords = tensor2d(transformedCoordsData);
|
||||
const transformedCoords = tf.tensor2d(transformedCoordsData);
|
||||
const prediction = {
|
||||
coords: transformedCoords,
|
||||
box: landmarksBox,
|
||||
|
@ -1162,10 +1136,6 @@ var require_uvcoords = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/face/facemesh.js
|
||||
import {
|
||||
clone,
|
||||
loadGraphModel
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_facemesh = __commonJS((exports) => {
|
||||
const blazeface = __toModule(require_blazeface());
|
||||
const keypoints = __toModule(require_keypoints());
|
||||
|
@ -1199,7 +1169,7 @@ var require_facemesh = __commonJS((exports) => {
|
|||
box: prediction.box ? [prediction.box.startPoint[0], prediction.box.startPoint[1], prediction.box.endPoint[0] - prediction.box.startPoint[0], prediction.box.endPoint[1] - prediction.box.startPoint[1]] : 0,
|
||||
mesh,
|
||||
annotations,
|
||||
image: prediction.image ? clone(prediction.image) : null
|
||||
image: prediction.image ? tf.clone(prediction.image) : null
|
||||
});
|
||||
if (prediction.coords)
|
||||
prediction.coords.dispose();
|
||||
|
@ -1254,13 +1224,6 @@ var require_profile = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/age/age.js
|
||||
import {
|
||||
dispose,
|
||||
image as image3,
|
||||
loadGraphModel,
|
||||
mul,
|
||||
profile as profile3
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_age = __commonJS((exports) => {
|
||||
const profile2 = __toModule(require_profile());
|
||||
const models = {};
|
||||
|
@ -1274,7 +1237,7 @@ var require_age = __commonJS((exports) => {
|
|||
}
|
||||
return models.age;
|
||||
}
|
||||
async function predict(image4, config2) {
|
||||
async function predict(image2, config2) {
|
||||
if (frame < config2.face.age.skipFrames && last.age && last.age > 0) {
|
||||
frame += 1;
|
||||
return last;
|
||||
|
@ -1282,21 +1245,21 @@ var require_age = __commonJS((exports) => {
|
|||
frame = 0;
|
||||
return new Promise(async (resolve) => {
|
||||
const box = [[
|
||||
image4.shape[1] * zoom[0] / image4.shape[1],
|
||||
image4.shape[2] * zoom[1] / image4.shape[2],
|
||||
(image4.shape[1] - image4.shape[1] * zoom[0]) / image4.shape[1],
|
||||
(image4.shape[2] - image4.shape[2] * zoom[1]) / image4.shape[2]
|
||||
image2.shape[1] * zoom[0] / image2.shape[1],
|
||||
image2.shape[2] * zoom[1] / image2.shape[2],
|
||||
(image2.shape[1] - image2.shape[1] * zoom[0]) / image2.shape[1],
|
||||
(image2.shape[2] - image2.shape[2] * zoom[1]) / image2.shape[2]
|
||||
]];
|
||||
const resize = image3.cropAndResize(image4, box, [0], [config2.face.age.inputSize, config2.face.age.inputSize]);
|
||||
const enhance = mul(resize, [255]);
|
||||
dispose(resize);
|
||||
const resize = tf.image.cropAndResize(image2, box, [0], [config2.face.age.inputSize, config2.face.age.inputSize]);
|
||||
const enhance = tf.mul(resize, [255]);
|
||||
tf.dispose(resize);
|
||||
let ageT;
|
||||
const obj = {};
|
||||
if (!config2.profile) {
|
||||
if (config2.face.age.enabled)
|
||||
ageT = await models.age.predict(enhance);
|
||||
} else {
|
||||
const profileAge = config2.face.age.enabled ? await profile3(() => models.age.predict(enhance)) : {};
|
||||
const profileAge = config2.face.age.enabled ? await tf.profile(() => models.age.predict(enhance)) : {};
|
||||
ageT = profileAge.result.clone();
|
||||
profileAge.result.dispose();
|
||||
profile2.run("age", profileAge);
|
||||
|
@ -1316,16 +1279,6 @@ var require_age = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/gender/gender.js
|
||||
import {
|
||||
addN,
|
||||
dispose,
|
||||
image as image3,
|
||||
loadGraphModel,
|
||||
mul,
|
||||
profile as profile3,
|
||||
split,
|
||||
tidy
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_gender = __commonJS((exports) => {
|
||||
const profile2 = __toModule(require_profile());
|
||||
const models = {};
|
||||
|
@ -1342,7 +1295,7 @@ var require_gender = __commonJS((exports) => {
|
|||
}
|
||||
return models.gender;
|
||||
}
|
||||
async function predict(image4, config2) {
|
||||
async function predict(image2, config2) {
|
||||
if (frame < config2.face.gender.skipFrames && last.gender !== "") {
|
||||
frame += 1;
|
||||
return last;
|
||||
|
@ -1350,33 +1303,33 @@ var require_gender = __commonJS((exports) => {
|
|||
frame = 0;
|
||||
return new Promise(async (resolve) => {
|
||||
const box = [[
|
||||
image4.shape[1] * zoom[0] / image4.shape[1],
|
||||
image4.shape[2] * zoom[1] / image4.shape[2],
|
||||
(image4.shape[1] - image4.shape[1] * zoom[0]) / image4.shape[1],
|
||||
(image4.shape[2] - image4.shape[2] * zoom[1]) / image4.shape[2]
|
||||
image2.shape[1] * zoom[0] / image2.shape[1],
|
||||
image2.shape[2] * zoom[1] / image2.shape[2],
|
||||
(image2.shape[1] - image2.shape[1] * zoom[0]) / image2.shape[1],
|
||||
(image2.shape[2] - image2.shape[2] * zoom[1]) / image2.shape[2]
|
||||
]];
|
||||
const resize = image3.cropAndResize(image4, box, [0], [config2.face.gender.inputSize, config2.face.gender.inputSize]);
|
||||
const resize = tf.image.cropAndResize(image2, box, [0], [config2.face.gender.inputSize, config2.face.gender.inputSize]);
|
||||
let enhance;
|
||||
if (alternative) {
|
||||
enhance = tidy(() => {
|
||||
const [red, green, blue] = split(resize, 3, 3);
|
||||
const redNorm = mul(red, rgb[0]);
|
||||
const greenNorm = mul(green, rgb[1]);
|
||||
const blueNorm = mul(blue, rgb[2]);
|
||||
const grayscale = addN([redNorm, greenNorm, blueNorm]);
|
||||
enhance = tf.tidy(() => {
|
||||
const [red, green, blue] = tf.split(resize, 3, 3);
|
||||
const redNorm = tf.mul(red, rgb[0]);
|
||||
const greenNorm = tf.mul(green, rgb[1]);
|
||||
const blueNorm = tf.mul(blue, rgb[2]);
|
||||
const grayscale = tf.addN([redNorm, greenNorm, blueNorm]);
|
||||
return grayscale.sub(0.5).mul(2);
|
||||
});
|
||||
} else {
|
||||
enhance = mul(resize, [255]);
|
||||
enhance = tf.mul(resize, [255]);
|
||||
}
|
||||
dispose(resize);
|
||||
tf.dispose(resize);
|
||||
let genderT;
|
||||
const obj = {};
|
||||
if (!config2.profile) {
|
||||
if (config2.face.gender.enabled)
|
||||
genderT = await models.gender.predict(enhance);
|
||||
} else {
|
||||
const profileGender = config2.face.gender.enabled ? await profile3(() => models.gender.predict(enhance)) : {};
|
||||
const profileGender = config2.face.gender.enabled ? await tf.profile(() => models.gender.predict(enhance)) : {};
|
||||
genderT = profileGender.result.clone();
|
||||
profileGender.result.dispose();
|
||||
profile2.run("gender", profileGender);
|
||||
|
@ -1408,16 +1361,6 @@ var require_gender = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/emotion/emotion.js
|
||||
import {
|
||||
addN,
|
||||
dispose,
|
||||
image as image3,
|
||||
loadGraphModel,
|
||||
mul,
|
||||
profile as profile3,
|
||||
split,
|
||||
tidy
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_emotion = __commonJS((exports) => {
|
||||
const profile2 = __toModule(require_profile());
|
||||
const annotations = ["angry", "disgust", "fear", "happy", "sad", "surpise", "neutral"];
|
||||
|
@ -1434,7 +1377,7 @@ var require_emotion = __commonJS((exports) => {
|
|||
}
|
||||
return models.emotion;
|
||||
}
|
||||
async function predict(image4, config2) {
|
||||
async function predict(image2, config2) {
|
||||
if (frame < config2.face.emotion.skipFrames && last.length > 0) {
|
||||
frame += 1;
|
||||
return last;
|
||||
|
@ -1442,25 +1385,25 @@ var require_emotion = __commonJS((exports) => {
|
|||
frame = 0;
|
||||
return new Promise(async (resolve) => {
|
||||
const box = [[
|
||||
image4.shape[1] * zoom[0] / image4.shape[1],
|
||||
image4.shape[2] * zoom[1] / image4.shape[2],
|
||||
(image4.shape[1] - image4.shape[1] * zoom[0]) / image4.shape[1],
|
||||
(image4.shape[2] - image4.shape[2] * zoom[1]) / image4.shape[2]
|
||||
image2.shape[1] * zoom[0] / image2.shape[1],
|
||||
image2.shape[2] * zoom[1] / image2.shape[2],
|
||||
(image2.shape[1] - image2.shape[1] * zoom[0]) / image2.shape[1],
|
||||
(image2.shape[2] - image2.shape[2] * zoom[1]) / image2.shape[2]
|
||||
]];
|
||||
const resize = image3.cropAndResize(image4, box, [0], [config2.face.emotion.inputSize, config2.face.emotion.inputSize]);
|
||||
const [red, green, blue] = split(resize, 3, 3);
|
||||
const resize = tf.image.cropAndResize(image2, box, [0], [config2.face.emotion.inputSize, config2.face.emotion.inputSize]);
|
||||
const [red, green, blue] = tf.split(resize, 3, 3);
|
||||
resize.dispose();
|
||||
const redNorm = mul(red, rgb[0]);
|
||||
const greenNorm = mul(green, rgb[1]);
|
||||
const blueNorm = mul(blue, rgb[2]);
|
||||
const redNorm = tf.mul(red, rgb[0]);
|
||||
const greenNorm = tf.mul(green, rgb[1]);
|
||||
const blueNorm = tf.mul(blue, rgb[2]);
|
||||
red.dispose();
|
||||
green.dispose();
|
||||
blue.dispose();
|
||||
const grayscale = addN([redNorm, greenNorm, blueNorm]);
|
||||
const grayscale = tf.addN([redNorm, greenNorm, blueNorm]);
|
||||
redNorm.dispose();
|
||||
greenNorm.dispose();
|
||||
blueNorm.dispose();
|
||||
const normalize = tidy(() => grayscale.sub(0.5).mul(2));
|
||||
const normalize = tf.tidy(() => grayscale.sub(0.5).mul(2));
|
||||
grayscale.dispose();
|
||||
const obj = [];
|
||||
if (config2.face.emotion.enabled) {
|
||||
|
@ -1468,9 +1411,9 @@ var require_emotion = __commonJS((exports) => {
|
|||
if (!config2.profile) {
|
||||
const emotionT = await models.emotion.predict(normalize);
|
||||
data2 = emotionT.dataSync();
|
||||
dispose(emotionT);
|
||||
tf.dispose(emotionT);
|
||||
} else {
|
||||
const profileData = await profile3(() => models.emotion.predict(normalize));
|
||||
const profileData = await tf.profile(() => models.emotion.predict(normalize));
|
||||
data2 = profileData.result.dataSync();
|
||||
profileData.result.dispose();
|
||||
profile2.run("emotion", profileData);
|
||||
|
@ -1491,9 +1434,6 @@ var require_emotion = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/body/modelBase.js
|
||||
import {
|
||||
tidy
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_modelBase = __commonJS((exports) => {
|
||||
class BaseModel {
|
||||
constructor(model, outputStride) {
|
||||
|
@ -1501,7 +1441,7 @@ var require_modelBase = __commonJS((exports) => {
|
|||
this.outputStride = outputStride;
|
||||
}
|
||||
predict(input) {
|
||||
return tidy(() => {
|
||||
return tf.tidy(() => {
|
||||
const asFloat = this.preprocessInput(input.toFloat());
|
||||
const asBatch = asFloat.expandDims(0);
|
||||
const results = this.model.predict(asBatch);
|
||||
|
@ -1523,15 +1463,11 @@ var require_modelBase = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/body/modelMobileNet.js
|
||||
import {
|
||||
div,
|
||||
tidy
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_modelMobileNet = __commonJS((exports) => {
|
||||
const modelBase = __toModule(require_modelBase());
|
||||
class MobileNet extends modelBase.BaseModel {
|
||||
preprocessInput(input) {
|
||||
return tidy(() => div(input, 127.5).sub(1));
|
||||
return tf.tidy(() => tf.div(input, 127.5).sub(1));
|
||||
}
|
||||
nameOutputResults(results) {
|
||||
const [offsets, heatmap, displacementFwd, displacementBwd] = results;
|
||||
|
@ -1946,8 +1882,8 @@ var require_util2 = __commonJS((exports) => {
|
|||
};
|
||||
}
|
||||
exports.scalePose = scalePose;
|
||||
function resizeTo(image3, [targetH, targetW]) {
|
||||
const input = image3.squeeze(0);
|
||||
function resizeTo(image2, [targetH, targetW]) {
|
||||
const input = image2.squeeze(0);
|
||||
const resized = input.resizeBilinear([targetH, targetW]);
|
||||
input.dispose();
|
||||
return resized;
|
||||
|
@ -1961,9 +1897,6 @@ var require_util2 = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/body/modelPoseNet.js
|
||||
import {
|
||||
loadGraphModel
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_modelPoseNet = __commonJS((exports) => {
|
||||
const modelMobileNet = __toModule(require_modelMobileNet());
|
||||
const decodeMultiple = __toModule(require_decodeMultiple());
|
||||
|
@ -2031,19 +1964,6 @@ var require_posenet = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/hand/handdetector.js
|
||||
import {
|
||||
add,
|
||||
concat2d,
|
||||
div,
|
||||
image as image3,
|
||||
mul,
|
||||
sigmoid,
|
||||
slice,
|
||||
sub,
|
||||
tensor1d,
|
||||
tensor2d,
|
||||
tidy
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_handdetector = __commonJS((exports) => {
|
||||
/**
|
||||
* @license
|
||||
|
@ -2065,46 +1985,46 @@ var require_handdetector = __commonJS((exports) => {
|
|||
constructor(model, inputSize, anchorsAnnotated) {
|
||||
this.model = model;
|
||||
this.anchors = anchorsAnnotated.map((anchor) => [anchor.x_center, anchor.y_center]);
|
||||
this.anchorsTensor = tensor2d(this.anchors);
|
||||
this.inputSizeTensor = tensor1d([inputSize, inputSize]);
|
||||
this.doubleInputSizeTensor = tensor1d([inputSize * 2, inputSize * 2]);
|
||||
this.anchorsTensor = tf.tensor2d(this.anchors);
|
||||
this.inputSizeTensor = tf.tensor1d([inputSize, inputSize]);
|
||||
this.doubleInputSizeTensor = tf.tensor1d([inputSize * 2, inputSize * 2]);
|
||||
}
|
||||
normalizeBoxes(boxes) {
|
||||
return tidy(() => {
|
||||
const boxOffsets = slice(boxes, [0, 0], [-1, 2]);
|
||||
const boxSizes = slice(boxes, [0, 2], [-1, 2]);
|
||||
const boxCenterPoints = add(div(boxOffsets, this.inputSizeTensor), this.anchorsTensor);
|
||||
const halfBoxSizes = div(boxSizes, this.doubleInputSizeTensor);
|
||||
const startPoints = mul(sub(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
|
||||
const endPoints = mul(add(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
|
||||
return concat2d([startPoints, endPoints], 1);
|
||||
return tf.tidy(() => {
|
||||
const boxOffsets = tf.slice(boxes, [0, 0], [-1, 2]);
|
||||
const boxSizes = tf.slice(boxes, [0, 2], [-1, 2]);
|
||||
const boxCenterPoints = tf.add(tf.div(boxOffsets, this.inputSizeTensor), this.anchorsTensor);
|
||||
const halfBoxSizes = tf.div(boxSizes, this.doubleInputSizeTensor);
|
||||
const startPoints = tf.mul(tf.sub(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
|
||||
const endPoints = tf.mul(tf.add(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
|
||||
return tf.concat2d([startPoints, endPoints], 1);
|
||||
});
|
||||
}
|
||||
normalizeLandmarks(rawPalmLandmarks, index) {
|
||||
return tidy(() => {
|
||||
const landmarks = add(div(rawPalmLandmarks.reshape([-1, 7, 2]), this.inputSizeTensor), this.anchors[index]);
|
||||
return mul(landmarks, this.inputSizeTensor);
|
||||
return tf.tidy(() => {
|
||||
const landmarks = tf.add(tf.div(rawPalmLandmarks.reshape([-1, 7, 2]), this.inputSizeTensor), this.anchors[index]);
|
||||
return tf.mul(landmarks, this.inputSizeTensor);
|
||||
});
|
||||
}
|
||||
async getBoxes(input, config2) {
|
||||
const batched = this.model.predict(input);
|
||||
const predictions = batched.squeeze();
|
||||
batched.dispose();
|
||||
const scores = tidy(() => sigmoid(slice(predictions, [0, 0], [-1, 1])).squeeze());
|
||||
const scores = tf.tidy(() => tf.sigmoid(tf.slice(predictions, [0, 0], [-1, 1])).squeeze());
|
||||
const scoresVal = scores.dataSync();
|
||||
const rawBoxes = slice(predictions, [0, 1], [-1, 4]);
|
||||
const rawBoxes = tf.slice(predictions, [0, 1], [-1, 4]);
|
||||
const boxes = this.normalizeBoxes(rawBoxes);
|
||||
rawBoxes.dispose();
|
||||
const filteredT = await image3.nonMaxSuppressionAsync(boxes, scores, config2.maxHands, config2.iouThreshold, config2.scoreThreshold);
|
||||
const filteredT = await tf.image.nonMaxSuppressionAsync(boxes, scores, config2.maxHands, config2.iouThreshold, config2.scoreThreshold);
|
||||
const filtered = filteredT.arraySync();
|
||||
scores.dispose();
|
||||
filteredT.dispose();
|
||||
const hands = [];
|
||||
for (const boxIndex of filtered) {
|
||||
if (scoresVal[boxIndex] >= config2.minConfidence) {
|
||||
const matchingBox = slice(boxes, [boxIndex, 0], [1, -1]);
|
||||
const rawPalmLandmarks = slice(predictions, [boxIndex, 5], [1, 14]);
|
||||
const palmLandmarks = tidy(() => this.normalizeLandmarks(rawPalmLandmarks, boxIndex).reshape([-1, 2]));
|
||||
const matchingBox = tf.slice(boxes, [boxIndex, 0], [1, -1]);
|
||||
const rawPalmLandmarks = tf.slice(predictions, [boxIndex, 5], [1, 14]);
|
||||
const palmLandmarks = tf.tidy(() => this.normalizeLandmarks(rawPalmLandmarks, boxIndex).reshape([-1, 2]));
|
||||
rawPalmLandmarks.dispose();
|
||||
hands.push({box: matchingBox, palmLandmarks, confidence: scoresVal[boxIndex]});
|
||||
}
|
||||
|
@ -2116,9 +2036,9 @@ var require_handdetector = __commonJS((exports) => {
|
|||
async estimateHandBounds(input, config2) {
|
||||
const inputHeight = input.shape[1];
|
||||
const inputWidth = input.shape[2];
|
||||
const image4 = tidy(() => input.resizeBilinear([config2.inputSize, config2.inputSize]).div(127.5).sub(1));
|
||||
const predictions = await this.getBoxes(image4, config2);
|
||||
image4.dispose();
|
||||
const image2 = tf.tidy(() => input.resizeBilinear([config2.inputSize, config2.inputSize]).div(127.5).sub(1));
|
||||
const predictions = await this.getBoxes(image2, config2);
|
||||
image2.dispose();
|
||||
if (!predictions || predictions.length === 0)
|
||||
return null;
|
||||
const hands = [];
|
||||
|
@ -2138,10 +2058,6 @@ var require_handdetector = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/hand/handpipeline.js
|
||||
import {
|
||||
image as image3,
|
||||
reshape
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_handpipeline = __commonJS((exports) => {
|
||||
/**
|
||||
* @license
|
||||
|
@ -2218,13 +2134,13 @@ var require_handpipeline = __commonJS((exports) => {
|
|||
coord[2]
|
||||
]);
|
||||
}
|
||||
async estimateHands(image4, config2) {
|
||||
async estimateHands(image2, config2) {
|
||||
this.skipped++;
|
||||
let useFreshBox = false;
|
||||
let boxes;
|
||||
if (this.skipped > config2.skipFrames || !config2.landmarks) {
|
||||
boxes = await this.boxDetector.estimateHandBounds(image4, config2);
|
||||
if (image4.shape[1] !== 255 && image4.shape[2] !== 255)
|
||||
boxes = await this.boxDetector.estimateHandBounds(image2, config2);
|
||||
if (image2.shape[1] !== 255 && image2.shape[2] !== 255)
|
||||
this.skipped = 0;
|
||||
}
|
||||
if (boxes && boxes.length > 0 && (boxes.length !== this.detectedHands && this.detectedHands !== config2.maxHands || !config2.landmarks)) {
|
||||
|
@ -2243,8 +2159,8 @@ var require_handpipeline = __commonJS((exports) => {
|
|||
if (config2.landmarks) {
|
||||
const angle = computeRotation(currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_PALM_BASE], currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE]);
|
||||
const palmCenter = getBoxCenter(currentBox);
|
||||
const palmCenterNormalized = [palmCenter[0] / image4.shape[2], palmCenter[1] / image4.shape[1]];
|
||||
const rotatedImage = image3.rotateWithOffset(image4, angle, 0, palmCenterNormalized);
|
||||
const palmCenterNormalized = [palmCenter[0] / image2.shape[2], palmCenter[1] / image2.shape[1]];
|
||||
const rotatedImage = tf.image.rotateWithOffset(image2, angle, 0, palmCenterNormalized);
|
||||
const rotationMatrix = buildRotationMatrix(-angle, palmCenter);
|
||||
const newBox = useFreshBox ? this.getBoxForPalmLandmarks(currentBox.palmLandmarks, rotationMatrix) : currentBox;
|
||||
const croppedInput = cutBoxFromImageAndResize(newBox, rotatedImage, [this.inputSize, this.inputSize]);
|
||||
|
@ -2256,7 +2172,7 @@ var require_handpipeline = __commonJS((exports) => {
|
|||
const confidenceValue = confidence.dataSync()[0];
|
||||
confidence.dispose();
|
||||
if (confidenceValue >= config2.minConfidence) {
|
||||
const keypointsReshaped = reshape(keypoints, [-1, 3]);
|
||||
const keypointsReshaped = tf.reshape(keypoints, [-1, 3]);
|
||||
const rawCoords = keypointsReshaped.arraySync();
|
||||
keypoints.dispose();
|
||||
keypointsReshaped.dispose();
|
||||
|
@ -19974,9 +19890,6 @@ var require_anchors = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/hand/handpose.js
|
||||
import {
|
||||
loadGraphModel
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_handpose = __commonJS((exports) => {
|
||||
const handdetector = __toModule(require_handdetector());
|
||||
const pipeline = __toModule(require_handpipeline());
|
||||
|
@ -20192,8 +20105,8 @@ var require_imagefx = __commonJS((exports) => {
|
|||
this.reset = function() {
|
||||
_filterChain = [];
|
||||
};
|
||||
this.apply = function(image3) {
|
||||
_resize(image3.width, image3.height);
|
||||
this.apply = function(image2) {
|
||||
_resize(image2.width, image2.height);
|
||||
_drawCount = 0;
|
||||
if (!_sourceTexture)
|
||||
_sourceTexture = gl.createTexture();
|
||||
|
@ -20202,7 +20115,7 @@ var require_imagefx = __commonJS((exports) => {
|
|||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image3);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image2);
|
||||
if (_filterChain.length === 0) {
|
||||
_draw();
|
||||
return _canvas;
|
||||
|
@ -20838,20 +20751,14 @@ var require_imagefx = __commonJS((exports) => {
|
|||
});
|
||||
|
||||
// src/image.js
|
||||
import {
|
||||
ENV,
|
||||
Tensor,
|
||||
browser,
|
||||
clone
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
var require_image = __commonJS((exports) => {
|
||||
const fxImage = __toModule(require_imagefx());
|
||||
let inCanvas = null;
|
||||
let outCanvas = null;
|
||||
function process3(input, config2) {
|
||||
let tensor;
|
||||
if (input instanceof Tensor) {
|
||||
tensor = clone(input);
|
||||
if (input instanceof tf.Tensor) {
|
||||
tensor = tf.clone(input);
|
||||
} else {
|
||||
const originalWidth = input.naturalWidth || input.videoWidth || input.width || input.shape && input.shape[1] > 0;
|
||||
const originalHeight = input.naturalHeight || input.videoHeight || input.height || input.shape && input.shape[2] > 0;
|
||||
|
@ -20884,7 +20791,7 @@ var require_image = __commonJS((exports) => {
|
|||
outCanvas.width = inCanvas.width;
|
||||
if (outCanvas.height !== inCanvas.height)
|
||||
outCanvas.height = inCanvas.height;
|
||||
this.fx = ENV.flags.IS_BROWSER ? new fxImage.Canvas({canvas: outCanvas}) : null;
|
||||
this.fx = tf.ENV.flags.IS_BROWSER ? new fxImage.Canvas({canvas: outCanvas}) : null;
|
||||
}
|
||||
this.fx.reset();
|
||||
this.fx.addFilter("brightness", config2.filter.brightness);
|
||||
|
@ -20920,7 +20827,7 @@ var require_image = __commonJS((exports) => {
|
|||
}
|
||||
let pixels;
|
||||
if (config2.backend === "webgl" || outCanvas instanceof ImageData) {
|
||||
pixels = browser.fromPixels(outCanvas);
|
||||
pixels = tf.browser.fromPixels(outCanvas);
|
||||
} else {
|
||||
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||
tempCanvas.width = targetWidth;
|
||||
|
@ -20928,7 +20835,7 @@ var require_image = __commonJS((exports) => {
|
|||
const tempCtx = tempCanvas.getContext("2d");
|
||||
tempCtx.drawImage(outCanvas, 0, 0);
|
||||
const data2 = tempCtx.getImageData(0, 0, targetWidth, targetHeight);
|
||||
pixels = browser.fromPixels(data2);
|
||||
pixels = tf.browser.fromPixels(data2);
|
||||
}
|
||||
const casted = pixels.toFloat();
|
||||
tensor = casted.expandDims(0);
|
||||
|
@ -20940,9 +20847,10 @@ var require_image = __commonJS((exports) => {
|
|||
exports.process = process3;
|
||||
});
|
||||
|
||||
// src/human.js
|
||||
import * as tf2 from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
// src/tf.js
|
||||
import * as tf from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
import {setWasmPaths} from "@tensorflow/tfjs-backend-wasm/dist/index.js";
|
||||
const loadGraphModel = tf.loadGraphModel;
|
||||
|
||||
// src/face/triangulation.js
|
||||
var triangulation_default = [
|
||||
|
@ -23596,9 +23504,6 @@ const emotion = __toModule(require_emotion());
|
|||
const posenet = __toModule(require_posenet());
|
||||
|
||||
// src/hand/box.js
|
||||
import {
|
||||
image
|
||||
} from "@tensorflow/tfjs/dist/tf.es2017.js";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
@ -23627,16 +23532,16 @@ function getBoxCenter(box) {
|
|||
box.startPoint[1] + (box.endPoint[1] - box.startPoint[1]) / 2
|
||||
];
|
||||
}
|
||||
function cutBoxFromImageAndResize(box, image3, cropSize) {
|
||||
const h = image3.shape[1];
|
||||
const w = image3.shape[2];
|
||||
function cutBoxFromImageAndResize(box, image2, cropSize) {
|
||||
const h = image2.shape[1];
|
||||
const w = image2.shape[2];
|
||||
const boxes = [[
|
||||
box.startPoint[1] / h,
|
||||
box.startPoint[0] / w,
|
||||
box.endPoint[1] / h,
|
||||
box.endPoint[0] / w
|
||||
]];
|
||||
return image.cropAndResize(image3, boxes, [0], cropSize);
|
||||
return tf.image.cropAndResize(image2, boxes, [0], cropSize);
|
||||
}
|
||||
function scaleBoxCoordinates(box, factor) {
|
||||
const startPoint = [box.startPoint[0] * factor[0], box.startPoint[1] * factor[1]];
|
||||
|
@ -23757,7 +23662,7 @@ function rotatePoint(homogeneousCoordinate, rotationMatrix) {
|
|||
// src/human.js
|
||||
const handpose = __toModule(require_handpose());
|
||||
const gesture = __toModule(require_gesture());
|
||||
const image2 = __toModule(require_image());
|
||||
const image = __toModule(require_image());
|
||||
const profile = __toModule(require_profile());
|
||||
|
||||
// config.js
|
||||
|
@ -23861,7 +23766,7 @@ var config_default = {
|
|||
};
|
||||
|
||||
// package.json
|
||||
var version = "0.8.5";
|
||||
var version = "0.8.6";
|
||||
|
||||
// src/human.js
|
||||
const disableSkipFrames = {
|
||||
|
@ -23892,7 +23797,7 @@ function mergeDeep(...objects) {
|
|||
}
|
||||
class Human {
|
||||
constructor(userConfig = {}) {
|
||||
this.tf = tf2;
|
||||
this.tf = tf;
|
||||
this.version = version;
|
||||
this.config = mergeDeep(config_default, userConfig);
|
||||
this.fx = null;
|
||||
|
@ -23930,7 +23835,7 @@ class Human {
|
|||
analyze(...msg) {
|
||||
if (!this.analyzeMemoryLeaks)
|
||||
return;
|
||||
const current = tf2.engine().state.numTensors;
|
||||
const current = tf.engine().state.numTensors;
|
||||
const previous = this.numTensors;
|
||||
this.numTensors = current;
|
||||
const leaked = current - previous;
|
||||
|
@ -23942,11 +23847,11 @@ class Human {
|
|||
return null;
|
||||
if (!input)
|
||||
return "input is not defined";
|
||||
if (tf2.ENV.flags.IS_NODE && !(input instanceof tf2.Tensor)) {
|
||||
if (tf.ENV.flags.IS_NODE && !(input instanceof tf.Tensor)) {
|
||||
return "input must be a tensor";
|
||||
}
|
||||
try {
|
||||
tf2.getBackend();
|
||||
tf.getBackend();
|
||||
} catch (e) {
|
||||
return "backend not loaded";
|
||||
}
|
||||
|
@ -23959,9 +23864,9 @@ class Human {
|
|||
this.config = mergeDeep(this.config, userConfig);
|
||||
if (this.firstRun) {
|
||||
this.checkBackend(true);
|
||||
this.log(`version: ${this.version} TensorFlow/JS version: ${tf2.version_core}`);
|
||||
this.log(`version: ${this.version} TensorFlow/JS version: ${tf.version_core}`);
|
||||
this.log("configuration:", this.config);
|
||||
this.log("flags:", tf2.ENV.flags);
|
||||
this.log("flags:", tf.ENV.flags);
|
||||
this.firstRun = false;
|
||||
}
|
||||
if (this.config.async) {
|
||||
|
@ -23973,12 +23878,12 @@ class Human {
|
|||
this.models.posenet,
|
||||
this.models.handpose
|
||||
] = await Promise.all([
|
||||
this.models.age || age.load(this.config),
|
||||
this.models.gender || gender.load(this.config),
|
||||
this.models.emotion || emotion.load(this.config),
|
||||
this.models.facemesh || facemesh.load(this.config.face),
|
||||
this.models.posenet || posenet.load(this.config),
|
||||
this.models.handpose || handpose.load(this.config.hand)
|
||||
this.config.face.age.enabled ? this.models.age || age.load(this.config) : null,
|
||||
this.config.face.gender.enabled ? this.models.gender || gender.load(this.config) : null,
|
||||
this.config.face.emotion.enabled ? this.models.emotion || emotion.load(this.config) : null,
|
||||
this.config.face.enabled ? this.models.facemesh || facemesh.load(this.config.face) : null,
|
||||
this.config.body.enabled ? this.models.posenet || posenet.load(this.config) : null,
|
||||
this.config.hand.enabled ? this.models.handpose || handpose.load(this.config.hand) : null
|
||||
]);
|
||||
} else {
|
||||
if (this.config.face.enabled && !this.models.facemesh)
|
||||
|
@ -24000,26 +23905,26 @@ class Human {
|
|||
}
|
||||
async checkBackend(force) {
|
||||
const timeStamp = now();
|
||||
if (this.config.backend && this.config.backend !== "" && force || tf2.getBackend() !== this.config.backend) {
|
||||
if (this.config.backend && this.config.backend !== "" && force || tf.getBackend() !== this.config.backend) {
|
||||
this.state = "backend";
|
||||
this.log("setting backend:", this.config.backend);
|
||||
if (this.config.backend === "wasm") {
|
||||
this.log("settings wasm path:", this.config.wasmPath);
|
||||
setWasmPaths(this.config.wasmPath);
|
||||
const simd = await tf2.env().getAsync("WASM_HAS_SIMD_SUPPORT");
|
||||
const simd = await tf.env().getAsync("WASM_HAS_SIMD_SUPPORT");
|
||||
if (!simd)
|
||||
this.log("warning: wasm simd support is not enabled");
|
||||
}
|
||||
await tf2.setBackend(this.config.backend);
|
||||
tf2.enableProdMode();
|
||||
await tf.setBackend(this.config.backend);
|
||||
tf.enableProdMode();
|
||||
if (this.config.backend === "webgl") {
|
||||
if (this.config.deallocate) {
|
||||
this.log("changing webgl: WEBGL_DELETE_TEXTURE_THRESHOLD:", this.config.deallocate);
|
||||
tf2.ENV.set("WEBGL_DELETE_TEXTURE_THRESHOLD", this.config.deallocate ? 0 : -1);
|
||||
tf.ENV.set("WEBGL_DELETE_TEXTURE_THRESHOLD", this.config.deallocate ? 0 : -1);
|
||||
}
|
||||
tf2.ENV.set("WEBGL_PACK_DEPTHWISECONV", true);
|
||||
tf.ENV.set("WEBGL_PACK_DEPTHWISECONV", true);
|
||||
}
|
||||
await tf2.ready();
|
||||
await tf.ready();
|
||||
}
|
||||
const current = Math.trunc(now() - timeStamp);
|
||||
if (current > (this.perf.backend || 0))
|
||||
|
@ -24121,10 +24026,10 @@ class Human {
|
|||
await this.checkBackend();
|
||||
await this.load();
|
||||
if (this.config.scoped)
|
||||
tf2.engine().startScope();
|
||||
tf.engine().startScope();
|
||||
this.analyze("Start Scope:");
|
||||
timeStamp = now();
|
||||
const process3 = image2.process(input, this.config);
|
||||
const process3 = image.process(input, this.config);
|
||||
this.perf.image = Math.trunc(now() - timeStamp);
|
||||
this.analyze("Get Image:");
|
||||
if (this.config.async) {
|
||||
|
@ -24165,7 +24070,7 @@ class Human {
|
|||
}
|
||||
process3.tensor.dispose();
|
||||
if (this.config.scoped)
|
||||
tf2.engine().endScope();
|
||||
tf.engine().endScope();
|
||||
this.analyze("End Scope:");
|
||||
let gestureRes = [];
|
||||
if (this.config.gesture.enabled) {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -9,8 +9,11 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytes": 1926,
|
||||
"bytes": 1912,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
}
|
||||
|
@ -58,20 +61,30 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/body/modelBase.js": {
|
||||
"bytes": 901,
|
||||
"imports": []
|
||||
"bytes": 874,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/body/modelMobileNet.js": {
|
||||
"bytes": 611,
|
||||
"bytes": 584,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/body/modelBase.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/body/modelPoseNet.js": {
|
||||
"bytes": 1940,
|
||||
"bytes": 1922,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/body/modelMobileNet.js"
|
||||
},
|
||||
|
@ -120,24 +133,38 @@
|
|||
]
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytes": 2942,
|
||||
"bytes": 2928,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/face/blazeface.js": {
|
||||
"bytes": 6955,
|
||||
"imports": []
|
||||
"bytes": 6941,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/face/box.js": {
|
||||
"bytes": 1947,
|
||||
"imports": []
|
||||
"bytes": 1920,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/face/facemesh.js": {
|
||||
"bytes": 2621,
|
||||
"bytes": 2604,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/blazeface.js"
|
||||
},
|
||||
|
@ -156,8 +183,11 @@
|
|||
]
|
||||
},
|
||||
"src/face/facepipeline.js": {
|
||||
"bytes": 13713,
|
||||
"bytes": 13686,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/box.js"
|
||||
},
|
||||
|
@ -186,8 +216,11 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytes": 3207,
|
||||
"bytes": 3193,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
}
|
||||
|
@ -202,20 +235,30 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/hand/box.js": {
|
||||
"bytes": 3238,
|
||||
"imports": []
|
||||
"bytes": 3211,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/hand/handdetector.js": {
|
||||
"bytes": 4248,
|
||||
"bytes": 4221,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/box.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/hand/handpipeline.js": {
|
||||
"bytes": 7559,
|
||||
"bytes": 7532,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/box.js"
|
||||
},
|
||||
|
@ -225,8 +268,11 @@
|
|||
]
|
||||
},
|
||||
"src/hand/handpose.js": {
|
||||
"bytes": 3047,
|
||||
"bytes": 3026,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/handdetector.js"
|
||||
},
|
||||
|
@ -243,8 +289,11 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytes": 14315,
|
||||
"bytes": 14448,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/facemesh.js"
|
||||
},
|
||||
|
@ -281,8 +330,11 @@
|
|||
]
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytes": 4666,
|
||||
"bytes": 4638,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/imagefx.js"
|
||||
}
|
||||
|
@ -295,55 +347,59 @@
|
|||
"src/profile.js": {
|
||||
"bytes": 1061,
|
||||
"imports": []
|
||||
},
|
||||
"src/tf.js": {
|
||||
"bytes": 871,
|
||||
"imports": []
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"dist/human.esm-nobundle.js.map": {
|
||||
"imports": [],
|
||||
"inputs": {},
|
||||
"bytes": 780280
|
||||
"bytes": 766195
|
||||
},
|
||||
"dist/human.esm-nobundle.js": {
|
||||
"imports": [],
|
||||
"inputs": {
|
||||
"src/face/blazeface.js": {
|
||||
"bytesInOutput": 7075
|
||||
"bytesInOutput": 6970
|
||||
},
|
||||
"src/face/keypoints.js": {
|
||||
"bytesInOutput": 2768
|
||||
},
|
||||
"src/face/box.js": {
|
||||
"bytesInOutput": 2122
|
||||
"bytesInOutput": 2052
|
||||
},
|
||||
"src/face/util.js": {
|
||||
"bytesInOutput": 3043
|
||||
},
|
||||
"src/face/facepipeline.js": {
|
||||
"bytesInOutput": 12482
|
||||
"bytesInOutput": 12379
|
||||
},
|
||||
"src/face/uvcoords.js": {
|
||||
"bytesInOutput": 20584
|
||||
},
|
||||
"src/face/facemesh.js": {
|
||||
"bytesInOutput": 2641
|
||||
"bytesInOutput": 2564
|
||||
},
|
||||
"src/profile.js": {
|
||||
"bytesInOutput": 1118
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytesInOutput": 1947
|
||||
"bytesInOutput": 1826
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytesInOutput": 3108
|
||||
"bytesInOutput": 2980
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytesInOutput": 2828
|
||||
"bytesInOutput": 2697
|
||||
},
|
||||
"src/body/modelBase.js": {
|
||||
"bytesInOutput": 924
|
||||
"bytesInOutput": 866
|
||||
},
|
||||
"src/body/modelMobileNet.js": {
|
||||
"bytesInOutput": 533
|
||||
"bytesInOutput": 471
|
||||
},
|
||||
"src/body/heapSort.js": {
|
||||
"bytesInOutput": 1637
|
||||
|
@ -367,22 +423,22 @@
|
|||
"bytesInOutput": 2410
|
||||
},
|
||||
"src/body/modelPoseNet.js": {
|
||||
"bytesInOutput": 2083
|
||||
"bytesInOutput": 2012
|
||||
},
|
||||
"src/body/posenet.js": {
|
||||
"bytesInOutput": 963
|
||||
},
|
||||
"src/hand/handdetector.js": {
|
||||
"bytesInOutput": 4486
|
||||
"bytesInOutput": 4402
|
||||
},
|
||||
"src/hand/handpipeline.js": {
|
||||
"bytesInOutput": 7243
|
||||
"bytesInOutput": 7165
|
||||
},
|
||||
"src/hand/anchors.js": {
|
||||
"bytesInOutput": 256590
|
||||
},
|
||||
"src/hand/handpose.js": {
|
||||
"bytesInOutput": 3135
|
||||
"bytesInOutput": 3064
|
||||
},
|
||||
"src/gesture.js": {
|
||||
"bytesInOutput": 3038
|
||||
|
@ -391,10 +447,10 @@
|
|||
"bytesInOutput": 20097
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytesInOutput": 4558
|
||||
"bytesInOutput": 4483
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 133
|
||||
"src/tf.js": {
|
||||
"bytesInOutput": 174
|
||||
},
|
||||
"src/face/triangulation.js": {
|
||||
"bytesInOutput": 17898
|
||||
|
@ -403,13 +459,13 @@
|
|||
"bytesInOutput": 227
|
||||
},
|
||||
"src/hand/box.js": {
|
||||
"bytesInOutput": 3096
|
||||
"bytesInOutput": 3037
|
||||
},
|
||||
"src/hand/util.js": {
|
||||
"bytesInOutput": 2884
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 187
|
||||
"bytesInOutput": 186
|
||||
},
|
||||
"config.js": {
|
||||
"bytesInOutput": 1933
|
||||
|
@ -421,13 +477,13 @@
|
|||
"bytesInOutput": 23
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 11792
|
||||
"bytesInOutput": 11998
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 0
|
||||
}
|
||||
},
|
||||
"bytes": 418961
|
||||
"bytes": 417911
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -12316,10 +12316,10 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytes": 1926,
|
||||
"bytes": 1912,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
|
@ -12368,18 +12368,18 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/body/modelBase.js": {
|
||||
"bytes": 901,
|
||||
"bytes": 874,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/body/modelMobileNet.js": {
|
||||
"bytes": 611,
|
||||
"bytes": 584,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/body/modelBase.js"
|
||||
|
@ -12387,10 +12387,10 @@
|
|||
]
|
||||
},
|
||||
"src/body/modelPoseNet.js": {
|
||||
"bytes": 1940,
|
||||
"bytes": 1922,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/body/modelMobileNet.js"
|
||||
|
@ -12440,10 +12440,10 @@
|
|||
]
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytes": 2942,
|
||||
"bytes": 2928,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
|
@ -12451,26 +12451,26 @@
|
|||
]
|
||||
},
|
||||
"src/face/blazeface.js": {
|
||||
"bytes": 6955,
|
||||
"bytes": 6941,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/face/box.js": {
|
||||
"bytes": 1947,
|
||||
"bytes": 1920,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/face/facemesh.js": {
|
||||
"bytes": 2621,
|
||||
"bytes": 2604,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/blazeface.js"
|
||||
|
@ -12490,10 +12490,10 @@
|
|||
]
|
||||
},
|
||||
"src/face/facepipeline.js": {
|
||||
"bytes": 13713,
|
||||
"bytes": 13686,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/box.js"
|
||||
|
@ -12523,10 +12523,10 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytes": 3207,
|
||||
"bytes": 3193,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
|
@ -12542,18 +12542,18 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/hand/box.js": {
|
||||
"bytes": 3238,
|
||||
"bytes": 3211,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/hand/handdetector.js": {
|
||||
"bytes": 4248,
|
||||
"bytes": 4221,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/box.js"
|
||||
|
@ -12561,10 +12561,10 @@
|
|||
]
|
||||
},
|
||||
"src/hand/handpipeline.js": {
|
||||
"bytes": 7559,
|
||||
"bytes": 7532,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/box.js"
|
||||
|
@ -12575,10 +12575,10 @@
|
|||
]
|
||||
},
|
||||
"src/hand/handpose.js": {
|
||||
"bytes": 3047,
|
||||
"bytes": 3026,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/handdetector.js"
|
||||
|
@ -12596,13 +12596,10 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytes": 14315,
|
||||
"bytes": 14448,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
},
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs-backend-wasm/dist/index.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/facemesh.js"
|
||||
|
@ -12640,10 +12637,10 @@
|
|||
]
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytes": 4666,
|
||||
"bytes": 4638,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/imagefx.js"
|
||||
|
@ -12658,6 +12655,17 @@
|
|||
"bytes": 1061,
|
||||
"imports": []
|
||||
},
|
||||
"src/tf.js": {
|
||||
"bytes": 871,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
},
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs-backend-wasm/dist/index.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"empty:/home/vlado/dev/human/node_modules/node-fetch/browser.js": {
|
||||
"bytes": 0,
|
||||
"imports": []
|
||||
|
@ -12683,7 +12691,7 @@
|
|||
"dist/human.esm.js.map": {
|
||||
"imports": [],
|
||||
"inputs": {},
|
||||
"bytes": 5469731
|
||||
"bytes": 5456850
|
||||
},
|
||||
"dist/human.esm.js": {
|
||||
"imports": [],
|
||||
|
@ -12698,7 +12706,7 @@
|
|||
"bytesInOutput": 6782
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs/dist/tf.es2017.js": {
|
||||
"bytesInOutput": 2548112
|
||||
"bytesInOutput": 2548114
|
||||
},
|
||||
"empty:path": {
|
||||
"bytesInOutput": 42
|
||||
|
@ -12716,43 +12724,43 @@
|
|||
"bytesInOutput": 39631
|
||||
},
|
||||
"src/face/blazeface.js": {
|
||||
"bytesInOutput": 7053
|
||||
"bytesInOutput": 6972
|
||||
},
|
||||
"src/face/keypoints.js": {
|
||||
"bytesInOutput": 2768
|
||||
},
|
||||
"src/face/box.js": {
|
||||
"bytesInOutput": 2100
|
||||
"bytesInOutput": 2052
|
||||
},
|
||||
"src/face/util.js": {
|
||||
"bytesInOutput": 3043
|
||||
},
|
||||
"src/face/facepipeline.js": {
|
||||
"bytesInOutput": 12452
|
||||
"bytesInOutput": 12397
|
||||
},
|
||||
"src/face/uvcoords.js": {
|
||||
"bytesInOutput": 20584
|
||||
},
|
||||
"src/face/facemesh.js": {
|
||||
"bytesInOutput": 2620
|
||||
"bytesInOutput": 2564
|
||||
},
|
||||
"src/profile.js": {
|
||||
"bytesInOutput": 1118
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytesInOutput": 1881
|
||||
"bytesInOutput": 1826
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytesInOutput": 3041
|
||||
"bytesInOutput": 2980
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytesInOutput": 2757
|
||||
"bytesInOutput": 2697
|
||||
},
|
||||
"src/body/modelBase.js": {
|
||||
"bytesInOutput": 914
|
||||
"bytesInOutput": 866
|
||||
},
|
||||
"src/body/modelMobileNet.js": {
|
||||
"bytesInOutput": 520
|
||||
"bytesInOutput": 471
|
||||
},
|
||||
"src/body/heapSort.js": {
|
||||
"bytesInOutput": 1639
|
||||
|
@ -12776,22 +12784,22 @@
|
|||
"bytesInOutput": 2412
|
||||
},
|
||||
"src/body/modelPoseNet.js": {
|
||||
"bytesInOutput": 2071
|
||||
"bytesInOutput": 2020
|
||||
},
|
||||
"src/body/posenet.js": {
|
||||
"bytesInOutput": 975
|
||||
},
|
||||
"src/hand/handdetector.js": {
|
||||
"bytesInOutput": 4476
|
||||
"bytesInOutput": 4402
|
||||
},
|
||||
"src/hand/handpipeline.js": {
|
||||
"bytesInOutput": 7214
|
||||
"bytesInOutput": 7165
|
||||
},
|
||||
"src/hand/anchors.js": {
|
||||
"bytesInOutput": 256590
|
||||
},
|
||||
"src/hand/handpose.js": {
|
||||
"bytesInOutput": 3119
|
||||
"bytesInOutput": 3064
|
||||
},
|
||||
"src/gesture.js": {
|
||||
"bytesInOutput": 3038
|
||||
|
@ -12800,10 +12808,10 @@
|
|||
"bytesInOutput": 20097
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytesInOutput": 4547
|
||||
"bytesInOutput": 4495
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 45
|
||||
"src/tf.js": {
|
||||
"bytesInOutput": 44
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs-core/dist/backends/backend.js": {
|
||||
"bytesInOutput": 12318
|
||||
|
@ -13393,6 +13401,9 @@
|
|||
"node_modules/@tensorflow/tfjs-backend-wasm/dist/index.js": {
|
||||
"bytesInOutput": 703
|
||||
},
|
||||
"src/tf.js": {
|
||||
"bytesInOutput": 42
|
||||
},
|
||||
"src/face/triangulation.js": {
|
||||
"bytesInOutput": 17898
|
||||
},
|
||||
|
@ -13400,13 +13411,13 @@
|
|||
"bytesInOutput": 227
|
||||
},
|
||||
"src/hand/box.js": {
|
||||
"bytesInOutput": 3081
|
||||
"bytesInOutput": 3037
|
||||
},
|
||||
"src/hand/util.js": {
|
||||
"bytesInOutput": 2884
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 187
|
||||
"bytesInOutput": 186
|
||||
},
|
||||
"config.js": {
|
||||
"bytesInOutput": 1933
|
||||
|
@ -13418,13 +13429,13 @@
|
|||
"bytesInOutput": 24
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 11818
|
||||
"bytesInOutput": 12024
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 0
|
||||
}
|
||||
},
|
||||
"bytes": 3442260
|
||||
"bytes": 3441681
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -12316,10 +12316,10 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytes": 1926,
|
||||
"bytes": 1912,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
|
@ -12368,18 +12368,18 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/body/modelBase.js": {
|
||||
"bytes": 901,
|
||||
"bytes": 874,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/body/modelMobileNet.js": {
|
||||
"bytes": 611,
|
||||
"bytes": 584,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/body/modelBase.js"
|
||||
|
@ -12387,10 +12387,10 @@
|
|||
]
|
||||
},
|
||||
"src/body/modelPoseNet.js": {
|
||||
"bytes": 1940,
|
||||
"bytes": 1922,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/body/modelMobileNet.js"
|
||||
|
@ -12440,10 +12440,10 @@
|
|||
]
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytes": 2942,
|
||||
"bytes": 2928,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
|
@ -12451,26 +12451,26 @@
|
|||
]
|
||||
},
|
||||
"src/face/blazeface.js": {
|
||||
"bytes": 6955,
|
||||
"bytes": 6941,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/face/box.js": {
|
||||
"bytes": 1947,
|
||||
"bytes": 1920,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/face/facemesh.js": {
|
||||
"bytes": 2621,
|
||||
"bytes": 2604,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/blazeface.js"
|
||||
|
@ -12490,10 +12490,10 @@
|
|||
]
|
||||
},
|
||||
"src/face/facepipeline.js": {
|
||||
"bytes": 13713,
|
||||
"bytes": 13686,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/box.js"
|
||||
|
@ -12523,10 +12523,10 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytes": 3207,
|
||||
"bytes": 3193,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
|
@ -12542,18 +12542,18 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/hand/box.js": {
|
||||
"bytes": 3238,
|
||||
"bytes": 3211,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/hand/handdetector.js": {
|
||||
"bytes": 4248,
|
||||
"bytes": 4221,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/box.js"
|
||||
|
@ -12561,10 +12561,10 @@
|
|||
]
|
||||
},
|
||||
"src/hand/handpipeline.js": {
|
||||
"bytes": 7559,
|
||||
"bytes": 7532,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/box.js"
|
||||
|
@ -12575,10 +12575,10 @@
|
|||
]
|
||||
},
|
||||
"src/hand/handpose.js": {
|
||||
"bytes": 3047,
|
||||
"bytes": 3026,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/handdetector.js"
|
||||
|
@ -12596,13 +12596,10 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytes": 14315,
|
||||
"bytes": 14448,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
},
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs-backend-wasm/dist/index.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/facemesh.js"
|
||||
|
@ -12640,10 +12637,10 @@
|
|||
]
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytes": 4666,
|
||||
"bytes": 4638,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/imagefx.js"
|
||||
|
@ -12658,6 +12655,17 @@
|
|||
"bytes": 1061,
|
||||
"imports": []
|
||||
},
|
||||
"src/tf.js": {
|
||||
"bytes": 871,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.es2017.js"
|
||||
},
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs-backend-wasm/dist/index.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"empty:/home/vlado/dev/human/node_modules/node-fetch/browser.js": {
|
||||
"bytes": 0,
|
||||
"imports": []
|
||||
|
@ -12683,7 +12691,7 @@
|
|||
"dist/human.js.map": {
|
||||
"imports": [],
|
||||
"inputs": {},
|
||||
"bytes": 5430856
|
||||
"bytes": 5432434
|
||||
},
|
||||
"dist/human.js": {
|
||||
"imports": [],
|
||||
|
@ -12698,7 +12706,7 @@
|
|||
"bytesInOutput": 7294
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs/dist/tf.es2017.js": {
|
||||
"bytesInOutput": 2663526
|
||||
"bytesInOutput": 2663519
|
||||
},
|
||||
"empty:path": {
|
||||
"bytesInOutput": 46
|
||||
|
@ -12716,43 +12724,43 @@
|
|||
"bytesInOutput": 41639
|
||||
},
|
||||
"src/face/blazeface.js": {
|
||||
"bytesInOutput": 7353
|
||||
"bytesInOutput": 7270
|
||||
},
|
||||
"src/face/keypoints.js": {
|
||||
"bytesInOutput": 2936
|
||||
},
|
||||
"src/face/box.js": {
|
||||
"bytesInOutput": 2208
|
||||
"bytesInOutput": 2154
|
||||
},
|
||||
"src/face/util.js": {
|
||||
"bytesInOutput": 3205
|
||||
},
|
||||
"src/face/facepipeline.js": {
|
||||
"bytesInOutput": 12926
|
||||
"bytesInOutput": 12869
|
||||
},
|
||||
"src/face/uvcoords.js": {
|
||||
"bytesInOutput": 21528
|
||||
},
|
||||
"src/face/facemesh.js": {
|
||||
"bytesInOutput": 2723
|
||||
"bytesInOutput": 2665
|
||||
},
|
||||
"src/profile.js": {
|
||||
"bytesInOutput": 1156
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytesInOutput": 1975
|
||||
"bytesInOutput": 1906
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytesInOutput": 3182
|
||||
"bytesInOutput": 3107
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytesInOutput": 2883
|
||||
"bytesInOutput": 2809
|
||||
},
|
||||
"src/body/modelBase.js": {
|
||||
"bytesInOutput": 970
|
||||
"bytesInOutput": 920
|
||||
},
|
||||
"src/body/modelMobileNet.js": {
|
||||
"bytesInOutput": 548
|
||||
"bytesInOutput": 497
|
||||
},
|
||||
"src/body/heapSort.js": {
|
||||
"bytesInOutput": 1767
|
||||
|
@ -12773,40 +12781,43 @@
|
|||
"bytesInOutput": 2100
|
||||
},
|
||||
"src/body/util.js": {
|
||||
"bytesInOutput": 2538
|
||||
"bytesInOutput": 2536
|
||||
},
|
||||
"src/body/modelPoseNet.js": {
|
||||
"bytesInOutput": 2148
|
||||
"bytesInOutput": 2095
|
||||
},
|
||||
"src/body/posenet.js": {
|
||||
"bytesInOutput": 1015
|
||||
},
|
||||
"src/hand/handdetector.js": {
|
||||
"bytesInOutput": 4651
|
||||
"bytesInOutput": 4572
|
||||
},
|
||||
"src/hand/handpipeline.js": {
|
||||
"bytesInOutput": 7528
|
||||
"bytesInOutput": 7470
|
||||
},
|
||||
"src/hand/anchors.js": {
|
||||
"bytesInOutput": 291926
|
||||
},
|
||||
"src/hand/handpose.js": {
|
||||
"bytesInOutput": 3262
|
||||
"bytesInOutput": 3205
|
||||
},
|
||||
"src/gesture.js": {
|
||||
"bytesInOutput": 3154
|
||||
},
|
||||
"src/imagefx.js": {
|
||||
"bytesInOutput": 21517
|
||||
"bytesInOutput": 21513
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytesInOutput": 4705
|
||||
"bytesInOutput": 4651
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 13722
|
||||
"bytesInOutput": 13878
|
||||
},
|
||||
"src/tf.js": {
|
||||
"bytesInOutput": 46
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs-core/dist/backends/backend.js": {
|
||||
"bytesInOutput": 13308
|
||||
"bytesInOutput": 13307
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs-core/dist/util_base.js": {
|
||||
"bytesInOutput": 13124
|
||||
|
@ -13187,7 +13198,7 @@
|
|||
"bytesInOutput": 785
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs-backend-wasm/dist/kernels/CropAndResize.js": {
|
||||
"bytesInOutput": 2696
|
||||
"bytesInOutput": 2683
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs-backend-wasm/dist/kernels/Cumsum.js": {
|
||||
"bytesInOutput": 2555
|
||||
|
@ -13211,7 +13222,7 @@
|
|||
"bytesInOutput": 1073
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs-backend-wasm/dist/kernels/FlipLeftRight.js": {
|
||||
"bytesInOutput": 1587
|
||||
"bytesInOutput": 1575
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs-backend-wasm/dist/kernels/FloorDiv.js": {
|
||||
"bytesInOutput": 860
|
||||
|
@ -13313,7 +13324,7 @@
|
|||
"bytesInOutput": 1839
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs-backend-wasm/dist/kernels/RotateWithOffset.js": {
|
||||
"bytesInOutput": 2182
|
||||
"bytesInOutput": 2170
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs-backend-wasm/dist/kernels/Rsqrt.js": {
|
||||
"bytesInOutput": 789
|
||||
|
@ -13393,11 +13404,14 @@
|
|||
"node_modules/@tensorflow/tfjs-backend-wasm/dist/index.js": {
|
||||
"bytesInOutput": 735
|
||||
},
|
||||
"src/tf.js": {
|
||||
"bytesInOutput": 44
|
||||
},
|
||||
"src/face/triangulation.js": {
|
||||
"bytesInOutput": 23182
|
||||
},
|
||||
"src/hand/box.js": {
|
||||
"bytesInOutput": 3233
|
||||
"bytesInOutput": 3183
|
||||
},
|
||||
"src/hand/util.js": {
|
||||
"bytesInOutput": 3038
|
||||
|
@ -13412,7 +13426,7 @@
|
|||
"bytesInOutput": 26
|
||||
}
|
||||
},
|
||||
"bytes": 3631167
|
||||
"bytes": 3630472
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ var __toModule = (module2) => {
|
|||
|
||||
// src/face/blazeface.js
|
||||
var require_blazeface = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const NUM_LANDMARKS = 6;
|
||||
function generateAnchors(inputSize) {
|
||||
const spec = {strides: [inputSize / 16, inputSize / 8], anchors: [2, 6]};
|
||||
|
@ -63,31 +62,31 @@ var require_blazeface = __commonJS((exports2) => {
|
|||
};
|
||||
const createBox = (startEndTensor) => ({
|
||||
startEndTensor,
|
||||
startPoint: tf3.slice(startEndTensor, [0, 0], [-1, 2]),
|
||||
endPoint: tf3.slice(startEndTensor, [0, 2], [-1, 2])
|
||||
startPoint: tf.slice(startEndTensor, [0, 0], [-1, 2]),
|
||||
endPoint: tf.slice(startEndTensor, [0, 2], [-1, 2])
|
||||
});
|
||||
const scaleBox = (box, factors) => {
|
||||
const starts = tf3.mul(box.startPoint, factors);
|
||||
const ends = tf3.mul(box.endPoint, factors);
|
||||
const newCoordinates = tf3.concat2d([starts, ends], 1);
|
||||
const starts = tf.mul(box.startPoint, factors);
|
||||
const ends = tf.mul(box.endPoint, factors);
|
||||
const newCoordinates = tf.concat2d([starts, ends], 1);
|
||||
return createBox(newCoordinates);
|
||||
};
|
||||
function decodeBounds(boxOutputs, anchors, inputSize) {
|
||||
const boxStarts = tf3.slice(boxOutputs, [0, 1], [-1, 2]);
|
||||
const centers = tf3.add(boxStarts, anchors);
|
||||
const boxSizes = tf3.slice(boxOutputs, [0, 3], [-1, 2]);
|
||||
const boxSizesNormalized = tf3.div(boxSizes, inputSize);
|
||||
const centersNormalized = tf3.div(centers, inputSize);
|
||||
const halfBoxSize = tf3.div(boxSizesNormalized, 2);
|
||||
const starts = tf3.sub(centersNormalized, halfBoxSize);
|
||||
const ends = tf3.add(centersNormalized, halfBoxSize);
|
||||
const startNormalized = tf3.mul(starts, inputSize);
|
||||
const endNormalized = tf3.mul(ends, inputSize);
|
||||
const boxStarts = tf.slice(boxOutputs, [0, 1], [-1, 2]);
|
||||
const centers = tf.add(boxStarts, anchors);
|
||||
const boxSizes = tf.slice(boxOutputs, [0, 3], [-1, 2]);
|
||||
const boxSizesNormalized = tf.div(boxSizes, inputSize);
|
||||
const centersNormalized = tf.div(centers, inputSize);
|
||||
const halfBoxSize = tf.div(boxSizesNormalized, 2);
|
||||
const starts = tf.sub(centersNormalized, halfBoxSize);
|
||||
const ends = tf.add(centersNormalized, halfBoxSize);
|
||||
const startNormalized = tf.mul(starts, inputSize);
|
||||
const endNormalized = tf.mul(ends, inputSize);
|
||||
const concatAxis = 1;
|
||||
return tf3.concat2d([startNormalized, endNormalized], concatAxis);
|
||||
return tf.concat2d([startNormalized, endNormalized], concatAxis);
|
||||
}
|
||||
function scaleBoxFromPrediction(face2, scaleFactor) {
|
||||
return tf3.tidy(() => {
|
||||
return tf.tidy(() => {
|
||||
const box = face2["box"] ? face2["box"] : face2;
|
||||
return scaleBox(box, scaleFactor).startEndTensor.squeeze();
|
||||
});
|
||||
|
@ -98,37 +97,37 @@ var require_blazeface = __commonJS((exports2) => {
|
|||
this.width = config2.detector.inputSize;
|
||||
this.height = config2.detector.inputSize;
|
||||
this.anchorsData = generateAnchors(config2.detector.inputSize);
|
||||
this.anchors = tf3.tensor2d(this.anchorsData);
|
||||
this.inputSize = tf3.tensor1d([this.width, this.height]);
|
||||
this.anchors = tf.tensor2d(this.anchorsData);
|
||||
this.inputSize = tf.tensor1d([this.width, this.height]);
|
||||
this.config = config2;
|
||||
this.scaleFaces = 0.8;
|
||||
}
|
||||
async getBoundingBoxes(inputImage) {
|
||||
if (!inputImage || inputImage.isDisposedInternal || inputImage.shape.length !== 4 || inputImage.shape[1] < 1 || inputImage.shape[2] < 1)
|
||||
return null;
|
||||
const [detectedOutputs, boxes, scores] = tf3.tidy(() => {
|
||||
const [detectedOutputs, boxes, scores] = tf.tidy(() => {
|
||||
const resizedImage = inputImage.resizeBilinear([this.width, this.height]);
|
||||
const normalizedImage = tf3.sub(resizedImage.div(127.5), 1);
|
||||
const normalizedImage = tf.sub(resizedImage.div(127.5), 1);
|
||||
const batchedPrediction = this.blazeFaceModel.predict(normalizedImage);
|
||||
let prediction;
|
||||
if (Array.isArray(batchedPrediction)) {
|
||||
const sorted = batchedPrediction.sort((a, b) => a.size - b.size);
|
||||
const concat384 = tf3.concat([sorted[0], sorted[2]], 2);
|
||||
const concat512 = tf3.concat([sorted[1], sorted[3]], 2);
|
||||
const concat2 = tf3.concat([concat512, concat384], 1);
|
||||
prediction = concat2.squeeze(0);
|
||||
const concat384 = tf.concat([sorted[0], sorted[2]], 2);
|
||||
const concat512 = tf.concat([sorted[1], sorted[3]], 2);
|
||||
const concat = tf.concat([concat512, concat384], 1);
|
||||
prediction = concat.squeeze(0);
|
||||
} else {
|
||||
prediction = batchedPrediction.squeeze();
|
||||
}
|
||||
const decodedBounds = decodeBounds(prediction, this.anchors, this.inputSize);
|
||||
const logits = tf3.slice(prediction, [0, 0], [-1, 1]);
|
||||
const scoresOut = tf3.sigmoid(logits).squeeze();
|
||||
const logits = tf.slice(prediction, [0, 0], [-1, 1]);
|
||||
const scoresOut = tf.sigmoid(logits).squeeze();
|
||||
return [prediction, decodedBounds, scoresOut];
|
||||
});
|
||||
const boxIndicesTensor = await tf3.image.nonMaxSuppressionAsync(boxes, scores, this.config.detector.maxFaces, this.config.detector.iouThreshold, this.config.detector.scoreThreshold);
|
||||
const boxIndicesTensor = await tf.image.nonMaxSuppressionAsync(boxes, scores, this.config.detector.maxFaces, this.config.detector.iouThreshold, this.config.detector.scoreThreshold);
|
||||
const boxIndices = boxIndicesTensor.arraySync();
|
||||
boxIndicesTensor.dispose();
|
||||
const boundingBoxesMap = boxIndices.map((boxIndex) => tf3.slice(boxes, [boxIndex, 0], [1, -1]));
|
||||
const boundingBoxesMap = boxIndices.map((boxIndex) => tf.slice(boxes, [boxIndex, 0], [1, -1]));
|
||||
const boundingBoxes = boundingBoxesMap.map((boundingBox) => {
|
||||
const vals = boundingBox.arraySync();
|
||||
boundingBox.dispose();
|
||||
|
@ -142,7 +141,7 @@ var require_blazeface = __commonJS((exports2) => {
|
|||
if (confidence > this.config.detector.minConfidence) {
|
||||
const box = createBox(boundingBoxes[i]);
|
||||
const anchor = this.anchorsData[boxIndex];
|
||||
const landmarks = tf3.tidy(() => tf3.slice(detectedOutputs, [boxIndex, NUM_LANDMARKS - 1], [1, -1]).squeeze().reshape([NUM_LANDMARKS, -1]));
|
||||
const landmarks = tf.tidy(() => tf.slice(detectedOutputs, [boxIndex, NUM_LANDMARKS - 1], [1, -1]).squeeze().reshape([NUM_LANDMARKS, -1]));
|
||||
annotatedBoxes.push({box, landmarks, anchor, confidence});
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +184,7 @@ var require_blazeface = __commonJS((exports2) => {
|
|||
}
|
||||
}
|
||||
async function load(config2) {
|
||||
const blazeface = await tf3.loadGraphModel(config2.detector.modelPath, {fromTFHub: config2.detector.modelPath.includes("tfhub.dev")});
|
||||
const blazeface = await loadGraphModel(config2.detector.modelPath, {fromTFHub: config2.detector.modelPath.includes("tfhub.dev")});
|
||||
const model = new BlazeFaceModel(blazeface, config2);
|
||||
console.log(`Human: load model: ${config2.detector.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
return model;
|
||||
|
@ -283,7 +282,6 @@ var require_keypoints = __commonJS((exports2) => {
|
|||
|
||||
// src/face/box.js
|
||||
var require_box = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
function scaleBoxCoordinates2(box, factor) {
|
||||
const startPoint = [box.startPoint[0] * factor[0], box.startPoint[1] * factor[1]];
|
||||
const endPoint = [box.endPoint[0] * factor[0], box.endPoint[1] * factor[1]];
|
||||
|
@ -304,16 +302,16 @@ var require_box = __commonJS((exports2) => {
|
|||
];
|
||||
}
|
||||
exports2.getBoxCenter = getBoxCenter2;
|
||||
function cutBoxFromImageAndResize2(box, image4, cropSize) {
|
||||
const h = image4.shape[1];
|
||||
const w = image4.shape[2];
|
||||
function cutBoxFromImageAndResize2(box, image2, cropSize) {
|
||||
const h = image2.shape[1];
|
||||
const w = image2.shape[2];
|
||||
const boxes = [[
|
||||
box.startPoint[1] / h,
|
||||
box.startPoint[0] / w,
|
||||
box.endPoint[1] / h,
|
||||
box.endPoint[0] / w
|
||||
]];
|
||||
return tf3.image.cropAndResize(image4, boxes, [0], cropSize);
|
||||
return tf.image.cropAndResize(image2, boxes, [0], cropSize);
|
||||
}
|
||||
exports2.cutBoxFromImageAndResize = cutBoxFromImageAndResize2;
|
||||
function enlargeBox2(box, factor = 1.5) {
|
||||
|
@ -422,7 +420,6 @@ var require_util = __commonJS((exports2) => {
|
|||
|
||||
// src/face/facepipeline.js
|
||||
var require_facepipeline = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const bounding = __toModule(require_box());
|
||||
const keypoints = __toModule(require_keypoints());
|
||||
const util = __toModule(require_util());
|
||||
|
@ -501,14 +498,14 @@ var require_facepipeline = __commonJS((exports2) => {
|
|||
getEyeBox(rawCoords, face2, eyeInnerCornerIndex, eyeOuterCornerIndex, flip = false) {
|
||||
const box = bounding.squarifyBox(bounding.enlargeBox(this.calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), this.irisEnlarge));
|
||||
const boxSize = bounding.getBoxSize(box);
|
||||
let crop = tf3.image.cropAndResize(face2, [[
|
||||
let crop = tf.image.cropAndResize(face2, [[
|
||||
box.startPoint[1] / this.meshHeight,
|
||||
box.startPoint[0] / this.meshWidth,
|
||||
box.endPoint[1] / this.meshHeight,
|
||||
box.endPoint[0] / this.meshWidth
|
||||
]], [0], [this.irisSize, this.irisSize]);
|
||||
if (flip) {
|
||||
crop = tf3.image.flipLeftRight(crop);
|
||||
crop = tf.image.flipLeftRight(crop);
|
||||
}
|
||||
return {box, boxSize, crop};
|
||||
}
|
||||
|
@ -580,7 +577,7 @@ var require_facepipeline = __commonJS((exports2) => {
|
|||
prediction.landmarks.dispose();
|
||||
});
|
||||
}
|
||||
let results = tf3.tidy(() => this.storedBoxes.map((box, i) => {
|
||||
let results = tf.tidy(() => this.storedBoxes.map((box, i) => {
|
||||
let angle = 0;
|
||||
const boxLandmarksFromMeshModel = box.landmarks.length >= LANDMARKS_COUNT;
|
||||
let [indexOfMouth, indexOfForehead] = MESH_KEYPOINTS_LINE_OF_SYMMETRY_INDICES;
|
||||
|
@ -593,7 +590,7 @@ var require_facepipeline = __commonJS((exports2) => {
|
|||
let rotatedImage = input;
|
||||
let rotationMatrix = util.IDENTITY_MATRIX;
|
||||
if (angle !== 0) {
|
||||
rotatedImage = tf3.image.rotateWithOffset(input, angle, 0, faceCenterNormalized);
|
||||
rotatedImage = tf.image.rotateWithOffset(input, angle, 0, faceCenterNormalized);
|
||||
rotationMatrix = util.buildRotationMatrix(-angle, faceCenter);
|
||||
}
|
||||
const boxCPU = {startPoint: box.startPoint, endPoint: box.endPoint};
|
||||
|
@ -615,12 +612,12 @@ var require_facepipeline = __commonJS((exports2) => {
|
|||
coords.dispose();
|
||||
return null;
|
||||
}
|
||||
const coordsReshaped = tf3.reshape(coords, [-1, 3]);
|
||||
const coordsReshaped = tf.reshape(coords, [-1, 3]);
|
||||
let rawCoords = coordsReshaped.arraySync();
|
||||
if (config2.iris.enabled) {
|
||||
const {box: leftEyeBox, boxSize: leftEyeBoxSize, crop: leftEyeCrop} = this.getEyeBox(rawCoords, face2, LEFT_EYE_BOUNDS[0], LEFT_EYE_BOUNDS[1], true);
|
||||
const {box: rightEyeBox, boxSize: rightEyeBoxSize, crop: rightEyeCrop} = this.getEyeBox(rawCoords, face2, RIGHT_EYE_BOUNDS[0], RIGHT_EYE_BOUNDS[1]);
|
||||
const eyePredictions = this.irisModel.predict(tf3.concat([leftEyeCrop, rightEyeCrop]));
|
||||
const eyePredictions = this.irisModel.predict(tf.concat([leftEyeCrop, rightEyeCrop]));
|
||||
const eyePredictionsData = eyePredictions.dataSync();
|
||||
eyePredictions.dispose();
|
||||
const leftEyeData = eyePredictionsData.slice(0, IRIS_NUM_COORDINATES * 3);
|
||||
|
@ -641,9 +638,9 @@ var require_facepipeline = __commonJS((exports2) => {
|
|||
rawCoords = rawCoords.concat(adjustedLeftIrisCoords).concat(adjustedRightIrisCoords);
|
||||
}
|
||||
const transformedCoordsData = this.transformRawCoords(rawCoords, box, angle, rotationMatrix);
|
||||
tf3.dispose(rawCoords);
|
||||
tf.dispose(rawCoords);
|
||||
const landmarksBox = bounding.enlargeBox(this.calculateLandmarksBoundingBox(transformedCoordsData));
|
||||
const transformedCoords = tf3.tensor2d(transformedCoordsData);
|
||||
const transformedCoords = tf.tensor2d(transformedCoordsData);
|
||||
const prediction = {
|
||||
coords: transformedCoords,
|
||||
box: landmarksBox,
|
||||
|
@ -1145,7 +1142,6 @@ var require_uvcoords = __commonJS((exports2) => {
|
|||
|
||||
// src/face/facemesh.js
|
||||
var require_facemesh = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const blazeface = __toModule(require_blazeface());
|
||||
const keypoints = __toModule(require_keypoints());
|
||||
const pipe = __toModule(require_facepipeline());
|
||||
|
@ -1178,7 +1174,7 @@ var require_facemesh = __commonJS((exports2) => {
|
|||
box: prediction.box ? [prediction.box.startPoint[0], prediction.box.startPoint[1], prediction.box.endPoint[0] - prediction.box.startPoint[0], prediction.box.endPoint[1] - prediction.box.startPoint[1]] : 0,
|
||||
mesh,
|
||||
annotations,
|
||||
image: prediction.image ? tf3.clone(prediction.image) : null
|
||||
image: prediction.image ? tf.clone(prediction.image) : null
|
||||
});
|
||||
if (prediction.coords)
|
||||
prediction.coords.dispose();
|
||||
|
@ -1191,8 +1187,8 @@ var require_facemesh = __commonJS((exports2) => {
|
|||
async function load(config2) {
|
||||
const models = await Promise.all([
|
||||
blazeface.load(config2),
|
||||
tf3.loadGraphModel(config2.mesh.modelPath, {fromTFHub: config2.mesh.modelPath.includes("tfhub.dev")}),
|
||||
tf3.loadGraphModel(config2.iris.modelPath, {fromTFHub: config2.iris.modelPath.includes("tfhub.dev")})
|
||||
loadGraphModel(config2.mesh.modelPath, {fromTFHub: config2.mesh.modelPath.includes("tfhub.dev")}),
|
||||
loadGraphModel(config2.iris.modelPath, {fromTFHub: config2.iris.modelPath.includes("tfhub.dev")})
|
||||
]);
|
||||
const faceMesh = new MediaPipeFaceMesh(models[0], models[1], models[2], config2);
|
||||
console.log(`Human: load model: ${config2.mesh.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
|
@ -1234,7 +1230,6 @@ var require_profile = __commonJS((exports2) => {
|
|||
|
||||
// src/age/age.js
|
||||
var require_age = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const profile2 = __toModule(require_profile());
|
||||
const models = {};
|
||||
let last = {age: 0};
|
||||
|
@ -1242,12 +1237,12 @@ var require_age = __commonJS((exports2) => {
|
|||
const zoom = [0, 0];
|
||||
async function load(config2) {
|
||||
if (!models.age) {
|
||||
models.age = await tf3.loadGraphModel(config2.face.age.modelPath);
|
||||
models.age = await loadGraphModel(config2.face.age.modelPath);
|
||||
console.log(`Human: load model: ${config2.face.age.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
}
|
||||
return models.age;
|
||||
}
|
||||
async function predict(image4, config2) {
|
||||
async function predict(image2, config2) {
|
||||
if (frame < config2.face.age.skipFrames && last.age && last.age > 0) {
|
||||
frame += 1;
|
||||
return last;
|
||||
|
@ -1255,21 +1250,21 @@ var require_age = __commonJS((exports2) => {
|
|||
frame = 0;
|
||||
return new Promise(async (resolve) => {
|
||||
const box = [[
|
||||
image4.shape[1] * zoom[0] / image4.shape[1],
|
||||
image4.shape[2] * zoom[1] / image4.shape[2],
|
||||
(image4.shape[1] - image4.shape[1] * zoom[0]) / image4.shape[1],
|
||||
(image4.shape[2] - image4.shape[2] * zoom[1]) / image4.shape[2]
|
||||
image2.shape[1] * zoom[0] / image2.shape[1],
|
||||
image2.shape[2] * zoom[1] / image2.shape[2],
|
||||
(image2.shape[1] - image2.shape[1] * zoom[0]) / image2.shape[1],
|
||||
(image2.shape[2] - image2.shape[2] * zoom[1]) / image2.shape[2]
|
||||
]];
|
||||
const resize = tf3.image.cropAndResize(image4, box, [0], [config2.face.age.inputSize, config2.face.age.inputSize]);
|
||||
const enhance = tf3.mul(resize, [255]);
|
||||
tf3.dispose(resize);
|
||||
const resize = tf.image.cropAndResize(image2, box, [0], [config2.face.age.inputSize, config2.face.age.inputSize]);
|
||||
const enhance = tf.mul(resize, [255]);
|
||||
tf.dispose(resize);
|
||||
let ageT;
|
||||
const obj = {};
|
||||
if (!config2.profile) {
|
||||
if (config2.face.age.enabled)
|
||||
ageT = await models.age.predict(enhance);
|
||||
} else {
|
||||
const profileAge = config2.face.age.enabled ? await tf3.profile(() => models.age.predict(enhance)) : {};
|
||||
const profileAge = config2.face.age.enabled ? await tf.profile(() => models.age.predict(enhance)) : {};
|
||||
ageT = profileAge.result.clone();
|
||||
profileAge.result.dispose();
|
||||
profile2.run("age", profileAge);
|
||||
|
@ -1290,7 +1285,6 @@ var require_age = __commonJS((exports2) => {
|
|||
|
||||
// src/gender/gender.js
|
||||
var require_gender = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const profile2 = __toModule(require_profile());
|
||||
const models = {};
|
||||
let last = {gender: ""};
|
||||
|
@ -1300,13 +1294,13 @@ var require_gender = __commonJS((exports2) => {
|
|||
const rgb = [0.2989, 0.587, 0.114];
|
||||
async function load(config2) {
|
||||
if (!models.gender) {
|
||||
models.gender = await tf3.loadGraphModel(config2.face.gender.modelPath);
|
||||
models.gender = await loadGraphModel(config2.face.gender.modelPath);
|
||||
alternative = models.gender.inputs[0].shape[3] === 1;
|
||||
console.log(`Human: load model: ${config2.face.gender.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
}
|
||||
return models.gender;
|
||||
}
|
||||
async function predict(image4, config2) {
|
||||
async function predict(image2, config2) {
|
||||
if (frame < config2.face.gender.skipFrames && last.gender !== "") {
|
||||
frame += 1;
|
||||
return last;
|
||||
|
@ -1314,33 +1308,33 @@ var require_gender = __commonJS((exports2) => {
|
|||
frame = 0;
|
||||
return new Promise(async (resolve) => {
|
||||
const box = [[
|
||||
image4.shape[1] * zoom[0] / image4.shape[1],
|
||||
image4.shape[2] * zoom[1] / image4.shape[2],
|
||||
(image4.shape[1] - image4.shape[1] * zoom[0]) / image4.shape[1],
|
||||
(image4.shape[2] - image4.shape[2] * zoom[1]) / image4.shape[2]
|
||||
image2.shape[1] * zoom[0] / image2.shape[1],
|
||||
image2.shape[2] * zoom[1] / image2.shape[2],
|
||||
(image2.shape[1] - image2.shape[1] * zoom[0]) / image2.shape[1],
|
||||
(image2.shape[2] - image2.shape[2] * zoom[1]) / image2.shape[2]
|
||||
]];
|
||||
const resize = tf3.image.cropAndResize(image4, box, [0], [config2.face.gender.inputSize, config2.face.gender.inputSize]);
|
||||
const resize = tf.image.cropAndResize(image2, box, [0], [config2.face.gender.inputSize, config2.face.gender.inputSize]);
|
||||
let enhance;
|
||||
if (alternative) {
|
||||
enhance = tf3.tidy(() => {
|
||||
const [red, green, blue] = tf3.split(resize, 3, 3);
|
||||
const redNorm = tf3.mul(red, rgb[0]);
|
||||
const greenNorm = tf3.mul(green, rgb[1]);
|
||||
const blueNorm = tf3.mul(blue, rgb[2]);
|
||||
const grayscale = tf3.addN([redNorm, greenNorm, blueNorm]);
|
||||
enhance = tf.tidy(() => {
|
||||
const [red, green, blue] = tf.split(resize, 3, 3);
|
||||
const redNorm = tf.mul(red, rgb[0]);
|
||||
const greenNorm = tf.mul(green, rgb[1]);
|
||||
const blueNorm = tf.mul(blue, rgb[2]);
|
||||
const grayscale = tf.addN([redNorm, greenNorm, blueNorm]);
|
||||
return grayscale.sub(0.5).mul(2);
|
||||
});
|
||||
} else {
|
||||
enhance = tf3.mul(resize, [255]);
|
||||
enhance = tf.mul(resize, [255]);
|
||||
}
|
||||
tf3.dispose(resize);
|
||||
tf.dispose(resize);
|
||||
let genderT;
|
||||
const obj = {};
|
||||
if (!config2.profile) {
|
||||
if (config2.face.gender.enabled)
|
||||
genderT = await models.gender.predict(enhance);
|
||||
} else {
|
||||
const profileGender = config2.face.gender.enabled ? await tf3.profile(() => models.gender.predict(enhance)) : {};
|
||||
const profileGender = config2.face.gender.enabled ? await tf.profile(() => models.gender.predict(enhance)) : {};
|
||||
genderT = profileGender.result.clone();
|
||||
profileGender.result.dispose();
|
||||
profile2.run("gender", profileGender);
|
||||
|
@ -1373,7 +1367,6 @@ var require_gender = __commonJS((exports2) => {
|
|||
|
||||
// src/emotion/emotion.js
|
||||
var require_emotion = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const profile2 = __toModule(require_profile());
|
||||
const annotations = ["angry", "disgust", "fear", "happy", "sad", "surpise", "neutral"];
|
||||
const models = {};
|
||||
|
@ -1384,12 +1377,12 @@ var require_emotion = __commonJS((exports2) => {
|
|||
const scale = 1;
|
||||
async function load(config2) {
|
||||
if (!models.emotion) {
|
||||
models.emotion = await tf3.loadGraphModel(config2.face.emotion.modelPath);
|
||||
models.emotion = await loadGraphModel(config2.face.emotion.modelPath);
|
||||
console.log(`Human: load model: ${config2.face.emotion.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
}
|
||||
return models.emotion;
|
||||
}
|
||||
async function predict(image4, config2) {
|
||||
async function predict(image2, config2) {
|
||||
if (frame < config2.face.emotion.skipFrames && last.length > 0) {
|
||||
frame += 1;
|
||||
return last;
|
||||
|
@ -1397,25 +1390,25 @@ var require_emotion = __commonJS((exports2) => {
|
|||
frame = 0;
|
||||
return new Promise(async (resolve) => {
|
||||
const box = [[
|
||||
image4.shape[1] * zoom[0] / image4.shape[1],
|
||||
image4.shape[2] * zoom[1] / image4.shape[2],
|
||||
(image4.shape[1] - image4.shape[1] * zoom[0]) / image4.shape[1],
|
||||
(image4.shape[2] - image4.shape[2] * zoom[1]) / image4.shape[2]
|
||||
image2.shape[1] * zoom[0] / image2.shape[1],
|
||||
image2.shape[2] * zoom[1] / image2.shape[2],
|
||||
(image2.shape[1] - image2.shape[1] * zoom[0]) / image2.shape[1],
|
||||
(image2.shape[2] - image2.shape[2] * zoom[1]) / image2.shape[2]
|
||||
]];
|
||||
const resize = tf3.image.cropAndResize(image4, box, [0], [config2.face.emotion.inputSize, config2.face.emotion.inputSize]);
|
||||
const [red, green, blue] = tf3.split(resize, 3, 3);
|
||||
const resize = tf.image.cropAndResize(image2, box, [0], [config2.face.emotion.inputSize, config2.face.emotion.inputSize]);
|
||||
const [red, green, blue] = tf.split(resize, 3, 3);
|
||||
resize.dispose();
|
||||
const redNorm = tf3.mul(red, rgb[0]);
|
||||
const greenNorm = tf3.mul(green, rgb[1]);
|
||||
const blueNorm = tf3.mul(blue, rgb[2]);
|
||||
const redNorm = tf.mul(red, rgb[0]);
|
||||
const greenNorm = tf.mul(green, rgb[1]);
|
||||
const blueNorm = tf.mul(blue, rgb[2]);
|
||||
red.dispose();
|
||||
green.dispose();
|
||||
blue.dispose();
|
||||
const grayscale = tf3.addN([redNorm, greenNorm, blueNorm]);
|
||||
const grayscale = tf.addN([redNorm, greenNorm, blueNorm]);
|
||||
redNorm.dispose();
|
||||
greenNorm.dispose();
|
||||
blueNorm.dispose();
|
||||
const normalize = tf3.tidy(() => grayscale.sub(0.5).mul(2));
|
||||
const normalize = tf.tidy(() => grayscale.sub(0.5).mul(2));
|
||||
grayscale.dispose();
|
||||
const obj = [];
|
||||
if (config2.face.emotion.enabled) {
|
||||
|
@ -1423,9 +1416,9 @@ var require_emotion = __commonJS((exports2) => {
|
|||
if (!config2.profile) {
|
||||
const emotionT = await models.emotion.predict(normalize);
|
||||
data2 = emotionT.dataSync();
|
||||
tf3.dispose(emotionT);
|
||||
tf.dispose(emotionT);
|
||||
} else {
|
||||
const profileData = await tf3.profile(() => models.emotion.predict(normalize));
|
||||
const profileData = await tf.profile(() => models.emotion.predict(normalize));
|
||||
data2 = profileData.result.dataSync();
|
||||
profileData.result.dispose();
|
||||
profile2.run("emotion", profileData);
|
||||
|
@ -1447,14 +1440,13 @@ var require_emotion = __commonJS((exports2) => {
|
|||
|
||||
// src/body/modelBase.js
|
||||
var require_modelBase = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
class BaseModel {
|
||||
constructor(model, outputStride) {
|
||||
this.model = model;
|
||||
this.outputStride = outputStride;
|
||||
}
|
||||
predict(input) {
|
||||
return tf3.tidy(() => {
|
||||
return tf.tidy(() => {
|
||||
const asFloat = this.preprocessInput(input.toFloat());
|
||||
const asBatch = asFloat.expandDims(0);
|
||||
const results = this.model.predict(asBatch);
|
||||
|
@ -1477,11 +1469,10 @@ var require_modelBase = __commonJS((exports2) => {
|
|||
|
||||
// src/body/modelMobileNet.js
|
||||
var require_modelMobileNet = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const modelBase = __toModule(require_modelBase());
|
||||
class MobileNet extends modelBase.BaseModel {
|
||||
preprocessInput(input) {
|
||||
return tf3.tidy(() => tf3.div(input, 127.5).sub(1));
|
||||
return tf.tidy(() => tf.div(input, 127.5).sub(1));
|
||||
}
|
||||
nameOutputResults(results) {
|
||||
const [offsets, heatmap, displacementFwd, displacementBwd] = results;
|
||||
|
@ -1896,8 +1887,8 @@ var require_util2 = __commonJS((exports2) => {
|
|||
};
|
||||
}
|
||||
exports2.scalePose = scalePose;
|
||||
function resizeTo(image3, [targetH, targetW]) {
|
||||
const input = image3.squeeze(0);
|
||||
function resizeTo(image2, [targetH, targetW]) {
|
||||
const input = image2.squeeze(0);
|
||||
const resized = input.resizeBilinear([targetH, targetW]);
|
||||
input.dispose();
|
||||
return resized;
|
||||
|
@ -1912,7 +1903,6 @@ var require_util2 = __commonJS((exports2) => {
|
|||
|
||||
// src/body/modelPoseNet.js
|
||||
var require_modelPoseNet = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const modelMobileNet = __toModule(require_modelMobileNet());
|
||||
const decodeMultiple = __toModule(require_decodeMultiple());
|
||||
const util = __toModule(require_util2());
|
||||
|
@ -1948,7 +1938,7 @@ var require_modelPoseNet = __commonJS((exports2) => {
|
|||
}
|
||||
exports2.PoseNet = PoseNet;
|
||||
async function load(config2) {
|
||||
const graphModel = await tf3.loadGraphModel(config2.body.modelPath);
|
||||
const graphModel = await loadGraphModel(config2.body.modelPath);
|
||||
const mobilenet = new modelMobileNet.MobileNet(graphModel, this.outputStride);
|
||||
console.log(`Human: load model: ${config2.body.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
return new PoseNet(mobilenet);
|
||||
|
@ -1980,7 +1970,6 @@ var require_posenet = __commonJS((exports2) => {
|
|||
|
||||
// src/hand/handdetector.js
|
||||
var require_handdetector = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
@ -2001,46 +1990,46 @@ var require_handdetector = __commonJS((exports2) => {
|
|||
constructor(model, inputSize, anchorsAnnotated) {
|
||||
this.model = model;
|
||||
this.anchors = anchorsAnnotated.map((anchor) => [anchor.x_center, anchor.y_center]);
|
||||
this.anchorsTensor = tf3.tensor2d(this.anchors);
|
||||
this.inputSizeTensor = tf3.tensor1d([inputSize, inputSize]);
|
||||
this.doubleInputSizeTensor = tf3.tensor1d([inputSize * 2, inputSize * 2]);
|
||||
this.anchorsTensor = tf.tensor2d(this.anchors);
|
||||
this.inputSizeTensor = tf.tensor1d([inputSize, inputSize]);
|
||||
this.doubleInputSizeTensor = tf.tensor1d([inputSize * 2, inputSize * 2]);
|
||||
}
|
||||
normalizeBoxes(boxes) {
|
||||
return tf3.tidy(() => {
|
||||
const boxOffsets = tf3.slice(boxes, [0, 0], [-1, 2]);
|
||||
const boxSizes = tf3.slice(boxes, [0, 2], [-1, 2]);
|
||||
const boxCenterPoints = tf3.add(tf3.div(boxOffsets, this.inputSizeTensor), this.anchorsTensor);
|
||||
const halfBoxSizes = tf3.div(boxSizes, this.doubleInputSizeTensor);
|
||||
const startPoints = tf3.mul(tf3.sub(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
|
||||
const endPoints = tf3.mul(tf3.add(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
|
||||
return tf3.concat2d([startPoints, endPoints], 1);
|
||||
return tf.tidy(() => {
|
||||
const boxOffsets = tf.slice(boxes, [0, 0], [-1, 2]);
|
||||
const boxSizes = tf.slice(boxes, [0, 2], [-1, 2]);
|
||||
const boxCenterPoints = tf.add(tf.div(boxOffsets, this.inputSizeTensor), this.anchorsTensor);
|
||||
const halfBoxSizes = tf.div(boxSizes, this.doubleInputSizeTensor);
|
||||
const startPoints = tf.mul(tf.sub(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
|
||||
const endPoints = tf.mul(tf.add(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
|
||||
return tf.concat2d([startPoints, endPoints], 1);
|
||||
});
|
||||
}
|
||||
normalizeLandmarks(rawPalmLandmarks, index) {
|
||||
return tf3.tidy(() => {
|
||||
const landmarks = tf3.add(tf3.div(rawPalmLandmarks.reshape([-1, 7, 2]), this.inputSizeTensor), this.anchors[index]);
|
||||
return tf3.mul(landmarks, this.inputSizeTensor);
|
||||
return tf.tidy(() => {
|
||||
const landmarks = tf.add(tf.div(rawPalmLandmarks.reshape([-1, 7, 2]), this.inputSizeTensor), this.anchors[index]);
|
||||
return tf.mul(landmarks, this.inputSizeTensor);
|
||||
});
|
||||
}
|
||||
async getBoxes(input, config2) {
|
||||
const batched = this.model.predict(input);
|
||||
const predictions = batched.squeeze();
|
||||
batched.dispose();
|
||||
const scores = tf3.tidy(() => tf3.sigmoid(tf3.slice(predictions, [0, 0], [-1, 1])).squeeze());
|
||||
const scores = tf.tidy(() => tf.sigmoid(tf.slice(predictions, [0, 0], [-1, 1])).squeeze());
|
||||
const scoresVal = scores.dataSync();
|
||||
const rawBoxes = tf3.slice(predictions, [0, 1], [-1, 4]);
|
||||
const rawBoxes = tf.slice(predictions, [0, 1], [-1, 4]);
|
||||
const boxes = this.normalizeBoxes(rawBoxes);
|
||||
rawBoxes.dispose();
|
||||
const filteredT = await tf3.image.nonMaxSuppressionAsync(boxes, scores, config2.maxHands, config2.iouThreshold, config2.scoreThreshold);
|
||||
const filteredT = await tf.image.nonMaxSuppressionAsync(boxes, scores, config2.maxHands, config2.iouThreshold, config2.scoreThreshold);
|
||||
const filtered = filteredT.arraySync();
|
||||
scores.dispose();
|
||||
filteredT.dispose();
|
||||
const hands = [];
|
||||
for (const boxIndex of filtered) {
|
||||
if (scoresVal[boxIndex] >= config2.minConfidence) {
|
||||
const matchingBox = tf3.slice(boxes, [boxIndex, 0], [1, -1]);
|
||||
const rawPalmLandmarks = tf3.slice(predictions, [boxIndex, 5], [1, 14]);
|
||||
const palmLandmarks = tf3.tidy(() => this.normalizeLandmarks(rawPalmLandmarks, boxIndex).reshape([-1, 2]));
|
||||
const matchingBox = tf.slice(boxes, [boxIndex, 0], [1, -1]);
|
||||
const rawPalmLandmarks = tf.slice(predictions, [boxIndex, 5], [1, 14]);
|
||||
const palmLandmarks = tf.tidy(() => this.normalizeLandmarks(rawPalmLandmarks, boxIndex).reshape([-1, 2]));
|
||||
rawPalmLandmarks.dispose();
|
||||
hands.push({box: matchingBox, palmLandmarks, confidence: scoresVal[boxIndex]});
|
||||
}
|
||||
|
@ -2052,9 +2041,9 @@ var require_handdetector = __commonJS((exports2) => {
|
|||
async estimateHandBounds(input, config2) {
|
||||
const inputHeight = input.shape[1];
|
||||
const inputWidth = input.shape[2];
|
||||
const image4 = tf3.tidy(() => input.resizeBilinear([config2.inputSize, config2.inputSize]).div(127.5).sub(1));
|
||||
const predictions = await this.getBoxes(image4, config2);
|
||||
image4.dispose();
|
||||
const image2 = tf.tidy(() => input.resizeBilinear([config2.inputSize, config2.inputSize]).div(127.5).sub(1));
|
||||
const predictions = await this.getBoxes(image2, config2);
|
||||
image2.dispose();
|
||||
if (!predictions || predictions.length === 0)
|
||||
return null;
|
||||
const hands = [];
|
||||
|
@ -2075,7 +2064,6 @@ var require_handdetector = __commonJS((exports2) => {
|
|||
|
||||
// src/hand/handpipeline.js
|
||||
var require_handpipeline = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
@ -2151,13 +2139,13 @@ var require_handpipeline = __commonJS((exports2) => {
|
|||
coord[2]
|
||||
]);
|
||||
}
|
||||
async estimateHands(image4, config2) {
|
||||
async estimateHands(image2, config2) {
|
||||
this.skipped++;
|
||||
let useFreshBox = false;
|
||||
let boxes;
|
||||
if (this.skipped > config2.skipFrames || !config2.landmarks) {
|
||||
boxes = await this.boxDetector.estimateHandBounds(image4, config2);
|
||||
if (image4.shape[1] !== 255 && image4.shape[2] !== 255)
|
||||
boxes = await this.boxDetector.estimateHandBounds(image2, config2);
|
||||
if (image2.shape[1] !== 255 && image2.shape[2] !== 255)
|
||||
this.skipped = 0;
|
||||
}
|
||||
if (boxes && boxes.length > 0 && (boxes.length !== this.detectedHands && this.detectedHands !== config2.maxHands || !config2.landmarks)) {
|
||||
|
@ -2176,8 +2164,8 @@ var require_handpipeline = __commonJS((exports2) => {
|
|||
if (config2.landmarks) {
|
||||
const angle = computeRotation(currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_PALM_BASE], currentBox.palmLandmarks[PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE]);
|
||||
const palmCenter = getBoxCenter(currentBox);
|
||||
const palmCenterNormalized = [palmCenter[0] / image4.shape[2], palmCenter[1] / image4.shape[1]];
|
||||
const rotatedImage = tf3.image.rotateWithOffset(image4, angle, 0, palmCenterNormalized);
|
||||
const palmCenterNormalized = [palmCenter[0] / image2.shape[2], palmCenter[1] / image2.shape[1]];
|
||||
const rotatedImage = tf.image.rotateWithOffset(image2, angle, 0, palmCenterNormalized);
|
||||
const rotationMatrix = buildRotationMatrix(-angle, palmCenter);
|
||||
const newBox = useFreshBox ? this.getBoxForPalmLandmarks(currentBox.palmLandmarks, rotationMatrix) : currentBox;
|
||||
const croppedInput = cutBoxFromImageAndResize(newBox, rotatedImage, [this.inputSize, this.inputSize]);
|
||||
|
@ -2189,7 +2177,7 @@ var require_handpipeline = __commonJS((exports2) => {
|
|||
const confidenceValue = confidence.dataSync()[0];
|
||||
confidence.dispose();
|
||||
if (confidenceValue >= config2.minConfidence) {
|
||||
const keypointsReshaped = tf3.reshape(keypoints, [-1, 3]);
|
||||
const keypointsReshaped = tf.reshape(keypoints, [-1, 3]);
|
||||
const rawCoords = keypointsReshaped.arraySync();
|
||||
keypoints.dispose();
|
||||
keypointsReshaped.dispose();
|
||||
|
@ -19908,7 +19896,6 @@ var require_anchors = __commonJS((exports2) => {
|
|||
|
||||
// src/hand/handpose.js
|
||||
var require_handpose = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const handdetector = __toModule(require_handdetector());
|
||||
const pipeline = __toModule(require_handpipeline());
|
||||
const anchors = __toModule(require_anchors());
|
||||
|
@ -19973,8 +19960,8 @@ var require_handpose = __commonJS((exports2) => {
|
|||
exports2.HandPose = HandPose;
|
||||
async function load(config2) {
|
||||
const [handDetectorModel, handPoseModel] = await Promise.all([
|
||||
tf3.loadGraphModel(config2.detector.modelPath, {fromTFHub: config2.detector.modelPath.includes("tfhub.dev")}),
|
||||
tf3.loadGraphModel(config2.skeleton.modelPath, {fromTFHub: config2.skeleton.modelPath.includes("tfhub.dev")})
|
||||
loadGraphModel(config2.detector.modelPath, {fromTFHub: config2.detector.modelPath.includes("tfhub.dev")}),
|
||||
loadGraphModel(config2.skeleton.modelPath, {fromTFHub: config2.skeleton.modelPath.includes("tfhub.dev")})
|
||||
]);
|
||||
const detector = new handdetector.HandDetector(handDetectorModel, config2.inputSize, anchors.anchors);
|
||||
const pipe = new pipeline.HandPipeline(detector, handPoseModel, config2.inputSize);
|
||||
|
@ -20123,8 +20110,8 @@ var require_imagefx = __commonJS((exports2) => {
|
|||
this.reset = function() {
|
||||
_filterChain = [];
|
||||
};
|
||||
this.apply = function(image3) {
|
||||
_resize(image3.width, image3.height);
|
||||
this.apply = function(image2) {
|
||||
_resize(image2.width, image2.height);
|
||||
_drawCount = 0;
|
||||
if (!_sourceTexture)
|
||||
_sourceTexture = gl.createTexture();
|
||||
|
@ -20133,7 +20120,7 @@ var require_imagefx = __commonJS((exports2) => {
|
|||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image3);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image2);
|
||||
if (_filterChain.length === 0) {
|
||||
_draw();
|
||||
return _canvas;
|
||||
|
@ -20770,14 +20757,13 @@ var require_imagefx = __commonJS((exports2) => {
|
|||
|
||||
// src/image.js
|
||||
var require_image = __commonJS((exports2) => {
|
||||
const tf3 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const fxImage = __toModule(require_imagefx());
|
||||
let inCanvas = null;
|
||||
let outCanvas = null;
|
||||
function process3(input, config2) {
|
||||
let tensor;
|
||||
if (input instanceof tf3.Tensor) {
|
||||
tensor = tf3.clone(input);
|
||||
if (input instanceof tf.Tensor) {
|
||||
tensor = tf.clone(input);
|
||||
} else {
|
||||
const originalWidth = input.naturalWidth || input.videoWidth || input.width || input.shape && input.shape[1] > 0;
|
||||
const originalHeight = input.naturalHeight || input.videoHeight || input.height || input.shape && input.shape[2] > 0;
|
||||
|
@ -20810,7 +20796,7 @@ var require_image = __commonJS((exports2) => {
|
|||
outCanvas.width = inCanvas.width;
|
||||
if (outCanvas.height !== inCanvas.height)
|
||||
outCanvas.height = inCanvas.height;
|
||||
this.fx = tf3.ENV.flags.IS_BROWSER ? new fxImage.Canvas({canvas: outCanvas}) : null;
|
||||
this.fx = tf.ENV.flags.IS_BROWSER ? new fxImage.Canvas({canvas: outCanvas}) : null;
|
||||
}
|
||||
this.fx.reset();
|
||||
this.fx.addFilter("brightness", config2.filter.brightness);
|
||||
|
@ -20846,7 +20832,7 @@ var require_image = __commonJS((exports2) => {
|
|||
}
|
||||
let pixels;
|
||||
if (config2.backend === "webgl" || outCanvas instanceof ImageData) {
|
||||
pixels = tf3.browser.fromPixels(outCanvas);
|
||||
pixels = tf.browser.fromPixels(outCanvas);
|
||||
} else {
|
||||
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||
tempCanvas.width = targetWidth;
|
||||
|
@ -20854,7 +20840,7 @@ var require_image = __commonJS((exports2) => {
|
|||
const tempCtx = tempCanvas.getContext("2d");
|
||||
tempCtx.drawImage(outCanvas, 0, 0);
|
||||
const data2 = tempCtx.getImageData(0, 0, targetWidth, targetHeight);
|
||||
pixels = tf3.browser.fromPixels(data2);
|
||||
pixels = tf.browser.fromPixels(data2);
|
||||
}
|
||||
const casted = pixels.toFloat();
|
||||
tensor = casted.expandDims(0);
|
||||
|
@ -20870,8 +20856,11 @@ var require_image = __commonJS((exports2) => {
|
|||
__export(exports, {
|
||||
default: () => Human
|
||||
});
|
||||
const tf2 = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
|
||||
// src/tf.js
|
||||
const tf = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
const dist = __toModule(require("@tensorflow/tfjs-backend-wasm/dist/index.js"));
|
||||
const loadGraphModel = tf.loadGraphModel;
|
||||
|
||||
// src/face/triangulation.js
|
||||
var triangulation_default = [
|
||||
|
@ -23525,7 +23514,6 @@ const emotion = __toModule(require_emotion());
|
|||
const posenet = __toModule(require_posenet());
|
||||
|
||||
// src/hand/box.js
|
||||
const tf = __toModule(require("@tensorflow/tfjs/dist/tf.es2017.js"));
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
@ -23554,16 +23542,16 @@ function getBoxCenter(box) {
|
|||
box.startPoint[1] + (box.endPoint[1] - box.startPoint[1]) / 2
|
||||
];
|
||||
}
|
||||
function cutBoxFromImageAndResize(box, image3, cropSize) {
|
||||
const h = image3.shape[1];
|
||||
const w = image3.shape[2];
|
||||
function cutBoxFromImageAndResize(box, image2, cropSize) {
|
||||
const h = image2.shape[1];
|
||||
const w = image2.shape[2];
|
||||
const boxes = [[
|
||||
box.startPoint[1] / h,
|
||||
box.startPoint[0] / w,
|
||||
box.endPoint[1] / h,
|
||||
box.endPoint[0] / w
|
||||
]];
|
||||
return tf.image.cropAndResize(image3, boxes, [0], cropSize);
|
||||
return tf.image.cropAndResize(image2, boxes, [0], cropSize);
|
||||
}
|
||||
function scaleBoxCoordinates(box, factor) {
|
||||
const startPoint = [box.startPoint[0] * factor[0], box.startPoint[1] * factor[1]];
|
||||
|
@ -23684,7 +23672,7 @@ function rotatePoint(homogeneousCoordinate, rotationMatrix) {
|
|||
// src/human.js
|
||||
const handpose = __toModule(require_handpose());
|
||||
const gesture = __toModule(require_gesture());
|
||||
const image2 = __toModule(require_image());
|
||||
const image = __toModule(require_image());
|
||||
const profile = __toModule(require_profile());
|
||||
|
||||
// config.js
|
||||
|
@ -23788,7 +23776,7 @@ var config_default = {
|
|||
};
|
||||
|
||||
// package.json
|
||||
var version = "0.8.5";
|
||||
var version = "0.8.6";
|
||||
|
||||
// src/human.js
|
||||
const disableSkipFrames = {
|
||||
|
@ -23819,7 +23807,7 @@ function mergeDeep(...objects) {
|
|||
}
|
||||
class Human {
|
||||
constructor(userConfig = {}) {
|
||||
this.tf = tf2;
|
||||
this.tf = tf;
|
||||
this.version = version;
|
||||
this.config = mergeDeep(config_default, userConfig);
|
||||
this.fx = null;
|
||||
|
@ -23857,7 +23845,7 @@ class Human {
|
|||
analyze(...msg) {
|
||||
if (!this.analyzeMemoryLeaks)
|
||||
return;
|
||||
const current = tf2.engine().state.numTensors;
|
||||
const current = tf.engine().state.numTensors;
|
||||
const previous = this.numTensors;
|
||||
this.numTensors = current;
|
||||
const leaked = current - previous;
|
||||
|
@ -23869,11 +23857,11 @@ class Human {
|
|||
return null;
|
||||
if (!input)
|
||||
return "input is not defined";
|
||||
if (tf2.ENV.flags.IS_NODE && !(input instanceof tf2.Tensor)) {
|
||||
if (tf.ENV.flags.IS_NODE && !(input instanceof tf.Tensor)) {
|
||||
return "input must be a tensor";
|
||||
}
|
||||
try {
|
||||
tf2.getBackend();
|
||||
tf.getBackend();
|
||||
} catch (e) {
|
||||
return "backend not loaded";
|
||||
}
|
||||
|
@ -23886,9 +23874,9 @@ class Human {
|
|||
this.config = mergeDeep(this.config, userConfig);
|
||||
if (this.firstRun) {
|
||||
this.checkBackend(true);
|
||||
this.log(`version: ${this.version} TensorFlow/JS version: ${tf2.version_core}`);
|
||||
this.log(`version: ${this.version} TensorFlow/JS version: ${tf.version_core}`);
|
||||
this.log("configuration:", this.config);
|
||||
this.log("flags:", tf2.ENV.flags);
|
||||
this.log("flags:", tf.ENV.flags);
|
||||
this.firstRun = false;
|
||||
}
|
||||
if (this.config.async) {
|
||||
|
@ -23900,12 +23888,12 @@ class Human {
|
|||
this.models.posenet,
|
||||
this.models.handpose
|
||||
] = await Promise.all([
|
||||
this.models.age || age.load(this.config),
|
||||
this.models.gender || gender.load(this.config),
|
||||
this.models.emotion || emotion.load(this.config),
|
||||
this.models.facemesh || facemesh.load(this.config.face),
|
||||
this.models.posenet || posenet.load(this.config),
|
||||
this.models.handpose || handpose.load(this.config.hand)
|
||||
this.config.face.age.enabled ? this.models.age || age.load(this.config) : null,
|
||||
this.config.face.gender.enabled ? this.models.gender || gender.load(this.config) : null,
|
||||
this.config.face.emotion.enabled ? this.models.emotion || emotion.load(this.config) : null,
|
||||
this.config.face.enabled ? this.models.facemesh || facemesh.load(this.config.face) : null,
|
||||
this.config.body.enabled ? this.models.posenet || posenet.load(this.config) : null,
|
||||
this.config.hand.enabled ? this.models.handpose || handpose.load(this.config.hand) : null
|
||||
]);
|
||||
} else {
|
||||
if (this.config.face.enabled && !this.models.facemesh)
|
||||
|
@ -23927,26 +23915,26 @@ class Human {
|
|||
}
|
||||
async checkBackend(force) {
|
||||
const timeStamp = now();
|
||||
if (this.config.backend && this.config.backend !== "" && force || tf2.getBackend() !== this.config.backend) {
|
||||
if (this.config.backend && this.config.backend !== "" && force || tf.getBackend() !== this.config.backend) {
|
||||
this.state = "backend";
|
||||
this.log("setting backend:", this.config.backend);
|
||||
if (this.config.backend === "wasm") {
|
||||
this.log("settings wasm path:", this.config.wasmPath);
|
||||
dist.setWasmPaths(this.config.wasmPath);
|
||||
const simd = await tf2.env().getAsync("WASM_HAS_SIMD_SUPPORT");
|
||||
const simd = await tf.env().getAsync("WASM_HAS_SIMD_SUPPORT");
|
||||
if (!simd)
|
||||
this.log("warning: wasm simd support is not enabled");
|
||||
}
|
||||
await tf2.setBackend(this.config.backend);
|
||||
tf2.enableProdMode();
|
||||
await tf.setBackend(this.config.backend);
|
||||
tf.enableProdMode();
|
||||
if (this.config.backend === "webgl") {
|
||||
if (this.config.deallocate) {
|
||||
this.log("changing webgl: WEBGL_DELETE_TEXTURE_THRESHOLD:", this.config.deallocate);
|
||||
tf2.ENV.set("WEBGL_DELETE_TEXTURE_THRESHOLD", this.config.deallocate ? 0 : -1);
|
||||
tf.ENV.set("WEBGL_DELETE_TEXTURE_THRESHOLD", this.config.deallocate ? 0 : -1);
|
||||
}
|
||||
tf2.ENV.set("WEBGL_PACK_DEPTHWISECONV", true);
|
||||
tf.ENV.set("WEBGL_PACK_DEPTHWISECONV", true);
|
||||
}
|
||||
await tf2.ready();
|
||||
await tf.ready();
|
||||
}
|
||||
const current = Math.trunc(now() - timeStamp);
|
||||
if (current > (this.perf.backend || 0))
|
||||
|
@ -24048,10 +24036,10 @@ class Human {
|
|||
await this.checkBackend();
|
||||
await this.load();
|
||||
if (this.config.scoped)
|
||||
tf2.engine().startScope();
|
||||
tf.engine().startScope();
|
||||
this.analyze("Start Scope:");
|
||||
timeStamp = now();
|
||||
const process3 = image2.process(input, this.config);
|
||||
const process3 = image.process(input, this.config);
|
||||
this.perf.image = Math.trunc(now() - timeStamp);
|
||||
this.analyze("Get Image:");
|
||||
if (this.config.async) {
|
||||
|
@ -24092,7 +24080,7 @@ class Human {
|
|||
}
|
||||
process3.tensor.dispose();
|
||||
if (this.config.scoped)
|
||||
tf2.engine().endScope();
|
||||
tf.engine().endScope();
|
||||
this.analyze("End Scope:");
|
||||
let gestureRes = [];
|
||||
if (this.config.gesture.enabled) {
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -9,8 +9,11 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytes": 1926,
|
||||
"bytes": 1912,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
}
|
||||
|
@ -58,20 +61,30 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/body/modelBase.js": {
|
||||
"bytes": 901,
|
||||
"imports": []
|
||||
"bytes": 874,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/body/modelMobileNet.js": {
|
||||
"bytes": 611,
|
||||
"bytes": 584,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/body/modelBase.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/body/modelPoseNet.js": {
|
||||
"bytes": 1940,
|
||||
"bytes": 1922,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/body/modelMobileNet.js"
|
||||
},
|
||||
|
@ -120,24 +133,38 @@
|
|||
]
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytes": 2942,
|
||||
"bytes": 2928,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/face/blazeface.js": {
|
||||
"bytes": 6955,
|
||||
"imports": []
|
||||
"bytes": 6941,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/face/box.js": {
|
||||
"bytes": 1947,
|
||||
"imports": []
|
||||
"bytes": 1920,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/face/facemesh.js": {
|
||||
"bytes": 2621,
|
||||
"bytes": 2604,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/blazeface.js"
|
||||
},
|
||||
|
@ -156,8 +183,11 @@
|
|||
]
|
||||
},
|
||||
"src/face/facepipeline.js": {
|
||||
"bytes": 13713,
|
||||
"bytes": 13686,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/box.js"
|
||||
},
|
||||
|
@ -186,8 +216,11 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytes": 3207,
|
||||
"bytes": 3193,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js"
|
||||
}
|
||||
|
@ -202,20 +235,30 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/hand/box.js": {
|
||||
"bytes": 3238,
|
||||
"imports": []
|
||||
"bytes": 3211,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/hand/handdetector.js": {
|
||||
"bytes": 4248,
|
||||
"bytes": 4221,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/box.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/hand/handpipeline.js": {
|
||||
"bytes": 7559,
|
||||
"bytes": 7532,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/box.js"
|
||||
},
|
||||
|
@ -225,8 +268,11 @@
|
|||
]
|
||||
},
|
||||
"src/hand/handpose.js": {
|
||||
"bytes": 3047,
|
||||
"bytes": 3026,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/hand/handdetector.js"
|
||||
},
|
||||
|
@ -243,8 +289,11 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytes": 14315,
|
||||
"bytes": 14448,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/face/facemesh.js"
|
||||
},
|
||||
|
@ -281,8 +330,11 @@
|
|||
]
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytes": 4666,
|
||||
"bytes": 4638,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/tf.js"
|
||||
},
|
||||
{
|
||||
"path": "src/imagefx.js"
|
||||
}
|
||||
|
@ -295,55 +347,59 @@
|
|||
"src/profile.js": {
|
||||
"bytes": 1061,
|
||||
"imports": []
|
||||
},
|
||||
"src/tf.js": {
|
||||
"bytes": 871,
|
||||
"imports": []
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"dist/human.node-nobundle.js.map": {
|
||||
"imports": [],
|
||||
"inputs": {},
|
||||
"bytes": 794759
|
||||
"bytes": 781095
|
||||
},
|
||||
"dist/human.node-nobundle.js": {
|
||||
"imports": [],
|
||||
"inputs": {
|
||||
"src/face/blazeface.js": {
|
||||
"bytesInOutput": 7083
|
||||
"bytesInOutput": 6974
|
||||
},
|
||||
"src/face/keypoints.js": {
|
||||
"bytesInOutput": 2771
|
||||
},
|
||||
"src/face/box.js": {
|
||||
"bytesInOutput": 2133
|
||||
"bytesInOutput": 2059
|
||||
},
|
||||
"src/face/util.js": {
|
||||
"bytesInOutput": 3054
|
||||
},
|
||||
"src/face/facepipeline.js": {
|
||||
"bytesInOutput": 12462
|
||||
"bytesInOutput": 12381
|
||||
},
|
||||
"src/face/uvcoords.js": {
|
||||
"bytesInOutput": 20586
|
||||
},
|
||||
"src/face/facemesh.js": {
|
||||
"bytesInOutput": 2651
|
||||
"bytesInOutput": 2569
|
||||
},
|
||||
"src/profile.js": {
|
||||
"bytesInOutput": 1120
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytesInOutput": 1910
|
||||
"bytesInOutput": 1829
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytesInOutput": 3070
|
||||
"bytesInOutput": 2983
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytesInOutput": 2786
|
||||
"bytesInOutput": 2700
|
||||
},
|
||||
"src/body/modelBase.js": {
|
||||
"bytesInOutput": 942
|
||||
"bytesInOutput": 868
|
||||
},
|
||||
"src/body/modelMobileNet.js": {
|
||||
"bytesInOutput": 548
|
||||
"bytesInOutput": 473
|
||||
},
|
||||
"src/body/heapSort.js": {
|
||||
"bytesInOutput": 1639
|
||||
|
@ -367,22 +423,22 @@
|
|||
"bytesInOutput": 2418
|
||||
},
|
||||
"src/body/modelPoseNet.js": {
|
||||
"bytesInOutput": 2092
|
||||
"bytesInOutput": 2015
|
||||
},
|
||||
"src/body/posenet.js": {
|
||||
"bytesInOutput": 977
|
||||
},
|
||||
"src/hand/handdetector.js": {
|
||||
"bytesInOutput": 4504
|
||||
"bytesInOutput": 4404
|
||||
},
|
||||
"src/hand/handpipeline.js": {
|
||||
"bytesInOutput": 7242
|
||||
"bytesInOutput": 7167
|
||||
},
|
||||
"src/hand/anchors.js": {
|
||||
"bytesInOutput": 256592
|
||||
},
|
||||
"src/hand/handpose.js": {
|
||||
"bytesInOutput": 3148
|
||||
"bytesInOutput": 3067
|
||||
},
|
||||
"src/gesture.js": {
|
||||
"bytesInOutput": 3042
|
||||
|
@ -391,13 +447,13 @@
|
|||
"bytesInOutput": 20099
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytesInOutput": 4563
|
||||
"bytesInOutput": 4485
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 47
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 152
|
||||
"src/tf.js": {
|
||||
"bytesInOutput": 193
|
||||
},
|
||||
"src/face/triangulation.js": {
|
||||
"bytesInOutput": 17898
|
||||
|
@ -406,13 +462,13 @@
|
|||
"bytesInOutput": 227
|
||||
},
|
||||
"src/hand/box.js": {
|
||||
"bytesInOutput": 3107
|
||||
"bytesInOutput": 3037
|
||||
},
|
||||
"src/hand/util.js": {
|
||||
"bytesInOutput": 2884
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 187
|
||||
"bytesInOutput": 186
|
||||
},
|
||||
"config.js": {
|
||||
"bytesInOutput": 1933
|
||||
|
@ -424,10 +480,10 @@
|
|||
"bytesInOutput": 23
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 11797
|
||||
"bytesInOutput": 12003
|
||||
}
|
||||
},
|
||||
"bytes": 419228
|
||||
"bytes": 418258
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf, loadGraphModel } from '../tf.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
const models = {};
|
||||
|
@ -10,7 +10,7 @@ const zoom = [0, 0]; // 0..1 meaning 0%..100%
|
|||
|
||||
async function load(config) {
|
||||
if (!models.age) {
|
||||
models.age = await tf.loadGraphModel(config.face.age.modelPath);
|
||||
models.age = await loadGraphModel(config.face.age.modelPath);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Human: load model: ${config.face.age.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf } from '../tf.js';
|
||||
import * as kpt from './keypoints';
|
||||
|
||||
function getPointsConfidence(heatmapScores, heatMapCoords) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf } from '../tf.js';
|
||||
|
||||
class BaseModel {
|
||||
constructor(model, outputStride) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf } from '../tf.js';
|
||||
import * as modelBase from './modelBase';
|
||||
|
||||
class MobileNet extends modelBase.BaseModel {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { loadGraphModel } from '../tf.js';
|
||||
import * as modelMobileNet from './modelMobileNet';
|
||||
import * as decodeMultiple from './decodeMultiple';
|
||||
import * as util from './util';
|
||||
|
@ -38,7 +38,7 @@ class PoseNet {
|
|||
exports.PoseNet = PoseNet;
|
||||
|
||||
async function load(config) {
|
||||
const graphModel = await tf.loadGraphModel(config.body.modelPath);
|
||||
const graphModel = await loadGraphModel(config.body.modelPath);
|
||||
const mobilenet = new modelMobileNet.MobileNet(graphModel, this.outputStride);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Human: load model: ${config.body.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf, loadGraphModel } from '../tf.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
const annotations = ['angry', 'disgust', 'fear', 'happy', 'sad', 'surpise', 'neutral'];
|
||||
|
@ -13,7 +13,7 @@ const scale = 1; // score multiplication factor
|
|||
|
||||
async function load(config) {
|
||||
if (!models.emotion) {
|
||||
models.emotion = await tf.loadGraphModel(config.face.emotion.modelPath);
|
||||
models.emotion = await loadGraphModel(config.face.emotion.modelPath);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Human: load model: ${config.face.emotion.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf, loadGraphModel } from '../tf.js';
|
||||
|
||||
const NUM_LANDMARKS = 6;
|
||||
|
||||
|
@ -164,7 +164,7 @@ class BlazeFaceModel {
|
|||
}
|
||||
|
||||
async function load(config) {
|
||||
const blazeface = await tf.loadGraphModel(config.detector.modelPath, { fromTFHub: config.detector.modelPath.includes('tfhub.dev') });
|
||||
const blazeface = await loadGraphModel(config.detector.modelPath, { fromTFHub: config.detector.modelPath.includes('tfhub.dev') });
|
||||
const model = new BlazeFaceModel(blazeface, config);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Human: load model: ${config.detector.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf } from '../tf.js';
|
||||
|
||||
function scaleBoxCoordinates(box, factor) {
|
||||
const startPoint = [box.startPoint[0] * factor[0], box.startPoint[1] * factor[1]];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf, loadGraphModel } from '../tf.js';
|
||||
import * as blazeface from './blazeface';
|
||||
import * as keypoints from './keypoints';
|
||||
import * as pipe from './facepipeline';
|
||||
|
@ -44,8 +44,8 @@ class MediaPipeFaceMesh {
|
|||
async function load(config) {
|
||||
const models = await Promise.all([
|
||||
blazeface.load(config),
|
||||
tf.loadGraphModel(config.mesh.modelPath, { fromTFHub: config.mesh.modelPath.includes('tfhub.dev') }),
|
||||
tf.loadGraphModel(config.iris.modelPath, { fromTFHub: config.iris.modelPath.includes('tfhub.dev') }),
|
||||
loadGraphModel(config.mesh.modelPath, { fromTFHub: config.mesh.modelPath.includes('tfhub.dev') }),
|
||||
loadGraphModel(config.iris.modelPath, { fromTFHub: config.iris.modelPath.includes('tfhub.dev') }),
|
||||
]);
|
||||
const faceMesh = new MediaPipeFaceMesh(models[0], models[1], models[2], config);
|
||||
// eslint-disable-next-line no-console
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable class-methods-use-this */
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf } from '../tf.js';
|
||||
import * as bounding from './box';
|
||||
import * as keypoints from './keypoints';
|
||||
import * as util from './util';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf, loadGraphModel } from '../tf.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
const models = {};
|
||||
|
@ -12,7 +12,7 @@ const rgb = [0.2989, 0.5870, 0.1140]; // factors for red/green/blue colors when
|
|||
|
||||
async function load(config) {
|
||||
if (!models.gender) {
|
||||
models.gender = await tf.loadGraphModel(config.face.gender.modelPath);
|
||||
models.gender = await loadGraphModel(config.face.gender.modelPath);
|
||||
alternative = models.gender.inputs[0].shape[3] === 1;
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Human: load model: ${config.face.gender.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf } from '../tf.js';
|
||||
|
||||
function getBoxSize(box) {
|
||||
return [
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* =============================================================================
|
||||
*/
|
||||
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf } from '../tf.js';
|
||||
import * as box from './box';
|
||||
|
||||
class HandDetector {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* =============================================================================
|
||||
*/
|
||||
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf } from '../tf.js';
|
||||
import * as box from './box';
|
||||
import * as util from './util';
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
// https://storage.googleapis.com/tfjs-models/demos/handpose/index.html
|
||||
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { loadGraphModel } from '../tf.js';
|
||||
import * as handdetector from './handdetector';
|
||||
import * as pipeline from './handpipeline';
|
||||
import * as anchors from './anchors';
|
||||
|
@ -69,8 +69,8 @@ exports.HandPose = HandPose;
|
|||
|
||||
async function load(config) {
|
||||
const [handDetectorModel, handPoseModel] = await Promise.all([
|
||||
tf.loadGraphModel(config.detector.modelPath, { fromTFHub: config.detector.modelPath.includes('tfhub.dev') }),
|
||||
tf.loadGraphModel(config.skeleton.modelPath, { fromTFHub: config.skeleton.modelPath.includes('tfhub.dev') }),
|
||||
loadGraphModel(config.detector.modelPath, { fromTFHub: config.detector.modelPath.includes('tfhub.dev') }),
|
||||
loadGraphModel(config.skeleton.modelPath, { fromTFHub: config.skeleton.modelPath.includes('tfhub.dev') }),
|
||||
]);
|
||||
const detector = new handdetector.HandDetector(handDetectorModel, config.inputSize, anchors.anchors);
|
||||
const pipe = new pipeline.HandPipeline(detector, handPoseModel, config.inputSize);
|
||||
|
|
15
src/human.js
15
src/human.js
|
@ -1,5 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { setWasmPaths } from '@tensorflow/tfjs-backend-wasm/dist/index.js';
|
||||
import { tf, setWasmPaths } from './tf.js';
|
||||
import * as facemesh from './face/facemesh.js';
|
||||
import * as age from './age/age.js';
|
||||
import * as gender from './gender/gender.js';
|
||||
|
@ -131,12 +130,12 @@ class Human {
|
|||
this.models.posenet,
|
||||
this.models.handpose,
|
||||
] = await Promise.all([
|
||||
this.models.age || age.load(this.config),
|
||||
this.models.gender || gender.load(this.config),
|
||||
this.models.emotion || emotion.load(this.config),
|
||||
this.models.facemesh || facemesh.load(this.config.face),
|
||||
this.models.posenet || posenet.load(this.config),
|
||||
this.models.handpose || handpose.load(this.config.hand),
|
||||
this.config.face.age.enabled ? this.models.age || age.load(this.config) : null,
|
||||
this.config.face.gender.enabled ? this.models.gender || gender.load(this.config) : null,
|
||||
this.config.face.emotion.enabled ? this.models.emotion || emotion.load(this.config) : null,
|
||||
this.config.face.enabled ? this.models.facemesh || facemesh.load(this.config.face) : null,
|
||||
this.config.body.enabled ? this.models.posenet || posenet.load(this.config) : null,
|
||||
this.config.hand.enabled ? this.models.handpose || handpose.load(this.config.hand) : null,
|
||||
]);
|
||||
} else {
|
||||
if (this.config.face.enabled && !this.models.facemesh) this.models.facemesh = await facemesh.load(this.config.face);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { tf } from './tf.js';
|
||||
import * as fxImage from './imagefx.js';
|
||||
|
||||
// internal temp canvases
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// monolithic: bundle 3.4M
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { setWasmPaths } from '@tensorflow/tfjs-backend-wasm/dist/index.js';
|
||||
|
||||
const loadGraphModel = tf.loadGraphModel;
|
||||
export { tf, setWasmPaths, loadGraphModel };
|
||||
|
||||
// modular: bundle 4.2M
|
||||
/*
|
||||
import * as tf from '@tensorflow/tfjs-core/dist/tf-core.es2017.js';
|
||||
import { loadGraphModel } from '@tensorflow/tfjs-converter/dist/tf-converter.es2017.js';
|
||||
import * as tfCPU from '@tensorflow/tfjs-backend-cpu/dist/tf-backend-cpu.es2017.js';
|
||||
import * as tfWebGL from '@tensorflow/tfjs-backend-webgl/dist/tf-backend-webgl.es2017.js';
|
||||
import { setWasmPaths, version_wasm } from '@tensorflow/tfjs-backend-wasm/dist/index.js';
|
||||
|
||||
const version = { core: tf.version, cpu: tfCPU.version_cpu, webgl: tfWebGL.version_webgl, wasm: version_wasm };
|
||||
|
||||
export { tf, setWasmPaths, loadGraphModel, version };
|
||||
*/
|
Loading…
Reference in New Issue