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 ## 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 - support for dynamic backend switching
- initial automated browser tests - initial automated browser tests

View File

@ -35,7 +35,7 @@
.video { display: none; } .video { display: none; }
.canvas { margin: 0 auto; } .canvas { margin: 0 auto; }
.bench { position: absolute; right: 0; bottom: 0; } .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 { 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, .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; } .loader::before { border-top-color: #bad375; animation: 3s spin linear infinite; }
@ -107,9 +107,13 @@
<video id="video" playsinline class="video"></video> <video id="video" playsinline class="video"></video>
</div> </div>
<div id="compare-container" class="compare-image"> <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 id="similarity"></div>
</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="samples-container" class="samples-container"></div>
<div id="hint" class="hint"></div> <div id="hint" class="hint"></div>
<div id="log" class="log"></div> <div id="log" class="log"></div>

View File

@ -51,8 +51,8 @@ let userConfig = {
}, },
object: { enabled: false }, object: { enabled: false },
gesture: { enabled: true }, gesture: { enabled: true },
// hand: { enabled: true, landmarks: false, maxDetected: 3, minConfidence: 0.1 }, hand: { enabled: false },
hand: { enabled: true, maxDetected: 3, minConfidence: 0.3, detector: { modelPath: 'handtrack.json' } }, // hand: { enabled: true, maxDetected: 1, minConfidence: 0.5, detector: { modelPath: 'handtrack.json' } },
body: { enabled: false }, body: { enabled: false },
// body: { enabled: true, modelPath: 'movenet-multipose.json' }, // body: { enabled: true, modelPath: 'movenet-multipose.json' },
// body: { enabled: true, modelPath: 'posenet.json' }, // body: { enabled: true, modelPath: 'posenet.json' },
@ -241,8 +241,20 @@ async function drawResults(input) {
// draw fps chart // draw fps chart
await menu.process.updateChart('FPS', ui.detectFPS); 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 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 } else if (!result.canvas || ui.buffered) { // refresh with input if using buffered output or if missing canvas
const image = await human.image(input); const image = await human.image(input);
result.canvas = image.canvas; 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 if (document.getElementById('canvas').style.display === 'block') { // replace canvas used for video
const canvas = document.getElementById('canvas'); const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
const overlaid = await human.segmentation(canvas, ui.background, userConfig); const seg = await human.segmentation(canvas, ui.background, userConfig);
if (overlaid) ctx.drawImage(overlaid, 0, 0); if (seg.canvas) ctx.drawImage(seg.canvas, 0, 0);
} else { } else {
const canvases = document.getElementById('samples-container').children; // replace loaded images const canvases = document.getElementById('samples-container').children; // replace loaded images
for (const canvas of canvases) { for (const canvas of canvases) {
const ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
const overlaid = await human.segmentation(canvas, ui.background, userConfig); const seg = await human.segmentation(canvas, ui.background, userConfig);
if (overlaid) ctx.drawImage(overlaid, 0, 0); if (seg.canvas) ctx.drawImage(seg.canvas, 0, 0);
} }
} }
}; };

View File

@ -14,6 +14,8 @@
<link rel="apple-touch-icon" href="../../assets/icon.png"> <link rel="apple-touch-icon" href="../../assets/icon.png">
<script src="./index.js" type="module"></script> <script src="./index.js" type="module"></script>
<style> <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 { margin: 0; background: black; color: white; overflow-x: hidden; width: 100vw; height: 100vh; text-align: center; }
body::-webkit-scrollbar { display: none; } body::-webkit-scrollbar { display: none; }
</style> </style>
@ -21,5 +23,6 @@
<body> <body>
<canvas id="canvas" style="margin: 0 auto"></canvas> <canvas id="canvas" style="margin: 0 auto"></canvas>
<video id="video" playsinline style="display: none"></video> <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> </body>
</html> </html>

View File

@ -10,9 +10,10 @@
import Human from '../../dist/human.esm.js'; // equivalent of @vladmandic/human 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 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', modelBasePath: '../../models',
}; };
const human = new Human(config); const human = new Human(config);
const webrtc = { const webrtc = {
@ -30,6 +31,9 @@ const video = document.getElementById('video') || document.createElement('video'
/** @type {HTMLCanvasElement} */ /** @type {HTMLCanvasElement} */
// @ts-ignore // @ts-ignore
const canvas = document.getElementById('canvas') || document.createElement('canvas'); // used as output 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() { async function webCam() {
const constraints = { audio: false, video: { facingMode: 'user', resizeMode: 'none', width: { ideal: document.body.clientWidth } } }; // set preffered camera options 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.width = video.videoWidth; // resize output canvas to match input
canvas.height = video.videoHeight; canvas.height = video.videoHeight;
log('video stream:', video.srcObject, 'track state:', video.srcObject.getVideoTracks()[0].readyState, 'stream state:', video.readyState); 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 // eslint-disable-next-line no-unused-vars
let result; let result;
async function detectionLoop() { 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 // eslint-disable-next-line @typescript-eslint/no-unused-vars
requestAnimationFrame(detectionLoop); // run in loop requestAnimationFrame(detectionLoop); // run in loop
} }
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
async function drawLoop() { async function drawLoop() {
const interpolated = await human.next(result); // interpolates results based on last known results const t0 = performance.now();
await human.draw.canvas(video, canvas); // draw input video to output canvas if (!video.paused) { // skip redraw if video is paused
await human.draw.all(canvas, interpolated); // draw results as overlay on output canvas 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 // eslint-disable-next-line @typescript-eslint/no-unused-vars
requestAnimationFrame(drawLoop); // run in loop requestAnimationFrame(drawLoop); // run in loop
} }
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
async function singleLoop() { async function singleLoop() {
const t0 = performance.now();
result = await human.detect(video); // updates result every time detection completes 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.canvas(video, canvas); // draw input video to output canvas
await human.draw.all(canvas, result); // draw results as overlay on 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 // eslint-disable-next-line @typescript-eslint/no-unused-vars
requestAnimationFrame(singleLoop); // run in loop requestAnimationFrame(singleLoop); // run in loop
} }

View File

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

View File

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

303
dist/human.node.js vendored
View File

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

View File

@ -118,10 +118,12 @@ export interface ObjectConfig {
* *
* - enabled: true/false * - enabled: true/false
* - modelPath: object detection model, can be absolute path or relative to modelBasePath * - 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 { export interface SegmentationConfig {
enabled: boolean, enabled: boolean,
modelPath: string, modelPath: string,
blur: number,
} }
/** Run input through image filters before inference /** Run input through image filters before inference
@ -399,6 +401,7 @@ const config: Config = {
// remove background or replace it with user-provided background // remove background or replace it with user-provided background
modelPath: 'selfie.json', // experimental: object detection model, can be absolute path or relative to modelBasePath modelPath: 'selfie.json', // experimental: object detection model, can be absolute path or relative to modelBasePath
// can be 'selfie' or 'meet' // can be 'selfie' or 'meet'
blur: 8, // blur segmentation output by n pixels for more realistic image
}, },
}; };
export { config as defaults }; 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 models: [GraphModel | null, GraphModel | null] = [null, null];
const modelOutputNodes = ['StatefulPartitionedCall/Postprocessor/Slice', 'StatefulPartitionedCall/Postprocessor/ExpandDims_1']; const modelOutputNodes = ['StatefulPartitionedCall/Postprocessor/Slice', 'StatefulPartitionedCall/Postprocessor/ExpandDims_1'];
const inputSize = [0, 0]; const inputSize = [[0, 0], [0, 0]];
const classes = [ const classes = [
'hand', 'hand',
@ -36,7 +36,15 @@ type HandDetectResult = {
yxBox: [number, number, number, number], 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 = { const fingerMap = {
thumb: [1, 2, 3, 4], thumb: [1, 2, 3, 4],
@ -55,14 +63,16 @@ export async function load(config: Config): Promise<[GraphModel, GraphModel]> {
if (!models[0]) { if (!models[0]) {
models[0] = await tf.loadGraphModel(join(config.modelBasePath, config.hand.detector?.modelPath || '')) as unknown as GraphModel; models[0] = await tf.loadGraphModel(join(config.modelBasePath, config.hand.detector?.modelPath || '')) as unknown as GraphModel;
const inputs = Object.values(models[0].modelSignature['inputs']); 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); 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('load model:', models[0]['modelUrl']);
} else if (config.debug) log('cached model:', models[0]['modelUrl']); } else if (config.debug) log('cached model:', models[0]['modelUrl']);
if (!models[1]) { if (!models[1]) {
models[1] = await tf.loadGraphModel(join(config.modelBasePath, config.hand.skeleton?.modelPath || '')) as unknown as GraphModel; models[1] = await tf.loadGraphModel(join(config.modelBasePath, config.hand.skeleton?.modelPath || '')) as unknown as GraphModel;
const inputs = Object.values(models[1].modelSignature['inputs']); 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); 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('load model:', models[1]['modelUrl']);
} else if (config.debug) log('cached 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[] = []; const hands: HandDetectResult[] = [];
if (!input || !models[0]) return hands; if (!input || !models[0]) return hands;
const t: Record<string, Tensor> = {}; 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.cast = tf.cast(t.resize, 'int32');
[t.rawScores, t.rawBoxes] = await models[0].executeAsync(t.cast, modelOutputNodes) as Tensor[]; [t.rawScores, t.rawBoxes] = await models[0].executeAsync(t.cast, modelOutputNodes) as Tensor[];
t.boxes = tf.squeeze(t.rawBoxes, [0, 2]); 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)); classScores.forEach((tensor) => tf.dispose(tensor));
Object.keys(t).forEach((tensor) => tf.dispose(t[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; return hands;
} }
/* const boxScaleFact = 1.5; // hand finger model prefers slighly larger box
const scaleFact = 1.2;
function updateBoxes(h, keypoints) { function updateBoxes(h, keypoints) {
const fingerX = keypoints.map((pt) => pt[0]); const finger = [keypoints.map((pt) => pt[0]), keypoints.map((pt) => pt[1])]; // all fingers coords
const fingerY = keypoints.map((pt) => pt[1]); 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 minX = Math.min(...fingerX); const center = [(minmax[0] + minmax[1]) / 2, (minmax[2] + minmax[3]) / 2]; // find center x and y coord of all fingers
const maxX = Math.max(...fingerX); 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
const minY = Math.min(...fingerY);
const maxY = Math.max(...fingerY);
h.box = [ h.box = [
Math.trunc(minX / scaleFact), Math.trunc(center[0] - diff),
Math.trunc(minY / scaleFact), Math.trunc(center[1] - diff),
Math.trunc(scaleFact * maxX - minX), Math.trunc(2 * diff),
Math.trunc(scaleFact * maxY - minY), Math.trunc(2 * diff),
] as [number, number, number, number]; ] as [number, number, number, number];
h.bowRaw = [ h.boxRaw = [ // work backwards
h.box / outputSize[0], h.box[0] / outputSize[0],
h.box / outputSize[1], h.box[1] / outputSize[1],
h.box / outputSize[0], h.box[2] / outputSize[0],
h.box / outputSize[1], h.box[3] / outputSize[1],
] as [number, number, number, number]; ] as [number, number, number, number];
h.yxBox = [ h.yxBox = [ // work backwards
h.boxRaw[1], h.boxRaw[1],
h.boxRaw[0], h.boxRaw[0],
h.boxRaw[3] + h.boxRaw[1], h.boxRaw[3] + h.boxRaw[1],
h.boxRaw[2] + h.boxRaw[0], h.boxRaw[2] + h.boxRaw[0],
] as [number, number, number, number]; ] as [number, number, number, number];
return h;
} }
*/
async function detectFingers(input: Tensor, h: HandDetectResult, config: Config): Promise<HandResult> { async function detectFingers(input: Tensor, h: HandDetectResult, config: Config): Promise<HandResult> {
const hand: HandResult = { const hand: HandResult = {
@ -148,60 +157,64 @@ async function detectFingers(input: Tensor, h: HandDetectResult, config: Config)
landmarks: {} as HandResult['landmarks'], landmarks: {} as HandResult['landmarks'],
annotations: {} as HandResult['annotations'], annotations: {} as HandResult['annotations'],
}; };
if (!input || !models[1] || !config.hand.landmarks) return hand; if (!input || !models[1]) return hand; // something is wrong
const t: Record<string, Tensor> = {}; if (config.hand.landmarks) {
t.crop = tf.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1], inputSize[1]], 'bilinear'); const t: Record<string, Tensor> = {};
t.cast = tf.cast(t.crop, 'float32'); if (!h.yxBox) return hand;
t.div = tf.div(t.cast, 255); t.crop = tf.image.cropAndResize(input, [h.yxBox], [0], [inputSize[1][0], inputSize[1][1]], 'bilinear');
[t.score, t.keypoints] = models[1].execute(t.div) as Tensor[]; t.cast = tf.cast(t.crop, 'float32');
const score = Math.round(100 * (await t.score.data())[0] / 100); t.div = tf.div(t.cast, 255);
if (score > (config.hand.minConfidence || 0)) { [t.score, t.keypoints] = models[1].execute(t.div) as Tensor[];
hand.fingerScore = score; const score = Math.round(100 * (await t.score.data())[0] / 100);
t.reshaped = tf.reshape(t.keypoints, [-1, 3]); if (score > (config.hand.minConfidence || 0)) {
const rawCoords = await t.reshaped.array() as number[]; hand.fingerScore = score;
hand.keypoints = (rawCoords as number[]).map((coord) => [ t.reshaped = tf.reshape(t.keypoints, [-1, 3]);
(h.box[2] * coord[0] / inputSize[1]) + h.box[0], const rawCoords = await t.reshaped.array() as number[];
(h.box[3] * coord[1] / inputSize[1]) + h.box[1], hand.keypoints = (rawCoords as number[]).map((coord) => [
(h.box[2] + h.box[3]) / 2 / inputSize[1] * coord[2], (h.box[2] * coord[0] / inputSize[1][0]) + h.box[0],
]); (h.box[3] * coord[1] / inputSize[1][1]) + h.box[1],
// h = updateBoxes(h, hand.keypoints); // replace detected box with box calculated around keypoints (h.box[2] + h.box[3]) / 2 / inputSize[1][0] * coord[2],
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 updateBoxes(h, hand.keypoints); // replace detected box with box calculated around keypoints
hand.annotations[key] = fingerMap[key].map((index) => (hand.landmarks && hand.keypoints[index] ? hand.keypoints[index] : null)); 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; return hand;
} }
let last = 0;
export async function predict(input: Tensor, config: Config): Promise<HandResult[]> { export async function predict(input: Tensor, config: Config): Promise<HandResult[]> {
outputSize = [input.shape[2] || 0, input.shape[1] || 0]; outputSize = [input.shape[2] || 0, input.shape[1] || 0];
if ((skipped < (config.object.skipFrames || 0)) && config.skipFrame) { let hands: Array<HandResult> = [];
// use cached boxes 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++; skipped++;
const hands: HandResult[] = await Promise.all(boxes.map((hand) => detectFingers(input, hand, config))); hands = await Promise.all(cache.fingerBoxes.map((hand) => detectFingers(input, hand, config))); // run from finger box cache
const withFingers = hands.filter((hand) => hand.fingerScore > 0).length; // console.log('SKIP', skipped, hands.length, cache.handBoxes.length, cache.fingerBoxes.length, cache.tmpBoxes.length);
if (withFingers === last) return hands; } 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 cache.fingerBoxes = [...cache.tmpBoxes]; // repopulate cache with validated hands
skipped = 0; return hands as HandResult[];
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;
} }
/* /*
<https://victordibia.com/handtrack.js/#/> - Live Site: <https://victordibia.com/handtrack.js/#/>
<https://github.com/victordibia/handtrack.js/> - TFJS Port: <https://github.com/victordibia/handtrack.js/>
<https://github.com/victordibia/handtracking> - Original: <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> - Writeup: <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
*/ */

View File

@ -47,7 +47,7 @@ export type Input = Tensor | ImageData | ImageBitmap | HTMLImageElement | HTMLMe
* *
* - `create`: triggered when Human object is instantiated * - `create`: triggered when Human object is instantiated
* - `load`: triggered when models are loaded (explicitly or on-demand) * - `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 * - `result`: triggered when detection is complete
* - `warmup`: triggered when warmup is complete * - `warmup`: triggered when warmup is complete
*/ */
@ -111,7 +111,7 @@ export class Human {
* - face: draw detected faces * - face: draw detected faces
* - body: draw detected people and body parts * - body: draw detected people and body parts
* - hand: draw detected hands and hand 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 * - all: meta-function that performs: canvas, face, body, hand
*/ */
draw: { canvas, face, body, hand, gesture, object, person, all, options: DrawOptions }; draw: { canvas, face, body, hand, gesture, object, person, all, options: DrawOptions };
@ -142,7 +142,7 @@ export class Human {
* Possible events: * Possible events:
* - `create`: triggered when Human object is instantiated * - `create`: triggered when Human object is instantiated
* - `load`: triggered when models are loaded (explicitly or on-demand) * - `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 * - `result`: triggered when detection is complete
* - `warmup`: triggered when warmup is complete * - `warmup`: triggered when warmup is complete
* - `error`: triggered on some errors * - `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), 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: [] }; 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 // @ts-ignore eslint-typescript cannot correctly infer type in anonymous function
this.process = { tensor: null, canvas: null }; this.process = { tensor: null, canvas: null };
// export raw access to underlying models // export raw access to underlying models
@ -284,16 +284,21 @@ export class Human {
return faceres.similarity(embedding1, embedding2); 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 * - 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 input: {@link Input}
* @param background?: {@link Input} * @param background?: {@link Input}
* @returns Canvas * @returns { data, canvas, alpha }
*/ */
async segmentation(input: Input, background?: Input) { async segmentation(input: Input, background?: Input): Promise<{ data: Uint8ClampedArray | null, canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
return input ? segmentation.process(input, background, this.config) : null; return segmentation.process(input, background, this.config);
} }
/** Enhance method performs additional enhacements to face image previously detected for futher processing /** Enhance method performs additional enhacements to face image previously detected for futher processing
@ -394,7 +399,7 @@ export class Human {
/** Main detection method /** Main detection method
* - Analyze configuration: {@link Config} * - Analyze configuration: {@link Config}
* - Pre-this.process input: {@link Input} * - Pre-process input: {@link Input}
* - Run inference for all configured models * - Run inference for all configured models
* - Process and return result: {@link Result} * - Process and return result: {@link Result}
* *
@ -431,26 +436,24 @@ export class Human {
timeStamp = now(); timeStamp = now();
this.state = 'image'; 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.process = img;
this.performance.image = Math.trunc(now() - timeStamp); this.performance.image = Math.trunc(now() - timeStamp);
this.analyze('Get Image:'); this.analyze('Get Image:');
// run segmentation prethis.processing // segmentation is only run explicitly via human.segmentation() which calls segmentation.process()
if (this.config.segmentation.enabled && this.process && img.tensor && img.canvas) { /*
if (this.config.segmentation.enabled && process && img.tensor && img.canvas) {
this.analyze('Start Segmentation:'); this.analyze('Start Segmentation:');
this.state = 'detect:segmentation'; this.state = 'detect:segmentation';
timeStamp = now(); 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); elapsedTime = Math.trunc(now() - timeStamp);
if (elapsedTime > 0) this.performance.segmentation = elapsedTime; 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:'); this.analyze('End Segmentation:');
} }
*/
if (!img.tensor) { if (!img.tensor) {
if (this.config.debug) log('could not convert input to 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; return model;
} }
export async function predict(input: { tensor: Tensor | null, canvas: OffscreenCanvas | HTMLCanvasElement | null }): Promise<Uint8ClampedArray | null> { export async function predict(input: { tensor: Tensor | null, canvas: OffscreenCanvas | HTMLCanvasElement | null }, config: Config)
const width = input.tensor?.shape[1] || 0; : Promise<{ data: Uint8ClampedArray | null, canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
const height = input.tensor?.shape[2] || 0; const width = input.tensor?.shape[2] || 0;
if (!input.tensor) return null; const height = input.tensor?.shape[1] || 0;
if (!model || !model.inputs[0].shape) return null; 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 resizeInput = tf.image.resizeBilinear(input.tensor, [model.inputs[0].shape[1], model.inputs[0].shape[2]], false);
const norm = tf.div(resizeInput, 255); const norm = tf.div(resizeInput, 255);
const res = model.predict(norm) as Tensor; 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); const squeeze = tf.squeeze(res, 0);
tf.dispose(res); tf.dispose(res);
let resizeOutput; let dataT;
if (squeeze.shape[2] === 2) { if (squeeze.shape[2] === 2) {
// model meet has two channels for fg and bg // model meet has two channels for fg and bg
const softmax = squeeze.softmax(); 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]); const crop = tf.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
// otherwise run softmax after unstack and use standard resize // otherwise run softmax after unstack and use standard resize
// resizeOutput = tf.image.resizeBilinear(expand, [input.tensor?.shape[1], input.tensor?.shape[2]]); // 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(crop);
tf.dispose(expand); tf.dispose(expand);
tf.dispose(pad); tf.dispose(pad);
} else { // model selfie has a single channel that we can use directly } 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); tf.dispose(squeeze);
const data = await dataT.dataSync();
if (env.node) { if (env.node) {
const data = await resizeOutput.data(); tf.dispose(dataT);
tf.dispose(resizeOutput); return { data, canvas: null, alpha: null }; // running in nodejs so return alpha array as-is
return data; // we're 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 alphaCanvas = image.canvas(width, height);
const ctxAlpha = alphaCanvas.getContext('2d') as CanvasRenderingContext2D; await tf.browser.toPixels(dataT, alphaCanvas);
ctxAlpha.filter = 'blur(8px'; tf.dispose(dataT);
await ctxAlpha.drawImage(overlay, 0, 0); const alphaCtx = alphaCanvas.getContext('2d') as CanvasRenderingContext2D;
const alpha = ctxAlpha.getImageData(0, 0, width, height).data; 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 // original canvas where only alpha shows
const original = image.canvas(width, height); const compositeCanvas = image.canvas(width, height);
const ctx = original.getContext('2d') as CanvasRenderingContext2D; const compositeCtx = compositeCanvas.getContext('2d') as CanvasRenderingContext2D;
if (input.canvas) await ctx.drawImage(input.canvas, 0, 0); if (input.canvas) compositeCtx.drawImage(input.canvas, 0, 0);
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation // best options are: darken, color-burn, multiply compositeCtx.globalCompositeOperation = 'darken'; // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation // best options are: darken, color-burn, multiply
ctx.globalCompositeOperation = 'darken'; 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
ctx.filter = 'blur(8px)'; // use css filter for bluring, can be done with gaussian blur manually instead compositeCtx.drawImage(alphaCanvas, 0, 0);
await ctx.drawImage(overlay, 0, 0); compositeCtx.globalCompositeOperation = 'source-over'; // reset composite operation
ctx.globalCompositeOperation = 'source-over'; // reset compositeCtx.filter = 'none'; // reset css filter
ctx.filter = 'none'; // reset 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 { data, canvas: compositeCanvas, alpha: alphaCanvas };
return alpha;
} }
export async function process(input: Input, background: Input | undefined, config: Config): Promise<HTMLCanvasElement | OffscreenCanvas | null> { export async function process(input: Input, background: Input | undefined, config: Config)
if (busy) return null; : Promise<{ data: Uint8ClampedArray | null, canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
if (busy) return { data: null, canvas: null, alpha: null };
busy = true; busy = true;
if (!model) await load(config); if (!model) await load(config);
const img = image.process(input, config); const inputImage = image.process(input, config);
const tmp = image.process(background, config); const segmentation = await predict(inputImage, config);
if (!img.canvas || !tmp.canvas) { tf.dispose(inputImage.tensor);
if (config.debug) log('segmentation cannot process input or background'); let mergedCanvas: HTMLCanvasElement | OffscreenCanvas | null = null;
return 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; 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-22 15:07:47 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-22 15:07:47 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-22 15:07:47 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-22 15:07:47 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-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-21 16:46:56 INFO:  Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]} 2021-09-22 15:07:47 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-22 15:07:47 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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-21 16:47:14 STATE: Typings: {"input":"src/human.ts","output":"types","files":96} 2021-09-22 15:08:08 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-22 15:08:14 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-22 15:08:43 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-22 15:08:43 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: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>face: draw detected faces</li>
<li>body: draw detected people and body parts</li> <li>body: draw detected people and body parts</li>
<li>hand: draw detected hands and hand 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> <li>all: meta-function that performs: canvas, face, body, hand</li>
</ul> </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"> </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> <ul>
<li><code>create</code>: triggered when Human object is instantiated</li> <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>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>result</code>: triggered when detection is complete</li>
<li><code>warmup</code>: triggered when warmup is complete</li> <li><code>warmup</code>: triggered when warmup is complete</li>
<li><code>error</code>: triggered on some errors</li> <li><code>error</code>: triggered on some errors</li>
@ -62,21 +62,21 @@
</ul> </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"> </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> <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> <p>Main detection method</p>
<ul> <ul>
<li>Analyze configuration: <a href="../interfaces/Config.html">Config</a></li> <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>Run inference for all configured models</li>
<li>Process and return result: <a href="../interfaces/Result.html">Result</a></li> <li>Process and return result: <a href="../interfaces/Result.html">Result</a></li>
</ul> </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></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> <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></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"> </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> <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> <p>Explicit backend initialization</p>
<ul> <ul>
<li>Normally done implicitly during initial load phase</li> <li>Normally done implicitly during initial load phase</li>
@ -84,29 +84,36 @@
<li>Use when changing backend during runtime</li> <li>Use when changing backend during runtime</li>
</ul> </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></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> <p>Load method preloads all configured models on-demand</p>
<ul> <ul>
<li>Not explicitly required as any required model is load implicitly on it&#39;s first run</li> <li>Not explicitly required as any required model is load implicitly on it&#39;s first run</li>
</ul> </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></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> <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></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 <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> 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></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"> </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> <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"> </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 this.processed canvas with body segmentation</p> <p>Segmentation method takes any input and returns processed canvas with body segmentation</p>
<ul> <ul>
<li>Optional parameter background is used to fill the background with specific input</li> <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> </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><div><p> Returns:</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"> <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> <p>Simmilarity method calculates simmilarity between two provided face descriptors (face embeddings)</p>
<ul> <ul>
<li>Calculation is based on normalized Minkowski distance between two descriptors</li> <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></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"> </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> <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> <p>Warmup method pre-initializes all configured models for faster inference</p>
<ul> <ul>
<li>can take significant time on startup</li> <li>can take significant time on startup</li>

View File

@ -5,7 +5,7 @@
</div><div><ul> </div><div><ul>
<li><code>create</code>: triggered when Human object is instantiated</li> <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>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>result</code>: triggered when detection is complete</li>
<li><code>warmup</code>: triggered when warmup is complete</li> <li><code>warmup</code>: triggered when warmup is complete</li>
</ul> </ul>
@ -15,6 +15,6 @@
<p>Defines all possible input types for <strong>Human</strong> detection</p> <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"> </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> <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> <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> </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"> <!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> <p>Configuration interface definition for <strong>Human</strong> library</p>
</div><div><p>Contains all configurable parameters</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> <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> <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> <p>Cache sensitivity</p>
<ul> <ul>
<li>values 0..1 where 0.01 means reset cache if input changed more than 1%</li> <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> <li>set to 0 to disable caching</li>
</ul> </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> <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> <p>Run input through image filters before inference</p>
<ul> <ul>
<li>image filters run with near-zero latency as they are executed on the GPU</li> <li>image filters run with near-zero latency as they are executed on the GPU</li>
</ul> </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> <p>Base model path (typically starting with file://, http:// or https://) for all models</p>
<ul> <ul>
<li>individual modelPath values are relative to this path</li> <li>individual modelPath values are relative to this path</li>
</ul> </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> <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> <p>What to use for <code>human.warmup()</code></p>
<ul> <ul>
<li>warmup pre-initializes all models for faster inference but can take significant time on startup</li> <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> <li>only used for <code>webgl</code> and <code>humangl</code> backends</li>
</ul> </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> <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> <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> </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> <ul>
<li>image filters run with near-zero latency as they are executed on the GPU</li> <li>image filters run with near-zero latency as they are executed on the GPU</li>
</ul> </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> <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> <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> <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> <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> <p>Resize input height</p>
<ul> <ul>
<li>if both width and height are set to 0, there is no resizing</li> <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 just one is set, second one is scaled automatically</li>
<li>if both are set, values are used as-is</li> <li>if both are set, values are used as-is</li>
</ul> </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> <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> <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> <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> <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> <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> <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> <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> <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> <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> <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> <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> <p>Resize input width</p>
<ul> <ul>
<li>if both width and height are set to 0, there is no resizing</li> <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"> <!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> <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> </div><div><ul>
<li>enabled: true/false</li> <li>enabled: true/false</li>
<li>modelPath: object detection model, can be absolute path or relative to modelBasePath</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> </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 * - enabled: true/false
* - modelPath: object detection model, can be absolute path or relative to modelBasePath * - modelPath: object detection model, can be absolute path or relative to modelBasePath
* - blur: blur segmentation output for more realistic image
*/ */
export interface SegmentationConfig { export interface SegmentationConfig {
enabled: boolean; enabled: boolean;
modelPath: string; modelPath: string;
blur: number;
} }
/** Run input through image filters before inference /** Run input through image filters before inference
* - image filters run with near-zero latency as they are executed on the GPU * - 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":"AAGA,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;EAUE;AACF,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtC,IAAI,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC5C,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACrC;AAED;;;;;EAKE;AACF,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;EAQE;AACF,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,QAAQ,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED;;;;;;EAME;AACF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;EAQE;AACF,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;EAEE;AACF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB;;;;MAIE;IACF,KAAK,EAAE,MAAM,CAAC;IACd;;;;MAIE;IACF,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,MAAM,EAAE,OAAO,CAAC;IAChB,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,yBAAyB;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,2BAA2B;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,+BAA+B;IAC/B,WAAW,EAAE,OAAO,CAAC;IACrB,mCAAmC;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,kCAAkC;AAClC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,MAAM;IACrB,uCAAuC;IACvC,OAAO,EAAE,EAAE,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;IAG7E,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IAEjB,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAC;IAEf,uEAAuE;IACvE,KAAK,EAAE,OAAO,CAAC;IAEf;;;MAGE;IACF,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAG1C;;MAEE;IACF,aAAa,EAAE,MAAM,CAAC;IAEtB;;;MAGE;IACF,gBAAgB,EAAE,MAAM,CAAC;IAEzB,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAC;IAEf,wBAAwB;IACxB,SAAS,EAAE,OAAO,CAAC;IAEnB;;MAEE;IACF,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAG9B,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAEhC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAE1B,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAE1B,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAE1B,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAE9B,YAAY,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC3C;AAED;;;GAGG;AACH,QAAA,MAAM,MAAM,EAAE,MA2Jb,CAAC;AACF,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,CAAC"} {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;EAUE;AACF,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtC,IAAI,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC5C,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACrC;AAED;;;;;EAKE;AACF,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;EAQE;AACF,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,QAAQ,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED;;;;;;EAME;AACF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;EASE;AACF,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;EAEE;AACF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB;;;;MAIE;IACF,KAAK,EAAE,MAAM,CAAC;IACd;;;;MAIE;IACF,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,MAAM,EAAE,OAAO,CAAC;IAChB,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,yBAAyB;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,2BAA2B;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,+BAA+B;IAC/B,WAAW,EAAE,OAAO,CAAC;IACrB,mCAAmC;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,kCAAkC;AAClC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,MAAM;IACrB,uCAAuC;IACvC,OAAO,EAAE,EAAE,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;IAG7E,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IAEjB,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAC;IAEf,uEAAuE;IACvE,KAAK,EAAE,OAAO,CAAC;IAEf;;;MAGE;IACF,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAG1C;;MAEE;IACF,aAAa,EAAE,MAAM,CAAC;IAEtB;;;MAGE;IACF,gBAAgB,EAAE,MAAM,CAAC;IAEzB,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAC;IAEf,wBAAwB;IACxB,SAAS,EAAE,OAAO,CAAC;IAEnB;;MAEE;IACF,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAG9B,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAEhC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAE1B,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAE1B,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAE1B,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAE9B,YAAY,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC3C;AAED;;;GAGG;AACH,QAAA,MAAM,MAAM,EAAE,MA4Jb,CAAC;AACF,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,CAAC"}

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 * - `create`: triggered when Human object is instantiated
* - `load`: triggered when models are loaded (explicitly or on-demand) * - `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 * - `result`: triggered when detection is complete
* - `warmup`: triggered when warmup is complete * - `warmup`: triggered when warmup is complete
*/ */
@ -80,7 +80,7 @@ export declare class Human {
* - face: draw detected faces * - face: draw detected faces
* - body: draw detected people and body parts * - body: draw detected people and body parts
* - hand: draw detected hands and hand 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 * - all: meta-function that performs: canvas, face, body, hand
*/ */
draw: { draw: {
@ -119,7 +119,7 @@ export declare class Human {
* Possible events: * Possible events:
* - `create`: triggered when Human object is instantiated * - `create`: triggered when Human object is instantiated
* - `load`: triggered when models are loaded (explicitly or on-demand) * - `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 * - `result`: triggered when detection is complete
* - `warmup`: triggered when warmup is complete * - `warmup`: triggered when warmup is complete
* - `error`: triggered on some errors * - `error`: triggered on some errors
@ -168,15 +168,26 @@ export declare class Human {
* @returns similarity: number * @returns similarity: number
*/ */
similarity(embedding1: Array<number>, embedding2: Array<number>): 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 * - 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 input: {@link Input}
* @param background?: {@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 /** Enhance method performs additional enhacements to face image previously detected for futher processing
* *
* @param input: Tensor as provided in human.result.face[n].tensor * @param input: Tensor as provided in human.result.face[n].tensor
@ -235,7 +246,7 @@ export declare class Human {
}>; }>;
/** Main detection method /** Main detection method
* - Analyze configuration: {@link Config} * - Analyze configuration: {@link Config}
* - Pre-this.process input: {@link Input} * - Pre-process input: {@link Input}
* - Run inference for all configured models * - Run inference for all configured models
* - Process and return result: {@link Result} * - Process and return result: {@link Result}
* *

View File

@ -1 +1 @@
{"version":3,"file":"human.d.ts","sourceRoot":"","sources":["../../src/human.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,MAAM,EAAY,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAiF,MAAM,UAAU,CAAC;AACtH,OAAO,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAG1C,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AAgBjD,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAK7B,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG1C,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC;;GAEG;AACH,oBAAY,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,eAAe,CAAC;AAEpJ;;;;;;;GAOG;AACH,oBAAY,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEjF;;GAEG;AACH,oBAAY,KAAK,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;GAEG;AACH,oBAAY,UAAU,GAAG,OAAO,EAAE,CAAC;AAEnC;;;;;;;;;;GAUG;AACH,qBAAa,KAAK;;IAChB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd,iDAAiD;IACjD,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CAAA;KAAE,CAAC;IAEvF;;;OAGG;IACH,EAAE,EAAE,UAAU,CAAC;IAEf,qEAAqE;IACrE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC;IAEb;;;;;;;OAOG;IACH,IAAI,EAAE;QAAE,MAAM,MAAC;QAAC,IAAI,MAAC;QAAC,IAAI,MAAC;QAAC,IAAI,MAAC;QAAC,OAAO,MAAC;QAAC,MAAM,MAAC;QAAC,MAAM,MAAC;QAAC,GAAG,MAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC;IAEvF;;MAEE;IACF,MAAM,EAAE;QACN,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QAC7D,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAC3B,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;QAC7B,aAAa,EAAE,UAAU,GAAG,IAAI,CAAC;QACjC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAC3B,QAAQ,EAAE,CAAC,UAAU,GAAG,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QACxD,SAAS,EAAE,CAAC,UAAU,GAAG,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QACzD,GAAG,EAAE,UAAU,GAAG,IAAI,CAAC;QACvB,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;QAC1B,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAC3B,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;QAC7B,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAC3B,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;QAC7B,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAC3B,YAAY,EAAE,UAAU,GAAG,IAAI,CAAC;KACjC,CAAC;IAEF;;;;;;;;;OASG;IACH,MAAM,EAAE,WAAW,CAAC;IACpB,oGAAoG;IACpG,iBAAiB,EAAE,OAAO,QAAQ,CAAC,aAAa,CAAC;IACjD,0EAA0E;IAC1E,SAAS,EAAE,OAAO,QAAQ,CAAC,KAAK,CAAC;IACjC,oFAAoF;IACpF,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAIpC,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAG5B;;;;;OAKG;gBACS,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC;IA+DxC,cAAc;IACd,OAAO,WAAY,MAAM,EAAE,UAO1B;IAgBD,4CAA4C;IAC5C,KAAK,aAIJ;IAED,4CAA4C;IAC5C,QAAQ;;;;QAAmF;IAE3F;;;;OAIG;IACH,KAAK,UAAW,KAAK;;;MAAuC;IAE5D;;;;;;;MAOE;IAEF,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM;IAIxE;;;;;;;OAOG;IACG,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,KAAK;IAInD;;;;OAIG;IAEH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIrC;;;;;;OAMG;IAEH,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,EAAE,SAAS,SAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE;IAI/L;;;;;;OAMG;IACG,IAAI;IAMV;;;;;MAKE;IACI,IAAI,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC;IAgCvC,cAAc;IACd,IAAI,UAAW,MAAM,aAAkD;IAEvE;;;;;OAKG;IACH,IAAI,CAAC,MAAM,GAAE,MAAoB;IAIjC;;;;;MAKE;IACI,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG;QAAE,KAAK,MAAA;KAAE,CAAC;IAIvE;;;;;;;;;MASE;IACI,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC;CA8KlF;AAED,oCAAoC;AACpC,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,CAAC"} {"version":3,"file":"human.d.ts","sourceRoot":"","sources":["../../src/human.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,MAAM,EAAY,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAiF,MAAM,UAAU,CAAC;AACtH,OAAO,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAG1C,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AAgBjD,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAK7B,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG1C,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC;;GAEG;AACH,oBAAY,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,eAAe,CAAC;AAEpJ;;;;;;;GAOG;AACH,oBAAY,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEjF;;GAEG;AACH,oBAAY,KAAK,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;GAEG;AACH,oBAAY,UAAU,GAAG,OAAO,EAAE,CAAC;AAEnC;;;;;;;;;;GAUG;AACH,qBAAa,KAAK;;IAChB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd,iDAAiD;IACjD,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CAAA;KAAE,CAAC;IAEvF;;;OAGG;IACH,EAAE,EAAE,UAAU,CAAC;IAEf,qEAAqE;IACrE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC;IAEb;;;;;;;OAOG;IACH,IAAI,EAAE;QAAE,MAAM,MAAC;QAAC,IAAI,MAAC;QAAC,IAAI,MAAC;QAAC,IAAI,MAAC;QAAC,OAAO,MAAC;QAAC,MAAM,MAAC;QAAC,MAAM,MAAC;QAAC,GAAG,MAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC;IAEvF;;MAEE;IACF,MAAM,EAAE;QACN,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QAC7D,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAC3B,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;QAC7B,aAAa,EAAE,UAAU,GAAG,IAAI,CAAC;QACjC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAC3B,QAAQ,EAAE,CAAC,UAAU,GAAG,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QACxD,SAAS,EAAE,CAAC,UAAU,GAAG,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QACzD,GAAG,EAAE,UAAU,GAAG,IAAI,CAAC;QACvB,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;QAC1B,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAC3B,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;QAC7B,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAC3B,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;QAC7B,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;QAC3B,YAAY,EAAE,UAAU,GAAG,IAAI,CAAC;KACjC,CAAC;IAEF;;;;;;;;;OASG;IACH,MAAM,EAAE,WAAW,CAAC;IACpB,oGAAoG;IACpG,iBAAiB,EAAE,OAAO,QAAQ,CAAC,aAAa,CAAC;IACjD,0EAA0E;IAC1E,SAAS,EAAE,OAAO,QAAQ,CAAC,KAAK,CAAC;IACjC,oFAAoF;IACpF,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAIpC,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAG5B;;;;;OAKG;gBACS,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC;IA+DxC,cAAc;IACd,OAAO,WAAY,MAAM,EAAE,UAO1B;IAgBD,4CAA4C;IAC5C,KAAK,aAIJ;IAED,4CAA4C;IAC5C,QAAQ;;;;QAAmF;IAE3F;;;;OAIG;IACH,KAAK,UAAW,KAAK;;;MAAuC;IAE5D;;;;;;;MAOE;IAEF,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM;IAIxE;;;;;;;;;;;;;;OAcG;IACG,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAA;KAAE,CAAC;IAIxM;;;;OAIG;IAEH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIrC;;;;;;OAMG;IAEH,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,EAAE,SAAS,SAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE;IAI/L;;;;;;OAMG;IACG,IAAI;IAMV;;;;;MAKE;IACI,IAAI,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC;IAgCvC,cAAc;IACd,IAAI,UAAW,MAAM,aAAkD;IAEvE;;;;;OAKG;IACH,IAAI,CAAC,MAAM,GAAE,MAAoB;IAIjC;;;;;MAKE;IACI,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG;QAAE,KAAK,MAAA;KAAE,CAAC;IAIvE;;;;;;;;;MASE;IACI,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC;CA4KlF;AAED,oCAAoC;AACpC,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,CAAC"}

View File

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