redo segmentation and handtracking

pull/193/head
Vladimir Mandic 2021-09-22 15:16:14 -04:00
parent a0acff62f2
commit a7970afd0c
33 changed files with 1587 additions and 1311 deletions

View File

@ -9,7 +9,10 @@
## Changelog
### **HEAD -> main** 2021/09/20 mandic00@live.com
### **HEAD -> main** 2021/09/21 mandic00@live.com
### **origin/main** 2021/09/20 mandic00@live.com
- support for dynamic backend switching
- initial automated browser tests

View File

@ -35,7 +35,7 @@
.video { display: none; }
.canvas { margin: 0 auto; }
.bench { position: absolute; right: 0; bottom: 0; }
.compare-image { width: 200px; position: absolute; top: 150px; left: 30px; box-shadow: 0 0 2px 2px black; background: black; display: none; }
.compare-image { width: 256px; position: absolute; top: 150px; left: 30px; box-shadow: 0 0 2px 2px black; background: black; display: none; }
.loader { width: 300px; height: 300px; border: 3px solid transparent; border-radius: 50%; border-top: 4px solid #f15e41; animation: spin 4s linear infinite; position: absolute; bottom: 15%; left: 50%; margin-left: -150px; z-index: 15; }
.loader::before, .loader::after { content: ""; position: absolute; top: 6px; bottom: 6px; left: 6px; right: 6px; border-radius: 50%; border: 4px solid transparent; }
.loader::before { border-top-color: #bad375; animation: 3s spin linear infinite; }
@ -107,9 +107,13 @@
<video id="video" playsinline class="video"></video>
</div>
<div id="compare-container" class="compare-image">
<canvas id="compare-canvas" width="200" height="200"></canvas>
<canvas id="compare-canvas" width="256" height="256"></canvas>
<div id="similarity"></div>
</div>
<div id="segmentation-container" class="compare-image">
<canvas id="segmentation-mask" width="256" height="256" style="width: 256px; height: 256px;"></canvas>
<canvas id="segmentation-canvas" width="256" height="256" style="width: 256px; height: 256px;"></canvas>
</div>
<div id="samples-container" class="samples-container"></div>
<div id="hint" class="hint"></div>
<div id="log" class="log"></div>

View File

@ -51,8 +51,8 @@ let userConfig = {
},
object: { enabled: false },
gesture: { enabled: true },
// hand: { enabled: true, landmarks: false, maxDetected: 3, minConfidence: 0.1 },
hand: { enabled: true, maxDetected: 3, minConfidence: 0.3, detector: { modelPath: 'handtrack.json' } },
hand: { enabled: false },
// hand: { enabled: true, maxDetected: 1, minConfidence: 0.5, detector: { modelPath: 'handtrack.json' } },
body: { enabled: false },
// body: { enabled: true, modelPath: 'movenet-multipose.json' },
// body: { enabled: true, modelPath: 'posenet.json' },
@ -241,8 +241,20 @@ async function drawResults(input) {
// draw fps chart
await menu.process.updateChart('FPS', ui.detectFPS);
document.getElementById('segmentation-container').style.display = userConfig.segmentation.enabled ? 'block' : 'none';
if (userConfig.segmentation.enabled && ui.buffered) { // refresh segmentation if using buffered output
result.canvas = await human.segmentation(input, ui.background, userConfig);
const seg = await human.segmentation(input, ui.background);
if (seg.alpha) {
let c = document.getElementById('segmentation-mask');
let ctx = c.getContext('2d');
ctx.clearRect(0, 0, c.width, c.height); // need to clear as seg.alpha is alpha based canvas so it adds
ctx.drawImage(seg.alpha, 0, 0, seg.alpha.width, seg.alpha.height, 0, 0, c.width, c.height);
c = document.getElementById('segmentation-canvas');
ctx = c.getContext('2d');
ctx.clearRect(0, 0, c.width, c.height); // need to clear as seg.alpha is alpha based canvas so it adds
ctx.drawImage(seg.canvas, 0, 0, seg.alpha.width, seg.alpha.height, 0, 0, c.width, c.height);
}
// result.canvas = seg.alpha;
} else if (!result.canvas || ui.buffered) { // refresh with input if using buffered output or if missing canvas
const image = await human.image(input);
result.canvas = image.canvas;
@ -825,14 +837,14 @@ async function processDataURL(f, action) {
if (document.getElementById('canvas').style.display === 'block') { // replace canvas used for video
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const overlaid = await human.segmentation(canvas, ui.background, userConfig);
if (overlaid) ctx.drawImage(overlaid, 0, 0);
const seg = await human.segmentation(canvas, ui.background, userConfig);
if (seg.canvas) ctx.drawImage(seg.canvas, 0, 0);
} else {
const canvases = document.getElementById('samples-container').children; // replace loaded images
for (const canvas of canvases) {
const ctx = canvas.getContext('2d');
const overlaid = await human.segmentation(canvas, ui.background, userConfig);
if (overlaid) ctx.drawImage(overlaid, 0, 0);
const seg = await human.segmentation(canvas, ui.background, userConfig);
if (seg.canvas) ctx.drawImage(seg.canvas, 0, 0);
}
}
};

View File

@ -14,6 +14,8 @@
<link rel="apple-touch-icon" href="../../assets/icon.png">
<script src="./index.js" type="module"></script>
<style>
@font-face { font-family: 'Lato'; font-display: swap; font-style: normal; font-weight: 100; src: local('Lato'), url('../assets/lato-light.woff2') }
html { font-family: 'Lato', 'Segoe UI'; font-size: 16px; font-variant: small-caps; }
body { margin: 0; background: black; color: white; overflow-x: hidden; width: 100vw; height: 100vh; text-align: center; }
body::-webkit-scrollbar { display: none; }
</style>
@ -21,5 +23,6 @@
<body>
<canvas id="canvas" style="margin: 0 auto"></canvas>
<video id="video" playsinline style="display: none"></video>
<div id="fps" style="position: absolute; top: 20px; right: 20px; background-color: grey; padding: 8px"></div>
</body>
</html>

View File

@ -10,9 +10,10 @@
import Human from '../../dist/human.esm.js'; // equivalent of @vladmandic/human
import webRTC from '../helpers/webrtc.js'; // handle webrtc handshake and connects to webrtc stream
const config = { // use default values
const config = { // use default values for everything just specify models location
modelBasePath: '../../models',
};
const human = new Human(config);
const webrtc = {
@ -30,6 +31,9 @@ const video = document.getElementById('video') || document.createElement('video'
/** @type {HTMLCanvasElement} */
// @ts-ignore
const canvas = document.getElementById('canvas') || document.createElement('canvas'); // used as output
// @ts-ignore
const fps = { detect: 0, draw: 0 };
fps.el = document.getElementById('fps') || document.createElement('div'); // used as draw fps counter
async function webCam() {
const constraints = { audio: false, video: { facingMode: 'user', resizeMode: 'none', width: { ideal: document.body.clientWidth } } }; // set preffered camera options
@ -41,30 +45,47 @@ async function webCam() {
canvas.width = video.videoWidth; // resize output canvas to match input
canvas.height = video.videoHeight;
log('video stream:', video.srcObject, 'track state:', video.srcObject.getVideoTracks()[0].readyState, 'stream state:', video.readyState);
canvas.onclick = () => { // play or pause on mouse click
if (video.paused) video.play();
else video.pause();
};
}
// eslint-disable-next-line no-unused-vars
let result;
async function detectionLoop() {
result = await human.detect(video); // updates result every time detection completes
const t0 = performance.now();
if (!video.paused) result = await human.detect(video); // updates result every time detection completes, skip if video is paused
const t1 = performance.now();
fps.detect = 1000 / (t1 - t0);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
requestAnimationFrame(detectionLoop); // run in loop
}
// eslint-disable-next-line no-unused-vars
async function drawLoop() {
const interpolated = await human.next(result); // interpolates results based on last known results
await human.draw.canvas(video, canvas); // draw input video to output canvas
await human.draw.all(canvas, interpolated); // draw results as overlay on output canvas
const t0 = performance.now();
if (!video.paused) { // skip redraw if video is paused
const interpolated = await human.next(result); // interpolates results based on last known results
await human.draw.canvas(video, canvas); // draw input video to output canvas
await human.draw.all(canvas, interpolated); // draw results as overlay on output canvas
}
const t1 = performance.now();
fps.draw = 1000 / (t1 - t0);
fps.el.innerText = video.paused ? 'paused' : `${fps.detect.toFixed(1)} / ${fps.draw.toFixed(1)}`;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
requestAnimationFrame(drawLoop); // run in loop
}
// eslint-disable-next-line no-unused-vars
async function singleLoop() {
const t0 = performance.now();
result = await human.detect(video); // updates result every time detection completes
await human.draw.canvas(video, canvas); // draw input video to output canvas
await human.draw.all(canvas, result); // draw results as overlay on output canvas
const t1 = performance.now();
fps.detect = 1000 / (t1 - t0);
fps.el.innerText = video.paused ? 'paused' : `${fps.detect.toFixed(1)}`;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
requestAnimationFrame(singleLoop); // run in loop
}

View File

@ -201,7 +201,8 @@ var config = {
},
segmentation: {
enabled: false,
modelPath: "selfie.json"
modelPath: "selfie.json",
blur: 8
}
};
@ -256,13 +257,13 @@ function getBoxCenter(box6) {
function cutBoxFromImageAndResize(box6, image23, cropSize) {
const h = image23.shape[1];
const w = image23.shape[2];
const boxes2 = [[
const boxes = [[
box6.startPoint[1] / h,
box6.startPoint[0] / w,
box6.endPoint[1] / h,
box6.endPoint[0] / w
]];
return tfjs_esm_exports.image.cropAndResize(image23, boxes2, [0], cropSize);
return tfjs_esm_exports.image.cropAndResize(image23, boxes, [0], cropSize);
}
function enlargeBox(box6, factor = 1.5) {
const center = getBoxCenter(box6);
@ -412,7 +413,7 @@ var BlazeFaceModel = class {
var _a, _b, _c, _d;
if (!inputImage || inputImage["isDisposedInternal"] || inputImage.shape.length !== 4 || inputImage.shape[1] < 1 || inputImage.shape[2] < 1)
return { boxes: [] };
const [batch, boxes2, scores] = tfjs_esm_exports.tidy(() => {
const [batch, boxes, scores] = tfjs_esm_exports.tidy(() => {
const resizedImage = tfjs_esm_exports.image.resizeBilinear(inputImage, [this.inputSize, this.inputSize]);
const normalizedImage = tfjs_esm_exports.sub(tfjs_esm_exports.div(resizedImage, 127.5), 0.5);
const res = this.model.execute(normalizedImage);
@ -432,7 +433,7 @@ var BlazeFaceModel = class {
return [batchOut, boxesOut, scoresOut];
});
this.config = mergeDeep(this.config, userConfig);
const nmsTensor = await tfjs_esm_exports.image.nonMaxSuppressionAsync(boxes2, scores, ((_a = this.config.face.detector) == null ? void 0 : _a.maxDetected) || 0, ((_b = this.config.face.detector) == null ? void 0 : _b.iouThreshold) || 0, ((_c = this.config.face.detector) == null ? void 0 : _c.minConfidence) || 0);
const nmsTensor = await tfjs_esm_exports.image.nonMaxSuppressionAsync(boxes, scores, ((_a = this.config.face.detector) == null ? void 0 : _a.maxDetected) || 0, ((_b = this.config.face.detector) == null ? void 0 : _b.iouThreshold) || 0, ((_c = this.config.face.detector) == null ? void 0 : _c.minConfidence) || 0);
const nms = await nmsTensor.array();
tfjs_esm_exports.dispose(nmsTensor);
const annotatedBoxes = [];
@ -440,14 +441,14 @@ var BlazeFaceModel = class {
for (let i = 0; i < nms.length; i++) {
const confidence = scoresData[nms[i]];
if (confidence > (((_d = this.config.face.detector) == null ? void 0 : _d.minConfidence) || 0)) {
const boundingBox = tfjs_esm_exports.slice(boxes2, [nms[i], 0], [1, -1]);
const boundingBox = tfjs_esm_exports.slice(boxes, [nms[i], 0], [1, -1]);
const landmarks = tfjs_esm_exports.tidy(() => tfjs_esm_exports.reshape(tfjs_esm_exports.squeeze(tfjs_esm_exports.slice(batch, [nms[i], keypointsCount - 1], [1, -1])), [keypointsCount, -1]));
annotatedBoxes.push({ box: createBox(boundingBox), landmarks, anchor: this.anchorsData[nms[i]], confidence });
tfjs_esm_exports.dispose(boundingBox);
}
}
tfjs_esm_exports.dispose(batch);
tfjs_esm_exports.dispose(boxes2);
tfjs_esm_exports.dispose(boxes);
tfjs_esm_exports.dispose(scores);
return {
boxes: annotatedBoxes,
@ -5625,13 +5626,13 @@ function getBoxCenter2(box6) {
function cutBoxFromImageAndResize2(box6, image23, cropSize) {
const h = image23.shape[1];
const w = image23.shape[2];
const boxes2 = [[
const boxes = [[
box6.startPoint[1] / h,
box6.startPoint[0] / w,
box6.endPoint[1] / h,
box6.endPoint[0] / w
]];
return tfjs_esm_exports.image.cropAndResize(image23, boxes2, [0], cropSize);
return tfjs_esm_exports.image.cropAndResize(image23, boxes, [0], cropSize);
}
function scaleBoxCoordinates2(box6, factor) {
const startPoint = [box6.startPoint[0] * factor[0], box6.startPoint[1] * factor[1]];
@ -8624,10 +8625,10 @@ var HandDetector = class {
this.inputSizeTensor = tfjs_esm_exports.tensor1d([this.inputSize, this.inputSize]);
this.doubleInputSizeTensor = tfjs_esm_exports.tensor1d([this.inputSize * 2, this.inputSize * 2]);
}
normalizeBoxes(boxes2) {
normalizeBoxes(boxes) {
return tfjs_esm_exports.tidy(() => {
const boxOffsets = tfjs_esm_exports.slice(boxes2, [0, 0], [-1, 2]);
const boxSizes = tfjs_esm_exports.slice(boxes2, [0, 2], [-1, 2]);
const boxOffsets = tfjs_esm_exports.slice(boxes, [0, 0], [-1, 2]);
const boxSizes = tfjs_esm_exports.slice(boxes, [0, 2], [-1, 2]);
const boxCenterPoints = tfjs_esm_exports.add(tfjs_esm_exports.div(boxOffsets, this.inputSizeTensor), this.anchorsTensor);
const halfBoxSizes = tfjs_esm_exports.div(boxSizes, this.doubleInputSizeTensor);
const startPoints = tfjs_esm_exports.mul(tfjs_esm_exports.sub(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
@ -8671,9 +8672,9 @@ var HandDetector = class {
if (!predictions || predictions.length === 0)
return hands;
for (const prediction of predictions) {
const boxes2 = await prediction.box.data();
const startPoint = boxes2.slice(0, 2);
const endPoint = boxes2.slice(2, 4);
const boxes = await prediction.box.data();
const startPoint = boxes.slice(0, 2);
const endPoint = boxes.slice(2, 4);
const palmLandmarks = await prediction.palmLandmarks.array();
tfjs_esm_exports.dispose(prediction.box);
tfjs_esm_exports.dispose(prediction.palmLandmarks);
@ -8815,16 +8816,16 @@ var HandPipeline = class {
}
async estimateHands(image23, config3) {
let useFreshBox = false;
let boxes2;
let boxes;
if (this.skipped === 0 || this.skipped > config3.hand.skipFrames || !config3.hand.landmarks || !config3.skipFrame) {
boxes2 = await this.handDetector.estimateHandBounds(image23, config3);
boxes = await this.handDetector.estimateHandBounds(image23, config3);
this.skipped = 0;
}
if (config3.skipFrame)
this.skipped++;
if (boxes2 && boxes2.length > 0 && (boxes2.length !== this.detectedHands && this.detectedHands !== config3.hand.maxDetected || !config3.hand.landmarks)) {
if (boxes && boxes.length > 0 && (boxes.length !== this.detectedHands && this.detectedHands !== config3.hand.maxDetected || !config3.hand.landmarks)) {
this.detectedHands = 0;
this.storedBoxes = [...boxes2];
this.storedBoxes = [...boxes];
if (this.storedBoxes.length > 0)
useFreshBox = true;
}
@ -9376,7 +9377,7 @@ async function load6(config3) {
// src/handtrack/handtrack.ts
var models = [null, null];
var modelOutputNodes = ["StatefulPartitionedCall/Postprocessor/Slice", "StatefulPartitionedCall/Postprocessor/ExpandDims_1"];
var inputSize = [0, 0];
var inputSize = [[0, 0], [0, 0]];
var classes = [
"hand",
"fist",
@ -9388,7 +9389,11 @@ var classes = [
];
var skipped3 = 0;
var outputSize;
var boxes = [];
var cache = {
handBoxes: [],
fingerBoxes: [],
tmpBoxes: []
};
var fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
@ -9406,7 +9411,8 @@ async function load7(config3) {
if (!models[0]) {
models[0] = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""));
const inputs = Object.values(models[0].modelSignature["inputs"]);
inputSize[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[0][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[0][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[0] || !models[0]["modelUrl"])
log("load model failed:", config3.object.modelPath);
else if (config3.debug)
@ -9416,7 +9422,8 @@ async function load7(config3) {
if (!models[1]) {
models[1] = await tfjs_esm_exports.loadGraphModel(join(config3.modelBasePath, ((_b = config3.hand.skeleton) == null ? void 0 : _b.modelPath) || ""));
const inputs = Object.values(models[1].modelSignature["inputs"]);
inputSize[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[1][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[1][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[1] || !models[1]["modelUrl"])
log("load model failed:", config3.object.modelPath);
else if (config3.debug)
@ -9430,7 +9437,10 @@ async function detectHands(input, config3) {
if (!input || !models[0])
return hands;
const t = {};
t.resize = tfjs_esm_exports.image.resizeBilinear(input, [240, 320]);
const ratio = (input.shape[2] || 1) / (input.shape[1] || 1);
const height = Math.min(Math.round((input.shape[1] || 0) / 8) * 8, 512);
const width = Math.round(height * ratio / 8) * 8;
t.resize = tfjs_esm_exports.image.resizeBilinear(input, [height, width]);
t.cast = tfjs_esm_exports.cast(t.resize, "int32");
[t.rawScores, t.rawBoxes] = await models[0].executeAsync(t.cast, modelOutputNodes);
t.boxes = tfjs_esm_exports.squeeze(t.rawBoxes, [0, 2]);
@ -9458,8 +9468,36 @@ async function detectHands(input, config3) {
}
classScores.forEach((tensor3) => tfjs_esm_exports.dispose(tensor3));
Object.keys(t).forEach((tensor3) => tfjs_esm_exports.dispose(t[tensor3]));
hands.sort((a, b) => b.score - a.score);
if (hands.length > (config3.hand.maxDetected || 1))
hands.length = config3.hand.maxDetected || 1;
return hands;
}
var boxScaleFact = 1.5;
function updateBoxes(h, keypoints3) {
const finger = [keypoints3.map((pt) => pt[0]), keypoints3.map((pt) => pt[1])];
const minmax = [Math.min(...finger[0]), Math.max(...finger[0]), Math.min(...finger[1]), Math.max(...finger[1])];
const center = [(minmax[0] + minmax[1]) / 2, (minmax[2] + minmax[3]) / 2];
const diff = Math.max(center[0] - minmax[0], center[1] - minmax[2], -center[0] + minmax[1], -center[1] + minmax[3]) * boxScaleFact;
h.box = [
Math.trunc(center[0] - diff),
Math.trunc(center[1] - diff),
Math.trunc(2 * diff),
Math.trunc(2 * diff)
];
h.boxRaw = [
h.box[0] / outputSize[0],
h.box[1] / outputSize[1],
h.box[2] / outputSize[0],
h.box[3] / outputSize[1]
];
h.yxBox = [
h.boxRaw[1],
h.boxRaw[0],
h.boxRaw[3] + h.boxRaw[1],
h.boxRaw[2] + h.boxRaw[0]
];
}
async function detectFingers(input, h, config3) {
const hand3 = {
id: h.id,
@ -9473,46 +9511,57 @@ async function detectFingers(input, h, config3) {
landmarks: {},
annotations: {}
};
if (!input || !models[1] || !config3.hand.landmarks)
if (!input || !models[1])
return hand3;
const t = {};
t.crop = tfjs_esm_exports.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1], inputSize[1]], "bilinear");
t.cast = tfjs_esm_exports.cast(t.crop, "float32");
t.div = tfjs_esm_exports.div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div);
const score3 = Math.round(100 * (await t.score.data())[0] / 100);
if (score3 > (config3.hand.minConfidence || 0)) {
hand3.fingerScore = score3;
t.reshaped = tfjs_esm_exports.reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array();
hand3.keypoints = rawCoords.map((coord) => [
h.box[2] * coord[0] / inputSize[1] + h.box[0],
h.box[3] * coord[1] / inputSize[1] + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1] * coord[2]
]);
hand3.landmarks = analyze(hand3.keypoints);
for (const key of Object.keys(fingerMap)) {
hand3.annotations[key] = fingerMap[key].map((index) => hand3.landmarks && hand3.keypoints[index] ? hand3.keypoints[index] : null);
if (config3.hand.landmarks) {
const t = {};
if (!h.yxBox)
return hand3;
t.crop = tfjs_esm_exports.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1][0], inputSize[1][1]], "bilinear");
t.cast = tfjs_esm_exports.cast(t.crop, "float32");
t.div = tfjs_esm_exports.div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div);
const score3 = Math.round(100 * (await t.score.data())[0] / 100);
if (score3 > (config3.hand.minConfidence || 0)) {
hand3.fingerScore = score3;
t.reshaped = tfjs_esm_exports.reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array();
hand3.keypoints = rawCoords.map((coord) => [
h.box[2] * coord[0] / inputSize[1][0] + h.box[0],
h.box[3] * coord[1] / inputSize[1][1] + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1][0] * coord[2]
]);
updateBoxes(h, hand3.keypoints);
hand3.box = h.box;
hand3.landmarks = analyze(hand3.keypoints);
for (const key of Object.keys(fingerMap)) {
hand3.annotations[key] = fingerMap[key].map((index) => hand3.landmarks && hand3.keypoints[index] ? hand3.keypoints[index] : null);
}
cache.tmpBoxes.push(h);
}
Object.keys(t).forEach((tensor3) => tfjs_esm_exports.dispose(t[tensor3]));
}
Object.keys(t).forEach((tensor3) => tfjs_esm_exports.dispose(t[tensor3]));
return hand3;
}
var last3 = 0;
async function predict6(input, config3) {
outputSize = [input.shape[2] || 0, input.shape[1] || 0];
if (skipped3 < (config3.object.skipFrames || 0) && config3.skipFrame) {
let hands = [];
cache.tmpBoxes = [];
if (!config3.hand.landmarks)
cache.fingerBoxes = cache.handBoxes;
if (skipped3 < (config3.hand.skipFrames || 0) && config3.skipFrame) {
skipped3++;
const hands2 = await Promise.all(boxes.map((hand3) => detectFingers(input, hand3, config3)));
const withFingers2 = hands2.filter((hand3) => hand3.fingerScore > 0).length;
if (withFingers2 === last3)
return hands2;
hands = await Promise.all(cache.fingerBoxes.map((hand3) => detectFingers(input, hand3, config3)));
} else {
skipped3 = 0;
hands = await Promise.all(cache.fingerBoxes.map((hand3) => detectFingers(input, hand3, config3)));
if (hands.length !== config3.hand.maxDetected) {
cache.handBoxes = await detectHands(input, config3);
const newHands = await Promise.all(cache.handBoxes.map((hand3) => detectFingers(input, hand3, config3)));
hands = hands.concat(newHands);
}
}
skipped3 = 0;
boxes = await detectHands(input, config3);
const hands = await Promise.all(boxes.map((hand3) => detectFingers(input, hand3, config3)));
const withFingers = hands.filter((hand3) => hand3.fingerScore > 0).length;
last3 = withFingers;
cache.fingerBoxes = [...cache.tmpBoxes];
return hands;
}
@ -9983,7 +10032,7 @@ var labels = [
// src/object/nanodet.ts
var model7;
var last4 = [];
var last3 = [];
var skipped6 = Number.MAX_SAFE_INTEGER;
var scaleBox = 2.5;
async function load11(config3) {
@ -10063,13 +10112,13 @@ async function process3(res, inputSize3, outputShape, config3) {
return results;
}
async function predict10(image23, config3) {
if (skipped6 < (config3.object.skipFrames || 0) && config3.skipFrame && last4.length > 0) {
if (skipped6 < (config3.object.skipFrames || 0) && config3.skipFrame && last3.length > 0) {
skipped6++;
return last4;
return last3;
}
skipped6 = 0;
if (!env.kernels.includes("mod") || !env.kernels.includes("sparsetodense"))
return last4;
return last3;
return new Promise(async (resolve) => {
const outputSize2 = [image23.shape[2], image23.shape[1]];
const resize = tfjs_esm_exports.image.resizeBilinear(image23, [model7.inputSize, model7.inputSize], false);
@ -10082,7 +10131,7 @@ async function predict10(image23, config3) {
objectT = await model7.predict(transpose);
tfjs_esm_exports.dispose(transpose);
const obj = await process3(objectT, model7.inputSize, outputSize2, config3);
last4 = obj;
last3 = obj;
resolve(obj);
});
}
@ -10090,7 +10139,7 @@ async function predict10(image23, config3) {
// src/object/centernet.ts
var model8;
var inputSize2 = 0;
var last5 = [];
var last4 = [];
var skipped7 = Number.MAX_SAFE_INTEGER;
async function load12(config3) {
if (env.initial)
@ -10154,20 +10203,20 @@ async function process4(res, outputShape, config3) {
return results;
}
async function predict11(input, config3) {
if (skipped7 < (config3.object.skipFrames || 0) && config3.skipFrame && last5.length > 0) {
if (skipped7 < (config3.object.skipFrames || 0) && config3.skipFrame && last4.length > 0) {
skipped7++;
return last5;
return last4;
}
skipped7 = 0;
if (!env.kernels.includes("mod") || !env.kernels.includes("sparsetodense"))
return last5;
return last4;
return new Promise(async (resolve) => {
const outputSize2 = [input.shape[2], input.shape[1]];
const resize = tfjs_esm_exports.image.resizeBilinear(input, [inputSize2, inputSize2]);
const objectT = config3.object.enabled ? model8 == null ? void 0 : model8.execute(resize, ["tower_0/detections"]) : null;
tfjs_esm_exports.dispose(resize);
const obj = await process4(objectT, outputSize2, config3);
last5 = obj;
last4 = obj;
resolve(obj);
});
}
@ -10186,14 +10235,12 @@ async function load13(config3) {
log("cached model:", model9["modelUrl"]);
return model9;
}
async function predict12(input) {
async function predict12(input, config3) {
var _a, _b;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[1]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[2]) || 0;
if (!input.tensor)
return null;
if (!model9 || !model9.inputs[0].shape)
return null;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[2]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[1]) || 0;
if (!input.tensor || !model9 || !model9.inputs[0].shape)
return { data: null, canvas: null, alpha: null };
const resizeInput = tfjs_esm_exports.image.resizeBilinear(input.tensor, [model9.inputs[0].shape[1], model9.inputs[0].shape[2]], false);
const norm = tfjs_esm_exports.div(resizeInput, 255);
const res = model9.predict(norm);
@ -10201,7 +10248,7 @@ async function predict12(input) {
tfjs_esm_exports.dispose(norm);
const squeeze8 = tfjs_esm_exports.squeeze(res, 0);
tfjs_esm_exports.dispose(res);
let resizeOutput;
let dataT;
if (squeeze8.shape[2] === 2) {
const softmax = squeeze8.softmax();
const [bg, fg] = tfjs_esm_exports.unstack(softmax, 2);
@ -10211,77 +10258,63 @@ async function predict12(input) {
tfjs_esm_exports.dispose(bg);
tfjs_esm_exports.dispose(fg);
const crop = tfjs_esm_exports.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
resizeOutput = tfjs_esm_exports.squeeze(crop, 0);
dataT = tfjs_esm_exports.squeeze(crop, 0);
tfjs_esm_exports.dispose(crop);
tfjs_esm_exports.dispose(expand);
tfjs_esm_exports.dispose(pad);
} else {
resizeOutput = tfjs_esm_exports.image.resizeBilinear(squeeze8, [width, height]);
dataT = tfjs_esm_exports.image.resizeBilinear(squeeze8, [height, width]);
}
tfjs_esm_exports.dispose(squeeze8);
const data = await dataT.dataSync();
if (env.node) {
const data = await resizeOutput.data();
tfjs_esm_exports.dispose(resizeOutput);
return data;
tfjs_esm_exports.dispose(dataT);
return { data, canvas: null, alpha: null };
}
const overlay = canvas(width, height);
if (tfjs_esm_exports.browser)
await tfjs_esm_exports.browser.toPixels(resizeOutput, overlay);
tfjs_esm_exports.dispose(resizeOutput);
const alphaCanvas = canvas(width, height);
const ctxAlpha = alphaCanvas.getContext("2d");
ctxAlpha.filter = "blur(8px";
await ctxAlpha.drawImage(overlay, 0, 0);
const alpha = ctxAlpha.getImageData(0, 0, width, height).data;
const original = canvas(width, height);
const ctx = original.getContext("2d");
await tfjs_esm_exports.browser.toPixels(dataT, alphaCanvas);
tfjs_esm_exports.dispose(dataT);
const alphaCtx = alphaCanvas.getContext("2d");
if (config3.segmentation.blur && config3.segmentation.blur > 0)
alphaCtx.filter = `blur(${config3.segmentation.blur}px)`;
const alphaData = alphaCtx.getImageData(0, 0, width, height);
const compositeCanvas = canvas(width, height);
const compositeCtx = compositeCanvas.getContext("2d");
if (input.canvas)
await ctx.drawImage(input.canvas, 0, 0);
ctx.globalCompositeOperation = "darken";
ctx.filter = "blur(8px)";
await ctx.drawImage(overlay, 0, 0);
ctx.globalCompositeOperation = "source-over";
ctx.filter = "none";
input.canvas = original;
return alpha;
compositeCtx.drawImage(input.canvas, 0, 0);
compositeCtx.globalCompositeOperation = "darken";
if (config3.segmentation.blur && config3.segmentation.blur > 0)
compositeCtx.filter = `blur(${config3.segmentation.blur}px)`;
compositeCtx.drawImage(alphaCanvas, 0, 0);
compositeCtx.globalCompositeOperation = "source-over";
compositeCtx.filter = "none";
const compositeData = compositeCtx.getImageData(0, 0, width, height);
for (let i = 0; i < width * height; i++)
compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0];
compositeCtx.putImageData(compositeData, 0, 0);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
async function process5(input, background, config3) {
var _a;
var _a, _b;
if (busy)
return null;
return { data: null, canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const img = process2(input, config3);
const tmp = process2(background, config3);
if (!img.canvas || !tmp.canvas) {
if (config3.debug)
log("segmentation cannot process input or background");
return null;
}
const alpha = await predict12(img);
tfjs_esm_exports.dispose(img.tensor);
if (background && alpha) {
const bg = tmp.canvas;
tfjs_esm_exports.dispose(tmp.tensor);
const fg = img.canvas;
const fgData = (_a = fg.getContext("2d")) == null ? void 0 : _a.getImageData(0, 0, fg.width, fg.height).data;
const c = canvas(fg.width, fg.height);
const ctx = c.getContext("2d");
ctx.globalCompositeOperation = "copy";
ctx.drawImage(bg, 0, 0, c.width, c.height);
const cData = ctx.getImageData(0, 0, c.width, c.height);
for (let i = 0; i < c.width * c.height; i++) {
cData.data[4 * i + 0] = (255 - alpha[4 * i + 0]) / 255 * cData.data[4 * i + 0] + alpha[4 * i + 0] / 255 * fgData[4 * i + 0];
cData.data[4 * i + 1] = (255 - alpha[4 * i + 1]) / 255 * cData.data[4 * i + 1] + alpha[4 * i + 1] / 255 * fgData[4 * i + 1];
cData.data[4 * i + 2] = (255 - alpha[4 * i + 2]) / 255 * cData.data[4 * i + 2] + alpha[4 * i + 2] / 255 * fgData[4 * i + 2];
cData.data[4 * i + 3] = (255 - alpha[4 * i + 3]) / 255 * cData.data[4 * i + 3] + alpha[4 * i + 3] / 255 * fgData[4 * i + 3];
}
ctx.putImageData(cData, 0, 0);
img.canvas = c;
const inputImage = process2(input, config3);
const segmentation3 = await predict12(inputImage, config3);
tfjs_esm_exports.dispose(inputImage.tensor);
let mergedCanvas = null;
if (background && segmentation3.canvas) {
mergedCanvas = canvas(((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0, ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0);
const bgImage = process2(background, config3);
tfjs_esm_exports.dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext("2d");
ctxMerge.drawImage(bgImage.canvas, 0, 0, mergedCanvas.width, mergedCanvas.height);
ctxMerge.drawImage(segmentation3.canvas, 0, 0);
}
busy = false;
return img.canvas;
return { data: segmentation3.data, canvas: mergedCanvas || segmentation3.canvas, alpha: segmentation3.alpha };
}
// src/models.ts
@ -12487,7 +12520,7 @@ var Human = class {
return similarity(embedding1, embedding2);
}
async segmentation(input, background) {
return input ? process5(input, background, this.config) : null;
return process5(input, background, this.config);
}
enhance(input) {
return enhance(input);
@ -12559,24 +12592,10 @@ var Human = class {
await this.load();
timeStamp = now();
this.state = "image";
let img = process2(input, this.config);
const img = process2(input, this.config);
this.process = img;
this.performance.image = Math.trunc(now() - timeStamp);
this.analyze("Get Image:");
if (this.config.segmentation.enabled && this.process && img.tensor && img.canvas) {
this.analyze("Start Segmentation:");
this.state = "detect:segmentation";
timeStamp = now();
await predict12(img);
elapsedTime = Math.trunc(now() - timeStamp);
if (elapsedTime > 0)
this.performance.segmentation = elapsedTime;
if (img.canvas) {
tfjs_esm_exports.dispose(img.tensor);
img = process2(img.canvas, this.config);
}
this.analyze("End Segmentation:");
}
if (!img.tensor) {
if (this.config.debug)
log("could not convert input to tensor");

File diff suppressed because one or more lines are too long

457
dist/human.esm.js vendored
View File

@ -190,7 +190,8 @@ var config = {
},
segmentation: {
enabled: false,
modelPath: "selfie.json"
modelPath: "selfie.json",
blur: 8
}
};
@ -1021,27 +1022,27 @@ var require_long = __commonJS({
var INT_CACHE = {};
var UINT_CACHE = {};
function fromInt(value, unsigned) {
var obj, cachedObj, cache;
var obj, cachedObj, cache2;
if (unsigned) {
value >>>= 0;
if (cache = 0 <= value && value < 256) {
if (cache2 = 0 <= value && value < 256) {
cachedObj = UINT_CACHE[value];
if (cachedObj)
return cachedObj;
}
obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true);
if (cache)
if (cache2)
UINT_CACHE[value] = obj;
return obj;
} else {
value |= 0;
if (cache = -128 <= value && value < 128) {
if (cache2 = -128 <= value && value < 128) {
cachedObj = INT_CACHE[value];
if (cachedObj)
return cachedObj;
}
obj = fromBits(value, value < 0 ? -1 : 0, false);
if (cache)
if (cache2)
INT_CACHE[value] = obj;
return obj;
}
@ -14446,9 +14447,9 @@ function stft_(signal2, frameLength, frameStep, fftLength, windowFn = hannWindow
return rfft(windowedSignal, fftLength);
}
var stft = op({ stft_ });
function cropAndResize_(image32, boxes2, boxInd, cropSize, method = "bilinear", extrapolationValue = 0) {
function cropAndResize_(image32, boxes, boxInd, cropSize, method = "bilinear", extrapolationValue = 0) {
const $image = convertToTensor(image32, "image", "cropAndResize");
const $boxes = convertToTensor(boxes2, "boxes", "cropAndResize", "float32");
const $boxes = convertToTensor(boxes, "boxes", "cropAndResize", "float32");
const $boxInd = convertToTensor(boxInd, "boxInd", "cropAndResize", "int32");
const numBoxes = $boxes.shape[0];
assert($image.rank === 4, () => `Error in cropAndResize: image must be rank 4,but got rank ${$image.rank}.`);
@ -14492,7 +14493,7 @@ function rotateWithOffset_(image32, radians, fillValue = 0, center = 0.5) {
return res;
}
var rotateWithOffset = op({ rotateWithOffset_ });
function nonMaxSuppSanityCheck(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma) {
function nonMaxSuppSanityCheck(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma) {
if (iouThreshold == null) {
iouThreshold = 0.5;
}
@ -14502,18 +14503,18 @@ function nonMaxSuppSanityCheck(boxes2, scores, maxOutputSize, iouThreshold, scor
if (softNmsSigma == null) {
softNmsSigma = 0;
}
const numBoxes = boxes2.shape[0];
const numBoxes = boxes.shape[0];
maxOutputSize = Math.min(maxOutputSize, numBoxes);
assert(0 <= iouThreshold && iouThreshold <= 1, () => `iouThreshold must be in [0, 1], but was '${iouThreshold}'`);
assert(boxes2.rank === 2, () => `boxes must be a 2D tensor, but was of rank '${boxes2.rank}'`);
assert(boxes2.shape[1] === 4, () => `boxes must have 4 columns, but 2nd dimension was ${boxes2.shape[1]}`);
assert(boxes.rank === 2, () => `boxes must be a 2D tensor, but was of rank '${boxes.rank}'`);
assert(boxes.shape[1] === 4, () => `boxes must have 4 columns, but 2nd dimension was ${boxes.shape[1]}`);
assert(scores.rank === 1, () => "scores must be a 1D tensor");
assert(scores.shape[0] === numBoxes, () => `scores has incompatible shape with boxes. Expected ${numBoxes}, but was ${scores.shape[0]}`);
assert(0 <= softNmsSigma && softNmsSigma <= 1, () => `softNmsSigma must be in [0, 1], but was '${softNmsSigma}'`);
return { maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma };
}
function nonMaxSuppression_(boxes2, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY) {
const $boxes = convertToTensor(boxes2, "boxes", "nonMaxSuppression");
function nonMaxSuppression_(boxes, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY) {
const $boxes = convertToTensor(boxes, "boxes", "nonMaxSuppression");
const $scores = convertToTensor(scores, "scores", "nonMaxSuppression");
const inputs = nonMaxSuppSanityCheck($boxes, $scores, maxOutputSize, iouThreshold, scoreThreshold);
maxOutputSize = inputs.maxOutputSize;
@ -14551,16 +14552,16 @@ function binarySearch_(arr, target, comparator) {
}
return found ? left : -left - 1;
}
function nonMaxSuppressionV3Impl(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold) {
return nonMaxSuppressionImpl_(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold, 0);
function nonMaxSuppressionV3Impl(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold) {
return nonMaxSuppressionImpl_(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold, 0);
}
function nonMaxSuppressionV4Impl(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize) {
return nonMaxSuppressionImpl_(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold, 0, false, padToMaxOutputSize, true);
function nonMaxSuppressionV4Impl(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize) {
return nonMaxSuppressionImpl_(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold, 0, false, padToMaxOutputSize, true);
}
function nonMaxSuppressionV5Impl(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma) {
return nonMaxSuppressionImpl_(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma, true);
function nonMaxSuppressionV5Impl(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma) {
return nonMaxSuppressionImpl_(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma, true);
}
function nonMaxSuppressionImpl_(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma, returnScoresTensor = false, padToMaxOutputSize = false, returnValidOutputs = false) {
function nonMaxSuppressionImpl_(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma, returnScoresTensor = false, padToMaxOutputSize = false, returnValidOutputs = false) {
const candidates = [];
for (let i = 0; i < scores.length; i++) {
if (scores[i] > scoreThreshold) {
@ -14579,7 +14580,7 @@ function nonMaxSuppressionImpl_(boxes2, scores, maxOutputSize, iouThreshold, sco
}
let ignoreCandidate = false;
for (let j = selectedIndices.length - 1; j >= suppressBeginIndex; --j) {
const iou = intersectionOverUnion(boxes2, boxIndex, selectedIndices[j]);
const iou = intersectionOverUnion(boxes, boxIndex, selectedIndices[j]);
if (iou >= iouThreshold) {
ignoreCandidate = true;
break;
@ -14614,9 +14615,9 @@ function nonMaxSuppressionImpl_(boxes2, scores, maxOutputSize, iouThreshold, sco
}
return result;
}
function intersectionOverUnion(boxes2, i, j) {
const iCoord = boxes2.subarray(i * 4, i * 4 + 4);
const jCoord = boxes2.subarray(j * 4, j * 4 + 4);
function intersectionOverUnion(boxes, i, j) {
const iCoord = boxes.subarray(i * 4, i * 4 + 4);
const jCoord = boxes.subarray(j * 4, j * 4 + 4);
const yminI = Math.min(iCoord[0], iCoord[2]);
const xminI = Math.min(iCoord[1], iCoord[3]);
const ymaxI = Math.max(iCoord[0], iCoord[2]);
@ -14644,8 +14645,8 @@ function suppressWeight(iouThreshold, scale2, iou) {
function ascendingComparator(c1, c2) {
return c1.score - c2.score || c1.score === c2.score && c2.boxIndex - c1.boxIndex;
}
async function nonMaxSuppressionAsync_(boxes2, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY) {
const $boxes = convertToTensor(boxes2, "boxes", "nonMaxSuppressionAsync");
async function nonMaxSuppressionAsync_(boxes, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY) {
const $boxes = convertToTensor(boxes, "boxes", "nonMaxSuppressionAsync");
const $scores = convertToTensor(scores, "scores", "nonMaxSuppressionAsync");
const inputs = nonMaxSuppSanityCheck($boxes, $scores, maxOutputSize, iouThreshold, scoreThreshold);
maxOutputSize = inputs.maxOutputSize;
@ -14655,7 +14656,7 @@ async function nonMaxSuppressionAsync_(boxes2, scores, maxOutputSize, iouThresho
const boxesVals = boxesAndScores[0];
const scoresVals = boxesAndScores[1];
const { selectedIndices } = nonMaxSuppressionV3Impl(boxesVals, scoresVals, maxOutputSize, iouThreshold, scoreThreshold);
if ($boxes !== boxes2) {
if ($boxes !== boxes) {
$boxes.dispose();
}
if ($scores !== scores) {
@ -14664,8 +14665,8 @@ async function nonMaxSuppressionAsync_(boxes2, scores, maxOutputSize, iouThresho
return tensor1d(selectedIndices, "int32");
}
var nonMaxSuppressionAsync = nonMaxSuppressionAsync_;
function nonMaxSuppressionWithScore_(boxes2, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY, softNmsSigma = 0) {
const $boxes = convertToTensor(boxes2, "boxes", "nonMaxSuppression");
function nonMaxSuppressionWithScore_(boxes, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY, softNmsSigma = 0) {
const $boxes = convertToTensor(boxes, "boxes", "nonMaxSuppression");
const $scores = convertToTensor(scores, "scores", "nonMaxSuppression");
const params = nonMaxSuppSanityCheck($boxes, $scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma);
maxOutputSize = params.maxOutputSize;
@ -14678,8 +14679,8 @@ function nonMaxSuppressionWithScore_(boxes2, scores, maxOutputSize, iouThreshold
return { selectedIndices: result[0], selectedScores: result[1] };
}
var nonMaxSuppressionWithScore = op({ nonMaxSuppressionWithScore_ });
async function nonMaxSuppressionWithScoreAsync_(boxes2, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY, softNmsSigma = 0) {
const $boxes = convertToTensor(boxes2, "boxes", "nonMaxSuppressionAsync");
async function nonMaxSuppressionWithScoreAsync_(boxes, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY, softNmsSigma = 0) {
const $boxes = convertToTensor(boxes, "boxes", "nonMaxSuppressionAsync");
const $scores = convertToTensor(scores, "scores", "nonMaxSuppressionAsync");
const params = nonMaxSuppSanityCheck($boxes, $scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma);
maxOutputSize = params.maxOutputSize;
@ -14690,7 +14691,7 @@ async function nonMaxSuppressionWithScoreAsync_(boxes2, scores, maxOutputSize, i
const boxesVals = boxesAndScores[0];
const scoresVals = boxesAndScores[1];
const { selectedIndices, selectedScores } = nonMaxSuppressionV5Impl(boxesVals, scoresVals, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma);
if ($boxes !== boxes2) {
if ($boxes !== boxes) {
$boxes.dispose();
}
if ($scores !== scores) {
@ -14702,8 +14703,8 @@ async function nonMaxSuppressionWithScoreAsync_(boxes2, scores, maxOutputSize, i
};
}
var nonMaxSuppressionWithScoreAsync = nonMaxSuppressionWithScoreAsync_;
function nonMaxSuppressionPadded_(boxes2, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY, padToMaxOutputSize = false) {
const $boxes = convertToTensor(boxes2, "boxes", "nonMaxSuppression");
function nonMaxSuppressionPadded_(boxes, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY, padToMaxOutputSize = false) {
const $boxes = convertToTensor(boxes, "boxes", "nonMaxSuppression");
const $scores = convertToTensor(scores, "scores", "nonMaxSuppression");
const params = nonMaxSuppSanityCheck($boxes, $scores, maxOutputSize, iouThreshold, scoreThreshold, null);
const $maxOutputSize = params.maxOutputSize;
@ -14720,8 +14721,8 @@ function nonMaxSuppressionPadded_(boxes2, scores, maxOutputSize, iouThreshold =
return { selectedIndices: result[0], validOutputs: result[1] };
}
var nonMaxSuppressionPadded = op({ nonMaxSuppressionPadded_ });
async function nonMaxSuppressionPaddedAsync_(boxes2, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY, padToMaxOutputSize = false) {
const $boxes = convertToTensor(boxes2, "boxes", "nonMaxSuppressionAsync");
async function nonMaxSuppressionPaddedAsync_(boxes, scores, maxOutputSize, iouThreshold = 0.5, scoreThreshold = Number.NEGATIVE_INFINITY, padToMaxOutputSize = false) {
const $boxes = convertToTensor(boxes, "boxes", "nonMaxSuppressionAsync");
const $scores = convertToTensor(scores, "scores", "nonMaxSuppressionAsync");
const params = nonMaxSuppSanityCheck($boxes, $scores, maxOutputSize, iouThreshold, scoreThreshold, null);
const $maxOutputSize = params.maxOutputSize;
@ -14729,7 +14730,7 @@ async function nonMaxSuppressionPaddedAsync_(boxes2, scores, maxOutputSize, iouT
const $scoreThreshold = params.scoreThreshold;
const [boxesVals, scoresVals] = await Promise.all([$boxes.data(), $scores.data()]);
const { selectedIndices, validOutputs } = nonMaxSuppressionV4Impl(boxesVals, scoresVals, $maxOutputSize, $iouThreshold, $scoreThreshold, padToMaxOutputSize);
if ($boxes !== boxes2) {
if ($boxes !== boxes) {
$boxes.dispose();
}
if ($scores !== scores) {
@ -34306,14 +34307,14 @@ var executeOp5 = (node2, tensorMap, context) => {
}
};
function nmsParams(node2, tensorMap, context) {
const boxes2 = getParamValue("boxes", node2, tensorMap, context);
const boxes = getParamValue("boxes", node2, tensorMap, context);
const scores = getParamValue("scores", node2, tensorMap, context);
const maxOutputSize = getParamValue("maxOutputSize", node2, tensorMap, context);
const iouThreshold = getParamValue("iouThreshold", node2, tensorMap, context);
const scoreThreshold = getParamValue("scoreThreshold", node2, tensorMap, context);
const softNmsSigma = getParamValue("softNmsSigma", node2, tensorMap, context);
return {
boxes: boxes2,
boxes,
scores,
maxOutputSize,
iouThreshold,
@ -34324,20 +34325,20 @@ function nmsParams(node2, tensorMap, context) {
var executeOp6 = async (node2, tensorMap, context) => {
switch (node2.op) {
case "NonMaxSuppressionV5": {
const { boxes: boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma } = nmsParams(node2, tensorMap, context);
const result = await image.nonMaxSuppressionWithScoreAsync(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma);
const { boxes, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma } = nmsParams(node2, tensorMap, context);
const result = await image.nonMaxSuppressionWithScoreAsync(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma);
return [result.selectedIndices, result.selectedScores];
}
case "NonMaxSuppressionV4": {
const { boxes: boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold } = nmsParams(node2, tensorMap, context);
const { boxes, scores, maxOutputSize, iouThreshold, scoreThreshold } = nmsParams(node2, tensorMap, context);
const padToMaxOutputSize = getParamValue("padToMaxOutputSize", node2, tensorMap, context);
const result = await image.nonMaxSuppressionPaddedAsync(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize);
const result = await image.nonMaxSuppressionPaddedAsync(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize);
return [result.selectedIndices, result.validOutputs];
}
case "NonMaxSuppressionV3":
case "NonMaxSuppressionV2": {
const { boxes: boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold } = nmsParams(node2, tensorMap, context);
return [await image.nonMaxSuppressionAsync(boxes2, scores, maxOutputSize, iouThreshold, scoreThreshold)];
const { boxes, scores, maxOutputSize, iouThreshold, scoreThreshold } = nmsParams(node2, tensorMap, context);
return [await image.nonMaxSuppressionAsync(boxes, scores, maxOutputSize, iouThreshold, scoreThreshold)];
}
case "Where": {
const condition = cast(getParamValue("condition", node2, tensorMap, context), "bool");
@ -34543,12 +34544,12 @@ var executeOp10 = (node2, tensorMap, context) => {
}
case "CropAndResize": {
const image32 = getParamValue("image", node2, tensorMap, context);
const boxes2 = getParamValue("boxes", node2, tensorMap, context);
const boxes = getParamValue("boxes", node2, tensorMap, context);
const boxInd = getParamValue("boxInd", node2, tensorMap, context);
const cropSize = getParamValue("cropSize", node2, tensorMap, context);
const method = getParamValue("method", node2, tensorMap, context);
const extrapolationValue = getParamValue("extrapolationValue", node2, tensorMap, context);
return [image.cropAndResize(image32, boxes2, boxInd, cropSize, method, extrapolationValue)];
return [image.cropAndResize(image32, boxes, boxInd, cropSize, method, extrapolationValue)];
}
default:
throw TypeError(`Node type ${node2.op} is not implemented`);
@ -40429,13 +40430,13 @@ var coshConfig = {
};
function cropAndResize2(args) {
const { inputs, backend: backend22, attrs } = args;
const { image: image32, boxes: boxes2, boxInd } = inputs;
const { image: image32, boxes, boxInd } = inputs;
const { cropSize, method, extrapolationValue } = attrs;
const [batch, imageHeight, imageWidth, numChannels] = image32.shape;
const numBoxes = boxes2.shape[0];
const numBoxes = boxes.shape[0];
const [cropHeight, cropWidth] = cropSize;
const output = buffer([numBoxes, cropHeight, cropWidth, numChannels], "float32");
const boxVals = backend22.data.get(boxes2.dataId).values;
const boxVals = backend22.data.get(boxes.dataId).values;
const boxIndVals = backend22.data.get(boxInd.dataId).values;
const imageVals = backend22.data.get(image32.dataId).values;
const inStride = util_exports.computeStrides(image32.shape);
@ -42107,10 +42108,10 @@ var multinomialConfig = {
var nonMaxSuppressionV3Impl2 = kernel_impls_exports.nonMaxSuppressionV3Impl;
function nonMaxSuppressionV3(args) {
const { inputs, backend: backend22, attrs } = args;
const { boxes: boxes2, scores } = inputs;
const { boxes, scores } = inputs;
const { maxOutputSize, iouThreshold, scoreThreshold } = attrs;
assertNotComplex(boxes2, "NonMaxSuppression");
const boxesVals = backend22.data.get(boxes2.dataId).values;
assertNotComplex(boxes, "NonMaxSuppression");
const boxesVals = backend22.data.get(boxes.dataId).values;
const scoresVals = backend22.data.get(scores.dataId).values;
const { selectedIndices } = nonMaxSuppressionV3Impl2(boxesVals, scoresVals, maxOutputSize, iouThreshold, scoreThreshold);
return backend22.makeTensorInfo([selectedIndices.length], "int32", new Int32Array(selectedIndices));
@ -42123,10 +42124,10 @@ var nonMaxSuppressionV3Config = {
var nonMaxSuppressionV4Impl2 = kernel_impls_exports.nonMaxSuppressionV4Impl;
function nonMaxSuppressionV4(args) {
const { inputs, backend: backend22, attrs } = args;
const { boxes: boxes2, scores } = inputs;
const { boxes, scores } = inputs;
const { maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize } = attrs;
assertNotComplex(boxes2, "NonMaxSuppressionPadded");
const boxesVals = backend22.data.get(boxes2.dataId).values;
assertNotComplex(boxes, "NonMaxSuppressionPadded");
const boxesVals = backend22.data.get(boxes.dataId).values;
const scoresVals = backend22.data.get(scores.dataId).values;
const { selectedIndices, validOutputs } = nonMaxSuppressionV4Impl2(boxesVals, scoresVals, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize);
return [
@ -42142,10 +42143,10 @@ var nonMaxSuppressionV4Config = {
var nonMaxSuppressionV5Impl2 = kernel_impls_exports.nonMaxSuppressionV5Impl;
function nonMaxSuppressionV5(args) {
const { inputs, backend: backend22, attrs } = args;
const { boxes: boxes2, scores } = inputs;
const { boxes, scores } = inputs;
const { maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma } = attrs;
assertNotComplex(boxes2, "NonMaxSuppressionWithScore");
const boxesVals = backend22.data.get(boxes2.dataId).values;
assertNotComplex(boxes, "NonMaxSuppressionWithScore");
const boxesVals = backend22.data.get(boxes.dataId).values;
const scoresVals = backend22.data.get(scores.dataId).values;
const maxOutputSizeVal = maxOutputSize;
const iouThresholdVal = iouThreshold;
@ -51954,10 +51955,10 @@ var CropAndResizeProgram = class {
};
var cropAndResize3 = (args) => {
const { inputs, backend: backend22, attrs } = args;
const { image: image32, boxes: boxes2, boxInd } = inputs;
const { image: image32, boxes, boxInd } = inputs;
const { cropSize, method, extrapolationValue } = attrs;
const program = new CropAndResizeProgram(image32.shape, boxes2.shape, cropSize, method, extrapolationValue);
return backend22.runWebGLProgram(program, [image32, boxes2, boxInd], "float32");
const program = new CropAndResizeProgram(image32.shape, boxes.shape, cropSize, method, extrapolationValue);
return backend22.runWebGLProgram(program, [image32, boxes, boxInd], "float32");
};
var cropAndResizeConfig2 = {
kernelName: CropAndResize,
@ -54655,9 +54656,9 @@ var nonMaxSuppressionV3Impl3 = kernel_impls_exports.nonMaxSuppressionV3Impl;
function nonMaxSuppressionV32(args) {
backend_util_exports.warn("tf.nonMaxSuppression() in webgl locks the UI thread. Call tf.nonMaxSuppressionAsync() instead");
const { inputs, backend: backend22, attrs } = args;
const { boxes: boxes2, scores } = inputs;
const { boxes, scores } = inputs;
const { maxOutputSize, iouThreshold, scoreThreshold } = attrs;
const boxesVals = backend22.readSync(boxes2.dataId);
const boxesVals = backend22.readSync(boxes.dataId);
const scoresVals = backend22.readSync(scores.dataId);
const { selectedIndices } = nonMaxSuppressionV3Impl3(boxesVals, scoresVals, maxOutputSize, iouThreshold, scoreThreshold);
return backend22.makeTensorInfo([selectedIndices.length], "int32", new Int32Array(selectedIndices));
@ -54671,9 +54672,9 @@ var nonMaxSuppressionV4Impl3 = kernel_impls_exports.nonMaxSuppressionV4Impl;
function nonMaxSuppressionV42(args) {
backend_util_exports.warn("tf.nonMaxSuppression() in webgl locks the UI thread. Call tf.nonMaxSuppressionAsync() instead");
const { inputs, backend: backend22, attrs } = args;
const { boxes: boxes2, scores } = inputs;
const { boxes, scores } = inputs;
const { maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize } = attrs;
const boxesVals = backend22.readSync(boxes2.dataId);
const boxesVals = backend22.readSync(boxes.dataId);
const scoresVals = backend22.readSync(scores.dataId);
const { selectedIndices, validOutputs } = nonMaxSuppressionV4Impl3(boxesVals, scoresVals, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize);
return [
@ -54690,9 +54691,9 @@ var nonMaxSuppressionV5Impl3 = kernel_impls_exports.nonMaxSuppressionV5Impl;
function nonMaxSuppressionV52(args) {
backend_util_exports.warn("tf.nonMaxSuppression() in webgl locks the UI thread. Call tf.nonMaxSuppressionAsync() instead");
const { inputs, backend: backend22, attrs } = args;
const { boxes: boxes2, scores } = inputs;
const { boxes, scores } = inputs;
const { maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma } = attrs;
const boxesVals = backend22.readSync(boxes2.dataId);
const boxesVals = backend22.readSync(boxes.dataId);
const scoresVals = backend22.readSync(scores.dataId);
const maxOutputSizeVal = maxOutputSize;
const iouThresholdVal = iouThreshold;
@ -58091,8 +58092,8 @@ function setup11(backend22) {
function cropAndResize4(args) {
const { backend: backend22, inputs, attrs } = args;
const { method, extrapolationValue, cropSize } = attrs;
const { image: image32, boxes: boxes2, boxInd } = inputs;
const numBoxes = boxes2.shape[0];
const { image: image32, boxes, boxInd } = inputs;
const numBoxes = boxes.shape[0];
const [cropHeight, cropWidth] = cropSize;
const outShape = [numBoxes, cropHeight, cropWidth, image32.shape[3]];
let imagesData = backend22.dataIdMap.get(image32.dataId);
@ -58102,7 +58103,7 @@ function cropAndResize4(args) {
imagesData = backend22.dataIdMap.get(castedData.dataId);
}
const imagesId = imagesData.id;
const boxesId = backend22.dataIdMap.get(boxes2.dataId).id;
const boxesId = backend22.dataIdMap.get(boxes.dataId).id;
const boxIndId = backend22.dataIdMap.get(boxInd.dataId).id;
const out = backend22.makeOutput(outShape, "float32");
const outId = backend22.dataIdMap.get(out.dataId).id;
@ -58917,8 +58918,8 @@ function setup26(backend22) {
function kernelFunc(args) {
const { backend: backend22, inputs, attrs } = args;
const { iouThreshold, maxOutputSize, scoreThreshold } = attrs;
const { boxes: boxes2, scores } = inputs;
const boxesId = backend22.dataIdMap.get(boxes2.dataId).id;
const { boxes, scores } = inputs;
const boxesId = backend22.dataIdMap.get(boxes.dataId).id;
const scoresId = backend22.dataIdMap.get(scores.dataId).id;
const resOffset = wasmFunc4(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold);
const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend22, resOffset);
@ -58947,8 +58948,8 @@ function setup27(backend22) {
function nonMaxSuppressionV43(args) {
const { backend: backend22, inputs, attrs } = args;
const { iouThreshold, maxOutputSize, scoreThreshold, padToMaxOutputSize } = attrs;
const { boxes: boxes2, scores } = inputs;
const boxesId = backend22.dataIdMap.get(boxes2.dataId).id;
const { boxes, scores } = inputs;
const boxesId = backend22.dataIdMap.get(boxes.dataId).id;
const scoresId = backend22.dataIdMap.get(scores.dataId).id;
const resOffset = wasmFunc5(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize);
const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend22, resOffset);
@ -58977,8 +58978,8 @@ function setup28(backend22) {
function kernelFunc2(args) {
const { backend: backend22, inputs, attrs } = args;
const { iouThreshold, maxOutputSize, scoreThreshold, softNmsSigma } = attrs;
const { boxes: boxes2, scores } = inputs;
const boxesId = backend22.dataIdMap.get(boxes2.dataId).id;
const { boxes, scores } = inputs;
const boxesId = backend22.dataIdMap.get(boxes.dataId).id;
const scoresId = backend22.dataIdMap.get(scores.dataId).id;
const resOffset = wasmFunc6(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma);
const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend22, resOffset);
@ -60313,13 +60314,13 @@ function getBoxCenter(box6) {
function cutBoxFromImageAndResize(box6, image7, cropSize) {
const h = image7.shape[1];
const w = image7.shape[2];
const boxes2 = [[
const boxes = [[
box6.startPoint[1] / h,
box6.startPoint[0] / w,
box6.endPoint[1] / h,
box6.endPoint[0] / w
]];
return image.cropAndResize(image7, boxes2, [0], cropSize);
return image.cropAndResize(image7, boxes, [0], cropSize);
}
function enlargeBox(box6, factor = 1.5) {
const center = getBoxCenter(box6);
@ -60469,7 +60470,7 @@ var BlazeFaceModel = class {
var _a, _b, _c, _d;
if (!inputImage || inputImage["isDisposedInternal"] || inputImage.shape.length !== 4 || inputImage.shape[1] < 1 || inputImage.shape[2] < 1)
return { boxes: [] };
const [batch, boxes2, scores] = tidy(() => {
const [batch, boxes, scores] = tidy(() => {
const resizedImage = image.resizeBilinear(inputImage, [this.inputSize, this.inputSize]);
const normalizedImage = sub(div(resizedImage, 127.5), 0.5);
const res = this.model.execute(normalizedImage);
@ -60489,7 +60490,7 @@ var BlazeFaceModel = class {
return [batchOut, boxesOut, scoresOut];
});
this.config = mergeDeep(this.config, userConfig);
const nmsTensor = await image.nonMaxSuppressionAsync(boxes2, scores, ((_a = this.config.face.detector) == null ? void 0 : _a.maxDetected) || 0, ((_b = this.config.face.detector) == null ? void 0 : _b.iouThreshold) || 0, ((_c = this.config.face.detector) == null ? void 0 : _c.minConfidence) || 0);
const nmsTensor = await image.nonMaxSuppressionAsync(boxes, scores, ((_a = this.config.face.detector) == null ? void 0 : _a.maxDetected) || 0, ((_b = this.config.face.detector) == null ? void 0 : _b.iouThreshold) || 0, ((_c = this.config.face.detector) == null ? void 0 : _c.minConfidence) || 0);
const nms = await nmsTensor.array();
dispose(nmsTensor);
const annotatedBoxes = [];
@ -60497,14 +60498,14 @@ var BlazeFaceModel = class {
for (let i = 0; i < nms.length; i++) {
const confidence = scoresData[nms[i]];
if (confidence > (((_d = this.config.face.detector) == null ? void 0 : _d.minConfidence) || 0)) {
const boundingBox = slice(boxes2, [nms[i], 0], [1, -1]);
const boundingBox = slice(boxes, [nms[i], 0], [1, -1]);
const landmarks = tidy(() => reshape(squeeze(slice(batch, [nms[i], keypointsCount - 1], [1, -1])), [keypointsCount, -1]));
annotatedBoxes.push({ box: createBox(boundingBox), landmarks, anchor: this.anchorsData[nms[i]], confidence });
dispose(boundingBox);
}
}
dispose(batch);
dispose(boxes2);
dispose(boxes);
dispose(scores);
return {
boxes: annotatedBoxes,
@ -65682,13 +65683,13 @@ function getBoxCenter2(box6) {
function cutBoxFromImageAndResize2(box6, image7, cropSize) {
const h = image7.shape[1];
const w = image7.shape[2];
const boxes2 = [[
const boxes = [[
box6.startPoint[1] / h,
box6.startPoint[0] / w,
box6.endPoint[1] / h,
box6.endPoint[0] / w
]];
return image.cropAndResize(image7, boxes2, [0], cropSize);
return image.cropAndResize(image7, boxes, [0], cropSize);
}
function scaleBoxCoordinates2(box6, factor) {
const startPoint = [box6.startPoint[0] * factor[0], box6.startPoint[1] * factor[1]];
@ -68681,10 +68682,10 @@ var HandDetector = class {
this.inputSizeTensor = tensor1d([this.inputSize, this.inputSize]);
this.doubleInputSizeTensor = tensor1d([this.inputSize * 2, this.inputSize * 2]);
}
normalizeBoxes(boxes2) {
normalizeBoxes(boxes) {
return tidy(() => {
const boxOffsets = slice(boxes2, [0, 0], [-1, 2]);
const boxSizes = slice(boxes2, [0, 2], [-1, 2]);
const boxOffsets = slice(boxes, [0, 0], [-1, 2]);
const boxSizes = slice(boxes, [0, 2], [-1, 2]);
const boxCenterPoints = add2(div(boxOffsets, this.inputSizeTensor), this.anchorsTensor);
const halfBoxSizes = div(boxSizes, this.doubleInputSizeTensor);
const startPoints = mul(sub(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
@ -68728,9 +68729,9 @@ var HandDetector = class {
if (!predictions || predictions.length === 0)
return hands;
for (const prediction of predictions) {
const boxes2 = await prediction.box.data();
const startPoint = boxes2.slice(0, 2);
const endPoint = boxes2.slice(2, 4);
const boxes = await prediction.box.data();
const startPoint = boxes.slice(0, 2);
const endPoint = boxes.slice(2, 4);
const palmLandmarks = await prediction.palmLandmarks.array();
dispose(prediction.box);
dispose(prediction.palmLandmarks);
@ -68872,16 +68873,16 @@ var HandPipeline = class {
}
async estimateHands(image7, config3) {
let useFreshBox = false;
let boxes2;
let boxes;
if (this.skipped === 0 || this.skipped > config3.hand.skipFrames || !config3.hand.landmarks || !config3.skipFrame) {
boxes2 = await this.handDetector.estimateHandBounds(image7, config3);
boxes = await this.handDetector.estimateHandBounds(image7, config3);
this.skipped = 0;
}
if (config3.skipFrame)
this.skipped++;
if (boxes2 && boxes2.length > 0 && (boxes2.length !== this.detectedHands && this.detectedHands !== config3.hand.maxDetected || !config3.hand.landmarks)) {
if (boxes && boxes.length > 0 && (boxes.length !== this.detectedHands && this.detectedHands !== config3.hand.maxDetected || !config3.hand.landmarks)) {
this.detectedHands = 0;
this.storedBoxes = [...boxes2];
this.storedBoxes = [...boxes];
if (this.storedBoxes.length > 0)
useFreshBox = true;
}
@ -69433,7 +69434,7 @@ async function load6(config3) {
// src/handtrack/handtrack.ts
var models = [null, null];
var modelOutputNodes = ["StatefulPartitionedCall/Postprocessor/Slice", "StatefulPartitionedCall/Postprocessor/ExpandDims_1"];
var inputSize = [0, 0];
var inputSize = [[0, 0], [0, 0]];
var classes = [
"hand",
"fist",
@ -69445,7 +69446,11 @@ var classes = [
];
var skipped3 = 0;
var outputSize;
var boxes = [];
var cache = {
handBoxes: [],
fingerBoxes: [],
tmpBoxes: []
};
var fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
@ -69463,7 +69468,8 @@ async function load7(config3) {
if (!models[0]) {
models[0] = await loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""));
const inputs = Object.values(models[0].modelSignature["inputs"]);
inputSize[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[0][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[0][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[0] || !models[0]["modelUrl"])
log("load model failed:", config3.object.modelPath);
else if (config3.debug)
@ -69473,7 +69479,8 @@ async function load7(config3) {
if (!models[1]) {
models[1] = await loadGraphModel(join(config3.modelBasePath, ((_b = config3.hand.skeleton) == null ? void 0 : _b.modelPath) || ""));
const inputs = Object.values(models[1].modelSignature["inputs"]);
inputSize[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[1][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[1][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[1] || !models[1]["modelUrl"])
log("load model failed:", config3.object.modelPath);
else if (config3.debug)
@ -69487,7 +69494,10 @@ async function detectHands(input2, config3) {
if (!input2 || !models[0])
return hands;
const t = {};
t.resize = image.resizeBilinear(input2, [240, 320]);
const ratio = (input2.shape[2] || 1) / (input2.shape[1] || 1);
const height = Math.min(Math.round((input2.shape[1] || 0) / 8) * 8, 512);
const width = Math.round(height * ratio / 8) * 8;
t.resize = image.resizeBilinear(input2, [height, width]);
t.cast = cast(t.resize, "int32");
[t.rawScores, t.rawBoxes] = await models[0].executeAsync(t.cast, modelOutputNodes);
t.boxes = squeeze(t.rawBoxes, [0, 2]);
@ -69515,8 +69525,36 @@ async function detectHands(input2, config3) {
}
classScores.forEach((tensor2) => dispose(tensor2));
Object.keys(t).forEach((tensor2) => dispose(t[tensor2]));
hands.sort((a, b) => b.score - a.score);
if (hands.length > (config3.hand.maxDetected || 1))
hands.length = config3.hand.maxDetected || 1;
return hands;
}
var boxScaleFact = 1.5;
function updateBoxes(h, keypoints3) {
const finger = [keypoints3.map((pt) => pt[0]), keypoints3.map((pt) => pt[1])];
const minmax = [Math.min(...finger[0]), Math.max(...finger[0]), Math.min(...finger[1]), Math.max(...finger[1])];
const center = [(minmax[0] + minmax[1]) / 2, (minmax[2] + minmax[3]) / 2];
const diff = Math.max(center[0] - minmax[0], center[1] - minmax[2], -center[0] + minmax[1], -center[1] + minmax[3]) * boxScaleFact;
h.box = [
Math.trunc(center[0] - diff),
Math.trunc(center[1] - diff),
Math.trunc(2 * diff),
Math.trunc(2 * diff)
];
h.boxRaw = [
h.box[0] / outputSize[0],
h.box[1] / outputSize[1],
h.box[2] / outputSize[0],
h.box[3] / outputSize[1]
];
h.yxBox = [
h.boxRaw[1],
h.boxRaw[0],
h.boxRaw[3] + h.boxRaw[1],
h.boxRaw[2] + h.boxRaw[0]
];
}
async function detectFingers(input2, h, config3) {
const hand3 = {
id: h.id,
@ -69530,46 +69568,57 @@ async function detectFingers(input2, h, config3) {
landmarks: {},
annotations: {}
};
if (!input2 || !models[1] || !config3.hand.landmarks)
if (!input2 || !models[1])
return hand3;
const t = {};
t.crop = image.cropAndResize(input2, [h.yxBox], [0], [inputSize[1], inputSize[1]], "bilinear");
t.cast = cast(t.crop, "float32");
t.div = div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div);
const score3 = Math.round(100 * (await t.score.data())[0] / 100);
if (score3 > (config3.hand.minConfidence || 0)) {
hand3.fingerScore = score3;
t.reshaped = reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array();
hand3.keypoints = rawCoords.map((coord) => [
h.box[2] * coord[0] / inputSize[1] + h.box[0],
h.box[3] * coord[1] / inputSize[1] + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1] * coord[2]
]);
hand3.landmarks = analyze(hand3.keypoints);
for (const key of Object.keys(fingerMap)) {
hand3.annotations[key] = fingerMap[key].map((index) => hand3.landmarks && hand3.keypoints[index] ? hand3.keypoints[index] : null);
if (config3.hand.landmarks) {
const t = {};
if (!h.yxBox)
return hand3;
t.crop = image.cropAndResize(input2, [h.yxBox], [0], [inputSize[1][0], inputSize[1][1]], "bilinear");
t.cast = cast(t.crop, "float32");
t.div = div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div);
const score3 = Math.round(100 * (await t.score.data())[0] / 100);
if (score3 > (config3.hand.minConfidence || 0)) {
hand3.fingerScore = score3;
t.reshaped = reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array();
hand3.keypoints = rawCoords.map((coord) => [
h.box[2] * coord[0] / inputSize[1][0] + h.box[0],
h.box[3] * coord[1] / inputSize[1][1] + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1][0] * coord[2]
]);
updateBoxes(h, hand3.keypoints);
hand3.box = h.box;
hand3.landmarks = analyze(hand3.keypoints);
for (const key of Object.keys(fingerMap)) {
hand3.annotations[key] = fingerMap[key].map((index) => hand3.landmarks && hand3.keypoints[index] ? hand3.keypoints[index] : null);
}
cache.tmpBoxes.push(h);
}
Object.keys(t).forEach((tensor2) => dispose(t[tensor2]));
}
Object.keys(t).forEach((tensor2) => dispose(t[tensor2]));
return hand3;
}
var last3 = 0;
async function predict6(input2, config3) {
outputSize = [input2.shape[2] || 0, input2.shape[1] || 0];
if (skipped3 < (config3.object.skipFrames || 0) && config3.skipFrame) {
let hands = [];
cache.tmpBoxes = [];
if (!config3.hand.landmarks)
cache.fingerBoxes = cache.handBoxes;
if (skipped3 < (config3.hand.skipFrames || 0) && config3.skipFrame) {
skipped3++;
const hands2 = await Promise.all(boxes.map((hand3) => detectFingers(input2, hand3, config3)));
const withFingers2 = hands2.filter((hand3) => hand3.fingerScore > 0).length;
if (withFingers2 === last3)
return hands2;
hands = await Promise.all(cache.fingerBoxes.map((hand3) => detectFingers(input2, hand3, config3)));
} else {
skipped3 = 0;
hands = await Promise.all(cache.fingerBoxes.map((hand3) => detectFingers(input2, hand3, config3)));
if (hands.length !== config3.hand.maxDetected) {
cache.handBoxes = await detectHands(input2, config3);
const newHands = await Promise.all(cache.handBoxes.map((hand3) => detectFingers(input2, hand3, config3)));
hands = hands.concat(newHands);
}
}
skipped3 = 0;
boxes = await detectHands(input2, config3);
const hands = await Promise.all(boxes.map((hand3) => detectFingers(input2, hand3, config3)));
const withFingers = hands.filter((hand3) => hand3.fingerScore > 0).length;
last3 = withFingers;
cache.fingerBoxes = [...cache.tmpBoxes];
return hands;
}
@ -70040,7 +70089,7 @@ var labels = [
// src/object/nanodet.ts
var model8;
var last4 = [];
var last3 = [];
var skipped6 = Number.MAX_SAFE_INTEGER;
var scaleBox = 2.5;
async function load11(config3) {
@ -70120,13 +70169,13 @@ async function process3(res, inputSize3, outputShape, config3) {
return results;
}
async function predict10(image7, config3) {
if (skipped6 < (config3.object.skipFrames || 0) && config3.skipFrame && last4.length > 0) {
if (skipped6 < (config3.object.skipFrames || 0) && config3.skipFrame && last3.length > 0) {
skipped6++;
return last4;
return last3;
}
skipped6 = 0;
if (!env2.kernels.includes("mod") || !env2.kernels.includes("sparsetodense"))
return last4;
return last3;
return new Promise(async (resolve) => {
const outputSize2 = [image7.shape[2], image7.shape[1]];
const resize = image.resizeBilinear(image7, [model8.inputSize, model8.inputSize], false);
@ -70139,7 +70188,7 @@ async function predict10(image7, config3) {
objectT = await model8.predict(transpose5);
dispose(transpose5);
const obj = await process3(objectT, model8.inputSize, outputSize2, config3);
last4 = obj;
last3 = obj;
resolve(obj);
});
}
@ -70147,7 +70196,7 @@ async function predict10(image7, config3) {
// src/object/centernet.ts
var model9;
var inputSize2 = 0;
var last5 = [];
var last4 = [];
var skipped7 = Number.MAX_SAFE_INTEGER;
async function load12(config3) {
if (env2.initial)
@ -70211,20 +70260,20 @@ async function process4(res, outputShape, config3) {
return results;
}
async function predict11(input2, config3) {
if (skipped7 < (config3.object.skipFrames || 0) && config3.skipFrame && last5.length > 0) {
if (skipped7 < (config3.object.skipFrames || 0) && config3.skipFrame && last4.length > 0) {
skipped7++;
return last5;
return last4;
}
skipped7 = 0;
if (!env2.kernels.includes("mod") || !env2.kernels.includes("sparsetodense"))
return last5;
return last4;
return new Promise(async (resolve) => {
const outputSize2 = [input2.shape[2], input2.shape[1]];
const resize = image.resizeBilinear(input2, [inputSize2, inputSize2]);
const objectT = config3.object.enabled ? model9 == null ? void 0 : model9.execute(resize, ["tower_0/detections"]) : null;
dispose(resize);
const obj = await process4(objectT, outputSize2, config3);
last5 = obj;
last4 = obj;
resolve(obj);
});
}
@ -70243,14 +70292,12 @@ async function load13(config3) {
log("cached model:", model10["modelUrl"]);
return model10;
}
async function predict12(input2) {
async function predict12(input2, config3) {
var _a, _b;
const width = ((_a = input2.tensor) == null ? void 0 : _a.shape[1]) || 0;
const height = ((_b = input2.tensor) == null ? void 0 : _b.shape[2]) || 0;
if (!input2.tensor)
return null;
if (!model10 || !model10.inputs[0].shape)
return null;
const width = ((_a = input2.tensor) == null ? void 0 : _a.shape[2]) || 0;
const height = ((_b = input2.tensor) == null ? void 0 : _b.shape[1]) || 0;
if (!input2.tensor || !model10 || !model10.inputs[0].shape)
return { data: null, canvas: null, alpha: null };
const resizeInput = image.resizeBilinear(input2.tensor, [model10.inputs[0].shape[1], model10.inputs[0].shape[2]], false);
const norm2 = div(resizeInput, 255);
const res = model10.predict(norm2);
@ -70258,7 +70305,7 @@ async function predict12(input2) {
dispose(norm2);
const squeeze2 = squeeze(res, 0);
dispose(res);
let resizeOutput;
let dataT;
if (squeeze2.shape[2] === 2) {
const softmax6 = squeeze2.softmax();
const [bg, fg] = unstack(softmax6, 2);
@ -70268,77 +70315,63 @@ async function predict12(input2) {
dispose(bg);
dispose(fg);
const crop = image.cropAndResize(pad3, [[0, 0, 0.5, 0.5]], [0], [width, height]);
resizeOutput = squeeze(crop, 0);
dataT = squeeze(crop, 0);
dispose(crop);
dispose(expand);
dispose(pad3);
} else {
resizeOutput = image.resizeBilinear(squeeze2, [width, height]);
dataT = image.resizeBilinear(squeeze2, [height, width]);
}
dispose(squeeze2);
const data = await dataT.dataSync();
if (env2.node) {
const data = await resizeOutput.data();
dispose(resizeOutput);
return data;
dispose(dataT);
return { data, canvas: null, alpha: null };
}
const overlay = canvas(width, height);
if (browser_exports)
await browser_exports.toPixels(resizeOutput, overlay);
dispose(resizeOutput);
const alphaCanvas = canvas(width, height);
const ctxAlpha = alphaCanvas.getContext("2d");
ctxAlpha.filter = "blur(8px";
await ctxAlpha.drawImage(overlay, 0, 0);
const alpha = ctxAlpha.getImageData(0, 0, width, height).data;
const original = canvas(width, height);
const ctx = original.getContext("2d");
await browser_exports.toPixels(dataT, alphaCanvas);
dispose(dataT);
const alphaCtx = alphaCanvas.getContext("2d");
if (config3.segmentation.blur && config3.segmentation.blur > 0)
alphaCtx.filter = `blur(${config3.segmentation.blur}px)`;
const alphaData = alphaCtx.getImageData(0, 0, width, height);
const compositeCanvas = canvas(width, height);
const compositeCtx = compositeCanvas.getContext("2d");
if (input2.canvas)
await ctx.drawImage(input2.canvas, 0, 0);
ctx.globalCompositeOperation = "darken";
ctx.filter = "blur(8px)";
await ctx.drawImage(overlay, 0, 0);
ctx.globalCompositeOperation = "source-over";
ctx.filter = "none";
input2.canvas = original;
return alpha;
compositeCtx.drawImage(input2.canvas, 0, 0);
compositeCtx.globalCompositeOperation = "darken";
if (config3.segmentation.blur && config3.segmentation.blur > 0)
compositeCtx.filter = `blur(${config3.segmentation.blur}px)`;
compositeCtx.drawImage(alphaCanvas, 0, 0);
compositeCtx.globalCompositeOperation = "source-over";
compositeCtx.filter = "none";
const compositeData = compositeCtx.getImageData(0, 0, width, height);
for (let i = 0; i < width * height; i++)
compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0];
compositeCtx.putImageData(compositeData, 0, 0);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
async function process5(input2, background, config3) {
var _a;
var _a, _b;
if (busy)
return null;
return { data: null, canvas: null, alpha: null };
busy = true;
if (!model10)
await load13(config3);
const img = process2(input2, config3);
const tmp = process2(background, config3);
if (!img.canvas || !tmp.canvas) {
if (config3.debug)
log("segmentation cannot process input or background");
return null;
}
const alpha = await predict12(img);
dispose(img.tensor);
if (background && alpha) {
const bg = tmp.canvas;
dispose(tmp.tensor);
const fg = img.canvas;
const fgData = (_a = fg.getContext("2d")) == null ? void 0 : _a.getImageData(0, 0, fg.width, fg.height).data;
const c = canvas(fg.width, fg.height);
const ctx = c.getContext("2d");
ctx.globalCompositeOperation = "copy";
ctx.drawImage(bg, 0, 0, c.width, c.height);
const cData = ctx.getImageData(0, 0, c.width, c.height);
for (let i = 0; i < c.width * c.height; i++) {
cData.data[4 * i + 0] = (255 - alpha[4 * i + 0]) / 255 * cData.data[4 * i + 0] + alpha[4 * i + 0] / 255 * fgData[4 * i + 0];
cData.data[4 * i + 1] = (255 - alpha[4 * i + 1]) / 255 * cData.data[4 * i + 1] + alpha[4 * i + 1] / 255 * fgData[4 * i + 1];
cData.data[4 * i + 2] = (255 - alpha[4 * i + 2]) / 255 * cData.data[4 * i + 2] + alpha[4 * i + 2] / 255 * fgData[4 * i + 2];
cData.data[4 * i + 3] = (255 - alpha[4 * i + 3]) / 255 * cData.data[4 * i + 3] + alpha[4 * i + 3] / 255 * fgData[4 * i + 3];
}
ctx.putImageData(cData, 0, 0);
img.canvas = c;
const inputImage = process2(input2, config3);
const segmentation3 = await predict12(inputImage, config3);
dispose(inputImage.tensor);
let mergedCanvas = null;
if (background && segmentation3.canvas) {
mergedCanvas = canvas(((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0, ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0);
const bgImage = process2(background, config3);
dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext("2d");
ctxMerge.drawImage(bgImage.canvas, 0, 0, mergedCanvas.width, mergedCanvas.height);
ctxMerge.drawImage(segmentation3.canvas, 0, 0);
}
busy = false;
return img.canvas;
return { data: segmentation3.data, canvas: mergedCanvas || segmentation3.canvas, alpha: segmentation3.alpha };
}
// src/models.ts
@ -72544,7 +72577,7 @@ var Human = class {
return similarity(embedding1, embedding2);
}
async segmentation(input2, background) {
return input2 ? process5(input2, background, this.config) : null;
return process5(input2, background, this.config);
}
enhance(input2) {
return enhance(input2);
@ -72616,24 +72649,10 @@ var Human = class {
await this.load();
timeStamp = now();
this.state = "image";
let img = process2(input2, this.config);
const img = process2(input2, this.config);
this.process = img;
this.performance.image = Math.trunc(now() - timeStamp);
this.analyze("Get Image:");
if (this.config.segmentation.enabled && this.process && img.tensor && img.canvas) {
this.analyze("Start Segmentation:");
this.state = "detect:segmentation";
timeStamp = now();
await predict12(img);
elapsedTime = Math.trunc(now() - timeStamp);
if (elapsedTime > 0)
this.performance.segmentation = elapsedTime;
if (img.canvas) {
dispose(img.tensor);
img = process2(img.canvas, this.config);
}
this.analyze("End Segmentation:");
}
if (!img.tensor) {
if (this.config.debug)
log("could not convert input to tensor");

File diff suppressed because one or more lines are too long

532
dist/human.js vendored

File diff suppressed because one or more lines are too long

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

@ -246,7 +246,8 @@ var config = {
},
segmentation: {
enabled: false,
modelPath: "selfie.json"
modelPath: "selfie.json",
blur: 8
}
};
@ -281,13 +282,13 @@ function getBoxCenter(box6) {
function cutBoxFromImageAndResize(box6, image23, cropSize) {
const h = image23.shape[1];
const w = image23.shape[2];
const boxes2 = [[
const boxes = [[
box6.startPoint[1] / h,
box6.startPoint[0] / w,
box6.endPoint[1] / h,
box6.endPoint[0] / w
]];
return tf.image.cropAndResize(image23, boxes2, [0], cropSize);
return tf.image.cropAndResize(image23, boxes, [0], cropSize);
}
function enlargeBox(box6, factor = 1.5) {
const center = getBoxCenter(box6);
@ -437,7 +438,7 @@ var BlazeFaceModel = class {
var _a, _b, _c, _d;
if (!inputImage || inputImage["isDisposedInternal"] || inputImage.shape.length !== 4 || inputImage.shape[1] < 1 || inputImage.shape[2] < 1)
return { boxes: [] };
const [batch, boxes2, scores] = tf2.tidy(() => {
const [batch, boxes, scores] = tf2.tidy(() => {
const resizedImage = tf2.image.resizeBilinear(inputImage, [this.inputSize, this.inputSize]);
const normalizedImage = tf2.sub(tf2.div(resizedImage, 127.5), 0.5);
const res = this.model.execute(normalizedImage);
@ -457,7 +458,7 @@ var BlazeFaceModel = class {
return [batchOut, boxesOut, scoresOut];
});
this.config = mergeDeep(this.config, userConfig);
const nmsTensor = await tf2.image.nonMaxSuppressionAsync(boxes2, scores, ((_a = this.config.face.detector) == null ? void 0 : _a.maxDetected) || 0, ((_b = this.config.face.detector) == null ? void 0 : _b.iouThreshold) || 0, ((_c = this.config.face.detector) == null ? void 0 : _c.minConfidence) || 0);
const nmsTensor = await tf2.image.nonMaxSuppressionAsync(boxes, scores, ((_a = this.config.face.detector) == null ? void 0 : _a.maxDetected) || 0, ((_b = this.config.face.detector) == null ? void 0 : _b.iouThreshold) || 0, ((_c = this.config.face.detector) == null ? void 0 : _c.minConfidence) || 0);
const nms = await nmsTensor.array();
tf2.dispose(nmsTensor);
const annotatedBoxes = [];
@ -465,14 +466,14 @@ var BlazeFaceModel = class {
for (let i = 0; i < nms.length; i++) {
const confidence = scoresData[nms[i]];
if (confidence > (((_d = this.config.face.detector) == null ? void 0 : _d.minConfidence) || 0)) {
const boundingBox = tf2.slice(boxes2, [nms[i], 0], [1, -1]);
const boundingBox = tf2.slice(boxes, [nms[i], 0], [1, -1]);
const landmarks = tf2.tidy(() => tf2.reshape(tf2.squeeze(tf2.slice(batch, [nms[i], keypointsCount - 1], [1, -1])), [keypointsCount, -1]));
annotatedBoxes.push({ box: createBox(boundingBox), landmarks, anchor: this.anchorsData[nms[i]], confidence });
tf2.dispose(boundingBox);
}
}
tf2.dispose(batch);
tf2.dispose(boxes2);
tf2.dispose(boxes);
tf2.dispose(scores);
return {
boxes: annotatedBoxes,
@ -5671,13 +5672,13 @@ function getBoxCenter2(box6) {
function cutBoxFromImageAndResize2(box6, image23, cropSize) {
const h = image23.shape[1];
const w = image23.shape[2];
const boxes2 = [[
const boxes = [[
box6.startPoint[1] / h,
box6.startPoint[0] / w,
box6.endPoint[1] / h,
box6.endPoint[0] / w
]];
return tf10.image.cropAndResize(image23, boxes2, [0], cropSize);
return tf10.image.cropAndResize(image23, boxes, [0], cropSize);
}
function scaleBoxCoordinates2(box6, factor) {
const startPoint = [box6.startPoint[0] * factor[0], box6.startPoint[1] * factor[1]];
@ -8670,10 +8671,10 @@ var HandDetector = class {
this.inputSizeTensor = tf11.tensor1d([this.inputSize, this.inputSize]);
this.doubleInputSizeTensor = tf11.tensor1d([this.inputSize * 2, this.inputSize * 2]);
}
normalizeBoxes(boxes2) {
normalizeBoxes(boxes) {
return tf11.tidy(() => {
const boxOffsets = tf11.slice(boxes2, [0, 0], [-1, 2]);
const boxSizes = tf11.slice(boxes2, [0, 2], [-1, 2]);
const boxOffsets = tf11.slice(boxes, [0, 0], [-1, 2]);
const boxSizes = tf11.slice(boxes, [0, 2], [-1, 2]);
const boxCenterPoints = tf11.add(tf11.div(boxOffsets, this.inputSizeTensor), this.anchorsTensor);
const halfBoxSizes = tf11.div(boxSizes, this.doubleInputSizeTensor);
const startPoints = tf11.mul(tf11.sub(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
@ -8717,9 +8718,9 @@ var HandDetector = class {
if (!predictions || predictions.length === 0)
return hands;
for (const prediction of predictions) {
const boxes2 = await prediction.box.data();
const startPoint = boxes2.slice(0, 2);
const endPoint = boxes2.slice(2, 4);
const boxes = await prediction.box.data();
const startPoint = boxes.slice(0, 2);
const endPoint = boxes.slice(2, 4);
const palmLandmarks = await prediction.palmLandmarks.array();
tf11.dispose(prediction.box);
tf11.dispose(prediction.palmLandmarks);
@ -8864,16 +8865,16 @@ var HandPipeline = class {
}
async estimateHands(image23, config3) {
let useFreshBox = false;
let boxes2;
let boxes;
if (this.skipped === 0 || this.skipped > config3.hand.skipFrames || !config3.hand.landmarks || !config3.skipFrame) {
boxes2 = await this.handDetector.estimateHandBounds(image23, config3);
boxes = await this.handDetector.estimateHandBounds(image23, config3);
this.skipped = 0;
}
if (config3.skipFrame)
this.skipped++;
if (boxes2 && boxes2.length > 0 && (boxes2.length !== this.detectedHands && this.detectedHands !== config3.hand.maxDetected || !config3.hand.landmarks)) {
if (boxes && boxes.length > 0 && (boxes.length !== this.detectedHands && this.detectedHands !== config3.hand.maxDetected || !config3.hand.landmarks)) {
this.detectedHands = 0;
this.storedBoxes = [...boxes2];
this.storedBoxes = [...boxes];
if (this.storedBoxes.length > 0)
useFreshBox = true;
}
@ -9426,7 +9427,7 @@ async function load6(config3) {
var tf14 = __toModule(require_tfjs_esm());
var models = [null, null];
var modelOutputNodes = ["StatefulPartitionedCall/Postprocessor/Slice", "StatefulPartitionedCall/Postprocessor/ExpandDims_1"];
var inputSize = [0, 0];
var inputSize = [[0, 0], [0, 0]];
var classes = [
"hand",
"fist",
@ -9438,7 +9439,11 @@ var classes = [
];
var skipped3 = 0;
var outputSize;
var boxes = [];
var cache = {
handBoxes: [],
fingerBoxes: [],
tmpBoxes: []
};
var fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
@ -9456,7 +9461,8 @@ async function load7(config3) {
if (!models[0]) {
models[0] = await tf14.loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""));
const inputs = Object.values(models[0].modelSignature["inputs"]);
inputSize[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[0][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[0][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[0] || !models[0]["modelUrl"])
log("load model failed:", config3.object.modelPath);
else if (config3.debug)
@ -9466,7 +9472,8 @@ async function load7(config3) {
if (!models[1]) {
models[1] = await tf14.loadGraphModel(join(config3.modelBasePath, ((_b = config3.hand.skeleton) == null ? void 0 : _b.modelPath) || ""));
const inputs = Object.values(models[1].modelSignature["inputs"]);
inputSize[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[1][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[1][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[1] || !models[1]["modelUrl"])
log("load model failed:", config3.object.modelPath);
else if (config3.debug)
@ -9480,7 +9487,10 @@ async function detectHands(input, config3) {
if (!input || !models[0])
return hands;
const t = {};
t.resize = tf14.image.resizeBilinear(input, [240, 320]);
const ratio = (input.shape[2] || 1) / (input.shape[1] || 1);
const height = Math.min(Math.round((input.shape[1] || 0) / 8) * 8, 512);
const width = Math.round(height * ratio / 8) * 8;
t.resize = tf14.image.resizeBilinear(input, [height, width]);
t.cast = tf14.cast(t.resize, "int32");
[t.rawScores, t.rawBoxes] = await models[0].executeAsync(t.cast, modelOutputNodes);
t.boxes = tf14.squeeze(t.rawBoxes, [0, 2]);
@ -9508,8 +9518,36 @@ async function detectHands(input, config3) {
}
classScores.forEach((tensor3) => tf14.dispose(tensor3));
Object.keys(t).forEach((tensor3) => tf14.dispose(t[tensor3]));
hands.sort((a, b) => b.score - a.score);
if (hands.length > (config3.hand.maxDetected || 1))
hands.length = config3.hand.maxDetected || 1;
return hands;
}
var boxScaleFact = 1.5;
function updateBoxes(h, keypoints3) {
const finger = [keypoints3.map((pt) => pt[0]), keypoints3.map((pt) => pt[1])];
const minmax = [Math.min(...finger[0]), Math.max(...finger[0]), Math.min(...finger[1]), Math.max(...finger[1])];
const center = [(minmax[0] + minmax[1]) / 2, (minmax[2] + minmax[3]) / 2];
const diff = Math.max(center[0] - minmax[0], center[1] - minmax[2], -center[0] + minmax[1], -center[1] + minmax[3]) * boxScaleFact;
h.box = [
Math.trunc(center[0] - diff),
Math.trunc(center[1] - diff),
Math.trunc(2 * diff),
Math.trunc(2 * diff)
];
h.boxRaw = [
h.box[0] / outputSize[0],
h.box[1] / outputSize[1],
h.box[2] / outputSize[0],
h.box[3] / outputSize[1]
];
h.yxBox = [
h.boxRaw[1],
h.boxRaw[0],
h.boxRaw[3] + h.boxRaw[1],
h.boxRaw[2] + h.boxRaw[0]
];
}
async function detectFingers(input, h, config3) {
const hand3 = {
id: h.id,
@ -9523,46 +9561,57 @@ async function detectFingers(input, h, config3) {
landmarks: {},
annotations: {}
};
if (!input || !models[1] || !config3.hand.landmarks)
if (!input || !models[1])
return hand3;
const t = {};
t.crop = tf14.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1], inputSize[1]], "bilinear");
t.cast = tf14.cast(t.crop, "float32");
t.div = tf14.div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div);
const score3 = Math.round(100 * (await t.score.data())[0] / 100);
if (score3 > (config3.hand.minConfidence || 0)) {
hand3.fingerScore = score3;
t.reshaped = tf14.reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array();
hand3.keypoints = rawCoords.map((coord) => [
h.box[2] * coord[0] / inputSize[1] + h.box[0],
h.box[3] * coord[1] / inputSize[1] + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1] * coord[2]
]);
hand3.landmarks = analyze(hand3.keypoints);
for (const key of Object.keys(fingerMap)) {
hand3.annotations[key] = fingerMap[key].map((index) => hand3.landmarks && hand3.keypoints[index] ? hand3.keypoints[index] : null);
if (config3.hand.landmarks) {
const t = {};
if (!h.yxBox)
return hand3;
t.crop = tf14.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1][0], inputSize[1][1]], "bilinear");
t.cast = tf14.cast(t.crop, "float32");
t.div = tf14.div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div);
const score3 = Math.round(100 * (await t.score.data())[0] / 100);
if (score3 > (config3.hand.minConfidence || 0)) {
hand3.fingerScore = score3;
t.reshaped = tf14.reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array();
hand3.keypoints = rawCoords.map((coord) => [
h.box[2] * coord[0] / inputSize[1][0] + h.box[0],
h.box[3] * coord[1] / inputSize[1][1] + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1][0] * coord[2]
]);
updateBoxes(h, hand3.keypoints);
hand3.box = h.box;
hand3.landmarks = analyze(hand3.keypoints);
for (const key of Object.keys(fingerMap)) {
hand3.annotations[key] = fingerMap[key].map((index) => hand3.landmarks && hand3.keypoints[index] ? hand3.keypoints[index] : null);
}
cache.tmpBoxes.push(h);
}
Object.keys(t).forEach((tensor3) => tf14.dispose(t[tensor3]));
}
Object.keys(t).forEach((tensor3) => tf14.dispose(t[tensor3]));
return hand3;
}
var last3 = 0;
async function predict6(input, config3) {
outputSize = [input.shape[2] || 0, input.shape[1] || 0];
if (skipped3 < (config3.object.skipFrames || 0) && config3.skipFrame) {
let hands = [];
cache.tmpBoxes = [];
if (!config3.hand.landmarks)
cache.fingerBoxes = cache.handBoxes;
if (skipped3 < (config3.hand.skipFrames || 0) && config3.skipFrame) {
skipped3++;
const hands2 = await Promise.all(boxes.map((hand3) => detectFingers(input, hand3, config3)));
const withFingers2 = hands2.filter((hand3) => hand3.fingerScore > 0).length;
if (withFingers2 === last3)
return hands2;
hands = await Promise.all(cache.fingerBoxes.map((hand3) => detectFingers(input, hand3, config3)));
} else {
skipped3 = 0;
hands = await Promise.all(cache.fingerBoxes.map((hand3) => detectFingers(input, hand3, config3)));
if (hands.length !== config3.hand.maxDetected) {
cache.handBoxes = await detectHands(input, config3);
const newHands = await Promise.all(cache.handBoxes.map((hand3) => detectFingers(input, hand3, config3)));
hands = hands.concat(newHands);
}
}
skipped3 = 0;
boxes = await detectHands(input, config3);
const hands = await Promise.all(boxes.map((hand3) => detectFingers(input, hand3, config3)));
const withFingers = hands.filter((hand3) => hand3.fingerScore > 0).length;
last3 = withFingers;
cache.fingerBoxes = [...cache.tmpBoxes];
return hands;
}
@ -10041,7 +10090,7 @@ var labels = [
// src/object/nanodet.ts
var model7;
var last4 = [];
var last3 = [];
var skipped6 = Number.MAX_SAFE_INTEGER;
var scaleBox = 2.5;
async function load11(config3) {
@ -10121,13 +10170,13 @@ async function process3(res, inputSize3, outputShape, config3) {
return results;
}
async function predict10(image23, config3) {
if (skipped6 < (config3.object.skipFrames || 0) && config3.skipFrame && last4.length > 0) {
if (skipped6 < (config3.object.skipFrames || 0) && config3.skipFrame && last3.length > 0) {
skipped6++;
return last4;
return last3;
}
skipped6 = 0;
if (!env.kernels.includes("mod") || !env.kernels.includes("sparsetodense"))
return last4;
return last3;
return new Promise(async (resolve) => {
const outputSize2 = [image23.shape[2], image23.shape[1]];
const resize = tf18.image.resizeBilinear(image23, [model7.inputSize, model7.inputSize], false);
@ -10140,7 +10189,7 @@ async function predict10(image23, config3) {
objectT = await model7.predict(transpose);
tf18.dispose(transpose);
const obj = await process3(objectT, model7.inputSize, outputSize2, config3);
last4 = obj;
last3 = obj;
resolve(obj);
});
}
@ -10149,7 +10198,7 @@ async function predict10(image23, config3) {
var tf19 = __toModule(require_tfjs_esm());
var model8;
var inputSize2 = 0;
var last5 = [];
var last4 = [];
var skipped7 = Number.MAX_SAFE_INTEGER;
async function load12(config3) {
if (env.initial)
@ -10213,20 +10262,20 @@ async function process4(res, outputShape, config3) {
return results;
}
async function predict11(input, config3) {
if (skipped7 < (config3.object.skipFrames || 0) && config3.skipFrame && last5.length > 0) {
if (skipped7 < (config3.object.skipFrames || 0) && config3.skipFrame && last4.length > 0) {
skipped7++;
return last5;
return last4;
}
skipped7 = 0;
if (!env.kernels.includes("mod") || !env.kernels.includes("sparsetodense"))
return last5;
return last4;
return new Promise(async (resolve) => {
const outputSize2 = [input.shape[2], input.shape[1]];
const resize = tf19.image.resizeBilinear(input, [inputSize2, inputSize2]);
const objectT = config3.object.enabled ? model8 == null ? void 0 : model8.execute(resize, ["tower_0/detections"]) : null;
tf19.dispose(resize);
const obj = await process4(objectT, outputSize2, config3);
last5 = obj;
last4 = obj;
resolve(obj);
});
}
@ -10246,14 +10295,12 @@ async function load13(config3) {
log("cached model:", model9["modelUrl"]);
return model9;
}
async function predict12(input) {
async function predict12(input, config3) {
var _a, _b;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[1]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[2]) || 0;
if (!input.tensor)
return null;
if (!model9 || !model9.inputs[0].shape)
return null;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[2]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[1]) || 0;
if (!input.tensor || !model9 || !model9.inputs[0].shape)
return { data: null, canvas: null, alpha: null };
const resizeInput = tf20.image.resizeBilinear(input.tensor, [model9.inputs[0].shape[1], model9.inputs[0].shape[2]], false);
const norm = tf20.div(resizeInput, 255);
const res = model9.predict(norm);
@ -10261,7 +10308,7 @@ async function predict12(input) {
tf20.dispose(norm);
const squeeze8 = tf20.squeeze(res, 0);
tf20.dispose(res);
let resizeOutput;
let dataT;
if (squeeze8.shape[2] === 2) {
const softmax = squeeze8.softmax();
const [bg, fg] = tf20.unstack(softmax, 2);
@ -10271,77 +10318,63 @@ async function predict12(input) {
tf20.dispose(bg);
tf20.dispose(fg);
const crop = tf20.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
resizeOutput = tf20.squeeze(crop, 0);
dataT = tf20.squeeze(crop, 0);
tf20.dispose(crop);
tf20.dispose(expand);
tf20.dispose(pad);
} else {
resizeOutput = tf20.image.resizeBilinear(squeeze8, [width, height]);
dataT = tf20.image.resizeBilinear(squeeze8, [height, width]);
}
tf20.dispose(squeeze8);
const data = await dataT.dataSync();
if (env.node) {
const data = await resizeOutput.data();
tf20.dispose(resizeOutput);
return data;
tf20.dispose(dataT);
return { data, canvas: null, alpha: null };
}
const overlay = canvas(width, height);
if (tf20.browser)
await tf20.browser.toPixels(resizeOutput, overlay);
tf20.dispose(resizeOutput);
const alphaCanvas = canvas(width, height);
const ctxAlpha = alphaCanvas.getContext("2d");
ctxAlpha.filter = "blur(8px";
await ctxAlpha.drawImage(overlay, 0, 0);
const alpha = ctxAlpha.getImageData(0, 0, width, height).data;
const original = canvas(width, height);
const ctx = original.getContext("2d");
await tf20.browser.toPixels(dataT, alphaCanvas);
tf20.dispose(dataT);
const alphaCtx = alphaCanvas.getContext("2d");
if (config3.segmentation.blur && config3.segmentation.blur > 0)
alphaCtx.filter = `blur(${config3.segmentation.blur}px)`;
const alphaData = alphaCtx.getImageData(0, 0, width, height);
const compositeCanvas = canvas(width, height);
const compositeCtx = compositeCanvas.getContext("2d");
if (input.canvas)
await ctx.drawImage(input.canvas, 0, 0);
ctx.globalCompositeOperation = "darken";
ctx.filter = "blur(8px)";
await ctx.drawImage(overlay, 0, 0);
ctx.globalCompositeOperation = "source-over";
ctx.filter = "none";
input.canvas = original;
return alpha;
compositeCtx.drawImage(input.canvas, 0, 0);
compositeCtx.globalCompositeOperation = "darken";
if (config3.segmentation.blur && config3.segmentation.blur > 0)
compositeCtx.filter = `blur(${config3.segmentation.blur}px)`;
compositeCtx.drawImage(alphaCanvas, 0, 0);
compositeCtx.globalCompositeOperation = "source-over";
compositeCtx.filter = "none";
const compositeData = compositeCtx.getImageData(0, 0, width, height);
for (let i = 0; i < width * height; i++)
compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0];
compositeCtx.putImageData(compositeData, 0, 0);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
async function process5(input, background, config3) {
var _a;
var _a, _b;
if (busy)
return null;
return { data: null, canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const img = process2(input, config3);
const tmp = process2(background, config3);
if (!img.canvas || !tmp.canvas) {
if (config3.debug)
log("segmentation cannot process input or background");
return null;
}
const alpha = await predict12(img);
tf20.dispose(img.tensor);
if (background && alpha) {
const bg = tmp.canvas;
tf20.dispose(tmp.tensor);
const fg = img.canvas;
const fgData = (_a = fg.getContext("2d")) == null ? void 0 : _a.getImageData(0, 0, fg.width, fg.height).data;
const c = canvas(fg.width, fg.height);
const ctx = c.getContext("2d");
ctx.globalCompositeOperation = "copy";
ctx.drawImage(bg, 0, 0, c.width, c.height);
const cData = ctx.getImageData(0, 0, c.width, c.height);
for (let i = 0; i < c.width * c.height; i++) {
cData.data[4 * i + 0] = (255 - alpha[4 * i + 0]) / 255 * cData.data[4 * i + 0] + alpha[4 * i + 0] / 255 * fgData[4 * i + 0];
cData.data[4 * i + 1] = (255 - alpha[4 * i + 1]) / 255 * cData.data[4 * i + 1] + alpha[4 * i + 1] / 255 * fgData[4 * i + 1];
cData.data[4 * i + 2] = (255 - alpha[4 * i + 2]) / 255 * cData.data[4 * i + 2] + alpha[4 * i + 2] / 255 * fgData[4 * i + 2];
cData.data[4 * i + 3] = (255 - alpha[4 * i + 3]) / 255 * cData.data[4 * i + 3] + alpha[4 * i + 3] / 255 * fgData[4 * i + 3];
}
ctx.putImageData(cData, 0, 0);
img.canvas = c;
const inputImage = process2(input, config3);
const segmentation3 = await predict12(inputImage, config3);
tf20.dispose(inputImage.tensor);
let mergedCanvas = null;
if (background && segmentation3.canvas) {
mergedCanvas = canvas(((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0, ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0);
const bgImage = process2(background, config3);
tf20.dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext("2d");
ctxMerge.drawImage(bgImage.canvas, 0, 0, mergedCanvas.width, mergedCanvas.height);
ctxMerge.drawImage(segmentation3.canvas, 0, 0);
}
busy = false;
return img.canvas;
return { data: segmentation3.data, canvas: mergedCanvas || segmentation3.canvas, alpha: segmentation3.alpha };
}
// src/models.ts
@ -12551,7 +12584,7 @@ var Human = class {
return similarity(embedding1, embedding2);
}
async segmentation(input, background) {
return input ? process5(input, background, this.config) : null;
return process5(input, background, this.config);
}
enhance(input) {
return enhance(input);
@ -12623,24 +12656,10 @@ var Human = class {
await this.load();
timeStamp = now();
this.state = "image";
let img = process2(input, this.config);
const img = process2(input, this.config);
this.process = img;
this.performance.image = Math.trunc(now() - timeStamp);
this.analyze("Get Image:");
if (this.config.segmentation.enabled && this.process && img.tensor && img.canvas) {
this.analyze("Start Segmentation:");
this.state = "detect:segmentation";
timeStamp = now();
await predict12(img);
elapsedTime = Math.trunc(now() - timeStamp);
if (elapsedTime > 0)
this.performance.segmentation = elapsedTime;
if (img.canvas) {
tf25.dispose(img.tensor);
img = process2(img.canvas, this.config);
}
this.analyze("End Segmentation:");
}
if (!img.tensor) {
if (this.config.debug)
log("could not convert input to tensor");

View File

@ -247,7 +247,8 @@ var config = {
},
segmentation: {
enabled: false,
modelPath: "selfie.json"
modelPath: "selfie.json",
blur: 8
}
};
@ -282,13 +283,13 @@ function getBoxCenter(box6) {
function cutBoxFromImageAndResize(box6, image23, cropSize) {
const h = image23.shape[1];
const w = image23.shape[2];
const boxes2 = [[
const boxes = [[
box6.startPoint[1] / h,
box6.startPoint[0] / w,
box6.endPoint[1] / h,
box6.endPoint[0] / w
]];
return tf.image.cropAndResize(image23, boxes2, [0], cropSize);
return tf.image.cropAndResize(image23, boxes, [0], cropSize);
}
function enlargeBox(box6, factor = 1.5) {
const center = getBoxCenter(box6);
@ -438,7 +439,7 @@ var BlazeFaceModel = class {
var _a, _b, _c, _d;
if (!inputImage || inputImage["isDisposedInternal"] || inputImage.shape.length !== 4 || inputImage.shape[1] < 1 || inputImage.shape[2] < 1)
return { boxes: [] };
const [batch, boxes2, scores] = tf2.tidy(() => {
const [batch, boxes, scores] = tf2.tidy(() => {
const resizedImage = tf2.image.resizeBilinear(inputImage, [this.inputSize, this.inputSize]);
const normalizedImage = tf2.sub(tf2.div(resizedImage, 127.5), 0.5);
const res = this.model.execute(normalizedImage);
@ -458,7 +459,7 @@ var BlazeFaceModel = class {
return [batchOut, boxesOut, scoresOut];
});
this.config = mergeDeep(this.config, userConfig);
const nmsTensor = await tf2.image.nonMaxSuppressionAsync(boxes2, scores, ((_a = this.config.face.detector) == null ? void 0 : _a.maxDetected) || 0, ((_b = this.config.face.detector) == null ? void 0 : _b.iouThreshold) || 0, ((_c = this.config.face.detector) == null ? void 0 : _c.minConfidence) || 0);
const nmsTensor = await tf2.image.nonMaxSuppressionAsync(boxes, scores, ((_a = this.config.face.detector) == null ? void 0 : _a.maxDetected) || 0, ((_b = this.config.face.detector) == null ? void 0 : _b.iouThreshold) || 0, ((_c = this.config.face.detector) == null ? void 0 : _c.minConfidence) || 0);
const nms = await nmsTensor.array();
tf2.dispose(nmsTensor);
const annotatedBoxes = [];
@ -466,14 +467,14 @@ var BlazeFaceModel = class {
for (let i = 0; i < nms.length; i++) {
const confidence = scoresData[nms[i]];
if (confidence > (((_d = this.config.face.detector) == null ? void 0 : _d.minConfidence) || 0)) {
const boundingBox = tf2.slice(boxes2, [nms[i], 0], [1, -1]);
const boundingBox = tf2.slice(boxes, [nms[i], 0], [1, -1]);
const landmarks = tf2.tidy(() => tf2.reshape(tf2.squeeze(tf2.slice(batch, [nms[i], keypointsCount - 1], [1, -1])), [keypointsCount, -1]));
annotatedBoxes.push({ box: createBox(boundingBox), landmarks, anchor: this.anchorsData[nms[i]], confidence });
tf2.dispose(boundingBox);
}
}
tf2.dispose(batch);
tf2.dispose(boxes2);
tf2.dispose(boxes);
tf2.dispose(scores);
return {
boxes: annotatedBoxes,
@ -5672,13 +5673,13 @@ function getBoxCenter2(box6) {
function cutBoxFromImageAndResize2(box6, image23, cropSize) {
const h = image23.shape[1];
const w = image23.shape[2];
const boxes2 = [[
const boxes = [[
box6.startPoint[1] / h,
box6.startPoint[0] / w,
box6.endPoint[1] / h,
box6.endPoint[0] / w
]];
return tf10.image.cropAndResize(image23, boxes2, [0], cropSize);
return tf10.image.cropAndResize(image23, boxes, [0], cropSize);
}
function scaleBoxCoordinates2(box6, factor) {
const startPoint = [box6.startPoint[0] * factor[0], box6.startPoint[1] * factor[1]];
@ -8671,10 +8672,10 @@ var HandDetector = class {
this.inputSizeTensor = tf11.tensor1d([this.inputSize, this.inputSize]);
this.doubleInputSizeTensor = tf11.tensor1d([this.inputSize * 2, this.inputSize * 2]);
}
normalizeBoxes(boxes2) {
normalizeBoxes(boxes) {
return tf11.tidy(() => {
const boxOffsets = tf11.slice(boxes2, [0, 0], [-1, 2]);
const boxSizes = tf11.slice(boxes2, [0, 2], [-1, 2]);
const boxOffsets = tf11.slice(boxes, [0, 0], [-1, 2]);
const boxSizes = tf11.slice(boxes, [0, 2], [-1, 2]);
const boxCenterPoints = tf11.add(tf11.div(boxOffsets, this.inputSizeTensor), this.anchorsTensor);
const halfBoxSizes = tf11.div(boxSizes, this.doubleInputSizeTensor);
const startPoints = tf11.mul(tf11.sub(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
@ -8718,9 +8719,9 @@ var HandDetector = class {
if (!predictions || predictions.length === 0)
return hands;
for (const prediction of predictions) {
const boxes2 = await prediction.box.data();
const startPoint = boxes2.slice(0, 2);
const endPoint = boxes2.slice(2, 4);
const boxes = await prediction.box.data();
const startPoint = boxes.slice(0, 2);
const endPoint = boxes.slice(2, 4);
const palmLandmarks = await prediction.palmLandmarks.array();
tf11.dispose(prediction.box);
tf11.dispose(prediction.palmLandmarks);
@ -8865,16 +8866,16 @@ var HandPipeline = class {
}
async estimateHands(image23, config3) {
let useFreshBox = false;
let boxes2;
let boxes;
if (this.skipped === 0 || this.skipped > config3.hand.skipFrames || !config3.hand.landmarks || !config3.skipFrame) {
boxes2 = await this.handDetector.estimateHandBounds(image23, config3);
boxes = await this.handDetector.estimateHandBounds(image23, config3);
this.skipped = 0;
}
if (config3.skipFrame)
this.skipped++;
if (boxes2 && boxes2.length > 0 && (boxes2.length !== this.detectedHands && this.detectedHands !== config3.hand.maxDetected || !config3.hand.landmarks)) {
if (boxes && boxes.length > 0 && (boxes.length !== this.detectedHands && this.detectedHands !== config3.hand.maxDetected || !config3.hand.landmarks)) {
this.detectedHands = 0;
this.storedBoxes = [...boxes2];
this.storedBoxes = [...boxes];
if (this.storedBoxes.length > 0)
useFreshBox = true;
}
@ -9427,7 +9428,7 @@ async function load6(config3) {
var tf14 = __toModule(require_tfjs_esm());
var models = [null, null];
var modelOutputNodes = ["StatefulPartitionedCall/Postprocessor/Slice", "StatefulPartitionedCall/Postprocessor/ExpandDims_1"];
var inputSize = [0, 0];
var inputSize = [[0, 0], [0, 0]];
var classes = [
"hand",
"fist",
@ -9439,7 +9440,11 @@ var classes = [
];
var skipped3 = 0;
var outputSize;
var boxes = [];
var cache = {
handBoxes: [],
fingerBoxes: [],
tmpBoxes: []
};
var fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
@ -9457,7 +9462,8 @@ async function load7(config3) {
if (!models[0]) {
models[0] = await tf14.loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""));
const inputs = Object.values(models[0].modelSignature["inputs"]);
inputSize[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[0][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[0][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[0] || !models[0]["modelUrl"])
log("load model failed:", config3.object.modelPath);
else if (config3.debug)
@ -9467,7 +9473,8 @@ async function load7(config3) {
if (!models[1]) {
models[1] = await tf14.loadGraphModel(join(config3.modelBasePath, ((_b = config3.hand.skeleton) == null ? void 0 : _b.modelPath) || ""));
const inputs = Object.values(models[1].modelSignature["inputs"]);
inputSize[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[1][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[1][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[1] || !models[1]["modelUrl"])
log("load model failed:", config3.object.modelPath);
else if (config3.debug)
@ -9481,7 +9488,10 @@ async function detectHands(input, config3) {
if (!input || !models[0])
return hands;
const t = {};
t.resize = tf14.image.resizeBilinear(input, [240, 320]);
const ratio = (input.shape[2] || 1) / (input.shape[1] || 1);
const height = Math.min(Math.round((input.shape[1] || 0) / 8) * 8, 512);
const width = Math.round(height * ratio / 8) * 8;
t.resize = tf14.image.resizeBilinear(input, [height, width]);
t.cast = tf14.cast(t.resize, "int32");
[t.rawScores, t.rawBoxes] = await models[0].executeAsync(t.cast, modelOutputNodes);
t.boxes = tf14.squeeze(t.rawBoxes, [0, 2]);
@ -9509,8 +9519,36 @@ async function detectHands(input, config3) {
}
classScores.forEach((tensor3) => tf14.dispose(tensor3));
Object.keys(t).forEach((tensor3) => tf14.dispose(t[tensor3]));
hands.sort((a, b) => b.score - a.score);
if (hands.length > (config3.hand.maxDetected || 1))
hands.length = config3.hand.maxDetected || 1;
return hands;
}
var boxScaleFact = 1.5;
function updateBoxes(h, keypoints3) {
const finger = [keypoints3.map((pt) => pt[0]), keypoints3.map((pt) => pt[1])];
const minmax = [Math.min(...finger[0]), Math.max(...finger[0]), Math.min(...finger[1]), Math.max(...finger[1])];
const center = [(minmax[0] + minmax[1]) / 2, (minmax[2] + minmax[3]) / 2];
const diff = Math.max(center[0] - minmax[0], center[1] - minmax[2], -center[0] + minmax[1], -center[1] + minmax[3]) * boxScaleFact;
h.box = [
Math.trunc(center[0] - diff),
Math.trunc(center[1] - diff),
Math.trunc(2 * diff),
Math.trunc(2 * diff)
];
h.boxRaw = [
h.box[0] / outputSize[0],
h.box[1] / outputSize[1],
h.box[2] / outputSize[0],
h.box[3] / outputSize[1]
];
h.yxBox = [
h.boxRaw[1],
h.boxRaw[0],
h.boxRaw[3] + h.boxRaw[1],
h.boxRaw[2] + h.boxRaw[0]
];
}
async function detectFingers(input, h, config3) {
const hand3 = {
id: h.id,
@ -9524,46 +9562,57 @@ async function detectFingers(input, h, config3) {
landmarks: {},
annotations: {}
};
if (!input || !models[1] || !config3.hand.landmarks)
if (!input || !models[1])
return hand3;
const t = {};
t.crop = tf14.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1], inputSize[1]], "bilinear");
t.cast = tf14.cast(t.crop, "float32");
t.div = tf14.div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div);
const score3 = Math.round(100 * (await t.score.data())[0] / 100);
if (score3 > (config3.hand.minConfidence || 0)) {
hand3.fingerScore = score3;
t.reshaped = tf14.reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array();
hand3.keypoints = rawCoords.map((coord) => [
h.box[2] * coord[0] / inputSize[1] + h.box[0],
h.box[3] * coord[1] / inputSize[1] + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1] * coord[2]
]);
hand3.landmarks = analyze(hand3.keypoints);
for (const key of Object.keys(fingerMap)) {
hand3.annotations[key] = fingerMap[key].map((index) => hand3.landmarks && hand3.keypoints[index] ? hand3.keypoints[index] : null);
if (config3.hand.landmarks) {
const t = {};
if (!h.yxBox)
return hand3;
t.crop = tf14.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1][0], inputSize[1][1]], "bilinear");
t.cast = tf14.cast(t.crop, "float32");
t.div = tf14.div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div);
const score3 = Math.round(100 * (await t.score.data())[0] / 100);
if (score3 > (config3.hand.minConfidence || 0)) {
hand3.fingerScore = score3;
t.reshaped = tf14.reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array();
hand3.keypoints = rawCoords.map((coord) => [
h.box[2] * coord[0] / inputSize[1][0] + h.box[0],
h.box[3] * coord[1] / inputSize[1][1] + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1][0] * coord[2]
]);
updateBoxes(h, hand3.keypoints);
hand3.box = h.box;
hand3.landmarks = analyze(hand3.keypoints);
for (const key of Object.keys(fingerMap)) {
hand3.annotations[key] = fingerMap[key].map((index) => hand3.landmarks && hand3.keypoints[index] ? hand3.keypoints[index] : null);
}
cache.tmpBoxes.push(h);
}
Object.keys(t).forEach((tensor3) => tf14.dispose(t[tensor3]));
}
Object.keys(t).forEach((tensor3) => tf14.dispose(t[tensor3]));
return hand3;
}
var last3 = 0;
async function predict6(input, config3) {
outputSize = [input.shape[2] || 0, input.shape[1] || 0];
if (skipped3 < (config3.object.skipFrames || 0) && config3.skipFrame) {
let hands = [];
cache.tmpBoxes = [];
if (!config3.hand.landmarks)
cache.fingerBoxes = cache.handBoxes;
if (skipped3 < (config3.hand.skipFrames || 0) && config3.skipFrame) {
skipped3++;
const hands2 = await Promise.all(boxes.map((hand3) => detectFingers(input, hand3, config3)));
const withFingers2 = hands2.filter((hand3) => hand3.fingerScore > 0).length;
if (withFingers2 === last3)
return hands2;
hands = await Promise.all(cache.fingerBoxes.map((hand3) => detectFingers(input, hand3, config3)));
} else {
skipped3 = 0;
hands = await Promise.all(cache.fingerBoxes.map((hand3) => detectFingers(input, hand3, config3)));
if (hands.length !== config3.hand.maxDetected) {
cache.handBoxes = await detectHands(input, config3);
const newHands = await Promise.all(cache.handBoxes.map((hand3) => detectFingers(input, hand3, config3)));
hands = hands.concat(newHands);
}
}
skipped3 = 0;
boxes = await detectHands(input, config3);
const hands = await Promise.all(boxes.map((hand3) => detectFingers(input, hand3, config3)));
const withFingers = hands.filter((hand3) => hand3.fingerScore > 0).length;
last3 = withFingers;
cache.fingerBoxes = [...cache.tmpBoxes];
return hands;
}
@ -10042,7 +10091,7 @@ var labels = [
// src/object/nanodet.ts
var model7;
var last4 = [];
var last3 = [];
var skipped6 = Number.MAX_SAFE_INTEGER;
var scaleBox = 2.5;
async function load11(config3) {
@ -10122,13 +10171,13 @@ async function process3(res, inputSize3, outputShape, config3) {
return results;
}
async function predict10(image23, config3) {
if (skipped6 < (config3.object.skipFrames || 0) && config3.skipFrame && last4.length > 0) {
if (skipped6 < (config3.object.skipFrames || 0) && config3.skipFrame && last3.length > 0) {
skipped6++;
return last4;
return last3;
}
skipped6 = 0;
if (!env.kernels.includes("mod") || !env.kernels.includes("sparsetodense"))
return last4;
return last3;
return new Promise(async (resolve) => {
const outputSize2 = [image23.shape[2], image23.shape[1]];
const resize = tf18.image.resizeBilinear(image23, [model7.inputSize, model7.inputSize], false);
@ -10141,7 +10190,7 @@ async function predict10(image23, config3) {
objectT = await model7.predict(transpose);
tf18.dispose(transpose);
const obj = await process3(objectT, model7.inputSize, outputSize2, config3);
last4 = obj;
last3 = obj;
resolve(obj);
});
}
@ -10150,7 +10199,7 @@ async function predict10(image23, config3) {
var tf19 = __toModule(require_tfjs_esm());
var model8;
var inputSize2 = 0;
var last5 = [];
var last4 = [];
var skipped7 = Number.MAX_SAFE_INTEGER;
async function load12(config3) {
if (env.initial)
@ -10214,20 +10263,20 @@ async function process4(res, outputShape, config3) {
return results;
}
async function predict11(input, config3) {
if (skipped7 < (config3.object.skipFrames || 0) && config3.skipFrame && last5.length > 0) {
if (skipped7 < (config3.object.skipFrames || 0) && config3.skipFrame && last4.length > 0) {
skipped7++;
return last5;
return last4;
}
skipped7 = 0;
if (!env.kernels.includes("mod") || !env.kernels.includes("sparsetodense"))
return last5;
return last4;
return new Promise(async (resolve) => {
const outputSize2 = [input.shape[2], input.shape[1]];
const resize = tf19.image.resizeBilinear(input, [inputSize2, inputSize2]);
const objectT = config3.object.enabled ? model8 == null ? void 0 : model8.execute(resize, ["tower_0/detections"]) : null;
tf19.dispose(resize);
const obj = await process4(objectT, outputSize2, config3);
last5 = obj;
last4 = obj;
resolve(obj);
});
}
@ -10247,14 +10296,12 @@ async function load13(config3) {
log("cached model:", model9["modelUrl"]);
return model9;
}
async function predict12(input) {
async function predict12(input, config3) {
var _a, _b;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[1]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[2]) || 0;
if (!input.tensor)
return null;
if (!model9 || !model9.inputs[0].shape)
return null;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[2]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[1]) || 0;
if (!input.tensor || !model9 || !model9.inputs[0].shape)
return { data: null, canvas: null, alpha: null };
const resizeInput = tf20.image.resizeBilinear(input.tensor, [model9.inputs[0].shape[1], model9.inputs[0].shape[2]], false);
const norm = tf20.div(resizeInput, 255);
const res = model9.predict(norm);
@ -10262,7 +10309,7 @@ async function predict12(input) {
tf20.dispose(norm);
const squeeze8 = tf20.squeeze(res, 0);
tf20.dispose(res);
let resizeOutput;
let dataT;
if (squeeze8.shape[2] === 2) {
const softmax = squeeze8.softmax();
const [bg, fg] = tf20.unstack(softmax, 2);
@ -10272,77 +10319,63 @@ async function predict12(input) {
tf20.dispose(bg);
tf20.dispose(fg);
const crop = tf20.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
resizeOutput = tf20.squeeze(crop, 0);
dataT = tf20.squeeze(crop, 0);
tf20.dispose(crop);
tf20.dispose(expand);
tf20.dispose(pad);
} else {
resizeOutput = tf20.image.resizeBilinear(squeeze8, [width, height]);
dataT = tf20.image.resizeBilinear(squeeze8, [height, width]);
}
tf20.dispose(squeeze8);
const data = await dataT.dataSync();
if (env.node) {
const data = await resizeOutput.data();
tf20.dispose(resizeOutput);
return data;
tf20.dispose(dataT);
return { data, canvas: null, alpha: null };
}
const overlay = canvas(width, height);
if (tf20.browser)
await tf20.browser.toPixels(resizeOutput, overlay);
tf20.dispose(resizeOutput);
const alphaCanvas = canvas(width, height);
const ctxAlpha = alphaCanvas.getContext("2d");
ctxAlpha.filter = "blur(8px";
await ctxAlpha.drawImage(overlay, 0, 0);
const alpha = ctxAlpha.getImageData(0, 0, width, height).data;
const original = canvas(width, height);
const ctx = original.getContext("2d");
await tf20.browser.toPixels(dataT, alphaCanvas);
tf20.dispose(dataT);
const alphaCtx = alphaCanvas.getContext("2d");
if (config3.segmentation.blur && config3.segmentation.blur > 0)
alphaCtx.filter = `blur(${config3.segmentation.blur}px)`;
const alphaData = alphaCtx.getImageData(0, 0, width, height);
const compositeCanvas = canvas(width, height);
const compositeCtx = compositeCanvas.getContext("2d");
if (input.canvas)
await ctx.drawImage(input.canvas, 0, 0);
ctx.globalCompositeOperation = "darken";
ctx.filter = "blur(8px)";
await ctx.drawImage(overlay, 0, 0);
ctx.globalCompositeOperation = "source-over";
ctx.filter = "none";
input.canvas = original;
return alpha;
compositeCtx.drawImage(input.canvas, 0, 0);
compositeCtx.globalCompositeOperation = "darken";
if (config3.segmentation.blur && config3.segmentation.blur > 0)
compositeCtx.filter = `blur(${config3.segmentation.blur}px)`;
compositeCtx.drawImage(alphaCanvas, 0, 0);
compositeCtx.globalCompositeOperation = "source-over";
compositeCtx.filter = "none";
const compositeData = compositeCtx.getImageData(0, 0, width, height);
for (let i = 0; i < width * height; i++)
compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0];
compositeCtx.putImageData(compositeData, 0, 0);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
async function process5(input, background, config3) {
var _a;
var _a, _b;
if (busy)
return null;
return { data: null, canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const img = process2(input, config3);
const tmp = process2(background, config3);
if (!img.canvas || !tmp.canvas) {
if (config3.debug)
log("segmentation cannot process input or background");
return null;
}
const alpha = await predict12(img);
tf20.dispose(img.tensor);
if (background && alpha) {
const bg = tmp.canvas;
tf20.dispose(tmp.tensor);
const fg = img.canvas;
const fgData = (_a = fg.getContext("2d")) == null ? void 0 : _a.getImageData(0, 0, fg.width, fg.height).data;
const c = canvas(fg.width, fg.height);
const ctx = c.getContext("2d");
ctx.globalCompositeOperation = "copy";
ctx.drawImage(bg, 0, 0, c.width, c.height);
const cData = ctx.getImageData(0, 0, c.width, c.height);
for (let i = 0; i < c.width * c.height; i++) {
cData.data[4 * i + 0] = (255 - alpha[4 * i + 0]) / 255 * cData.data[4 * i + 0] + alpha[4 * i + 0] / 255 * fgData[4 * i + 0];
cData.data[4 * i + 1] = (255 - alpha[4 * i + 1]) / 255 * cData.data[4 * i + 1] + alpha[4 * i + 1] / 255 * fgData[4 * i + 1];
cData.data[4 * i + 2] = (255 - alpha[4 * i + 2]) / 255 * cData.data[4 * i + 2] + alpha[4 * i + 2] / 255 * fgData[4 * i + 2];
cData.data[4 * i + 3] = (255 - alpha[4 * i + 3]) / 255 * cData.data[4 * i + 3] + alpha[4 * i + 3] / 255 * fgData[4 * i + 3];
}
ctx.putImageData(cData, 0, 0);
img.canvas = c;
const inputImage = process2(input, config3);
const segmentation3 = await predict12(inputImage, config3);
tf20.dispose(inputImage.tensor);
let mergedCanvas = null;
if (background && segmentation3.canvas) {
mergedCanvas = canvas(((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0, ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0);
const bgImage = process2(background, config3);
tf20.dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext("2d");
ctxMerge.drawImage(bgImage.canvas, 0, 0, mergedCanvas.width, mergedCanvas.height);
ctxMerge.drawImage(segmentation3.canvas, 0, 0);
}
busy = false;
return img.canvas;
return { data: segmentation3.data, canvas: mergedCanvas || segmentation3.canvas, alpha: segmentation3.alpha };
}
// src/models.ts
@ -12552,7 +12585,7 @@ var Human = class {
return similarity(embedding1, embedding2);
}
async segmentation(input, background) {
return input ? process5(input, background, this.config) : null;
return process5(input, background, this.config);
}
enhance(input) {
return enhance(input);
@ -12624,24 +12657,10 @@ var Human = class {
await this.load();
timeStamp = now();
this.state = "image";
let img = process2(input, this.config);
const img = process2(input, this.config);
this.process = img;
this.performance.image = Math.trunc(now() - timeStamp);
this.analyze("Get Image:");
if (this.config.segmentation.enabled && this.process && img.tensor && img.canvas) {
this.analyze("Start Segmentation:");
this.state = "detect:segmentation";
timeStamp = now();
await predict12(img);
elapsedTime = Math.trunc(now() - timeStamp);
if (elapsedTime > 0)
this.performance.segmentation = elapsedTime;
if (img.canvas) {
tf25.dispose(img.tensor);
img = process2(img.canvas, this.config);
}
this.analyze("End Segmentation:");
}
if (!img.tensor) {
if (this.config.debug)
log("could not convert input to tensor");

303
dist/human.node.js vendored
View File

@ -246,7 +246,8 @@ var config = {
},
segmentation: {
enabled: false,
modelPath: "selfie.json"
modelPath: "selfie.json",
blur: 8
}
};
@ -281,13 +282,13 @@ function getBoxCenter(box6) {
function cutBoxFromImageAndResize(box6, image23, cropSize) {
const h = image23.shape[1];
const w = image23.shape[2];
const boxes2 = [[
const boxes = [[
box6.startPoint[1] / h,
box6.startPoint[0] / w,
box6.endPoint[1] / h,
box6.endPoint[0] / w
]];
return tf.image.cropAndResize(image23, boxes2, [0], cropSize);
return tf.image.cropAndResize(image23, boxes, [0], cropSize);
}
function enlargeBox(box6, factor = 1.5) {
const center = getBoxCenter(box6);
@ -437,7 +438,7 @@ var BlazeFaceModel = class {
var _a, _b, _c, _d;
if (!inputImage || inputImage["isDisposedInternal"] || inputImage.shape.length !== 4 || inputImage.shape[1] < 1 || inputImage.shape[2] < 1)
return { boxes: [] };
const [batch, boxes2, scores] = tf2.tidy(() => {
const [batch, boxes, scores] = tf2.tidy(() => {
const resizedImage = tf2.image.resizeBilinear(inputImage, [this.inputSize, this.inputSize]);
const normalizedImage = tf2.sub(tf2.div(resizedImage, 127.5), 0.5);
const res = this.model.execute(normalizedImage);
@ -457,7 +458,7 @@ var BlazeFaceModel = class {
return [batchOut, boxesOut, scoresOut];
});
this.config = mergeDeep(this.config, userConfig);
const nmsTensor = await tf2.image.nonMaxSuppressionAsync(boxes2, scores, ((_a = this.config.face.detector) == null ? void 0 : _a.maxDetected) || 0, ((_b = this.config.face.detector) == null ? void 0 : _b.iouThreshold) || 0, ((_c = this.config.face.detector) == null ? void 0 : _c.minConfidence) || 0);
const nmsTensor = await tf2.image.nonMaxSuppressionAsync(boxes, scores, ((_a = this.config.face.detector) == null ? void 0 : _a.maxDetected) || 0, ((_b = this.config.face.detector) == null ? void 0 : _b.iouThreshold) || 0, ((_c = this.config.face.detector) == null ? void 0 : _c.minConfidence) || 0);
const nms = await nmsTensor.array();
tf2.dispose(nmsTensor);
const annotatedBoxes = [];
@ -465,14 +466,14 @@ var BlazeFaceModel = class {
for (let i = 0; i < nms.length; i++) {
const confidence = scoresData[nms[i]];
if (confidence > (((_d = this.config.face.detector) == null ? void 0 : _d.minConfidence) || 0)) {
const boundingBox = tf2.slice(boxes2, [nms[i], 0], [1, -1]);
const boundingBox = tf2.slice(boxes, [nms[i], 0], [1, -1]);
const landmarks = tf2.tidy(() => tf2.reshape(tf2.squeeze(tf2.slice(batch, [nms[i], keypointsCount - 1], [1, -1])), [keypointsCount, -1]));
annotatedBoxes.push({ box: createBox(boundingBox), landmarks, anchor: this.anchorsData[nms[i]], confidence });
tf2.dispose(boundingBox);
}
}
tf2.dispose(batch);
tf2.dispose(boxes2);
tf2.dispose(boxes);
tf2.dispose(scores);
return {
boxes: annotatedBoxes,
@ -5671,13 +5672,13 @@ function getBoxCenter2(box6) {
function cutBoxFromImageAndResize2(box6, image23, cropSize) {
const h = image23.shape[1];
const w = image23.shape[2];
const boxes2 = [[
const boxes = [[
box6.startPoint[1] / h,
box6.startPoint[0] / w,
box6.endPoint[1] / h,
box6.endPoint[0] / w
]];
return tf10.image.cropAndResize(image23, boxes2, [0], cropSize);
return tf10.image.cropAndResize(image23, boxes, [0], cropSize);
}
function scaleBoxCoordinates2(box6, factor) {
const startPoint = [box6.startPoint[0] * factor[0], box6.startPoint[1] * factor[1]];
@ -8670,10 +8671,10 @@ var HandDetector = class {
this.inputSizeTensor = tf11.tensor1d([this.inputSize, this.inputSize]);
this.doubleInputSizeTensor = tf11.tensor1d([this.inputSize * 2, this.inputSize * 2]);
}
normalizeBoxes(boxes2) {
normalizeBoxes(boxes) {
return tf11.tidy(() => {
const boxOffsets = tf11.slice(boxes2, [0, 0], [-1, 2]);
const boxSizes = tf11.slice(boxes2, [0, 2], [-1, 2]);
const boxOffsets = tf11.slice(boxes, [0, 0], [-1, 2]);
const boxSizes = tf11.slice(boxes, [0, 2], [-1, 2]);
const boxCenterPoints = tf11.add(tf11.div(boxOffsets, this.inputSizeTensor), this.anchorsTensor);
const halfBoxSizes = tf11.div(boxSizes, this.doubleInputSizeTensor);
const startPoints = tf11.mul(tf11.sub(boxCenterPoints, halfBoxSizes), this.inputSizeTensor);
@ -8717,9 +8718,9 @@ var HandDetector = class {
if (!predictions || predictions.length === 0)
return hands;
for (const prediction of predictions) {
const boxes2 = await prediction.box.data();
const startPoint = boxes2.slice(0, 2);
const endPoint = boxes2.slice(2, 4);
const boxes = await prediction.box.data();
const startPoint = boxes.slice(0, 2);
const endPoint = boxes.slice(2, 4);
const palmLandmarks = await prediction.palmLandmarks.array();
tf11.dispose(prediction.box);
tf11.dispose(prediction.palmLandmarks);
@ -8864,16 +8865,16 @@ var HandPipeline = class {
}
async estimateHands(image23, config3) {
let useFreshBox = false;
let boxes2;
let boxes;
if (this.skipped === 0 || this.skipped > config3.hand.skipFrames || !config3.hand.landmarks || !config3.skipFrame) {
boxes2 = await this.handDetector.estimateHandBounds(image23, config3);
boxes = await this.handDetector.estimateHandBounds(image23, config3);
this.skipped = 0;
}
if (config3.skipFrame)
this.skipped++;
if (boxes2 && boxes2.length > 0 && (boxes2.length !== this.detectedHands && this.detectedHands !== config3.hand.maxDetected || !config3.hand.landmarks)) {
if (boxes && boxes.length > 0 && (boxes.length !== this.detectedHands && this.detectedHands !== config3.hand.maxDetected || !config3.hand.landmarks)) {
this.detectedHands = 0;
this.storedBoxes = [...boxes2];
this.storedBoxes = [...boxes];
if (this.storedBoxes.length > 0)
useFreshBox = true;
}
@ -9426,7 +9427,7 @@ async function load6(config3) {
var tf14 = __toModule(require_tfjs_esm());
var models = [null, null];
var modelOutputNodes = ["StatefulPartitionedCall/Postprocessor/Slice", "StatefulPartitionedCall/Postprocessor/ExpandDims_1"];
var inputSize = [0, 0];
var inputSize = [[0, 0], [0, 0]];
var classes = [
"hand",
"fist",
@ -9438,7 +9439,11 @@ var classes = [
];
var skipped3 = 0;
var outputSize;
var boxes = [];
var cache = {
handBoxes: [],
fingerBoxes: [],
tmpBoxes: []
};
var fingerMap = {
thumb: [1, 2, 3, 4],
index: [5, 6, 7, 8],
@ -9456,7 +9461,8 @@ async function load7(config3) {
if (!models[0]) {
models[0] = await tf14.loadGraphModel(join(config3.modelBasePath, ((_a = config3.hand.detector) == null ? void 0 : _a.modelPath) || ""));
const inputs = Object.values(models[0].modelSignature["inputs"]);
inputSize[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[0][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[0][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[0] || !models[0]["modelUrl"])
log("load model failed:", config3.object.modelPath);
else if (config3.debug)
@ -9466,7 +9472,8 @@ async function load7(config3) {
if (!models[1]) {
models[1] = await tf14.loadGraphModel(join(config3.modelBasePath, ((_b = config3.hand.skeleton) == null ? void 0 : _b.modelPath) || ""));
const inputs = Object.values(models[1].modelSignature["inputs"]);
inputSize[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[1][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[1][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[1] || !models[1]["modelUrl"])
log("load model failed:", config3.object.modelPath);
else if (config3.debug)
@ -9480,7 +9487,10 @@ async function detectHands(input, config3) {
if (!input || !models[0])
return hands;
const t = {};
t.resize = tf14.image.resizeBilinear(input, [240, 320]);
const ratio = (input.shape[2] || 1) / (input.shape[1] || 1);
const height = Math.min(Math.round((input.shape[1] || 0) / 8) * 8, 512);
const width = Math.round(height * ratio / 8) * 8;
t.resize = tf14.image.resizeBilinear(input, [height, width]);
t.cast = tf14.cast(t.resize, "int32");
[t.rawScores, t.rawBoxes] = await models[0].executeAsync(t.cast, modelOutputNodes);
t.boxes = tf14.squeeze(t.rawBoxes, [0, 2]);
@ -9508,8 +9518,36 @@ async function detectHands(input, config3) {
}
classScores.forEach((tensor3) => tf14.dispose(tensor3));
Object.keys(t).forEach((tensor3) => tf14.dispose(t[tensor3]));
hands.sort((a, b) => b.score - a.score);
if (hands.length > (config3.hand.maxDetected || 1))
hands.length = config3.hand.maxDetected || 1;
return hands;
}
var boxScaleFact = 1.5;
function updateBoxes(h, keypoints3) {
const finger = [keypoints3.map((pt) => pt[0]), keypoints3.map((pt) => pt[1])];
const minmax = [Math.min(...finger[0]), Math.max(...finger[0]), Math.min(...finger[1]), Math.max(...finger[1])];
const center = [(minmax[0] + minmax[1]) / 2, (minmax[2] + minmax[3]) / 2];
const diff = Math.max(center[0] - minmax[0], center[1] - minmax[2], -center[0] + minmax[1], -center[1] + minmax[3]) * boxScaleFact;
h.box = [
Math.trunc(center[0] - diff),
Math.trunc(center[1] - diff),
Math.trunc(2 * diff),
Math.trunc(2 * diff)
];
h.boxRaw = [
h.box[0] / outputSize[0],
h.box[1] / outputSize[1],
h.box[2] / outputSize[0],
h.box[3] / outputSize[1]
];
h.yxBox = [
h.boxRaw[1],
h.boxRaw[0],
h.boxRaw[3] + h.boxRaw[1],
h.boxRaw[2] + h.boxRaw[0]
];
}
async function detectFingers(input, h, config3) {
const hand3 = {
id: h.id,
@ -9523,46 +9561,57 @@ async function detectFingers(input, h, config3) {
landmarks: {},
annotations: {}
};
if (!input || !models[1] || !config3.hand.landmarks)
if (!input || !models[1])
return hand3;
const t = {};
t.crop = tf14.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1], inputSize[1]], "bilinear");
t.cast = tf14.cast(t.crop, "float32");
t.div = tf14.div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div);
const score3 = Math.round(100 * (await t.score.data())[0] / 100);
if (score3 > (config3.hand.minConfidence || 0)) {
hand3.fingerScore = score3;
t.reshaped = tf14.reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array();
hand3.keypoints = rawCoords.map((coord) => [
h.box[2] * coord[0] / inputSize[1] + h.box[0],
h.box[3] * coord[1] / inputSize[1] + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1] * coord[2]
]);
hand3.landmarks = analyze(hand3.keypoints);
for (const key of Object.keys(fingerMap)) {
hand3.annotations[key] = fingerMap[key].map((index) => hand3.landmarks && hand3.keypoints[index] ? hand3.keypoints[index] : null);
if (config3.hand.landmarks) {
const t = {};
if (!h.yxBox)
return hand3;
t.crop = tf14.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1][0], inputSize[1][1]], "bilinear");
t.cast = tf14.cast(t.crop, "float32");
t.div = tf14.div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div);
const score3 = Math.round(100 * (await t.score.data())[0] / 100);
if (score3 > (config3.hand.minConfidence || 0)) {
hand3.fingerScore = score3;
t.reshaped = tf14.reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array();
hand3.keypoints = rawCoords.map((coord) => [
h.box[2] * coord[0] / inputSize[1][0] + h.box[0],
h.box[3] * coord[1] / inputSize[1][1] + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1][0] * coord[2]
]);
updateBoxes(h, hand3.keypoints);
hand3.box = h.box;
hand3.landmarks = analyze(hand3.keypoints);
for (const key of Object.keys(fingerMap)) {
hand3.annotations[key] = fingerMap[key].map((index) => hand3.landmarks && hand3.keypoints[index] ? hand3.keypoints[index] : null);
}
cache.tmpBoxes.push(h);
}
Object.keys(t).forEach((tensor3) => tf14.dispose(t[tensor3]));
}
Object.keys(t).forEach((tensor3) => tf14.dispose(t[tensor3]));
return hand3;
}
var last3 = 0;
async function predict6(input, config3) {
outputSize = [input.shape[2] || 0, input.shape[1] || 0];
if (skipped3 < (config3.object.skipFrames || 0) && config3.skipFrame) {
let hands = [];
cache.tmpBoxes = [];
if (!config3.hand.landmarks)
cache.fingerBoxes = cache.handBoxes;
if (skipped3 < (config3.hand.skipFrames || 0) && config3.skipFrame) {
skipped3++;
const hands2 = await Promise.all(boxes.map((hand3) => detectFingers(input, hand3, config3)));
const withFingers2 = hands2.filter((hand3) => hand3.fingerScore > 0).length;
if (withFingers2 === last3)
return hands2;
hands = await Promise.all(cache.fingerBoxes.map((hand3) => detectFingers(input, hand3, config3)));
} else {
skipped3 = 0;
hands = await Promise.all(cache.fingerBoxes.map((hand3) => detectFingers(input, hand3, config3)));
if (hands.length !== config3.hand.maxDetected) {
cache.handBoxes = await detectHands(input, config3);
const newHands = await Promise.all(cache.handBoxes.map((hand3) => detectFingers(input, hand3, config3)));
hands = hands.concat(newHands);
}
}
skipped3 = 0;
boxes = await detectHands(input, config3);
const hands = await Promise.all(boxes.map((hand3) => detectFingers(input, hand3, config3)));
const withFingers = hands.filter((hand3) => hand3.fingerScore > 0).length;
last3 = withFingers;
cache.fingerBoxes = [...cache.tmpBoxes];
return hands;
}
@ -10041,7 +10090,7 @@ var labels = [
// src/object/nanodet.ts
var model7;
var last4 = [];
var last3 = [];
var skipped6 = Number.MAX_SAFE_INTEGER;
var scaleBox = 2.5;
async function load11(config3) {
@ -10121,13 +10170,13 @@ async function process3(res, inputSize3, outputShape, config3) {
return results;
}
async function predict10(image23, config3) {
if (skipped6 < (config3.object.skipFrames || 0) && config3.skipFrame && last4.length > 0) {
if (skipped6 < (config3.object.skipFrames || 0) && config3.skipFrame && last3.length > 0) {
skipped6++;
return last4;
return last3;
}
skipped6 = 0;
if (!env.kernels.includes("mod") || !env.kernels.includes("sparsetodense"))
return last4;
return last3;
return new Promise(async (resolve) => {
const outputSize2 = [image23.shape[2], image23.shape[1]];
const resize = tf18.image.resizeBilinear(image23, [model7.inputSize, model7.inputSize], false);
@ -10140,7 +10189,7 @@ async function predict10(image23, config3) {
objectT = await model7.predict(transpose);
tf18.dispose(transpose);
const obj = await process3(objectT, model7.inputSize, outputSize2, config3);
last4 = obj;
last3 = obj;
resolve(obj);
});
}
@ -10149,7 +10198,7 @@ async function predict10(image23, config3) {
var tf19 = __toModule(require_tfjs_esm());
var model8;
var inputSize2 = 0;
var last5 = [];
var last4 = [];
var skipped7 = Number.MAX_SAFE_INTEGER;
async function load12(config3) {
if (env.initial)
@ -10213,20 +10262,20 @@ async function process4(res, outputShape, config3) {
return results;
}
async function predict11(input, config3) {
if (skipped7 < (config3.object.skipFrames || 0) && config3.skipFrame && last5.length > 0) {
if (skipped7 < (config3.object.skipFrames || 0) && config3.skipFrame && last4.length > 0) {
skipped7++;
return last5;
return last4;
}
skipped7 = 0;
if (!env.kernels.includes("mod") || !env.kernels.includes("sparsetodense"))
return last5;
return last4;
return new Promise(async (resolve) => {
const outputSize2 = [input.shape[2], input.shape[1]];
const resize = tf19.image.resizeBilinear(input, [inputSize2, inputSize2]);
const objectT = config3.object.enabled ? model8 == null ? void 0 : model8.execute(resize, ["tower_0/detections"]) : null;
tf19.dispose(resize);
const obj = await process4(objectT, outputSize2, config3);
last5 = obj;
last4 = obj;
resolve(obj);
});
}
@ -10246,14 +10295,12 @@ async function load13(config3) {
log("cached model:", model9["modelUrl"]);
return model9;
}
async function predict12(input) {
async function predict12(input, config3) {
var _a, _b;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[1]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[2]) || 0;
if (!input.tensor)
return null;
if (!model9 || !model9.inputs[0].shape)
return null;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[2]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[1]) || 0;
if (!input.tensor || !model9 || !model9.inputs[0].shape)
return { data: null, canvas: null, alpha: null };
const resizeInput = tf20.image.resizeBilinear(input.tensor, [model9.inputs[0].shape[1], model9.inputs[0].shape[2]], false);
const norm = tf20.div(resizeInput, 255);
const res = model9.predict(norm);
@ -10261,7 +10308,7 @@ async function predict12(input) {
tf20.dispose(norm);
const squeeze8 = tf20.squeeze(res, 0);
tf20.dispose(res);
let resizeOutput;
let dataT;
if (squeeze8.shape[2] === 2) {
const softmax = squeeze8.softmax();
const [bg, fg] = tf20.unstack(softmax, 2);
@ -10271,77 +10318,63 @@ async function predict12(input) {
tf20.dispose(bg);
tf20.dispose(fg);
const crop = tf20.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
resizeOutput = tf20.squeeze(crop, 0);
dataT = tf20.squeeze(crop, 0);
tf20.dispose(crop);
tf20.dispose(expand);
tf20.dispose(pad);
} else {
resizeOutput = tf20.image.resizeBilinear(squeeze8, [width, height]);
dataT = tf20.image.resizeBilinear(squeeze8, [height, width]);
}
tf20.dispose(squeeze8);
const data = await dataT.dataSync();
if (env.node) {
const data = await resizeOutput.data();
tf20.dispose(resizeOutput);
return data;
tf20.dispose(dataT);
return { data, canvas: null, alpha: null };
}
const overlay = canvas(width, height);
if (tf20.browser)
await tf20.browser.toPixels(resizeOutput, overlay);
tf20.dispose(resizeOutput);
const alphaCanvas = canvas(width, height);
const ctxAlpha = alphaCanvas.getContext("2d");
ctxAlpha.filter = "blur(8px";
await ctxAlpha.drawImage(overlay, 0, 0);
const alpha = ctxAlpha.getImageData(0, 0, width, height).data;
const original = canvas(width, height);
const ctx = original.getContext("2d");
await tf20.browser.toPixels(dataT, alphaCanvas);
tf20.dispose(dataT);
const alphaCtx = alphaCanvas.getContext("2d");
if (config3.segmentation.blur && config3.segmentation.blur > 0)
alphaCtx.filter = `blur(${config3.segmentation.blur}px)`;
const alphaData = alphaCtx.getImageData(0, 0, width, height);
const compositeCanvas = canvas(width, height);
const compositeCtx = compositeCanvas.getContext("2d");
if (input.canvas)
await ctx.drawImage(input.canvas, 0, 0);
ctx.globalCompositeOperation = "darken";
ctx.filter = "blur(8px)";
await ctx.drawImage(overlay, 0, 0);
ctx.globalCompositeOperation = "source-over";
ctx.filter = "none";
input.canvas = original;
return alpha;
compositeCtx.drawImage(input.canvas, 0, 0);
compositeCtx.globalCompositeOperation = "darken";
if (config3.segmentation.blur && config3.segmentation.blur > 0)
compositeCtx.filter = `blur(${config3.segmentation.blur}px)`;
compositeCtx.drawImage(alphaCanvas, 0, 0);
compositeCtx.globalCompositeOperation = "source-over";
compositeCtx.filter = "none";
const compositeData = compositeCtx.getImageData(0, 0, width, height);
for (let i = 0; i < width * height; i++)
compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0];
compositeCtx.putImageData(compositeData, 0, 0);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
async function process5(input, background, config3) {
var _a;
var _a, _b;
if (busy)
return null;
return { data: null, canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const img = process2(input, config3);
const tmp = process2(background, config3);
if (!img.canvas || !tmp.canvas) {
if (config3.debug)
log("segmentation cannot process input or background");
return null;
}
const alpha = await predict12(img);
tf20.dispose(img.tensor);
if (background && alpha) {
const bg = tmp.canvas;
tf20.dispose(tmp.tensor);
const fg = img.canvas;
const fgData = (_a = fg.getContext("2d")) == null ? void 0 : _a.getImageData(0, 0, fg.width, fg.height).data;
const c = canvas(fg.width, fg.height);
const ctx = c.getContext("2d");
ctx.globalCompositeOperation = "copy";
ctx.drawImage(bg, 0, 0, c.width, c.height);
const cData = ctx.getImageData(0, 0, c.width, c.height);
for (let i = 0; i < c.width * c.height; i++) {
cData.data[4 * i + 0] = (255 - alpha[4 * i + 0]) / 255 * cData.data[4 * i + 0] + alpha[4 * i + 0] / 255 * fgData[4 * i + 0];
cData.data[4 * i + 1] = (255 - alpha[4 * i + 1]) / 255 * cData.data[4 * i + 1] + alpha[4 * i + 1] / 255 * fgData[4 * i + 1];
cData.data[4 * i + 2] = (255 - alpha[4 * i + 2]) / 255 * cData.data[4 * i + 2] + alpha[4 * i + 2] / 255 * fgData[4 * i + 2];
cData.data[4 * i + 3] = (255 - alpha[4 * i + 3]) / 255 * cData.data[4 * i + 3] + alpha[4 * i + 3] / 255 * fgData[4 * i + 3];
}
ctx.putImageData(cData, 0, 0);
img.canvas = c;
const inputImage = process2(input, config3);
const segmentation3 = await predict12(inputImage, config3);
tf20.dispose(inputImage.tensor);
let mergedCanvas = null;
if (background && segmentation3.canvas) {
mergedCanvas = canvas(((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0, ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0);
const bgImage = process2(background, config3);
tf20.dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext("2d");
ctxMerge.drawImage(bgImage.canvas, 0, 0, mergedCanvas.width, mergedCanvas.height);
ctxMerge.drawImage(segmentation3.canvas, 0, 0);
}
busy = false;
return img.canvas;
return { data: segmentation3.data, canvas: mergedCanvas || segmentation3.canvas, alpha: segmentation3.alpha };
}
// src/models.ts
@ -12551,7 +12584,7 @@ var Human = class {
return similarity(embedding1, embedding2);
}
async segmentation(input, background) {
return input ? process5(input, background, this.config) : null;
return process5(input, background, this.config);
}
enhance(input) {
return enhance(input);
@ -12623,24 +12656,10 @@ var Human = class {
await this.load();
timeStamp = now();
this.state = "image";
let img = process2(input, this.config);
const img = process2(input, this.config);
this.process = img;
this.performance.image = Math.trunc(now() - timeStamp);
this.analyze("Get Image:");
if (this.config.segmentation.enabled && this.process && img.tensor && img.canvas) {
this.analyze("Start Segmentation:");
this.state = "detect:segmentation";
timeStamp = now();
await predict12(img);
elapsedTime = Math.trunc(now() - timeStamp);
if (elapsedTime > 0)
this.performance.segmentation = elapsedTime;
if (img.canvas) {
tf25.dispose(img.tensor);
img = process2(img.canvas, this.config);
}
this.analyze("End Segmentation:");
}
if (!img.tensor) {
if (this.config.debug)
log("could not convert input to tensor");

View File

@ -118,10 +118,12 @@ export interface ObjectConfig {
*
* - enabled: true/false
* - modelPath: object detection model, can be absolute path or relative to modelBasePath
* - blur: blur segmentation output by <number> pixels for more realistic image
*/
export interface SegmentationConfig {
enabled: boolean,
modelPath: string,
blur: number,
}
/** Run input through image filters before inference
@ -399,6 +401,7 @@ const config: Config = {
// remove background or replace it with user-provided background
modelPath: 'selfie.json', // experimental: object detection model, can be absolute path or relative to modelBasePath
// can be 'selfie' or 'meet'
blur: 8, // blur segmentation output by n pixels for more realistic image
},
};
export { config as defaults };

View File

@ -12,7 +12,7 @@ import * as fingerPose from '../fingerpose/fingerpose';
const models: [GraphModel | null, GraphModel | null] = [null, null];
const modelOutputNodes = ['StatefulPartitionedCall/Postprocessor/Slice', 'StatefulPartitionedCall/Postprocessor/ExpandDims_1'];
const inputSize = [0, 0];
const inputSize = [[0, 0], [0, 0]];
const classes = [
'hand',
@ -36,7 +36,15 @@ type HandDetectResult = {
yxBox: [number, number, number, number],
}
let boxes: Array<HandDetectResult> = [];
const cache: {
handBoxes: Array<HandDetectResult>,
fingerBoxes: Array<HandDetectResult>
tmpBoxes: Array<HandDetectResult>
} = {
handBoxes: [],
fingerBoxes: [],
tmpBoxes: [],
};
const fingerMap = {
thumb: [1, 2, 3, 4],
@ -55,14 +63,16 @@ export async function load(config: Config): Promise<[GraphModel, GraphModel]> {
if (!models[0]) {
models[0] = await tf.loadGraphModel(join(config.modelBasePath, config.hand.detector?.modelPath || '')) as unknown as GraphModel;
const inputs = Object.values(models[0].modelSignature['inputs']);
inputSize[0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[0][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[0][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[0] || !models[0]['modelUrl']) log('load model failed:', config.object.modelPath);
else if (config.debug) log('load model:', models[0]['modelUrl']);
} else if (config.debug) log('cached model:', models[0]['modelUrl']);
if (!models[1]) {
models[1] = await tf.loadGraphModel(join(config.modelBasePath, config.hand.skeleton?.modelPath || '')) as unknown as GraphModel;
const inputs = Object.values(models[1].modelSignature['inputs']);
inputSize[1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
inputSize[1][0] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[1].size) : 0;
inputSize[1][1] = Array.isArray(inputs) ? parseInt(inputs[0].tensorShape.dim[2].size) : 0;
if (!models[1] || !models[1]['modelUrl']) log('load model failed:', config.object.modelPath);
else if (config.debug) log('load model:', models[1]['modelUrl']);
} else if (config.debug) log('cached model:', models[1]['modelUrl']);
@ -73,7 +83,10 @@ async function detectHands(input: Tensor, config: Config): Promise<HandDetectRes
const hands: HandDetectResult[] = [];
if (!input || !models[0]) return hands;
const t: Record<string, Tensor> = {};
t.resize = tf.image.resizeBilinear(input, [240, 320]); // todo: resize with padding
const ratio = (input.shape[2] || 1) / (input.shape[1] || 1);
const height = Math.min(Math.round((input.shape[1] || 0) / 8) * 8, 512); // use dynamic input size but cap at 1024
const width = Math.round(height * ratio / 8) * 8;
t.resize = tf.image.resizeBilinear(input, [height, width]); // todo: resize with padding
t.cast = tf.cast(t.resize, 'int32');
[t.rawScores, t.rawBoxes] = await models[0].executeAsync(t.cast, modelOutputNodes) as Tensor[];
t.boxes = tf.squeeze(t.rawBoxes, [0, 2]);
@ -100,40 +113,36 @@ async function detectHands(input: Tensor, config: Config): Promise<HandDetectRes
}
classScores.forEach((tensor) => tf.dispose(tensor));
Object.keys(t).forEach((tensor) => tf.dispose(t[tensor]));
hands.sort((a, b) => b.score - a.score);
if (hands.length > (config.hand.maxDetected || 1)) hands.length = (config.hand.maxDetected || 1);
return hands;
}
/*
const scaleFact = 1.2;
const boxScaleFact = 1.5; // hand finger model prefers slighly larger box
function updateBoxes(h, keypoints) {
const fingerX = keypoints.map((pt) => pt[0]);
const fingerY = keypoints.map((pt) => pt[1]);
const minX = Math.min(...fingerX);
const maxX = Math.max(...fingerX);
const minY = Math.min(...fingerY);
const maxY = Math.max(...fingerY);
const finger = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])]; // all fingers coords
const minmax = [Math.min(...finger[0]), Math.max(...finger[0]), Math.min(...finger[1]), Math.max(...finger[1])]; // find min and max coordinates for x and y of all fingers
const center = [(minmax[0] + minmax[1]) / 2, (minmax[2] + minmax[3]) / 2]; // find center x and y coord of all fingers
const diff = Math.max(center[0] - minmax[0], center[1] - minmax[2], -center[0] + minmax[1], -center[1] + minmax[3]) * boxScaleFact; // largest distance from center in any direction
h.box = [
Math.trunc(minX / scaleFact),
Math.trunc(minY / scaleFact),
Math.trunc(scaleFact * maxX - minX),
Math.trunc(scaleFact * maxY - minY),
Math.trunc(center[0] - diff),
Math.trunc(center[1] - diff),
Math.trunc(2 * diff),
Math.trunc(2 * diff),
] as [number, number, number, number];
h.bowRaw = [
h.box / outputSize[0],
h.box / outputSize[1],
h.box / outputSize[0],
h.box / outputSize[1],
h.boxRaw = [ // work backwards
h.box[0] / outputSize[0],
h.box[1] / outputSize[1],
h.box[2] / outputSize[0],
h.box[3] / outputSize[1],
] as [number, number, number, number];
h.yxBox = [
h.yxBox = [ // work backwards
h.boxRaw[1],
h.boxRaw[0],
h.boxRaw[3] + h.boxRaw[1],
h.boxRaw[2] + h.boxRaw[0],
] as [number, number, number, number];
return h;
}
*/
async function detectFingers(input: Tensor, h: HandDetectResult, config: Config): Promise<HandResult> {
const hand: HandResult = {
@ -148,60 +157,64 @@ async function detectFingers(input: Tensor, h: HandDetectResult, config: Config)
landmarks: {} as HandResult['landmarks'],
annotations: {} as HandResult['annotations'],
};
if (!input || !models[1] || !config.hand.landmarks) return hand;
const t: Record<string, Tensor> = {};
t.crop = tf.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1], inputSize[1]], 'bilinear');
t.cast = tf.cast(t.crop, 'float32');
t.div = tf.div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div) as Tensor[];
const score = Math.round(100 * (await t.score.data())[0] / 100);
if (score > (config.hand.minConfidence || 0)) {
hand.fingerScore = score;
t.reshaped = tf.reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array() as number[];
hand.keypoints = (rawCoords as number[]).map((coord) => [
(h.box[2] * coord[0] / inputSize[1]) + h.box[0],
(h.box[3] * coord[1] / inputSize[1]) + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1] * coord[2],
]);
// h = updateBoxes(h, hand.keypoints); // replace detected box with box calculated around keypoints
hand.landmarks = fingerPose.analyze(hand.keypoints) as HandResult['landmarks']; // calculate finger landmarks
for (const key of Object.keys(fingerMap)) { // map keypoints to per-finger annotations
hand.annotations[key] = fingerMap[key].map((index) => (hand.landmarks && hand.keypoints[index] ? hand.keypoints[index] : null));
if (!input || !models[1]) return hand; // something is wrong
if (config.hand.landmarks) {
const t: Record<string, Tensor> = {};
if (!h.yxBox) return hand;
t.crop = tf.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1][0], inputSize[1][1]], 'bilinear');
t.cast = tf.cast(t.crop, 'float32');
t.div = tf.div(t.cast, 255);
[t.score, t.keypoints] = models[1].execute(t.div) as Tensor[];
const score = Math.round(100 * (await t.score.data())[0] / 100);
if (score > (config.hand.minConfidence || 0)) {
hand.fingerScore = score;
t.reshaped = tf.reshape(t.keypoints, [-1, 3]);
const rawCoords = await t.reshaped.array() as number[];
hand.keypoints = (rawCoords as number[]).map((coord) => [
(h.box[2] * coord[0] / inputSize[1][0]) + h.box[0],
(h.box[3] * coord[1] / inputSize[1][1]) + h.box[1],
(h.box[2] + h.box[3]) / 2 / inputSize[1][0] * coord[2],
]);
updateBoxes(h, hand.keypoints); // replace detected box with box calculated around keypoints
hand.box = h.box;
hand.landmarks = fingerPose.analyze(hand.keypoints) as HandResult['landmarks']; // calculate finger landmarks
for (const key of Object.keys(fingerMap)) { // map keypoints to per-finger annotations
hand.annotations[key] = fingerMap[key].map((index) => (hand.landmarks && hand.keypoints[index] ? hand.keypoints[index] : null));
}
cache.tmpBoxes.push(h); // if finger detection is enabled, only update cache if fingers are detected
}
Object.keys(t).forEach((tensor) => tf.dispose(t[tensor]));
}
Object.keys(t).forEach((tensor) => tf.dispose(t[tensor]));
return hand;
}
let last = 0;
export async function predict(input: Tensor, config: Config): Promise<HandResult[]> {
outputSize = [input.shape[2] || 0, input.shape[1] || 0];
if ((skipped < (config.object.skipFrames || 0)) && config.skipFrame) {
// use cached boxes
let hands: Array<HandResult> = [];
cache.tmpBoxes = []; // clear temp cache
if (!config.hand.landmarks) cache.fingerBoxes = cache.handBoxes; // if hand detection only reset finger boxes cache
if ((skipped < (config.hand.skipFrames || 0)) && config.skipFrame) { // just run finger detection while reusing cached boxes
skipped++;
const hands: HandResult[] = await Promise.all(boxes.map((hand) => detectFingers(input, hand, config)));
const withFingers = hands.filter((hand) => hand.fingerScore > 0).length;
if (withFingers === last) return hands;
hands = await Promise.all(cache.fingerBoxes.map((hand) => detectFingers(input, hand, config))); // run from finger box cache
// console.log('SKIP', skipped, hands.length, cache.handBoxes.length, cache.fingerBoxes.length, cache.tmpBoxes.length);
} else { // calculate new boxes and run finger detection
skipped = 0;
hands = await Promise.all(cache.fingerBoxes.map((hand) => detectFingers(input, hand, config))); // run from finger box cache
// console.log('CACHE', skipped, hands.length, cache.handBoxes.length, cache.fingerBoxes.length, cache.tmpBoxes.length);
if (hands.length !== config.hand.maxDetected) { // run hand detection only if we dont have enough hands in cache
cache.handBoxes = await detectHands(input, config);
const newHands = await Promise.all(cache.handBoxes.map((hand) => detectFingers(input, hand, config)));
hands = hands.concat(newHands);
// console.log('DETECT', skipped, hands.length, cache.handBoxes.length, cache.fingerBoxes.length, cache.tmpBoxes.length);
}
}
// calculate new boxes
skipped = 0;
boxes = await detectHands(input, config);
const hands: HandResult[] = await Promise.all(boxes.map((hand) => detectFingers(input, hand, config)));
const withFingers = hands.filter((hand) => hand.fingerScore > 0).length;
last = withFingers;
// console.log('NEW', withFingers, hands.length, boxes.length);
return hands;
cache.fingerBoxes = [...cache.tmpBoxes]; // repopulate cache with validated hands
return hands as HandResult[];
}
/*
<https://victordibia.com/handtrack.js/#/>
<https://github.com/victordibia/handtrack.js/>
<https://github.com/victordibia/handtracking>
<https://medium.com/@victor.dibia/how-to-build-a-real-time-hand-detector-using-neural-networks-ssd-on-tensorflow-d6bac0e4b2ce>
*/
/* TODO
- smart resize
- updateboxes is drifting
- Live Site: <https://victordibia.com/handtrack.js/#/>
- TFJS Port: <https://github.com/victordibia/handtrack.js/>
- Original: <https://github.com/victordibia/handtracking>
- Writeup: <https://medium.com/@victor.dibia/how-to-build-a-real-time-hand-detector-using-neural-networks-ssd-on-tensorflow-d6bac0e4b2ce>
*/

View File

@ -47,7 +47,7 @@ export type Input = Tensor | ImageData | ImageBitmap | HTMLImageElement | HTMLMe
*
* - `create`: triggered when Human object is instantiated
* - `load`: triggered when models are loaded (explicitly or on-demand)
* - `image`: triggered when input image is this.processed
* - `image`: triggered when input image is processed
* - `result`: triggered when detection is complete
* - `warmup`: triggered when warmup is complete
*/
@ -111,7 +111,7 @@ export class Human {
* - face: draw detected faces
* - body: draw detected people and body parts
* - hand: draw detected hands and hand parts
* - canvas: draw this.processed canvas which is a this.processed copy of the input
* - canvas: draw processed canvas which is a processed copy of the input
* - all: meta-function that performs: canvas, face, body, hand
*/
draw: { canvas, face, body, hand, gesture, object, person, all, options: DrawOptions };
@ -142,7 +142,7 @@ export class Human {
* Possible events:
* - `create`: triggered when Human object is instantiated
* - `load`: triggered when models are loaded (explicitly or on-demand)
* - `image`: triggered when input image is this.processed
* - `image`: triggered when input image is processed
* - `result`: triggered when detection is complete
* - `warmup`: triggered when warmup is complete
* - `error`: triggered on some errors
@ -217,7 +217,7 @@ export class Human {
all: (output: HTMLCanvasElement | OffscreenCanvas, result: Result, options?: Partial<DrawOptions>) => draw.all(output, result, options),
};
this.result = { face: [], body: [], hand: [], gesture: [], object: [], performance: {}, timestamp: 0, persons: [] };
// export access to image this.processing
// export access to image processing
// @ts-ignore eslint-typescript cannot correctly infer type in anonymous function
this.process = { tensor: null, canvas: null };
// export raw access to underlying models
@ -284,16 +284,21 @@ export class Human {
return faceres.similarity(embedding1, embedding2);
}
/** Segmentation method takes any input and returns this.processed canvas with body segmentation
/** Segmentation method takes any input and returns processed canvas with body segmentation
* - Optional parameter background is used to fill the background with specific input
* - Segmentation is not triggered as part of detect this.process
* - Segmentation is not triggered as part of detect process
*
* Returns:
* - `data` as raw data array with per-pixel segmentation values
* - `canvas` as canvas which is input image filtered with segementation data and optionally merged with background image. canvas alpha values are set to segmentation values for easy merging
* - `alpha` as grayscale canvas that represents segmentation alpha values
*
* @param input: {@link Input}
* @param background?: {@link Input}
* @returns Canvas
* @returns { data, canvas, alpha }
*/
async segmentation(input: Input, background?: Input) {
return input ? segmentation.process(input, background, this.config) : null;
async segmentation(input: Input, background?: Input): Promise<{ data: Uint8ClampedArray | null, canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
return segmentation.process(input, background, this.config);
}
/** Enhance method performs additional enhacements to face image previously detected for futher processing
@ -394,7 +399,7 @@ export class Human {
/** Main detection method
* - Analyze configuration: {@link Config}
* - Pre-this.process input: {@link Input}
* - Pre-process input: {@link Input}
* - Run inference for all configured models
* - Process and return result: {@link Result}
*
@ -431,26 +436,24 @@ export class Human {
timeStamp = now();
this.state = 'image';
let img = image.process(input, this.config);
const img = image.process(input, this.config) as { canvas: HTMLCanvasElement | OffscreenCanvas, tensor: Tensor };
this.process = img;
this.performance.image = Math.trunc(now() - timeStamp);
this.analyze('Get Image:');
// run segmentation prethis.processing
if (this.config.segmentation.enabled && this.process && img.tensor && img.canvas) {
// segmentation is only run explicitly via human.segmentation() which calls segmentation.process()
/*
if (this.config.segmentation.enabled && process && img.tensor && img.canvas) {
this.analyze('Start Segmentation:');
this.state = 'detect:segmentation';
timeStamp = now();
await segmentation.predict(img);
const seg = await segmentation.predict(img, this.config);
img = { canvas: seg.canvas, tensor: seg.tensor };
elapsedTime = Math.trunc(now() - timeStamp);
if (elapsedTime > 0) this.performance.segmentation = elapsedTime;
if (img.canvas) {
// replace input
tf.dispose(img.tensor);
img = image.process(img.canvas, this.config);
}
this.analyze('End Segmentation:');
}
*/
if (!img.tensor) {
if (this.config.debug) log('could not convert input to tensor');

View File

@ -23,11 +23,11 @@ export async function load(config: Config): Promise<GraphModel> {
return model;
}
export async function predict(input: { tensor: Tensor | null, canvas: OffscreenCanvas | HTMLCanvasElement | null }): Promise<Uint8ClampedArray | null> {
const width = input.tensor?.shape[1] || 0;
const height = input.tensor?.shape[2] || 0;
if (!input.tensor) return null;
if (!model || !model.inputs[0].shape) return null;
export async function predict(input: { tensor: Tensor | null, canvas: OffscreenCanvas | HTMLCanvasElement | null }, config: Config)
: Promise<{ data: Uint8ClampedArray | null, canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
const width = input.tensor?.shape[2] || 0;
const height = input.tensor?.shape[1] || 0;
if (!input.tensor || !model || !model.inputs[0].shape) return { data: null, canvas: null, alpha: null };
const resizeInput = tf.image.resizeBilinear(input.tensor, [model.inputs[0].shape[1], model.inputs[0].shape[2]], false);
const norm = tf.div(resizeInput, 255);
const res = model.predict(norm) as Tensor;
@ -38,7 +38,7 @@ export async function predict(input: { tensor: Tensor | null, canvas: OffscreenC
const squeeze = tf.squeeze(res, 0);
tf.dispose(res);
let resizeOutput;
let dataT;
if (squeeze.shape[2] === 2) {
// model meet has two channels for fg and bg
const softmax = squeeze.softmax();
@ -52,82 +52,66 @@ export async function predict(input: { tensor: Tensor | null, canvas: OffscreenC
const crop = tf.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
// otherwise run softmax after unstack and use standard resize
// resizeOutput = tf.image.resizeBilinear(expand, [input.tensor?.shape[1], input.tensor?.shape[2]]);
resizeOutput = tf.squeeze(crop, 0);
dataT = tf.squeeze(crop, 0);
tf.dispose(crop);
tf.dispose(expand);
tf.dispose(pad);
} else { // model selfie has a single channel that we can use directly
resizeOutput = tf.image.resizeBilinear(squeeze, [width, height]);
dataT = tf.image.resizeBilinear(squeeze, [height, width]);
}
tf.dispose(squeeze);
const data = await dataT.dataSync();
if (env.node) {
const data = await resizeOutput.data();
tf.dispose(resizeOutput);
return data; // we're running in nodejs so return alpha array as-is
tf.dispose(dataT);
return { data, canvas: null, alpha: null }; // running in nodejs so return alpha array as-is
}
const overlay = image.canvas(width, height);
if (tf.browser) await tf.browser.toPixels(resizeOutput, overlay);
tf.dispose(resizeOutput);
// get alpha channel data
const alphaCanvas = image.canvas(width, height);
const ctxAlpha = alphaCanvas.getContext('2d') as CanvasRenderingContext2D;
ctxAlpha.filter = 'blur(8px';
await ctxAlpha.drawImage(overlay, 0, 0);
const alpha = ctxAlpha.getImageData(0, 0, width, height).data;
await tf.browser.toPixels(dataT, alphaCanvas);
tf.dispose(dataT);
const alphaCtx = alphaCanvas.getContext('2d') as CanvasRenderingContext2D;
if (config.segmentation.blur && config.segmentation.blur > 0) alphaCtx.filter = `blur(${config.segmentation.blur}px)`; // use css filter for bluring, can be done with gaussian blur manually instead
const alphaData = alphaCtx.getImageData(0, 0, width, height);
// get original canvas merged with overlay
const original = image.canvas(width, height);
const ctx = original.getContext('2d') as CanvasRenderingContext2D;
if (input.canvas) await ctx.drawImage(input.canvas, 0, 0);
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation // best options are: darken, color-burn, multiply
ctx.globalCompositeOperation = 'darken';
ctx.filter = 'blur(8px)'; // use css filter for bluring, can be done with gaussian blur manually instead
await ctx.drawImage(overlay, 0, 0);
ctx.globalCompositeOperation = 'source-over'; // reset
ctx.filter = 'none'; // reset
// original canvas where only alpha shows
const compositeCanvas = image.canvas(width, height);
const compositeCtx = compositeCanvas.getContext('2d') as CanvasRenderingContext2D;
if (input.canvas) compositeCtx.drawImage(input.canvas, 0, 0);
compositeCtx.globalCompositeOperation = 'darken'; // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation // best options are: darken, color-burn, multiply
if (config.segmentation.blur && config.segmentation.blur > 0) compositeCtx.filter = `blur(${config.segmentation.blur}px)`; // use css filter for bluring, can be done with gaussian blur manually instead
compositeCtx.drawImage(alphaCanvas, 0, 0);
compositeCtx.globalCompositeOperation = 'source-over'; // reset composite operation
compositeCtx.filter = 'none'; // reset css filter
const compositeData = compositeCtx.getImageData(0, 0, width, height);
for (let i = 0; i < width * height; i++) compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0]; // copy original alpha value to new composite canvas
compositeCtx.putImageData(compositeData, 0, 0);
input.canvas = original;
return alpha;
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
export async function process(input: Input, background: Input | undefined, config: Config): Promise<HTMLCanvasElement | OffscreenCanvas | null> {
if (busy) return null;
export async function process(input: Input, background: Input | undefined, config: Config)
: Promise<{ data: Uint8ClampedArray | null, canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
if (busy) return { data: null, canvas: null, alpha: null };
busy = true;
if (!model) await load(config);
const img = image.process(input, config);
const tmp = image.process(background, config);
if (!img.canvas || !tmp.canvas) {
if (config.debug) log('segmentation cannot process input or background');
return null;
const inputImage = image.process(input, config);
const segmentation = await predict(inputImage, config);
tf.dispose(inputImage.tensor);
let mergedCanvas: HTMLCanvasElement | OffscreenCanvas | null = null;
if (background && segmentation.canvas) { // draw background with segmentation as overlay if background is present
mergedCanvas = image.canvas(inputImage.canvas?.width || 0, inputImage.canvas?.height || 0);
const bgImage = image.process(background, config);
tf.dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext('2d') as CanvasRenderingContext2D;
// ctxMerge.globalCompositeOperation = 'source-over';
ctxMerge.drawImage(bgImage.canvas as HTMLCanvasElement, 0, 0, mergedCanvas.width, mergedCanvas.height);
// ctxMerge.globalCompositeOperation = 'source-atop';
ctxMerge.drawImage(segmentation.canvas as HTMLCanvasElement, 0, 0);
// ctxMerge.globalCompositeOperation = 'source-over';
}
const alpha = await predict(img);
tf.dispose(img.tensor);
if (background && alpha) {
const bg = tmp.canvas as HTMLCanvasElement;
tf.dispose(tmp.tensor);
const fg = img.canvas as HTMLCanvasElement;
const fgData = fg.getContext('2d')?.getImageData(0, 0, fg.width, fg.height).data as Uint8ClampedArray;
const c = image.canvas(fg.width, fg.height);
const ctx = c.getContext('2d') as CanvasRenderingContext2D;
ctx.globalCompositeOperation = 'copy'; // reset
ctx.drawImage(bg, 0, 0, c.width, c.height);
const cData = ctx.getImageData(0, 0, c.width, c.height) as ImageData;
for (let i = 0; i < c.width * c.height; i++) { // this should be done with globalCompositeOperation instead of looping through image data
cData.data[4 * i + 0] = ((255 - alpha[4 * i + 0]) / 255.0 * cData.data[4 * i + 0]) + (alpha[4 * i + 0] / 255.0 * fgData[4 * i + 0]);
cData.data[4 * i + 1] = ((255 - alpha[4 * i + 1]) / 255.0 * cData.data[4 * i + 1]) + (alpha[4 * i + 1] / 255.0 * fgData[4 * i + 1]);
cData.data[4 * i + 2] = ((255 - alpha[4 * i + 2]) / 255.0 * cData.data[4 * i + 2]) + (alpha[4 * i + 2] / 255.0 * fgData[4 * i + 2]);
cData.data[4 * i + 3] = ((255 - alpha[4 * i + 3]) / 255.0 * cData.data[4 * i + 3]) + (alpha[4 * i + 3] / 255.0 * fgData[4 * i + 3]);
}
ctx.putImageData(cData, 0, 0);
img.canvas = c;
}
busy = false;
return img.canvas;
return { data: segmentation.data, canvas: mergedCanvas || segmentation.canvas, alpha: segmentation.alpha };
}

View File

@ -1,24 +1,130 @@
2021-09-21 16:46:56 INFO:  @vladmandic/human version 2.2.2
2021-09-21 16:46:56 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.5.0
2021-09-21 16:46:56 INFO:  Application: {"name":"@vladmandic/human","version":"2.2.2"}
2021-09-21 16:46:56 INFO:  Environment: {"profile":"production","config":"build.json","tsconfig":true,"eslintrc":true,"git":true}
2021-09-21 16:46:56 INFO:  Toolchain: {"build":"0.5.2","esbuild":"0.12.28","typescript":"4.4.3","typedoc":"0.22.4","eslint":"7.32.0"}
2021-09-21 16:46:56 INFO:  Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
2021-09-21 16:46:56 STATE: Clean: {"locations":["dist/*","types/*","typedoc/*"]}
2021-09-21 16:46:56 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":1416}
2021-09-21 16:46:56 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":51,"inputBytes":493232,"outputBytes":417484}
2021-09-21 16:46:56 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":1424}
2021-09-21 16:46:56 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":51,"inputBytes":493240,"outputBytes":417488}
2021-09-21 16:46:56 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":1491}
2021-09-21 16:46:56 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":51,"inputBytes":493307,"outputBytes":417560}
2021-09-21 16:46:56 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":1631}
2021-09-21 16:46:56 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":3088,"outputBytes":793}
2021-09-21 16:46:56 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":51,"inputBytes":492609,"outputBytes":418986}
2021-09-21 16:46:57 STATE: Compile: {"name":"tfjs/browser/esm/bundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":8,"inputBytes":3088,"outputBytes":2376809}
2021-09-21 16:46:57 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":51,"inputBytes":2868625,"outputBytes":1414584}
2021-09-21 16:46:58 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":51,"inputBytes":2868625,"outputBytes":2622860}
2021-09-21 16:47:14 STATE: Typings: {"input":"src/human.ts","output":"types","files":96}
2021-09-21 16:47:20 STATE: TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":30,"generated":true}
2021-09-21 16:47:47 STATE: Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":84,"errors":0,"warnings":0}
2021-09-21 16:47:47 STATE: ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
2021-09-21 16:47:47 INFO:  Done...
2021-09-22 15:07:47 INFO:  @vladmandic/human version 2.2.2
2021-09-22 15:07:47 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.5.0
2021-09-22 15:07:47 INFO:  Application: {"name":"@vladmandic/human","version":"2.2.2"}
2021-09-22 15:07:47 INFO:  Environment: {"profile":"production","config":"build.json","tsconfig":true,"eslintrc":true,"git":true}
2021-09-22 15:07:47 INFO:  Toolchain: {"build":"0.5.2","esbuild":"0.12.28","typescript":"4.4.3","typedoc":"0.22.4","eslint":"7.32.0"}
2021-09-22 15:07:47 INFO:  Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
2021-09-22 15:07:47 STATE: Clean: {"locations":["dist/*","types/*","typedoc/*"]}
2021-09-22 15:07:47 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":1416}
2021-09-22 15:07:47 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":51,"inputBytes":496246,"outputBytes":418463}
2021-09-22 15:07:47 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":1424}
2021-09-22 15:07:47 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":51,"inputBytes":496254,"outputBytes":418467}
2021-09-22 15:07:47 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":1491}
2021-09-22 15:07:47 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":51,"inputBytes":496321,"outputBytes":418539}
2021-09-22 15:07:47 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":1631}
2021-09-22 15:07:47 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":3088,"outputBytes":793}
2021-09-22 15:07:47 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":51,"inputBytes":495623,"outputBytes":419941}
2021-09-22 15:07:48 STATE: Compile: {"name":"tfjs/browser/esm/bundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":8,"inputBytes":3088,"outputBytes":2376809}
2021-09-22 15:07:49 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":51,"inputBytes":2871639,"outputBytes":1415127}
2021-09-22 15:07:49 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":51,"inputBytes":2871639,"outputBytes":2623662}
2021-09-22 15:08:08 STATE: Typings: {"input":"src/human.ts","output":"types","files":96}
2021-09-22 15:08:14 STATE: TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":30,"generated":true}
2021-09-22 15:08:43 STATE: Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":84,"errors":0,"warnings":0}
2021-09-22 15:08:43 STATE: ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
2021-09-22 15:08:43 INFO:  Done...
2021-09-22 15:08:49 INFO:  @vladmandic/human version 2.2.2
2021-09-22 15:08:49 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.5.0
2021-09-22 15:08:49 INFO:  Application: {"name":"@vladmandic/human","version":"2.2.2"}
2021-09-22 15:08:49 INFO:  Environment: {"profile":"development","config":"build.json","tsconfig":true,"eslintrc":true,"git":true}
2021-09-22 15:08:49 INFO:  Toolchain: {"build":"0.5.2","esbuild":"0.12.28","typescript":"4.4.3","typedoc":"0.22.4","eslint":"7.32.0"}
2021-09-22 15:08:49 INFO:  Build: {"profile":"development","steps":["serve","watch","compile"]}
2021-09-22 15:08:49 STATE: WebServer: {"ssl":false,"port":10030,"root":"."}
2021-09-22 15:08:49 STATE: WebServer: {"ssl":true,"port":10031,"root":".","sslKey":"node_modules/@vladmandic/build/cert/https.key","sslCrt":"node_modules/@vladmandic/build/cert/https.crt"}
2021-09-22 15:08:49 STATE: Watch: {"locations":["src/**","README.md","src/**/*","tfjs/**/*"]}
2021-09-22 15:08:49 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":1416}
2021-09-22 15:08:49 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":51,"inputBytes":496246,"outputBytes":418463}
2021-09-22 15:08:49 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":1424}
2021-09-22 15:08:49 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":51,"inputBytes":496254,"outputBytes":418467}
2021-09-22 15:08:49 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":1491}
2021-09-22 15:08:49 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":51,"inputBytes":496321,"outputBytes":418539}
2021-09-22 15:08:49 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":1631}
2021-09-22 15:08:49 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":3088,"outputBytes":793}
2021-09-22 15:08:49 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":51,"inputBytes":495623,"outputBytes":419941}
2021-09-22 15:08:50 STATE: Compile: {"name":"tfjs/browser/esm/bundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":8,"inputBytes":3088,"outputBytes":2376809}
2021-09-22 15:08:50 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":51,"inputBytes":2871639,"outputBytes":1415127}
2021-09-22 15:08:51 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":51,"inputBytes":2871639,"outputBytes":2623662}
2021-09-22 15:08:51 INFO:  Listening...
2021-09-22 15:09:00 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/html","size":32718,"url":"/typedoc/index.html","remote":"::ffff:192.168.0.200"}
2021-09-22 15:09:00 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":32475,"url":"/typedoc/assets/style.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:09:00 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":480,"url":"/typedoc/assets/highlight.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:09:00 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/javascript","size":43169,"url":"/typedoc/assets/main.js","remote":"::ffff:192.168.0.200"}
2021-09-22 15:09:00 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/javascript","size":69586,"url":"/typedoc/assets/search.js","remote":"::ffff:192.168.0.200"}
2021-09-22 15:09:00 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":35195,"url":"/typedoc/assets/icons.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:09:00 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"image/png","size":855,"url":"/typedoc/assets/widgets@2x.png","remote":"::ffff:192.168.0.200"}
2021-09-22 15:09:00 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"image/png","size":28144,"url":"/typedoc/assets/icons@2x.png","remote":"::ffff:192.168.0.200"}
2021-09-22 15:10:06 INFO:  Watch: {"event":"modify","input":"src/segmentation/segmentation.ts"}
2021-09-22 15:10:06 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":1416}
2021-09-22 15:10:06 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":51,"inputBytes":496308,"outputBytes":418531}
2021-09-22 15:10:06 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":1424}
2021-09-22 15:10:06 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":51,"inputBytes":496316,"outputBytes":418535}
2021-09-22 15:10:06 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":1491}
2021-09-22 15:10:06 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":51,"inputBytes":496383,"outputBytes":418607}
2021-09-22 15:10:06 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":1631}
2021-09-22 15:10:06 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":3088,"outputBytes":793}
2021-09-22 15:10:06 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":51,"inputBytes":495685,"outputBytes":420009}
2021-09-22 15:10:07 STATE: Compile: {"name":"tfjs/browser/esm/bundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":8,"inputBytes":3088,"outputBytes":2376809}
2021-09-22 15:10:07 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":51,"inputBytes":2871701,"outputBytes":1415173}
2021-09-22 15:10:08 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":51,"inputBytes":2871701,"outputBytes":2623730}
2021-09-22 15:10:15 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/html","size":6619,"url":"/typedoc/interfaces/SegmentationConfig.html","remote":"::ffff:192.168.0.200"}
2021-09-22 15:10:15 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":32475,"url":"/typedoc/assets/style.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:10:15 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":480,"url":"/typedoc/assets/highlight.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:10:15 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/javascript","size":43169,"url":"/typedoc/assets/main.js","remote":"::ffff:192.168.0.200"}
2021-09-22 15:10:15 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/javascript","size":69586,"url":"/typedoc/assets/search.js","remote":"::ffff:192.168.0.200"}
2021-09-22 15:10:15 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":35195,"url":"/typedoc/assets/icons.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:10:15 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"image/png","size":855,"url":"/typedoc/assets/widgets@2x.png","remote":"::ffff:192.168.0.200"}
2021-09-22 15:10:15 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"image/png","size":28144,"url":"/typedoc/assets/icons@2x.png","remote":"::ffff:192.168.0.200"}
2021-09-22 15:11:25 INFO:  Watch: {"event":"modify","input":"src/config.ts"}
2021-09-22 15:11:25 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":1416}
2021-09-22 15:11:25 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":51,"inputBytes":496380,"outputBytes":418531}
2021-09-22 15:11:25 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":1424}
2021-09-22 15:11:25 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":51,"inputBytes":496388,"outputBytes":418535}
2021-09-22 15:11:25 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":1491}
2021-09-22 15:11:25 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":51,"inputBytes":496455,"outputBytes":418607}
2021-09-22 15:11:25 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":1631}
2021-09-22 15:11:25 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":3088,"outputBytes":793}
2021-09-22 15:11:25 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":51,"inputBytes":495757,"outputBytes":420009}
2021-09-22 15:11:26 STATE: Compile: {"name":"tfjs/browser/esm/bundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":8,"inputBytes":3088,"outputBytes":2376809}
2021-09-22 15:11:26 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":51,"inputBytes":2871773,"outputBytes":1415173}
2021-09-22 15:11:27 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":51,"inputBytes":2871773,"outputBytes":2623730}
2021-09-22 15:11:48 INFO:  Watch: {"event":"modify","input":"src/config.ts"}
2021-09-22 15:11:48 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":1416}
2021-09-22 15:11:48 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":51,"inputBytes":496327,"outputBytes":418531}
2021-09-22 15:11:48 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":1424}
2021-09-22 15:11:48 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":51,"inputBytes":496335,"outputBytes":418535}
2021-09-22 15:11:48 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":1491}
2021-09-22 15:11:48 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":51,"inputBytes":496402,"outputBytes":418607}
2021-09-22 15:11:48 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":1631}
2021-09-22 15:11:48 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":3088,"outputBytes":793}
2021-09-22 15:11:48 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":51,"inputBytes":495704,"outputBytes":420009}
2021-09-22 15:11:49 STATE: Compile: {"name":"tfjs/browser/esm/bundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":8,"inputBytes":3088,"outputBytes":2376809}
2021-09-22 15:11:49 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":51,"inputBytes":2871720,"outputBytes":1415173}
2021-09-22 15:11:50 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":51,"inputBytes":2871720,"outputBytes":2623730}
2021-09-22 15:14:03 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/html","size":32718,"url":"/typedoc/index.html","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:04 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":32475,"url":"/typedoc/assets/style.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:04 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":480,"url":"/typedoc/assets/highlight.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:04 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/javascript","size":43169,"url":"/typedoc/assets/main.js","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:04 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/javascript","size":69586,"url":"/typedoc/assets/search.js","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:04 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":35195,"url":"/typedoc/assets/icons.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:04 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"image/png","size":855,"url":"/typedoc/assets/widgets@2x.png","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:04 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"image/png","size":28144,"url":"/typedoc/assets/icons@2x.png","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:13 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/html","size":54951,"url":"/typedoc/classes/Human.html","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:13 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":32475,"url":"/typedoc/assets/style.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:13 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":480,"url":"/typedoc/assets/highlight.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:13 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/javascript","size":43169,"url":"/typedoc/assets/main.js","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:13 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/javascript","size":69586,"url":"/typedoc/assets/search.js","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:13 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"text/css","size":35195,"url":"/typedoc/assets/icons.css","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:13 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"image/png","size":855,"url":"/typedoc/assets/widgets@2x.png","remote":"::ffff:192.168.0.200"}
2021-09-22 15:14:13 DATA:  HTTP: {"method":"GET","ver":"1.1","status":200,"mime":"image/png","size":28144,"url":"/typedoc/assets/icons@2x.png","remote":"::ffff:192.168.0.200"}
2021-09-22 15:15:06 INFO:  Watch: {"event":"modify","input":"src/human.ts"}
2021-09-22 15:15:06 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":1416}
2021-09-22 15:15:06 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":51,"inputBytes":496312,"outputBytes":418531}
2021-09-22 15:15:06 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":1424}
2021-09-22 15:15:06 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":51,"inputBytes":496320,"outputBytes":418535}
2021-09-22 15:15:06 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":1491}
2021-09-22 15:15:06 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":51,"inputBytes":496387,"outputBytes":418607}
2021-09-22 15:15:06 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":1631}
2021-09-22 15:15:06 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":3088,"outputBytes":793}
2021-09-22 15:15:06 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":51,"inputBytes":495689,"outputBytes":420009}
2021-09-22 15:15:07 STATE: Compile: {"name":"tfjs/browser/esm/bundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":8,"inputBytes":3088,"outputBytes":2376809}
2021-09-22 15:15:07 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":51,"inputBytes":2871705,"outputBytes":1415173}
2021-09-22 15:15:08 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":51,"inputBytes":2871705,"outputBytes":2623730}

File diff suppressed because one or more lines are too long

View File

@ -23,7 +23,7 @@
<li>face: draw detected faces</li>
<li>body: draw detected people and body parts</li>
<li>hand: draw detected hands and hand parts</li>
<li>canvas: draw this.processed canvas which is a this.processed copy of the input</li>
<li>canvas: draw processed canvas which is a processed copy of the input</li>
<li>all: meta-function that performs: canvas, face, body, hand</li>
</ul>
</div></div><div class="tsd-type-declaration"><h4>Type declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter"><h5>all<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></h5></li><li class="tsd-parameter"><h5>body<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></h5></li><li class="tsd-parameter"><h5>canvas<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></h5></li><li class="tsd-parameter"><h5>face<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></h5></li><li class="tsd-parameter"><h5>gesture<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></h5></li><li class="tsd-parameter"><h5>hand<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></h5></li><li class="tsd-parameter"><h5>object<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></h5></li><li class="tsd-parameter"><h5>options<span class="tsd-signature-symbol">: </span><a href="../interfaces/DrawOptions.html" class="tsd-signature-type" data-tsd-kind="Interface">DrawOptions</a></h5></li><li class="tsd-parameter"><h5>person<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></h5></li></ul></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-class"><a name="env" class="tsd-anchor"></a><h3>env</h3><div class="tsd-signature tsd-kind-icon">env<span class="tsd-signature-symbol">:</span> <a href="../index.html#Env" class="tsd-signature-type" data-tsd-kind="Type alias">Env</a></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L107">human.ts:107</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
@ -34,7 +34,7 @@
<ul>
<li><code>create</code>: triggered when Human object is instantiated</li>
<li><code>load</code>: triggered when models are loaded (explicitly or on-demand)</li>
<li><code>image</code>: triggered when input image is this.processed</li>
<li><code>image</code>: triggered when input image is processed</li>
<li><code>result</code>: triggered when detection is complete</li>
<li><code>warmup</code>: triggered when warmup is complete</li>
<li><code>error</code>: triggered on some errors</li>
@ -62,21 +62,21 @@
</ul>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-class"><a name="version" class="tsd-anchor"></a><h3>version</h3><div class="tsd-signature tsd-kind-icon">version<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L79">human.ts:79</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Current version of Human library in <em>semver</em> format</p>
</div></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Methods</h2><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="detect" class="tsd-anchor"></a><h3>detect</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">detect<span class="tsd-signature-symbol">(</span>input<span class="tsd-signature-symbol">: </span><a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a>, userConfig<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><a href="../index.html#Error" class="tsd-signature-type" data-tsd-kind="Type alias">Error</a><span class="tsd-signature-symbol"> | </span><a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L405">human.ts:405</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Methods</h2><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="detect" class="tsd-anchor"></a><h3>detect</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">detect<span class="tsd-signature-symbol">(</span>input<span class="tsd-signature-symbol">: </span><a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a>, userConfig<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><a href="../index.html#Error" class="tsd-signature-type" data-tsd-kind="Type alias">Error</a><span class="tsd-signature-symbol"> | </span><a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L412">human.ts:412</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Main detection method</p>
<ul>
<li>Analyze configuration: <a href="../interfaces/Config.html">Config</a></li>
<li>Pre-this.process input: <a href="../index.html#Input">Input</a></li>
<li>Pre-process input: <a href="../index.html#Input">Input</a></li>
<li>Run inference for all configured models</li>
<li>Process and return result: <a href="../interfaces/Result.html">Result</a></li>
</ul>
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5>input: <a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a></h5></li><li><h5><span class="tsd-flag ts-flagOptional">Optional</span> userConfig: <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><a href="../index.html#Error" class="tsd-signature-type" data-tsd-kind="Type alias">Error</a><span class="tsd-signature-symbol"> | </span><a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a><span class="tsd-signature-symbol">&gt;</span></h4><div><p>result: <a href="../interfaces/Result.html">Result</a></p>
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="enhance" class="tsd-anchor"></a><h3>enhance</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">enhance<span class="tsd-signature-symbol">(</span>input<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L305">human.ts:305</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="enhance" class="tsd-anchor"></a><h3>enhance</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">enhance<span class="tsd-signature-symbol">(</span>input<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L312">human.ts:312</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Enhance method performs additional enhacements to face image previously detected for futher processing</p>
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5>input: <span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span></h4><div><p>Tensor</p>
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="image" class="tsd-anchor"></a><h3>image</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">image<span class="tsd-signature-symbol">(</span>input<span class="tsd-signature-symbol">: </span><a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>canvas<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span><span class="tsd-signature-symbol">; </span>tensor<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol"> }</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L272">human.ts:272</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Process input as return canvas and tensor</p>
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5>input: <a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-symbol">{ </span>canvas<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span><span class="tsd-signature-symbol">; </span>tensor<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol"> }</span></h4><div></div><ul class="tsd-parameters"><li class="tsd-parameter"><h5>canvas<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span></h5></li><li class="tsd-parameter"><h5>tensor<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span></h5></li></ul></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="init" class="tsd-anchor"></a><h3>init</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">init<span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L328">human.ts:328</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5>input: <a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-symbol">{ </span>canvas<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span><span class="tsd-signature-symbol">; </span>tensor<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol"> }</span></h4><div></div><ul class="tsd-parameters"><li class="tsd-parameter"><h5>canvas<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span></h5></li><li class="tsd-parameter"><h5>tensor<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Tensor</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Rank</span><span class="tsd-signature-symbol">&gt;</span></h5></li></ul></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="init" class="tsd-anchor"></a><h3>init</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">init<span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L335">human.ts:335</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Explicit backend initialization</p>
<ul>
<li>Normally done implicitly during initial load phase</li>
@ -84,29 +84,36 @@
<li>Use when changing backend during runtime</li>
</ul>
</div></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><div><p>Promise<void></p>
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="load" class="tsd-anchor"></a><h3>load</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">load<span class="tsd-signature-symbol">(</span>userConfig<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L340">human.ts:340</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="load" class="tsd-anchor"></a><h3>load</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">load<span class="tsd-signature-symbol">(</span>userConfig<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L347">human.ts:347</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Load method preloads all configured models on-demand</p>
<ul>
<li>Not explicitly required as any required model is load implicitly on it&#39;s first run</li>
</ul>
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5><span class="tsd-flag ts-flagOptional">Optional</span> userConfig: <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><div><p>Promise<void></p>
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="match" class="tsd-anchor"></a><h3>match</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">match<span class="tsd-signature-symbol">(</span>faceEmbedding<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span>, db<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>embedding<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">; </span>name<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>source<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">[]</span>, threshold<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>embedding<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">; </span>name<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>similarity<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span>source<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> }</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L317">human.ts:317</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="match" class="tsd-anchor"></a><h3>match</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">match<span class="tsd-signature-symbol">(</span>faceEmbedding<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span>, db<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>embedding<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">; </span>name<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>source<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">[]</span>, threshold<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>embedding<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">; </span>name<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>similarity<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span>source<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> }</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L324">human.ts:324</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Math method find best match between provided face descriptor and predefined database of known descriptors</p>
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5>faceEmbedding: <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span></h5></li><li><h5>db: <span class="tsd-signature-symbol">{ </span>embedding<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">; </span>name<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>source<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">[]</span></h5></li><li><h5>threshold: <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> = 0</span></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-symbol">{ </span>embedding<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">; </span>name<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>similarity<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span>source<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> }</span></h4><div><p>best match</p>
</div><ul class="tsd-parameters"><li class="tsd-parameter"><h5>embedding<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span></h5></li><li class="tsd-parameter"><h5>name<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></h5></li><li class="tsd-parameter"><h5>similarity<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5></li><li class="tsd-parameter"><h5>source<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></h5></li></ul></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="next" class="tsd-anchor"></a><h3>next</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">next<span class="tsd-signature-symbol">(</span>result<span class="tsd-signature-symbol">?: </span><a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L381">human.ts:381</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div><ul class="tsd-parameters"><li class="tsd-parameter"><h5>embedding<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span></h5></li><li class="tsd-parameter"><h5>name<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></h5></li><li class="tsd-parameter"><h5>similarity<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5></li><li class="tsd-parameter"><h5>source<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></h5></li></ul></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="next" class="tsd-anchor"></a><h3>next</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">next<span class="tsd-signature-symbol">(</span>result<span class="tsd-signature-symbol">?: </span><a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L388">human.ts:388</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Runs interpolation using last known result and returns smoothened result
Interpolation is based on time since last known result so can be called independently</p>
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5>result: <a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a><span class="tsd-signature-symbol"> = ...</span></h5></li></ul><h4 class="tsd-returns-title">Returns <a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a></h4><div><p>result: <a href="../interfaces/Result.html">Result</a></p>
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="reset" class="tsd-anchor"></a><h3>reset</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">reset<span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">void</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L258">human.ts:258</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Reset configuration to default values</p>
</div></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="segmentation" class="tsd-anchor"></a><h3>segmentation</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">segmentation<span class="tsd-signature-symbol">(</span>input<span class="tsd-signature-symbol">: </span><a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a>, background<span class="tsd-signature-symbol">?: </span><a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L295">human.ts:295</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Segmentation method takes any input and returns this.processed canvas with body segmentation</p>
</div></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="segmentation" class="tsd-anchor"></a><h3>segmentation</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">segmentation<span class="tsd-signature-symbol">(</span>input<span class="tsd-signature-symbol">: </span><a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a>, background<span class="tsd-signature-symbol">?: </span><a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-symbol">{ </span>alpha<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span><span class="tsd-signature-symbol">; </span>canvas<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span><span class="tsd-signature-symbol">; </span>data<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Uint8ClampedArray</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L302">human.ts:302</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Segmentation method takes any input and returns processed canvas with body segmentation</p>
<ul>
<li>Optional parameter background is used to fill the background with specific input</li>
<li>Segmentation is not triggered as part of detect this.process</li>
<li>Segmentation is not triggered as part of detect process</li>
</ul>
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5>input: <a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a></h5></li><li><h5><span class="tsd-flag ts-flagOptional">Optional</span> background: <a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span><span class="tsd-signature-symbol">&gt;</span></h4><div><p>Canvas</p>
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="similarity" class="tsd-anchor"></a><h3>similarity</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">similarity<span class="tsd-signature-symbol">(</span>embedding1<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span>, embedding2<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L283">human.ts:283</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div><div><p> Returns:</p>
<ul>
<li><code>data</code> as raw data array with per-pixel segmentation values</li>
<li><code>canvas</code> as canvas which is input image filtered with segementation data
and optionally merged with background image
canvas alpha values are set to segmentation values for easy merging</li>
<li><code>alpha</code> as grayscale canvas that represents segmentation alpha values</li>
</ul>
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5>input: <a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a></h5></li><li><h5><span class="tsd-flag ts-flagOptional">Optional</span> background: <a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-symbol">{ </span>alpha<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span><span class="tsd-signature-symbol">; </span>canvas<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">OffscreenCanvas</span><span class="tsd-signature-symbol">; </span>data<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Uint8ClampedArray</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">&gt;</span></h4><div></div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="similarity" class="tsd-anchor"></a><h3>similarity</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">similarity<span class="tsd-signature-symbol">(</span>embedding1<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span>, embedding2<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L283">human.ts:283</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Simmilarity method calculates simmilarity between two provided face descriptors (face embeddings)</p>
<ul>
<li>Calculation is based on normalized Minkowski distance between two descriptors</li>
@ -115,7 +122,7 @@ Interpolation is based on time since last known result so can be called independ
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5>embedding1: <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span></h5></li><li><h5>embedding2: <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">number</span></h4><div><p>similarity: number</p>
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="validate" class="tsd-anchor"></a><h3>validate</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">validate<span class="tsd-signature-symbol">(</span>userConfig<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>expected<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>reason<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>where<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">[]</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L265">human.ts:265</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Validate current configuration schema</p>
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5><span class="tsd-flag ts-flagOptional">Optional</span> userConfig: <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-symbol">{ </span>expected<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>reason<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>where<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">[]</span></h4></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="warmup" class="tsd-anchor"></a><h3>warmup</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">warmup<span class="tsd-signature-symbol">(</span>userConfig<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-symbol">{ </span>error<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L391">human.ts:391</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameters"><li><h5><span class="tsd-flag ts-flagOptional">Optional</span> userConfig: <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span></h5></li></ul><h4 class="tsd-returns-title">Returns <span class="tsd-signature-symbol">{ </span>expected<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>reason<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span>where<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">[]</span></h4></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="warmup" class="tsd-anchor"></a><h3>warmup</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">warmup<span class="tsd-signature-symbol">(</span>userConfig<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-symbol">{ </span>error<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">&gt;</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L398">human.ts:398</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Warmup method pre-initializes all configured models for faster inference</p>
<ul>
<li>can take significant time on startup</li>

View File

@ -5,7 +5,7 @@
</div><div><ul>
<li><code>create</code>: triggered when Human object is instantiated</li>
<li><code>load</code>: triggered when models are loaded (explicitly or on-demand)</li>
<li><code>image</code>: triggered when input image is this.processed</li>
<li><code>image</code>: triggered when input image is processed</li>
<li><code>result</code>: triggered when detection is complete</li>
<li><code>warmup</code>: triggered when warmup is complete</li>
</ul>
@ -15,6 +15,6 @@
<p>Defines all possible input types for <strong>Human</strong> detection</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-type-alias"><a name="TensorFlow" class="tsd-anchor"></a><h3>Tensor<wbr/>Flow</h3><div class="tsd-signature tsd-kind-icon">Tensor<wbr/>Flow<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">typeof </span><span class="tsd-signature-type">tf</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L64">human.ts:64</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Instance of TensorFlow/JS</p>
</div><dl class="tsd-comment-tags"><dt>external</dt><dd></dd></dl></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Variables</h2><section class="tsd-panel tsd-member tsd-kind-variable"><a name="defaults" class="tsd-anchor"></a><h3>defaults</h3><div class="tsd-signature tsd-kind-icon">defaults<span class="tsd-signature-symbol">:</span> <a href="interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol"> = ...</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L248">config.ts:248</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div><dl class="tsd-comment-tags"><dt>external</dt><dd></dd></dl></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Variables</h2><section class="tsd-panel tsd-member tsd-kind-variable"><a name="defaults" class="tsd-anchor"></a><h3>defaults</h3><div class="tsd-signature tsd-kind-icon">defaults<span class="tsd-signature-symbol">:</span> <a href="interfaces/Config.html" class="tsd-signature-type" data-tsd-kind="Interface">Config</a><span class="tsd-signature-symbol"> = ...</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L250">config.ts:250</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p><a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L244">See all default Config values...</a></p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-variable"><a name="env" class="tsd-anchor"></a><h3>env</h3><div class="tsd-signature tsd-kind-icon">env<span class="tsd-signature-symbol">:</span> <a href="index.html#Env" class="tsd-signature-type" data-tsd-kind="Type alias">Env</a><span class="tsd-signature-symbol"> = ...</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/env.ts#L40">env.ts:40</a></li></ul></aside></section></section></div><div class="col-4 col-menu menu-sticky-wrap menu-highlight"><nav class="tsd-navigation primary"><ul><li class="current"><a href="index.html">Exports</a></li></ul></nav><nav class="tsd-navigation secondary menu-sticky"><ul><li class="tsd-kind-reference"><a href="index.html#default" class="tsd-kind-icon">default</a></li><li class="tsd-kind-class"><a href="classes/Human.html" class="tsd-kind-icon">Human</a></li><li class="tsd-kind-interface"><a href="interfaces/BodyConfig.html" class="tsd-kind-icon">Body<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/BodyResult.html" class="tsd-kind-icon">Body<wbr/>Result</a></li><li class="tsd-kind-interface"><a href="interfaces/Config.html" class="tsd-kind-icon">Config</a></li><li class="tsd-kind-interface"><a href="interfaces/DrawOptions.html" class="tsd-kind-icon">Draw<wbr/>Options</a></li><li class="tsd-kind-interface"><a href="interfaces/FaceConfig.html" class="tsd-kind-icon">Face<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/FaceDescriptionConfig.html" class="tsd-kind-icon">Face<wbr/>Description<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/FaceDetectorConfig.html" class="tsd-kind-icon">Face<wbr/>Detector<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/FaceEmotionConfig.html" class="tsd-kind-icon">Face<wbr/>Emotion<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/FaceIrisConfig.html" class="tsd-kind-icon">Face<wbr/>Iris<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/FaceMeshConfig.html" class="tsd-kind-icon">Face<wbr/>Mesh<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/FaceResult.html" class="tsd-kind-icon">Face<wbr/>Result</a></li><li class="tsd-kind-interface"><a href="interfaces/FilterConfig.html" class="tsd-kind-icon">Filter<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/GestureConfig.html" class="tsd-kind-icon">Gesture<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/HandConfig.html" class="tsd-kind-icon">Hand<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/HandResult.html" class="tsd-kind-icon">Hand<wbr/>Result</a></li><li class="tsd-kind-interface"><a href="interfaces/ObjectConfig.html" class="tsd-kind-icon">Object<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/ObjectResult.html" class="tsd-kind-icon">Object<wbr/>Result</a></li><li class="tsd-kind-interface"><a href="interfaces/PersonResult.html" class="tsd-kind-icon">Person<wbr/>Result</a></li><li class="tsd-kind-interface"><a href="interfaces/Result.html" class="tsd-kind-icon">Result</a></li><li class="tsd-kind-interface"><a href="interfaces/SegmentationConfig.html" class="tsd-kind-icon">Segmentation<wbr/>Config</a></li><li class="tsd-kind-type-alias"><a href="index.html#Env" class="tsd-kind-icon">Env</a></li><li class="tsd-kind-type-alias"><a href="index.html#Error" class="tsd-kind-icon">Error</a></li><li class="tsd-kind-type-alias"><a href="index.html#Events" class="tsd-kind-icon">Events</a></li><li class="tsd-kind-type-alias"><a href="index.html#GestureResult" class="tsd-kind-icon">Gesture<wbr/>Result</a></li><li class="tsd-kind-type-alias"><a href="index.html#Input" class="tsd-kind-icon">Input</a></li><li class="tsd-kind-type-alias"><a href="index.html#TensorFlow" class="tsd-kind-icon">Tensor<wbr/>Flow</a></li><li class="tsd-kind-variable"><a href="index.html#defaults" class="tsd-kind-icon">defaults</a></li><li class="tsd-kind-variable"><a href="index.html#env" class="tsd-kind-icon">env</a></li></ul></nav></div></div></div><footer class=""><div class="container"><h2>Legend</h2><div class="tsd-legend-group"><ul class="tsd-legend"><li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li><li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li><li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li></ul><ul class="tsd-legend"><li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li></ul></div><h2>Settings</h2><p>Theme <select id="theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></p></div></footer><div class="overlay"></div><script src="assets/main.js"></script></body></html>

View File

@ -1,38 +1,38 @@
<!DOCTYPE html><html class="default no-js"><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><title>Config | @vladmandic/human - v2.2.2</title><meta name="description" content="Documentation for @vladmandic/human - v2.2.2"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script async src="../assets/search.js" id="search-script"></script></head><body><header><div class="tsd-page-toolbar"><div class="container"><div class="table-wrap"><div class="table-cell" id="tsd-search" data-base=".."><div class="field"><label for="tsd-search-field" class="tsd-widget search no-caption">Search</label><input type="text" id="tsd-search-field"/></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">@vladmandic/human - v2.2.2</a></div><div class="table-cell" id="tsd-widgets"><div id="tsd-filter"><a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a><div class="tsd-filter-group"><div class="tsd-select" id="tsd-filter-visibility"><span class="tsd-select-label">All</span><ul class="tsd-select-list"><li data-value="public">Public</li><li data-value="protected">Public/Protected</li><li data-value="private" class="selected">All</li></ul></div> <input type="checkbox" id="tsd-filter-inherited" checked/><label class="tsd-widget" for="tsd-filter-inherited">Inherited</label></div></div><a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a></div></div></div></div><div class="tsd-page-title"><div class="container"><ul class="tsd-breadcrumb"><li><a href="../index.html">@vladmandic/human - v2.2.2</a></li><li><a href="Config.html">Config</a></li></ul><h1>Interface Config</h1></div></div></header><div class="container container-main"><div class="row"><div class="col-8 col-content"><section class="tsd-panel tsd-comment"><div class="tsd-comment tsd-typography"><div class="lead">
<p>Configuration interface definition for <strong>Human</strong> library</p>
</div><div><p>Contains all configurable parameters</p>
</div></div></section><section class="tsd-panel tsd-hierarchy"><h3>Hierarchy</h3><ul class="tsd-hierarchy"><li><span class="target">Config</span></li></ul></section><section class="tsd-panel-group tsd-index-group"><h2>Index</h2><section class="tsd-panel tsd-index-panel"><div class="tsd-index-content"><section class="tsd-index-section "><h3>Properties</h3><ul class="tsd-index-list"><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#async" class="tsd-kind-icon">async</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#backend" class="tsd-kind-icon">backend</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#body" class="tsd-kind-icon">body</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#cacheSensitivity" class="tsd-kind-icon">cache<wbr/>Sensitivity</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#debug" class="tsd-kind-icon">debug</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#face" class="tsd-kind-icon">face</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#filter" class="tsd-kind-icon">filter</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#gesture" class="tsd-kind-icon">gesture</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#hand" class="tsd-kind-icon">hand</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#modelBasePath" class="tsd-kind-icon">model<wbr/>Base<wbr/>Path</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#object" class="tsd-kind-icon">object</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#segmentation" class="tsd-kind-icon">segmentation</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#skipFrame" class="tsd-kind-icon">skip<wbr/>Frame</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#warmup" class="tsd-kind-icon">warmup</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#wasmPath" class="tsd-kind-icon">wasm<wbr/>Path</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#yield" class="tsd-kind-icon">yield</a></li></ul></section></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Properties</h2><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="async" class="tsd-anchor"></a><h3>async</h3><div class="tsd-signature tsd-kind-icon">async<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L199">config.ts:199</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-hierarchy"><h3>Hierarchy</h3><ul class="tsd-hierarchy"><li><span class="target">Config</span></li></ul></section><section class="tsd-panel-group tsd-index-group"><h2>Index</h2><section class="tsd-panel tsd-index-panel"><div class="tsd-index-content"><section class="tsd-index-section "><h3>Properties</h3><ul class="tsd-index-list"><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#async" class="tsd-kind-icon">async</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#backend" class="tsd-kind-icon">backend</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#body" class="tsd-kind-icon">body</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#cacheSensitivity" class="tsd-kind-icon">cache<wbr/>Sensitivity</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#debug" class="tsd-kind-icon">debug</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#face" class="tsd-kind-icon">face</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#filter" class="tsd-kind-icon">filter</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#gesture" class="tsd-kind-icon">gesture</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#hand" class="tsd-kind-icon">hand</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#modelBasePath" class="tsd-kind-icon">model<wbr/>Base<wbr/>Path</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#object" class="tsd-kind-icon">object</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#segmentation" class="tsd-kind-icon">segmentation</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#skipFrame" class="tsd-kind-icon">skip<wbr/>Frame</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#warmup" class="tsd-kind-icon">warmup</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#wasmPath" class="tsd-kind-icon">wasm<wbr/>Path</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#yield" class="tsd-kind-icon">yield</a></li></ul></section></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Properties</h2><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="async" class="tsd-anchor"></a><h3>async</h3><div class="tsd-signature tsd-kind-icon">async<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L201">config.ts:201</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Perform model loading and inference concurrently or sequentially</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="backend" class="tsd-anchor"></a><h3>backend</h3><div class="tsd-signature tsd-kind-icon">backend<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">&quot;&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;cpu&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;wasm&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;webgl&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;humangl&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;tensorflow&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;webgpu&quot;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L189">config.ts:189</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="backend" class="tsd-anchor"></a><h3>backend</h3><div class="tsd-signature tsd-kind-icon">backend<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">&quot;&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;cpu&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;wasm&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;webgl&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;humangl&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;tensorflow&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;webgpu&quot;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L191">config.ts:191</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Backend used for TFJS operations</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="body" class="tsd-anchor"></a><h3>body</h3><div class="tsd-signature tsd-kind-icon">body<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="BodyConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">BodyConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L235">config.ts:235</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="cacheSensitivity" class="tsd-anchor"></a><h3>cache<wbr/>Sensitivity</h3><div class="tsd-signature tsd-kind-icon">cache<wbr/>Sensitivity<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L217">config.ts:217</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="body" class="tsd-anchor"></a><h3>body</h3><div class="tsd-signature tsd-kind-icon">body<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="BodyConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">BodyConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L237">config.ts:237</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="cacheSensitivity" class="tsd-anchor"></a><h3>cache<wbr/>Sensitivity</h3><div class="tsd-signature tsd-kind-icon">cache<wbr/>Sensitivity<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L219">config.ts:219</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Cache sensitivity</p>
<ul>
<li>values 0..1 where 0.01 means reset cache if input changed more than 1%</li>
<li>set to 0 to disable caching</li>
</ul>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="debug" class="tsd-anchor"></a><h3>debug</h3><div class="tsd-signature tsd-kind-icon">debug<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L196">config.ts:196</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="debug" class="tsd-anchor"></a><h3>debug</h3><div class="tsd-signature tsd-kind-icon">debug<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L198">config.ts:198</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Print debug statements to console</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="face" class="tsd-anchor"></a><h3>face</h3><div class="tsd-signature tsd-kind-icon">face<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="FaceConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">FaceConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L233">config.ts:233</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="filter" class="tsd-anchor"></a><h3>filter</h3><div class="tsd-signature tsd-kind-icon">filter<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="FilterConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">FilterConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L228">config.ts:228</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="face" class="tsd-anchor"></a><h3>face</h3><div class="tsd-signature tsd-kind-icon">face<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="FaceConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">FaceConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L235">config.ts:235</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="filter" class="tsd-anchor"></a><h3>filter</h3><div class="tsd-signature tsd-kind-icon">filter<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="FilterConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">FilterConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L230">config.ts:230</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Run input through image filters before inference</p>
<ul>
<li>image filters run with near-zero latency as they are executed on the GPU</li>
</ul>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="gesture" class="tsd-anchor"></a><h3>gesture</h3><div class="tsd-signature tsd-kind-icon">gesture<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="GestureConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">GestureConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L231">config.ts:231</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="hand" class="tsd-anchor"></a><h3>hand</h3><div class="tsd-signature tsd-kind-icon">hand<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="HandConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">HandConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L237">config.ts:237</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="modelBasePath" class="tsd-anchor"></a><h3>model<wbr/>Base<wbr/>Path</h3><div class="tsd-signature tsd-kind-icon">model<wbr/>Base<wbr/>Path<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L211">config.ts:211</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="gesture" class="tsd-anchor"></a><h3>gesture</h3><div class="tsd-signature tsd-kind-icon">gesture<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="GestureConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">GestureConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L233">config.ts:233</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="hand" class="tsd-anchor"></a><h3>hand</h3><div class="tsd-signature tsd-kind-icon">hand<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="HandConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">HandConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L239">config.ts:239</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="modelBasePath" class="tsd-anchor"></a><h3>model<wbr/>Base<wbr/>Path</h3><div class="tsd-signature tsd-kind-icon">model<wbr/>Base<wbr/>Path<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L213">config.ts:213</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Base model path (typically starting with file://, http:// or https://) for all models</p>
<ul>
<li>individual modelPath values are relative to this path</li>
</ul>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="object" class="tsd-anchor"></a><h3>object</h3><div class="tsd-signature tsd-kind-icon">object<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="ObjectConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">ObjectConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L239">config.ts:239</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="segmentation" class="tsd-anchor"></a><h3>segmentation</h3><div class="tsd-signature tsd-kind-icon">segmentation<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="SegmentationConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">SegmentationConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L241">config.ts:241</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="skipFrame" class="tsd-anchor"></a><h3>skip<wbr/>Frame</h3><div class="tsd-signature tsd-kind-icon">skip<wbr/>Frame<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L223">config.ts:223</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="object" class="tsd-anchor"></a><h3>object</h3><div class="tsd-signature tsd-kind-icon">object<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="ObjectConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">ObjectConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L241">config.ts:241</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="segmentation" class="tsd-anchor"></a><h3>segmentation</h3><div class="tsd-signature tsd-kind-icon">segmentation<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><a href="SegmentationConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">SegmentationConfig</a><span class="tsd-signature-symbol">&gt;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L243">config.ts:243</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="skipFrame" class="tsd-anchor"></a><h3>skip<wbr/>Frame</h3><div class="tsd-signature tsd-kind-icon">skip<wbr/>Frame<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L225">config.ts:225</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Internal Variable</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="warmup" class="tsd-anchor"></a><h3>warmup</h3><div class="tsd-signature tsd-kind-icon">warmup<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">&quot;face&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;body&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;none&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;full&quot;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L205">config.ts:205</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="warmup" class="tsd-anchor"></a><h3>warmup</h3><div class="tsd-signature tsd-kind-icon">warmup<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">&quot;face&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;body&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;none&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;full&quot;</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L207">config.ts:207</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>What to use for <code>human.warmup()</code></p>
<ul>
<li>warmup pre-initializes all models for faster inference but can take significant time on startup</li>
<li>only used for <code>webgl</code> and <code>humangl</code> backends</li>
</ul>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="wasmPath" class="tsd-anchor"></a><h3>wasm<wbr/>Path</h3><div class="tsd-signature tsd-kind-icon">wasm<wbr/>Path<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L193">config.ts:193</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="wasmPath" class="tsd-anchor"></a><h3>wasm<wbr/>Path</h3><div class="tsd-signature tsd-kind-icon">wasm<wbr/>Path<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L195">config.ts:195</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Path to *.wasm files if backend is set to <code>wasm</code></p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="yield" class="tsd-anchor"></a><h3>yield</h3><div class="tsd-signature tsd-kind-icon">yield<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L220">config.ts:220</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="yield" class="tsd-anchor"></a><h3>yield</h3><div class="tsd-signature tsd-kind-icon">yield<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L222">config.ts:222</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Yield to main thread periodically</p>
</div></div></section></section></div><div class="col-4 col-menu menu-sticky-wrap menu-highlight"><nav class="tsd-navigation primary"><ul><li class=""><a href="../index.html">Exports</a></li></ul></nav><nav class="tsd-navigation secondary menu-sticky"><ul><li class="current tsd-kind-interface"><a href="Config.html" class="tsd-kind-icon">Config</a><ul><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#async" class="tsd-kind-icon">async</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#backend" class="tsd-kind-icon">backend</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#body" class="tsd-kind-icon">body</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#cacheSensitivity" class="tsd-kind-icon">cache<wbr/>Sensitivity</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#debug" class="tsd-kind-icon">debug</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#face" class="tsd-kind-icon">face</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#filter" class="tsd-kind-icon">filter</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#gesture" class="tsd-kind-icon">gesture</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#hand" class="tsd-kind-icon">hand</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#modelBasePath" class="tsd-kind-icon">model<wbr/>Base<wbr/>Path</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#object" class="tsd-kind-icon">object</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#segmentation" class="tsd-kind-icon">segmentation</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#skipFrame" class="tsd-kind-icon">skip<wbr/>Frame</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#warmup" class="tsd-kind-icon">warmup</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#wasmPath" class="tsd-kind-icon">wasm<wbr/>Path</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="Config.html#yield" class="tsd-kind-icon">yield</a></li></ul></li></ul></nav></div></div></div><footer class=""><div class="container"><h2>Legend</h2><div class="tsd-legend-group"><ul class="tsd-legend"><li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li><li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li><li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li></ul><ul class="tsd-legend"><li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li></ul></div><h2>Settings</h2><p>Theme <select id="theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></p></div></footer><div class="overlay"></div><script src="../assets/main.js"></script></body></html>

View File

@ -3,44 +3,44 @@
<ul>
<li>image filters run with near-zero latency as they are executed on the GPU</li>
</ul>
</div></div></section><section class="tsd-panel tsd-hierarchy"><h3>Hierarchy</h3><ul class="tsd-hierarchy"><li><span class="target">FilterConfig</span></li></ul></section><section class="tsd-panel-group tsd-index-group"><h2>Index</h2><section class="tsd-panel tsd-index-panel"><div class="tsd-index-content"><section class="tsd-index-section "><h3>Properties</h3><ul class="tsd-index-list"><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#blur" class="tsd-kind-icon">blur</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#brightness" class="tsd-kind-icon">brightness</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#contrast" class="tsd-kind-icon">contrast</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#enabled" class="tsd-kind-icon">enabled</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#flip" class="tsd-kind-icon">flip</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#height" class="tsd-kind-icon">height</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#hue" class="tsd-kind-icon">hue</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#kodachrome" class="tsd-kind-icon">kodachrome</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#negative" class="tsd-kind-icon">negative</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#pixelate" class="tsd-kind-icon">pixelate</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#polaroid" class="tsd-kind-icon">polaroid</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#return" class="tsd-kind-icon">return</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#saturation" class="tsd-kind-icon">saturation</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#sepia" class="tsd-kind-icon">sepia</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#sharpness" class="tsd-kind-icon">sharpness</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#technicolor" class="tsd-kind-icon">technicolor</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#vintage" class="tsd-kind-icon">vintage</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#width" class="tsd-kind-icon">width</a></li></ul></section></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Properties</h2><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="blur" class="tsd-anchor"></a><h3>blur</h3><div class="tsd-signature tsd-kind-icon">blur<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L155">config.ts:155</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-hierarchy"><h3>Hierarchy</h3><ul class="tsd-hierarchy"><li><span class="target">FilterConfig</span></li></ul></section><section class="tsd-panel-group tsd-index-group"><h2>Index</h2><section class="tsd-panel tsd-index-panel"><div class="tsd-index-content"><section class="tsd-index-section "><h3>Properties</h3><ul class="tsd-index-list"><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#blur" class="tsd-kind-icon">blur</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#brightness" class="tsd-kind-icon">brightness</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#contrast" class="tsd-kind-icon">contrast</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#enabled" class="tsd-kind-icon">enabled</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#flip" class="tsd-kind-icon">flip</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#height" class="tsd-kind-icon">height</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#hue" class="tsd-kind-icon">hue</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#kodachrome" class="tsd-kind-icon">kodachrome</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#negative" class="tsd-kind-icon">negative</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#pixelate" class="tsd-kind-icon">pixelate</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#polaroid" class="tsd-kind-icon">polaroid</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#return" class="tsd-kind-icon">return</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#saturation" class="tsd-kind-icon">saturation</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#sepia" class="tsd-kind-icon">sepia</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#sharpness" class="tsd-kind-icon">sharpness</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#technicolor" class="tsd-kind-icon">technicolor</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#vintage" class="tsd-kind-icon">vintage</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="FilterConfig.html#width" class="tsd-kind-icon">width</a></li></ul></section></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Properties</h2><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="blur" class="tsd-anchor"></a><h3>blur</h3><div class="tsd-signature tsd-kind-icon">blur<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L157">config.ts:157</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Range: 0 (no blur) to N (blur radius in pixels)</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="brightness" class="tsd-anchor"></a><h3>brightness</h3><div class="tsd-signature tsd-kind-icon">brightness<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L149">config.ts:149</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="brightness" class="tsd-anchor"></a><h3>brightness</h3><div class="tsd-signature tsd-kind-icon">brightness<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L151">config.ts:151</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Range: -1 (darken) to 1 (lighten)</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="contrast" class="tsd-anchor"></a><h3>contrast</h3><div class="tsd-signature tsd-kind-icon">contrast<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L151">config.ts:151</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="contrast" class="tsd-anchor"></a><h3>contrast</h3><div class="tsd-signature tsd-kind-icon">contrast<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L153">config.ts:153</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Range: -1 (reduce contrast) to 1 (increase contrast)</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="enabled" class="tsd-anchor"></a><h3>enabled</h3><div class="tsd-signature tsd-kind-icon">enabled<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L131">config.ts:131</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="flip" class="tsd-anchor"></a><h3>flip</h3><div class="tsd-signature tsd-kind-icon">flip<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L147">config.ts:147</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="enabled" class="tsd-anchor"></a><h3>enabled</h3><div class="tsd-signature tsd-kind-icon">enabled<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L133">config.ts:133</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="flip" class="tsd-anchor"></a><h3>flip</h3><div class="tsd-signature tsd-kind-icon">flip<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L149">config.ts:149</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Flip input as mirror image</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="height" class="tsd-anchor"></a><h3>height</h3><div class="tsd-signature tsd-kind-icon">height<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L143">config.ts:143</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="height" class="tsd-anchor"></a><h3>height</h3><div class="tsd-signature tsd-kind-icon">height<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L145">config.ts:145</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Resize input height</p>
<ul>
<li>if both width and height are set to 0, there is no resizing</li>
<li>if just one is set, second one is scaled automatically</li>
<li>if both are set, values are used as-is</li>
</ul>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="hue" class="tsd-anchor"></a><h3>hue</h3><div class="tsd-signature tsd-kind-icon">hue<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L159">config.ts:159</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="hue" class="tsd-anchor"></a><h3>hue</h3><div class="tsd-signature tsd-kind-icon">hue<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L161">config.ts:161</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Range: 0 (no change) to 360 (hue rotation in degrees)</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="kodachrome" class="tsd-anchor"></a><h3>kodachrome</h3><div class="tsd-signature tsd-kind-icon">kodachrome<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L167">config.ts:167</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="kodachrome" class="tsd-anchor"></a><h3>kodachrome</h3><div class="tsd-signature tsd-kind-icon">kodachrome<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L169">config.ts:169</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Image kodachrome colors</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="negative" class="tsd-anchor"></a><h3>negative</h3><div class="tsd-signature tsd-kind-icon">negative<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L161">config.ts:161</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="negative" class="tsd-anchor"></a><h3>negative</h3><div class="tsd-signature tsd-kind-icon">negative<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L163">config.ts:163</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Image negative</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="pixelate" class="tsd-anchor"></a><h3>pixelate</h3><div class="tsd-signature tsd-kind-icon">pixelate<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L173">config.ts:173</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="pixelate" class="tsd-anchor"></a><h3>pixelate</h3><div class="tsd-signature tsd-kind-icon">pixelate<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L175">config.ts:175</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Range: 0 (no pixelate) to N (number of pixels to pixelate)</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="polaroid" class="tsd-anchor"></a><h3>polaroid</h3><div class="tsd-signature tsd-kind-icon">polaroid<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L171">config.ts:171</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="polaroid" class="tsd-anchor"></a><h3>polaroid</h3><div class="tsd-signature tsd-kind-icon">polaroid<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L173">config.ts:173</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Image polaroid camera effect</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="return" class="tsd-anchor"></a><h3>return</h3><div class="tsd-signature tsd-kind-icon">return<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L145">config.ts:145</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="return" class="tsd-anchor"></a><h3>return</h3><div class="tsd-signature tsd-kind-icon">return<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L147">config.ts:147</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Return processed canvas imagedata in result</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="saturation" class="tsd-anchor"></a><h3>saturation</h3><div class="tsd-signature tsd-kind-icon">saturation<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L157">config.ts:157</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="saturation" class="tsd-anchor"></a><h3>saturation</h3><div class="tsd-signature tsd-kind-icon">saturation<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L159">config.ts:159</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Range: -1 (reduce saturation) to 1 (increase saturation)</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="sepia" class="tsd-anchor"></a><h3>sepia</h3><div class="tsd-signature tsd-kind-icon">sepia<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L163">config.ts:163</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="sepia" class="tsd-anchor"></a><h3>sepia</h3><div class="tsd-signature tsd-kind-icon">sepia<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L165">config.ts:165</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Image sepia colors</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="sharpness" class="tsd-anchor"></a><h3>sharpness</h3><div class="tsd-signature tsd-kind-icon">sharpness<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L153">config.ts:153</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="sharpness" class="tsd-anchor"></a><h3>sharpness</h3><div class="tsd-signature tsd-kind-icon">sharpness<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L155">config.ts:155</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Range: 0 (no sharpening) to 1 (maximum sharpening)</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="technicolor" class="tsd-anchor"></a><h3>technicolor</h3><div class="tsd-signature tsd-kind-icon">technicolor<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L169">config.ts:169</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="technicolor" class="tsd-anchor"></a><h3>technicolor</h3><div class="tsd-signature tsd-kind-icon">technicolor<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L171">config.ts:171</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Image technicolor colors</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="vintage" class="tsd-anchor"></a><h3>vintage</h3><div class="tsd-signature tsd-kind-icon">vintage<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L165">config.ts:165</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="vintage" class="tsd-anchor"></a><h3>vintage</h3><div class="tsd-signature tsd-kind-icon">vintage<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L167">config.ts:167</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Image vintage colors</p>
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="width" class="tsd-anchor"></a><h3>width</h3><div class="tsd-signature tsd-kind-icon">width<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L137">config.ts:137</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
</div></div></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="width" class="tsd-anchor"></a><h3>width</h3><div class="tsd-signature tsd-kind-icon">width<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L139">config.ts:139</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Resize input width</p>
<ul>
<li>if both width and height are set to 0, there is no resizing</li>

View File

@ -1,3 +1,3 @@
<!DOCTYPE html><html class="default no-js"><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><title>GestureConfig | @vladmandic/human - v2.2.2</title><meta name="description" content="Documentation for @vladmandic/human - v2.2.2"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script async src="../assets/search.js" id="search-script"></script></head><body><header><div class="tsd-page-toolbar"><div class="container"><div class="table-wrap"><div class="table-cell" id="tsd-search" data-base=".."><div class="field"><label for="tsd-search-field" class="tsd-widget search no-caption">Search</label><input type="text" id="tsd-search-field"/></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">@vladmandic/human - v2.2.2</a></div><div class="table-cell" id="tsd-widgets"><div id="tsd-filter"><a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a><div class="tsd-filter-group"><div class="tsd-select" id="tsd-filter-visibility"><span class="tsd-select-label">All</span><ul class="tsd-select-list"><li data-value="public">Public</li><li data-value="protected">Public/Protected</li><li data-value="private" class="selected">All</li></ul></div> <input type="checkbox" id="tsd-filter-inherited" checked/><label class="tsd-widget" for="tsd-filter-inherited">Inherited</label></div></div><a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a></div></div></div></div><div class="tsd-page-title"><div class="container"><ul class="tsd-breadcrumb"><li><a href="../index.html">@vladmandic/human - v2.2.2</a></li><li><a href="GestureConfig.html">GestureConfig</a></li></ul><h1>Interface GestureConfig</h1></div></div></header><div class="container container-main"><div class="row"><div class="col-8 col-content"><section class="tsd-panel tsd-comment"><div class="tsd-comment tsd-typography"><div class="lead">
<p>Controlls gesture detection</p>
</div></div></section><section class="tsd-panel tsd-hierarchy"><h3>Hierarchy</h3><ul class="tsd-hierarchy"><li><span class="target">GestureConfig</span></li></ul></section><section class="tsd-panel-group tsd-index-group"><h2>Index</h2><section class="tsd-panel tsd-index-panel"><div class="tsd-index-content"><section class="tsd-index-section "><h3>Properties</h3><ul class="tsd-index-list"><li class="tsd-kind-property tsd-parent-kind-interface"><a href="GestureConfig.html#enabled" class="tsd-kind-icon">enabled</a></li></ul></section></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Properties</h2><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="enabled" class="tsd-anchor"></a><h3>enabled</h3><div class="tsd-signature tsd-kind-icon">enabled<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L178">config.ts:178</a></li></ul></aside></section></section></div><div class="col-4 col-menu menu-sticky-wrap menu-highlight"><nav class="tsd-navigation primary"><ul><li class=""><a href="../index.html">Exports</a></li></ul></nav><nav class="tsd-navigation secondary menu-sticky"><ul><li class="current tsd-kind-interface"><a href="GestureConfig.html" class="tsd-kind-icon">Gesture<wbr/>Config</a><ul><li class="tsd-kind-property tsd-parent-kind-interface"><a href="GestureConfig.html#enabled" class="tsd-kind-icon">enabled</a></li></ul></li></ul></nav></div></div></div><footer class=""><div class="container"><h2>Legend</h2><div class="tsd-legend-group"><ul class="tsd-legend"><li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li><li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li><li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li></ul><ul class="tsd-legend"><li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li></ul></div><h2>Settings</h2><p>Theme <select id="theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></p></div></footer><div class="overlay"></div><script src="../assets/main.js"></script></body></html>
</div></div></section><section class="tsd-panel tsd-hierarchy"><h3>Hierarchy</h3><ul class="tsd-hierarchy"><li><span class="target">GestureConfig</span></li></ul></section><section class="tsd-panel-group tsd-index-group"><h2>Index</h2><section class="tsd-panel tsd-index-panel"><div class="tsd-index-content"><section class="tsd-index-section "><h3>Properties</h3><ul class="tsd-index-list"><li class="tsd-kind-property tsd-parent-kind-interface"><a href="GestureConfig.html#enabled" class="tsd-kind-icon">enabled</a></li></ul></section></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Properties</h2><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="enabled" class="tsd-anchor"></a><h3>enabled</h3><div class="tsd-signature tsd-kind-icon">enabled<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L180">config.ts:180</a></li></ul></aside></section></section></div><div class="col-4 col-menu menu-sticky-wrap menu-highlight"><nav class="tsd-navigation primary"><ul><li class=""><a href="../index.html">Exports</a></li></ul></nav><nav class="tsd-navigation secondary menu-sticky"><ul><li class="current tsd-kind-interface"><a href="GestureConfig.html" class="tsd-kind-icon">Gesture<wbr/>Config</a><ul><li class="tsd-kind-property tsd-parent-kind-interface"><a href="GestureConfig.html#enabled" class="tsd-kind-icon">enabled</a></li></ul></li></ul></nav></div></div></div><footer class=""><div class="container"><h2>Legend</h2><div class="tsd-legend-group"><ul class="tsd-legend"><li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li><li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li><li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li></ul><ul class="tsd-legend"><li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li></ul></div><h2>Settings</h2><p>Theme <select id="theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></p></div></footer><div class="overlay"></div><script src="../assets/main.js"></script></body></html>

View File

@ -7,5 +7,6 @@ remove background or replace it with user-provided background</p>
</div><div><ul>
<li>enabled: true/false</li>
<li>modelPath: object detection model, can be absolute path or relative to modelBasePath</li>
<li>blur: blur segmentation output for more realistic image</li>
</ul>
</div></div></section><section class="tsd-panel tsd-hierarchy"><h3>Hierarchy</h3><ul class="tsd-hierarchy"><li><span class="target">SegmentationConfig</span></li></ul></section><section class="tsd-panel-group tsd-index-group"><h2>Index</h2><section class="tsd-panel tsd-index-panel"><div class="tsd-index-content"><section class="tsd-index-section "><h3>Properties</h3><ul class="tsd-index-list"><li class="tsd-kind-property tsd-parent-kind-interface"><a href="SegmentationConfig.html#enabled" class="tsd-kind-icon">enabled</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="SegmentationConfig.html#modelPath" class="tsd-kind-icon">model<wbr/>Path</a></li></ul></section></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Properties</h2><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="enabled" class="tsd-anchor"></a><h3>enabled</h3><div class="tsd-signature tsd-kind-icon">enabled<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L123">config.ts:123</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="modelPath" class="tsd-anchor"></a><h3>model<wbr/>Path</h3><div class="tsd-signature tsd-kind-icon">model<wbr/>Path<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L124">config.ts:124</a></li></ul></aside></section></section></div><div class="col-4 col-menu menu-sticky-wrap menu-highlight"><nav class="tsd-navigation primary"><ul><li class=""><a href="../index.html">Exports</a></li></ul></nav><nav class="tsd-navigation secondary menu-sticky"><ul><li class="current tsd-kind-interface"><a href="SegmentationConfig.html" class="tsd-kind-icon">Segmentation<wbr/>Config</a><ul><li class="tsd-kind-property tsd-parent-kind-interface"><a href="SegmentationConfig.html#enabled" class="tsd-kind-icon">enabled</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="SegmentationConfig.html#modelPath" class="tsd-kind-icon">model<wbr/>Path</a></li></ul></li></ul></nav></div></div></div><footer class=""><div class="container"><h2>Legend</h2><div class="tsd-legend-group"><ul class="tsd-legend"><li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li><li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li><li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li></ul><ul class="tsd-legend"><li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li></ul></div><h2>Settings</h2><p>Theme <select id="theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></p></div></footer><div class="overlay"></div><script src="../assets/main.js"></script></body></html>
</div></div></section><section class="tsd-panel tsd-hierarchy"><h3>Hierarchy</h3><ul class="tsd-hierarchy"><li><span class="target">SegmentationConfig</span></li></ul></section><section class="tsd-panel-group tsd-index-group"><h2>Index</h2><section class="tsd-panel tsd-index-panel"><div class="tsd-index-content"><section class="tsd-index-section "><h3>Properties</h3><ul class="tsd-index-list"><li class="tsd-kind-property tsd-parent-kind-interface"><a href="SegmentationConfig.html#blur" class="tsd-kind-icon">blur</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="SegmentationConfig.html#enabled" class="tsd-kind-icon">enabled</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="SegmentationConfig.html#modelPath" class="tsd-kind-icon">model<wbr/>Path</a></li></ul></section></div></section></section><section class="tsd-panel-group tsd-member-group "><h2>Properties</h2><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="blur" class="tsd-anchor"></a><h3>blur</h3><div class="tsd-signature tsd-kind-icon">blur<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L126">config.ts:126</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="enabled" class="tsd-anchor"></a><h3>enabled</h3><div class="tsd-signature tsd-kind-icon">enabled<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L124">config.ts:124</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface"><a name="modelPath" class="tsd-anchor"></a><h3>model<wbr/>Path</h3><div class="tsd-signature tsd-kind-icon">model<wbr/>Path<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/config.ts#L125">config.ts:125</a></li></ul></aside></section></section></div><div class="col-4 col-menu menu-sticky-wrap menu-highlight"><nav class="tsd-navigation primary"><ul><li class=""><a href="../index.html">Exports</a></li></ul></nav><nav class="tsd-navigation secondary menu-sticky"><ul><li class="current tsd-kind-interface"><a href="SegmentationConfig.html" class="tsd-kind-icon">Segmentation<wbr/>Config</a><ul><li class="tsd-kind-property tsd-parent-kind-interface"><a href="SegmentationConfig.html#blur" class="tsd-kind-icon">blur</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="SegmentationConfig.html#enabled" class="tsd-kind-icon">enabled</a></li><li class="tsd-kind-property tsd-parent-kind-interface"><a href="SegmentationConfig.html#modelPath" class="tsd-kind-icon">model<wbr/>Path</a></li></ul></li></ul></nav></div></div></div><footer class=""><div class="container"><h2>Legend</h2><div class="tsd-legend-group"><ul class="tsd-legend"><li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li><li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li><li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li></ul><ul class="tsd-legend"><li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li></ul></div><h2>Settings</h2><p>Theme <select id="theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></p></div></footer><div class="overlay"></div><script src="../assets/main.js"></script></body></html>

View File

@ -106,10 +106,12 @@ export interface ObjectConfig {
*
* - enabled: true/false
* - modelPath: object detection model, can be absolute path or relative to modelBasePath
* - blur: blur segmentation output for more realistic image
*/
export interface SegmentationConfig {
enabled: boolean;
modelPath: string;
blur: number;
}
/** Run input through image filters before inference
* - image filters run with near-zero latency as they are executed on the GPU

View File

@ -1 +1 @@
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}

View File

@ -1 +1 @@
{"version":3,"file":"handtrack.d.ts","sourceRoot":"","sources":["../../../src/handtrack/handtrack.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAyCxC,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAoB5E;AA4GD,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAiBlF"}
{"version":3,"file":"handtrack.d.ts","sourceRoot":"","sources":["../../../src/handtrack/handtrack.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAiDxC,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAsB5E;AA+GD,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAsBlF"}

27
types/src/human.d.ts vendored
View File

@ -20,7 +20,7 @@ export declare type Input = Tensor | ImageData | ImageBitmap | HTMLImageElement
*
* - `create`: triggered when Human object is instantiated
* - `load`: triggered when models are loaded (explicitly or on-demand)
* - `image`: triggered when input image is this.processed
* - `image`: triggered when input image is processed
* - `result`: triggered when detection is complete
* - `warmup`: triggered when warmup is complete
*/
@ -80,7 +80,7 @@ export declare class Human {
* - face: draw detected faces
* - body: draw detected people and body parts
* - hand: draw detected hands and hand parts
* - canvas: draw this.processed canvas which is a this.processed copy of the input
* - canvas: draw processed canvas which is a processed copy of the input
* - all: meta-function that performs: canvas, face, body, hand
*/
draw: {
@ -119,7 +119,7 @@ export declare class Human {
* Possible events:
* - `create`: triggered when Human object is instantiated
* - `load`: triggered when models are loaded (explicitly or on-demand)
* - `image`: triggered when input image is this.processed
* - `image`: triggered when input image is processed
* - `result`: triggered when detection is complete
* - `warmup`: triggered when warmup is complete
* - `error`: triggered on some errors
@ -168,15 +168,26 @@ export declare class Human {
* @returns similarity: number
*/
similarity(embedding1: Array<number>, embedding2: Array<number>): number;
/** Segmentation method takes any input and returns this.processed canvas with body segmentation
/** Segmentation method takes any input and returns processed canvas with body segmentation
* - Optional parameter background is used to fill the background with specific input
* - Segmentation is not triggered as part of detect this.process
* - Segmentation is not triggered as part of detect process
*
* Returns:
* - `data` as raw data array with per-pixel segmentation values
* - `canvas` as canvas which is input image filtered with segementation data
* and optionally merged with background image
* canvas alpha values are set to segmentation values for easy merging
* - `alpha` as grayscale canvas that represents segmentation alpha values
*
* @param input: {@link Input}
* @param background?: {@link Input}
* @returns Canvas
* @returns { data, canvas, alpha }
*/
segmentation(input: Input, background?: Input): Promise<OffscreenCanvas | HTMLCanvasElement | null>;
segmentation(input: Input, background?: Input): Promise<{
data: Uint8ClampedArray | null;
canvas: HTMLCanvasElement | OffscreenCanvas | null;
alpha: HTMLCanvasElement | OffscreenCanvas | null;
}>;
/** Enhance method performs additional enhacements to face image previously detected for futher processing
*
* @param input: Tensor as provided in human.result.face[n].tensor
@ -235,7 +246,7 @@ export declare class Human {
}>;
/** Main detection method
* - Analyze configuration: {@link Config}
* - Pre-this.process input: {@link Input}
* - Pre-process input: {@link Input}
* - Run inference for all configured models
* - Process and return result: {@link Result}
*

View File

@ -1 +1 @@
{"version":3,"file":"human.d.ts","sourceRoot":"","sources":["../../src/human.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"human.d.ts","sourceRoot":"","sources":["../../src/human.ts"],"names":[],"mappings":"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"}

View File

@ -8,7 +8,15 @@ export declare function load(config: Config): Promise<GraphModel>;
export declare function predict(input: {
tensor: Tensor | null;
canvas: OffscreenCanvas | HTMLCanvasElement | null;
}): Promise<Uint8ClampedArray | null>;
export declare function process(input: Input, background: Input | undefined, config: Config): Promise<HTMLCanvasElement | OffscreenCanvas | null>;
}, config: Config): Promise<{
data: Uint8ClampedArray | null;
canvas: HTMLCanvasElement | OffscreenCanvas | null;
alpha: HTMLCanvasElement | OffscreenCanvas | null;
}>;
export declare function process(input: Input, background: Input | undefined, config: Config): Promise<{
data: Uint8ClampedArray | null;
canvas: HTMLCanvasElement | OffscreenCanvas | null;
alpha: HTMLCanvasElement | OffscreenCanvas | null;
}>;
export {};
//# sourceMappingURL=segmentation.d.ts.map

View File

@ -1 +1 @@
{"version":3,"file":"segmentation.d.ts","sourceRoot":"","sources":["../../../src/segmentation/segmentation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGxC,aAAK,KAAK,GAAG,MAAM,GAAG,OAAO,KAAK,GAAG,SAAS,GAAG,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,eAAe,CAAC;AAK5J,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAO9D;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAqErJ;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAC,CAoC9I"}
{"version":3,"file":"segmentation.d.ts","sourceRoot":"","sources":["../../../src/segmentation/segmentation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGxC,aAAK,KAAK,GAAG,MAAM,GAAG,OAAO,KAAK,GAAG,SAAS,GAAG,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,eAAe,CAAC;AAK5J,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAO9D;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CAAA;CAAE,EAAE,MAAM,EAAE,MAAM,GAChI,OAAO,CAAC;IAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAA;CAAE,CAAC,CAgEnJ;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GACvF,OAAO,CAAC;IAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAA;CAAE,CAAC,CAuBnJ"}

2
wiki

@ -1 +1 @@
Subproject commit b24eafa265bda331788e0d36cf5c854a494e33d6
Subproject commit d293f4a20b640e6bc8485dc0f8a2c2147ce33073