support segmentation for nodejs

pull/193/head
Vladimir Mandic 2021-09-22 19:27:12 -04:00
parent e7f92cc364
commit 36e9ca363c
30 changed files with 1006 additions and 1084 deletions

View File

@ -11,6 +11,7 @@
### **HEAD -> main** 2021/09/22 mandic00@live.com
- redo segmentation and handtracking
- prototype handtracking
- automated browser tests
- support for dynamic backend switching

View File

@ -13,11 +13,6 @@
<br>
### Segmentation
- Implement `NodeJS` support
- Test for leaks
### Backends
- Optimize shader packing for WebGL backend:

View File

@ -245,14 +245,14 @@ async function drawResults(input) {
if (userConfig.segmentation.enabled && ui.buffered) { // refresh segmentation if using buffered output
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);
const canvasSegMask = document.getElementById('segmentation-mask');
const ctxSegMask = canvasSegMask.getContext('2d');
ctxSegMask.clearRect(0, 0, canvasSegMask.width, canvasSegMask.height); // need to clear as seg.alpha is alpha based canvas so it adds
ctxSegMask.drawImage(seg.alpha, 0, 0, seg.alpha.width, seg.alpha.height, 0, 0, canvasSegMask.width, canvasSegMask.height);
const canvasSegCanvas = document.getElementById('segmentation-canvas');
const ctxSegCanvas = canvasSegCanvas.getContext('2d');
ctxSegCanvas.clearRect(0, 0, canvasSegCanvas.width, canvasSegCanvas.height); // need to clear as seg.alpha is alpha based canvas so it adds
ctxSegCanvas.drawImage(seg.canvas, 0, 0, seg.alpha.width, seg.alpha.height, 0, 0, canvasSegCanvas.width, canvasSegCanvas.height);
}
// result.canvas = seg.alpha;
} else if (!result.canvas || ui.buffered) { // refresh with input if using buffered output or if missing canvas

View File

@ -21,11 +21,15 @@ const config = { // just enable all and leave default settings
async function main() {
log.header();
globalThis.Canvas = canvas.Canvas; // patch global namespace with canvas library
globalThis.ImageData = canvas.ImageData; // patch global namespace with canvas library
// human.env.Canvas = canvas.Canvas; // alternatively monkey-patch human to use external canvas library
// human.env.ImageData = canvas.ImageData; // alternatively monkey-patch human to use external canvas library
// init
const human = new Human.Human(config); // create instance of human
log.info('Human:', human.version);
// @ts-ignore
human.env.Canvas = canvas.Canvas; // monkey-patch human to use external canvas library
await human.load(); // pre-load models
log.info('Loaded models:', Object.keys(human.models).filter((a) => human.models[a]));
log.info('Memory state:', human.tf.engine().memory());
@ -46,6 +50,10 @@ async function main() {
// run detection
const result = await human.detect(inputCanvas);
// run segmentation
// const seg = await human.segmentation(inputCanvas);
// log.data('Segmentation:', { data: seg.data.length, alpha: typeof seg.alpha, canvas: typeof seg.canvas });
// print results summary
const persons = result.persons; // invoke persons getter, only used to print summary on console
for (let i = 0; i < persons.length; i++) {

View File

@ -4454,7 +4454,10 @@ function canvas(width, height) {
c.height = height;
}
} else {
c = typeof env.Canvas !== "undefined" ? new env.Canvas(width, height) : null;
if (typeof env.Canvas !== "undefined")
c = new env.Canvas(width, height);
else if (typeof globalThis.Canvas !== "undefined")
c = new globalThis.Canvas(width, height);
}
return c;
}
@ -4465,7 +4468,7 @@ function process2(input, config3) {
log("input is missing");
return { tensor: null, canvas: null };
}
if (!(input instanceof tfjs_esm_exports.Tensor) && !(typeof Image !== "undefined" && input instanceof Image) && !(typeof env.Canvas !== "undefined" && input instanceof env.Canvas) && !(typeof ImageData !== "undefined" && input instanceof ImageData) && !(typeof ImageBitmap !== "undefined" && input instanceof ImageBitmap) && !(typeof HTMLImageElement !== "undefined" && input instanceof HTMLImageElement) && !(typeof HTMLMediaElement !== "undefined" && input instanceof HTMLMediaElement) && !(typeof HTMLVideoElement !== "undefined" && input instanceof HTMLVideoElement) && !(typeof HTMLCanvasElement !== "undefined" && input instanceof HTMLCanvasElement) && !(typeof OffscreenCanvas !== "undefined" && input instanceof OffscreenCanvas)) {
if (!(input instanceof tfjs_esm_exports.Tensor) && !(typeof Image !== "undefined" && input instanceof Image) && !(typeof env.Canvas !== "undefined" && input instanceof env.Canvas) && !(typeof globalThis.Canvas !== "undefined" && input instanceof globalThis.Canvas) && !(typeof ImageData !== "undefined" && input instanceof ImageData) && !(typeof ImageBitmap !== "undefined" && input instanceof ImageBitmap) && !(typeof HTMLImageElement !== "undefined" && input instanceof HTMLImageElement) && !(typeof HTMLMediaElement !== "undefined" && input instanceof HTMLMediaElement) && !(typeof HTMLVideoElement !== "undefined" && input instanceof HTMLVideoElement) && !(typeof HTMLCanvasElement !== "undefined" && input instanceof HTMLCanvasElement) && !(typeof OffscreenCanvas !== "undefined" && input instanceof OffscreenCanvas)) {
throw new Error("input type is not recognized");
}
if (input instanceof tfjs_esm_exports.Tensor) {
@ -4675,7 +4678,8 @@ var env = {
},
kernels: [],
Canvas: void 0,
Image: void 0
Image: void 0,
ImageData: void 0
};
async function backendInfo() {
var _a;
@ -10231,53 +10235,51 @@ async function load13(config3) {
log("cached model:", model9["modelUrl"]);
return model9;
}
async function predict12(input, config3) {
async function process5(input, background, config3) {
var _a, _b;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[2]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[1]) || 0;
if (!input.tensor || !model9 || !model9.inputs[0].shape)
return { data: null, canvas: null, alpha: null };
const resizeInput = tfjs_esm_exports.image.resizeBilinear(input.tensor, [model9.inputs[0].shape[1], model9.inputs[0].shape[2]], false);
const norm = tfjs_esm_exports.div(resizeInput, 255);
const res = model9.predict(norm);
tfjs_esm_exports.dispose(resizeInput);
tfjs_esm_exports.dispose(norm);
const squeeze8 = tfjs_esm_exports.squeeze(res, 0);
tfjs_esm_exports.dispose(res);
let dataT;
if (squeeze8.shape[2] === 2) {
const softmax = squeeze8.softmax();
const [bg, fg] = tfjs_esm_exports.unstack(softmax, 2);
const expand = tfjs_esm_exports.expandDims(fg, 2);
const pad = tfjs_esm_exports.expandDims(expand, 0);
tfjs_esm_exports.dispose(softmax);
tfjs_esm_exports.dispose(bg);
tfjs_esm_exports.dispose(fg);
const crop = tfjs_esm_exports.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
dataT = tfjs_esm_exports.squeeze(crop, 0);
tfjs_esm_exports.dispose(crop);
tfjs_esm_exports.dispose(expand);
tfjs_esm_exports.dispose(pad);
if (busy)
return { data: [], canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const inputImage = process2(input, config3);
const width = ((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0;
const height = ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0;
if (!inputImage.tensor)
return { data: [], canvas: null, alpha: null };
const t = {};
t.resize = tfjs_esm_exports.image.resizeBilinear(inputImage.tensor, [model9.inputs[0].shape ? model9.inputs[0].shape[1] : 0, model9.inputs[0].shape ? model9.inputs[0].shape[2] : 0], false);
tfjs_esm_exports.dispose(inputImage.tensor);
t.norm = tfjs_esm_exports.div(t.resize, 255);
t.res = model9.predict(t.norm);
t.squeeze = tfjs_esm_exports.squeeze(t.res, 0);
if (t.squeeze.shape[2] === 2) {
t.softmax = tfjs_esm_exports.softmax(t.squeeze);
[t.bg, t.fg] = tfjs_esm_exports.unstack(t.softmax, 2);
t.expand = tfjs_esm_exports.expandDims(t.fg, 2);
t.pad = tfjs_esm_exports.expandDims(t.expand, 0);
t.crop = tfjs_esm_exports.image.cropAndResize(t.pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
t.data = tfjs_esm_exports.squeeze(t.crop, 0);
} else {
dataT = tfjs_esm_exports.image.resizeBilinear(squeeze8, [height, width]);
t.data = tfjs_esm_exports.image.resizeBilinear(t.squeeze, [height, width]);
}
tfjs_esm_exports.dispose(squeeze8);
const data = await dataT.dataSync();
if (env.node) {
tfjs_esm_exports.dispose(dataT);
const data = Array.from(await t.data.data());
if (env.node && !env.Canvas && typeof ImageData === "undefined") {
if (config3.debug)
log("canvas support missing");
Object.keys(t).forEach((tensor3) => tfjs_esm_exports.dispose(t[tensor3]));
return { data, canvas: null, alpha: null };
}
const alphaCanvas = canvas(width, height);
await tfjs_esm_exports.browser.toPixels(dataT, alphaCanvas);
tfjs_esm_exports.dispose(dataT);
await tfjs_esm_exports.browser.toPixels(t.data, alphaCanvas);
const alphaCtx = alphaCanvas.getContext("2d");
if (config3.segmentation.blur && config3.segmentation.blur > 0)
alphaCtx.filter = `blur(${config3.segmentation.blur}px)`;
const alphaData = alphaCtx.getImageData(0, 0, width, height);
const compositeCanvas = canvas(width, height);
const compositeCtx = compositeCanvas.getContext("2d");
if (input.canvas)
compositeCtx.drawImage(input.canvas, 0, 0);
if (inputImage.canvas)
compositeCtx.drawImage(inputImage.canvas, 0, 0);
compositeCtx.globalCompositeOperation = "darken";
if (config3.segmentation.blur && config3.segmentation.blur > 0)
compositeCtx.filter = `blur(${config3.segmentation.blur}px)`;
@ -10288,29 +10290,18 @@ async function predict12(input, config3) {
for (let i = 0; i < width * height; i++)
compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0];
compositeCtx.putImageData(compositeData, 0, 0);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
async function process5(input, background, config3) {
var _a, _b;
if (busy)
return { data: null, canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const inputImage = process2(input, config3);
const segmentation3 = await predict12(inputImage, config3);
tfjs_esm_exports.dispose(inputImage.tensor);
let mergedCanvas = null;
if (background && segmentation3.canvas) {
mergedCanvas = canvas(((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0, ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0);
if (background && compositeCanvas) {
mergedCanvas = canvas(width, height);
const bgImage = process2(background, config3);
tfjs_esm_exports.dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext("2d");
ctxMerge.drawImage(bgImage.canvas, 0, 0, mergedCanvas.width, mergedCanvas.height);
ctxMerge.drawImage(segmentation3.canvas, 0, 0);
ctxMerge.drawImage(compositeCanvas, 0, 0);
}
Object.keys(t).forEach((tensor3) => tfjs_esm_exports.dispose(t[tensor3]));
busy = false;
return { data: segmentation3.data, canvas: mergedCanvas || segmentation3.canvas, alpha: segmentation3.alpha };
return { data, canvas: mergedCanvas || compositeCanvas, alpha: alphaCanvas };
}
// src/models.ts

File diff suppressed because one or more lines are too long

99
dist/human.esm.js vendored
View File

@ -64522,7 +64522,10 @@ function canvas(width, height) {
c.height = height;
}
} else {
c = typeof env2.Canvas !== "undefined" ? new env2.Canvas(width, height) : null;
if (typeof env2.Canvas !== "undefined")
c = new env2.Canvas(width, height);
else if (typeof globalThis.Canvas !== "undefined")
c = new globalThis.Canvas(width, height);
}
return c;
}
@ -64533,7 +64536,7 @@ function process2(input2, config3) {
log("input is missing");
return { tensor: null, canvas: null };
}
if (!(input2 instanceof Tensor) && !(typeof Image !== "undefined" && input2 instanceof Image) && !(typeof env2.Canvas !== "undefined" && input2 instanceof env2.Canvas) && !(typeof ImageData !== "undefined" && input2 instanceof ImageData) && !(typeof ImageBitmap !== "undefined" && input2 instanceof ImageBitmap) && !(typeof HTMLImageElement !== "undefined" && input2 instanceof HTMLImageElement) && !(typeof HTMLMediaElement !== "undefined" && input2 instanceof HTMLMediaElement) && !(typeof HTMLVideoElement !== "undefined" && input2 instanceof HTMLVideoElement) && !(typeof HTMLCanvasElement !== "undefined" && input2 instanceof HTMLCanvasElement) && !(typeof OffscreenCanvas !== "undefined" && input2 instanceof OffscreenCanvas)) {
if (!(input2 instanceof Tensor) && !(typeof Image !== "undefined" && input2 instanceof Image) && !(typeof env2.Canvas !== "undefined" && input2 instanceof env2.Canvas) && !(typeof globalThis.Canvas !== "undefined" && input2 instanceof globalThis.Canvas) && !(typeof ImageData !== "undefined" && input2 instanceof ImageData) && !(typeof ImageBitmap !== "undefined" && input2 instanceof ImageBitmap) && !(typeof HTMLImageElement !== "undefined" && input2 instanceof HTMLImageElement) && !(typeof HTMLMediaElement !== "undefined" && input2 instanceof HTMLMediaElement) && !(typeof HTMLVideoElement !== "undefined" && input2 instanceof HTMLVideoElement) && !(typeof HTMLCanvasElement !== "undefined" && input2 instanceof HTMLCanvasElement) && !(typeof OffscreenCanvas !== "undefined" && input2 instanceof OffscreenCanvas)) {
throw new Error("input type is not recognized");
}
if (input2 instanceof Tensor) {
@ -64743,7 +64746,8 @@ var env2 = {
},
kernels: [],
Canvas: void 0,
Image: void 0
Image: void 0,
ImageData: void 0
};
async function backendInfo() {
var _a;
@ -70299,53 +70303,51 @@ async function load13(config3) {
log("cached model:", model10["modelUrl"]);
return model10;
}
async function predict12(input2, config3) {
async function process5(input2, background, config3) {
var _a, _b;
const width = ((_a = input2.tensor) == null ? void 0 : _a.shape[2]) || 0;
const height = ((_b = input2.tensor) == null ? void 0 : _b.shape[1]) || 0;
if (!input2.tensor || !model10 || !model10.inputs[0].shape)
return { data: null, canvas: null, alpha: null };
const resizeInput = image.resizeBilinear(input2.tensor, [model10.inputs[0].shape[1], model10.inputs[0].shape[2]], false);
const norm2 = div(resizeInput, 255);
const res = model10.predict(norm2);
dispose(resizeInput);
dispose(norm2);
const squeeze2 = squeeze(res, 0);
dispose(res);
let dataT;
if (squeeze2.shape[2] === 2) {
const softmax6 = squeeze2.softmax();
const [bg, fg] = unstack(softmax6, 2);
const expand = expandDims(fg, 2);
const pad3 = expandDims(expand, 0);
dispose(softmax6);
dispose(bg);
dispose(fg);
const crop = image.cropAndResize(pad3, [[0, 0, 0.5, 0.5]], [0], [width, height]);
dataT = squeeze(crop, 0);
dispose(crop);
dispose(expand);
dispose(pad3);
if (busy)
return { data: [], canvas: null, alpha: null };
busy = true;
if (!model10)
await load13(config3);
const inputImage = process2(input2, config3);
const width = ((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0;
const height = ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0;
if (!inputImage.tensor)
return { data: [], canvas: null, alpha: null };
const t = {};
t.resize = image.resizeBilinear(inputImage.tensor, [model10.inputs[0].shape ? model10.inputs[0].shape[1] : 0, model10.inputs[0].shape ? model10.inputs[0].shape[2] : 0], false);
dispose(inputImage.tensor);
t.norm = div(t.resize, 255);
t.res = model10.predict(t.norm);
t.squeeze = squeeze(t.res, 0);
if (t.squeeze.shape[2] === 2) {
t.softmax = softmax(t.squeeze);
[t.bg, t.fg] = unstack(t.softmax, 2);
t.expand = expandDims(t.fg, 2);
t.pad = expandDims(t.expand, 0);
t.crop = image.cropAndResize(t.pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
t.data = squeeze(t.crop, 0);
} else {
dataT = image.resizeBilinear(squeeze2, [height, width]);
t.data = image.resizeBilinear(t.squeeze, [height, width]);
}
dispose(squeeze2);
const data = await dataT.dataSync();
if (env2.node) {
dispose(dataT);
const data = Array.from(await t.data.data());
if (env2.node && !env2.Canvas && typeof ImageData === "undefined") {
if (config3.debug)
log("canvas support missing");
Object.keys(t).forEach((tensor2) => dispose(t[tensor2]));
return { data, canvas: null, alpha: null };
}
const alphaCanvas = canvas(width, height);
await browser_exports.toPixels(dataT, alphaCanvas);
dispose(dataT);
await browser_exports.toPixels(t.data, alphaCanvas);
const alphaCtx = alphaCanvas.getContext("2d");
if (config3.segmentation.blur && config3.segmentation.blur > 0)
alphaCtx.filter = `blur(${config3.segmentation.blur}px)`;
const alphaData = alphaCtx.getImageData(0, 0, width, height);
const compositeCanvas = canvas(width, height);
const compositeCtx = compositeCanvas.getContext("2d");
if (input2.canvas)
compositeCtx.drawImage(input2.canvas, 0, 0);
if (inputImage.canvas)
compositeCtx.drawImage(inputImage.canvas, 0, 0);
compositeCtx.globalCompositeOperation = "darken";
if (config3.segmentation.blur && config3.segmentation.blur > 0)
compositeCtx.filter = `blur(${config3.segmentation.blur}px)`;
@ -70356,29 +70358,18 @@ async function predict12(input2, config3) {
for (let i = 0; i < width * height; i++)
compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0];
compositeCtx.putImageData(compositeData, 0, 0);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
async function process5(input2, background, config3) {
var _a, _b;
if (busy)
return { data: null, canvas: null, alpha: null };
busy = true;
if (!model10)
await load13(config3);
const inputImage = process2(input2, config3);
const segmentation3 = await predict12(inputImage, config3);
dispose(inputImage.tensor);
let mergedCanvas = null;
if (background && segmentation3.canvas) {
mergedCanvas = canvas(((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0, ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0);
if (background && compositeCanvas) {
mergedCanvas = canvas(width, height);
const bgImage = process2(background, config3);
dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext("2d");
ctxMerge.drawImage(bgImage.canvas, 0, 0, mergedCanvas.width, mergedCanvas.height);
ctxMerge.drawImage(segmentation3.canvas, 0, 0);
ctxMerge.drawImage(compositeCanvas, 0, 0);
}
Object.keys(t).forEach((tensor2) => dispose(t[tensor2]));
busy = false;
return { data: segmentation3.data, canvas: mergedCanvas || segmentation3.canvas, alpha: segmentation3.alpha };
return { data, canvas: mergedCanvas || compositeCanvas, alpha: alphaCanvas };
}
// src/models.ts

File diff suppressed because one or more lines are too long

254
dist/human.js vendored

File diff suppressed because one or more lines are too long

View File

@ -4485,7 +4485,10 @@ function canvas(width, height) {
c.height = height;
}
} else {
c = typeof env.Canvas !== "undefined" ? new env.Canvas(width, height) : null;
if (typeof env.Canvas !== "undefined")
c = new env.Canvas(width, height);
else if (typeof globalThis.Canvas !== "undefined")
c = new globalThis.Canvas(width, height);
}
return c;
}
@ -4496,7 +4499,7 @@ function process2(input, config3) {
log("input is missing");
return { tensor: null, canvas: null };
}
if (!(input instanceof tf3.Tensor) && !(typeof Image !== "undefined" && input instanceof Image) && !(typeof env.Canvas !== "undefined" && input instanceof env.Canvas) && !(typeof ImageData !== "undefined" && input instanceof ImageData) && !(typeof ImageBitmap !== "undefined" && input instanceof ImageBitmap) && !(typeof HTMLImageElement !== "undefined" && input instanceof HTMLImageElement) && !(typeof HTMLMediaElement !== "undefined" && input instanceof HTMLMediaElement) && !(typeof HTMLVideoElement !== "undefined" && input instanceof HTMLVideoElement) && !(typeof HTMLCanvasElement !== "undefined" && input instanceof HTMLCanvasElement) && !(typeof OffscreenCanvas !== "undefined" && input instanceof OffscreenCanvas)) {
if (!(input instanceof tf3.Tensor) && !(typeof Image !== "undefined" && input instanceof Image) && !(typeof env.Canvas !== "undefined" && input instanceof env.Canvas) && !(typeof globalThis.Canvas !== "undefined" && input instanceof globalThis.Canvas) && !(typeof ImageData !== "undefined" && input instanceof ImageData) && !(typeof ImageBitmap !== "undefined" && input instanceof ImageBitmap) && !(typeof HTMLImageElement !== "undefined" && input instanceof HTMLImageElement) && !(typeof HTMLMediaElement !== "undefined" && input instanceof HTMLMediaElement) && !(typeof HTMLVideoElement !== "undefined" && input instanceof HTMLVideoElement) && !(typeof HTMLCanvasElement !== "undefined" && input instanceof HTMLCanvasElement) && !(typeof OffscreenCanvas !== "undefined" && input instanceof OffscreenCanvas)) {
throw new Error("input type is not recognized");
}
if (input instanceof tf3.Tensor) {
@ -4706,7 +4709,8 @@ var env = {
},
kernels: [],
Canvas: void 0,
Image: void 0
Image: void 0,
ImageData: void 0
};
async function backendInfo() {
var _a;
@ -10288,53 +10292,51 @@ async function load13(config3) {
log("cached model:", model9["modelUrl"]);
return model9;
}
async function predict12(input, config3) {
async function process5(input, background, config3) {
var _a, _b;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[2]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[1]) || 0;
if (!input.tensor || !model9 || !model9.inputs[0].shape)
return { data: null, canvas: null, alpha: null };
const resizeInput = tf20.image.resizeBilinear(input.tensor, [model9.inputs[0].shape[1], model9.inputs[0].shape[2]], false);
const norm = tf20.div(resizeInput, 255);
const res = model9.predict(norm);
tf20.dispose(resizeInput);
tf20.dispose(norm);
const squeeze8 = tf20.squeeze(res, 0);
tf20.dispose(res);
let dataT;
if (squeeze8.shape[2] === 2) {
const softmax = squeeze8.softmax();
const [bg, fg] = tf20.unstack(softmax, 2);
const expand = tf20.expandDims(fg, 2);
const pad = tf20.expandDims(expand, 0);
tf20.dispose(softmax);
tf20.dispose(bg);
tf20.dispose(fg);
const crop = tf20.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
dataT = tf20.squeeze(crop, 0);
tf20.dispose(crop);
tf20.dispose(expand);
tf20.dispose(pad);
if (busy)
return { data: [], canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const inputImage = process2(input, config3);
const width = ((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0;
const height = ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0;
if (!inputImage.tensor)
return { data: [], canvas: null, alpha: null };
const t = {};
t.resize = tf20.image.resizeBilinear(inputImage.tensor, [model9.inputs[0].shape ? model9.inputs[0].shape[1] : 0, model9.inputs[0].shape ? model9.inputs[0].shape[2] : 0], false);
tf20.dispose(inputImage.tensor);
t.norm = tf20.div(t.resize, 255);
t.res = model9.predict(t.norm);
t.squeeze = tf20.squeeze(t.res, 0);
if (t.squeeze.shape[2] === 2) {
t.softmax = tf20.softmax(t.squeeze);
[t.bg, t.fg] = tf20.unstack(t.softmax, 2);
t.expand = tf20.expandDims(t.fg, 2);
t.pad = tf20.expandDims(t.expand, 0);
t.crop = tf20.image.cropAndResize(t.pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
t.data = tf20.squeeze(t.crop, 0);
} else {
dataT = tf20.image.resizeBilinear(squeeze8, [height, width]);
t.data = tf20.image.resizeBilinear(t.squeeze, [height, width]);
}
tf20.dispose(squeeze8);
const data = await dataT.dataSync();
if (env.node) {
tf20.dispose(dataT);
const data = Array.from(await t.data.data());
if (env.node && !env.Canvas && typeof ImageData === "undefined") {
if (config3.debug)
log("canvas support missing");
Object.keys(t).forEach((tensor3) => tf20.dispose(t[tensor3]));
return { data, canvas: null, alpha: null };
}
const alphaCanvas = canvas(width, height);
await tf20.browser.toPixels(dataT, alphaCanvas);
tf20.dispose(dataT);
await tf20.browser.toPixels(t.data, alphaCanvas);
const alphaCtx = alphaCanvas.getContext("2d");
if (config3.segmentation.blur && config3.segmentation.blur > 0)
alphaCtx.filter = `blur(${config3.segmentation.blur}px)`;
const alphaData = alphaCtx.getImageData(0, 0, width, height);
const compositeCanvas = canvas(width, height);
const compositeCtx = compositeCanvas.getContext("2d");
if (input.canvas)
compositeCtx.drawImage(input.canvas, 0, 0);
if (inputImage.canvas)
compositeCtx.drawImage(inputImage.canvas, 0, 0);
compositeCtx.globalCompositeOperation = "darken";
if (config3.segmentation.blur && config3.segmentation.blur > 0)
compositeCtx.filter = `blur(${config3.segmentation.blur}px)`;
@ -10345,29 +10347,18 @@ async function predict12(input, config3) {
for (let i = 0; i < width * height; i++)
compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0];
compositeCtx.putImageData(compositeData, 0, 0);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
async function process5(input, background, config3) {
var _a, _b;
if (busy)
return { data: null, canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const inputImage = process2(input, config3);
const segmentation3 = await predict12(inputImage, config3);
tf20.dispose(inputImage.tensor);
let mergedCanvas = null;
if (background && segmentation3.canvas) {
mergedCanvas = canvas(((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0, ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0);
if (background && compositeCanvas) {
mergedCanvas = canvas(width, height);
const bgImage = process2(background, config3);
tf20.dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext("2d");
ctxMerge.drawImage(bgImage.canvas, 0, 0, mergedCanvas.width, mergedCanvas.height);
ctxMerge.drawImage(segmentation3.canvas, 0, 0);
ctxMerge.drawImage(compositeCanvas, 0, 0);
}
Object.keys(t).forEach((tensor3) => tf20.dispose(t[tensor3]));
busy = false;
return { data: segmentation3.data, canvas: mergedCanvas || segmentation3.canvas, alpha: segmentation3.alpha };
return { data, canvas: mergedCanvas || compositeCanvas, alpha: alphaCanvas };
}
// src/models.ts

View File

@ -4486,7 +4486,10 @@ function canvas(width, height) {
c.height = height;
}
} else {
c = typeof env.Canvas !== "undefined" ? new env.Canvas(width, height) : null;
if (typeof env.Canvas !== "undefined")
c = new env.Canvas(width, height);
else if (typeof globalThis.Canvas !== "undefined")
c = new globalThis.Canvas(width, height);
}
return c;
}
@ -4497,7 +4500,7 @@ function process2(input, config3) {
log("input is missing");
return { tensor: null, canvas: null };
}
if (!(input instanceof tf3.Tensor) && !(typeof Image !== "undefined" && input instanceof Image) && !(typeof env.Canvas !== "undefined" && input instanceof env.Canvas) && !(typeof ImageData !== "undefined" && input instanceof ImageData) && !(typeof ImageBitmap !== "undefined" && input instanceof ImageBitmap) && !(typeof HTMLImageElement !== "undefined" && input instanceof HTMLImageElement) && !(typeof HTMLMediaElement !== "undefined" && input instanceof HTMLMediaElement) && !(typeof HTMLVideoElement !== "undefined" && input instanceof HTMLVideoElement) && !(typeof HTMLCanvasElement !== "undefined" && input instanceof HTMLCanvasElement) && !(typeof OffscreenCanvas !== "undefined" && input instanceof OffscreenCanvas)) {
if (!(input instanceof tf3.Tensor) && !(typeof Image !== "undefined" && input instanceof Image) && !(typeof env.Canvas !== "undefined" && input instanceof env.Canvas) && !(typeof globalThis.Canvas !== "undefined" && input instanceof globalThis.Canvas) && !(typeof ImageData !== "undefined" && input instanceof ImageData) && !(typeof ImageBitmap !== "undefined" && input instanceof ImageBitmap) && !(typeof HTMLImageElement !== "undefined" && input instanceof HTMLImageElement) && !(typeof HTMLMediaElement !== "undefined" && input instanceof HTMLMediaElement) && !(typeof HTMLVideoElement !== "undefined" && input instanceof HTMLVideoElement) && !(typeof HTMLCanvasElement !== "undefined" && input instanceof HTMLCanvasElement) && !(typeof OffscreenCanvas !== "undefined" && input instanceof OffscreenCanvas)) {
throw new Error("input type is not recognized");
}
if (input instanceof tf3.Tensor) {
@ -4707,7 +4710,8 @@ var env = {
},
kernels: [],
Canvas: void 0,
Image: void 0
Image: void 0,
ImageData: void 0
};
async function backendInfo() {
var _a;
@ -10289,53 +10293,51 @@ async function load13(config3) {
log("cached model:", model9["modelUrl"]);
return model9;
}
async function predict12(input, config3) {
async function process5(input, background, config3) {
var _a, _b;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[2]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[1]) || 0;
if (!input.tensor || !model9 || !model9.inputs[0].shape)
return { data: null, canvas: null, alpha: null };
const resizeInput = tf20.image.resizeBilinear(input.tensor, [model9.inputs[0].shape[1], model9.inputs[0].shape[2]], false);
const norm = tf20.div(resizeInput, 255);
const res = model9.predict(norm);
tf20.dispose(resizeInput);
tf20.dispose(norm);
const squeeze8 = tf20.squeeze(res, 0);
tf20.dispose(res);
let dataT;
if (squeeze8.shape[2] === 2) {
const softmax = squeeze8.softmax();
const [bg, fg] = tf20.unstack(softmax, 2);
const expand = tf20.expandDims(fg, 2);
const pad = tf20.expandDims(expand, 0);
tf20.dispose(softmax);
tf20.dispose(bg);
tf20.dispose(fg);
const crop = tf20.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
dataT = tf20.squeeze(crop, 0);
tf20.dispose(crop);
tf20.dispose(expand);
tf20.dispose(pad);
if (busy)
return { data: [], canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const inputImage = process2(input, config3);
const width = ((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0;
const height = ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0;
if (!inputImage.tensor)
return { data: [], canvas: null, alpha: null };
const t = {};
t.resize = tf20.image.resizeBilinear(inputImage.tensor, [model9.inputs[0].shape ? model9.inputs[0].shape[1] : 0, model9.inputs[0].shape ? model9.inputs[0].shape[2] : 0], false);
tf20.dispose(inputImage.tensor);
t.norm = tf20.div(t.resize, 255);
t.res = model9.predict(t.norm);
t.squeeze = tf20.squeeze(t.res, 0);
if (t.squeeze.shape[2] === 2) {
t.softmax = tf20.softmax(t.squeeze);
[t.bg, t.fg] = tf20.unstack(t.softmax, 2);
t.expand = tf20.expandDims(t.fg, 2);
t.pad = tf20.expandDims(t.expand, 0);
t.crop = tf20.image.cropAndResize(t.pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
t.data = tf20.squeeze(t.crop, 0);
} else {
dataT = tf20.image.resizeBilinear(squeeze8, [height, width]);
t.data = tf20.image.resizeBilinear(t.squeeze, [height, width]);
}
tf20.dispose(squeeze8);
const data = await dataT.dataSync();
if (env.node) {
tf20.dispose(dataT);
const data = Array.from(await t.data.data());
if (env.node && !env.Canvas && typeof ImageData === "undefined") {
if (config3.debug)
log("canvas support missing");
Object.keys(t).forEach((tensor3) => tf20.dispose(t[tensor3]));
return { data, canvas: null, alpha: null };
}
const alphaCanvas = canvas(width, height);
await tf20.browser.toPixels(dataT, alphaCanvas);
tf20.dispose(dataT);
await tf20.browser.toPixels(t.data, alphaCanvas);
const alphaCtx = alphaCanvas.getContext("2d");
if (config3.segmentation.blur && config3.segmentation.blur > 0)
alphaCtx.filter = `blur(${config3.segmentation.blur}px)`;
const alphaData = alphaCtx.getImageData(0, 0, width, height);
const compositeCanvas = canvas(width, height);
const compositeCtx = compositeCanvas.getContext("2d");
if (input.canvas)
compositeCtx.drawImage(input.canvas, 0, 0);
if (inputImage.canvas)
compositeCtx.drawImage(inputImage.canvas, 0, 0);
compositeCtx.globalCompositeOperation = "darken";
if (config3.segmentation.blur && config3.segmentation.blur > 0)
compositeCtx.filter = `blur(${config3.segmentation.blur}px)`;
@ -10346,29 +10348,18 @@ async function predict12(input, config3) {
for (let i = 0; i < width * height; i++)
compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0];
compositeCtx.putImageData(compositeData, 0, 0);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
async function process5(input, background, config3) {
var _a, _b;
if (busy)
return { data: null, canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const inputImage = process2(input, config3);
const segmentation3 = await predict12(inputImage, config3);
tf20.dispose(inputImage.tensor);
let mergedCanvas = null;
if (background && segmentation3.canvas) {
mergedCanvas = canvas(((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0, ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0);
if (background && compositeCanvas) {
mergedCanvas = canvas(width, height);
const bgImage = process2(background, config3);
tf20.dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext("2d");
ctxMerge.drawImage(bgImage.canvas, 0, 0, mergedCanvas.width, mergedCanvas.height);
ctxMerge.drawImage(segmentation3.canvas, 0, 0);
ctxMerge.drawImage(compositeCanvas, 0, 0);
}
Object.keys(t).forEach((tensor3) => tf20.dispose(t[tensor3]));
busy = false;
return { data: segmentation3.data, canvas: mergedCanvas || segmentation3.canvas, alpha: segmentation3.alpha };
return { data, canvas: mergedCanvas || compositeCanvas, alpha: alphaCanvas };
}
// src/models.ts

99
dist/human.node.js vendored
View File

@ -4485,7 +4485,10 @@ function canvas(width, height) {
c.height = height;
}
} else {
c = typeof env.Canvas !== "undefined" ? new env.Canvas(width, height) : null;
if (typeof env.Canvas !== "undefined")
c = new env.Canvas(width, height);
else if (typeof globalThis.Canvas !== "undefined")
c = new globalThis.Canvas(width, height);
}
return c;
}
@ -4496,7 +4499,7 @@ function process2(input, config3) {
log("input is missing");
return { tensor: null, canvas: null };
}
if (!(input instanceof tf3.Tensor) && !(typeof Image !== "undefined" && input instanceof Image) && !(typeof env.Canvas !== "undefined" && input instanceof env.Canvas) && !(typeof ImageData !== "undefined" && input instanceof ImageData) && !(typeof ImageBitmap !== "undefined" && input instanceof ImageBitmap) && !(typeof HTMLImageElement !== "undefined" && input instanceof HTMLImageElement) && !(typeof HTMLMediaElement !== "undefined" && input instanceof HTMLMediaElement) && !(typeof HTMLVideoElement !== "undefined" && input instanceof HTMLVideoElement) && !(typeof HTMLCanvasElement !== "undefined" && input instanceof HTMLCanvasElement) && !(typeof OffscreenCanvas !== "undefined" && input instanceof OffscreenCanvas)) {
if (!(input instanceof tf3.Tensor) && !(typeof Image !== "undefined" && input instanceof Image) && !(typeof env.Canvas !== "undefined" && input instanceof env.Canvas) && !(typeof globalThis.Canvas !== "undefined" && input instanceof globalThis.Canvas) && !(typeof ImageData !== "undefined" && input instanceof ImageData) && !(typeof ImageBitmap !== "undefined" && input instanceof ImageBitmap) && !(typeof HTMLImageElement !== "undefined" && input instanceof HTMLImageElement) && !(typeof HTMLMediaElement !== "undefined" && input instanceof HTMLMediaElement) && !(typeof HTMLVideoElement !== "undefined" && input instanceof HTMLVideoElement) && !(typeof HTMLCanvasElement !== "undefined" && input instanceof HTMLCanvasElement) && !(typeof OffscreenCanvas !== "undefined" && input instanceof OffscreenCanvas)) {
throw new Error("input type is not recognized");
}
if (input instanceof tf3.Tensor) {
@ -4706,7 +4709,8 @@ var env = {
},
kernels: [],
Canvas: void 0,
Image: void 0
Image: void 0,
ImageData: void 0
};
async function backendInfo() {
var _a;
@ -10288,53 +10292,51 @@ async function load13(config3) {
log("cached model:", model9["modelUrl"]);
return model9;
}
async function predict12(input, config3) {
async function process5(input, background, config3) {
var _a, _b;
const width = ((_a = input.tensor) == null ? void 0 : _a.shape[2]) || 0;
const height = ((_b = input.tensor) == null ? void 0 : _b.shape[1]) || 0;
if (!input.tensor || !model9 || !model9.inputs[0].shape)
return { data: null, canvas: null, alpha: null };
const resizeInput = tf20.image.resizeBilinear(input.tensor, [model9.inputs[0].shape[1], model9.inputs[0].shape[2]], false);
const norm = tf20.div(resizeInput, 255);
const res = model9.predict(norm);
tf20.dispose(resizeInput);
tf20.dispose(norm);
const squeeze8 = tf20.squeeze(res, 0);
tf20.dispose(res);
let dataT;
if (squeeze8.shape[2] === 2) {
const softmax = squeeze8.softmax();
const [bg, fg] = tf20.unstack(softmax, 2);
const expand = tf20.expandDims(fg, 2);
const pad = tf20.expandDims(expand, 0);
tf20.dispose(softmax);
tf20.dispose(bg);
tf20.dispose(fg);
const crop = tf20.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
dataT = tf20.squeeze(crop, 0);
tf20.dispose(crop);
tf20.dispose(expand);
tf20.dispose(pad);
if (busy)
return { data: [], canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const inputImage = process2(input, config3);
const width = ((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0;
const height = ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0;
if (!inputImage.tensor)
return { data: [], canvas: null, alpha: null };
const t = {};
t.resize = tf20.image.resizeBilinear(inputImage.tensor, [model9.inputs[0].shape ? model9.inputs[0].shape[1] : 0, model9.inputs[0].shape ? model9.inputs[0].shape[2] : 0], false);
tf20.dispose(inputImage.tensor);
t.norm = tf20.div(t.resize, 255);
t.res = model9.predict(t.norm);
t.squeeze = tf20.squeeze(t.res, 0);
if (t.squeeze.shape[2] === 2) {
t.softmax = tf20.softmax(t.squeeze);
[t.bg, t.fg] = tf20.unstack(t.softmax, 2);
t.expand = tf20.expandDims(t.fg, 2);
t.pad = tf20.expandDims(t.expand, 0);
t.crop = tf20.image.cropAndResize(t.pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
t.data = tf20.squeeze(t.crop, 0);
} else {
dataT = tf20.image.resizeBilinear(squeeze8, [height, width]);
t.data = tf20.image.resizeBilinear(t.squeeze, [height, width]);
}
tf20.dispose(squeeze8);
const data = await dataT.dataSync();
if (env.node) {
tf20.dispose(dataT);
const data = Array.from(await t.data.data());
if (env.node && !env.Canvas && typeof ImageData === "undefined") {
if (config3.debug)
log("canvas support missing");
Object.keys(t).forEach((tensor3) => tf20.dispose(t[tensor3]));
return { data, canvas: null, alpha: null };
}
const alphaCanvas = canvas(width, height);
await tf20.browser.toPixels(dataT, alphaCanvas);
tf20.dispose(dataT);
await tf20.browser.toPixels(t.data, alphaCanvas);
const alphaCtx = alphaCanvas.getContext("2d");
if (config3.segmentation.blur && config3.segmentation.blur > 0)
alphaCtx.filter = `blur(${config3.segmentation.blur}px)`;
const alphaData = alphaCtx.getImageData(0, 0, width, height);
const compositeCanvas = canvas(width, height);
const compositeCtx = compositeCanvas.getContext("2d");
if (input.canvas)
compositeCtx.drawImage(input.canvas, 0, 0);
if (inputImage.canvas)
compositeCtx.drawImage(inputImage.canvas, 0, 0);
compositeCtx.globalCompositeOperation = "darken";
if (config3.segmentation.blur && config3.segmentation.blur > 0)
compositeCtx.filter = `blur(${config3.segmentation.blur}px)`;
@ -10345,29 +10347,18 @@ async function predict12(input, config3) {
for (let i = 0; i < width * height; i++)
compositeData.data[4 * i + 3] = alphaData.data[4 * i + 0];
compositeCtx.putImageData(compositeData, 0, 0);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
async function process5(input, background, config3) {
var _a, _b;
if (busy)
return { data: null, canvas: null, alpha: null };
busy = true;
if (!model9)
await load13(config3);
const inputImage = process2(input, config3);
const segmentation3 = await predict12(inputImage, config3);
tf20.dispose(inputImage.tensor);
let mergedCanvas = null;
if (background && segmentation3.canvas) {
mergedCanvas = canvas(((_a = inputImage.canvas) == null ? void 0 : _a.width) || 0, ((_b = inputImage.canvas) == null ? void 0 : _b.height) || 0);
if (background && compositeCanvas) {
mergedCanvas = canvas(width, height);
const bgImage = process2(background, config3);
tf20.dispose(bgImage.tensor);
const ctxMerge = mergedCanvas.getContext("2d");
ctxMerge.drawImage(bgImage.canvas, 0, 0, mergedCanvas.width, mergedCanvas.height);
ctxMerge.drawImage(segmentation3.canvas, 0, 0);
ctxMerge.drawImage(compositeCanvas, 0, 0);
}
Object.keys(t).forEach((tensor3) => tf20.dispose(t[tensor3]));
busy = false;
return { data: segmentation3.data, canvas: mergedCanvas || segmentation3.canvas, alpha: segmentation3.alpha };
return { data, canvas: mergedCanvas || compositeCanvas, alpha: alphaCanvas };
}
// src/models.ts

View File

@ -34,6 +34,7 @@ export type Env = {
kernels: string[],
Canvas: undefined,
Image: undefined,
ImageData: undefined,
}
// eslint-disable-next-line import/no-mutable-exports
@ -69,6 +70,7 @@ export let env: Env = {
kernels: [],
Canvas: undefined,
Image: undefined,
ImageData: undefined,
};
export async function cpuInfo() {

View File

@ -297,7 +297,7 @@ export class Human {
* @param background?: {@link Input}
* @returns { data, canvas, alpha }
*/
async segmentation(input: Input, background?: Input): Promise<{ data: Uint8ClampedArray | null, canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
async segmentation(input: Input, background?: Input): Promise<{ data: number[], canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
return segmentation.process(input, background, this.config);
}
@ -441,20 +441,6 @@ export class Human {
this.performance.image = Math.trunc(now() - timeStamp);
this.analyze('Get Image:');
// segmentation is only run explicitly via human.segmentation() which calls segmentation.process()
/*
if (this.config.segmentation.enabled && process && img.tensor && img.canvas) {
this.analyze('Start Segmentation:');
this.state = 'detect:segmentation';
timeStamp = now();
const seg = await segmentation.predict(img, this.config);
img = { canvas: seg.canvas, tensor: seg.tensor };
elapsedTime = Math.trunc(now() - timeStamp);
if (elapsedTime > 0) this.performance.segmentation = elapsedTime;
this.analyze('End Segmentation:');
}
*/
if (!img.tensor) {
if (this.config.debug) log('could not convert input to tensor');
resolve({ error: 'could not convert input to tensor' });

View File

@ -30,7 +30,8 @@ export function canvas(width, height): HTMLCanvasElement | OffscreenCanvas {
}
} else {
// @ts-ignore // env.canvas is an external monkey-patch
c = (typeof env.Canvas !== 'undefined') ? new env.Canvas(width, height) : null;
if (typeof env.Canvas !== 'undefined') c = new env.Canvas(width, height);
else if (typeof globalThis.Canvas !== 'undefined') c = new globalThis.Canvas(width, height);
}
// if (!c) throw new Error('cannot create canvas');
return c;
@ -51,6 +52,7 @@ export function process(input: Input, config: Config): { tensor: Tensor | null,
!(input instanceof tf.Tensor)
&& !(typeof Image !== 'undefined' && input instanceof Image)
&& !(typeof env.Canvas !== 'undefined' && input instanceof env.Canvas)
&& !(typeof globalThis.Canvas !== 'undefined' && input instanceof globalThis.Canvas)
&& !(typeof ImageData !== 'undefined' && input instanceof ImageData)
&& !(typeof ImageBitmap !== 'undefined' && input instanceof ImageBitmap)
&& !(typeof HTMLImageElement !== 'undefined' && input instanceof HTMLImageElement)

View File

@ -23,61 +23,53 @@ export async function load(config: Config): Promise<GraphModel> {
return model;
}
export async function predict(input: { tensor: Tensor | null, canvas: OffscreenCanvas | HTMLCanvasElement | null }, config: Config)
: Promise<{ data: Uint8ClampedArray | null, canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
const width = input.tensor?.shape[2] || 0;
const height = input.tensor?.shape[1] || 0;
if (!input.tensor || !model || !model.inputs[0].shape) return { data: null, canvas: null, alpha: null };
const resizeInput = tf.image.resizeBilinear(input.tensor, [model.inputs[0].shape[1], model.inputs[0].shape[2]], false);
const norm = tf.div(resizeInput, 255);
const res = model.predict(norm) as Tensor;
// meet output: 1,256,256,1
// selfie output: 1,144,256,2
tf.dispose(resizeInput);
tf.dispose(norm);
export async function process(input: Input, background: Input | undefined, config: Config)
: Promise<{ data: Array<number>, canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
if (busy) return { data: [], canvas: null, alpha: null };
busy = true;
if (!model) await load(config);
const inputImage = image.process(input, config);
const width = inputImage.canvas?.width || 0;
const height = inputImage.canvas?.height || 0;
if (!inputImage.tensor) return { data: [], canvas: null, alpha: null };
const t: Record<string, Tensor> = {};
const squeeze = tf.squeeze(res, 0);
tf.dispose(res);
let dataT;
if (squeeze.shape[2] === 2) {
// model meet has two channels for fg and bg
const softmax = squeeze.softmax();
const [bg, fg] = tf.unstack(softmax, 2);
const expand = tf.expandDims(fg, 2);
const pad = tf.expandDims(expand, 0);
tf.dispose(softmax);
tf.dispose(bg);
tf.dispose(fg);
t.resize = tf.image.resizeBilinear(inputImage.tensor, [model.inputs[0].shape ? model.inputs[0].shape[1] : 0, model.inputs[0].shape ? model.inputs[0].shape[2] : 0], false);
tf.dispose(inputImage.tensor);
t.norm = tf.div(t.resize, 255);
t.res = model.predict(t.norm) as Tensor;
t.squeeze = tf.squeeze(t.res, 0); // meet.shape:[1,256,256,1], selfie.shape:[1,144,256,2]
if (t.squeeze.shape[2] === 2) {
t.softmax = tf.softmax(t.squeeze); // model meet has two channels for fg and bg
[t.bg, t.fg] = tf.unstack(t.softmax, 2);
t.expand = tf.expandDims(t.fg, 2);
t.pad = tf.expandDims(t.expand, 0);
t.crop = tf.image.cropAndResize(t.pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
// running sofmax before unstack creates 2x2 matrix so we only take upper-left quadrant
const crop = tf.image.cropAndResize(pad, [[0, 0, 0.5, 0.5]], [0], [width, height]);
// otherwise run softmax after unstack and use standard resize
// resizeOutput = tf.image.resizeBilinear(expand, [input.tensor?.shape[1], input.tensor?.shape[2]]);
dataT = tf.squeeze(crop, 0);
tf.dispose(crop);
tf.dispose(expand);
tf.dispose(pad);
} else { // model selfie has a single channel that we can use directly
dataT = tf.image.resizeBilinear(squeeze, [height, width]);
t.data = tf.squeeze(t.crop, 0);
} else {
t.data = tf.image.resizeBilinear(t.squeeze, [height, width]); // model selfie has a single channel that we can use directly
}
tf.dispose(squeeze);
const data = await dataT.dataSync();
const data = Array.from(await t.data.data());
if (env.node) {
tf.dispose(dataT);
if (env.node && !env.Canvas && (typeof ImageData === 'undefined')) {
if (config.debug) log('canvas support missing');
Object.keys(t).forEach((tensor) => tf.dispose(t[tensor]));
return { data, canvas: null, alpha: null }; // running in nodejs so return alpha array as-is
}
const alphaCanvas = image.canvas(width, height);
await tf.browser.toPixels(dataT, alphaCanvas);
tf.dispose(dataT);
await tf.browser.toPixels(t.data, alphaCanvas);
const alphaCtx = alphaCanvas.getContext('2d') as CanvasRenderingContext2D;
if (config.segmentation.blur && config.segmentation.blur > 0) alphaCtx.filter = `blur(${config.segmentation.blur}px)`; // use css filter for bluring, can be done with gaussian blur manually instead
const alphaData = alphaCtx.getImageData(0, 0, width, height);
// original canvas where only alpha shows
const compositeCanvas = image.canvas(width, height);
const compositeCtx = compositeCanvas.getContext('2d') as CanvasRenderingContext2D;
if (input.canvas) compositeCtx.drawImage(input.canvas, 0, 0);
if (inputImage.canvas) compositeCtx.drawImage(inputImage.canvas, 0, 0);
compositeCtx.globalCompositeOperation = 'darken'; // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation // best options are: darken, color-burn, multiply
if (config.segmentation.blur && config.segmentation.blur > 0) compositeCtx.filter = `blur(${config.segmentation.blur}px)`; // use css filter for bluring, can be done with gaussian blur manually instead
compositeCtx.drawImage(alphaCanvas, 0, 0);
@ -87,31 +79,18 @@ export async function predict(input: { tensor: Tensor | null, canvas: OffscreenC
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);
return { data, canvas: compositeCanvas, alpha: alphaCanvas };
}
export async function process(input: Input, background: Input | undefined, config: Config)
: Promise<{ data: Uint8ClampedArray | null, canvas: HTMLCanvasElement | OffscreenCanvas | null, alpha: HTMLCanvasElement | OffscreenCanvas | null }> {
if (busy) return { data: null, canvas: null, alpha: null };
busy = true;
if (!model) await load(config);
const inputImage = image.process(input, config);
const segmentation = await predict(inputImage, config);
tf.dispose(inputImage.tensor);
let mergedCanvas: HTMLCanvasElement | OffscreenCanvas | null = null;
if (background && segmentation.canvas) { // draw background with segmentation as overlay if background is present
mergedCanvas = image.canvas(inputImage.canvas?.width || 0, inputImage.canvas?.height || 0);
if (background && compositeCanvas) { // draw background with segmentation as overlay if background is present
mergedCanvas = image.canvas(width, height);
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';
ctxMerge.drawImage(compositeCanvas, 0, 0);
}
Object.keys(t).forEach((tensor) => tf.dispose(t[tensor]));
busy = false;
return { data: segmentation.data, canvas: mergedCanvas || segmentation.canvas, alpha: segmentation.alpha };
return { data, canvas: mergedCanvas || compositeCanvas, alpha: alphaCanvas };
}

View File

@ -1,24 +1,24 @@
2021-09-22 15:51:45 INFO:  @vladmandic/human version 2.2.2
2021-09-22 15:51:45 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.5.0
2021-09-22 15:51:45 INFO:  Application: {"name":"@vladmandic/human","version":"2.2.2"}
2021-09-22 15:51:45 INFO:  Environment: {"profile":"production","config":"build.json","tsconfig":true,"eslintrc":true,"git":true}
2021-09-22 15:51:45 INFO:  Toolchain: {"build":"0.5.3","esbuild":"0.13.0","typescript":"4.4.3","typedoc":"0.22.4","eslint":"7.32.0"}
2021-09-22 15:51:45 INFO:  Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
2021-09-22 15:51:45 STATE: Clean: {"locations":["dist/*","types/*","typedoc/*"]}
2021-09-22 15:51:45 STATE: Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":102,"outputBytes":1275}
2021-09-22 15:51:45 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":51,"inputBytes":497228,"outputBytes":418219}
2021-09-22 15:51:45 STATE: Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":1283}
2021-09-22 15:51:45 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":51,"inputBytes":497236,"outputBytes":418223}
2021-09-22 15:51:45 STATE: Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":149,"outputBytes":1350}
2021-09-22 15:51:45 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":51,"inputBytes":497303,"outputBytes":418295}
2021-09-22 15:51:45 STATE: Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1063,"outputBytes":1631}
2021-09-22 15:51:45 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":3088,"outputBytes":793}
2021-09-22 15:51:45 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":51,"inputBytes":496746,"outputBytes":419852}
2021-09-22 15:51:46 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":2377041}
2021-09-22 15:51:46 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":51,"inputBytes":2872994,"outputBytes":1415500}
2021-09-22 15:51:47 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":51,"inputBytes":2872994,"outputBytes":2624186}
2021-09-22 15:52:04 STATE: Typings: {"input":"src/human.ts","output":"types","files":96}
2021-09-22 15:52:10 STATE: TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":30,"generated":true}
2021-09-22 15:52:37 STATE: Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":84,"errors":0,"warnings":0}
2021-09-22 15:52:38 STATE: ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
2021-09-22 15:52:38 INFO:  Done...
2021-09-22 19:21:14 INFO:  @vladmandic/human version 2.2.2
2021-09-22 19:21:14 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.5.0
2021-09-22 19:21:14 INFO:  Application: {"name":"@vladmandic/human","version":"2.2.2"}
2021-09-22 19:21:14 INFO:  Environment: {"profile":"production","config":"build.json","tsconfig":true,"eslintrc":true,"git":true}
2021-09-22 19:21:14 INFO:  Toolchain: {"build":"0.5.3","esbuild":"0.13.0","typescript":"4.4.3","typedoc":"0.22.4","eslint":"7.32.0"}
2021-09-22 19:21:14 INFO:  Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
2021-09-22 19:21:14 STATE: Clean: {"locations":["dist/*","types/*","typedoc/*"]}
2021-09-22 19:21:14 STATE: Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":102,"outputBytes":1275}
2021-09-22 19:21:14 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":51,"inputBytes":496083,"outputBytes":418081}
2021-09-22 19:21:14 STATE: Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":1283}
2021-09-22 19:21:14 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":51,"inputBytes":496091,"outputBytes":418085}
2021-09-22 19:21:14 STATE: Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":149,"outputBytes":1350}
2021-09-22 19:21:14 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":51,"inputBytes":496158,"outputBytes":418157}
2021-09-22 19:21:14 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 19:21:14 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 19:21:14 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":51,"inputBytes":495601,"outputBytes":419606}
2021-09-22 19:21:15 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":2377041}
2021-09-22 19:21:15 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":51,"inputBytes":2871849,"outputBytes":1415684}
2021-09-22 19:21:15 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":51,"inputBytes":2871849,"outputBytes":2624079}
2021-09-22 19:21:32 STATE: Typings: {"input":"src/human.ts","output":"types","files":96}
2021-09-22 19:21:39 STATE: TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":30,"generated":true}
2021-09-22 19:22:06 STATE: Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":84,"errors":0,"warnings":0}
2021-09-22 19:22:07 STATE: ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
2021-09-22 19:22:07 INFO:  Done...

View File

@ -327,7 +327,8 @@ async function test(Human, inputConfig) {
]);
// test monkey-patch
human.env.Canvas = canvasJS.Canvas; // monkey-patch human to use external canvas library
globalThis.Canvas = canvasJS.Canvas; // monkey-patch to use external canvas library
globalThis.ImageData = canvasJS.ImageData; // monkey-patch to use external canvas library
const inputImage = await canvasJS.loadImage('samples/ai-face.jpg'); // load image using canvas library
const inputCanvas = new canvasJS.Canvas(inputImage.width, inputImage.height); // create canvas
const ctx = inputCanvas.getContext('2d');
@ -338,7 +339,7 @@ async function test(Human, inputConfig) {
// test segmentation
res = await human.segmentation(inputCanvas, inputCanvas);
if (!res || !res.data) log('error', 'failed: segmentation', res);
if (!res || !res.data || !res.canvas) log('error', 'failed: segmentation');
else log('state', 'passed: segmentation', [res.data.length]);
human.env.Canvas = undefined;

View File

@ -5,9 +5,9 @@ const Human = require('../dist/human.node-wasm.js');
const test = require('./test-main.js').test;
// @ts-ignore
Human.env.Canvas = Canvas;
Human.env.Canvas = Canvas; // requires monkey-patch as wasm does not have tf.browser namespace
// @ts-ignore
Human.env.Image = Image;
Human.env.Image = Image; // requires monkey-patch as wasm does not have tf.browser namespace
const config = {
// modelBasePath: 'http://localhost:10030/models/',

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -99,7 +99,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>result: <a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a><span class="tsd-signature-symbol"> = ...</span></h5></li></ul><h4 class="tsd-returns-title">Returns <a href="../interfaces/Result.html" class="tsd-signature-type" data-tsd-kind="Interface">Result</a></h4><div><p>result: <a href="../interfaces/Result.html">Result</a></p>
</div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="reset" class="tsd-anchor"></a><h3>reset</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">reset<span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">void</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L258">human.ts:258</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Reset configuration to default values</p>
</div></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="segmentation" class="tsd-anchor"></a><h3>segmentation</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">segmentation<span class="tsd-signature-symbol">(</span>input<span class="tsd-signature-symbol">: </span><a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a>, background<span class="tsd-signature-symbol">?: </span><a href="../index.html#Input" class="tsd-signature-type" data-tsd-kind="Type alias">Input</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-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#L300">human.ts:300</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">number</span><span class="tsd-signature-symbol">[]</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#L300">human.ts:300</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Segmentation method takes any input and returns processed canvas with body segmentation</p>
<ul>
<li>Optional parameter background is used to fill the background with specific input</li>
@ -111,7 +111,7 @@ Interpolation is based on time since last known result so can be called independ
<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">
</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">number</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol">&gt;</span></h4><div></div></li></ul></section><section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class"><a name="similarity" class="tsd-anchor"></a><h3>similarity</h3><ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class"><li class="tsd-signature tsd-kind-icon">similarity<span class="tsd-signature-symbol">(</span>embedding1<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span>, embedding2<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></li></ul><ul class="tsd-descriptions"><li class="tsd-description"><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/human.ts#L283">human.ts:283</a></li></ul></aside><div class="tsd-comment tsd-typography"><div class="lead">
<p>Simmilarity method calculates simmilarity between two provided face descriptors (face embeddings)</p>
<ul>
<li>Calculation is based on normalized Minkowski distance between two descriptors</li>

File diff suppressed because one or more lines are too long

1
types/src/env.d.ts vendored
View File

@ -30,6 +30,7 @@ export declare type Env = {
kernels: string[];
Canvas: undefined;
Image: undefined;
ImageData: undefined;
};
export declare let env: Env;
export declare function cpuInfo(): Promise<void>;

View File

@ -1 +1 @@
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/env.ts"],"names":[],"mappings":"AAIA,oBAAY,GAAG,GAAG;IAChB,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC;IAC7B,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAC5B,QAAQ,EAAE,SAAS,GAAG,MAAM,CAAC;IAC7B,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE;QACJ,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC;KAC7B,CAAC;IACF,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;IAC/B,IAAI,EAAE;QACJ,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;QAC/B,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC;QAC7B,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;QAC1B,WAAW,EAAE,SAAS,GAAG,OAAO,CAAC;KAClC,CAAC;IACF,KAAK,EAAE;QACL,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;QAC/B,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC;QAC7B,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC;QAC5B,QAAQ,EAAE,SAAS,GAAG,MAAM,CAAC;KAC9B,CAAC;IACF,MAAM,EAAE;QACN,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;QAC/B,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC;QAC7B,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC;KAC7B,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;CAClB,CAAA;AAGD,eAAO,IAAI,GAAG,EAAE,GAgCf,CAAC;AAEF,wBAAsB,OAAO,kBAmB5B;AAED,wBAAsB,WAAW,kBA8BhC;AAED,wBAAsB,GAAG,kBA2BxB;AAED,wBAAsB,GAAG,CAAC,GAAG,KAAA,iBAE5B"}
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/env.ts"],"names":[],"mappings":"AAIA,oBAAY,GAAG,GAAG;IAChB,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC;IAC7B,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAC5B,QAAQ,EAAE,SAAS,GAAG,MAAM,CAAC;IAC7B,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE;QACJ,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC;KAC7B,CAAC;IACF,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;IAC/B,IAAI,EAAE;QACJ,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;QAC/B,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC;QAC7B,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;QAC1B,WAAW,EAAE,SAAS,GAAG,OAAO,CAAC;KAClC,CAAC;IACF,KAAK,EAAE;QACL,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;QAC/B,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC;QAC7B,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC;QAC5B,QAAQ,EAAE,SAAS,GAAG,MAAM,CAAC;KAC9B,CAAC;IACF,MAAM,EAAE;QACN,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;QAC/B,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC;QAC7B,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC;KAC7B,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;CACtB,CAAA;AAGD,eAAO,IAAI,GAAG,EAAE,GAiCf,CAAC;AAEF,wBAAsB,OAAO,kBAmB5B;AAED,wBAAsB,WAAW,kBA8BhC;AAED,wBAAsB,GAAG,kBA2BxB;AAED,wBAAsB,GAAG,CAAC,GAAG,KAAA,iBAE5B"}

View File

@ -182,7 +182,7 @@ export declare class Human {
* @returns { data, canvas, alpha }
*/
segmentation(input: Input, background?: Input): Promise<{
data: Uint8ClampedArray | null;
data: number[];
canvas: HTMLCanvasElement | OffscreenCanvas | null;
alpha: HTMLCanvasElement | OffscreenCanvas | null;
}>;

View File

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

View File

@ -1 +1 @@
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/image/image.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAG7B,aAAK,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,eAAe,GAAG,OAAO,KAAK,GAAG,OAAO,GAAG,CAAC,MAAM,CAAC;AAShL,wBAAgB,MAAM,CAAC,KAAK,KAAA,EAAE,MAAM,KAAA,GAAG,iBAAiB,GAAG,eAAe,CAgBzE;AAKD,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CAAA;CAAE,CAqLnI;AAID,wBAAsB,IAAI,CAAC,MAAM,KAAA,EAAE,KAAK,EAAE,MAAM,oBA2B/C"}
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/image/image.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAG7B,aAAK,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,eAAe,GAAG,OAAO,KAAK,GAAG,OAAO,GAAG,CAAC,MAAM,CAAC;AAShL,wBAAgB,MAAM,CAAC,KAAK,KAAA,EAAE,MAAM,KAAA,GAAG,iBAAiB,GAAG,eAAe,CAiBzE;AAKD,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CAAA;CAAE,CAsLnI;AAID,wBAAsB,IAAI,CAAC,MAAM,KAAA,EAAE,KAAK,EAAE,MAAM,oBA2B/C"}

View File

@ -5,16 +5,8 @@ import type { GraphModel, Tensor } from '../tfjs/types';
import type { Config } from '../config';
declare type Input = Tensor | typeof Image | ImageData | ImageBitmap | HTMLImageElement | HTMLMediaElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas;
export declare function load(config: Config): Promise<GraphModel>;
export declare function predict(input: {
tensor: Tensor | null;
canvas: OffscreenCanvas | HTMLCanvasElement | null;
}, config: Config): Promise<{
data: Uint8ClampedArray | null;
canvas: HTMLCanvasElement | OffscreenCanvas | null;
alpha: HTMLCanvasElement | OffscreenCanvas | null;
}>;
export declare function process(input: Input, background: Input | undefined, config: Config): Promise<{
data: Uint8ClampedArray | null;
data: Array<number>;
canvas: HTMLCanvasElement | OffscreenCanvas | null;
alpha: HTMLCanvasElement | OffscreenCanvas | null;
}>;

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,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"}
{"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,KAAK,EAAE,UAAU,EAAE,KAAK,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GACvF,OAAO,CAAC;IAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAA;CAAE,CAAC,CAqExI"}