update blazepose and extend hand annotations

pull/233/head
Vladimir Mandic 2021-11-24 16:17:03 -05:00
parent db6fe46741
commit 8050f5ed99
18 changed files with 2394 additions and 2686 deletions

View File

@ -11,14 +11,13 @@
### **HEAD -> main** 2021/11/23 mandic00@live.com
- fix face box scaling on detection
- cleanup
### **2.5.4** 2021/11/22 mandic00@live.com
- prototype blazepose detector
### **origin/main** 2021/11/21 mandic00@live.com
- minor fixes
- add body 3d interpolation
- edit blazepose keypoints
- new build process

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,7 @@
import { Human, Config } from '../../dist/human.esm.js'; // equivalent of @vladmandic/Human
const humanConfig: Partial<Config> = { // user configuration for human, used to fine-tune behavior
// backend: 'webgpu' as 'webgpu,
// backend: 'webgpu' as const,
// async: true,
modelBasePath: '../../models',
filter: { enabled: true, equalization: false },

View File

@ -963,8 +963,8 @@ function GLImageFilter() {
// src/image/enhance.ts
async function histogramEqualization(inputImage) {
const squeeze11 = inputImage.shape.length === 4 ? tfjs_esm_exports.squeeze(inputImage) : inputImage;
const channels = tfjs_esm_exports.split(squeeze11, 3, 2);
const squeeze10 = inputImage.shape.length === 4 ? tfjs_esm_exports.squeeze(inputImage) : inputImage;
const channels = tfjs_esm_exports.split(squeeze10, 3, 2);
const min2 = [tfjs_esm_exports.min(channels[0]), tfjs_esm_exports.min(channels[1]), tfjs_esm_exports.min(channels[2])];
const max4 = [tfjs_esm_exports.max(channels[0]), tfjs_esm_exports.max(channels[1]), tfjs_esm_exports.max(channels[2])];
const absMax = await Promise.all(max4.map((channel) => channel.data()));
@ -974,8 +974,8 @@ async function histogramEqualization(inputImage) {
const fact = [tfjs_esm_exports.div(maxValue, range[0]), tfjs_esm_exports.div(maxValue, range[1]), tfjs_esm_exports.div(maxValue, range[2])];
const enh = [tfjs_esm_exports.mul(sub10[0], fact[0]), tfjs_esm_exports.mul(sub10[1], fact[1]), tfjs_esm_exports.mul(sub10[2], fact[2])];
const rgb2 = tfjs_esm_exports.stack([enh[0], enh[1], enh[2]], 2);
const reshape8 = tfjs_esm_exports.reshape(rgb2, [1, squeeze11.shape[0], squeeze11.shape[1], 3]);
tfjs_esm_exports.dispose([...channels, ...min2, ...max4, ...sub10, ...range, ...fact, ...enh, rgb2, squeeze11]);
const reshape8 = tfjs_esm_exports.reshape(rgb2, [1, squeeze10.shape[0], squeeze10.shape[1], 3]);
tfjs_esm_exports.dispose([...channels, ...min2, ...max4, ...sub10, ...range, ...fact, ...enh, rgb2, squeeze10]);
return reshape8;
}
@ -1390,8 +1390,8 @@ async function predict(image29, config3, idx, count2) {
if (!(model == null ? void 0 : model.inputs[0].shape))
return;
const t = {};
const box4 = [[0, 0.1, 0.9, 0.9]];
t.resize = tfjs_esm_exports.image.cropAndResize(image29, box4, [0], [model.inputs[0].shape[2], model.inputs[0].shape[1]]);
const box5 = [[0, 0.1, 0.9, 0.9]];
t.resize = tfjs_esm_exports.image.cropAndResize(image29, box5, [0], [model.inputs[0].shape[2], model.inputs[0].shape[1]]);
const obj = { age: 0, gender: "unknown", genderScore: 0, race: [] };
if ((_a2 = config3.face["gear"]) == null ? void 0 : _a2.enabled)
[t.age, t.gender, t.race] = model.execute(t.resize, ["age_output", "gender_output", "race_output"]);
@ -4875,44 +4875,44 @@ var UV33 = VTX33.map((x) => UV468[x]);
var UV7 = VTX7.map((x) => UV468[x]);
// src/face/facemeshutil.ts
var getBoxSize = (box4) => [Math.abs(box4.endPoint[0] - box4.startPoint[0]), Math.abs(box4.endPoint[1] - box4.startPoint[1])];
var getBoxCenter = (box4) => [box4.startPoint[0] + (box4.endPoint[0] - box4.startPoint[0]) / 2, box4.startPoint[1] + (box4.endPoint[1] - box4.startPoint[1]) / 2];
var getClampedBox = (box4, input) => box4 ? [
Math.trunc(Math.max(0, box4.startPoint[0])),
Math.trunc(Math.max(0, box4.startPoint[1])),
Math.trunc(Math.min(input.shape[2] || 0, box4.endPoint[0]) - Math.max(0, box4.startPoint[0])),
Math.trunc(Math.min(input.shape[1] || 0, box4.endPoint[1]) - Math.max(0, box4.startPoint[1]))
var getBoxSize = (box5) => [Math.abs(box5.endPoint[0] - box5.startPoint[0]), Math.abs(box5.endPoint[1] - box5.startPoint[1])];
var getBoxCenter = (box5) => [box5.startPoint[0] + (box5.endPoint[0] - box5.startPoint[0]) / 2, box5.startPoint[1] + (box5.endPoint[1] - box5.startPoint[1]) / 2];
var getClampedBox = (box5, input) => box5 ? [
Math.trunc(Math.max(0, box5.startPoint[0])),
Math.trunc(Math.max(0, box5.startPoint[1])),
Math.trunc(Math.min(input.shape[2] || 0, box5.endPoint[0]) - Math.max(0, box5.startPoint[0])),
Math.trunc(Math.min(input.shape[1] || 0, box5.endPoint[1]) - Math.max(0, box5.startPoint[1]))
] : [0, 0, 0, 0];
var getRawBox = (box4, input) => box4 ? [
box4.startPoint[0] / (input.shape[2] || 0),
box4.startPoint[1] / (input.shape[1] || 0),
(box4.endPoint[0] - box4.startPoint[0]) / (input.shape[2] || 0),
(box4.endPoint[1] - box4.startPoint[1]) / (input.shape[1] || 0)
var getRawBox = (box5, input) => box5 ? [
box5.startPoint[0] / (input.shape[2] || 0),
box5.startPoint[1] / (input.shape[1] || 0),
(box5.endPoint[0] - box5.startPoint[0]) / (input.shape[2] || 0),
(box5.endPoint[1] - box5.startPoint[1]) / (input.shape[1] || 0)
] : [0, 0, 0, 0];
var scaleBoxCoordinates = (box4, factor) => {
const startPoint = [box4.startPoint[0] * factor[0], box4.startPoint[1] * factor[1]];
const endPoint = [box4.endPoint[0] * factor[0], box4.endPoint[1] * factor[1]];
return { startPoint, endPoint, landmarks: box4.landmarks, confidence: box4.confidence };
var scaleBoxCoordinates = (box5, factor) => {
const startPoint = [box5.startPoint[0] * factor[0], box5.startPoint[1] * factor[1]];
const endPoint = [box5.endPoint[0] * factor[0], box5.endPoint[1] * factor[1]];
return { startPoint, endPoint, landmarks: box5.landmarks, confidence: box5.confidence };
};
var cutBoxFromImageAndResize = (box4, image29, cropSize) => {
var cutBoxFromImageAndResize = (box5, image29, cropSize) => {
const h = image29.shape[1];
const w = image29.shape[2];
const crop2 = tfjs_esm_exports.image.cropAndResize(image29, [[box4.startPoint[1] / h, box4.startPoint[0] / w, box4.endPoint[1] / h, box4.endPoint[0] / w]], [0], cropSize);
const crop2 = tfjs_esm_exports.image.cropAndResize(image29, [[box5.startPoint[1] / h, box5.startPoint[0] / w, box5.endPoint[1] / h, box5.endPoint[0] / w]], [0], cropSize);
const norm = tfjs_esm_exports.div(crop2, constants.tf255);
tfjs_esm_exports.dispose(crop2);
return norm;
};
var enlargeBox = (box4, factor) => {
const center = getBoxCenter(box4);
const size2 = getBoxSize(box4);
var enlargeBox = (box5, factor) => {
const center = getBoxCenter(box5);
const size2 = getBoxSize(box5);
const halfSize = [factor * size2[0] / 2, factor * size2[1] / 2];
return { startPoint: [center[0] - halfSize[0], center[1] - halfSize[1]], endPoint: [center[0] + halfSize[0], center[1] + halfSize[1]], landmarks: box4.landmarks, confidence: box4.confidence };
return { startPoint: [center[0] - halfSize[0], center[1] - halfSize[1]], endPoint: [center[0] + halfSize[0], center[1] + halfSize[1]], landmarks: box5.landmarks, confidence: box5.confidence };
};
var squarifyBox = (box4) => {
const centers = getBoxCenter(box4);
const size2 = getBoxSize(box4);
var squarifyBox = (box5) => {
const centers = getBoxCenter(box5);
const size2 = getBoxSize(box5);
const halfSize = Math.max(...size2) / 2;
return { startPoint: [Math.round(centers[0] - halfSize), Math.round(centers[1] - halfSize)], endPoint: [Math.round(centers[0] + halfSize), Math.round(centers[1] + halfSize)], landmarks: box4.landmarks, confidence: box4.confidence };
return { startPoint: [Math.round(centers[0] - halfSize), Math.round(centers[1] - halfSize)], endPoint: [Math.round(centers[0] + halfSize), Math.round(centers[1] + halfSize)], landmarks: box5.landmarks, confidence: box5.confidence };
};
var calculateLandmarksBoundingBox = (landmarks) => {
const xs = landmarks.map((d) => d[0]);
@ -4980,8 +4980,8 @@ function generateAnchors(inputSize9) {
}
return anchors4;
}
function transformRawCoords(coordsRaw, box4, angle, rotationMatrix, inputSize9) {
const boxSize = getBoxSize(box4);
function transformRawCoords(coordsRaw, box5, angle, rotationMatrix, inputSize9) {
const boxSize = getBoxSize(box5);
const coordsScaled = coordsRaw.map((coord) => [
boxSize[0] / inputSize9 * (coord[0] - inputSize9 / 2),
boxSize[1] / inputSize9 * (coord[1] - inputSize9 / 2),
@ -4991,33 +4991,33 @@ function transformRawCoords(coordsRaw, box4, angle, rotationMatrix, inputSize9)
const coordsRotationMatrix = largeAngle ? buildRotationMatrix(angle, [0, 0]) : fixedRotationMatrix;
const coordsRotated = largeAngle ? coordsScaled.map((coord) => [...rotatePoint(coord, coordsRotationMatrix), coord[2]]) : coordsScaled;
const inverseRotationMatrix = largeAngle ? invertTransformMatrix(rotationMatrix) : fixedRotationMatrix;
const boxCenter = [...getBoxCenter({ startPoint: box4.startPoint, endPoint: box4.endPoint }), 1];
const boxCenter = [...getBoxCenter({ startPoint: box5.startPoint, endPoint: box5.endPoint }), 1];
return coordsRotated.map((coord) => [
Math.round(coord[0] + dot(boxCenter, inverseRotationMatrix[0])),
Math.round(coord[1] + dot(boxCenter, inverseRotationMatrix[1])),
Math.round(coord[2] || 0)
]);
}
function correctFaceRotation(rotate, box4, input, inputSize9) {
const symmetryLine = box4.landmarks.length >= meshLandmarks.count ? meshLandmarks.symmetryLine : blazeFaceLandmarks.symmetryLine;
function correctFaceRotation(rotate, box5, input, inputSize9) {
const symmetryLine = box5.landmarks.length >= meshLandmarks.count ? meshLandmarks.symmetryLine : blazeFaceLandmarks.symmetryLine;
let angle = 0;
let rotationMatrix = fixedRotationMatrix;
let face5;
if (rotate && env.kernels.includes("rotatewithoffset")) {
angle = computeRotation(box4.landmarks[symmetryLine[0]], box4.landmarks[symmetryLine[1]]);
angle = computeRotation(box5.landmarks[symmetryLine[0]], box5.landmarks[symmetryLine[1]]);
const largeAngle = angle && angle !== 0 && Math.abs(angle) > 0.2;
if (largeAngle) {
const center = getBoxCenter({ startPoint: box4.startPoint, endPoint: box4.endPoint });
const center = getBoxCenter({ startPoint: box5.startPoint, endPoint: box5.endPoint });
const centerRaw = [center[0] / input.shape[2], center[1] / input.shape[1]];
const rotated = tfjs_esm_exports.image.rotateWithOffset(input, angle, 0, centerRaw);
rotationMatrix = buildRotationMatrix(-angle, center);
face5 = cutBoxFromImageAndResize(box4, rotated, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, rotated, [inputSize9, inputSize9]);
tfjs_esm_exports.dispose(rotated);
} else {
face5 = cutBoxFromImageAndResize(box4, input, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, input, [inputSize9, inputSize9]);
}
} else {
face5 = cutBoxFromImageAndResize(box4, input, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, input, [inputSize9, inputSize9]);
}
return [angle, rotationMatrix, face5];
}
@ -5198,41 +5198,39 @@ async function createAnchors() {
}
anchorTensor = { x: tfjs_esm_exports.tensor1d(anchors4.map((a) => a.x)), y: tfjs_esm_exports.tensor1d(anchors4.map((a) => a.y)) };
}
var cropFactor = [5, 5];
function decodeBoxes(boxesTensor, anchor) {
return tfjs_esm_exports.tidy(() => {
const split5 = tfjs_esm_exports.split(boxesTensor, 12, 1);
let xCenter = tfjs_esm_exports.squeeze(split5[0]);
let yCenter = tfjs_esm_exports.squeeze(split5[1]);
let width = tfjs_esm_exports.squeeze(split5[2]);
let height = tfjs_esm_exports.squeeze(split5[3]);
xCenter = tfjs_esm_exports.add(tfjs_esm_exports.div(xCenter, inputSize2), anchor.x);
yCenter = tfjs_esm_exports.add(tfjs_esm_exports.div(yCenter, inputSize2), anchor.y);
width = tfjs_esm_exports.mul(tfjs_esm_exports.div(width, inputSize2), cropFactor[0]);
height = tfjs_esm_exports.mul(tfjs_esm_exports.div(height, inputSize2), cropFactor[1]);
const xMin = tfjs_esm_exports.sub(xCenter, tfjs_esm_exports.div(width, 2));
const yMin = tfjs_esm_exports.sub(yCenter, tfjs_esm_exports.div(height, 2));
const boxes = tfjs_esm_exports.stack([xMin, yMin, width, height], 1);
return boxes;
});
// src/util/box.ts
function calc(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const box5 = [min2[0], min2[1], max4[0] - min2[0], max4[1] - min2[1]];
const boxRaw = [box5[0] / outputSize2[0], box5[1] / outputSize2[1], box5[2] / outputSize2[0], box5[3] / outputSize2[1]];
return { box: box5, boxRaw };
}
async function decode(boxesTensor, logitsTensor, config3, outputSize2) {
const t = {};
t.boxes = decodeBoxes(boxesTensor, anchorTensor);
t.scores = tfjs_esm_exports.sigmoid(logitsTensor);
t.argmax = tfjs_esm_exports.argMax(t.scores);
const i = (await t.argmax.data())[0];
const scores = await t.scores.data();
const detected = [];
const minScore = config3.body["detector"] && config3.body["detector"]["minConfidence"] ? config3.body["detector"]["minConfidence"] : 0;
if (scores[i] >= minScore) {
const boxes = await t.boxes.array();
const boxRaw = boxes[i];
const box4 = [boxRaw[0] * outputSize2[0], boxRaw[1] * outputSize2[1], boxRaw[2] * outputSize2[0], boxRaw[3] * outputSize2[1]];
detected.push({ box: box4, boxRaw, score: scores[i] });
function square(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const center = [(min2[0] + max4[0]) / 2, (min2[1] + max4[1]) / 2];
const dist = Math.max(center[0] - min2[0], center[1] - min2[1], -center[0] + max4[0], -center[1] + max4[1]);
const box5 = [Math.trunc(center[0] - dist), Math.trunc(center[1] - dist), Math.trunc(2 * dist), Math.trunc(2 * dist)];
const boxRaw = [box5[0] / outputSize2[0], box5[1] / outputSize2[1], box5[2] / outputSize2[0], box5[3] / outputSize2[1]];
return { box: box5, boxRaw };
}
Object.keys(t).forEach((tensor3) => tfjs_esm_exports.dispose(t[tensor3]));
return detected;
function scale(box5, scaleFact) {
const dist = [box5[2] * scaleFact, box5[3] * scaleFact];
const newBox = [
box5[0] - (dist[0] - box5[2]) / 2,
box5[1] - (dist[1] - box5[3]) / 2,
dist[0],
dist[1]
];
return newBox;
}
function crop(box5) {
const yxBox = [Math.max(0, box5[1]), Math.max(0, box5[0]), Math.min(1, box5[3] + box5[1]), Math.min(1, box5[2] + box5[0])];
return yxBox;
}
// src/body/blazepose.ts
@ -5245,7 +5243,7 @@ var outputNodes = {
detector: []
};
var cache = null;
var lastBox;
var cropBox;
var padding = [[0, 0], [0, 0], [0, 0], [0, 0]];
var lastTime5 = 0;
var sigmoid3 = (x) => 1 - 1 / (1 + Math.exp(x));
@ -5282,39 +5280,37 @@ async function loadPose(config3) {
log("cached model:", models.landmarks["modelUrl"]);
return models.landmarks;
}
function calculateBoxes(keypoints, outputSize2) {
const x = keypoints.map((a) => a.position[0]);
const y = keypoints.map((a) => a.position[1]);
const keypointsBox = [Math.min(...x), Math.min(...y), Math.max(...x) - Math.min(...x), Math.max(...y) - Math.min(...y)];
const keypointsBoxRaw = [keypointsBox[0] / outputSize2[0], keypointsBox[1] / outputSize2[1], keypointsBox[2] / outputSize2[0], keypointsBox[3] / outputSize2[1]];
return { keypointsBox, keypointsBoxRaw };
}
async function prepareImage(input, size2, box4) {
async function prepareImage(input, size2) {
const t = {};
if (!input.shape || !input.shape[1] || !input.shape[2])
return input;
let final;
if (cropBox) {
t.cropped = tfjs_esm_exports.image.cropAndResize(input, [cropBox], [0], [input.shape[1], input.shape[2]]);
}
if (input.shape[1] !== input.shape[2]) {
const height = box4 ? [Math.trunc(input.shape[1] * box4[1]), Math.trunc(input.shape[1] * (box4[1] + box4[3]))] : [input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0, input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0];
const width = box4 ? [Math.trunc(input.shape[2] * box4[0]), Math.trunc(input.shape[2] * (box4[0] + box4[2]))] : [input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0, input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0];
const height = [
input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0,
input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0
];
const width = [
input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0,
input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0
];
padding = [
[0, 0],
height,
width,
[0, 0]
];
if (box4) {
t.resize = tfjs_esm_exports.image.cropAndResize(input, [box4], [0], [size2, size2]);
} else {
t.pad = tfjs_esm_exports.pad(input, padding);
t.pad = tfjs_esm_exports.pad(t.cropped || input, padding);
t.resize = tfjs_esm_exports.image.resizeBilinear(t.pad, [size2, size2]);
}
final = tfjs_esm_exports.div(t.resize, constants.tf255);
} else if (input.shape[1] !== size2) {
t.resize = tfjs_esm_exports.image.resizeBilinear(input, [size2, size2]);
t.resize = tfjs_esm_exports.image.resizeBilinear(t.cropped || input, [size2, size2]);
final = tfjs_esm_exports.div(t.resize, constants.tf255);
} else {
final = tfjs_esm_exports.div(input, constants.tf255);
final = tfjs_esm_exports.div(t.cropped || input, constants.tf255);
}
Object.keys(t).forEach((tensor3) => tfjs_esm_exports.dispose(t[tensor3]));
return final;
@ -5328,19 +5324,21 @@ function rescaleKeypoints(keypoints, outputSize2) {
];
kpt4.positionRaw = [kpt4.position[0] / outputSize2[0], kpt4.position[1] / outputSize2[1], kpt4.position[2]];
}
return keypoints;
}
function rescaleBoxes(boxes, outputSize2) {
for (const box4 of boxes) {
box4.box = [
Math.trunc(box4.box[0] * (outputSize2[0] + padding[2][0] + padding[2][1]) / outputSize2[0]),
Math.trunc(box4.box[1] * (outputSize2[1] + padding[1][0] + padding[1][1]) / outputSize2[1]),
Math.trunc(box4.box[2] * (outputSize2[0] + padding[2][0] + padding[2][1]) / outputSize2[0]),
Math.trunc(box4.box[3] * (outputSize2[1] + padding[1][0] + padding[1][1]) / outputSize2[1])
if (cropBox) {
for (const kpt4 of keypoints) {
kpt4.positionRaw = [
kpt4.positionRaw[0] + cropBox[1],
kpt4.positionRaw[1] + cropBox[0],
kpt4.positionRaw[2]
];
kpt4.position = [
Math.trunc(kpt4.positionRaw[0] * outputSize2[0]),
Math.trunc(kpt4.positionRaw[1] * outputSize2[1]),
kpt4.positionRaw[2]
];
box4.boxRaw = [box4.box[0] / outputSize2[0], box4.box[1] / outputSize2[1], box4.box[2] / outputSize2[0], box4.box[3] / outputSize2[1]];
}
return boxes;
}
return keypoints;
}
async function detectLandmarks(input, config3, outputSize2) {
var _a;
@ -5362,7 +5360,8 @@ async function detectLandmarks(input, config3, outputSize2) {
if (poseScore < (config3.body.minConfidence || 0))
return null;
const keypoints = rescaleKeypoints(keypointsRelative, outputSize2);
const boxes = calculateBoxes(keypoints, [outputSize2[0], outputSize2[1]]);
const kpts = keypoints.map((k) => k.position);
const boxes = calc(kpts, [outputSize2[0], outputSize2[1]]);
const annotations2 = {};
for (const [name, indexes] of Object.entries(connected)) {
const pt = [];
@ -5374,22 +5373,9 @@ async function detectLandmarks(input, config3, outputSize2) {
}
annotations2[name] = pt;
}
const body4 = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.keypointsBox, boxRaw: boxes.keypointsBoxRaw, keypoints, annotations: annotations2 };
const body4 = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.box, boxRaw: boxes.boxRaw, keypoints, annotations: annotations2 };
return body4;
}
async function detectBoxes(input, config3, outputSize2) {
var _a;
const t = {};
t.res = (_a = models.detector) == null ? void 0 : _a.execute(input, ["Identity"]);
t.logitsRaw = tfjs_esm_exports.slice(t.res, [0, 0, 0], [1, -1, 1]);
t.boxesRaw = tfjs_esm_exports.slice(t.res, [0, 0, 1], [1, -1, -1]);
t.logits = tfjs_esm_exports.squeeze(t.logitsRaw);
t.boxes = tfjs_esm_exports.squeeze(t.boxesRaw);
const boxes = await decode(t.boxes, t.logits, config3, outputSize2);
rescaleBoxes(boxes, outputSize2);
Object.keys(t).forEach((tensor3) => tfjs_esm_exports.dispose(t[tensor3]));
return boxes;
}
async function predict5(input, config3) {
const outputSize2 = [input.shape[2] || 0, input.shape[1] || 0];
const skipTime = (config3.body.skipTime || 0) > now() - lastTime5;
@ -5398,26 +5384,13 @@ async function predict5(input, config3) {
skipped5++;
} else {
const t = {};
if (config3.body["detector"] && config3.body["detector"]["enabled"]) {
t.detector = await prepareImage(input, 224);
const boxes = await detectBoxes(t.detector, config3, outputSize2);
if (boxes && boxes.length === 1) {
t.landmarks = await prepareImage(input, 256, boxes[0].box);
t.landmarks = await prepareImage(input, 256);
cache = await detectLandmarks(t.landmarks, config3, outputSize2);
}
if (cache)
cache.score = boxes[0].score;
} else {
t.landmarks = await prepareImage(input, 256, lastBox);
cache = await detectLandmarks(t.landmarks, config3, outputSize2);
}
Object.keys(t).forEach((tensor3) => tfjs_esm_exports.dispose(t[tensor3]));
lastTime5 = now();
skipped5 = 0;
}
if (cache)
return [cache];
return [];
return cache ? [cache] : [];
}
// src/object/labels.ts
@ -5555,13 +5528,13 @@ async function process3(res, outputShape, config3) {
detections[0][id][2] / inputSize4 - x,
detections[0][id][3] / inputSize4 - y
];
const box4 = [
const box5 = [
Math.trunc(boxRaw[0] * outputShape[0]),
Math.trunc(boxRaw[1] * outputShape[1]),
Math.trunc(boxRaw[2] * outputShape[0]),
Math.trunc(boxRaw[3] * outputShape[1])
];
results.push({ id: i++, score, class: classVal, label, box: box4, boxRaw });
results.push({ id: i++, score, class: classVal, label, box: box5, boxRaw });
}
Object.keys(t).forEach((tensor3) => tfjs_esm_exports.dispose(t[tensor3]));
return results;
@ -5679,10 +5652,10 @@ async function predict7(image29, config3) {
tfjs_esm_exports.dispose(tensor3);
if (resT) {
cache2.keypoints.length = 0;
const squeeze11 = resT.squeeze();
const squeeze10 = resT.squeeze();
tfjs_esm_exports.dispose(resT);
const stack5 = squeeze11.unstack(2);
tfjs_esm_exports.dispose(squeeze11);
const stack5 = squeeze10.unstack(2);
tfjs_esm_exports.dispose(squeeze10);
for (let id = 0; id < stack5.length; id++) {
const [x2, y2, partScore] = await max2d(stack5[id], config3.body.minConfidence);
if (partScore > (((_a = config3.body) == null ? void 0 : _a.minConfidence) || 0)) {
@ -5894,20 +5867,20 @@ var getLeftToRightEyeDepthDifference = (rawCoords) => {
return leftEyeZ - rightEyeZ;
};
var getEyeBox = (rawCoords, face5, eyeInnerCornerIndex, eyeOuterCornerIndex, meshSize, flip = false) => {
const box4 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), irisEnlarge));
const boxSize = getBoxSize(box4);
const box5 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), irisEnlarge));
const boxSize = getBoxSize(box5);
let crop2 = tfjs_esm_exports.image.cropAndResize(face5, [[
box4.startPoint[1] / meshSize,
box4.startPoint[0] / meshSize,
box4.endPoint[1] / meshSize,
box4.endPoint[0] / meshSize
box5.startPoint[1] / meshSize,
box5.startPoint[0] / meshSize,
box5.endPoint[1] / meshSize,
box5.endPoint[0] / meshSize
]], [0], [inputSize5, inputSize5]);
if (flip && env.kernels.includes("flipleftright")) {
const flipped = tfjs_esm_exports.image.flipLeftRight(crop2);
tfjs_esm_exports.dispose(crop2);
crop2 = flipped;
}
return { box: box4, boxSize, crop: crop2 };
return { box: box5, boxSize, crop: crop2 };
};
var getEyeCoords = (eyeData, eyeBox, eyeBoxSize, flip = false) => {
const eyeRawCoords = [];
@ -6001,7 +5974,7 @@ async function predict10(input, config3) {
const newCache = [];
let id = 0;
for (let i = 0; i < boxCache.length; i++) {
let box4 = boxCache[i];
let box5 = boxCache[i];
let angle = 0;
let rotationMatrix;
const face5 = {
@ -6015,20 +5988,20 @@ async function predict10(input, config3) {
faceScore: 0,
annotations: {}
};
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box4, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize6 : size());
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box5, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize6 : size());
if ((_f = config3 == null ? void 0 : config3.filter) == null ? void 0 : _f.equalization) {
const equilized = await histogramEqualization(face5.tensor);
tfjs_esm_exports.dispose(face5.tensor);
face5.tensor = equilized;
}
face5.boxScore = Math.round(100 * box4.confidence) / 100;
face5.boxScore = Math.round(100 * box5.confidence) / 100;
if (!((_g = config3.face.mesh) == null ? void 0 : _g.enabled)) {
face5.box = getClampedBox(box4, input);
face5.boxRaw = getRawBox(box4, input);
face5.box = getClampedBox(box5, input);
face5.boxRaw = getRawBox(box5, input);
face5.score = face5.boxScore;
face5.mesh = box4.landmarks.map((pt) => [
(box4.startPoint[0] + box4.endPoint[0]) / 2 + (box4.endPoint[0] + box4.startPoint[0]) * pt[0] / size(),
(box4.startPoint[1] + box4.endPoint[1]) / 2 + (box4.endPoint[1] + box4.startPoint[1]) * pt[1] / size()
face5.mesh = box5.landmarks.map((pt) => [
(box5.startPoint[0] + box5.endPoint[0]) / 2 + (box5.endPoint[0] + box5.startPoint[0]) * pt[0] / size(),
(box5.startPoint[1] + box5.endPoint[1]) / 2 + (box5.endPoint[1] + box5.startPoint[1]) * pt[1] / size()
]);
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize6]);
for (const key of Object.keys(blazeFaceLandmarks))
@ -6044,24 +6017,24 @@ async function predict10(input, config3) {
let rawCoords = await coordsReshaped.array();
tfjs_esm_exports.dispose([contourCoords, coordsReshaped, confidence, contours]);
if (face5.faceScore < (((_h = config3.face.detector) == null ? void 0 : _h.minConfidence) || 1)) {
box4.confidence = face5.faceScore;
box5.confidence = face5.faceScore;
} else {
if ((_i = config3.face.iris) == null ? void 0 : _i.enabled)
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize6);
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize6);
face5.mesh = transformRawCoords(rawCoords, box5, angle, rotationMatrix, inputSize6);
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize6]);
for (const key of Object.keys(meshAnnotations))
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
const boxCalculated = calculateLandmarksBoundingBox(face5.mesh);
const boxEnlarged = enlargeBox(boxCalculated, ((_j = config3.face.detector) == null ? void 0 : _j.cropFactor) || 1.6);
const boxSquared = squarifyBox(boxEnlarged);
box4 = { ...boxSquared, confidence: box4.confidence };
face5.box = getClampedBox(box4, input);
face5.boxRaw = getRawBox(box4, input);
box5 = { ...boxSquared, confidence: box5.confidence };
face5.box = getClampedBox(box5, input);
face5.boxRaw = getRawBox(box5, input);
face5.score = face5.faceScore;
newCache.push(box4);
newCache.push(box5);
tfjs_esm_exports.dispose(face5.tensor);
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box4, input, inputSize6);
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box5, input, inputSize6);
}
}
faces.push(face5);
@ -6166,54 +6139,54 @@ async function predict11(image29, config3, idx, count2) {
}
// src/hand/handposeutil.ts
function getBoxSize2(box4) {
function getBoxSize2(box5) {
return [
Math.abs(box4.endPoint[0] - box4.startPoint[0]),
Math.abs(box4.endPoint[1] - box4.startPoint[1])
Math.abs(box5.endPoint[0] - box5.startPoint[0]),
Math.abs(box5.endPoint[1] - box5.startPoint[1])
];
}
function getBoxCenter2(box4) {
function getBoxCenter2(box5) {
return [
box4.startPoint[0] + (box4.endPoint[0] - box4.startPoint[0]) / 2,
box4.startPoint[1] + (box4.endPoint[1] - box4.startPoint[1]) / 2
box5.startPoint[0] + (box5.endPoint[0] - box5.startPoint[0]) / 2,
box5.startPoint[1] + (box5.endPoint[1] - box5.startPoint[1]) / 2
];
}
function cutBoxFromImageAndResize2(box4, image29, cropSize) {
function cutBoxFromImageAndResize2(box5, image29, cropSize) {
const h = image29.shape[1];
const w = image29.shape[2];
const boxes = [[
box4.startPoint[1] / h,
box4.startPoint[0] / w,
box4.endPoint[1] / h,
box4.endPoint[0] / w
box5.startPoint[1] / h,
box5.startPoint[0] / w,
box5.endPoint[1] / h,
box5.endPoint[0] / w
]];
return tfjs_esm_exports.image.cropAndResize(image29, boxes, [0], cropSize);
}
function scaleBoxCoordinates2(box4, factor) {
const startPoint = [box4.startPoint[0] * factor[0], box4.startPoint[1] * factor[1]];
const endPoint = [box4.endPoint[0] * factor[0], box4.endPoint[1] * factor[1]];
const palmLandmarks = box4.palmLandmarks.map((coord) => {
function scaleBoxCoordinates2(box5, factor) {
const startPoint = [box5.startPoint[0] * factor[0], box5.startPoint[1] * factor[1]];
const endPoint = [box5.endPoint[0] * factor[0], box5.endPoint[1] * factor[1]];
const palmLandmarks = box5.palmLandmarks.map((coord) => {
const scaledCoord = [coord[0] * factor[0], coord[1] * factor[1]];
return scaledCoord;
});
return { startPoint, endPoint, palmLandmarks, confidence: box4.confidence };
return { startPoint, endPoint, palmLandmarks, confidence: box5.confidence };
}
function enlargeBox2(box4, factor = 1.5) {
const center = getBoxCenter2(box4);
const size2 = getBoxSize2(box4);
function enlargeBox2(box5, factor = 1.5) {
const center = getBoxCenter2(box5);
const size2 = getBoxSize2(box5);
const newHalfSize = [factor * size2[0] / 2, factor * size2[1] / 2];
const startPoint = [center[0] - newHalfSize[0], center[1] - newHalfSize[1]];
const endPoint = [center[0] + newHalfSize[0], center[1] + newHalfSize[1]];
return { startPoint, endPoint, palmLandmarks: box4.palmLandmarks };
return { startPoint, endPoint, palmLandmarks: box5.palmLandmarks };
}
function squarifyBox2(box4) {
const centers = getBoxCenter2(box4);
const size2 = getBoxSize2(box4);
function squarifyBox2(box5) {
const centers = getBoxCenter2(box5);
const size2 = getBoxSize2(box5);
const maxEdge = Math.max(...size2);
const halfSize = maxEdge / 2;
const startPoint = [centers[0] - halfSize, centers[1] - halfSize];
const endPoint = [centers[0] + halfSize, centers[1] + halfSize];
return { startPoint, endPoint, palmLandmarks: box4.palmLandmarks };
return { startPoint, endPoint, palmLandmarks: box5.palmLandmarks };
}
function normalizeRadians2(angle) {
return angle - 2 * Math.PI * Math.floor((angle + Math.PI) / (2 * Math.PI));
@ -9287,9 +9260,9 @@ var HandDetector = class {
p.slice = tfjs_esm_exports.slice(t.predictions, [index2, 5], [1, 14]);
p.norm = this.normalizeLandmarks(p.slice, index2);
p.palmLandmarks = tfjs_esm_exports.reshape(p.norm, [-1, 2]);
const box4 = await p.box.data();
const startPoint = box4.slice(0, 2);
const endPoint = box4.slice(2, 4);
const box5 = await p.box.data();
const startPoint = box5.slice(0, 2);
const endPoint = box5.slice(2, 4);
const palmLandmarks = await p.palmLandmarks.array();
const hand3 = { startPoint, endPoint, palmLandmarks, confidence: scores[index2] };
const scaled = scaleBoxCoordinates2(hand3, [input.shape[2] / this.inputSize, input.shape[1] / this.inputSize]);
@ -9875,24 +9848,24 @@ async function predict12(input, config3) {
}
}
const keypoints = predictions[i].landmarks;
let box4 = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0, 0];
let box5 = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0, 0];
let boxRaw = [0, 0, 0, 0];
if (keypoints && keypoints.length > 0) {
for (const pt of keypoints) {
if (pt[0] < box4[0])
box4[0] = pt[0];
if (pt[1] < box4[1])
box4[1] = pt[1];
if (pt[0] > box4[2])
box4[2] = pt[0];
if (pt[1] > box4[3])
box4[3] = pt[1];
if (pt[0] < box5[0])
box5[0] = pt[0];
if (pt[1] < box5[1])
box5[1] = pt[1];
if (pt[0] > box5[2])
box5[2] = pt[0];
if (pt[1] > box5[3])
box5[3] = pt[1];
}
box4[2] -= box4[0];
box4[3] -= box4[1];
boxRaw = [box4[0] / (input.shape[2] || 0), box4[1] / (input.shape[1] || 0), box4[2] / (input.shape[2] || 0), box4[3] / (input.shape[1] || 0)];
box5[2] -= box5[0];
box5[3] -= box5[1];
boxRaw = [box5[0] / (input.shape[2] || 0), box5[1] / (input.shape[1] || 0), box5[2] / (input.shape[2] || 0), box5[3] / (input.shape[1] || 0)];
} else {
box4 = predictions[i].box ? [
box5 = predictions[i].box ? [
Math.trunc(Math.max(0, predictions[i].box.topLeft[0])),
Math.trunc(Math.max(0, predictions[i].box.topLeft[1])),
Math.trunc(Math.min(input.shape[2] || 0, predictions[i].box.bottomRight[0]) - Math.max(0, predictions[i].box.topLeft[0])),
@ -9912,7 +9885,7 @@ async function predict12(input, config3) {
boxScore: Math.round(100 * predictions[i].boxConfidence) / 100,
fingerScore: Math.round(100 * predictions[i].fingerConfidence) / 100,
label: "hand",
box: box4,
box: box5,
boxRaw,
keypoints,
annotations: annotations2,
@ -9953,40 +9926,6 @@ async function load13(config3) {
return [handDetectorModel, handPoseModel];
}
// src/util/box.ts
function calc(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const box4 = [min2[0], min2[1], max4[0] - min2[0], max4[1] - min2[1]];
const boxRaw = [box4[0] / outputSize2[0], box4[1] / outputSize2[1], box4[2] / outputSize2[0], box4[3] / outputSize2[1]];
return { box: box4, boxRaw };
}
function square(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const center = [(min2[0] + max4[0]) / 2, (min2[1] + max4[1]) / 2];
const dist = Math.max(center[0] - min2[0], center[1] - min2[1], -center[0] + max4[0], -center[1] + max4[1]);
const box4 = [Math.trunc(center[0] - dist), Math.trunc(center[1] - dist), Math.trunc(2 * dist), Math.trunc(2 * dist)];
const boxRaw = [box4[0] / outputSize2[0], box4[1] / outputSize2[1], box4[2] / outputSize2[0], box4[3] / outputSize2[1]];
return { box: box4, boxRaw };
}
function scale(box4, scaleFact) {
const dist = [box4[2] * scaleFact, box4[3] * scaleFact];
const newBox = [
box4[0] - (dist[0] - box4[2]) / 2,
box4[1] - (dist[1] - box4[3]) / 2,
dist[0],
dist[1]
];
return newBox;
}
function crop(box4) {
const yxBox = [Math.max(0, box4[1]), Math.max(0, box4[0]), Math.min(1, box4[3] + box4[1]), Math.min(1, box4[2] + box4[0])];
return yxBox;
}
// src/hand/handtrack.ts
var models2 = [null, null];
var modelOutputNodes = ["StatefulPartitionedCall/Postprocessor/Slice", "StatefulPartitionedCall/Postprocessor/ExpandDims_1"];
@ -10004,11 +9943,11 @@ var cache3 = {
hands: []
};
var fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
middle: [9, 10, 11, 12],
ring: [13, 14, 15, 16],
pinky: [17, 18, 19, 20],
thumb: [0, 1, 2, 3, 4],
index: [0, 5, 6, 7, 8],
middle: [0, 9, 10, 11, 12],
ring: [0, 13, 14, 15, 16],
pinky: [0, 17, 18, 19, 20],
palm: [0]
};
async function loadDetect2(config3) {
@ -10553,7 +10492,7 @@ async function process4(res, inputSize9, outputShape, config3) {
];
let boxRaw = [x, y, w, h];
boxRaw = boxRaw.map((a) => Math.max(0, Math.min(a, 1)));
const box4 = [
const box5 = [
boxRaw[0] * outputShape[0],
boxRaw[1] * outputShape[1],
boxRaw[2] * outputShape[0],
@ -10564,7 +10503,7 @@ async function process4(res, inputSize9, outputShape, config3) {
score: Math.round(100 * score) / 100,
class: j + 1,
label: labels[j].label,
box: box4.map((a) => Math.trunc(a)),
box: box5.map((a) => Math.trunc(a)),
boxRaw
};
results.push(result);
@ -10904,7 +10843,7 @@ function getInstanceScore(existingPoses, keypoints) {
}, 0);
return notOverlappedKeypointScores / keypoints.length;
}
function decode2(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence2) {
function decode(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence2) {
const poses = [];
const queue = buildPartWithScoreQueue(minConfidence2, scores);
while (poses.length < maxDetected && !queue.empty()) {
@ -10915,9 +10854,9 @@ function decode2(offsets, scores, displacementsFwd, displacementsBwd, maxDetecte
let keypoints = decodePose(root, scores, offsets, displacementsFwd, displacementsBwd);
keypoints = keypoints.filter((a) => a.score > minConfidence2);
const score = getInstanceScore(poses, keypoints);
const box4 = getBoundingBox(keypoints);
const box5 = getBoundingBox(keypoints);
if (score > minConfidence2)
poses.push({ keypoints, box: box4, score: Math.round(100 * score) / 100 });
poses.push({ keypoints, box: box5, score: Math.round(100 * score) / 100 });
}
return poses;
}
@ -10935,7 +10874,7 @@ async function predict17(input, config3) {
const buffers = await Promise.all(res.map((tensor3) => tensor3.buffer()));
for (const t of res)
tfjs_esm_exports.dispose(t);
const decoded = await decode2(buffers[0], buffers[1], buffers[2], buffers[3], config3.body.maxDetected, config3.body.minConfidence);
const decoded = await decode(buffers[0], buffers[1], buffers[2], buffers[3], config3.body.maxDetected, config3.body.minConfidence);
if (!model16.inputs[0].shape)
return [];
const scaled = scalePoses(decoded, [input.shape[1], input.shape[2]], [model16.inputs[0].shape[2], model16.inputs[0].shape[1]]);
@ -11988,7 +11927,7 @@ var calculateFaceAngle = (face5, imageSize) => {
thetaY = 0;
if (isNaN(thetaZ))
thetaZ = 0;
return { pitch: 2 * -thetaX, yaw: 2 * -thetaY, roll: 2 * -thetaZ };
return { pitch: -thetaX, yaw: -thetaY, roll: -thetaZ };
};
const meshToEulerAngle = (mesh2) => {
const radians = (a1, a2, b1, b2) => Math.atan2(b2 - a2, b1 - a1);
@ -12334,7 +12273,7 @@ function calc2(newResult, config3) {
bufferedResult.body = JSON.parse(JSON.stringify(newResult.body));
} else {
for (let i = 0; i < newResult.body.length; i++) {
const box4 = newResult.body[i].box.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].box[j] + newBoxCoord) / bufferedFactor);
const box5 = newResult.body[i].box.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].box[j] + newBoxCoord) / bufferedFactor);
const boxRaw = newResult.body[i].boxRaw.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].boxRaw[j] + newBoxCoord) / bufferedFactor);
const keypoints = newResult.body[i].keypoints.map((newKpt, j) => ({
score: newKpt.score,
@ -12368,14 +12307,14 @@ function calc2(newResult, config3) {
}
annotations2[name] = pt;
}
bufferedResult.body[i] = { ...newResult.body[i], box: box4, boxRaw, keypoints, annotations: annotations2 };
bufferedResult.body[i] = { ...newResult.body[i], box: box5, boxRaw, keypoints, annotations: annotations2 };
}
}
if (!bufferedResult.hand || newResult.hand.length !== bufferedResult.hand.length) {
bufferedResult.hand = JSON.parse(JSON.stringify(newResult.hand));
} else {
for (let i = 0; i < newResult.hand.length; i++) {
const box4 = newResult.hand[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].box[j] + b) / bufferedFactor);
const box5 = newResult.hand[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.hand[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].boxRaw[j] + b) / bufferedFactor);
if (bufferedResult.hand[i].keypoints.length !== newResult.hand[i].keypoints.length)
bufferedResult.hand[i].keypoints = newResult.hand[i].keypoints;
@ -12389,14 +12328,14 @@ function calc2(newResult, config3) {
annotations2[key] = newResult.hand[i].annotations[key] && newResult.hand[i].annotations[key][0] ? newResult.hand[i].annotations[key].map((val, j) => val.map((coord, k) => ((bufferedFactor - 1) * bufferedResult.hand[i].annotations[key][j][k] + coord) / bufferedFactor)) : null;
}
}
bufferedResult.hand[i] = { ...newResult.hand[i], box: box4, boxRaw, keypoints, annotations: annotations2 };
bufferedResult.hand[i] = { ...newResult.hand[i], box: box5, boxRaw, keypoints, annotations: annotations2 };
}
}
if (!bufferedResult.face || newResult.face.length !== bufferedResult.face.length) {
bufferedResult.face = JSON.parse(JSON.stringify(newResult.face));
} else {
for (let i = 0; i < newResult.face.length; i++) {
const box4 = newResult.face[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].box[j] + b) / bufferedFactor);
const box5 = newResult.face[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.face[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].boxRaw[j] + b) / bufferedFactor);
if (newResult.face[i].rotation) {
const rotation = { matrix: [0, 0, 0, 0, 0, 0, 0, 0, 0], angle: { roll: 0, yaw: 0, pitch: 0 }, gaze: { bearing: 0, strength: 0 } };
@ -12410,18 +12349,18 @@ function calc2(newResult, config3) {
bearing: ((bufferedFactor - 1) * (((_u = (_t = bufferedResult.face[i].rotation) == null ? void 0 : _t.gaze) == null ? void 0 : _u.bearing) || 0) + (((_w = (_v = newResult.face[i].rotation) == null ? void 0 : _v.gaze) == null ? void 0 : _w.bearing) || 0)) / bufferedFactor,
strength: ((bufferedFactor - 1) * (((_y = (_x = bufferedResult.face[i].rotation) == null ? void 0 : _x.gaze) == null ? void 0 : _y.strength) || 0) + (((_A = (_z = newResult.face[i].rotation) == null ? void 0 : _z.gaze) == null ? void 0 : _A.strength) || 0)) / bufferedFactor
};
bufferedResult.face[i] = { ...newResult.face[i], rotation, box: box4, boxRaw };
bufferedResult.face[i] = { ...newResult.face[i], rotation, box: box5, boxRaw };
}
bufferedResult.face[i] = { ...newResult.face[i], box: box4, boxRaw };
bufferedResult.face[i] = { ...newResult.face[i], box: box5, boxRaw };
}
}
if (!bufferedResult.object || newResult.object.length !== bufferedResult.object.length) {
bufferedResult.object = JSON.parse(JSON.stringify(newResult.object));
} else {
for (let i = 0; i < newResult.object.length; i++) {
const box4 = newResult.object[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].box[j] + b) / bufferedFactor);
const box5 = newResult.object[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.object[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].boxRaw[j] + b) / bufferedFactor);
bufferedResult.object[i] = { ...newResult.object[i], box: box4, boxRaw };
bufferedResult.object[i] = { ...newResult.object[i], box: box5, boxRaw };
}
}
if (newResult.persons) {
@ -12430,7 +12369,7 @@ function calc2(newResult, config3) {
bufferedResult.persons = JSON.parse(JSON.stringify(newPersons));
} else {
for (let i = 0; i < newPersons.length; i++) {
bufferedResult.persons[i].box = newPersons[i].box.map((box4, j) => ((bufferedFactor - 1) * bufferedResult.persons[i].box[j] + box4) / bufferedFactor);
bufferedResult.persons[i].box = newPersons[i].box.map((box5, j) => ((bufferedFactor - 1) * bufferedResult.persons[i].box[j] + box5) / bufferedFactor);
}
}
}
@ -12521,10 +12460,10 @@ function join2(faces, bodies, hands, gestures, shape) {
}
const x = [];
const y = [];
const extractXY = (box4) => {
if (box4 && box4.length === 4) {
x.push(box4[0], box4[0] + box4[2]);
y.push(box4[1], box4[1] + box4[3]);
const extractXY = (box5) => {
if (box5 && box5.length === 4) {
x.push(box5[0], box5[0] + box5[2]);
y.push(box5[1], box5[1] + box5[3]);
}
};
extractXY((_k = person2.face) == null ? void 0 : _k.box);

File diff suppressed because one or more lines are too long

504
dist/human.esm.js vendored
View File

@ -49402,19 +49402,20 @@ var PackProgram = class {
this.packedInputs = false;
this.packedOutput = true;
this.outputShape = outputShape;
const rank = outputShape.length;
if (rank === 0) {
this.rank = outputShape.length;
this.enableShapeUniforms = useShapeUniforms(this.outputShape.length);
if (this.rank === 0) {
this.userCode = `
void main() {
setOutput(vec4(getA(), 0., 0., 0.));
}
`;
} else {
const channels = getChannels("rc", rank);
const dtype = getCoordsDataType(rank);
const outOfBoundsCondition = getOutOfBoundsCondition(rank, outputShape, channels);
const setup46 = getSetup(rank, outputShape[outputShape.length - 1], outputShape[outputShape.length - 2], channels);
const output = getOutput(outputShape, channels);
const channels = getChannels("rc", this.rank);
const dtype = getCoordsDataType(this.rank);
const outOfBoundsCondition = this.getOutOfBoundsCondition(channels);
const setup46 = this.getSetup(channels);
const output = this.getOutput(channels);
this.userCode = `
void main() {
${dtype} rc = getOutputCoords();
@ -49430,13 +49431,12 @@ var PackProgram = class {
`;
}
}
};
function getSourceCoordsArr(rank, dims) {
getSourceCoordsArr(dims) {
const coords32 = [];
for (let row = 0; row <= 1; row++) {
for (let col = 0; col <= 1; col++) {
let coord = `${row === 0 ? "r" : "rp1"}, ${col === 0 ? "c" : "cp1"}`;
for (let d = 2; d < rank; d++) {
for (let d = 2; d < this.rank; d++) {
coord = `${dims[dims.length - 1 - d]},` + coord;
}
coords32.push(coord);
@ -49444,40 +49444,41 @@ function getSourceCoordsArr(rank, dims) {
}
return coords32;
}
function getOutOfBoundsCondition(rank, shape, dims) {
if (rank === 1) {
return `rc > ${shape[0]}`;
getOutOfBoundsCondition(dims) {
if (this.rank === 1) {
return `rc > ${this.enableShapeUniforms ? "outShape" : this.outputShape[0]}`;
}
let cond = "";
for (let i = rank - 2; i < rank; i++) {
cond += `${dims[i]} >= ${shape[i]}`;
if (i < rank - 1) {
for (let i = this.rank - 2; i < this.rank; i++) {
cond += `${dims[i]} >= ${this.enableShapeUniforms ? `outShape[${i}]` : this.outputShape[i]}`;
if (i < this.rank - 1) {
cond += "||";
}
}
return cond;
}
function getSetup(rank, cols, rows, dims) {
if (rank === 1) {
getSetup(dims) {
if (this.rank === 1) {
return "";
}
const innerDims = dims.slice(-2);
const col = this.enableShapeUniforms ? `outShape[${this.rank} - 1]` : this.outputShape[this.rank - 1];
const row = this.enableShapeUniforms ? `outShape[${this.rank} - 2]` : this.outputShape[this.rank - 2];
return `
int r = ${innerDims[0]};
int c = ${innerDims[1]};
int rp1 = r + 1;
int cp1 = c + 1;
bool cEdge = cp1 >= ${cols};
bool rEdge = rp1 >= ${rows};
bool cEdge = cp1 >= ${col};
bool rEdge = rp1 >= ${row};
`;
}
function getOutput(shape, dims) {
const rank = shape.length;
const sourceCoords = getSourceCoordsArr(rank, dims);
if (rank === 1) {
getOutput(dims) {
const sourceCoords = this.getSourceCoordsArr(dims);
if (this.rank === 1) {
return `getA(rc),
rc + 1 >= ${shape[0]} ? 0. : getA(rc + 1),
rc + 1 >= ${this.enableShapeUniforms ? "outShape" : this.outputShape[0]} ? 0. : getA(rc + 1),
0, 0`;
}
return `getA(${sourceCoords[0]}),
@ -49485,6 +49486,7 @@ function getOutput(shape, dims) {
rEdge ? 0. : getA(${sourceCoords[2]}),
rEdge || cEdge ? 0. : getA(${sourceCoords[3]})`;
}
};
var ReshapePackedProgram = class {
constructor(outputShape, inputShape) {
this.variableNames = ["A"];
@ -49827,6 +49829,7 @@ var UnpackProgram = class {
this.packedInputs = true;
this.packedOutput = false;
this.outputShape = outputShape;
this.enableShapeUniforms = useShapeUniforms(this.outputShape.length);
const rank = outputShape.length;
const channels = getChannels("rc", rank);
const dtype = getCoordsDataType(rank);
@ -70672,7 +70675,7 @@ registerBackend("wasm", async () => {
const { wasm } = await init();
return new BackendWasm(wasm);
}, WASM_PRIORITY);
var externalVersion = "3.11.0-20211123";
var externalVersion = "3.11.0-20211124";
var version8 = {
tfjs: externalVersion,
"tfjs-core": externalVersion,
@ -71818,8 +71821,8 @@ async function predict(image7, config3, idx, count3) {
if (!(model2 == null ? void 0 : model2.inputs[0].shape))
return;
const t = {};
const box4 = [[0, 0.1, 0.9, 0.9]];
t.resize = image.cropAndResize(image7, box4, [0], [model2.inputs[0].shape[2], model2.inputs[0].shape[1]]);
const box5 = [[0, 0.1, 0.9, 0.9]];
t.resize = image.cropAndResize(image7, box5, [0], [model2.inputs[0].shape[2], model2.inputs[0].shape[1]]);
const obj = { age: 0, gender: "unknown", genderScore: 0, race: [] };
if ((_a2 = config3.face["gear"]) == null ? void 0 : _a2.enabled)
[t.age, t.gender, t.race] = model2.execute(t.resize, ["age_output", "gender_output", "race_output"]);
@ -75303,44 +75306,44 @@ var UV33 = VTX33.map((x) => UV468[x]);
var UV7 = VTX7.map((x) => UV468[x]);
// src/face/facemeshutil.ts
var getBoxSize = (box4) => [Math.abs(box4.endPoint[0] - box4.startPoint[0]), Math.abs(box4.endPoint[1] - box4.startPoint[1])];
var getBoxCenter = (box4) => [box4.startPoint[0] + (box4.endPoint[0] - box4.startPoint[0]) / 2, box4.startPoint[1] + (box4.endPoint[1] - box4.startPoint[1]) / 2];
var getClampedBox = (box4, input2) => box4 ? [
Math.trunc(Math.max(0, box4.startPoint[0])),
Math.trunc(Math.max(0, box4.startPoint[1])),
Math.trunc(Math.min(input2.shape[2] || 0, box4.endPoint[0]) - Math.max(0, box4.startPoint[0])),
Math.trunc(Math.min(input2.shape[1] || 0, box4.endPoint[1]) - Math.max(0, box4.startPoint[1]))
var getBoxSize = (box5) => [Math.abs(box5.endPoint[0] - box5.startPoint[0]), Math.abs(box5.endPoint[1] - box5.startPoint[1])];
var getBoxCenter = (box5) => [box5.startPoint[0] + (box5.endPoint[0] - box5.startPoint[0]) / 2, box5.startPoint[1] + (box5.endPoint[1] - box5.startPoint[1]) / 2];
var getClampedBox = (box5, input2) => box5 ? [
Math.trunc(Math.max(0, box5.startPoint[0])),
Math.trunc(Math.max(0, box5.startPoint[1])),
Math.trunc(Math.min(input2.shape[2] || 0, box5.endPoint[0]) - Math.max(0, box5.startPoint[0])),
Math.trunc(Math.min(input2.shape[1] || 0, box5.endPoint[1]) - Math.max(0, box5.startPoint[1]))
] : [0, 0, 0, 0];
var getRawBox = (box4, input2) => box4 ? [
box4.startPoint[0] / (input2.shape[2] || 0),
box4.startPoint[1] / (input2.shape[1] || 0),
(box4.endPoint[0] - box4.startPoint[0]) / (input2.shape[2] || 0),
(box4.endPoint[1] - box4.startPoint[1]) / (input2.shape[1] || 0)
var getRawBox = (box5, input2) => box5 ? [
box5.startPoint[0] / (input2.shape[2] || 0),
box5.startPoint[1] / (input2.shape[1] || 0),
(box5.endPoint[0] - box5.startPoint[0]) / (input2.shape[2] || 0),
(box5.endPoint[1] - box5.startPoint[1]) / (input2.shape[1] || 0)
] : [0, 0, 0, 0];
var scaleBoxCoordinates = (box4, factor) => {
const startPoint = [box4.startPoint[0] * factor[0], box4.startPoint[1] * factor[1]];
const endPoint = [box4.endPoint[0] * factor[0], box4.endPoint[1] * factor[1]];
return { startPoint, endPoint, landmarks: box4.landmarks, confidence: box4.confidence };
var scaleBoxCoordinates = (box5, factor) => {
const startPoint = [box5.startPoint[0] * factor[0], box5.startPoint[1] * factor[1]];
const endPoint = [box5.endPoint[0] * factor[0], box5.endPoint[1] * factor[1]];
return { startPoint, endPoint, landmarks: box5.landmarks, confidence: box5.confidence };
};
var cutBoxFromImageAndResize = (box4, image7, cropSize) => {
var cutBoxFromImageAndResize = (box5, image7, cropSize) => {
const h = image7.shape[1];
const w = image7.shape[2];
const crop2 = image.cropAndResize(image7, [[box4.startPoint[1] / h, box4.startPoint[0] / w, box4.endPoint[1] / h, box4.endPoint[0] / w]], [0], cropSize);
const crop2 = image.cropAndResize(image7, [[box5.startPoint[1] / h, box5.startPoint[0] / w, box5.endPoint[1] / h, box5.endPoint[0] / w]], [0], cropSize);
const norm2 = div(crop2, constants.tf255);
dispose(crop2);
return norm2;
};
var enlargeBox = (box4, factor) => {
const center = getBoxCenter(box4);
const size2 = getBoxSize(box4);
var enlargeBox = (box5, factor) => {
const center = getBoxCenter(box5);
const size2 = getBoxSize(box5);
const halfSize = [factor * size2[0] / 2, factor * size2[1] / 2];
return { startPoint: [center[0] - halfSize[0], center[1] - halfSize[1]], endPoint: [center[0] + halfSize[0], center[1] + halfSize[1]], landmarks: box4.landmarks, confidence: box4.confidence };
return { startPoint: [center[0] - halfSize[0], center[1] - halfSize[1]], endPoint: [center[0] + halfSize[0], center[1] + halfSize[1]], landmarks: box5.landmarks, confidence: box5.confidence };
};
var squarifyBox = (box4) => {
const centers = getBoxCenter(box4);
const size2 = getBoxSize(box4);
var squarifyBox = (box5) => {
const centers = getBoxCenter(box5);
const size2 = getBoxSize(box5);
const halfSize = Math.max(...size2) / 2;
return { startPoint: [Math.round(centers[0] - halfSize), Math.round(centers[1] - halfSize)], endPoint: [Math.round(centers[0] + halfSize), Math.round(centers[1] + halfSize)], landmarks: box4.landmarks, confidence: box4.confidence };
return { startPoint: [Math.round(centers[0] - halfSize), Math.round(centers[1] - halfSize)], endPoint: [Math.round(centers[0] + halfSize), Math.round(centers[1] + halfSize)], landmarks: box5.landmarks, confidence: box5.confidence };
};
var calculateLandmarksBoundingBox = (landmarks) => {
const xs = landmarks.map((d) => d[0]);
@ -75408,8 +75411,8 @@ function generateAnchors(inputSize9) {
}
return anchors4;
}
function transformRawCoords(coordsRaw, box4, angle, rotationMatrix, inputSize9) {
const boxSize = getBoxSize(box4);
function transformRawCoords(coordsRaw, box5, angle, rotationMatrix, inputSize9) {
const boxSize = getBoxSize(box5);
const coordsScaled = coordsRaw.map((coord) => [
boxSize[0] / inputSize9 * (coord[0] - inputSize9 / 2),
boxSize[1] / inputSize9 * (coord[1] - inputSize9 / 2),
@ -75419,33 +75422,33 @@ function transformRawCoords(coordsRaw, box4, angle, rotationMatrix, inputSize9)
const coordsRotationMatrix = largeAngle ? buildRotationMatrix(angle, [0, 0]) : fixedRotationMatrix;
const coordsRotated = largeAngle ? coordsScaled.map((coord) => [...rotatePoint(coord, coordsRotationMatrix), coord[2]]) : coordsScaled;
const inverseRotationMatrix = largeAngle ? invertTransformMatrix(rotationMatrix) : fixedRotationMatrix;
const boxCenter = [...getBoxCenter({ startPoint: box4.startPoint, endPoint: box4.endPoint }), 1];
const boxCenter = [...getBoxCenter({ startPoint: box5.startPoint, endPoint: box5.endPoint }), 1];
return coordsRotated.map((coord) => [
Math.round(coord[0] + dot4(boxCenter, inverseRotationMatrix[0])),
Math.round(coord[1] + dot4(boxCenter, inverseRotationMatrix[1])),
Math.round(coord[2] || 0)
]);
}
function correctFaceRotation(rotate, box4, input2, inputSize9) {
const symmetryLine = box4.landmarks.length >= meshLandmarks.count ? meshLandmarks.symmetryLine : blazeFaceLandmarks.symmetryLine;
function correctFaceRotation(rotate, box5, input2, inputSize9) {
const symmetryLine = box5.landmarks.length >= meshLandmarks.count ? meshLandmarks.symmetryLine : blazeFaceLandmarks.symmetryLine;
let angle = 0;
let rotationMatrix = fixedRotationMatrix;
let face5;
if (rotate && env2.kernels.includes("rotatewithoffset")) {
angle = computeRotation(box4.landmarks[symmetryLine[0]], box4.landmarks[symmetryLine[1]]);
angle = computeRotation(box5.landmarks[symmetryLine[0]], box5.landmarks[symmetryLine[1]]);
const largeAngle = angle && angle !== 0 && Math.abs(angle) > 0.2;
if (largeAngle) {
const center = getBoxCenter({ startPoint: box4.startPoint, endPoint: box4.endPoint });
const center = getBoxCenter({ startPoint: box5.startPoint, endPoint: box5.endPoint });
const centerRaw = [center[0] / input2.shape[2], center[1] / input2.shape[1]];
const rotated = image.rotateWithOffset(input2, angle, 0, centerRaw);
rotationMatrix = buildRotationMatrix(-angle, center);
face5 = cutBoxFromImageAndResize(box4, rotated, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, rotated, [inputSize9, inputSize9]);
dispose(rotated);
} else {
face5 = cutBoxFromImageAndResize(box4, input2, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, input2, [inputSize9, inputSize9]);
}
} else {
face5 = cutBoxFromImageAndResize(box4, input2, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, input2, [inputSize9, inputSize9]);
}
return [angle, rotationMatrix, face5];
}
@ -75626,41 +75629,39 @@ async function createAnchors() {
}
anchorTensor = { x: tensor1d(anchors4.map((a) => a.x)), y: tensor1d(anchors4.map((a) => a.y)) };
}
var cropFactor = [5, 5];
function decodeBoxes(boxesTensor, anchor) {
return tidy(() => {
const split4 = split(boxesTensor, 12, 1);
let xCenter = squeeze(split4[0]);
let yCenter = squeeze(split4[1]);
let width = squeeze(split4[2]);
let height = squeeze(split4[3]);
xCenter = add2(div(xCenter, inputSize2), anchor.x);
yCenter = add2(div(yCenter, inputSize2), anchor.y);
width = mul(div(width, inputSize2), cropFactor[0]);
height = mul(div(height, inputSize2), cropFactor[1]);
const xMin = sub(xCenter, div(width, 2));
const yMin = sub(yCenter, div(height, 2));
const boxes = stack([xMin, yMin, width, height], 1);
return boxes;
});
// src/util/box.ts
function calc(keypoints, outputSize2 = [1, 1]) {
const coords10 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min7 = [Math.min(...coords10[0]), Math.min(...coords10[1])];
const max7 = [Math.max(...coords10[0]), Math.max(...coords10[1])];
const box5 = [min7[0], min7[1], max7[0] - min7[0], max7[1] - min7[1]];
const boxRaw = [box5[0] / outputSize2[0], box5[1] / outputSize2[1], box5[2] / outputSize2[0], box5[3] / outputSize2[1]];
return { box: box5, boxRaw };
}
async function decode(boxesTensor, logitsTensor, config3, outputSize2) {
const t = {};
t.boxes = decodeBoxes(boxesTensor, anchorTensor);
t.scores = sigmoid(logitsTensor);
t.argmax = argMax(t.scores);
const i = (await t.argmax.data())[0];
const scores = await t.scores.data();
const detected = [];
const minScore = config3.body["detector"] && config3.body["detector"]["minConfidence"] ? config3.body["detector"]["minConfidence"] : 0;
if (scores[i] >= minScore) {
const boxes = await t.boxes.array();
const boxRaw = boxes[i];
const box4 = [boxRaw[0] * outputSize2[0], boxRaw[1] * outputSize2[1], boxRaw[2] * outputSize2[0], boxRaw[3] * outputSize2[1]];
detected.push({ box: box4, boxRaw, score: scores[i] });
function square4(keypoints, outputSize2 = [1, 1]) {
const coords10 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min7 = [Math.min(...coords10[0]), Math.min(...coords10[1])];
const max7 = [Math.max(...coords10[0]), Math.max(...coords10[1])];
const center = [(min7[0] + max7[0]) / 2, (min7[1] + max7[1]) / 2];
const dist = Math.max(center[0] - min7[0], center[1] - min7[1], -center[0] + max7[0], -center[1] + max7[1]);
const box5 = [Math.trunc(center[0] - dist), Math.trunc(center[1] - dist), Math.trunc(2 * dist), Math.trunc(2 * dist)];
const boxRaw = [box5[0] / outputSize2[0], box5[1] / outputSize2[1], box5[2] / outputSize2[0], box5[3] / outputSize2[1]];
return { box: box5, boxRaw };
}
Object.keys(t).forEach((tensor2) => dispose(t[tensor2]));
return detected;
function scale2(box5, scaleFact) {
const dist = [box5[2] * scaleFact, box5[3] * scaleFact];
const newBox = [
box5[0] - (dist[0] - box5[2]) / 2,
box5[1] - (dist[1] - box5[3]) / 2,
dist[0],
dist[1]
];
return newBox;
}
function crop(box5) {
const yxBox = [Math.max(0, box5[1]), Math.max(0, box5[0]), Math.min(1, box5[3] + box5[1]), Math.min(1, box5[2] + box5[0])];
return yxBox;
}
// src/body/blazepose.ts
@ -75673,7 +75674,7 @@ var outputNodes = {
detector: []
};
var cache = null;
var lastBox;
var cropBox;
var padding = [[0, 0], [0, 0], [0, 0], [0, 0]];
var lastTime5 = 0;
var sigmoid6 = (x) => 1 - 1 / (1 + Math.exp(x));
@ -75710,39 +75711,37 @@ async function loadPose(config3) {
log("cached model:", models.landmarks["modelUrl"]);
return models.landmarks;
}
function calculateBoxes(keypoints, outputSize2) {
const x = keypoints.map((a) => a.position[0]);
const y = keypoints.map((a) => a.position[1]);
const keypointsBox = [Math.min(...x), Math.min(...y), Math.max(...x) - Math.min(...x), Math.max(...y) - Math.min(...y)];
const keypointsBoxRaw = [keypointsBox[0] / outputSize2[0], keypointsBox[1] / outputSize2[1], keypointsBox[2] / outputSize2[0], keypointsBox[3] / outputSize2[1]];
return { keypointsBox, keypointsBoxRaw };
}
async function prepareImage(input2, size2, box4) {
async function prepareImage(input2, size2) {
const t = {};
if (!input2.shape || !input2.shape[1] || !input2.shape[2])
return input2;
let final;
if (cropBox) {
t.cropped = image.cropAndResize(input2, [cropBox], [0], [input2.shape[1], input2.shape[2]]);
}
if (input2.shape[1] !== input2.shape[2]) {
const height = box4 ? [Math.trunc(input2.shape[1] * box4[1]), Math.trunc(input2.shape[1] * (box4[1] + box4[3]))] : [input2.shape[2] > input2.shape[1] ? Math.trunc((input2.shape[2] - input2.shape[1]) / 2) : 0, input2.shape[2] > input2.shape[1] ? Math.trunc((input2.shape[2] - input2.shape[1]) / 2) : 0];
const width = box4 ? [Math.trunc(input2.shape[2] * box4[0]), Math.trunc(input2.shape[2] * (box4[0] + box4[2]))] : [input2.shape[1] > input2.shape[2] ? Math.trunc((input2.shape[1] - input2.shape[2]) / 2) : 0, input2.shape[1] > input2.shape[2] ? Math.trunc((input2.shape[1] - input2.shape[2]) / 2) : 0];
const height = [
input2.shape[2] > input2.shape[1] ? Math.trunc((input2.shape[2] - input2.shape[1]) / 2) : 0,
input2.shape[2] > input2.shape[1] ? Math.trunc((input2.shape[2] - input2.shape[1]) / 2) : 0
];
const width = [
input2.shape[1] > input2.shape[2] ? Math.trunc((input2.shape[1] - input2.shape[2]) / 2) : 0,
input2.shape[1] > input2.shape[2] ? Math.trunc((input2.shape[1] - input2.shape[2]) / 2) : 0
];
padding = [
[0, 0],
height,
width,
[0, 0]
];
if (box4) {
t.resize = image.cropAndResize(input2, [box4], [0], [size2, size2]);
} else {
t.pad = pad(input2, padding);
t.pad = pad(t.cropped || input2, padding);
t.resize = image.resizeBilinear(t.pad, [size2, size2]);
}
final = div(t.resize, constants.tf255);
} else if (input2.shape[1] !== size2) {
t.resize = image.resizeBilinear(input2, [size2, size2]);
t.resize = image.resizeBilinear(t.cropped || input2, [size2, size2]);
final = div(t.resize, constants.tf255);
} else {
final = div(input2, constants.tf255);
final = div(t.cropped || input2, constants.tf255);
}
Object.keys(t).forEach((tensor2) => dispose(t[tensor2]));
return final;
@ -75756,19 +75755,21 @@ function rescaleKeypoints(keypoints, outputSize2) {
];
kpt4.positionRaw = [kpt4.position[0] / outputSize2[0], kpt4.position[1] / outputSize2[1], kpt4.position[2]];
}
return keypoints;
}
function rescaleBoxes(boxes, outputSize2) {
for (const box4 of boxes) {
box4.box = [
Math.trunc(box4.box[0] * (outputSize2[0] + padding[2][0] + padding[2][1]) / outputSize2[0]),
Math.trunc(box4.box[1] * (outputSize2[1] + padding[1][0] + padding[1][1]) / outputSize2[1]),
Math.trunc(box4.box[2] * (outputSize2[0] + padding[2][0] + padding[2][1]) / outputSize2[0]),
Math.trunc(box4.box[3] * (outputSize2[1] + padding[1][0] + padding[1][1]) / outputSize2[1])
if (cropBox) {
for (const kpt4 of keypoints) {
kpt4.positionRaw = [
kpt4.positionRaw[0] + cropBox[1],
kpt4.positionRaw[1] + cropBox[0],
kpt4.positionRaw[2]
];
kpt4.position = [
Math.trunc(kpt4.positionRaw[0] * outputSize2[0]),
Math.trunc(kpt4.positionRaw[1] * outputSize2[1]),
kpt4.positionRaw[2]
];
box4.boxRaw = [box4.box[0] / outputSize2[0], box4.box[1] / outputSize2[1], box4.box[2] / outputSize2[0], box4.box[3] / outputSize2[1]];
}
return boxes;
}
return keypoints;
}
async function detectLandmarks(input2, config3, outputSize2) {
var _a;
@ -75790,7 +75791,8 @@ async function detectLandmarks(input2, config3, outputSize2) {
if (poseScore < (config3.body.minConfidence || 0))
return null;
const keypoints = rescaleKeypoints(keypointsRelative, outputSize2);
const boxes = calculateBoxes(keypoints, [outputSize2[0], outputSize2[1]]);
const kpts = keypoints.map((k) => k.position);
const boxes = calc(kpts, [outputSize2[0], outputSize2[1]]);
const annotations2 = {};
for (const [name, indexes] of Object.entries(connected)) {
const pt = [];
@ -75802,22 +75804,9 @@ async function detectLandmarks(input2, config3, outputSize2) {
}
annotations2[name] = pt;
}
const body4 = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.keypointsBox, boxRaw: boxes.keypointsBoxRaw, keypoints, annotations: annotations2 };
const body4 = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.box, boxRaw: boxes.boxRaw, keypoints, annotations: annotations2 };
return body4;
}
async function detectBoxes(input2, config3, outputSize2) {
var _a;
const t = {};
t.res = (_a = models.detector) == null ? void 0 : _a.execute(input2, ["Identity"]);
t.logitsRaw = slice(t.res, [0, 0, 0], [1, -1, 1]);
t.boxesRaw = slice(t.res, [0, 0, 1], [1, -1, -1]);
t.logits = squeeze(t.logitsRaw);
t.boxes = squeeze(t.boxesRaw);
const boxes = await decode(t.boxes, t.logits, config3, outputSize2);
rescaleBoxes(boxes, outputSize2);
Object.keys(t).forEach((tensor2) => dispose(t[tensor2]));
return boxes;
}
async function predict5(input2, config3) {
const outputSize2 = [input2.shape[2] || 0, input2.shape[1] || 0];
const skipTime = (config3.body.skipTime || 0) > now() - lastTime5;
@ -75826,26 +75815,13 @@ async function predict5(input2, config3) {
skipped5++;
} else {
const t = {};
if (config3.body["detector"] && config3.body["detector"]["enabled"]) {
t.detector = await prepareImage(input2, 224);
const boxes = await detectBoxes(t.detector, config3, outputSize2);
if (boxes && boxes.length === 1) {
t.landmarks = await prepareImage(input2, 256, boxes[0].box);
t.landmarks = await prepareImage(input2, 256);
cache = await detectLandmarks(t.landmarks, config3, outputSize2);
}
if (cache)
cache.score = boxes[0].score;
} else {
t.landmarks = await prepareImage(input2, 256, lastBox);
cache = await detectLandmarks(t.landmarks, config3, outputSize2);
}
Object.keys(t).forEach((tensor2) => dispose(t[tensor2]));
lastTime5 = now();
skipped5 = 0;
}
if (cache)
return [cache];
return [];
return cache ? [cache] : [];
}
// src/object/labels.ts
@ -75983,13 +75959,13 @@ async function process3(res, outputShape, config3) {
detections[0][id][2] / inputSize4 - x,
detections[0][id][3] / inputSize4 - y
];
const box4 = [
const box5 = [
Math.trunc(boxRaw[0] * outputShape[0]),
Math.trunc(boxRaw[1] * outputShape[1]),
Math.trunc(boxRaw[2] * outputShape[0]),
Math.trunc(boxRaw[3] * outputShape[1])
];
results.push({ id: i++, score, class: classVal, label, box: box4, boxRaw });
results.push({ id: i++, score, class: classVal, label, box: box5, boxRaw });
}
Object.keys(t).forEach((tensor2) => dispose(t[tensor2]));
return results;
@ -76322,20 +76298,20 @@ var getLeftToRightEyeDepthDifference = (rawCoords) => {
return leftEyeZ - rightEyeZ;
};
var getEyeBox = (rawCoords, face5, eyeInnerCornerIndex, eyeOuterCornerIndex, meshSize, flip = false) => {
const box4 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), irisEnlarge));
const boxSize = getBoxSize(box4);
const box5 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), irisEnlarge));
const boxSize = getBoxSize(box5);
let crop2 = image.cropAndResize(face5, [[
box4.startPoint[1] / meshSize,
box4.startPoint[0] / meshSize,
box4.endPoint[1] / meshSize,
box4.endPoint[0] / meshSize
box5.startPoint[1] / meshSize,
box5.startPoint[0] / meshSize,
box5.endPoint[1] / meshSize,
box5.endPoint[0] / meshSize
]], [0], [inputSize5, inputSize5]);
if (flip && env2.kernels.includes("flipleftright")) {
const flipped = image.flipLeftRight(crop2);
dispose(crop2);
crop2 = flipped;
}
return { box: box4, boxSize, crop: crop2 };
return { box: box5, boxSize, crop: crop2 };
};
var getEyeCoords = (eyeData, eyeBox, eyeBoxSize, flip = false) => {
const eyeRawCoords = [];
@ -76429,7 +76405,7 @@ async function predict10(input2, config3) {
const newCache = [];
let id = 0;
for (let i = 0; i < boxCache.length; i++) {
let box4 = boxCache[i];
let box5 = boxCache[i];
let angle = 0;
let rotationMatrix;
const face5 = {
@ -76443,20 +76419,20 @@ async function predict10(input2, config3) {
faceScore: 0,
annotations: {}
};
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box4, input2, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize6 : size());
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box5, input2, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize6 : size());
if ((_f = config3 == null ? void 0 : config3.filter) == null ? void 0 : _f.equalization) {
const equilized = await histogramEqualization(face5.tensor);
dispose(face5.tensor);
face5.tensor = equilized;
}
face5.boxScore = Math.round(100 * box4.confidence) / 100;
face5.boxScore = Math.round(100 * box5.confidence) / 100;
if (!((_g = config3.face.mesh) == null ? void 0 : _g.enabled)) {
face5.box = getClampedBox(box4, input2);
face5.boxRaw = getRawBox(box4, input2);
face5.box = getClampedBox(box5, input2);
face5.boxRaw = getRawBox(box5, input2);
face5.score = face5.boxScore;
face5.mesh = box4.landmarks.map((pt) => [
(box4.startPoint[0] + box4.endPoint[0]) / 2 + (box4.endPoint[0] + box4.startPoint[0]) * pt[0] / size(),
(box4.startPoint[1] + box4.endPoint[1]) / 2 + (box4.endPoint[1] + box4.startPoint[1]) * pt[1] / size()
face5.mesh = box5.landmarks.map((pt) => [
(box5.startPoint[0] + box5.endPoint[0]) / 2 + (box5.endPoint[0] + box5.startPoint[0]) * pt[0] / size(),
(box5.startPoint[1] + box5.endPoint[1]) / 2 + (box5.endPoint[1] + box5.startPoint[1]) * pt[1] / size()
]);
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input2.shape[2] || 0), pt[1] / (input2.shape[1] || 0), (pt[2] || 0) / inputSize6]);
for (const key of Object.keys(blazeFaceLandmarks))
@ -76472,24 +76448,24 @@ async function predict10(input2, config3) {
let rawCoords = await coordsReshaped.array();
dispose([contourCoords, coordsReshaped, confidence, contours]);
if (face5.faceScore < (((_h = config3.face.detector) == null ? void 0 : _h.minConfidence) || 1)) {
box4.confidence = face5.faceScore;
box5.confidence = face5.faceScore;
} else {
if ((_i = config3.face.iris) == null ? void 0 : _i.enabled)
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize6);
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize6);
face5.mesh = transformRawCoords(rawCoords, box5, angle, rotationMatrix, inputSize6);
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input2.shape[2] || 0), pt[1] / (input2.shape[1] || 0), (pt[2] || 0) / inputSize6]);
for (const key of Object.keys(meshAnnotations))
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
const boxCalculated = calculateLandmarksBoundingBox(face5.mesh);
const boxEnlarged = enlargeBox(boxCalculated, ((_j = config3.face.detector) == null ? void 0 : _j.cropFactor) || 1.6);
const boxSquared = squarifyBox(boxEnlarged);
box4 = { ...boxSquared, confidence: box4.confidence };
face5.box = getClampedBox(box4, input2);
face5.boxRaw = getRawBox(box4, input2);
box5 = { ...boxSquared, confidence: box5.confidence };
face5.box = getClampedBox(box5, input2);
face5.boxRaw = getRawBox(box5, input2);
face5.score = face5.faceScore;
newCache.push(box4);
newCache.push(box5);
dispose(face5.tensor);
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box4, input2, inputSize6);
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box5, input2, inputSize6);
}
}
faces.push(face5);
@ -76594,54 +76570,54 @@ async function predict11(image7, config3, idx, count3) {
}
// src/hand/handposeutil.ts
function getBoxSize2(box4) {
function getBoxSize2(box5) {
return [
Math.abs(box4.endPoint[0] - box4.startPoint[0]),
Math.abs(box4.endPoint[1] - box4.startPoint[1])
Math.abs(box5.endPoint[0] - box5.startPoint[0]),
Math.abs(box5.endPoint[1] - box5.startPoint[1])
];
}
function getBoxCenter2(box4) {
function getBoxCenter2(box5) {
return [
box4.startPoint[0] + (box4.endPoint[0] - box4.startPoint[0]) / 2,
box4.startPoint[1] + (box4.endPoint[1] - box4.startPoint[1]) / 2
box5.startPoint[0] + (box5.endPoint[0] - box5.startPoint[0]) / 2,
box5.startPoint[1] + (box5.endPoint[1] - box5.startPoint[1]) / 2
];
}
function cutBoxFromImageAndResize2(box4, image7, cropSize) {
function cutBoxFromImageAndResize2(box5, image7, cropSize) {
const h = image7.shape[1];
const w = image7.shape[2];
const boxes = [[
box4.startPoint[1] / h,
box4.startPoint[0] / w,
box4.endPoint[1] / h,
box4.endPoint[0] / w
box5.startPoint[1] / h,
box5.startPoint[0] / w,
box5.endPoint[1] / h,
box5.endPoint[0] / w
]];
return image.cropAndResize(image7, boxes, [0], cropSize);
}
function scaleBoxCoordinates2(box4, factor) {
const startPoint = [box4.startPoint[0] * factor[0], box4.startPoint[1] * factor[1]];
const endPoint = [box4.endPoint[0] * factor[0], box4.endPoint[1] * factor[1]];
const palmLandmarks = box4.palmLandmarks.map((coord) => {
function scaleBoxCoordinates2(box5, factor) {
const startPoint = [box5.startPoint[0] * factor[0], box5.startPoint[1] * factor[1]];
const endPoint = [box5.endPoint[0] * factor[0], box5.endPoint[1] * factor[1]];
const palmLandmarks = box5.palmLandmarks.map((coord) => {
const scaledCoord = [coord[0] * factor[0], coord[1] * factor[1]];
return scaledCoord;
});
return { startPoint, endPoint, palmLandmarks, confidence: box4.confidence };
return { startPoint, endPoint, palmLandmarks, confidence: box5.confidence };
}
function enlargeBox2(box4, factor = 1.5) {
const center = getBoxCenter2(box4);
const size2 = getBoxSize2(box4);
function enlargeBox2(box5, factor = 1.5) {
const center = getBoxCenter2(box5);
const size2 = getBoxSize2(box5);
const newHalfSize = [factor * size2[0] / 2, factor * size2[1] / 2];
const startPoint = [center[0] - newHalfSize[0], center[1] - newHalfSize[1]];
const endPoint = [center[0] + newHalfSize[0], center[1] + newHalfSize[1]];
return { startPoint, endPoint, palmLandmarks: box4.palmLandmarks };
return { startPoint, endPoint, palmLandmarks: box5.palmLandmarks };
}
function squarifyBox2(box4) {
const centers = getBoxCenter2(box4);
const size2 = getBoxSize2(box4);
function squarifyBox2(box5) {
const centers = getBoxCenter2(box5);
const size2 = getBoxSize2(box5);
const maxEdge = Math.max(...size2);
const halfSize = maxEdge / 2;
const startPoint = [centers[0] - halfSize, centers[1] - halfSize];
const endPoint = [centers[0] + halfSize, centers[1] + halfSize];
return { startPoint, endPoint, palmLandmarks: box4.palmLandmarks };
return { startPoint, endPoint, palmLandmarks: box5.palmLandmarks };
}
function normalizeRadians2(angle) {
return angle - 2 * Math.PI * Math.floor((angle + Math.PI) / (2 * Math.PI));
@ -79715,9 +79691,9 @@ var HandDetector = class {
p2.slice = slice(t.predictions, [index2, 5], [1, 14]);
p2.norm = this.normalizeLandmarks(p2.slice, index2);
p2.palmLandmarks = reshape(p2.norm, [-1, 2]);
const box4 = await p2.box.data();
const startPoint = box4.slice(0, 2);
const endPoint = box4.slice(2, 4);
const box5 = await p2.box.data();
const startPoint = box5.slice(0, 2);
const endPoint = box5.slice(2, 4);
const palmLandmarks = await p2.palmLandmarks.array();
const hand3 = { startPoint, endPoint, palmLandmarks, confidence: scores[index2] };
const scaled = scaleBoxCoordinates2(hand3, [input2.shape[2] / this.inputSize, input2.shape[1] / this.inputSize]);
@ -80303,24 +80279,24 @@ async function predict12(input2, config3) {
}
}
const keypoints = predictions[i].landmarks;
let box4 = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0, 0];
let box5 = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0, 0];
let boxRaw = [0, 0, 0, 0];
if (keypoints && keypoints.length > 0) {
for (const pt of keypoints) {
if (pt[0] < box4[0])
box4[0] = pt[0];
if (pt[1] < box4[1])
box4[1] = pt[1];
if (pt[0] > box4[2])
box4[2] = pt[0];
if (pt[1] > box4[3])
box4[3] = pt[1];
if (pt[0] < box5[0])
box5[0] = pt[0];
if (pt[1] < box5[1])
box5[1] = pt[1];
if (pt[0] > box5[2])
box5[2] = pt[0];
if (pt[1] > box5[3])
box5[3] = pt[1];
}
box4[2] -= box4[0];
box4[3] -= box4[1];
boxRaw = [box4[0] / (input2.shape[2] || 0), box4[1] / (input2.shape[1] || 0), box4[2] / (input2.shape[2] || 0), box4[3] / (input2.shape[1] || 0)];
box5[2] -= box5[0];
box5[3] -= box5[1];
boxRaw = [box5[0] / (input2.shape[2] || 0), box5[1] / (input2.shape[1] || 0), box5[2] / (input2.shape[2] || 0), box5[3] / (input2.shape[1] || 0)];
} else {
box4 = predictions[i].box ? [
box5 = predictions[i].box ? [
Math.trunc(Math.max(0, predictions[i].box.topLeft[0])),
Math.trunc(Math.max(0, predictions[i].box.topLeft[1])),
Math.trunc(Math.min(input2.shape[2] || 0, predictions[i].box.bottomRight[0]) - Math.max(0, predictions[i].box.topLeft[0])),
@ -80340,7 +80316,7 @@ async function predict12(input2, config3) {
boxScore: Math.round(100 * predictions[i].boxConfidence) / 100,
fingerScore: Math.round(100 * predictions[i].fingerConfidence) / 100,
label: "hand",
box: box4,
box: box5,
boxRaw,
keypoints,
annotations: annotations2,
@ -80381,40 +80357,6 @@ async function load13(config3) {
return [handDetectorModel, handPoseModel];
}
// src/util/box.ts
function calc(keypoints, outputSize2 = [1, 1]) {
const coords10 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min7 = [Math.min(...coords10[0]), Math.min(...coords10[1])];
const max7 = [Math.max(...coords10[0]), Math.max(...coords10[1])];
const box4 = [min7[0], min7[1], max7[0] - min7[0], max7[1] - min7[1]];
const boxRaw = [box4[0] / outputSize2[0], box4[1] / outputSize2[1], box4[2] / outputSize2[0], box4[3] / outputSize2[1]];
return { box: box4, boxRaw };
}
function square4(keypoints, outputSize2 = [1, 1]) {
const coords10 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min7 = [Math.min(...coords10[0]), Math.min(...coords10[1])];
const max7 = [Math.max(...coords10[0]), Math.max(...coords10[1])];
const center = [(min7[0] + max7[0]) / 2, (min7[1] + max7[1]) / 2];
const dist = Math.max(center[0] - min7[0], center[1] - min7[1], -center[0] + max7[0], -center[1] + max7[1]);
const box4 = [Math.trunc(center[0] - dist), Math.trunc(center[1] - dist), Math.trunc(2 * dist), Math.trunc(2 * dist)];
const boxRaw = [box4[0] / outputSize2[0], box4[1] / outputSize2[1], box4[2] / outputSize2[0], box4[3] / outputSize2[1]];
return { box: box4, boxRaw };
}
function scale2(box4, scaleFact) {
const dist = [box4[2] * scaleFact, box4[3] * scaleFact];
const newBox = [
box4[0] - (dist[0] - box4[2]) / 2,
box4[1] - (dist[1] - box4[3]) / 2,
dist[0],
dist[1]
];
return newBox;
}
function crop(box4) {
const yxBox = [Math.max(0, box4[1]), Math.max(0, box4[0]), Math.min(1, box4[3] + box4[1]), Math.min(1, box4[2] + box4[0])];
return yxBox;
}
// src/hand/handtrack.ts
var models2 = [null, null];
var modelOutputNodes = ["StatefulPartitionedCall/Postprocessor/Slice", "StatefulPartitionedCall/Postprocessor/ExpandDims_1"];
@ -80432,11 +80374,11 @@ var cache3 = {
hands: []
};
var fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
middle: [9, 10, 11, 12],
ring: [13, 14, 15, 16],
pinky: [17, 18, 19, 20],
thumb: [0, 1, 2, 3, 4],
index: [0, 5, 6, 7, 8],
middle: [0, 9, 10, 11, 12],
ring: [0, 13, 14, 15, 16],
pinky: [0, 17, 18, 19, 20],
palm: [0]
};
async function loadDetect2(config3) {
@ -80981,7 +80923,7 @@ async function process4(res, inputSize9, outputShape, config3) {
];
let boxRaw = [x, y, w, h];
boxRaw = boxRaw.map((a) => Math.max(0, Math.min(a, 1)));
const box4 = [
const box5 = [
boxRaw[0] * outputShape[0],
boxRaw[1] * outputShape[1],
boxRaw[2] * outputShape[0],
@ -80992,7 +80934,7 @@ async function process4(res, inputSize9, outputShape, config3) {
score: Math.round(100 * score) / 100,
class: j + 1,
label: labels[j].label,
box: box4.map((a) => Math.trunc(a)),
box: box5.map((a) => Math.trunc(a)),
boxRaw
};
results.push(result);
@ -81332,7 +81274,7 @@ function getInstanceScore(existingPoses, keypoints) {
}, 0);
return notOverlappedKeypointScores / keypoints.length;
}
function decode2(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence2) {
function decode(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence2) {
const poses = [];
const queue = buildPartWithScoreQueue(minConfidence2, scores);
while (poses.length < maxDetected && !queue.empty()) {
@ -81343,9 +81285,9 @@ function decode2(offsets, scores, displacementsFwd, displacementsBwd, maxDetecte
let keypoints = decodePose(root, scores, offsets, displacementsFwd, displacementsBwd);
keypoints = keypoints.filter((a) => a.score > minConfidence2);
const score = getInstanceScore(poses, keypoints);
const box4 = getBoundingBox(keypoints);
const box5 = getBoundingBox(keypoints);
if (score > minConfidence2)
poses.push({ keypoints, box: box4, score: Math.round(100 * score) / 100 });
poses.push({ keypoints, box: box5, score: Math.round(100 * score) / 100 });
}
return poses;
}
@ -81363,7 +81305,7 @@ async function predict17(input2, config3) {
const buffers = await Promise.all(res.map((tensor2) => tensor2.buffer()));
for (const t of res)
dispose(t);
const decoded = await decode2(buffers[0], buffers[1], buffers[2], buffers[3], config3.body.maxDetected, config3.body.minConfidence);
const decoded = await decode(buffers[0], buffers[1], buffers[2], buffers[3], config3.body.maxDetected, config3.body.minConfidence);
if (!model17.inputs[0].shape)
return [];
const scaled = scalePoses(decoded, [input2.shape[1], input2.shape[2]], [model17.inputs[0].shape[2], model17.inputs[0].shape[1]]);
@ -82416,7 +82358,7 @@ var calculateFaceAngle = (face5, imageSize) => {
thetaY = 0;
if (isNaN(thetaZ))
thetaZ = 0;
return { pitch: 2 * -thetaX, yaw: 2 * -thetaY, roll: 2 * -thetaZ };
return { pitch: -thetaX, yaw: -thetaY, roll: -thetaZ };
};
const meshToEulerAngle = (mesh2) => {
const radians = (a12, a22, b1, b2) => Math.atan2(b2 - a22, b1 - a12);
@ -82762,7 +82704,7 @@ function calc2(newResult, config3) {
bufferedResult.body = JSON.parse(JSON.stringify(newResult.body));
} else {
for (let i = 0; i < newResult.body.length; i++) {
const box4 = newResult.body[i].box.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].box[j] + newBoxCoord) / bufferedFactor);
const box5 = newResult.body[i].box.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].box[j] + newBoxCoord) / bufferedFactor);
const boxRaw = newResult.body[i].boxRaw.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].boxRaw[j] + newBoxCoord) / bufferedFactor);
const keypoints = newResult.body[i].keypoints.map((newKpt, j) => ({
score: newKpt.score,
@ -82796,14 +82738,14 @@ function calc2(newResult, config3) {
}
annotations2[name] = pt;
}
bufferedResult.body[i] = { ...newResult.body[i], box: box4, boxRaw, keypoints, annotations: annotations2 };
bufferedResult.body[i] = { ...newResult.body[i], box: box5, boxRaw, keypoints, annotations: annotations2 };
}
}
if (!bufferedResult.hand || newResult.hand.length !== bufferedResult.hand.length) {
bufferedResult.hand = JSON.parse(JSON.stringify(newResult.hand));
} else {
for (let i = 0; i < newResult.hand.length; i++) {
const box4 = newResult.hand[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].box[j] + b) / bufferedFactor);
const box5 = newResult.hand[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.hand[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].boxRaw[j] + b) / bufferedFactor);
if (bufferedResult.hand[i].keypoints.length !== newResult.hand[i].keypoints.length)
bufferedResult.hand[i].keypoints = newResult.hand[i].keypoints;
@ -82817,14 +82759,14 @@ function calc2(newResult, config3) {
annotations2[key] = newResult.hand[i].annotations[key] && newResult.hand[i].annotations[key][0] ? newResult.hand[i].annotations[key].map((val, j) => val.map((coord, k) => ((bufferedFactor - 1) * bufferedResult.hand[i].annotations[key][j][k] + coord) / bufferedFactor)) : null;
}
}
bufferedResult.hand[i] = { ...newResult.hand[i], box: box4, boxRaw, keypoints, annotations: annotations2 };
bufferedResult.hand[i] = { ...newResult.hand[i], box: box5, boxRaw, keypoints, annotations: annotations2 };
}
}
if (!bufferedResult.face || newResult.face.length !== bufferedResult.face.length) {
bufferedResult.face = JSON.parse(JSON.stringify(newResult.face));
} else {
for (let i = 0; i < newResult.face.length; i++) {
const box4 = newResult.face[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].box[j] + b) / bufferedFactor);
const box5 = newResult.face[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.face[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].boxRaw[j] + b) / bufferedFactor);
if (newResult.face[i].rotation) {
const rotation = { matrix: [0, 0, 0, 0, 0, 0, 0, 0, 0], angle: { roll: 0, yaw: 0, pitch: 0 }, gaze: { bearing: 0, strength: 0 } };
@ -82838,18 +82780,18 @@ function calc2(newResult, config3) {
bearing: ((bufferedFactor - 1) * (((_u = (_t = bufferedResult.face[i].rotation) == null ? void 0 : _t.gaze) == null ? void 0 : _u.bearing) || 0) + (((_w = (_v = newResult.face[i].rotation) == null ? void 0 : _v.gaze) == null ? void 0 : _w.bearing) || 0)) / bufferedFactor,
strength: ((bufferedFactor - 1) * (((_y = (_x = bufferedResult.face[i].rotation) == null ? void 0 : _x.gaze) == null ? void 0 : _y.strength) || 0) + (((_A = (_z = newResult.face[i].rotation) == null ? void 0 : _z.gaze) == null ? void 0 : _A.strength) || 0)) / bufferedFactor
};
bufferedResult.face[i] = { ...newResult.face[i], rotation, box: box4, boxRaw };
bufferedResult.face[i] = { ...newResult.face[i], rotation, box: box5, boxRaw };
}
bufferedResult.face[i] = { ...newResult.face[i], box: box4, boxRaw };
bufferedResult.face[i] = { ...newResult.face[i], box: box5, boxRaw };
}
}
if (!bufferedResult.object || newResult.object.length !== bufferedResult.object.length) {
bufferedResult.object = JSON.parse(JSON.stringify(newResult.object));
} else {
for (let i = 0; i < newResult.object.length; i++) {
const box4 = newResult.object[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].box[j] + b) / bufferedFactor);
const box5 = newResult.object[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.object[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].boxRaw[j] + b) / bufferedFactor);
bufferedResult.object[i] = { ...newResult.object[i], box: box4, boxRaw };
bufferedResult.object[i] = { ...newResult.object[i], box: box5, boxRaw };
}
}
if (newResult.persons) {
@ -82858,7 +82800,7 @@ function calc2(newResult, config3) {
bufferedResult.persons = JSON.parse(JSON.stringify(newPersons));
} else {
for (let i = 0; i < newPersons.length; i++) {
bufferedResult.persons[i].box = newPersons[i].box.map((box4, j) => ((bufferedFactor - 1) * bufferedResult.persons[i].box[j] + box4) / bufferedFactor);
bufferedResult.persons[i].box = newPersons[i].box.map((box5, j) => ((bufferedFactor - 1) * bufferedResult.persons[i].box[j] + box5) / bufferedFactor);
}
}
}
@ -82949,10 +82891,10 @@ function join2(faces, bodies, hands, gestures, shape) {
}
const x = [];
const y = [];
const extractXY = (box4) => {
if (box4 && box4.length === 4) {
x.push(box4[0], box4[0] + box4[2]);
y.push(box4[1], box4[1] + box4[3]);
const extractXY = (box5) => {
if (box5 && box5.length === 4) {
x.push(box5[0], box5[0] + box5[2]);
y.push(box5[1], box5[1] + box5[3]);
}
};
extractXY((_k = person2.face) == null ? void 0 : _k.box);

File diff suppressed because one or more lines are too long

914
dist/human.js vendored

File diff suppressed because one or more lines are too long

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

@ -980,8 +980,8 @@ function GLImageFilter() {
// src/image/enhance.ts
var tf = __toModule(require_tfjs_esm());
async function histogramEqualization(inputImage) {
const squeeze11 = inputImage.shape.length === 4 ? tf.squeeze(inputImage) : inputImage;
const channels = tf.split(squeeze11, 3, 2);
const squeeze10 = inputImage.shape.length === 4 ? tf.squeeze(inputImage) : inputImage;
const channels = tf.split(squeeze10, 3, 2);
const min2 = [tf.min(channels[0]), tf.min(channels[1]), tf.min(channels[2])];
const max4 = [tf.max(channels[0]), tf.max(channels[1]), tf.max(channels[2])];
const absMax = await Promise.all(max4.map((channel) => channel.data()));
@ -991,8 +991,8 @@ async function histogramEqualization(inputImage) {
const fact = [tf.div(maxValue, range[0]), tf.div(maxValue, range[1]), tf.div(maxValue, range[2])];
const enh = [tf.mul(sub10[0], fact[0]), tf.mul(sub10[1], fact[1]), tf.mul(sub10[2], fact[2])];
const rgb2 = tf.stack([enh[0], enh[1], enh[2]], 2);
const reshape8 = tf.reshape(rgb2, [1, squeeze11.shape[0], squeeze11.shape[1], 3]);
tf.dispose([...channels, ...min2, ...max4, ...sub10, ...range, ...fact, ...enh, rgb2, squeeze11]);
const reshape8 = tf.reshape(rgb2, [1, squeeze10.shape[0], squeeze10.shape[1], 3]);
tf.dispose([...channels, ...min2, ...max4, ...sub10, ...range, ...fact, ...enh, rgb2, squeeze10]);
return reshape8;
}
@ -1414,8 +1414,8 @@ async function predict(image29, config3, idx, count2) {
if (!(model == null ? void 0 : model.inputs[0].shape))
return;
const t = {};
const box4 = [[0, 0.1, 0.9, 0.9]];
t.resize = tf4.image.cropAndResize(image29, box4, [0], [model.inputs[0].shape[2], model.inputs[0].shape[1]]);
const box5 = [[0, 0.1, 0.9, 0.9]];
t.resize = tf4.image.cropAndResize(image29, box5, [0], [model.inputs[0].shape[2], model.inputs[0].shape[1]]);
const obj = { age: 0, gender: "unknown", genderScore: 0, race: [] };
if ((_a2 = config3.face["gear"]) == null ? void 0 : _a2.enabled)
[t.age, t.gender, t.race] = model.execute(t.resize, ["age_output", "gender_output", "race_output"]);
@ -4911,44 +4911,44 @@ var UV33 = VTX33.map((x) => UV468[x]);
var UV7 = VTX7.map((x) => UV468[x]);
// src/face/facemeshutil.ts
var getBoxSize = (box4) => [Math.abs(box4.endPoint[0] - box4.startPoint[0]), Math.abs(box4.endPoint[1] - box4.startPoint[1])];
var getBoxCenter = (box4) => [box4.startPoint[0] + (box4.endPoint[0] - box4.startPoint[0]) / 2, box4.startPoint[1] + (box4.endPoint[1] - box4.startPoint[1]) / 2];
var getClampedBox = (box4, input) => box4 ? [
Math.trunc(Math.max(0, box4.startPoint[0])),
Math.trunc(Math.max(0, box4.startPoint[1])),
Math.trunc(Math.min(input.shape[2] || 0, box4.endPoint[0]) - Math.max(0, box4.startPoint[0])),
Math.trunc(Math.min(input.shape[1] || 0, box4.endPoint[1]) - Math.max(0, box4.startPoint[1]))
var getBoxSize = (box5) => [Math.abs(box5.endPoint[0] - box5.startPoint[0]), Math.abs(box5.endPoint[1] - box5.startPoint[1])];
var getBoxCenter = (box5) => [box5.startPoint[0] + (box5.endPoint[0] - box5.startPoint[0]) / 2, box5.startPoint[1] + (box5.endPoint[1] - box5.startPoint[1]) / 2];
var getClampedBox = (box5, input) => box5 ? [
Math.trunc(Math.max(0, box5.startPoint[0])),
Math.trunc(Math.max(0, box5.startPoint[1])),
Math.trunc(Math.min(input.shape[2] || 0, box5.endPoint[0]) - Math.max(0, box5.startPoint[0])),
Math.trunc(Math.min(input.shape[1] || 0, box5.endPoint[1]) - Math.max(0, box5.startPoint[1]))
] : [0, 0, 0, 0];
var getRawBox = (box4, input) => box4 ? [
box4.startPoint[0] / (input.shape[2] || 0),
box4.startPoint[1] / (input.shape[1] || 0),
(box4.endPoint[0] - box4.startPoint[0]) / (input.shape[2] || 0),
(box4.endPoint[1] - box4.startPoint[1]) / (input.shape[1] || 0)
var getRawBox = (box5, input) => box5 ? [
box5.startPoint[0] / (input.shape[2] || 0),
box5.startPoint[1] / (input.shape[1] || 0),
(box5.endPoint[0] - box5.startPoint[0]) / (input.shape[2] || 0),
(box5.endPoint[1] - box5.startPoint[1]) / (input.shape[1] || 0)
] : [0, 0, 0, 0];
var scaleBoxCoordinates = (box4, factor) => {
const startPoint = [box4.startPoint[0] * factor[0], box4.startPoint[1] * factor[1]];
const endPoint = [box4.endPoint[0] * factor[0], box4.endPoint[1] * factor[1]];
return { startPoint, endPoint, landmarks: box4.landmarks, confidence: box4.confidence };
var scaleBoxCoordinates = (box5, factor) => {
const startPoint = [box5.startPoint[0] * factor[0], box5.startPoint[1] * factor[1]];
const endPoint = [box5.endPoint[0] * factor[0], box5.endPoint[1] * factor[1]];
return { startPoint, endPoint, landmarks: box5.landmarks, confidence: box5.confidence };
};
var cutBoxFromImageAndResize = (box4, image29, cropSize) => {
var cutBoxFromImageAndResize = (box5, image29, cropSize) => {
const h = image29.shape[1];
const w = image29.shape[2];
const crop2 = tf9.image.cropAndResize(image29, [[box4.startPoint[1] / h, box4.startPoint[0] / w, box4.endPoint[1] / h, box4.endPoint[0] / w]], [0], cropSize);
const crop2 = tf9.image.cropAndResize(image29, [[box5.startPoint[1] / h, box5.startPoint[0] / w, box5.endPoint[1] / h, box5.endPoint[0] / w]], [0], cropSize);
const norm = tf9.div(crop2, constants.tf255);
tf9.dispose(crop2);
return norm;
};
var enlargeBox = (box4, factor) => {
const center = getBoxCenter(box4);
const size2 = getBoxSize(box4);
var enlargeBox = (box5, factor) => {
const center = getBoxCenter(box5);
const size2 = getBoxSize(box5);
const halfSize = [factor * size2[0] / 2, factor * size2[1] / 2];
return { startPoint: [center[0] - halfSize[0], center[1] - halfSize[1]], endPoint: [center[0] + halfSize[0], center[1] + halfSize[1]], landmarks: box4.landmarks, confidence: box4.confidence };
return { startPoint: [center[0] - halfSize[0], center[1] - halfSize[1]], endPoint: [center[0] + halfSize[0], center[1] + halfSize[1]], landmarks: box5.landmarks, confidence: box5.confidence };
};
var squarifyBox = (box4) => {
const centers = getBoxCenter(box4);
const size2 = getBoxSize(box4);
var squarifyBox = (box5) => {
const centers = getBoxCenter(box5);
const size2 = getBoxSize(box5);
const halfSize = Math.max(...size2) / 2;
return { startPoint: [Math.round(centers[0] - halfSize), Math.round(centers[1] - halfSize)], endPoint: [Math.round(centers[0] + halfSize), Math.round(centers[1] + halfSize)], landmarks: box4.landmarks, confidence: box4.confidence };
return { startPoint: [Math.round(centers[0] - halfSize), Math.round(centers[1] - halfSize)], endPoint: [Math.round(centers[0] + halfSize), Math.round(centers[1] + halfSize)], landmarks: box5.landmarks, confidence: box5.confidence };
};
var calculateLandmarksBoundingBox = (landmarks) => {
const xs = landmarks.map((d) => d[0]);
@ -5016,8 +5016,8 @@ function generateAnchors(inputSize9) {
}
return anchors4;
}
function transformRawCoords(coordsRaw, box4, angle, rotationMatrix, inputSize9) {
const boxSize = getBoxSize(box4);
function transformRawCoords(coordsRaw, box5, angle, rotationMatrix, inputSize9) {
const boxSize = getBoxSize(box5);
const coordsScaled = coordsRaw.map((coord) => [
boxSize[0] / inputSize9 * (coord[0] - inputSize9 / 2),
boxSize[1] / inputSize9 * (coord[1] - inputSize9 / 2),
@ -5027,33 +5027,33 @@ function transformRawCoords(coordsRaw, box4, angle, rotationMatrix, inputSize9)
const coordsRotationMatrix = largeAngle ? buildRotationMatrix(angle, [0, 0]) : fixedRotationMatrix;
const coordsRotated = largeAngle ? coordsScaled.map((coord) => [...rotatePoint(coord, coordsRotationMatrix), coord[2]]) : coordsScaled;
const inverseRotationMatrix = largeAngle ? invertTransformMatrix(rotationMatrix) : fixedRotationMatrix;
const boxCenter = [...getBoxCenter({ startPoint: box4.startPoint, endPoint: box4.endPoint }), 1];
const boxCenter = [...getBoxCenter({ startPoint: box5.startPoint, endPoint: box5.endPoint }), 1];
return coordsRotated.map((coord) => [
Math.round(coord[0] + dot(boxCenter, inverseRotationMatrix[0])),
Math.round(coord[1] + dot(boxCenter, inverseRotationMatrix[1])),
Math.round(coord[2] || 0)
]);
}
function correctFaceRotation(rotate, box4, input, inputSize9) {
const symmetryLine = box4.landmarks.length >= meshLandmarks.count ? meshLandmarks.symmetryLine : blazeFaceLandmarks.symmetryLine;
function correctFaceRotation(rotate, box5, input, inputSize9) {
const symmetryLine = box5.landmarks.length >= meshLandmarks.count ? meshLandmarks.symmetryLine : blazeFaceLandmarks.symmetryLine;
let angle = 0;
let rotationMatrix = fixedRotationMatrix;
let face5;
if (rotate && env.kernels.includes("rotatewithoffset")) {
angle = computeRotation(box4.landmarks[symmetryLine[0]], box4.landmarks[symmetryLine[1]]);
angle = computeRotation(box5.landmarks[symmetryLine[0]], box5.landmarks[symmetryLine[1]]);
const largeAngle = angle && angle !== 0 && Math.abs(angle) > 0.2;
if (largeAngle) {
const center = getBoxCenter({ startPoint: box4.startPoint, endPoint: box4.endPoint });
const center = getBoxCenter({ startPoint: box5.startPoint, endPoint: box5.endPoint });
const centerRaw = [center[0] / input.shape[2], center[1] / input.shape[1]];
const rotated = tf9.image.rotateWithOffset(input, angle, 0, centerRaw);
rotationMatrix = buildRotationMatrix(-angle, center);
face5 = cutBoxFromImageAndResize(box4, rotated, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, rotated, [inputSize9, inputSize9]);
tf9.dispose(rotated);
} else {
face5 = cutBoxFromImageAndResize(box4, input, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, input, [inputSize9, inputSize9]);
}
} else {
face5 = cutBoxFromImageAndResize(box4, input, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, input, [inputSize9, inputSize9]);
}
return [angle, rotationMatrix, face5];
}
@ -5238,41 +5238,39 @@ async function createAnchors() {
}
anchorTensor = { x: tf11.tensor1d(anchors4.map((a) => a.x)), y: tf11.tensor1d(anchors4.map((a) => a.y)) };
}
var cropFactor = [5, 5];
function decodeBoxes(boxesTensor, anchor) {
return tf11.tidy(() => {
const split5 = tf11.split(boxesTensor, 12, 1);
let xCenter = tf11.squeeze(split5[0]);
let yCenter = tf11.squeeze(split5[1]);
let width = tf11.squeeze(split5[2]);
let height = tf11.squeeze(split5[3]);
xCenter = tf11.add(tf11.div(xCenter, inputSize2), anchor.x);
yCenter = tf11.add(tf11.div(yCenter, inputSize2), anchor.y);
width = tf11.mul(tf11.div(width, inputSize2), cropFactor[0]);
height = tf11.mul(tf11.div(height, inputSize2), cropFactor[1]);
const xMin = tf11.sub(xCenter, tf11.div(width, 2));
const yMin = tf11.sub(yCenter, tf11.div(height, 2));
const boxes = tf11.stack([xMin, yMin, width, height], 1);
return boxes;
});
// src/util/box.ts
function calc(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const box5 = [min2[0], min2[1], max4[0] - min2[0], max4[1] - min2[1]];
const boxRaw = [box5[0] / outputSize2[0], box5[1] / outputSize2[1], box5[2] / outputSize2[0], box5[3] / outputSize2[1]];
return { box: box5, boxRaw };
}
async function decode(boxesTensor, logitsTensor, config3, outputSize2) {
const t = {};
t.boxes = decodeBoxes(boxesTensor, anchorTensor);
t.scores = tf11.sigmoid(logitsTensor);
t.argmax = tf11.argMax(t.scores);
const i = (await t.argmax.data())[0];
const scores = await t.scores.data();
const detected = [];
const minScore = config3.body["detector"] && config3.body["detector"]["minConfidence"] ? config3.body["detector"]["minConfidence"] : 0;
if (scores[i] >= minScore) {
const boxes = await t.boxes.array();
const boxRaw = boxes[i];
const box4 = [boxRaw[0] * outputSize2[0], boxRaw[1] * outputSize2[1], boxRaw[2] * outputSize2[0], boxRaw[3] * outputSize2[1]];
detected.push({ box: box4, boxRaw, score: scores[i] });
function square(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const center = [(min2[0] + max4[0]) / 2, (min2[1] + max4[1]) / 2];
const dist = Math.max(center[0] - min2[0], center[1] - min2[1], -center[0] + max4[0], -center[1] + max4[1]);
const box5 = [Math.trunc(center[0] - dist), Math.trunc(center[1] - dist), Math.trunc(2 * dist), Math.trunc(2 * dist)];
const boxRaw = [box5[0] / outputSize2[0], box5[1] / outputSize2[1], box5[2] / outputSize2[0], box5[3] / outputSize2[1]];
return { box: box5, boxRaw };
}
Object.keys(t).forEach((tensor3) => tf11.dispose(t[tensor3]));
return detected;
function scale(box5, scaleFact) {
const dist = [box5[2] * scaleFact, box5[3] * scaleFact];
const newBox = [
box5[0] - (dist[0] - box5[2]) / 2,
box5[1] - (dist[1] - box5[3]) / 2,
dist[0],
dist[1]
];
return newBox;
}
function crop(box5) {
const yxBox = [Math.max(0, box5[1]), Math.max(0, box5[0]), Math.min(1, box5[3] + box5[1]), Math.min(1, box5[2] + box5[0])];
return yxBox;
}
// src/body/blazepose.ts
@ -5285,7 +5283,7 @@ var outputNodes = {
detector: []
};
var cache = null;
var lastBox;
var cropBox;
var padding = [[0, 0], [0, 0], [0, 0], [0, 0]];
var lastTime5 = 0;
var sigmoid3 = (x) => 1 - 1 / (1 + Math.exp(x));
@ -5322,39 +5320,37 @@ async function loadPose(config3) {
log("cached model:", models.landmarks["modelUrl"]);
return models.landmarks;
}
function calculateBoxes(keypoints, outputSize2) {
const x = keypoints.map((a) => a.position[0]);
const y = keypoints.map((a) => a.position[1]);
const keypointsBox = [Math.min(...x), Math.min(...y), Math.max(...x) - Math.min(...x), Math.max(...y) - Math.min(...y)];
const keypointsBoxRaw = [keypointsBox[0] / outputSize2[0], keypointsBox[1] / outputSize2[1], keypointsBox[2] / outputSize2[0], keypointsBox[3] / outputSize2[1]];
return { keypointsBox, keypointsBoxRaw };
}
async function prepareImage(input, size2, box4) {
async function prepareImage(input, size2) {
const t = {};
if (!input.shape || !input.shape[1] || !input.shape[2])
return input;
let final;
if (cropBox) {
t.cropped = tf12.image.cropAndResize(input, [cropBox], [0], [input.shape[1], input.shape[2]]);
}
if (input.shape[1] !== input.shape[2]) {
const height = box4 ? [Math.trunc(input.shape[1] * box4[1]), Math.trunc(input.shape[1] * (box4[1] + box4[3]))] : [input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0, input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0];
const width = box4 ? [Math.trunc(input.shape[2] * box4[0]), Math.trunc(input.shape[2] * (box4[0] + box4[2]))] : [input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0, input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0];
const height = [
input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0,
input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0
];
const width = [
input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0,
input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0
];
padding = [
[0, 0],
height,
width,
[0, 0]
];
if (box4) {
t.resize = tf12.image.cropAndResize(input, [box4], [0], [size2, size2]);
} else {
t.pad = tf12.pad(input, padding);
t.pad = tf12.pad(t.cropped || input, padding);
t.resize = tf12.image.resizeBilinear(t.pad, [size2, size2]);
}
final = tf12.div(t.resize, constants.tf255);
} else if (input.shape[1] !== size2) {
t.resize = tf12.image.resizeBilinear(input, [size2, size2]);
t.resize = tf12.image.resizeBilinear(t.cropped || input, [size2, size2]);
final = tf12.div(t.resize, constants.tf255);
} else {
final = tf12.div(input, constants.tf255);
final = tf12.div(t.cropped || input, constants.tf255);
}
Object.keys(t).forEach((tensor3) => tf12.dispose(t[tensor3]));
return final;
@ -5368,19 +5364,21 @@ function rescaleKeypoints(keypoints, outputSize2) {
];
kpt4.positionRaw = [kpt4.position[0] / outputSize2[0], kpt4.position[1] / outputSize2[1], kpt4.position[2]];
}
return keypoints;
}
function rescaleBoxes(boxes, outputSize2) {
for (const box4 of boxes) {
box4.box = [
Math.trunc(box4.box[0] * (outputSize2[0] + padding[2][0] + padding[2][1]) / outputSize2[0]),
Math.trunc(box4.box[1] * (outputSize2[1] + padding[1][0] + padding[1][1]) / outputSize2[1]),
Math.trunc(box4.box[2] * (outputSize2[0] + padding[2][0] + padding[2][1]) / outputSize2[0]),
Math.trunc(box4.box[3] * (outputSize2[1] + padding[1][0] + padding[1][1]) / outputSize2[1])
if (cropBox) {
for (const kpt4 of keypoints) {
kpt4.positionRaw = [
kpt4.positionRaw[0] + cropBox[1],
kpt4.positionRaw[1] + cropBox[0],
kpt4.positionRaw[2]
];
kpt4.position = [
Math.trunc(kpt4.positionRaw[0] * outputSize2[0]),
Math.trunc(kpt4.positionRaw[1] * outputSize2[1]),
kpt4.positionRaw[2]
];
box4.boxRaw = [box4.box[0] / outputSize2[0], box4.box[1] / outputSize2[1], box4.box[2] / outputSize2[0], box4.box[3] / outputSize2[1]];
}
return boxes;
}
return keypoints;
}
async function detectLandmarks(input, config3, outputSize2) {
var _a;
@ -5402,7 +5400,8 @@ async function detectLandmarks(input, config3, outputSize2) {
if (poseScore < (config3.body.minConfidence || 0))
return null;
const keypoints = rescaleKeypoints(keypointsRelative, outputSize2);
const boxes = calculateBoxes(keypoints, [outputSize2[0], outputSize2[1]]);
const kpts = keypoints.map((k) => k.position);
const boxes = calc(kpts, [outputSize2[0], outputSize2[1]]);
const annotations2 = {};
for (const [name, indexes] of Object.entries(connected)) {
const pt = [];
@ -5414,22 +5413,9 @@ async function detectLandmarks(input, config3, outputSize2) {
}
annotations2[name] = pt;
}
const body4 = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.keypointsBox, boxRaw: boxes.keypointsBoxRaw, keypoints, annotations: annotations2 };
const body4 = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.box, boxRaw: boxes.boxRaw, keypoints, annotations: annotations2 };
return body4;
}
async function detectBoxes(input, config3, outputSize2) {
var _a;
const t = {};
t.res = (_a = models.detector) == null ? void 0 : _a.execute(input, ["Identity"]);
t.logitsRaw = tf12.slice(t.res, [0, 0, 0], [1, -1, 1]);
t.boxesRaw = tf12.slice(t.res, [0, 0, 1], [1, -1, -1]);
t.logits = tf12.squeeze(t.logitsRaw);
t.boxes = tf12.squeeze(t.boxesRaw);
const boxes = await decode(t.boxes, t.logits, config3, outputSize2);
rescaleBoxes(boxes, outputSize2);
Object.keys(t).forEach((tensor3) => tf12.dispose(t[tensor3]));
return boxes;
}
async function predict5(input, config3) {
const outputSize2 = [input.shape[2] || 0, input.shape[1] || 0];
const skipTime = (config3.body.skipTime || 0) > now() - lastTime5;
@ -5438,26 +5424,13 @@ async function predict5(input, config3) {
skipped5++;
} else {
const t = {};
if (config3.body["detector"] && config3.body["detector"]["enabled"]) {
t.detector = await prepareImage(input, 224);
const boxes = await detectBoxes(t.detector, config3, outputSize2);
if (boxes && boxes.length === 1) {
t.landmarks = await prepareImage(input, 256, boxes[0].box);
t.landmarks = await prepareImage(input, 256);
cache = await detectLandmarks(t.landmarks, config3, outputSize2);
}
if (cache)
cache.score = boxes[0].score;
} else {
t.landmarks = await prepareImage(input, 256, lastBox);
cache = await detectLandmarks(t.landmarks, config3, outputSize2);
}
Object.keys(t).forEach((tensor3) => tf12.dispose(t[tensor3]));
lastTime5 = now();
skipped5 = 0;
}
if (cache)
return [cache];
return [];
return cache ? [cache] : [];
}
// src/object/centernet.ts
@ -5598,13 +5571,13 @@ async function process3(res, outputShape, config3) {
detections[0][id][2] / inputSize4 - x,
detections[0][id][3] / inputSize4 - y
];
const box4 = [
const box5 = [
Math.trunc(boxRaw[0] * outputShape[0]),
Math.trunc(boxRaw[1] * outputShape[1]),
Math.trunc(boxRaw[2] * outputShape[0]),
Math.trunc(boxRaw[3] * outputShape[1])
];
results.push({ id: i++, score, class: classVal, label, box: box4, boxRaw });
results.push({ id: i++, score, class: classVal, label, box: box5, boxRaw });
}
Object.keys(t).forEach((tensor3) => tf13.dispose(t[tensor3]));
return results;
@ -5725,10 +5698,10 @@ async function predict7(image29, config3) {
tf14.dispose(tensor3);
if (resT) {
cache2.keypoints.length = 0;
const squeeze11 = resT.squeeze();
const squeeze10 = resT.squeeze();
tf14.dispose(resT);
const stack5 = squeeze11.unstack(2);
tf14.dispose(squeeze11);
const stack5 = squeeze10.unstack(2);
tf14.dispose(squeeze10);
for (let id = 0; id < stack5.length; id++) {
const [x2, y2, partScore] = await max2d(stack5[id], config3.body.minConfidence);
if (partScore > (((_a = config3.body) == null ? void 0 : _a.minConfidence) || 0)) {
@ -5946,20 +5919,20 @@ var getLeftToRightEyeDepthDifference = (rawCoords) => {
return leftEyeZ - rightEyeZ;
};
var getEyeBox = (rawCoords, face5, eyeInnerCornerIndex, eyeOuterCornerIndex, meshSize, flip = false) => {
const box4 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), irisEnlarge));
const boxSize = getBoxSize(box4);
const box5 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), irisEnlarge));
const boxSize = getBoxSize(box5);
let crop2 = tf17.image.cropAndResize(face5, [[
box4.startPoint[1] / meshSize,
box4.startPoint[0] / meshSize,
box4.endPoint[1] / meshSize,
box4.endPoint[0] / meshSize
box5.startPoint[1] / meshSize,
box5.startPoint[0] / meshSize,
box5.endPoint[1] / meshSize,
box5.endPoint[0] / meshSize
]], [0], [inputSize5, inputSize5]);
if (flip && env.kernels.includes("flipleftright")) {
const flipped = tf17.image.flipLeftRight(crop2);
tf17.dispose(crop2);
crop2 = flipped;
}
return { box: box4, boxSize, crop: crop2 };
return { box: box5, boxSize, crop: crop2 };
};
var getEyeCoords = (eyeData, eyeBox, eyeBoxSize, flip = false) => {
const eyeRawCoords = [];
@ -6053,7 +6026,7 @@ async function predict10(input, config3) {
const newCache = [];
let id = 0;
for (let i = 0; i < boxCache.length; i++) {
let box4 = boxCache[i];
let box5 = boxCache[i];
let angle = 0;
let rotationMatrix;
const face5 = {
@ -6067,20 +6040,20 @@ async function predict10(input, config3) {
faceScore: 0,
annotations: {}
};
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box4, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize6 : size());
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box5, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize6 : size());
if ((_f = config3 == null ? void 0 : config3.filter) == null ? void 0 : _f.equalization) {
const equilized = await histogramEqualization(face5.tensor);
tf18.dispose(face5.tensor);
face5.tensor = equilized;
}
face5.boxScore = Math.round(100 * box4.confidence) / 100;
face5.boxScore = Math.round(100 * box5.confidence) / 100;
if (!((_g = config3.face.mesh) == null ? void 0 : _g.enabled)) {
face5.box = getClampedBox(box4, input);
face5.boxRaw = getRawBox(box4, input);
face5.box = getClampedBox(box5, input);
face5.boxRaw = getRawBox(box5, input);
face5.score = face5.boxScore;
face5.mesh = box4.landmarks.map((pt) => [
(box4.startPoint[0] + box4.endPoint[0]) / 2 + (box4.endPoint[0] + box4.startPoint[0]) * pt[0] / size(),
(box4.startPoint[1] + box4.endPoint[1]) / 2 + (box4.endPoint[1] + box4.startPoint[1]) * pt[1] / size()
face5.mesh = box5.landmarks.map((pt) => [
(box5.startPoint[0] + box5.endPoint[0]) / 2 + (box5.endPoint[0] + box5.startPoint[0]) * pt[0] / size(),
(box5.startPoint[1] + box5.endPoint[1]) / 2 + (box5.endPoint[1] + box5.startPoint[1]) * pt[1] / size()
]);
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize6]);
for (const key of Object.keys(blazeFaceLandmarks))
@ -6096,24 +6069,24 @@ async function predict10(input, config3) {
let rawCoords = await coordsReshaped.array();
tf18.dispose([contourCoords, coordsReshaped, confidence, contours]);
if (face5.faceScore < (((_h = config3.face.detector) == null ? void 0 : _h.minConfidence) || 1)) {
box4.confidence = face5.faceScore;
box5.confidence = face5.faceScore;
} else {
if ((_i = config3.face.iris) == null ? void 0 : _i.enabled)
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize6);
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize6);
face5.mesh = transformRawCoords(rawCoords, box5, angle, rotationMatrix, inputSize6);
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize6]);
for (const key of Object.keys(meshAnnotations))
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
const boxCalculated = calculateLandmarksBoundingBox(face5.mesh);
const boxEnlarged = enlargeBox(boxCalculated, ((_j = config3.face.detector) == null ? void 0 : _j.cropFactor) || 1.6);
const boxSquared = squarifyBox(boxEnlarged);
box4 = { ...boxSquared, confidence: box4.confidence };
face5.box = getClampedBox(box4, input);
face5.boxRaw = getRawBox(box4, input);
box5 = { ...boxSquared, confidence: box5.confidence };
face5.box = getClampedBox(box5, input);
face5.boxRaw = getRawBox(box5, input);
face5.score = face5.faceScore;
newCache.push(box4);
newCache.push(box5);
tf18.dispose(face5.tensor);
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box4, input, inputSize6);
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box5, input, inputSize6);
}
}
faces.push(face5);
@ -6226,54 +6199,54 @@ var tf21 = __toModule(require_tfjs_esm());
// src/hand/handposeutil.ts
var tf20 = __toModule(require_tfjs_esm());
function getBoxSize2(box4) {
function getBoxSize2(box5) {
return [
Math.abs(box4.endPoint[0] - box4.startPoint[0]),
Math.abs(box4.endPoint[1] - box4.startPoint[1])
Math.abs(box5.endPoint[0] - box5.startPoint[0]),
Math.abs(box5.endPoint[1] - box5.startPoint[1])
];
}
function getBoxCenter2(box4) {
function getBoxCenter2(box5) {
return [
box4.startPoint[0] + (box4.endPoint[0] - box4.startPoint[0]) / 2,
box4.startPoint[1] + (box4.endPoint[1] - box4.startPoint[1]) / 2
box5.startPoint[0] + (box5.endPoint[0] - box5.startPoint[0]) / 2,
box5.startPoint[1] + (box5.endPoint[1] - box5.startPoint[1]) / 2
];
}
function cutBoxFromImageAndResize2(box4, image29, cropSize) {
function cutBoxFromImageAndResize2(box5, image29, cropSize) {
const h = image29.shape[1];
const w = image29.shape[2];
const boxes = [[
box4.startPoint[1] / h,
box4.startPoint[0] / w,
box4.endPoint[1] / h,
box4.endPoint[0] / w
box5.startPoint[1] / h,
box5.startPoint[0] / w,
box5.endPoint[1] / h,
box5.endPoint[0] / w
]];
return tf20.image.cropAndResize(image29, boxes, [0], cropSize);
}
function scaleBoxCoordinates2(box4, factor) {
const startPoint = [box4.startPoint[0] * factor[0], box4.startPoint[1] * factor[1]];
const endPoint = [box4.endPoint[0] * factor[0], box4.endPoint[1] * factor[1]];
const palmLandmarks = box4.palmLandmarks.map((coord) => {
function scaleBoxCoordinates2(box5, factor) {
const startPoint = [box5.startPoint[0] * factor[0], box5.startPoint[1] * factor[1]];
const endPoint = [box5.endPoint[0] * factor[0], box5.endPoint[1] * factor[1]];
const palmLandmarks = box5.palmLandmarks.map((coord) => {
const scaledCoord = [coord[0] * factor[0], coord[1] * factor[1]];
return scaledCoord;
});
return { startPoint, endPoint, palmLandmarks, confidence: box4.confidence };
return { startPoint, endPoint, palmLandmarks, confidence: box5.confidence };
}
function enlargeBox2(box4, factor = 1.5) {
const center = getBoxCenter2(box4);
const size2 = getBoxSize2(box4);
function enlargeBox2(box5, factor = 1.5) {
const center = getBoxCenter2(box5);
const size2 = getBoxSize2(box5);
const newHalfSize = [factor * size2[0] / 2, factor * size2[1] / 2];
const startPoint = [center[0] - newHalfSize[0], center[1] - newHalfSize[1]];
const endPoint = [center[0] + newHalfSize[0], center[1] + newHalfSize[1]];
return { startPoint, endPoint, palmLandmarks: box4.palmLandmarks };
return { startPoint, endPoint, palmLandmarks: box5.palmLandmarks };
}
function squarifyBox2(box4) {
const centers = getBoxCenter2(box4);
const size2 = getBoxSize2(box4);
function squarifyBox2(box5) {
const centers = getBoxCenter2(box5);
const size2 = getBoxSize2(box5);
const maxEdge = Math.max(...size2);
const halfSize = maxEdge / 2;
const startPoint = [centers[0] - halfSize, centers[1] - halfSize];
const endPoint = [centers[0] + halfSize, centers[1] + halfSize];
return { startPoint, endPoint, palmLandmarks: box4.palmLandmarks };
return { startPoint, endPoint, palmLandmarks: box5.palmLandmarks };
}
function normalizeRadians2(angle) {
return angle - 2 * Math.PI * Math.floor((angle + Math.PI) / (2 * Math.PI));
@ -9347,9 +9320,9 @@ var HandDetector = class {
p.slice = tf21.slice(t.predictions, [index2, 5], [1, 14]);
p.norm = this.normalizeLandmarks(p.slice, index2);
p.palmLandmarks = tf21.reshape(p.norm, [-1, 2]);
const box4 = await p.box.data();
const startPoint = box4.slice(0, 2);
const endPoint = box4.slice(2, 4);
const box5 = await p.box.data();
const startPoint = box5.slice(0, 2);
const endPoint = box5.slice(2, 4);
const palmLandmarks = await p.palmLandmarks.array();
const hand3 = { startPoint, endPoint, palmLandmarks, confidence: scores[index2] };
const scaled = scaleBoxCoordinates2(hand3, [input.shape[2] / this.inputSize, input.shape[1] / this.inputSize]);
@ -9936,24 +9909,24 @@ async function predict12(input, config3) {
}
}
const keypoints = predictions[i].landmarks;
let box4 = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0, 0];
let box5 = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0, 0];
let boxRaw = [0, 0, 0, 0];
if (keypoints && keypoints.length > 0) {
for (const pt of keypoints) {
if (pt[0] < box4[0])
box4[0] = pt[0];
if (pt[1] < box4[1])
box4[1] = pt[1];
if (pt[0] > box4[2])
box4[2] = pt[0];
if (pt[1] > box4[3])
box4[3] = pt[1];
if (pt[0] < box5[0])
box5[0] = pt[0];
if (pt[1] < box5[1])
box5[1] = pt[1];
if (pt[0] > box5[2])
box5[2] = pt[0];
if (pt[1] > box5[3])
box5[3] = pt[1];
}
box4[2] -= box4[0];
box4[3] -= box4[1];
boxRaw = [box4[0] / (input.shape[2] || 0), box4[1] / (input.shape[1] || 0), box4[2] / (input.shape[2] || 0), box4[3] / (input.shape[1] || 0)];
box5[2] -= box5[0];
box5[3] -= box5[1];
boxRaw = [box5[0] / (input.shape[2] || 0), box5[1] / (input.shape[1] || 0), box5[2] / (input.shape[2] || 0), box5[3] / (input.shape[1] || 0)];
} else {
box4 = predictions[i].box ? [
box5 = predictions[i].box ? [
Math.trunc(Math.max(0, predictions[i].box.topLeft[0])),
Math.trunc(Math.max(0, predictions[i].box.topLeft[1])),
Math.trunc(Math.min(input.shape[2] || 0, predictions[i].box.bottomRight[0]) - Math.max(0, predictions[i].box.topLeft[0])),
@ -9973,7 +9946,7 @@ async function predict12(input, config3) {
boxScore: Math.round(100 * predictions[i].boxConfidence) / 100,
fingerScore: Math.round(100 * predictions[i].fingerConfidence) / 100,
label: "hand",
box: box4,
box: box5,
boxRaw,
keypoints,
annotations: annotations2,
@ -10014,40 +9987,6 @@ async function load13(config3) {
return [handDetectorModel, handPoseModel];
}
// src/util/box.ts
function calc(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const box4 = [min2[0], min2[1], max4[0] - min2[0], max4[1] - min2[1]];
const boxRaw = [box4[0] / outputSize2[0], box4[1] / outputSize2[1], box4[2] / outputSize2[0], box4[3] / outputSize2[1]];
return { box: box4, boxRaw };
}
function square(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const center = [(min2[0] + max4[0]) / 2, (min2[1] + max4[1]) / 2];
const dist = Math.max(center[0] - min2[0], center[1] - min2[1], -center[0] + max4[0], -center[1] + max4[1]);
const box4 = [Math.trunc(center[0] - dist), Math.trunc(center[1] - dist), Math.trunc(2 * dist), Math.trunc(2 * dist)];
const boxRaw = [box4[0] / outputSize2[0], box4[1] / outputSize2[1], box4[2] / outputSize2[0], box4[3] / outputSize2[1]];
return { box: box4, boxRaw };
}
function scale(box4, scaleFact) {
const dist = [box4[2] * scaleFact, box4[3] * scaleFact];
const newBox = [
box4[0] - (dist[0] - box4[2]) / 2,
box4[1] - (dist[1] - box4[3]) / 2,
dist[0],
dist[1]
];
return newBox;
}
function crop(box4) {
const yxBox = [Math.max(0, box4[1]), Math.max(0, box4[0]), Math.min(1, box4[3] + box4[1]), Math.min(1, box4[2] + box4[0])];
return yxBox;
}
// src/hand/handtrack.ts
var tf24 = __toModule(require_tfjs_esm());
var models2 = [null, null];
@ -10066,11 +10005,11 @@ var cache3 = {
hands: []
};
var fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
middle: [9, 10, 11, 12],
ring: [13, 14, 15, 16],
pinky: [17, 18, 19, 20],
thumb: [0, 1, 2, 3, 4],
index: [0, 5, 6, 7, 8],
middle: [0, 9, 10, 11, 12],
ring: [0, 13, 14, 15, 16],
pinky: [0, 17, 18, 19, 20],
palm: [0]
};
async function loadDetect2(config3) {
@ -10621,7 +10560,7 @@ async function process4(res, inputSize9, outputShape, config3) {
];
let boxRaw = [x, y, w, h];
boxRaw = boxRaw.map((a) => Math.max(0, Math.min(a, 1)));
const box4 = [
const box5 = [
boxRaw[0] * outputShape[0],
boxRaw[1] * outputShape[1],
boxRaw[2] * outputShape[0],
@ -10632,7 +10571,7 @@ async function process4(res, inputSize9, outputShape, config3) {
score: Math.round(100 * score) / 100,
class: j + 1,
label: labels[j].label,
box: box4.map((a) => Math.trunc(a)),
box: box5.map((a) => Math.trunc(a)),
boxRaw
};
results.push(result);
@ -10975,7 +10914,7 @@ function getInstanceScore(existingPoses, keypoints) {
}, 0);
return notOverlappedKeypointScores / keypoints.length;
}
function decode2(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence2) {
function decode(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence2) {
const poses = [];
const queue = buildPartWithScoreQueue(minConfidence2, scores);
while (poses.length < maxDetected && !queue.empty()) {
@ -10986,9 +10925,9 @@ function decode2(offsets, scores, displacementsFwd, displacementsBwd, maxDetecte
let keypoints = decodePose(root, scores, offsets, displacementsFwd, displacementsBwd);
keypoints = keypoints.filter((a) => a.score > minConfidence2);
const score = getInstanceScore(poses, keypoints);
const box4 = getBoundingBox(keypoints);
const box5 = getBoundingBox(keypoints);
if (score > minConfidence2)
poses.push({ keypoints, box: box4, score: Math.round(100 * score) / 100 });
poses.push({ keypoints, box: box5, score: Math.round(100 * score) / 100 });
}
return poses;
}
@ -11006,7 +10945,7 @@ async function predict17(input, config3) {
const buffers = await Promise.all(res.map((tensor3) => tensor3.buffer()));
for (const t of res)
tf29.dispose(t);
const decoded = await decode2(buffers[0], buffers[1], buffers[2], buffers[3], config3.body.maxDetected, config3.body.minConfidence);
const decoded = await decode(buffers[0], buffers[1], buffers[2], buffers[3], config3.body.maxDetected, config3.body.minConfidence);
if (!model16.inputs[0].shape)
return [];
const scaled = scalePoses(decoded, [input.shape[1], input.shape[2]], [model16.inputs[0].shape[2], model16.inputs[0].shape[1]]);
@ -12065,7 +12004,7 @@ var calculateFaceAngle = (face5, imageSize) => {
thetaY = 0;
if (isNaN(thetaZ))
thetaZ = 0;
return { pitch: 2 * -thetaX, yaw: 2 * -thetaY, roll: 2 * -thetaZ };
return { pitch: -thetaX, yaw: -thetaY, roll: -thetaZ };
};
const meshToEulerAngle = (mesh2) => {
const radians = (a1, a2, b1, b2) => Math.atan2(b2 - a2, b1 - a1);
@ -12411,7 +12350,7 @@ function calc2(newResult, config3) {
bufferedResult.body = JSON.parse(JSON.stringify(newResult.body));
} else {
for (let i = 0; i < newResult.body.length; i++) {
const box4 = newResult.body[i].box.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].box[j] + newBoxCoord) / bufferedFactor);
const box5 = newResult.body[i].box.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].box[j] + newBoxCoord) / bufferedFactor);
const boxRaw = newResult.body[i].boxRaw.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].boxRaw[j] + newBoxCoord) / bufferedFactor);
const keypoints = newResult.body[i].keypoints.map((newKpt, j) => ({
score: newKpt.score,
@ -12445,14 +12384,14 @@ function calc2(newResult, config3) {
}
annotations2[name] = pt;
}
bufferedResult.body[i] = { ...newResult.body[i], box: box4, boxRaw, keypoints, annotations: annotations2 };
bufferedResult.body[i] = { ...newResult.body[i], box: box5, boxRaw, keypoints, annotations: annotations2 };
}
}
if (!bufferedResult.hand || newResult.hand.length !== bufferedResult.hand.length) {
bufferedResult.hand = JSON.parse(JSON.stringify(newResult.hand));
} else {
for (let i = 0; i < newResult.hand.length; i++) {
const box4 = newResult.hand[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].box[j] + b) / bufferedFactor);
const box5 = newResult.hand[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.hand[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].boxRaw[j] + b) / bufferedFactor);
if (bufferedResult.hand[i].keypoints.length !== newResult.hand[i].keypoints.length)
bufferedResult.hand[i].keypoints = newResult.hand[i].keypoints;
@ -12466,14 +12405,14 @@ function calc2(newResult, config3) {
annotations2[key] = newResult.hand[i].annotations[key] && newResult.hand[i].annotations[key][0] ? newResult.hand[i].annotations[key].map((val, j) => val.map((coord, k) => ((bufferedFactor - 1) * bufferedResult.hand[i].annotations[key][j][k] + coord) / bufferedFactor)) : null;
}
}
bufferedResult.hand[i] = { ...newResult.hand[i], box: box4, boxRaw, keypoints, annotations: annotations2 };
bufferedResult.hand[i] = { ...newResult.hand[i], box: box5, boxRaw, keypoints, annotations: annotations2 };
}
}
if (!bufferedResult.face || newResult.face.length !== bufferedResult.face.length) {
bufferedResult.face = JSON.parse(JSON.stringify(newResult.face));
} else {
for (let i = 0; i < newResult.face.length; i++) {
const box4 = newResult.face[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].box[j] + b) / bufferedFactor);
const box5 = newResult.face[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.face[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].boxRaw[j] + b) / bufferedFactor);
if (newResult.face[i].rotation) {
const rotation = { matrix: [0, 0, 0, 0, 0, 0, 0, 0, 0], angle: { roll: 0, yaw: 0, pitch: 0 }, gaze: { bearing: 0, strength: 0 } };
@ -12487,18 +12426,18 @@ function calc2(newResult, config3) {
bearing: ((bufferedFactor - 1) * (((_u = (_t = bufferedResult.face[i].rotation) == null ? void 0 : _t.gaze) == null ? void 0 : _u.bearing) || 0) + (((_w = (_v = newResult.face[i].rotation) == null ? void 0 : _v.gaze) == null ? void 0 : _w.bearing) || 0)) / bufferedFactor,
strength: ((bufferedFactor - 1) * (((_y = (_x = bufferedResult.face[i].rotation) == null ? void 0 : _x.gaze) == null ? void 0 : _y.strength) || 0) + (((_A = (_z = newResult.face[i].rotation) == null ? void 0 : _z.gaze) == null ? void 0 : _A.strength) || 0)) / bufferedFactor
};
bufferedResult.face[i] = { ...newResult.face[i], rotation, box: box4, boxRaw };
bufferedResult.face[i] = { ...newResult.face[i], rotation, box: box5, boxRaw };
}
bufferedResult.face[i] = { ...newResult.face[i], box: box4, boxRaw };
bufferedResult.face[i] = { ...newResult.face[i], box: box5, boxRaw };
}
}
if (!bufferedResult.object || newResult.object.length !== bufferedResult.object.length) {
bufferedResult.object = JSON.parse(JSON.stringify(newResult.object));
} else {
for (let i = 0; i < newResult.object.length; i++) {
const box4 = newResult.object[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].box[j] + b) / bufferedFactor);
const box5 = newResult.object[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.object[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].boxRaw[j] + b) / bufferedFactor);
bufferedResult.object[i] = { ...newResult.object[i], box: box4, boxRaw };
bufferedResult.object[i] = { ...newResult.object[i], box: box5, boxRaw };
}
}
if (newResult.persons) {
@ -12507,7 +12446,7 @@ function calc2(newResult, config3) {
bufferedResult.persons = JSON.parse(JSON.stringify(newPersons));
} else {
for (let i = 0; i < newPersons.length; i++) {
bufferedResult.persons[i].box = newPersons[i].box.map((box4, j) => ((bufferedFactor - 1) * bufferedResult.persons[i].box[j] + box4) / bufferedFactor);
bufferedResult.persons[i].box = newPersons[i].box.map((box5, j) => ((bufferedFactor - 1) * bufferedResult.persons[i].box[j] + box5) / bufferedFactor);
}
}
}
@ -12598,10 +12537,10 @@ function join2(faces, bodies, hands, gestures, shape) {
}
const x = [];
const y = [];
const extractXY = (box4) => {
if (box4 && box4.length === 4) {
x.push(box4[0], box4[0] + box4[2]);
y.push(box4[1], box4[1] + box4[3]);
const extractXY = (box5) => {
if (box5 && box5.length === 4) {
x.push(box5[0], box5[0] + box5[2]);
y.push(box5[1], box5[1] + box5[3]);
}
};
extractXY((_k = person2.face) == null ? void 0 : _k.box);

View File

@ -981,8 +981,8 @@ function GLImageFilter() {
// src/image/enhance.ts
var tf = __toModule(require_tfjs_esm());
async function histogramEqualization(inputImage) {
const squeeze11 = inputImage.shape.length === 4 ? tf.squeeze(inputImage) : inputImage;
const channels = tf.split(squeeze11, 3, 2);
const squeeze10 = inputImage.shape.length === 4 ? tf.squeeze(inputImage) : inputImage;
const channels = tf.split(squeeze10, 3, 2);
const min2 = [tf.min(channels[0]), tf.min(channels[1]), tf.min(channels[2])];
const max4 = [tf.max(channels[0]), tf.max(channels[1]), tf.max(channels[2])];
const absMax = await Promise.all(max4.map((channel) => channel.data()));
@ -992,8 +992,8 @@ async function histogramEqualization(inputImage) {
const fact = [tf.div(maxValue, range[0]), tf.div(maxValue, range[1]), tf.div(maxValue, range[2])];
const enh = [tf.mul(sub10[0], fact[0]), tf.mul(sub10[1], fact[1]), tf.mul(sub10[2], fact[2])];
const rgb2 = tf.stack([enh[0], enh[1], enh[2]], 2);
const reshape8 = tf.reshape(rgb2, [1, squeeze11.shape[0], squeeze11.shape[1], 3]);
tf.dispose([...channels, ...min2, ...max4, ...sub10, ...range, ...fact, ...enh, rgb2, squeeze11]);
const reshape8 = tf.reshape(rgb2, [1, squeeze10.shape[0], squeeze10.shape[1], 3]);
tf.dispose([...channels, ...min2, ...max4, ...sub10, ...range, ...fact, ...enh, rgb2, squeeze10]);
return reshape8;
}
@ -1415,8 +1415,8 @@ async function predict(image29, config3, idx, count2) {
if (!(model == null ? void 0 : model.inputs[0].shape))
return;
const t = {};
const box4 = [[0, 0.1, 0.9, 0.9]];
t.resize = tf4.image.cropAndResize(image29, box4, [0], [model.inputs[0].shape[2], model.inputs[0].shape[1]]);
const box5 = [[0, 0.1, 0.9, 0.9]];
t.resize = tf4.image.cropAndResize(image29, box5, [0], [model.inputs[0].shape[2], model.inputs[0].shape[1]]);
const obj = { age: 0, gender: "unknown", genderScore: 0, race: [] };
if ((_a2 = config3.face["gear"]) == null ? void 0 : _a2.enabled)
[t.age, t.gender, t.race] = model.execute(t.resize, ["age_output", "gender_output", "race_output"]);
@ -4912,44 +4912,44 @@ var UV33 = VTX33.map((x) => UV468[x]);
var UV7 = VTX7.map((x) => UV468[x]);
// src/face/facemeshutil.ts
var getBoxSize = (box4) => [Math.abs(box4.endPoint[0] - box4.startPoint[0]), Math.abs(box4.endPoint[1] - box4.startPoint[1])];
var getBoxCenter = (box4) => [box4.startPoint[0] + (box4.endPoint[0] - box4.startPoint[0]) / 2, box4.startPoint[1] + (box4.endPoint[1] - box4.startPoint[1]) / 2];
var getClampedBox = (box4, input) => box4 ? [
Math.trunc(Math.max(0, box4.startPoint[0])),
Math.trunc(Math.max(0, box4.startPoint[1])),
Math.trunc(Math.min(input.shape[2] || 0, box4.endPoint[0]) - Math.max(0, box4.startPoint[0])),
Math.trunc(Math.min(input.shape[1] || 0, box4.endPoint[1]) - Math.max(0, box4.startPoint[1]))
var getBoxSize = (box5) => [Math.abs(box5.endPoint[0] - box5.startPoint[0]), Math.abs(box5.endPoint[1] - box5.startPoint[1])];
var getBoxCenter = (box5) => [box5.startPoint[0] + (box5.endPoint[0] - box5.startPoint[0]) / 2, box5.startPoint[1] + (box5.endPoint[1] - box5.startPoint[1]) / 2];
var getClampedBox = (box5, input) => box5 ? [
Math.trunc(Math.max(0, box5.startPoint[0])),
Math.trunc(Math.max(0, box5.startPoint[1])),
Math.trunc(Math.min(input.shape[2] || 0, box5.endPoint[0]) - Math.max(0, box5.startPoint[0])),
Math.trunc(Math.min(input.shape[1] || 0, box5.endPoint[1]) - Math.max(0, box5.startPoint[1]))
] : [0, 0, 0, 0];
var getRawBox = (box4, input) => box4 ? [
box4.startPoint[0] / (input.shape[2] || 0),
box4.startPoint[1] / (input.shape[1] || 0),
(box4.endPoint[0] - box4.startPoint[0]) / (input.shape[2] || 0),
(box4.endPoint[1] - box4.startPoint[1]) / (input.shape[1] || 0)
var getRawBox = (box5, input) => box5 ? [
box5.startPoint[0] / (input.shape[2] || 0),
box5.startPoint[1] / (input.shape[1] || 0),
(box5.endPoint[0] - box5.startPoint[0]) / (input.shape[2] || 0),
(box5.endPoint[1] - box5.startPoint[1]) / (input.shape[1] || 0)
] : [0, 0, 0, 0];
var scaleBoxCoordinates = (box4, factor) => {
const startPoint = [box4.startPoint[0] * factor[0], box4.startPoint[1] * factor[1]];
const endPoint = [box4.endPoint[0] * factor[0], box4.endPoint[1] * factor[1]];
return { startPoint, endPoint, landmarks: box4.landmarks, confidence: box4.confidence };
var scaleBoxCoordinates = (box5, factor) => {
const startPoint = [box5.startPoint[0] * factor[0], box5.startPoint[1] * factor[1]];
const endPoint = [box5.endPoint[0] * factor[0], box5.endPoint[1] * factor[1]];
return { startPoint, endPoint, landmarks: box5.landmarks, confidence: box5.confidence };
};
var cutBoxFromImageAndResize = (box4, image29, cropSize) => {
var cutBoxFromImageAndResize = (box5, image29, cropSize) => {
const h = image29.shape[1];
const w = image29.shape[2];
const crop2 = tf9.image.cropAndResize(image29, [[box4.startPoint[1] / h, box4.startPoint[0] / w, box4.endPoint[1] / h, box4.endPoint[0] / w]], [0], cropSize);
const crop2 = tf9.image.cropAndResize(image29, [[box5.startPoint[1] / h, box5.startPoint[0] / w, box5.endPoint[1] / h, box5.endPoint[0] / w]], [0], cropSize);
const norm = tf9.div(crop2, constants.tf255);
tf9.dispose(crop2);
return norm;
};
var enlargeBox = (box4, factor) => {
const center = getBoxCenter(box4);
const size2 = getBoxSize(box4);
var enlargeBox = (box5, factor) => {
const center = getBoxCenter(box5);
const size2 = getBoxSize(box5);
const halfSize = [factor * size2[0] / 2, factor * size2[1] / 2];
return { startPoint: [center[0] - halfSize[0], center[1] - halfSize[1]], endPoint: [center[0] + halfSize[0], center[1] + halfSize[1]], landmarks: box4.landmarks, confidence: box4.confidence };
return { startPoint: [center[0] - halfSize[0], center[1] - halfSize[1]], endPoint: [center[0] + halfSize[0], center[1] + halfSize[1]], landmarks: box5.landmarks, confidence: box5.confidence };
};
var squarifyBox = (box4) => {
const centers = getBoxCenter(box4);
const size2 = getBoxSize(box4);
var squarifyBox = (box5) => {
const centers = getBoxCenter(box5);
const size2 = getBoxSize(box5);
const halfSize = Math.max(...size2) / 2;
return { startPoint: [Math.round(centers[0] - halfSize), Math.round(centers[1] - halfSize)], endPoint: [Math.round(centers[0] + halfSize), Math.round(centers[1] + halfSize)], landmarks: box4.landmarks, confidence: box4.confidence };
return { startPoint: [Math.round(centers[0] - halfSize), Math.round(centers[1] - halfSize)], endPoint: [Math.round(centers[0] + halfSize), Math.round(centers[1] + halfSize)], landmarks: box5.landmarks, confidence: box5.confidence };
};
var calculateLandmarksBoundingBox = (landmarks) => {
const xs = landmarks.map((d) => d[0]);
@ -5017,8 +5017,8 @@ function generateAnchors(inputSize9) {
}
return anchors4;
}
function transformRawCoords(coordsRaw, box4, angle, rotationMatrix, inputSize9) {
const boxSize = getBoxSize(box4);
function transformRawCoords(coordsRaw, box5, angle, rotationMatrix, inputSize9) {
const boxSize = getBoxSize(box5);
const coordsScaled = coordsRaw.map((coord) => [
boxSize[0] / inputSize9 * (coord[0] - inputSize9 / 2),
boxSize[1] / inputSize9 * (coord[1] - inputSize9 / 2),
@ -5028,33 +5028,33 @@ function transformRawCoords(coordsRaw, box4, angle, rotationMatrix, inputSize9)
const coordsRotationMatrix = largeAngle ? buildRotationMatrix(angle, [0, 0]) : fixedRotationMatrix;
const coordsRotated = largeAngle ? coordsScaled.map((coord) => [...rotatePoint(coord, coordsRotationMatrix), coord[2]]) : coordsScaled;
const inverseRotationMatrix = largeAngle ? invertTransformMatrix(rotationMatrix) : fixedRotationMatrix;
const boxCenter = [...getBoxCenter({ startPoint: box4.startPoint, endPoint: box4.endPoint }), 1];
const boxCenter = [...getBoxCenter({ startPoint: box5.startPoint, endPoint: box5.endPoint }), 1];
return coordsRotated.map((coord) => [
Math.round(coord[0] + dot(boxCenter, inverseRotationMatrix[0])),
Math.round(coord[1] + dot(boxCenter, inverseRotationMatrix[1])),
Math.round(coord[2] || 0)
]);
}
function correctFaceRotation(rotate, box4, input, inputSize9) {
const symmetryLine = box4.landmarks.length >= meshLandmarks.count ? meshLandmarks.symmetryLine : blazeFaceLandmarks.symmetryLine;
function correctFaceRotation(rotate, box5, input, inputSize9) {
const symmetryLine = box5.landmarks.length >= meshLandmarks.count ? meshLandmarks.symmetryLine : blazeFaceLandmarks.symmetryLine;
let angle = 0;
let rotationMatrix = fixedRotationMatrix;
let face5;
if (rotate && env.kernels.includes("rotatewithoffset")) {
angle = computeRotation(box4.landmarks[symmetryLine[0]], box4.landmarks[symmetryLine[1]]);
angle = computeRotation(box5.landmarks[symmetryLine[0]], box5.landmarks[symmetryLine[1]]);
const largeAngle = angle && angle !== 0 && Math.abs(angle) > 0.2;
if (largeAngle) {
const center = getBoxCenter({ startPoint: box4.startPoint, endPoint: box4.endPoint });
const center = getBoxCenter({ startPoint: box5.startPoint, endPoint: box5.endPoint });
const centerRaw = [center[0] / input.shape[2], center[1] / input.shape[1]];
const rotated = tf9.image.rotateWithOffset(input, angle, 0, centerRaw);
rotationMatrix = buildRotationMatrix(-angle, center);
face5 = cutBoxFromImageAndResize(box4, rotated, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, rotated, [inputSize9, inputSize9]);
tf9.dispose(rotated);
} else {
face5 = cutBoxFromImageAndResize(box4, input, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, input, [inputSize9, inputSize9]);
}
} else {
face5 = cutBoxFromImageAndResize(box4, input, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, input, [inputSize9, inputSize9]);
}
return [angle, rotationMatrix, face5];
}
@ -5239,41 +5239,39 @@ async function createAnchors() {
}
anchorTensor = { x: tf11.tensor1d(anchors4.map((a) => a.x)), y: tf11.tensor1d(anchors4.map((a) => a.y)) };
}
var cropFactor = [5, 5];
function decodeBoxes(boxesTensor, anchor) {
return tf11.tidy(() => {
const split5 = tf11.split(boxesTensor, 12, 1);
let xCenter = tf11.squeeze(split5[0]);
let yCenter = tf11.squeeze(split5[1]);
let width = tf11.squeeze(split5[2]);
let height = tf11.squeeze(split5[3]);
xCenter = tf11.add(tf11.div(xCenter, inputSize2), anchor.x);
yCenter = tf11.add(tf11.div(yCenter, inputSize2), anchor.y);
width = tf11.mul(tf11.div(width, inputSize2), cropFactor[0]);
height = tf11.mul(tf11.div(height, inputSize2), cropFactor[1]);
const xMin = tf11.sub(xCenter, tf11.div(width, 2));
const yMin = tf11.sub(yCenter, tf11.div(height, 2));
const boxes = tf11.stack([xMin, yMin, width, height], 1);
return boxes;
});
// src/util/box.ts
function calc(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const box5 = [min2[0], min2[1], max4[0] - min2[0], max4[1] - min2[1]];
const boxRaw = [box5[0] / outputSize2[0], box5[1] / outputSize2[1], box5[2] / outputSize2[0], box5[3] / outputSize2[1]];
return { box: box5, boxRaw };
}
async function decode(boxesTensor, logitsTensor, config3, outputSize2) {
const t = {};
t.boxes = decodeBoxes(boxesTensor, anchorTensor);
t.scores = tf11.sigmoid(logitsTensor);
t.argmax = tf11.argMax(t.scores);
const i = (await t.argmax.data())[0];
const scores = await t.scores.data();
const detected = [];
const minScore = config3.body["detector"] && config3.body["detector"]["minConfidence"] ? config3.body["detector"]["minConfidence"] : 0;
if (scores[i] >= minScore) {
const boxes = await t.boxes.array();
const boxRaw = boxes[i];
const box4 = [boxRaw[0] * outputSize2[0], boxRaw[1] * outputSize2[1], boxRaw[2] * outputSize2[0], boxRaw[3] * outputSize2[1]];
detected.push({ box: box4, boxRaw, score: scores[i] });
function square(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const center = [(min2[0] + max4[0]) / 2, (min2[1] + max4[1]) / 2];
const dist = Math.max(center[0] - min2[0], center[1] - min2[1], -center[0] + max4[0], -center[1] + max4[1]);
const box5 = [Math.trunc(center[0] - dist), Math.trunc(center[1] - dist), Math.trunc(2 * dist), Math.trunc(2 * dist)];
const boxRaw = [box5[0] / outputSize2[0], box5[1] / outputSize2[1], box5[2] / outputSize2[0], box5[3] / outputSize2[1]];
return { box: box5, boxRaw };
}
Object.keys(t).forEach((tensor3) => tf11.dispose(t[tensor3]));
return detected;
function scale(box5, scaleFact) {
const dist = [box5[2] * scaleFact, box5[3] * scaleFact];
const newBox = [
box5[0] - (dist[0] - box5[2]) / 2,
box5[1] - (dist[1] - box5[3]) / 2,
dist[0],
dist[1]
];
return newBox;
}
function crop(box5) {
const yxBox = [Math.max(0, box5[1]), Math.max(0, box5[0]), Math.min(1, box5[3] + box5[1]), Math.min(1, box5[2] + box5[0])];
return yxBox;
}
// src/body/blazepose.ts
@ -5286,7 +5284,7 @@ var outputNodes = {
detector: []
};
var cache = null;
var lastBox;
var cropBox;
var padding = [[0, 0], [0, 0], [0, 0], [0, 0]];
var lastTime5 = 0;
var sigmoid3 = (x) => 1 - 1 / (1 + Math.exp(x));
@ -5323,39 +5321,37 @@ async function loadPose(config3) {
log("cached model:", models.landmarks["modelUrl"]);
return models.landmarks;
}
function calculateBoxes(keypoints, outputSize2) {
const x = keypoints.map((a) => a.position[0]);
const y = keypoints.map((a) => a.position[1]);
const keypointsBox = [Math.min(...x), Math.min(...y), Math.max(...x) - Math.min(...x), Math.max(...y) - Math.min(...y)];
const keypointsBoxRaw = [keypointsBox[0] / outputSize2[0], keypointsBox[1] / outputSize2[1], keypointsBox[2] / outputSize2[0], keypointsBox[3] / outputSize2[1]];
return { keypointsBox, keypointsBoxRaw };
}
async function prepareImage(input, size2, box4) {
async function prepareImage(input, size2) {
const t = {};
if (!input.shape || !input.shape[1] || !input.shape[2])
return input;
let final;
if (cropBox) {
t.cropped = tf12.image.cropAndResize(input, [cropBox], [0], [input.shape[1], input.shape[2]]);
}
if (input.shape[1] !== input.shape[2]) {
const height = box4 ? [Math.trunc(input.shape[1] * box4[1]), Math.trunc(input.shape[1] * (box4[1] + box4[3]))] : [input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0, input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0];
const width = box4 ? [Math.trunc(input.shape[2] * box4[0]), Math.trunc(input.shape[2] * (box4[0] + box4[2]))] : [input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0, input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0];
const height = [
input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0,
input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0
];
const width = [
input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0,
input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0
];
padding = [
[0, 0],
height,
width,
[0, 0]
];
if (box4) {
t.resize = tf12.image.cropAndResize(input, [box4], [0], [size2, size2]);
} else {
t.pad = tf12.pad(input, padding);
t.pad = tf12.pad(t.cropped || input, padding);
t.resize = tf12.image.resizeBilinear(t.pad, [size2, size2]);
}
final = tf12.div(t.resize, constants.tf255);
} else if (input.shape[1] !== size2) {
t.resize = tf12.image.resizeBilinear(input, [size2, size2]);
t.resize = tf12.image.resizeBilinear(t.cropped || input, [size2, size2]);
final = tf12.div(t.resize, constants.tf255);
} else {
final = tf12.div(input, constants.tf255);
final = tf12.div(t.cropped || input, constants.tf255);
}
Object.keys(t).forEach((tensor3) => tf12.dispose(t[tensor3]));
return final;
@ -5369,19 +5365,21 @@ function rescaleKeypoints(keypoints, outputSize2) {
];
kpt4.positionRaw = [kpt4.position[0] / outputSize2[0], kpt4.position[1] / outputSize2[1], kpt4.position[2]];
}
return keypoints;
}
function rescaleBoxes(boxes, outputSize2) {
for (const box4 of boxes) {
box4.box = [
Math.trunc(box4.box[0] * (outputSize2[0] + padding[2][0] + padding[2][1]) / outputSize2[0]),
Math.trunc(box4.box[1] * (outputSize2[1] + padding[1][0] + padding[1][1]) / outputSize2[1]),
Math.trunc(box4.box[2] * (outputSize2[0] + padding[2][0] + padding[2][1]) / outputSize2[0]),
Math.trunc(box4.box[3] * (outputSize2[1] + padding[1][0] + padding[1][1]) / outputSize2[1])
if (cropBox) {
for (const kpt4 of keypoints) {
kpt4.positionRaw = [
kpt4.positionRaw[0] + cropBox[1],
kpt4.positionRaw[1] + cropBox[0],
kpt4.positionRaw[2]
];
kpt4.position = [
Math.trunc(kpt4.positionRaw[0] * outputSize2[0]),
Math.trunc(kpt4.positionRaw[1] * outputSize2[1]),
kpt4.positionRaw[2]
];
box4.boxRaw = [box4.box[0] / outputSize2[0], box4.box[1] / outputSize2[1], box4.box[2] / outputSize2[0], box4.box[3] / outputSize2[1]];
}
return boxes;
}
return keypoints;
}
async function detectLandmarks(input, config3, outputSize2) {
var _a;
@ -5403,7 +5401,8 @@ async function detectLandmarks(input, config3, outputSize2) {
if (poseScore < (config3.body.minConfidence || 0))
return null;
const keypoints = rescaleKeypoints(keypointsRelative, outputSize2);
const boxes = calculateBoxes(keypoints, [outputSize2[0], outputSize2[1]]);
const kpts = keypoints.map((k) => k.position);
const boxes = calc(kpts, [outputSize2[0], outputSize2[1]]);
const annotations2 = {};
for (const [name, indexes] of Object.entries(connected)) {
const pt = [];
@ -5415,22 +5414,9 @@ async function detectLandmarks(input, config3, outputSize2) {
}
annotations2[name] = pt;
}
const body4 = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.keypointsBox, boxRaw: boxes.keypointsBoxRaw, keypoints, annotations: annotations2 };
const body4 = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.box, boxRaw: boxes.boxRaw, keypoints, annotations: annotations2 };
return body4;
}
async function detectBoxes(input, config3, outputSize2) {
var _a;
const t = {};
t.res = (_a = models.detector) == null ? void 0 : _a.execute(input, ["Identity"]);
t.logitsRaw = tf12.slice(t.res, [0, 0, 0], [1, -1, 1]);
t.boxesRaw = tf12.slice(t.res, [0, 0, 1], [1, -1, -1]);
t.logits = tf12.squeeze(t.logitsRaw);
t.boxes = tf12.squeeze(t.boxesRaw);
const boxes = await decode(t.boxes, t.logits, config3, outputSize2);
rescaleBoxes(boxes, outputSize2);
Object.keys(t).forEach((tensor3) => tf12.dispose(t[tensor3]));
return boxes;
}
async function predict5(input, config3) {
const outputSize2 = [input.shape[2] || 0, input.shape[1] || 0];
const skipTime = (config3.body.skipTime || 0) > now() - lastTime5;
@ -5439,26 +5425,13 @@ async function predict5(input, config3) {
skipped5++;
} else {
const t = {};
if (config3.body["detector"] && config3.body["detector"]["enabled"]) {
t.detector = await prepareImage(input, 224);
const boxes = await detectBoxes(t.detector, config3, outputSize2);
if (boxes && boxes.length === 1) {
t.landmarks = await prepareImage(input, 256, boxes[0].box);
t.landmarks = await prepareImage(input, 256);
cache = await detectLandmarks(t.landmarks, config3, outputSize2);
}
if (cache)
cache.score = boxes[0].score;
} else {
t.landmarks = await prepareImage(input, 256, lastBox);
cache = await detectLandmarks(t.landmarks, config3, outputSize2);
}
Object.keys(t).forEach((tensor3) => tf12.dispose(t[tensor3]));
lastTime5 = now();
skipped5 = 0;
}
if (cache)
return [cache];
return [];
return cache ? [cache] : [];
}
// src/object/centernet.ts
@ -5599,13 +5572,13 @@ async function process3(res, outputShape, config3) {
detections[0][id][2] / inputSize4 - x,
detections[0][id][3] / inputSize4 - y
];
const box4 = [
const box5 = [
Math.trunc(boxRaw[0] * outputShape[0]),
Math.trunc(boxRaw[1] * outputShape[1]),
Math.trunc(boxRaw[2] * outputShape[0]),
Math.trunc(boxRaw[3] * outputShape[1])
];
results.push({ id: i++, score, class: classVal, label, box: box4, boxRaw });
results.push({ id: i++, score, class: classVal, label, box: box5, boxRaw });
}
Object.keys(t).forEach((tensor3) => tf13.dispose(t[tensor3]));
return results;
@ -5726,10 +5699,10 @@ async function predict7(image29, config3) {
tf14.dispose(tensor3);
if (resT) {
cache2.keypoints.length = 0;
const squeeze11 = resT.squeeze();
const squeeze10 = resT.squeeze();
tf14.dispose(resT);
const stack5 = squeeze11.unstack(2);
tf14.dispose(squeeze11);
const stack5 = squeeze10.unstack(2);
tf14.dispose(squeeze10);
for (let id = 0; id < stack5.length; id++) {
const [x2, y2, partScore] = await max2d(stack5[id], config3.body.minConfidence);
if (partScore > (((_a = config3.body) == null ? void 0 : _a.minConfidence) || 0)) {
@ -5947,20 +5920,20 @@ var getLeftToRightEyeDepthDifference = (rawCoords) => {
return leftEyeZ - rightEyeZ;
};
var getEyeBox = (rawCoords, face5, eyeInnerCornerIndex, eyeOuterCornerIndex, meshSize, flip = false) => {
const box4 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), irisEnlarge));
const boxSize = getBoxSize(box4);
const box5 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), irisEnlarge));
const boxSize = getBoxSize(box5);
let crop2 = tf17.image.cropAndResize(face5, [[
box4.startPoint[1] / meshSize,
box4.startPoint[0] / meshSize,
box4.endPoint[1] / meshSize,
box4.endPoint[0] / meshSize
box5.startPoint[1] / meshSize,
box5.startPoint[0] / meshSize,
box5.endPoint[1] / meshSize,
box5.endPoint[0] / meshSize
]], [0], [inputSize5, inputSize5]);
if (flip && env.kernels.includes("flipleftright")) {
const flipped = tf17.image.flipLeftRight(crop2);
tf17.dispose(crop2);
crop2 = flipped;
}
return { box: box4, boxSize, crop: crop2 };
return { box: box5, boxSize, crop: crop2 };
};
var getEyeCoords = (eyeData, eyeBox, eyeBoxSize, flip = false) => {
const eyeRawCoords = [];
@ -6054,7 +6027,7 @@ async function predict10(input, config3) {
const newCache = [];
let id = 0;
for (let i = 0; i < boxCache.length; i++) {
let box4 = boxCache[i];
let box5 = boxCache[i];
let angle = 0;
let rotationMatrix;
const face5 = {
@ -6068,20 +6041,20 @@ async function predict10(input, config3) {
faceScore: 0,
annotations: {}
};
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box4, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize6 : size());
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box5, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize6 : size());
if ((_f = config3 == null ? void 0 : config3.filter) == null ? void 0 : _f.equalization) {
const equilized = await histogramEqualization(face5.tensor);
tf18.dispose(face5.tensor);
face5.tensor = equilized;
}
face5.boxScore = Math.round(100 * box4.confidence) / 100;
face5.boxScore = Math.round(100 * box5.confidence) / 100;
if (!((_g = config3.face.mesh) == null ? void 0 : _g.enabled)) {
face5.box = getClampedBox(box4, input);
face5.boxRaw = getRawBox(box4, input);
face5.box = getClampedBox(box5, input);
face5.boxRaw = getRawBox(box5, input);
face5.score = face5.boxScore;
face5.mesh = box4.landmarks.map((pt) => [
(box4.startPoint[0] + box4.endPoint[0]) / 2 + (box4.endPoint[0] + box4.startPoint[0]) * pt[0] / size(),
(box4.startPoint[1] + box4.endPoint[1]) / 2 + (box4.endPoint[1] + box4.startPoint[1]) * pt[1] / size()
face5.mesh = box5.landmarks.map((pt) => [
(box5.startPoint[0] + box5.endPoint[0]) / 2 + (box5.endPoint[0] + box5.startPoint[0]) * pt[0] / size(),
(box5.startPoint[1] + box5.endPoint[1]) / 2 + (box5.endPoint[1] + box5.startPoint[1]) * pt[1] / size()
]);
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize6]);
for (const key of Object.keys(blazeFaceLandmarks))
@ -6097,24 +6070,24 @@ async function predict10(input, config3) {
let rawCoords = await coordsReshaped.array();
tf18.dispose([contourCoords, coordsReshaped, confidence, contours]);
if (face5.faceScore < (((_h = config3.face.detector) == null ? void 0 : _h.minConfidence) || 1)) {
box4.confidence = face5.faceScore;
box5.confidence = face5.faceScore;
} else {
if ((_i = config3.face.iris) == null ? void 0 : _i.enabled)
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize6);
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize6);
face5.mesh = transformRawCoords(rawCoords, box5, angle, rotationMatrix, inputSize6);
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize6]);
for (const key of Object.keys(meshAnnotations))
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
const boxCalculated = calculateLandmarksBoundingBox(face5.mesh);
const boxEnlarged = enlargeBox(boxCalculated, ((_j = config3.face.detector) == null ? void 0 : _j.cropFactor) || 1.6);
const boxSquared = squarifyBox(boxEnlarged);
box4 = { ...boxSquared, confidence: box4.confidence };
face5.box = getClampedBox(box4, input);
face5.boxRaw = getRawBox(box4, input);
box5 = { ...boxSquared, confidence: box5.confidence };
face5.box = getClampedBox(box5, input);
face5.boxRaw = getRawBox(box5, input);
face5.score = face5.faceScore;
newCache.push(box4);
newCache.push(box5);
tf18.dispose(face5.tensor);
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box4, input, inputSize6);
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box5, input, inputSize6);
}
}
faces.push(face5);
@ -6227,54 +6200,54 @@ var tf21 = __toModule(require_tfjs_esm());
// src/hand/handposeutil.ts
var tf20 = __toModule(require_tfjs_esm());
function getBoxSize2(box4) {
function getBoxSize2(box5) {
return [
Math.abs(box4.endPoint[0] - box4.startPoint[0]),
Math.abs(box4.endPoint[1] - box4.startPoint[1])
Math.abs(box5.endPoint[0] - box5.startPoint[0]),
Math.abs(box5.endPoint[1] - box5.startPoint[1])
];
}
function getBoxCenter2(box4) {
function getBoxCenter2(box5) {
return [
box4.startPoint[0] + (box4.endPoint[0] - box4.startPoint[0]) / 2,
box4.startPoint[1] + (box4.endPoint[1] - box4.startPoint[1]) / 2
box5.startPoint[0] + (box5.endPoint[0] - box5.startPoint[0]) / 2,
box5.startPoint[1] + (box5.endPoint[1] - box5.startPoint[1]) / 2
];
}
function cutBoxFromImageAndResize2(box4, image29, cropSize) {
function cutBoxFromImageAndResize2(box5, image29, cropSize) {
const h = image29.shape[1];
const w = image29.shape[2];
const boxes = [[
box4.startPoint[1] / h,
box4.startPoint[0] / w,
box4.endPoint[1] / h,
box4.endPoint[0] / w
box5.startPoint[1] / h,
box5.startPoint[0] / w,
box5.endPoint[1] / h,
box5.endPoint[0] / w
]];
return tf20.image.cropAndResize(image29, boxes, [0], cropSize);
}
function scaleBoxCoordinates2(box4, factor) {
const startPoint = [box4.startPoint[0] * factor[0], box4.startPoint[1] * factor[1]];
const endPoint = [box4.endPoint[0] * factor[0], box4.endPoint[1] * factor[1]];
const palmLandmarks = box4.palmLandmarks.map((coord) => {
function scaleBoxCoordinates2(box5, factor) {
const startPoint = [box5.startPoint[0] * factor[0], box5.startPoint[1] * factor[1]];
const endPoint = [box5.endPoint[0] * factor[0], box5.endPoint[1] * factor[1]];
const palmLandmarks = box5.palmLandmarks.map((coord) => {
const scaledCoord = [coord[0] * factor[0], coord[1] * factor[1]];
return scaledCoord;
});
return { startPoint, endPoint, palmLandmarks, confidence: box4.confidence };
return { startPoint, endPoint, palmLandmarks, confidence: box5.confidence };
}
function enlargeBox2(box4, factor = 1.5) {
const center = getBoxCenter2(box4);
const size2 = getBoxSize2(box4);
function enlargeBox2(box5, factor = 1.5) {
const center = getBoxCenter2(box5);
const size2 = getBoxSize2(box5);
const newHalfSize = [factor * size2[0] / 2, factor * size2[1] / 2];
const startPoint = [center[0] - newHalfSize[0], center[1] - newHalfSize[1]];
const endPoint = [center[0] + newHalfSize[0], center[1] + newHalfSize[1]];
return { startPoint, endPoint, palmLandmarks: box4.palmLandmarks };
return { startPoint, endPoint, palmLandmarks: box5.palmLandmarks };
}
function squarifyBox2(box4) {
const centers = getBoxCenter2(box4);
const size2 = getBoxSize2(box4);
function squarifyBox2(box5) {
const centers = getBoxCenter2(box5);
const size2 = getBoxSize2(box5);
const maxEdge = Math.max(...size2);
const halfSize = maxEdge / 2;
const startPoint = [centers[0] - halfSize, centers[1] - halfSize];
const endPoint = [centers[0] + halfSize, centers[1] + halfSize];
return { startPoint, endPoint, palmLandmarks: box4.palmLandmarks };
return { startPoint, endPoint, palmLandmarks: box5.palmLandmarks };
}
function normalizeRadians2(angle) {
return angle - 2 * Math.PI * Math.floor((angle + Math.PI) / (2 * Math.PI));
@ -9348,9 +9321,9 @@ var HandDetector = class {
p.slice = tf21.slice(t.predictions, [index2, 5], [1, 14]);
p.norm = this.normalizeLandmarks(p.slice, index2);
p.palmLandmarks = tf21.reshape(p.norm, [-1, 2]);
const box4 = await p.box.data();
const startPoint = box4.slice(0, 2);
const endPoint = box4.slice(2, 4);
const box5 = await p.box.data();
const startPoint = box5.slice(0, 2);
const endPoint = box5.slice(2, 4);
const palmLandmarks = await p.palmLandmarks.array();
const hand3 = { startPoint, endPoint, palmLandmarks, confidence: scores[index2] };
const scaled = scaleBoxCoordinates2(hand3, [input.shape[2] / this.inputSize, input.shape[1] / this.inputSize]);
@ -9937,24 +9910,24 @@ async function predict12(input, config3) {
}
}
const keypoints = predictions[i].landmarks;
let box4 = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0, 0];
let box5 = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0, 0];
let boxRaw = [0, 0, 0, 0];
if (keypoints && keypoints.length > 0) {
for (const pt of keypoints) {
if (pt[0] < box4[0])
box4[0] = pt[0];
if (pt[1] < box4[1])
box4[1] = pt[1];
if (pt[0] > box4[2])
box4[2] = pt[0];
if (pt[1] > box4[3])
box4[3] = pt[1];
if (pt[0] < box5[0])
box5[0] = pt[0];
if (pt[1] < box5[1])
box5[1] = pt[1];
if (pt[0] > box5[2])
box5[2] = pt[0];
if (pt[1] > box5[3])
box5[3] = pt[1];
}
box4[2] -= box4[0];
box4[3] -= box4[1];
boxRaw = [box4[0] / (input.shape[2] || 0), box4[1] / (input.shape[1] || 0), box4[2] / (input.shape[2] || 0), box4[3] / (input.shape[1] || 0)];
box5[2] -= box5[0];
box5[3] -= box5[1];
boxRaw = [box5[0] / (input.shape[2] || 0), box5[1] / (input.shape[1] || 0), box5[2] / (input.shape[2] || 0), box5[3] / (input.shape[1] || 0)];
} else {
box4 = predictions[i].box ? [
box5 = predictions[i].box ? [
Math.trunc(Math.max(0, predictions[i].box.topLeft[0])),
Math.trunc(Math.max(0, predictions[i].box.topLeft[1])),
Math.trunc(Math.min(input.shape[2] || 0, predictions[i].box.bottomRight[0]) - Math.max(0, predictions[i].box.topLeft[0])),
@ -9974,7 +9947,7 @@ async function predict12(input, config3) {
boxScore: Math.round(100 * predictions[i].boxConfidence) / 100,
fingerScore: Math.round(100 * predictions[i].fingerConfidence) / 100,
label: "hand",
box: box4,
box: box5,
boxRaw,
keypoints,
annotations: annotations2,
@ -10015,40 +9988,6 @@ async function load13(config3) {
return [handDetectorModel, handPoseModel];
}
// src/util/box.ts
function calc(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const box4 = [min2[0], min2[1], max4[0] - min2[0], max4[1] - min2[1]];
const boxRaw = [box4[0] / outputSize2[0], box4[1] / outputSize2[1], box4[2] / outputSize2[0], box4[3] / outputSize2[1]];
return { box: box4, boxRaw };
}
function square(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const center = [(min2[0] + max4[0]) / 2, (min2[1] + max4[1]) / 2];
const dist = Math.max(center[0] - min2[0], center[1] - min2[1], -center[0] + max4[0], -center[1] + max4[1]);
const box4 = [Math.trunc(center[0] - dist), Math.trunc(center[1] - dist), Math.trunc(2 * dist), Math.trunc(2 * dist)];
const boxRaw = [box4[0] / outputSize2[0], box4[1] / outputSize2[1], box4[2] / outputSize2[0], box4[3] / outputSize2[1]];
return { box: box4, boxRaw };
}
function scale(box4, scaleFact) {
const dist = [box4[2] * scaleFact, box4[3] * scaleFact];
const newBox = [
box4[0] - (dist[0] - box4[2]) / 2,
box4[1] - (dist[1] - box4[3]) / 2,
dist[0],
dist[1]
];
return newBox;
}
function crop(box4) {
const yxBox = [Math.max(0, box4[1]), Math.max(0, box4[0]), Math.min(1, box4[3] + box4[1]), Math.min(1, box4[2] + box4[0])];
return yxBox;
}
// src/hand/handtrack.ts
var tf24 = __toModule(require_tfjs_esm());
var models2 = [null, null];
@ -10067,11 +10006,11 @@ var cache3 = {
hands: []
};
var fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
middle: [9, 10, 11, 12],
ring: [13, 14, 15, 16],
pinky: [17, 18, 19, 20],
thumb: [0, 1, 2, 3, 4],
index: [0, 5, 6, 7, 8],
middle: [0, 9, 10, 11, 12],
ring: [0, 13, 14, 15, 16],
pinky: [0, 17, 18, 19, 20],
palm: [0]
};
async function loadDetect2(config3) {
@ -10622,7 +10561,7 @@ async function process4(res, inputSize9, outputShape, config3) {
];
let boxRaw = [x, y, w, h];
boxRaw = boxRaw.map((a) => Math.max(0, Math.min(a, 1)));
const box4 = [
const box5 = [
boxRaw[0] * outputShape[0],
boxRaw[1] * outputShape[1],
boxRaw[2] * outputShape[0],
@ -10633,7 +10572,7 @@ async function process4(res, inputSize9, outputShape, config3) {
score: Math.round(100 * score) / 100,
class: j + 1,
label: labels[j].label,
box: box4.map((a) => Math.trunc(a)),
box: box5.map((a) => Math.trunc(a)),
boxRaw
};
results.push(result);
@ -10976,7 +10915,7 @@ function getInstanceScore(existingPoses, keypoints) {
}, 0);
return notOverlappedKeypointScores / keypoints.length;
}
function decode2(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence2) {
function decode(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence2) {
const poses = [];
const queue = buildPartWithScoreQueue(minConfidence2, scores);
while (poses.length < maxDetected && !queue.empty()) {
@ -10987,9 +10926,9 @@ function decode2(offsets, scores, displacementsFwd, displacementsBwd, maxDetecte
let keypoints = decodePose(root, scores, offsets, displacementsFwd, displacementsBwd);
keypoints = keypoints.filter((a) => a.score > minConfidence2);
const score = getInstanceScore(poses, keypoints);
const box4 = getBoundingBox(keypoints);
const box5 = getBoundingBox(keypoints);
if (score > minConfidence2)
poses.push({ keypoints, box: box4, score: Math.round(100 * score) / 100 });
poses.push({ keypoints, box: box5, score: Math.round(100 * score) / 100 });
}
return poses;
}
@ -11007,7 +10946,7 @@ async function predict17(input, config3) {
const buffers = await Promise.all(res.map((tensor3) => tensor3.buffer()));
for (const t of res)
tf29.dispose(t);
const decoded = await decode2(buffers[0], buffers[1], buffers[2], buffers[3], config3.body.maxDetected, config3.body.minConfidence);
const decoded = await decode(buffers[0], buffers[1], buffers[2], buffers[3], config3.body.maxDetected, config3.body.minConfidence);
if (!model16.inputs[0].shape)
return [];
const scaled = scalePoses(decoded, [input.shape[1], input.shape[2]], [model16.inputs[0].shape[2], model16.inputs[0].shape[1]]);
@ -12066,7 +12005,7 @@ var calculateFaceAngle = (face5, imageSize) => {
thetaY = 0;
if (isNaN(thetaZ))
thetaZ = 0;
return { pitch: 2 * -thetaX, yaw: 2 * -thetaY, roll: 2 * -thetaZ };
return { pitch: -thetaX, yaw: -thetaY, roll: -thetaZ };
};
const meshToEulerAngle = (mesh2) => {
const radians = (a1, a2, b1, b2) => Math.atan2(b2 - a2, b1 - a1);
@ -12412,7 +12351,7 @@ function calc2(newResult, config3) {
bufferedResult.body = JSON.parse(JSON.stringify(newResult.body));
} else {
for (let i = 0; i < newResult.body.length; i++) {
const box4 = newResult.body[i].box.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].box[j] + newBoxCoord) / bufferedFactor);
const box5 = newResult.body[i].box.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].box[j] + newBoxCoord) / bufferedFactor);
const boxRaw = newResult.body[i].boxRaw.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].boxRaw[j] + newBoxCoord) / bufferedFactor);
const keypoints = newResult.body[i].keypoints.map((newKpt, j) => ({
score: newKpt.score,
@ -12446,14 +12385,14 @@ function calc2(newResult, config3) {
}
annotations2[name] = pt;
}
bufferedResult.body[i] = { ...newResult.body[i], box: box4, boxRaw, keypoints, annotations: annotations2 };
bufferedResult.body[i] = { ...newResult.body[i], box: box5, boxRaw, keypoints, annotations: annotations2 };
}
}
if (!bufferedResult.hand || newResult.hand.length !== bufferedResult.hand.length) {
bufferedResult.hand = JSON.parse(JSON.stringify(newResult.hand));
} else {
for (let i = 0; i < newResult.hand.length; i++) {
const box4 = newResult.hand[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].box[j] + b) / bufferedFactor);
const box5 = newResult.hand[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.hand[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].boxRaw[j] + b) / bufferedFactor);
if (bufferedResult.hand[i].keypoints.length !== newResult.hand[i].keypoints.length)
bufferedResult.hand[i].keypoints = newResult.hand[i].keypoints;
@ -12467,14 +12406,14 @@ function calc2(newResult, config3) {
annotations2[key] = newResult.hand[i].annotations[key] && newResult.hand[i].annotations[key][0] ? newResult.hand[i].annotations[key].map((val, j) => val.map((coord, k) => ((bufferedFactor - 1) * bufferedResult.hand[i].annotations[key][j][k] + coord) / bufferedFactor)) : null;
}
}
bufferedResult.hand[i] = { ...newResult.hand[i], box: box4, boxRaw, keypoints, annotations: annotations2 };
bufferedResult.hand[i] = { ...newResult.hand[i], box: box5, boxRaw, keypoints, annotations: annotations2 };
}
}
if (!bufferedResult.face || newResult.face.length !== bufferedResult.face.length) {
bufferedResult.face = JSON.parse(JSON.stringify(newResult.face));
} else {
for (let i = 0; i < newResult.face.length; i++) {
const box4 = newResult.face[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].box[j] + b) / bufferedFactor);
const box5 = newResult.face[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.face[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].boxRaw[j] + b) / bufferedFactor);
if (newResult.face[i].rotation) {
const rotation = { matrix: [0, 0, 0, 0, 0, 0, 0, 0, 0], angle: { roll: 0, yaw: 0, pitch: 0 }, gaze: { bearing: 0, strength: 0 } };
@ -12488,18 +12427,18 @@ function calc2(newResult, config3) {
bearing: ((bufferedFactor - 1) * (((_u = (_t = bufferedResult.face[i].rotation) == null ? void 0 : _t.gaze) == null ? void 0 : _u.bearing) || 0) + (((_w = (_v = newResult.face[i].rotation) == null ? void 0 : _v.gaze) == null ? void 0 : _w.bearing) || 0)) / bufferedFactor,
strength: ((bufferedFactor - 1) * (((_y = (_x = bufferedResult.face[i].rotation) == null ? void 0 : _x.gaze) == null ? void 0 : _y.strength) || 0) + (((_A = (_z = newResult.face[i].rotation) == null ? void 0 : _z.gaze) == null ? void 0 : _A.strength) || 0)) / bufferedFactor
};
bufferedResult.face[i] = { ...newResult.face[i], rotation, box: box4, boxRaw };
bufferedResult.face[i] = { ...newResult.face[i], rotation, box: box5, boxRaw };
}
bufferedResult.face[i] = { ...newResult.face[i], box: box4, boxRaw };
bufferedResult.face[i] = { ...newResult.face[i], box: box5, boxRaw };
}
}
if (!bufferedResult.object || newResult.object.length !== bufferedResult.object.length) {
bufferedResult.object = JSON.parse(JSON.stringify(newResult.object));
} else {
for (let i = 0; i < newResult.object.length; i++) {
const box4 = newResult.object[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].box[j] + b) / bufferedFactor);
const box5 = newResult.object[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.object[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].boxRaw[j] + b) / bufferedFactor);
bufferedResult.object[i] = { ...newResult.object[i], box: box4, boxRaw };
bufferedResult.object[i] = { ...newResult.object[i], box: box5, boxRaw };
}
}
if (newResult.persons) {
@ -12508,7 +12447,7 @@ function calc2(newResult, config3) {
bufferedResult.persons = JSON.parse(JSON.stringify(newPersons));
} else {
for (let i = 0; i < newPersons.length; i++) {
bufferedResult.persons[i].box = newPersons[i].box.map((box4, j) => ((bufferedFactor - 1) * bufferedResult.persons[i].box[j] + box4) / bufferedFactor);
bufferedResult.persons[i].box = newPersons[i].box.map((box5, j) => ((bufferedFactor - 1) * bufferedResult.persons[i].box[j] + box5) / bufferedFactor);
}
}
}
@ -12599,10 +12538,10 @@ function join2(faces, bodies, hands, gestures, shape) {
}
const x = [];
const y = [];
const extractXY = (box4) => {
if (box4 && box4.length === 4) {
x.push(box4[0], box4[0] + box4[2]);
y.push(box4[1], box4[1] + box4[3]);
const extractXY = (box5) => {
if (box5 && box5.length === 4) {
x.push(box5[0], box5[0] + box5[2]);
y.push(box5[1], box5[1] + box5[3]);
}
};
extractXY((_k = person2.face) == null ? void 0 : _k.box);

463
dist/human.node.js vendored
View File

@ -980,8 +980,8 @@ function GLImageFilter() {
// src/image/enhance.ts
var tf = __toModule(require_tfjs_esm());
async function histogramEqualization(inputImage) {
const squeeze11 = inputImage.shape.length === 4 ? tf.squeeze(inputImage) : inputImage;
const channels = tf.split(squeeze11, 3, 2);
const squeeze10 = inputImage.shape.length === 4 ? tf.squeeze(inputImage) : inputImage;
const channels = tf.split(squeeze10, 3, 2);
const min2 = [tf.min(channels[0]), tf.min(channels[1]), tf.min(channels[2])];
const max4 = [tf.max(channels[0]), tf.max(channels[1]), tf.max(channels[2])];
const absMax = await Promise.all(max4.map((channel) => channel.data()));
@ -991,8 +991,8 @@ async function histogramEqualization(inputImage) {
const fact = [tf.div(maxValue, range[0]), tf.div(maxValue, range[1]), tf.div(maxValue, range[2])];
const enh = [tf.mul(sub10[0], fact[0]), tf.mul(sub10[1], fact[1]), tf.mul(sub10[2], fact[2])];
const rgb2 = tf.stack([enh[0], enh[1], enh[2]], 2);
const reshape8 = tf.reshape(rgb2, [1, squeeze11.shape[0], squeeze11.shape[1], 3]);
tf.dispose([...channels, ...min2, ...max4, ...sub10, ...range, ...fact, ...enh, rgb2, squeeze11]);
const reshape8 = tf.reshape(rgb2, [1, squeeze10.shape[0], squeeze10.shape[1], 3]);
tf.dispose([...channels, ...min2, ...max4, ...sub10, ...range, ...fact, ...enh, rgb2, squeeze10]);
return reshape8;
}
@ -1414,8 +1414,8 @@ async function predict(image29, config3, idx, count2) {
if (!(model == null ? void 0 : model.inputs[0].shape))
return;
const t = {};
const box4 = [[0, 0.1, 0.9, 0.9]];
t.resize = tf4.image.cropAndResize(image29, box4, [0], [model.inputs[0].shape[2], model.inputs[0].shape[1]]);
const box5 = [[0, 0.1, 0.9, 0.9]];
t.resize = tf4.image.cropAndResize(image29, box5, [0], [model.inputs[0].shape[2], model.inputs[0].shape[1]]);
const obj = { age: 0, gender: "unknown", genderScore: 0, race: [] };
if ((_a2 = config3.face["gear"]) == null ? void 0 : _a2.enabled)
[t.age, t.gender, t.race] = model.execute(t.resize, ["age_output", "gender_output", "race_output"]);
@ -4911,44 +4911,44 @@ var UV33 = VTX33.map((x) => UV468[x]);
var UV7 = VTX7.map((x) => UV468[x]);
// src/face/facemeshutil.ts
var getBoxSize = (box4) => [Math.abs(box4.endPoint[0] - box4.startPoint[0]), Math.abs(box4.endPoint[1] - box4.startPoint[1])];
var getBoxCenter = (box4) => [box4.startPoint[0] + (box4.endPoint[0] - box4.startPoint[0]) / 2, box4.startPoint[1] + (box4.endPoint[1] - box4.startPoint[1]) / 2];
var getClampedBox = (box4, input) => box4 ? [
Math.trunc(Math.max(0, box4.startPoint[0])),
Math.trunc(Math.max(0, box4.startPoint[1])),
Math.trunc(Math.min(input.shape[2] || 0, box4.endPoint[0]) - Math.max(0, box4.startPoint[0])),
Math.trunc(Math.min(input.shape[1] || 0, box4.endPoint[1]) - Math.max(0, box4.startPoint[1]))
var getBoxSize = (box5) => [Math.abs(box5.endPoint[0] - box5.startPoint[0]), Math.abs(box5.endPoint[1] - box5.startPoint[1])];
var getBoxCenter = (box5) => [box5.startPoint[0] + (box5.endPoint[0] - box5.startPoint[0]) / 2, box5.startPoint[1] + (box5.endPoint[1] - box5.startPoint[1]) / 2];
var getClampedBox = (box5, input) => box5 ? [
Math.trunc(Math.max(0, box5.startPoint[0])),
Math.trunc(Math.max(0, box5.startPoint[1])),
Math.trunc(Math.min(input.shape[2] || 0, box5.endPoint[0]) - Math.max(0, box5.startPoint[0])),
Math.trunc(Math.min(input.shape[1] || 0, box5.endPoint[1]) - Math.max(0, box5.startPoint[1]))
] : [0, 0, 0, 0];
var getRawBox = (box4, input) => box4 ? [
box4.startPoint[0] / (input.shape[2] || 0),
box4.startPoint[1] / (input.shape[1] || 0),
(box4.endPoint[0] - box4.startPoint[0]) / (input.shape[2] || 0),
(box4.endPoint[1] - box4.startPoint[1]) / (input.shape[1] || 0)
var getRawBox = (box5, input) => box5 ? [
box5.startPoint[0] / (input.shape[2] || 0),
box5.startPoint[1] / (input.shape[1] || 0),
(box5.endPoint[0] - box5.startPoint[0]) / (input.shape[2] || 0),
(box5.endPoint[1] - box5.startPoint[1]) / (input.shape[1] || 0)
] : [0, 0, 0, 0];
var scaleBoxCoordinates = (box4, factor) => {
const startPoint = [box4.startPoint[0] * factor[0], box4.startPoint[1] * factor[1]];
const endPoint = [box4.endPoint[0] * factor[0], box4.endPoint[1] * factor[1]];
return { startPoint, endPoint, landmarks: box4.landmarks, confidence: box4.confidence };
var scaleBoxCoordinates = (box5, factor) => {
const startPoint = [box5.startPoint[0] * factor[0], box5.startPoint[1] * factor[1]];
const endPoint = [box5.endPoint[0] * factor[0], box5.endPoint[1] * factor[1]];
return { startPoint, endPoint, landmarks: box5.landmarks, confidence: box5.confidence };
};
var cutBoxFromImageAndResize = (box4, image29, cropSize) => {
var cutBoxFromImageAndResize = (box5, image29, cropSize) => {
const h = image29.shape[1];
const w = image29.shape[2];
const crop2 = tf9.image.cropAndResize(image29, [[box4.startPoint[1] / h, box4.startPoint[0] / w, box4.endPoint[1] / h, box4.endPoint[0] / w]], [0], cropSize);
const crop2 = tf9.image.cropAndResize(image29, [[box5.startPoint[1] / h, box5.startPoint[0] / w, box5.endPoint[1] / h, box5.endPoint[0] / w]], [0], cropSize);
const norm = tf9.div(crop2, constants.tf255);
tf9.dispose(crop2);
return norm;
};
var enlargeBox = (box4, factor) => {
const center = getBoxCenter(box4);
const size2 = getBoxSize(box4);
var enlargeBox = (box5, factor) => {
const center = getBoxCenter(box5);
const size2 = getBoxSize(box5);
const halfSize = [factor * size2[0] / 2, factor * size2[1] / 2];
return { startPoint: [center[0] - halfSize[0], center[1] - halfSize[1]], endPoint: [center[0] + halfSize[0], center[1] + halfSize[1]], landmarks: box4.landmarks, confidence: box4.confidence };
return { startPoint: [center[0] - halfSize[0], center[1] - halfSize[1]], endPoint: [center[0] + halfSize[0], center[1] + halfSize[1]], landmarks: box5.landmarks, confidence: box5.confidence };
};
var squarifyBox = (box4) => {
const centers = getBoxCenter(box4);
const size2 = getBoxSize(box4);
var squarifyBox = (box5) => {
const centers = getBoxCenter(box5);
const size2 = getBoxSize(box5);
const halfSize = Math.max(...size2) / 2;
return { startPoint: [Math.round(centers[0] - halfSize), Math.round(centers[1] - halfSize)], endPoint: [Math.round(centers[0] + halfSize), Math.round(centers[1] + halfSize)], landmarks: box4.landmarks, confidence: box4.confidence };
return { startPoint: [Math.round(centers[0] - halfSize), Math.round(centers[1] - halfSize)], endPoint: [Math.round(centers[0] + halfSize), Math.round(centers[1] + halfSize)], landmarks: box5.landmarks, confidence: box5.confidence };
};
var calculateLandmarksBoundingBox = (landmarks) => {
const xs = landmarks.map((d) => d[0]);
@ -5016,8 +5016,8 @@ function generateAnchors(inputSize9) {
}
return anchors4;
}
function transformRawCoords(coordsRaw, box4, angle, rotationMatrix, inputSize9) {
const boxSize = getBoxSize(box4);
function transformRawCoords(coordsRaw, box5, angle, rotationMatrix, inputSize9) {
const boxSize = getBoxSize(box5);
const coordsScaled = coordsRaw.map((coord) => [
boxSize[0] / inputSize9 * (coord[0] - inputSize9 / 2),
boxSize[1] / inputSize9 * (coord[1] - inputSize9 / 2),
@ -5027,33 +5027,33 @@ function transformRawCoords(coordsRaw, box4, angle, rotationMatrix, inputSize9)
const coordsRotationMatrix = largeAngle ? buildRotationMatrix(angle, [0, 0]) : fixedRotationMatrix;
const coordsRotated = largeAngle ? coordsScaled.map((coord) => [...rotatePoint(coord, coordsRotationMatrix), coord[2]]) : coordsScaled;
const inverseRotationMatrix = largeAngle ? invertTransformMatrix(rotationMatrix) : fixedRotationMatrix;
const boxCenter = [...getBoxCenter({ startPoint: box4.startPoint, endPoint: box4.endPoint }), 1];
const boxCenter = [...getBoxCenter({ startPoint: box5.startPoint, endPoint: box5.endPoint }), 1];
return coordsRotated.map((coord) => [
Math.round(coord[0] + dot(boxCenter, inverseRotationMatrix[0])),
Math.round(coord[1] + dot(boxCenter, inverseRotationMatrix[1])),
Math.round(coord[2] || 0)
]);
}
function correctFaceRotation(rotate, box4, input, inputSize9) {
const symmetryLine = box4.landmarks.length >= meshLandmarks.count ? meshLandmarks.symmetryLine : blazeFaceLandmarks.symmetryLine;
function correctFaceRotation(rotate, box5, input, inputSize9) {
const symmetryLine = box5.landmarks.length >= meshLandmarks.count ? meshLandmarks.symmetryLine : blazeFaceLandmarks.symmetryLine;
let angle = 0;
let rotationMatrix = fixedRotationMatrix;
let face5;
if (rotate && env.kernels.includes("rotatewithoffset")) {
angle = computeRotation(box4.landmarks[symmetryLine[0]], box4.landmarks[symmetryLine[1]]);
angle = computeRotation(box5.landmarks[symmetryLine[0]], box5.landmarks[symmetryLine[1]]);
const largeAngle = angle && angle !== 0 && Math.abs(angle) > 0.2;
if (largeAngle) {
const center = getBoxCenter({ startPoint: box4.startPoint, endPoint: box4.endPoint });
const center = getBoxCenter({ startPoint: box5.startPoint, endPoint: box5.endPoint });
const centerRaw = [center[0] / input.shape[2], center[1] / input.shape[1]];
const rotated = tf9.image.rotateWithOffset(input, angle, 0, centerRaw);
rotationMatrix = buildRotationMatrix(-angle, center);
face5 = cutBoxFromImageAndResize(box4, rotated, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, rotated, [inputSize9, inputSize9]);
tf9.dispose(rotated);
} else {
face5 = cutBoxFromImageAndResize(box4, input, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, input, [inputSize9, inputSize9]);
}
} else {
face5 = cutBoxFromImageAndResize(box4, input, [inputSize9, inputSize9]);
face5 = cutBoxFromImageAndResize(box5, input, [inputSize9, inputSize9]);
}
return [angle, rotationMatrix, face5];
}
@ -5238,41 +5238,39 @@ async function createAnchors() {
}
anchorTensor = { x: tf11.tensor1d(anchors4.map((a) => a.x)), y: tf11.tensor1d(anchors4.map((a) => a.y)) };
}
var cropFactor = [5, 5];
function decodeBoxes(boxesTensor, anchor) {
return tf11.tidy(() => {
const split5 = tf11.split(boxesTensor, 12, 1);
let xCenter = tf11.squeeze(split5[0]);
let yCenter = tf11.squeeze(split5[1]);
let width = tf11.squeeze(split5[2]);
let height = tf11.squeeze(split5[3]);
xCenter = tf11.add(tf11.div(xCenter, inputSize2), anchor.x);
yCenter = tf11.add(tf11.div(yCenter, inputSize2), anchor.y);
width = tf11.mul(tf11.div(width, inputSize2), cropFactor[0]);
height = tf11.mul(tf11.div(height, inputSize2), cropFactor[1]);
const xMin = tf11.sub(xCenter, tf11.div(width, 2));
const yMin = tf11.sub(yCenter, tf11.div(height, 2));
const boxes = tf11.stack([xMin, yMin, width, height], 1);
return boxes;
});
// src/util/box.ts
function calc(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const box5 = [min2[0], min2[1], max4[0] - min2[0], max4[1] - min2[1]];
const boxRaw = [box5[0] / outputSize2[0], box5[1] / outputSize2[1], box5[2] / outputSize2[0], box5[3] / outputSize2[1]];
return { box: box5, boxRaw };
}
async function decode(boxesTensor, logitsTensor, config3, outputSize2) {
const t = {};
t.boxes = decodeBoxes(boxesTensor, anchorTensor);
t.scores = tf11.sigmoid(logitsTensor);
t.argmax = tf11.argMax(t.scores);
const i = (await t.argmax.data())[0];
const scores = await t.scores.data();
const detected = [];
const minScore = config3.body["detector"] && config3.body["detector"]["minConfidence"] ? config3.body["detector"]["minConfidence"] : 0;
if (scores[i] >= minScore) {
const boxes = await t.boxes.array();
const boxRaw = boxes[i];
const box4 = [boxRaw[0] * outputSize2[0], boxRaw[1] * outputSize2[1], boxRaw[2] * outputSize2[0], boxRaw[3] * outputSize2[1]];
detected.push({ box: box4, boxRaw, score: scores[i] });
function square(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const center = [(min2[0] + max4[0]) / 2, (min2[1] + max4[1]) / 2];
const dist = Math.max(center[0] - min2[0], center[1] - min2[1], -center[0] + max4[0], -center[1] + max4[1]);
const box5 = [Math.trunc(center[0] - dist), Math.trunc(center[1] - dist), Math.trunc(2 * dist), Math.trunc(2 * dist)];
const boxRaw = [box5[0] / outputSize2[0], box5[1] / outputSize2[1], box5[2] / outputSize2[0], box5[3] / outputSize2[1]];
return { box: box5, boxRaw };
}
Object.keys(t).forEach((tensor3) => tf11.dispose(t[tensor3]));
return detected;
function scale(box5, scaleFact) {
const dist = [box5[2] * scaleFact, box5[3] * scaleFact];
const newBox = [
box5[0] - (dist[0] - box5[2]) / 2,
box5[1] - (dist[1] - box5[3]) / 2,
dist[0],
dist[1]
];
return newBox;
}
function crop(box5) {
const yxBox = [Math.max(0, box5[1]), Math.max(0, box5[0]), Math.min(1, box5[3] + box5[1]), Math.min(1, box5[2] + box5[0])];
return yxBox;
}
// src/body/blazepose.ts
@ -5285,7 +5283,7 @@ var outputNodes = {
detector: []
};
var cache = null;
var lastBox;
var cropBox;
var padding = [[0, 0], [0, 0], [0, 0], [0, 0]];
var lastTime5 = 0;
var sigmoid3 = (x) => 1 - 1 / (1 + Math.exp(x));
@ -5322,39 +5320,37 @@ async function loadPose(config3) {
log("cached model:", models.landmarks["modelUrl"]);
return models.landmarks;
}
function calculateBoxes(keypoints, outputSize2) {
const x = keypoints.map((a) => a.position[0]);
const y = keypoints.map((a) => a.position[1]);
const keypointsBox = [Math.min(...x), Math.min(...y), Math.max(...x) - Math.min(...x), Math.max(...y) - Math.min(...y)];
const keypointsBoxRaw = [keypointsBox[0] / outputSize2[0], keypointsBox[1] / outputSize2[1], keypointsBox[2] / outputSize2[0], keypointsBox[3] / outputSize2[1]];
return { keypointsBox, keypointsBoxRaw };
}
async function prepareImage(input, size2, box4) {
async function prepareImage(input, size2) {
const t = {};
if (!input.shape || !input.shape[1] || !input.shape[2])
return input;
let final;
if (cropBox) {
t.cropped = tf12.image.cropAndResize(input, [cropBox], [0], [input.shape[1], input.shape[2]]);
}
if (input.shape[1] !== input.shape[2]) {
const height = box4 ? [Math.trunc(input.shape[1] * box4[1]), Math.trunc(input.shape[1] * (box4[1] + box4[3]))] : [input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0, input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0];
const width = box4 ? [Math.trunc(input.shape[2] * box4[0]), Math.trunc(input.shape[2] * (box4[0] + box4[2]))] : [input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0, input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0];
const height = [
input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0,
input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0
];
const width = [
input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0,
input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0
];
padding = [
[0, 0],
height,
width,
[0, 0]
];
if (box4) {
t.resize = tf12.image.cropAndResize(input, [box4], [0], [size2, size2]);
} else {
t.pad = tf12.pad(input, padding);
t.pad = tf12.pad(t.cropped || input, padding);
t.resize = tf12.image.resizeBilinear(t.pad, [size2, size2]);
}
final = tf12.div(t.resize, constants.tf255);
} else if (input.shape[1] !== size2) {
t.resize = tf12.image.resizeBilinear(input, [size2, size2]);
t.resize = tf12.image.resizeBilinear(t.cropped || input, [size2, size2]);
final = tf12.div(t.resize, constants.tf255);
} else {
final = tf12.div(input, constants.tf255);
final = tf12.div(t.cropped || input, constants.tf255);
}
Object.keys(t).forEach((tensor3) => tf12.dispose(t[tensor3]));
return final;
@ -5368,19 +5364,21 @@ function rescaleKeypoints(keypoints, outputSize2) {
];
kpt4.positionRaw = [kpt4.position[0] / outputSize2[0], kpt4.position[1] / outputSize2[1], kpt4.position[2]];
}
return keypoints;
}
function rescaleBoxes(boxes, outputSize2) {
for (const box4 of boxes) {
box4.box = [
Math.trunc(box4.box[0] * (outputSize2[0] + padding[2][0] + padding[2][1]) / outputSize2[0]),
Math.trunc(box4.box[1] * (outputSize2[1] + padding[1][0] + padding[1][1]) / outputSize2[1]),
Math.trunc(box4.box[2] * (outputSize2[0] + padding[2][0] + padding[2][1]) / outputSize2[0]),
Math.trunc(box4.box[3] * (outputSize2[1] + padding[1][0] + padding[1][1]) / outputSize2[1])
if (cropBox) {
for (const kpt4 of keypoints) {
kpt4.positionRaw = [
kpt4.positionRaw[0] + cropBox[1],
kpt4.positionRaw[1] + cropBox[0],
kpt4.positionRaw[2]
];
kpt4.position = [
Math.trunc(kpt4.positionRaw[0] * outputSize2[0]),
Math.trunc(kpt4.positionRaw[1] * outputSize2[1]),
kpt4.positionRaw[2]
];
box4.boxRaw = [box4.box[0] / outputSize2[0], box4.box[1] / outputSize2[1], box4.box[2] / outputSize2[0], box4.box[3] / outputSize2[1]];
}
return boxes;
}
return keypoints;
}
async function detectLandmarks(input, config3, outputSize2) {
var _a;
@ -5402,7 +5400,8 @@ async function detectLandmarks(input, config3, outputSize2) {
if (poseScore < (config3.body.minConfidence || 0))
return null;
const keypoints = rescaleKeypoints(keypointsRelative, outputSize2);
const boxes = calculateBoxes(keypoints, [outputSize2[0], outputSize2[1]]);
const kpts = keypoints.map((k) => k.position);
const boxes = calc(kpts, [outputSize2[0], outputSize2[1]]);
const annotations2 = {};
for (const [name, indexes] of Object.entries(connected)) {
const pt = [];
@ -5414,22 +5413,9 @@ async function detectLandmarks(input, config3, outputSize2) {
}
annotations2[name] = pt;
}
const body4 = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.keypointsBox, boxRaw: boxes.keypointsBoxRaw, keypoints, annotations: annotations2 };
const body4 = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.box, boxRaw: boxes.boxRaw, keypoints, annotations: annotations2 };
return body4;
}
async function detectBoxes(input, config3, outputSize2) {
var _a;
const t = {};
t.res = (_a = models.detector) == null ? void 0 : _a.execute(input, ["Identity"]);
t.logitsRaw = tf12.slice(t.res, [0, 0, 0], [1, -1, 1]);
t.boxesRaw = tf12.slice(t.res, [0, 0, 1], [1, -1, -1]);
t.logits = tf12.squeeze(t.logitsRaw);
t.boxes = tf12.squeeze(t.boxesRaw);
const boxes = await decode(t.boxes, t.logits, config3, outputSize2);
rescaleBoxes(boxes, outputSize2);
Object.keys(t).forEach((tensor3) => tf12.dispose(t[tensor3]));
return boxes;
}
async function predict5(input, config3) {
const outputSize2 = [input.shape[2] || 0, input.shape[1] || 0];
const skipTime = (config3.body.skipTime || 0) > now() - lastTime5;
@ -5438,26 +5424,13 @@ async function predict5(input, config3) {
skipped5++;
} else {
const t = {};
if (config3.body["detector"] && config3.body["detector"]["enabled"]) {
t.detector = await prepareImage(input, 224);
const boxes = await detectBoxes(t.detector, config3, outputSize2);
if (boxes && boxes.length === 1) {
t.landmarks = await prepareImage(input, 256, boxes[0].box);
t.landmarks = await prepareImage(input, 256);
cache = await detectLandmarks(t.landmarks, config3, outputSize2);
}
if (cache)
cache.score = boxes[0].score;
} else {
t.landmarks = await prepareImage(input, 256, lastBox);
cache = await detectLandmarks(t.landmarks, config3, outputSize2);
}
Object.keys(t).forEach((tensor3) => tf12.dispose(t[tensor3]));
lastTime5 = now();
skipped5 = 0;
}
if (cache)
return [cache];
return [];
return cache ? [cache] : [];
}
// src/object/centernet.ts
@ -5598,13 +5571,13 @@ async function process3(res, outputShape, config3) {
detections[0][id][2] / inputSize4 - x,
detections[0][id][3] / inputSize4 - y
];
const box4 = [
const box5 = [
Math.trunc(boxRaw[0] * outputShape[0]),
Math.trunc(boxRaw[1] * outputShape[1]),
Math.trunc(boxRaw[2] * outputShape[0]),
Math.trunc(boxRaw[3] * outputShape[1])
];
results.push({ id: i++, score, class: classVal, label, box: box4, boxRaw });
results.push({ id: i++, score, class: classVal, label, box: box5, boxRaw });
}
Object.keys(t).forEach((tensor3) => tf13.dispose(t[tensor3]));
return results;
@ -5725,10 +5698,10 @@ async function predict7(image29, config3) {
tf14.dispose(tensor3);
if (resT) {
cache2.keypoints.length = 0;
const squeeze11 = resT.squeeze();
const squeeze10 = resT.squeeze();
tf14.dispose(resT);
const stack5 = squeeze11.unstack(2);
tf14.dispose(squeeze11);
const stack5 = squeeze10.unstack(2);
tf14.dispose(squeeze10);
for (let id = 0; id < stack5.length; id++) {
const [x2, y2, partScore] = await max2d(stack5[id], config3.body.minConfidence);
if (partScore > (((_a = config3.body) == null ? void 0 : _a.minConfidence) || 0)) {
@ -5946,20 +5919,20 @@ var getLeftToRightEyeDepthDifference = (rawCoords) => {
return leftEyeZ - rightEyeZ;
};
var getEyeBox = (rawCoords, face5, eyeInnerCornerIndex, eyeOuterCornerIndex, meshSize, flip = false) => {
const box4 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), irisEnlarge));
const boxSize = getBoxSize(box4);
const box5 = squarifyBox(enlargeBox(calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), irisEnlarge));
const boxSize = getBoxSize(box5);
let crop2 = tf17.image.cropAndResize(face5, [[
box4.startPoint[1] / meshSize,
box4.startPoint[0] / meshSize,
box4.endPoint[1] / meshSize,
box4.endPoint[0] / meshSize
box5.startPoint[1] / meshSize,
box5.startPoint[0] / meshSize,
box5.endPoint[1] / meshSize,
box5.endPoint[0] / meshSize
]], [0], [inputSize5, inputSize5]);
if (flip && env.kernels.includes("flipleftright")) {
const flipped = tf17.image.flipLeftRight(crop2);
tf17.dispose(crop2);
crop2 = flipped;
}
return { box: box4, boxSize, crop: crop2 };
return { box: box5, boxSize, crop: crop2 };
};
var getEyeCoords = (eyeData, eyeBox, eyeBoxSize, flip = false) => {
const eyeRawCoords = [];
@ -6053,7 +6026,7 @@ async function predict10(input, config3) {
const newCache = [];
let id = 0;
for (let i = 0; i < boxCache.length; i++) {
let box4 = boxCache[i];
let box5 = boxCache[i];
let angle = 0;
let rotationMatrix;
const face5 = {
@ -6067,20 +6040,20 @@ async function predict10(input, config3) {
faceScore: 0,
annotations: {}
};
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box4, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize6 : size());
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box5, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize6 : size());
if ((_f = config3 == null ? void 0 : config3.filter) == null ? void 0 : _f.equalization) {
const equilized = await histogramEqualization(face5.tensor);
tf18.dispose(face5.tensor);
face5.tensor = equilized;
}
face5.boxScore = Math.round(100 * box4.confidence) / 100;
face5.boxScore = Math.round(100 * box5.confidence) / 100;
if (!((_g = config3.face.mesh) == null ? void 0 : _g.enabled)) {
face5.box = getClampedBox(box4, input);
face5.boxRaw = getRawBox(box4, input);
face5.box = getClampedBox(box5, input);
face5.boxRaw = getRawBox(box5, input);
face5.score = face5.boxScore;
face5.mesh = box4.landmarks.map((pt) => [
(box4.startPoint[0] + box4.endPoint[0]) / 2 + (box4.endPoint[0] + box4.startPoint[0]) * pt[0] / size(),
(box4.startPoint[1] + box4.endPoint[1]) / 2 + (box4.endPoint[1] + box4.startPoint[1]) * pt[1] / size()
face5.mesh = box5.landmarks.map((pt) => [
(box5.startPoint[0] + box5.endPoint[0]) / 2 + (box5.endPoint[0] + box5.startPoint[0]) * pt[0] / size(),
(box5.startPoint[1] + box5.endPoint[1]) / 2 + (box5.endPoint[1] + box5.startPoint[1]) * pt[1] / size()
]);
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize6]);
for (const key of Object.keys(blazeFaceLandmarks))
@ -6096,24 +6069,24 @@ async function predict10(input, config3) {
let rawCoords = await coordsReshaped.array();
tf18.dispose([contourCoords, coordsReshaped, confidence, contours]);
if (face5.faceScore < (((_h = config3.face.detector) == null ? void 0 : _h.minConfidence) || 1)) {
box4.confidence = face5.faceScore;
box5.confidence = face5.faceScore;
} else {
if ((_i = config3.face.iris) == null ? void 0 : _i.enabled)
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize6);
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize6);
face5.mesh = transformRawCoords(rawCoords, box5, angle, rotationMatrix, inputSize6);
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize6]);
for (const key of Object.keys(meshAnnotations))
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
const boxCalculated = calculateLandmarksBoundingBox(face5.mesh);
const boxEnlarged = enlargeBox(boxCalculated, ((_j = config3.face.detector) == null ? void 0 : _j.cropFactor) || 1.6);
const boxSquared = squarifyBox(boxEnlarged);
box4 = { ...boxSquared, confidence: box4.confidence };
face5.box = getClampedBox(box4, input);
face5.boxRaw = getRawBox(box4, input);
box5 = { ...boxSquared, confidence: box5.confidence };
face5.box = getClampedBox(box5, input);
face5.boxRaw = getRawBox(box5, input);
face5.score = face5.faceScore;
newCache.push(box4);
newCache.push(box5);
tf18.dispose(face5.tensor);
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box4, input, inputSize6);
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box5, input, inputSize6);
}
}
faces.push(face5);
@ -6226,54 +6199,54 @@ var tf21 = __toModule(require_tfjs_esm());
// src/hand/handposeutil.ts
var tf20 = __toModule(require_tfjs_esm());
function getBoxSize2(box4) {
function getBoxSize2(box5) {
return [
Math.abs(box4.endPoint[0] - box4.startPoint[0]),
Math.abs(box4.endPoint[1] - box4.startPoint[1])
Math.abs(box5.endPoint[0] - box5.startPoint[0]),
Math.abs(box5.endPoint[1] - box5.startPoint[1])
];
}
function getBoxCenter2(box4) {
function getBoxCenter2(box5) {
return [
box4.startPoint[0] + (box4.endPoint[0] - box4.startPoint[0]) / 2,
box4.startPoint[1] + (box4.endPoint[1] - box4.startPoint[1]) / 2
box5.startPoint[0] + (box5.endPoint[0] - box5.startPoint[0]) / 2,
box5.startPoint[1] + (box5.endPoint[1] - box5.startPoint[1]) / 2
];
}
function cutBoxFromImageAndResize2(box4, image29, cropSize) {
function cutBoxFromImageAndResize2(box5, image29, cropSize) {
const h = image29.shape[1];
const w = image29.shape[2];
const boxes = [[
box4.startPoint[1] / h,
box4.startPoint[0] / w,
box4.endPoint[1] / h,
box4.endPoint[0] / w
box5.startPoint[1] / h,
box5.startPoint[0] / w,
box5.endPoint[1] / h,
box5.endPoint[0] / w
]];
return tf20.image.cropAndResize(image29, boxes, [0], cropSize);
}
function scaleBoxCoordinates2(box4, factor) {
const startPoint = [box4.startPoint[0] * factor[0], box4.startPoint[1] * factor[1]];
const endPoint = [box4.endPoint[0] * factor[0], box4.endPoint[1] * factor[1]];
const palmLandmarks = box4.palmLandmarks.map((coord) => {
function scaleBoxCoordinates2(box5, factor) {
const startPoint = [box5.startPoint[0] * factor[0], box5.startPoint[1] * factor[1]];
const endPoint = [box5.endPoint[0] * factor[0], box5.endPoint[1] * factor[1]];
const palmLandmarks = box5.palmLandmarks.map((coord) => {
const scaledCoord = [coord[0] * factor[0], coord[1] * factor[1]];
return scaledCoord;
});
return { startPoint, endPoint, palmLandmarks, confidence: box4.confidence };
return { startPoint, endPoint, palmLandmarks, confidence: box5.confidence };
}
function enlargeBox2(box4, factor = 1.5) {
const center = getBoxCenter2(box4);
const size2 = getBoxSize2(box4);
function enlargeBox2(box5, factor = 1.5) {
const center = getBoxCenter2(box5);
const size2 = getBoxSize2(box5);
const newHalfSize = [factor * size2[0] / 2, factor * size2[1] / 2];
const startPoint = [center[0] - newHalfSize[0], center[1] - newHalfSize[1]];
const endPoint = [center[0] + newHalfSize[0], center[1] + newHalfSize[1]];
return { startPoint, endPoint, palmLandmarks: box4.palmLandmarks };
return { startPoint, endPoint, palmLandmarks: box5.palmLandmarks };
}
function squarifyBox2(box4) {
const centers = getBoxCenter2(box4);
const size2 = getBoxSize2(box4);
function squarifyBox2(box5) {
const centers = getBoxCenter2(box5);
const size2 = getBoxSize2(box5);
const maxEdge = Math.max(...size2);
const halfSize = maxEdge / 2;
const startPoint = [centers[0] - halfSize, centers[1] - halfSize];
const endPoint = [centers[0] + halfSize, centers[1] + halfSize];
return { startPoint, endPoint, palmLandmarks: box4.palmLandmarks };
return { startPoint, endPoint, palmLandmarks: box5.palmLandmarks };
}
function normalizeRadians2(angle) {
return angle - 2 * Math.PI * Math.floor((angle + Math.PI) / (2 * Math.PI));
@ -9347,9 +9320,9 @@ var HandDetector = class {
p.slice = tf21.slice(t.predictions, [index2, 5], [1, 14]);
p.norm = this.normalizeLandmarks(p.slice, index2);
p.palmLandmarks = tf21.reshape(p.norm, [-1, 2]);
const box4 = await p.box.data();
const startPoint = box4.slice(0, 2);
const endPoint = box4.slice(2, 4);
const box5 = await p.box.data();
const startPoint = box5.slice(0, 2);
const endPoint = box5.slice(2, 4);
const palmLandmarks = await p.palmLandmarks.array();
const hand3 = { startPoint, endPoint, palmLandmarks, confidence: scores[index2] };
const scaled = scaleBoxCoordinates2(hand3, [input.shape[2] / this.inputSize, input.shape[1] / this.inputSize]);
@ -9936,24 +9909,24 @@ async function predict12(input, config3) {
}
}
const keypoints = predictions[i].landmarks;
let box4 = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0, 0];
let box5 = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0, 0];
let boxRaw = [0, 0, 0, 0];
if (keypoints && keypoints.length > 0) {
for (const pt of keypoints) {
if (pt[0] < box4[0])
box4[0] = pt[0];
if (pt[1] < box4[1])
box4[1] = pt[1];
if (pt[0] > box4[2])
box4[2] = pt[0];
if (pt[1] > box4[3])
box4[3] = pt[1];
if (pt[0] < box5[0])
box5[0] = pt[0];
if (pt[1] < box5[1])
box5[1] = pt[1];
if (pt[0] > box5[2])
box5[2] = pt[0];
if (pt[1] > box5[3])
box5[3] = pt[1];
}
box4[2] -= box4[0];
box4[3] -= box4[1];
boxRaw = [box4[0] / (input.shape[2] || 0), box4[1] / (input.shape[1] || 0), box4[2] / (input.shape[2] || 0), box4[3] / (input.shape[1] || 0)];
box5[2] -= box5[0];
box5[3] -= box5[1];
boxRaw = [box5[0] / (input.shape[2] || 0), box5[1] / (input.shape[1] || 0), box5[2] / (input.shape[2] || 0), box5[3] / (input.shape[1] || 0)];
} else {
box4 = predictions[i].box ? [
box5 = predictions[i].box ? [
Math.trunc(Math.max(0, predictions[i].box.topLeft[0])),
Math.trunc(Math.max(0, predictions[i].box.topLeft[1])),
Math.trunc(Math.min(input.shape[2] || 0, predictions[i].box.bottomRight[0]) - Math.max(0, predictions[i].box.topLeft[0])),
@ -9973,7 +9946,7 @@ async function predict12(input, config3) {
boxScore: Math.round(100 * predictions[i].boxConfidence) / 100,
fingerScore: Math.round(100 * predictions[i].fingerConfidence) / 100,
label: "hand",
box: box4,
box: box5,
boxRaw,
keypoints,
annotations: annotations2,
@ -10014,40 +9987,6 @@ async function load13(config3) {
return [handDetectorModel, handPoseModel];
}
// src/util/box.ts
function calc(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const box4 = [min2[0], min2[1], max4[0] - min2[0], max4[1] - min2[1]];
const boxRaw = [box4[0] / outputSize2[0], box4[1] / outputSize2[1], box4[2] / outputSize2[0], box4[3] / outputSize2[1]];
return { box: box4, boxRaw };
}
function square(keypoints, outputSize2 = [1, 1]) {
const coords8 = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])];
const min2 = [Math.min(...coords8[0]), Math.min(...coords8[1])];
const max4 = [Math.max(...coords8[0]), Math.max(...coords8[1])];
const center = [(min2[0] + max4[0]) / 2, (min2[1] + max4[1]) / 2];
const dist = Math.max(center[0] - min2[0], center[1] - min2[1], -center[0] + max4[0], -center[1] + max4[1]);
const box4 = [Math.trunc(center[0] - dist), Math.trunc(center[1] - dist), Math.trunc(2 * dist), Math.trunc(2 * dist)];
const boxRaw = [box4[0] / outputSize2[0], box4[1] / outputSize2[1], box4[2] / outputSize2[0], box4[3] / outputSize2[1]];
return { box: box4, boxRaw };
}
function scale(box4, scaleFact) {
const dist = [box4[2] * scaleFact, box4[3] * scaleFact];
const newBox = [
box4[0] - (dist[0] - box4[2]) / 2,
box4[1] - (dist[1] - box4[3]) / 2,
dist[0],
dist[1]
];
return newBox;
}
function crop(box4) {
const yxBox = [Math.max(0, box4[1]), Math.max(0, box4[0]), Math.min(1, box4[3] + box4[1]), Math.min(1, box4[2] + box4[0])];
return yxBox;
}
// src/hand/handtrack.ts
var tf24 = __toModule(require_tfjs_esm());
var models2 = [null, null];
@ -10066,11 +10005,11 @@ var cache3 = {
hands: []
};
var fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
middle: [9, 10, 11, 12],
ring: [13, 14, 15, 16],
pinky: [17, 18, 19, 20],
thumb: [0, 1, 2, 3, 4],
index: [0, 5, 6, 7, 8],
middle: [0, 9, 10, 11, 12],
ring: [0, 13, 14, 15, 16],
pinky: [0, 17, 18, 19, 20],
palm: [0]
};
async function loadDetect2(config3) {
@ -10621,7 +10560,7 @@ async function process4(res, inputSize9, outputShape, config3) {
];
let boxRaw = [x, y, w, h];
boxRaw = boxRaw.map((a) => Math.max(0, Math.min(a, 1)));
const box4 = [
const box5 = [
boxRaw[0] * outputShape[0],
boxRaw[1] * outputShape[1],
boxRaw[2] * outputShape[0],
@ -10632,7 +10571,7 @@ async function process4(res, inputSize9, outputShape, config3) {
score: Math.round(100 * score) / 100,
class: j + 1,
label: labels[j].label,
box: box4.map((a) => Math.trunc(a)),
box: box5.map((a) => Math.trunc(a)),
boxRaw
};
results.push(result);
@ -10975,7 +10914,7 @@ function getInstanceScore(existingPoses, keypoints) {
}, 0);
return notOverlappedKeypointScores / keypoints.length;
}
function decode2(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence2) {
function decode(offsets, scores, displacementsFwd, displacementsBwd, maxDetected, minConfidence2) {
const poses = [];
const queue = buildPartWithScoreQueue(minConfidence2, scores);
while (poses.length < maxDetected && !queue.empty()) {
@ -10986,9 +10925,9 @@ function decode2(offsets, scores, displacementsFwd, displacementsBwd, maxDetecte
let keypoints = decodePose(root, scores, offsets, displacementsFwd, displacementsBwd);
keypoints = keypoints.filter((a) => a.score > minConfidence2);
const score = getInstanceScore(poses, keypoints);
const box4 = getBoundingBox(keypoints);
const box5 = getBoundingBox(keypoints);
if (score > minConfidence2)
poses.push({ keypoints, box: box4, score: Math.round(100 * score) / 100 });
poses.push({ keypoints, box: box5, score: Math.round(100 * score) / 100 });
}
return poses;
}
@ -11006,7 +10945,7 @@ async function predict17(input, config3) {
const buffers = await Promise.all(res.map((tensor3) => tensor3.buffer()));
for (const t of res)
tf29.dispose(t);
const decoded = await decode2(buffers[0], buffers[1], buffers[2], buffers[3], config3.body.maxDetected, config3.body.minConfidence);
const decoded = await decode(buffers[0], buffers[1], buffers[2], buffers[3], config3.body.maxDetected, config3.body.minConfidence);
if (!model16.inputs[0].shape)
return [];
const scaled = scalePoses(decoded, [input.shape[1], input.shape[2]], [model16.inputs[0].shape[2], model16.inputs[0].shape[1]]);
@ -12065,7 +12004,7 @@ var calculateFaceAngle = (face5, imageSize) => {
thetaY = 0;
if (isNaN(thetaZ))
thetaZ = 0;
return { pitch: 2 * -thetaX, yaw: 2 * -thetaY, roll: 2 * -thetaZ };
return { pitch: -thetaX, yaw: -thetaY, roll: -thetaZ };
};
const meshToEulerAngle = (mesh2) => {
const radians = (a1, a2, b1, b2) => Math.atan2(b2 - a2, b1 - a1);
@ -12411,7 +12350,7 @@ function calc2(newResult, config3) {
bufferedResult.body = JSON.parse(JSON.stringify(newResult.body));
} else {
for (let i = 0; i < newResult.body.length; i++) {
const box4 = newResult.body[i].box.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].box[j] + newBoxCoord) / bufferedFactor);
const box5 = newResult.body[i].box.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].box[j] + newBoxCoord) / bufferedFactor);
const boxRaw = newResult.body[i].boxRaw.map((newBoxCoord, j) => ((bufferedFactor - 1) * bufferedResult.body[i].boxRaw[j] + newBoxCoord) / bufferedFactor);
const keypoints = newResult.body[i].keypoints.map((newKpt, j) => ({
score: newKpt.score,
@ -12445,14 +12384,14 @@ function calc2(newResult, config3) {
}
annotations2[name] = pt;
}
bufferedResult.body[i] = { ...newResult.body[i], box: box4, boxRaw, keypoints, annotations: annotations2 };
bufferedResult.body[i] = { ...newResult.body[i], box: box5, boxRaw, keypoints, annotations: annotations2 };
}
}
if (!bufferedResult.hand || newResult.hand.length !== bufferedResult.hand.length) {
bufferedResult.hand = JSON.parse(JSON.stringify(newResult.hand));
} else {
for (let i = 0; i < newResult.hand.length; i++) {
const box4 = newResult.hand[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].box[j] + b) / bufferedFactor);
const box5 = newResult.hand[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.hand[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.hand[i].boxRaw[j] + b) / bufferedFactor);
if (bufferedResult.hand[i].keypoints.length !== newResult.hand[i].keypoints.length)
bufferedResult.hand[i].keypoints = newResult.hand[i].keypoints;
@ -12466,14 +12405,14 @@ function calc2(newResult, config3) {
annotations2[key] = newResult.hand[i].annotations[key] && newResult.hand[i].annotations[key][0] ? newResult.hand[i].annotations[key].map((val, j) => val.map((coord, k) => ((bufferedFactor - 1) * bufferedResult.hand[i].annotations[key][j][k] + coord) / bufferedFactor)) : null;
}
}
bufferedResult.hand[i] = { ...newResult.hand[i], box: box4, boxRaw, keypoints, annotations: annotations2 };
bufferedResult.hand[i] = { ...newResult.hand[i], box: box5, boxRaw, keypoints, annotations: annotations2 };
}
}
if (!bufferedResult.face || newResult.face.length !== bufferedResult.face.length) {
bufferedResult.face = JSON.parse(JSON.stringify(newResult.face));
} else {
for (let i = 0; i < newResult.face.length; i++) {
const box4 = newResult.face[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].box[j] + b) / bufferedFactor);
const box5 = newResult.face[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.face[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.face[i].boxRaw[j] + b) / bufferedFactor);
if (newResult.face[i].rotation) {
const rotation = { matrix: [0, 0, 0, 0, 0, 0, 0, 0, 0], angle: { roll: 0, yaw: 0, pitch: 0 }, gaze: { bearing: 0, strength: 0 } };
@ -12487,18 +12426,18 @@ function calc2(newResult, config3) {
bearing: ((bufferedFactor - 1) * (((_u = (_t = bufferedResult.face[i].rotation) == null ? void 0 : _t.gaze) == null ? void 0 : _u.bearing) || 0) + (((_w = (_v = newResult.face[i].rotation) == null ? void 0 : _v.gaze) == null ? void 0 : _w.bearing) || 0)) / bufferedFactor,
strength: ((bufferedFactor - 1) * (((_y = (_x = bufferedResult.face[i].rotation) == null ? void 0 : _x.gaze) == null ? void 0 : _y.strength) || 0) + (((_A = (_z = newResult.face[i].rotation) == null ? void 0 : _z.gaze) == null ? void 0 : _A.strength) || 0)) / bufferedFactor
};
bufferedResult.face[i] = { ...newResult.face[i], rotation, box: box4, boxRaw };
bufferedResult.face[i] = { ...newResult.face[i], rotation, box: box5, boxRaw };
}
bufferedResult.face[i] = { ...newResult.face[i], box: box4, boxRaw };
bufferedResult.face[i] = { ...newResult.face[i], box: box5, boxRaw };
}
}
if (!bufferedResult.object || newResult.object.length !== bufferedResult.object.length) {
bufferedResult.object = JSON.parse(JSON.stringify(newResult.object));
} else {
for (let i = 0; i < newResult.object.length; i++) {
const box4 = newResult.object[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].box[j] + b) / bufferedFactor);
const box5 = newResult.object[i].box.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].box[j] + b) / bufferedFactor);
const boxRaw = newResult.object[i].boxRaw.map((b, j) => ((bufferedFactor - 1) * bufferedResult.object[i].boxRaw[j] + b) / bufferedFactor);
bufferedResult.object[i] = { ...newResult.object[i], box: box4, boxRaw };
bufferedResult.object[i] = { ...newResult.object[i], box: box5, boxRaw };
}
}
if (newResult.persons) {
@ -12507,7 +12446,7 @@ function calc2(newResult, config3) {
bufferedResult.persons = JSON.parse(JSON.stringify(newPersons));
} else {
for (let i = 0; i < newPersons.length; i++) {
bufferedResult.persons[i].box = newPersons[i].box.map((box4, j) => ((bufferedFactor - 1) * bufferedResult.persons[i].box[j] + box4) / bufferedFactor);
bufferedResult.persons[i].box = newPersons[i].box.map((box5, j) => ((bufferedFactor - 1) * bufferedResult.persons[i].box[j] + box5) / bufferedFactor);
}
}
}
@ -12598,10 +12537,10 @@ function join2(faces, bodies, hands, gestures, shape) {
}
const x = [];
const y = [];
const extractXY = (box4) => {
if (box4 && box4.length === 4) {
x.push(box4[0], box4[0] + box4[2]);
y.push(box4[1], box4[1] + box4[3]);
const extractXY = (box5) => {
if (box5 && box5.length === 4) {
x.push(box5[0], box5[0] + box5[2]);
y.push(box5[1], box5[1] + box5[3]);
}
};
extractXY((_k = person2.face) == null ? void 0 : _k.box);

57
dist/tfjs.esm.js vendored
View File

@ -4,7 +4,7 @@
author: <https://github.com/vladmandic>'
*/
// node_modules/.pnpm/github.com+vladmandic+tfjs@23eb80be7626f37f74b23351f804509a335f2a55/node_modules/@vladmandic/tfjs/dist/tfjs.esm.js
// node_modules/.pnpm/github.com+vladmandic+tfjs@2127fce0dddf3d77d045441f26e892d4792418f4/node_modules/@vladmandic/tfjs/dist/tfjs.esm.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@ -48697,19 +48697,20 @@ var PackProgram = class {
this.packedInputs = false;
this.packedOutput = true;
this.outputShape = outputShape;
const rank = outputShape.length;
if (rank === 0) {
this.rank = outputShape.length;
this.enableShapeUniforms = useShapeUniforms(this.outputShape.length);
if (this.rank === 0) {
this.userCode = `
void main() {
setOutput(vec4(getA(), 0., 0., 0.));
}
`;
} else {
const channels = getChannels("rc", rank);
const dtype = getCoordsDataType(rank);
const outOfBoundsCondition = getOutOfBoundsCondition(rank, outputShape, channels);
const setup46 = getSetup(rank, outputShape[outputShape.length - 1], outputShape[outputShape.length - 2], channels);
const output = getOutput(outputShape, channels);
const channels = getChannels("rc", this.rank);
const dtype = getCoordsDataType(this.rank);
const outOfBoundsCondition = this.getOutOfBoundsCondition(channels);
const setup46 = this.getSetup(channels);
const output = this.getOutput(channels);
this.userCode = `
void main() {
${dtype} rc = getOutputCoords();
@ -48725,13 +48726,12 @@ var PackProgram = class {
`;
}
}
};
function getSourceCoordsArr(rank, dims) {
getSourceCoordsArr(dims) {
const coords3 = [];
for (let row = 0; row <= 1; row++) {
for (let col = 0; col <= 1; col++) {
let coord = `${row === 0 ? "r" : "rp1"}, ${col === 0 ? "c" : "cp1"}`;
for (let d = 2; d < rank; d++) {
for (let d = 2; d < this.rank; d++) {
coord = `${dims[dims.length - 1 - d]},` + coord;
}
coords3.push(coord);
@ -48739,40 +48739,41 @@ function getSourceCoordsArr(rank, dims) {
}
return coords3;
}
function getOutOfBoundsCondition(rank, shape, dims) {
if (rank === 1) {
return `rc > ${shape[0]}`;
getOutOfBoundsCondition(dims) {
if (this.rank === 1) {
return `rc > ${this.enableShapeUniforms ? "outShape" : this.outputShape[0]}`;
}
let cond = "";
for (let i = rank - 2; i < rank; i++) {
cond += `${dims[i]} >= ${shape[i]}`;
if (i < rank - 1) {
for (let i = this.rank - 2; i < this.rank; i++) {
cond += `${dims[i]} >= ${this.enableShapeUniforms ? `outShape[${i}]` : this.outputShape[i]}`;
if (i < this.rank - 1) {
cond += "||";
}
}
return cond;
}
function getSetup(rank, cols, rows, dims) {
if (rank === 1) {
getSetup(dims) {
if (this.rank === 1) {
return "";
}
const innerDims = dims.slice(-2);
const col = this.enableShapeUniforms ? `outShape[${this.rank} - 1]` : this.outputShape[this.rank - 1];
const row = this.enableShapeUniforms ? `outShape[${this.rank} - 2]` : this.outputShape[this.rank - 2];
return `
int r = ${innerDims[0]};
int c = ${innerDims[1]};
int rp1 = r + 1;
int cp1 = c + 1;
bool cEdge = cp1 >= ${cols};
bool rEdge = rp1 >= ${rows};
bool cEdge = cp1 >= ${col};
bool rEdge = rp1 >= ${row};
`;
}
function getOutput(shape, dims) {
const rank = shape.length;
const sourceCoords = getSourceCoordsArr(rank, dims);
if (rank === 1) {
getOutput(dims) {
const sourceCoords = this.getSourceCoordsArr(dims);
if (this.rank === 1) {
return `getA(rc),
rc + 1 >= ${shape[0]} ? 0. : getA(rc + 1),
rc + 1 >= ${this.enableShapeUniforms ? "outShape" : this.outputShape[0]} ? 0. : getA(rc + 1),
0, 0`;
}
return `getA(${sourceCoords[0]}),
@ -48780,6 +48781,7 @@ function getOutput(shape, dims) {
rEdge ? 0. : getA(${sourceCoords[2]}),
rEdge || cEdge ? 0. : getA(${sourceCoords[3]})`;
}
};
var ReshapePackedProgram = class {
constructor(outputShape, inputShape) {
this.variableNames = ["A"];
@ -49122,6 +49124,7 @@ var UnpackProgram = class {
this.packedInputs = true;
this.packedOutput = false;
this.outputShape = outputShape;
this.enableShapeUniforms = useShapeUniforms(this.outputShape.length);
const rank = outputShape.length;
const channels = getChannels("rc", rank);
const dtype = getCoordsDataType(rank);
@ -69967,7 +69970,7 @@ registerBackend("wasm", async () => {
const { wasm } = await init();
return new BackendWasm(wasm);
}, WASM_PRIORITY);
var externalVersion = "3.11.0-20211123";
var externalVersion = "3.11.0-20211124";
var version8 = {
tfjs: externalVersion,
"tfjs-core": externalVersion,

View File

@ -65,7 +65,7 @@
"@tensorflow/tfjs-layers": "^3.11.0",
"@tensorflow/tfjs-node": "^3.11.0",
"@tensorflow/tfjs-node-gpu": "^3.11.0",
"@types/node": "^16.11.9",
"@types/node": "^16.11.10",
"@types/offscreencanvas": "^2019.6.4",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",

View File

@ -10,8 +10,7 @@ import type { GraphModel, Tensor } from '../tfjs/types';
import type { Config } from '../config';
import * as coords from './blazeposecoords';
import * as detect from './blazeposedetector';
interface DetectedBox { box: Box, boxRaw: Box, score: number }
import * as box from '../util/box';
const env = { initial: true };
// const models: [GraphModel | null, GraphModel | null] = [null, null];
@ -24,7 +23,7 @@ const outputNodes: { detector: string[], landmarks: string[] } = {
};
let cache: BodyResult | null = null;
let lastBox: Box | undefined;
let cropBox: Box | undefined;
let padding: [number, number][] = [[0, 0], [0, 0], [0, 0], [0, 0]];
let lastTime = 0;
@ -63,50 +62,43 @@ export async function load(config: Config): Promise<[GraphModel | null, GraphMod
return [models.detector, models.landmarks];
}
function calculateBoxes(keypoints: Array<BodyKeypoint>, outputSize: [number, number]): { keypointsBox: Box, keypointsBoxRaw: Box } {
const x = keypoints.map((a) => a.position[0]);
const y = keypoints.map((a) => a.position[1]);
const keypointsBox: Box = [Math.min(...x), Math.min(...y), Math.max(...x) - Math.min(...x), Math.max(...y) - Math.min(...y)];
const keypointsBoxRaw: Box = [keypointsBox[0] / outputSize[0], keypointsBox[1] / outputSize[1], keypointsBox[2] / outputSize[0], keypointsBox[3] / outputSize[1]];
return { keypointsBox, keypointsBoxRaw };
}
async function prepareImage(input: Tensor, size: number, box?: Box): Promise<Tensor> {
async function prepareImage(input: Tensor, size: number): Promise<Tensor> {
const t: Record<string, Tensor> = {};
if (!input.shape || !input.shape[1] || !input.shape[2]) return input;
let final: Tensor;
if (cropBox) {
t.cropped = tf.image.cropAndResize(input, [cropBox], [0], [input.shape[1], input.shape[2]]); // if we have cached box use it to crop input
}
if (input.shape[1] !== input.shape[2]) { // only pad if width different than height
const height: [number, number] = box
? [Math.trunc(input.shape[1] * box[1]), Math.trunc(input.shape[1] * (box[1] + box[3]))]
: [input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0, input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0];
const width: [number, number] = box
? [Math.trunc(input.shape[2] * box[0]), Math.trunc(input.shape[2] * (box[0] + box[2]))]
: [input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0, input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0];
const height: [number, number] = [
input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0,
input.shape[2] > input.shape[1] ? Math.trunc((input.shape[2] - input.shape[1]) / 2) : 0,
];
const width: [number, number] = [
input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0,
input.shape[1] > input.shape[2] ? Math.trunc((input.shape[1] - input.shape[2]) / 2) : 0,
];
padding = [
[0, 0], // dont touch batch
height, // height before&after
width, // width before&after
[0, 0], // dont touch rbg
];
if (box) {
t.resize = tf.image.cropAndResize(input, [box], [0], [size, size]);
} else {
t.pad = tf.pad(input, padding);
t.pad = tf.pad(t.cropped || input, padding); // use cropped box if it exists
t.resize = tf.image.resizeBilinear(t.pad, [size, size]);
}
final = tf.div(t.resize, constants.tf255);
} else if (input.shape[1] !== size) { // if input needs resizing
t.resize = tf.image.resizeBilinear(input, [size, size]);
t.resize = tf.image.resizeBilinear(t.cropped || input, [size, size]);
final = tf.div(t.resize, constants.tf255);
} else { // if input is already in a correct resolution just normalize it
final = tf.div(input, constants.tf255);
final = tf.div(t.cropped || input, constants.tf255);
}
Object.keys(t).forEach((tensor) => tf.dispose(t[tensor]));
return final;
}
function rescaleKeypoints(keypoints: Array<BodyKeypoint>, outputSize: [number, number]): Array<BodyKeypoint> {
for (const kpt of keypoints) {
for (const kpt of keypoints) { // first rescale due to padding
kpt.position = [
Math.trunc(kpt.position[0] * (outputSize[0] + padding[2][0] + padding[2][1]) / outputSize[0] - padding[2][0]),
Math.trunc(kpt.position[1] * (outputSize[1] + padding[1][0] + padding[1][1]) / outputSize[1] - padding[1][0]),
@ -114,20 +106,21 @@ function rescaleKeypoints(keypoints: Array<BodyKeypoint>, outputSize: [number, n
];
kpt.positionRaw = [kpt.position[0] / outputSize[0], kpt.position[1] / outputSize[1], kpt.position[2] as number];
}
return keypoints;
}
function rescaleBoxes(boxes: Array<DetectedBox>, outputSize: [number, number]): Array<DetectedBox> {
for (const box of boxes) {
box.box = [
Math.trunc(box.box[0] * (outputSize[0] + padding[2][0] + padding[2][1]) / outputSize[0]),
Math.trunc(box.box[1] * (outputSize[1] + padding[1][0] + padding[1][1]) / outputSize[1]),
Math.trunc(box.box[2] * (outputSize[0] + padding[2][0] + padding[2][1]) / outputSize[0]),
Math.trunc(box.box[3] * (outputSize[1] + padding[1][0] + padding[1][1]) / outputSize[1]),
if (cropBox) { // second rescale due to cropping
for (const kpt of keypoints) {
kpt.positionRaw = [
kpt.positionRaw[0] + cropBox[1], // correct offset due to crop
kpt.positionRaw[1] + cropBox[0], // correct offset due to crop
kpt.positionRaw[2] as number,
];
kpt.position = [
Math.trunc(kpt.positionRaw[0] * outputSize[0]),
Math.trunc(kpt.positionRaw[1] * outputSize[1]),
kpt.positionRaw[2] as number,
];
box.boxRaw = [box.box[0] / outputSize[0], box.box[1] / outputSize[1], box.box[2] / outputSize[0], box.box[3] / outputSize[1]];
}
return boxes;
}
return keypoints;
}
async function detectLandmarks(input: Tensor, config: Config, outputSize: [number, number]): Promise<BodyResult | null> {
@ -155,22 +148,38 @@ async function detectLandmarks(input: Tensor, config: Config, outputSize: [numbe
}
if (poseScore < (config.body.minConfidence || 0)) return null;
const keypoints: Array<BodyKeypoint> = rescaleKeypoints(keypointsRelative, outputSize); // keypoints were relative to input image which is padded
const boxes = calculateBoxes(keypoints, [outputSize[0], outputSize[1]]); // now find boxes based on rescaled keypoints
const kpts = keypoints.map((k) => k.position);
const boxes = box.calc(kpts, [outputSize[0], outputSize[1]]); // now find boxes based on rescaled keypoints
const annotations: Record<string, Point[][]> = {};
for (const [name, indexes] of Object.entries(coords.connected)) {
const pt: Array<Point[]> = [];
for (let i = 0; i < indexes.length - 1; i++) {
const pt0 = keypoints.find((kpt) => kpt.part === indexes[i]);
const pt1 = keypoints.find((kpt) => kpt.part === indexes[i + 1]);
// if (pt0 && pt1 && pt0.score > (config.body.minConfidence || 0) && pt1.score > (config.body.minConfidence || 0)) pt.push([pt0.position, pt1.position]);
if (pt0 && pt1) pt.push([pt0.position, pt1.position]);
}
annotations[name] = pt;
}
const body = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.keypointsBox, boxRaw: boxes.keypointsBoxRaw, keypoints, annotations };
const body = { id: 0, score: Math.trunc(100 * poseScore) / 100, box: boxes.box, boxRaw: boxes.boxRaw, keypoints, annotations };
return body;
}
/*
interface DetectedBox { box: Box, boxRaw: Box, score: number }
function rescaleBoxes(boxes: Array<DetectedBox>, outputSize: [number, number]): Array<DetectedBox> {
for (const b of boxes) {
b.box = [
Math.trunc(b.box[0] * (outputSize[0] + padding[2][0] + padding[2][1]) / outputSize[0]),
Math.trunc(b.box[1] * (outputSize[1] + padding[1][0] + padding[1][1]) / outputSize[1]),
Math.trunc(b.box[2] * (outputSize[0] + padding[2][0] + padding[2][1]) / outputSize[0]),
Math.trunc(b.box[3] * (outputSize[1] + padding[1][0] + padding[1][1]) / outputSize[1]),
];
b.boxRaw = [b.box[0] / outputSize[0], b.box[1] / outputSize[1], b.box[2] / outputSize[0], b.box[3] / outputSize[1]];
}
return boxes;
}
async function detectBoxes(input: Tensor, config: Config, outputSize: [number, number]) {
const t: Record<string, Tensor> = {};
t.res = models.detector?.execute(input, ['Identity']) as Tensor; //
@ -183,6 +192,7 @@ async function detectBoxes(input: Tensor, config: Config, outputSize: [number, n
Object.keys(t).forEach((tensor) => tf.dispose(t[tensor]));
return boxes;
}
*/
export async function predict(input: Tensor, config: Config): Promise<BodyResult[]> {
const outputSize: [number, number] = [input.shape[2] || 0, input.shape[1] || 0];
@ -192,33 +202,31 @@ export async function predict(input: Tensor, config: Config): Promise<BodyResult
skipped++;
} else {
const t: Record<string, Tensor> = {};
/*
if (config.body['detector'] && config.body['detector']['enabled']) {
t.detector = await prepareImage(input, 224);
const boxes = await detectBoxes(t.detector, config, outputSize);
if (boxes && boxes.length === 1) {
t.landmarks = await prepareImage(input, 256, boxes[0].box); // padded and resized according to detector
cache = await detectLandmarks(t.landmarks, config, outputSize);
}
if (cache) cache.score = boxes[0].score;
} else {
t.landmarks = await prepareImage(input, 256, lastBox); // padded and resized
cache = await detectLandmarks(t.landmarks, config, outputSize);
/*
lastBox = undefined;
if (cache?.box) {
const cx = cache.boxRaw[0] + (cache.boxRaw[2] / 2);
const cy = cache.boxRaw[1] + (cache.boxRaw[3] / 2);
let size = cache.boxRaw[2] > cache.boxRaw[3] ? cache.boxRaw[2] : cache.boxRaw[3];
size = (size * 1.2) / 2; // enlarge and half it
lastBox = [cx - size, cy - size, 2 * size, 2 * size];
}
*/
t.landmarks = await prepareImage(input, 256); // padded and resized
cache = await detectLandmarks(t.landmarks, config, outputSize);
/*
cropBox = [0, 0, 1, 1]; // reset crop coordinates
if (cache?.boxRaw && config.skipAllowed) {
const cx = (2.0 * cache.boxRaw[0] + cache.boxRaw[2]) / 2;
const cy = (2.0 * cache.boxRaw[1] + cache.boxRaw[3]) / 2;
let size = cache.boxRaw[2] > cache.boxRaw[3] ? cache.boxRaw[2] : cache.boxRaw[3];
size = (size * 1.0) / 2; // enlarge and half it
if (cx > 0.1 && cx < 0.9 && cy > 0.1 && cy < 0.9 && size > 0.1) { // only update if box is sane
const y = 0; // cy - size;
const x = cx - size;
cropBox = [y, x, y + 1, x + 1]; // [y0,x0,y1,x1] used for cropping but width/height are not yet implemented so we only reposition image to center of body
}
}
*/
Object.keys(t).forEach((tensor) => tf.dispose(t[tensor]));
// if (cache && boxes.length > 0) cache.box = boxes[0].box;
lastTime = now();
skipped = 0;
}
if (cache) return [cache];
return [];
return cache ? [cache] : [];
}

View File

@ -78,7 +78,7 @@ export const calculateFaceAngle = (face, imageSize): {
if (isNaN(thetaX)) thetaX = 0;
if (isNaN(thetaY)) thetaY = 0;
if (isNaN(thetaZ)) thetaZ = 0;
return { pitch: 2 * -thetaX, yaw: 2 * -thetaY, roll: 2 * -thetaZ };
return { pitch: -thetaX, yaw: -thetaY, roll: -thetaZ };
};
// simple Euler angle calculation based existing 3D mesh
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars

View File

@ -51,11 +51,11 @@ const cache: {
};
const fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
middle: [9, 10, 11, 12],
ring: [13, 14, 15, 16],
pinky: [17, 18, 19, 20],
thumb: [0, 1, 2, 3, 4],
index: [0, 5, 6, 7, 8],
middle: [0, 9, 10, 11, 12],
ring: [0, 13, 14, 15, 16],
pinky: [0, 17, 18, 19, 20],
palm: [0],
};

View File

@ -1,25 +1,25 @@
2021-11-23 10:21:50 INFO:  Application: {"name":"@vladmandic/human","version":"2.5.4"}
2021-11-23 10:21:50 INFO:  Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
2021-11-23 10:21:50 INFO:  Toolchain: {"build":"0.6.4","esbuild":"0.13.15","typescript":"4.5.2","typedoc":"0.22.9","eslint":"8.3.0"}
2021-11-23 10:21:50 INFO:  Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
2021-11-23 10:21:50 STATE: Clean: {"locations":["dist/*","types/lib/*","typedoc/*"]}
2021-11-23 10:21:50 STATE: Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":102,"outputBytes":1275}
2021-11-23 10:21:50 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":63,"inputBytes":556638,"outputBytes":468195}
2021-11-23 10:21:50 STATE: Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":1283}
2021-11-23 10:21:50 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":63,"inputBytes":556646,"outputBytes":468199}
2021-11-23 10:21:50 STATE: Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":149,"outputBytes":1350}
2021-11-23 10:21:50 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":63,"inputBytes":556713,"outputBytes":468271}
2021-11-23 10:21:50 STATE: Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1063,"outputBytes":1652}
2021-11-23 10:21:50 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":2326,"outputBytes":912}
2021-11-23 10:21:50 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":63,"inputBytes":556275,"outputBytes":470281}
2021-11-23 10:21:51 STATE: Compile: {"name":"tfjs/browser/esm/custom","format":"esm","platform":"browser","input":"tfjs/tf-custom.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":2500868}
2021-11-23 10:21:51 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":63,"inputBytes":3056231,"outputBytes":1627483}
2021-11-23 10:21:51 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":63,"inputBytes":3056231,"outputBytes":2977445}
2021-11-23 10:22:12 STATE: Typings: {"input":"src/human.ts","output":"types/lib","files":110}
2021-11-23 10:22:12 WARN:  You are running with an unsupported TypeScript version! TypeDoc supports 4.0, 4.1, 4.2, 4.3, 4.4
2021-11-23 10:22:20 STATE: TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":52,"generated":true}
2021-11-23 10:22:20 STATE: Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":5866,"outputBytes":4127}
2021-11-23 10:22:20 STATE: Compile: {"name":"demo/faceid","format":"esm","platform":"browser","input":"demo/faceid/index.ts","output":"demo/faceid/index.js","files":2,"inputBytes":15174,"outputBytes":11794}
2021-11-23 10:23:03 STATE: Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":94,"errors":0,"warnings":0}
2021-11-23 10:23:04 STATE: ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
2021-11-23 10:23:04 INFO:  Done...
2021-11-24 16:12:45 INFO:  Application: {"name":"@vladmandic/human","version":"2.5.4"}
2021-11-24 16:12:45 INFO:  Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
2021-11-24 16:12:45 INFO:  Toolchain: {"build":"0.6.4","esbuild":"0.13.15","typescript":"4.5.2","typedoc":"0.22.9","eslint":"8.3.0"}
2021-11-24 16:12:45 INFO:  Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
2021-11-24 16:12:45 STATE: Clean: {"locations":["dist/*","types/lib/*","typedoc/*"]}
2021-11-24 16:12:45 STATE: Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":102,"outputBytes":1275}
2021-11-24 16:12:45 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":63,"inputBytes":556369,"outputBytes":464672}
2021-11-24 16:12:45 STATE: Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":1283}
2021-11-24 16:12:45 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":63,"inputBytes":556377,"outputBytes":464676}
2021-11-24 16:12:45 STATE: Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":149,"outputBytes":1350}
2021-11-24 16:12:45 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":63,"inputBytes":556444,"outputBytes":464748}
2021-11-24 16:12:45 STATE: Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1063,"outputBytes":1652}
2021-11-24 16:12:45 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":2326,"outputBytes":912}
2021-11-24 16:12:45 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":63,"inputBytes":556006,"outputBytes":466434}
2021-11-24 16:12:46 STATE: Compile: {"name":"tfjs/browser/esm/custom","format":"esm","platform":"browser","input":"tfjs/tf-custom.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":2501333}
2021-11-24 16:12:46 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":63,"inputBytes":3056427,"outputBytes":1626393}
2021-11-24 16:12:47 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":63,"inputBytes":3056427,"outputBytes":2974514}
2021-11-24 16:13:08 STATE: Typings: {"input":"src/human.ts","output":"types/lib","files":110}
2021-11-24 16:13:08 WARN:  You are running with an unsupported TypeScript version! TypeDoc supports 4.0, 4.1, 4.2, 4.3, 4.4
2021-11-24 16:13:16 STATE: TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":52,"generated":true}
2021-11-24 16:13:16 STATE: Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":5864,"outputBytes":4127}
2021-11-24 16:13:16 STATE: Compile: {"name":"demo/faceid","format":"esm","platform":"browser","input":"demo/faceid/index.ts","output":"demo/faceid/index.js","files":2,"inputBytes":15174,"outputBytes":11794}
2021-11-24 16:13:55 STATE: Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":94,"errors":0,"warnings":0}
2021-11-24 16:13:55 STATE: ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
2021-11-24 16:13:55 INFO:  Done...

File diff suppressed because it is too large Load Diff