mirror of https://github.com/vladmandic/human
add webgu checks
parent
5022c416be
commit
c97eb67c5b
|
@ -11,6 +11,8 @@ Repository: **<git+https://github.com/vladmandic/human.git>**
|
||||||
|
|
||||||
### **HEAD -> main** 2021/08/14 mandic00@live.com
|
### **HEAD -> main** 2021/08/14 mandic00@live.com
|
||||||
|
|
||||||
|
- experimental webgpu support
|
||||||
|
- add experimental webgu demo
|
||||||
- add backend initialization checks
|
- add backend initialization checks
|
||||||
- complete async work
|
- complete async work
|
||||||
- list detect cameras
|
- list detect cameras
|
||||||
|
|
|
@ -6,25 +6,33 @@
|
||||||
*/
|
*/
|
||||||
// @ts-nocheck // typescript checks disabled as this is pure javascript
|
// @ts-nocheck // typescript checks disabled as this is pure javascript
|
||||||
|
|
||||||
import '../../node_modules/@tensorflow/tfjs-core/dist/tf-core.es2017.js';
|
|
||||||
import '../../assets/tf-backend-webgpu.es2017.js';
|
|
||||||
import Human from '../../dist/human.esm.js';
|
import Human from '../../dist/human.esm.js';
|
||||||
|
import GLBench from '../helpers/gl-bench.js';
|
||||||
|
|
||||||
let human;
|
const workerJS = './worker.js';
|
||||||
let canvas;
|
|
||||||
let video;
|
|
||||||
let result;
|
|
||||||
|
|
||||||
const myConfig = {
|
const backend = 'webgpu';
|
||||||
backend: 'webgl',
|
|
||||||
async: true,
|
const config = {
|
||||||
|
main: { // processes input and runs gesture analysis
|
||||||
warmup: 'none',
|
warmup: 'none',
|
||||||
modelBasePath: '../../models',
|
backend,
|
||||||
cacheSensitivity: 0,
|
modelBasePath: '../../models/',
|
||||||
filter: {
|
async: false,
|
||||||
enabled: true,
|
filter: { enabled: true },
|
||||||
flip: false,
|
face: { enabled: false },
|
||||||
|
object: { enabled: false },
|
||||||
|
gesture: { enabled: true },
|
||||||
|
hand: { enabled: false },
|
||||||
|
body: { enabled: false },
|
||||||
|
segmentation: { enabled: false },
|
||||||
},
|
},
|
||||||
|
face: { // runs all face models
|
||||||
|
warmup: 'none',
|
||||||
|
backend,
|
||||||
|
modelBasePath: '../../models/',
|
||||||
|
async: false,
|
||||||
|
filter: { enabled: false },
|
||||||
face: { enabled: true,
|
face: { enabled: true,
|
||||||
detector: { return: false, rotation: false },
|
detector: { return: false, rotation: false },
|
||||||
mesh: { enabled: true },
|
mesh: { enabled: true },
|
||||||
|
@ -33,13 +41,96 @@ const myConfig = {
|
||||||
emotion: { enabled: false },
|
emotion: { enabled: false },
|
||||||
},
|
},
|
||||||
object: { enabled: false },
|
object: { enabled: false },
|
||||||
gesture: { enabled: true },
|
gesture: { enabled: false },
|
||||||
hand: { enabled: true, rotation: false },
|
hand: { enabled: false },
|
||||||
|
body: { enabled: false },
|
||||||
|
segmentation: { enabled: false },
|
||||||
|
},
|
||||||
|
body: { // runs body model
|
||||||
|
warmup: 'none',
|
||||||
|
backend,
|
||||||
|
modelBasePath: '../../models/',
|
||||||
|
async: false,
|
||||||
|
filter: { enabled: false },
|
||||||
|
face: { enabled: false },
|
||||||
|
object: { enabled: false },
|
||||||
|
gesture: { enabled: false },
|
||||||
|
hand: { enabled: false },
|
||||||
body: { enabled: true },
|
body: { enabled: true },
|
||||||
segmentation: { enabled: false },
|
segmentation: { enabled: false },
|
||||||
|
},
|
||||||
|
hand: { // runs hands model
|
||||||
|
warmup: 'none',
|
||||||
|
backend,
|
||||||
|
modelBasePath: '../../models/',
|
||||||
|
async: false,
|
||||||
|
filter: { enabled: false },
|
||||||
|
face: { enabled: false },
|
||||||
|
object: { enabled: false },
|
||||||
|
gesture: { enabled: false },
|
||||||
|
hand: { enabled: true, rotation: false },
|
||||||
|
body: { enabled: false },
|
||||||
|
segmentation: { enabled: false },
|
||||||
|
},
|
||||||
|
object: { // runs object model
|
||||||
|
warmup: 'none',
|
||||||
|
backend,
|
||||||
|
modelBasePath: '../../models/',
|
||||||
|
async: false,
|
||||||
|
filter: { enabled: false },
|
||||||
|
face: { enabled: false },
|
||||||
|
object: { enabled: false },
|
||||||
|
gesture: { enabled: false },
|
||||||
|
hand: { enabled: false },
|
||||||
|
body: { enabled: false },
|
||||||
|
segmentation: { enabled: false },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let time = 0;
|
let human;
|
||||||
|
let canvas;
|
||||||
|
let video;
|
||||||
|
let bench;
|
||||||
|
|
||||||
|
const busy = {
|
||||||
|
face: false,
|
||||||
|
hand: false,
|
||||||
|
body: false,
|
||||||
|
object: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const workers = {
|
||||||
|
face: null,
|
||||||
|
body: null,
|
||||||
|
hand: null,
|
||||||
|
object: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const time = {
|
||||||
|
main: 0,
|
||||||
|
draw: 0,
|
||||||
|
face: '[warmup]',
|
||||||
|
body: '[warmup]',
|
||||||
|
hand: '[warmup]',
|
||||||
|
object: '[warmup]',
|
||||||
|
};
|
||||||
|
|
||||||
|
const start = {
|
||||||
|
main: 0,
|
||||||
|
draw: 0,
|
||||||
|
face: 0,
|
||||||
|
body: 0,
|
||||||
|
hand: 0,
|
||||||
|
object: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = { // initialize empty result object which will be partially filled with results from each thread
|
||||||
|
performance: {},
|
||||||
|
hand: [],
|
||||||
|
body: [],
|
||||||
|
face: [],
|
||||||
|
object: [],
|
||||||
|
};
|
||||||
|
|
||||||
function log(...msg) {
|
function log(...msg) {
|
||||||
const dt = new Date();
|
const dt = new Date();
|
||||||
|
@ -49,18 +140,57 @@ function log(...msg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function drawResults() {
|
async function drawResults() {
|
||||||
|
start.draw = performance.now();
|
||||||
const interpolated = human.next(result);
|
const interpolated = human.next(result);
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
||||||
await human.draw.all(canvas, interpolated);
|
await human.draw.all(canvas, interpolated);
|
||||||
document.getElementById('log').innerText = `Human: version ${human.version} | ${Math.trunc(time)} ms | FPS: ${Math.trunc(10000 / time) / 10}`;
|
time.draw = Math.round(1 + performance.now() - start.draw);
|
||||||
|
const fps = Math.round(10 * 1000 / time.main) / 10;
|
||||||
|
const draw = Math.round(10 * 1000 / time.draw) / 10;
|
||||||
|
document.getElementById('log').innerText = `Human: version ${human.version} | Performance: Main ${time.main}ms Face: ${time.face}ms Body: ${time.body}ms Hand: ${time.hand}ms Object ${time.object}ms | FPS: ${fps} / ${draw}`;
|
||||||
requestAnimationFrame(drawResults);
|
requestAnimationFrame(drawResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function receiveMessage(msg) {
|
||||||
|
result[msg.data.type] = msg.data.result;
|
||||||
|
busy[msg.data.type] = false;
|
||||||
|
time[msg.data.type] = Math.round(performance.now() - start[msg.data.type]);
|
||||||
|
}
|
||||||
|
|
||||||
async function runDetection() {
|
async function runDetection() {
|
||||||
const t0 = performance.now();
|
start.main = performance.now();
|
||||||
result = await human.detect(video);
|
if (!bench) {
|
||||||
time = performance.now() - t0;
|
bench = new GLBench(null, { trackGPU: false, chartHz: 20, chartLen: 20 });
|
||||||
|
bench.begin();
|
||||||
|
}
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
// const image = await human.image(video);
|
||||||
|
// ctx.drawImage(image.canvas, 0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
||||||
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
|
if (!busy.face) {
|
||||||
|
busy.face = true;
|
||||||
|
start.face = performance.now();
|
||||||
|
workers.face.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.face, type: 'face' }, [imageData.data.buffer.slice(0)]);
|
||||||
|
}
|
||||||
|
if (!busy.body) {
|
||||||
|
busy.body = true;
|
||||||
|
start.body = performance.now();
|
||||||
|
workers.body.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.body, type: 'body' }, [imageData.data.buffer.slice(0)]);
|
||||||
|
}
|
||||||
|
if (!busy.hand) {
|
||||||
|
busy.hand = true;
|
||||||
|
start.hand = performance.now();
|
||||||
|
workers.hand.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.hand, type: 'hand' }, [imageData.data.buffer.slice(0)]);
|
||||||
|
}
|
||||||
|
if (!busy.object) {
|
||||||
|
busy.object = true;
|
||||||
|
start.object = performance.now();
|
||||||
|
workers.object.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.object, type: 'object' }, [imageData.data.buffer.slice(0)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
time.main = Math.round(performance.now() - start.main);
|
||||||
|
|
||||||
|
bench.nextFrame();
|
||||||
requestAnimationFrame(runDetection);
|
requestAnimationFrame(runDetection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +210,7 @@ async function setupCamera() {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// enumerate devices for diag purposes
|
// enumerate devices for diag purposes
|
||||||
navigator.mediaDevices.enumerateDevices().then((devices) => log('enumerated input devices:', devices));
|
navigator.mediaDevices.enumerateDevices().then((devices) => log('enumerated devices:', devices));
|
||||||
log('camera constraints', constraints);
|
log('camera constraints', constraints);
|
||||||
try {
|
try {
|
||||||
stream = await navigator.mediaDevices.getUserMedia(constraints);
|
stream = await navigator.mediaDevices.getUserMedia(constraints);
|
||||||
|
@ -109,9 +239,35 @@ async function setupCamera() {
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function startWorkers() {
|
||||||
|
if (!workers.face) workers.face = new Worker(workerJS);
|
||||||
|
if (!workers.body) workers.body = new Worker(workerJS);
|
||||||
|
if (!workers.hand) workers.hand = new Worker(workerJS);
|
||||||
|
if (!workers.object) workers.object = new Worker(workerJS);
|
||||||
|
workers.face.onmessage = receiveMessage;
|
||||||
|
workers.body.onmessage = receiveMessage;
|
||||||
|
workers.hand.onmessage = receiveMessage;
|
||||||
|
workers.object.onmessage = receiveMessage;
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
human = new Human(myConfig);
|
window.addEventListener('unhandledrejection', (evt) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(evt.reason || evt);
|
||||||
|
document.getElementById('log').innerHTML = evt.reason.message || evt.reason || evt;
|
||||||
|
status('exception error');
|
||||||
|
evt.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof Worker === 'undefined' || typeof OffscreenCanvas === 'undefined') {
|
||||||
|
status('workers are not supported');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
human = new Human(config.main);
|
||||||
document.getElementById('log').innerText = `Human: version ${human.version}`;
|
document.getElementById('log').innerText = `Human: version ${human.version}`;
|
||||||
|
|
||||||
|
await startWorkers();
|
||||||
await setupCamera();
|
await setupCamera();
|
||||||
runDetection();
|
runDetection();
|
||||||
drawResults();
|
drawResults();
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// load Human using IIFE script as Chome Mobile does not support Modules as Workers
|
||||||
|
|
||||||
|
// import Human from '../dist/human.esm.js';
|
||||||
|
self.importScripts('../../dist/human.js');
|
||||||
|
self.importScripts('../../node_modules/@tensorflow/tfjs-core/dist/tf-core.es2017.js');
|
||||||
|
self.importScripts('../../assets/tf-backend-webgpu.es2017.js');
|
||||||
|
|
||||||
|
let human;
|
||||||
|
|
||||||
|
onmessage = async (msg) => {
|
||||||
|
// received from index.js using:
|
||||||
|
// worker.postMessage({ image: image.data.buffer, width: canvas.width, height: canvas.height, config }, [image.data.buffer]);
|
||||||
|
|
||||||
|
// @ts-ignore // Human is registered as global namespace using IIFE script
|
||||||
|
// eslint-disable-next-line no-undef, new-cap
|
||||||
|
if (!human) human = new Human.default(msg.data.config);
|
||||||
|
const image = new ImageData(new Uint8ClampedArray(msg.data.image), msg.data.width, msg.data.height);
|
||||||
|
let result = {};
|
||||||
|
result = await human.detect(image, msg.data.config);
|
||||||
|
// @ts-ignore tslint wrong type matching for worker
|
||||||
|
postMessage({ result: result[msg.data.type], type: msg.data.type });
|
||||||
|
};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -11395,18 +11395,29 @@ var Human = class {
|
||||||
const timeStamp = now();
|
const timeStamp = now();
|
||||||
this.state = "backend";
|
this.state = "backend";
|
||||||
if (this.config.backend && this.config.backend.length > 0) {
|
if (this.config.backend && this.config.backend.length > 0) {
|
||||||
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug)
|
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug) {
|
||||||
log("running inside web worker");
|
log("running inside web worker");
|
||||||
|
}
|
||||||
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "tensorflow") {
|
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "tensorflow") {
|
||||||
if (this.config.debug)
|
|
||||||
log("override: backend set to tensorflow while running in browser");
|
log("override: backend set to tensorflow while running in browser");
|
||||||
this.config.backend = "humangl";
|
this.config.backend = "humangl";
|
||||||
}
|
}
|
||||||
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === "webgl" || this.config.backend === "humangl")) {
|
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === "webgl" || this.config.backend === "humangl")) {
|
||||||
if (this.config.debug)
|
|
||||||
log("override: backend set to webgl while running in nodejs");
|
log("override: backend set to webgl while running in nodejs");
|
||||||
this.config.backend = "tensorflow";
|
this.config.backend = "tensorflow";
|
||||||
}
|
}
|
||||||
|
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "webgpu") {
|
||||||
|
if (typeof navigator === "undefined" || typeof navigator["gpu"] === "undefined") {
|
||||||
|
log("override: backend set to webgpu but browser does not support webgpu");
|
||||||
|
this.config.backend = "humangl";
|
||||||
|
} else {
|
||||||
|
const adapter = await navigator["gpu"].requestAdapter();
|
||||||
|
if (this.config.debug)
|
||||||
|
log("enumerated webgpu adapter:", adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.config.backend === "humangl")
|
||||||
|
register();
|
||||||
const available = Object.keys(this.tf.engine().registryFactory);
|
const available = Object.keys(this.tf.engine().registryFactory);
|
||||||
if (this.config.debug)
|
if (this.config.debug)
|
||||||
log("available backends:", available);
|
log("available backends:", available);
|
||||||
|
@ -11431,15 +11442,12 @@ var Human = class {
|
||||||
if (this.config.debug && !simd)
|
if (this.config.debug && !simd)
|
||||||
log("warning: wasm simd support is not enabled");
|
log("warning: wasm simd support is not enabled");
|
||||||
}
|
}
|
||||||
if (this.config.backend === "humangl")
|
|
||||||
register();
|
|
||||||
try {
|
try {
|
||||||
await this.tf.setBackend(this.config.backend);
|
await this.tf.setBackend(this.config.backend);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log("error: cannot set backend:", this.config.backend, err);
|
log("error: cannot set backend:", this.config.backend, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.tf.enableProdMode();
|
|
||||||
if (this.tf.getBackend() === "webgl" || this.tf.getBackend() === "humangl") {
|
if (this.tf.getBackend() === "webgl" || this.tf.getBackend() === "humangl") {
|
||||||
this.tf.ENV.set("CHECK_COMPUTATION_FOR_ERRORS", false);
|
this.tf.ENV.set("CHECK_COMPUTATION_FOR_ERRORS", false);
|
||||||
this.tf.ENV.set("WEBGL_CPU_FORWARD", true);
|
this.tf.ENV.set("WEBGL_CPU_FORWARD", true);
|
||||||
|
@ -11453,6 +11461,7 @@ var Human = class {
|
||||||
if (this.config.debug)
|
if (this.config.debug)
|
||||||
log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
|
log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
|
||||||
}
|
}
|
||||||
|
this.tf.enableProdMode();
|
||||||
await this.tf.ready();
|
await this.tf.ready();
|
||||||
this.performance.backend = Math.trunc(now() - timeStamp);
|
this.performance.backend = Math.trunc(now() - timeStamp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11396,18 +11396,29 @@ var Human = class {
|
||||||
const timeStamp = now();
|
const timeStamp = now();
|
||||||
this.state = "backend";
|
this.state = "backend";
|
||||||
if (this.config.backend && this.config.backend.length > 0) {
|
if (this.config.backend && this.config.backend.length > 0) {
|
||||||
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug)
|
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug) {
|
||||||
log("running inside web worker");
|
log("running inside web worker");
|
||||||
|
}
|
||||||
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "tensorflow") {
|
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "tensorflow") {
|
||||||
if (this.config.debug)
|
|
||||||
log("override: backend set to tensorflow while running in browser");
|
log("override: backend set to tensorflow while running in browser");
|
||||||
this.config.backend = "humangl";
|
this.config.backend = "humangl";
|
||||||
}
|
}
|
||||||
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === "webgl" || this.config.backend === "humangl")) {
|
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === "webgl" || this.config.backend === "humangl")) {
|
||||||
if (this.config.debug)
|
|
||||||
log("override: backend set to webgl while running in nodejs");
|
log("override: backend set to webgl while running in nodejs");
|
||||||
this.config.backend = "tensorflow";
|
this.config.backend = "tensorflow";
|
||||||
}
|
}
|
||||||
|
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "webgpu") {
|
||||||
|
if (typeof navigator === "undefined" || typeof navigator["gpu"] === "undefined") {
|
||||||
|
log("override: backend set to webgpu but browser does not support webgpu");
|
||||||
|
this.config.backend = "humangl";
|
||||||
|
} else {
|
||||||
|
const adapter = await navigator["gpu"].requestAdapter();
|
||||||
|
if (this.config.debug)
|
||||||
|
log("enumerated webgpu adapter:", adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.config.backend === "humangl")
|
||||||
|
register();
|
||||||
const available = Object.keys(this.tf.engine().registryFactory);
|
const available = Object.keys(this.tf.engine().registryFactory);
|
||||||
if (this.config.debug)
|
if (this.config.debug)
|
||||||
log("available backends:", available);
|
log("available backends:", available);
|
||||||
|
@ -11432,15 +11443,12 @@ var Human = class {
|
||||||
if (this.config.debug && !simd)
|
if (this.config.debug && !simd)
|
||||||
log("warning: wasm simd support is not enabled");
|
log("warning: wasm simd support is not enabled");
|
||||||
}
|
}
|
||||||
if (this.config.backend === "humangl")
|
|
||||||
register();
|
|
||||||
try {
|
try {
|
||||||
await this.tf.setBackend(this.config.backend);
|
await this.tf.setBackend(this.config.backend);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log("error: cannot set backend:", this.config.backend, err);
|
log("error: cannot set backend:", this.config.backend, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.tf.enableProdMode();
|
|
||||||
if (this.tf.getBackend() === "webgl" || this.tf.getBackend() === "humangl") {
|
if (this.tf.getBackend() === "webgl" || this.tf.getBackend() === "humangl") {
|
||||||
this.tf.ENV.set("CHECK_COMPUTATION_FOR_ERRORS", false);
|
this.tf.ENV.set("CHECK_COMPUTATION_FOR_ERRORS", false);
|
||||||
this.tf.ENV.set("WEBGL_CPU_FORWARD", true);
|
this.tf.ENV.set("WEBGL_CPU_FORWARD", true);
|
||||||
|
@ -11454,6 +11462,7 @@ var Human = class {
|
||||||
if (this.config.debug)
|
if (this.config.debug)
|
||||||
log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
|
log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
|
||||||
}
|
}
|
||||||
|
this.tf.enableProdMode();
|
||||||
await this.tf.ready();
|
await this.tf.ready();
|
||||||
this.performance.backend = Math.trunc(now() - timeStamp);
|
this.performance.backend = Math.trunc(now() - timeStamp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11395,18 +11395,29 @@ var Human = class {
|
||||||
const timeStamp = now();
|
const timeStamp = now();
|
||||||
this.state = "backend";
|
this.state = "backend";
|
||||||
if (this.config.backend && this.config.backend.length > 0) {
|
if (this.config.backend && this.config.backend.length > 0) {
|
||||||
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug)
|
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug) {
|
||||||
log("running inside web worker");
|
log("running inside web worker");
|
||||||
|
}
|
||||||
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "tensorflow") {
|
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "tensorflow") {
|
||||||
if (this.config.debug)
|
|
||||||
log("override: backend set to tensorflow while running in browser");
|
log("override: backend set to tensorflow while running in browser");
|
||||||
this.config.backend = "humangl";
|
this.config.backend = "humangl";
|
||||||
}
|
}
|
||||||
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === "webgl" || this.config.backend === "humangl")) {
|
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === "webgl" || this.config.backend === "humangl")) {
|
||||||
if (this.config.debug)
|
|
||||||
log("override: backend set to webgl while running in nodejs");
|
log("override: backend set to webgl while running in nodejs");
|
||||||
this.config.backend = "tensorflow";
|
this.config.backend = "tensorflow";
|
||||||
}
|
}
|
||||||
|
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "webgpu") {
|
||||||
|
if (typeof navigator === "undefined" || typeof navigator["gpu"] === "undefined") {
|
||||||
|
log("override: backend set to webgpu but browser does not support webgpu");
|
||||||
|
this.config.backend = "humangl";
|
||||||
|
} else {
|
||||||
|
const adapter = await navigator["gpu"].requestAdapter();
|
||||||
|
if (this.config.debug)
|
||||||
|
log("enumerated webgpu adapter:", adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.config.backend === "humangl")
|
||||||
|
register();
|
||||||
const available = Object.keys(this.tf.engine().registryFactory);
|
const available = Object.keys(this.tf.engine().registryFactory);
|
||||||
if (this.config.debug)
|
if (this.config.debug)
|
||||||
log("available backends:", available);
|
log("available backends:", available);
|
||||||
|
@ -11431,15 +11442,12 @@ var Human = class {
|
||||||
if (this.config.debug && !simd)
|
if (this.config.debug && !simd)
|
||||||
log("warning: wasm simd support is not enabled");
|
log("warning: wasm simd support is not enabled");
|
||||||
}
|
}
|
||||||
if (this.config.backend === "humangl")
|
|
||||||
register();
|
|
||||||
try {
|
try {
|
||||||
await this.tf.setBackend(this.config.backend);
|
await this.tf.setBackend(this.config.backend);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log("error: cannot set backend:", this.config.backend, err);
|
log("error: cannot set backend:", this.config.backend, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.tf.enableProdMode();
|
|
||||||
if (this.tf.getBackend() === "webgl" || this.tf.getBackend() === "humangl") {
|
if (this.tf.getBackend() === "webgl" || this.tf.getBackend() === "humangl") {
|
||||||
this.tf.ENV.set("CHECK_COMPUTATION_FOR_ERRORS", false);
|
this.tf.ENV.set("CHECK_COMPUTATION_FOR_ERRORS", false);
|
||||||
this.tf.ENV.set("WEBGL_CPU_FORWARD", true);
|
this.tf.ENV.set("WEBGL_CPU_FORWARD", true);
|
||||||
|
@ -11453,6 +11461,7 @@ var Human = class {
|
||||||
if (this.config.debug)
|
if (this.config.debug)
|
||||||
log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
|
log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
|
||||||
}
|
}
|
||||||
|
this.tf.enableProdMode();
|
||||||
await this.tf.ready();
|
await this.tf.ready();
|
||||||
this.performance.backend = Math.trunc(now() - timeStamp);
|
this.performance.backend = Math.trunc(now() - timeStamp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
2021-08-14 17:59:16 [36mINFO: [39m @vladmandic/human version 2.1.3
|
2021-08-15 08:08:32 [36mINFO: [39m @vladmandic/human version 2.1.3
|
||||||
2021-08-14 17:59:16 [36mINFO: [39m User: vlado Platform: linux Arch: x64 Node: v16.5.0
|
2021-08-15 08:08:32 [36mINFO: [39m User: vlado Platform: linux Arch: x64 Node: v16.5.0
|
||||||
2021-08-14 17:59:16 [36mINFO: [39m Toolchain: {"tfjs":"3.8.0","esbuild":"0.12.20","typescript":"4.3.5","typedoc":"0.21.5","eslint":"7.32.0"}
|
2021-08-15 08:08:32 [36mINFO: [39m Toolchain: {"tfjs":"3.8.0","esbuild":"0.12.20","typescript":"4.3.5","typedoc":"0.21.5","eslint":"7.32.0"}
|
||||||
2021-08-14 17:59:16 [36mINFO: [39m Clean: ["dist/*","types/*","typedoc/*"]
|
2021-08-15 08:08:32 [36mINFO: [39m Clean: ["dist/*","types/*","typedoc/*"]
|
||||||
2021-08-14 17:59:16 [36mINFO: [39m Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
|
2021-08-15 08:08:32 [36mINFO: [39m Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
|
||||||
2021-08-14 17:59:16 [35mSTATE:[39m target: node type: tfjs: {"imports":1,"importBytes":102,"outputBytes":1303,"outputFiles":"dist/tfjs.esm.js"}
|
2021-08-15 08:08:32 [35mSTATE:[39m target: node type: tfjs: {"imports":1,"importBytes":102,"outputBytes":1303,"outputFiles":"dist/tfjs.esm.js"}
|
||||||
2021-08-14 17:59:16 [35mSTATE:[39m target: node type: node: {"imports":42,"importBytes":437259,"outputBytes":379053,"outputFiles":"dist/human.node.js"}
|
2021-08-15 08:08:32 [35mSTATE:[39m target: node type: node: {"imports":42,"importBytes":437903,"outputBytes":379522,"outputFiles":"dist/human.node.js"}
|
||||||
2021-08-14 17:59:16 [35mSTATE:[39m target: nodeGPU type: tfjs: {"imports":1,"importBytes":110,"outputBytes":1311,"outputFiles":"dist/tfjs.esm.js"}
|
2021-08-15 08:08:32 [35mSTATE:[39m target: nodeGPU type: tfjs: {"imports":1,"importBytes":110,"outputBytes":1311,"outputFiles":"dist/tfjs.esm.js"}
|
||||||
2021-08-14 17:59:16 [35mSTATE:[39m target: nodeGPU type: node: {"imports":42,"importBytes":437267,"outputBytes":379057,"outputFiles":"dist/human.node-gpu.js"}
|
2021-08-15 08:08:32 [35mSTATE:[39m target: nodeGPU type: node: {"imports":42,"importBytes":437911,"outputBytes":379526,"outputFiles":"dist/human.node-gpu.js"}
|
||||||
2021-08-14 17:59:16 [35mSTATE:[39m target: nodeWASM type: tfjs: {"imports":1,"importBytes":149,"outputBytes":1378,"outputFiles":"dist/tfjs.esm.js"}
|
2021-08-15 08:08:32 [35mSTATE:[39m target: nodeWASM type: tfjs: {"imports":1,"importBytes":149,"outputBytes":1378,"outputFiles":"dist/tfjs.esm.js"}
|
||||||
2021-08-14 17:59:16 [35mSTATE:[39m target: nodeWASM type: node: {"imports":42,"importBytes":437334,"outputBytes":379129,"outputFiles":"dist/human.node-wasm.js"}
|
2021-08-15 08:08:33 [35mSTATE:[39m target: nodeWASM type: node: {"imports":42,"importBytes":437978,"outputBytes":379598,"outputFiles":"dist/human.node-wasm.js"}
|
||||||
2021-08-14 17:59:16 [35mSTATE:[39m target: browserNoBundle type: tfjs: {"imports":1,"importBytes":2168,"outputBytes":1242,"outputFiles":"dist/tfjs.esm.js"}
|
2021-08-15 08:08:33 [35mSTATE:[39m target: browserNoBundle type: tfjs: {"imports":1,"importBytes":2168,"outputBytes":1242,"outputFiles":"dist/tfjs.esm.js"}
|
||||||
2021-08-14 17:59:16 [35mSTATE:[39m target: browserNoBundle type: esm: {"imports":42,"importBytes":437198,"outputBytes":248711,"outputFiles":"dist/human.esm-nobundle.js"}
|
2021-08-15 08:08:33 [35mSTATE:[39m target: browserNoBundle type: esm: {"imports":42,"importBytes":437842,"outputBytes":249009,"outputFiles":"dist/human.esm-nobundle.js"}
|
||||||
2021-08-14 17:59:17 [35mSTATE:[39m target: browserBundle type: tfjs: {"modules":1170,"moduleBytes":4145868,"imports":7,"importBytes":2168,"outputBytes":2334701,"outputFiles":"dist/tfjs.esm.js"}
|
2021-08-15 08:08:33 [35mSTATE:[39m target: browserBundle type: tfjs: {"modules":1170,"moduleBytes":4145868,"imports":7,"importBytes":2168,"outputBytes":2334701,"outputFiles":"dist/tfjs.esm.js"}
|
||||||
2021-08-14 17:59:17 [35mSTATE:[39m target: browserBundle type: iife: {"imports":42,"importBytes":2770657,"outputBytes":1379075,"outputFiles":"dist/human.js"}
|
2021-08-15 08:08:33 [35mSTATE:[39m target: browserBundle type: iife: {"imports":42,"importBytes":2771301,"outputBytes":1379375,"outputFiles":"dist/human.js"}
|
||||||
2021-08-14 17:59:18 [35mSTATE:[39m target: browserBundle type: esm: {"imports":42,"importBytes":2770657,"outputBytes":1379067,"outputFiles":"dist/human.esm.js"}
|
2021-08-15 08:08:34 [35mSTATE:[39m target: browserBundle type: esm: {"imports":42,"importBytes":2771301,"outputBytes":1379367,"outputFiles":"dist/human.esm.js"}
|
||||||
2021-08-14 17:59:18 [36mINFO: [39m Running Linter: ["server/","src/","tfjs/","test/","demo/"]
|
2021-08-15 08:08:34 [36mINFO: [39m Running Linter: ["server/","src/","tfjs/","test/","demo/"]
|
||||||
2021-08-14 17:59:40 [36mINFO: [39m Linter complete: files: 76 errors: 0 warnings: 0
|
2021-08-15 08:08:57 [36mINFO: [39m Linter complete: files: 77 errors: 0 warnings: 0
|
||||||
2021-08-14 17:59:40 [36mINFO: [39m Generate ChangeLog: ["/home/vlado/dev/human/CHANGELOG.md"]
|
2021-08-15 08:08:57 [36mINFO: [39m Generate ChangeLog: ["/home/vlado/dev/human/CHANGELOG.md"]
|
||||||
2021-08-14 17:59:40 [36mINFO: [39m Generate Typings: ["src/human.ts"] outDir: ["types"]
|
2021-08-15 08:08:57 [36mINFO: [39m Generate Typings: ["src/human.ts"] outDir: ["types"]
|
||||||
2021-08-14 17:59:54 [36mINFO: [39m Generate TypeDocs: ["src/human.ts"] outDir: ["typedoc"]
|
2021-08-15 08:09:11 [36mINFO: [39m Generate TypeDocs: ["src/human.ts"] outDir: ["typedoc"]
|
||||||
2021-08-14 18:00:09 [36mINFO: [39m Documentation generated at /home/vlado/dev/human/typedoc 1
|
2021-08-15 08:09:25 [36mINFO: [39m Documentation generated at /home/vlado/dev/human/typedoc 1
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*/
|
*/
|
||||||
export interface Config {
|
export interface Config {
|
||||||
/** Backend used for TFJS operations */
|
/** Backend used for TFJS operations */
|
||||||
backend: null | '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow',
|
backend: null | '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow' | 'webgpu',
|
||||||
|
|
||||||
/** Path to *.wasm files if backend is set to `wasm` */
|
/** Path to *.wasm files if backend is set to `wasm` */
|
||||||
wasmPath: string,
|
wasmPath: string,
|
||||||
|
|
32
src/human.ts
32
src/human.ts
|
@ -298,19 +298,35 @@ export class Human {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (this.config.backend && this.config.backend.length > 0) {
|
if (this.config.backend && this.config.backend.length > 0) {
|
||||||
|
// detect web worker
|
||||||
// @ts-ignore ignore missing type for WorkerGlobalScope as that is the point
|
// @ts-ignore ignore missing type for WorkerGlobalScope as that is the point
|
||||||
if (typeof window === 'undefined' && typeof WorkerGlobalScope !== 'undefined' && this.config.debug) log('running inside web worker');
|
if (typeof window === 'undefined' && typeof WorkerGlobalScope !== 'undefined' && this.config.debug) {
|
||||||
|
log('running inside web worker');
|
||||||
|
}
|
||||||
|
|
||||||
// force browser vs node backend
|
// force browser vs node backend
|
||||||
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === 'tensorflow') {
|
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === 'tensorflow') {
|
||||||
if (this.config.debug) log('override: backend set to tensorflow while running in browser');
|
log('override: backend set to tensorflow while running in browser');
|
||||||
this.config.backend = 'humangl';
|
this.config.backend = 'humangl';
|
||||||
}
|
}
|
||||||
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === 'webgl' || this.config.backend === 'humangl')) {
|
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === 'webgl' || this.config.backend === 'humangl')) {
|
||||||
if (this.config.debug) log('override: backend set to webgl while running in nodejs');
|
log('override: backend set to webgl while running in nodejs');
|
||||||
this.config.backend = 'tensorflow';
|
this.config.backend = 'tensorflow';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle webgpu
|
||||||
|
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === 'webgpu') {
|
||||||
|
if (typeof navigator === 'undefined' || typeof navigator['gpu'] === 'undefined') {
|
||||||
|
log('override: backend set to webgpu but browser does not support webgpu');
|
||||||
|
this.config.backend = 'humangl';
|
||||||
|
} else {
|
||||||
|
const adapter = await navigator['gpu'].requestAdapter();
|
||||||
|
if (this.config.debug) log('enumerated webgpu adapter:', adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check available backends
|
||||||
|
if (this.config.backend === 'humangl') backend.register();
|
||||||
const available = Object.keys(this.tf.engine().registryFactory);
|
const available = Object.keys(this.tf.engine().registryFactory);
|
||||||
if (this.config.debug) log('available backends:', available);
|
if (this.config.debug) log('available backends:', available);
|
||||||
|
|
||||||
|
@ -322,6 +338,7 @@ export class Human {
|
||||||
|
|
||||||
if (this.config.debug) log('setting backend:', this.config.backend);
|
if (this.config.debug) log('setting backend:', this.config.backend);
|
||||||
|
|
||||||
|
// handle wasm
|
||||||
if (this.config.backend === 'wasm') {
|
if (this.config.backend === 'wasm') {
|
||||||
if (this.config.debug) log('wasm path:', this.config.wasmPath);
|
if (this.config.debug) log('wasm path:', this.config.wasmPath);
|
||||||
if (typeof this.tf?.setWasmPaths !== 'undefined') this.tf.setWasmPaths(this.config.wasmPath);
|
if (typeof this.tf?.setWasmPaths !== 'undefined') this.tf.setWasmPaths(this.config.wasmPath);
|
||||||
|
@ -332,15 +349,15 @@ export class Human {
|
||||||
if (this.config.debug && !simd) log('warning: wasm simd support is not enabled');
|
if (this.config.debug && !simd) log('warning: wasm simd support is not enabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.config.backend === 'humangl') backend.register();
|
// handle humangl
|
||||||
try {
|
try {
|
||||||
await this.tf.setBackend(this.config.backend);
|
await this.tf.setBackend(this.config.backend);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log('error: cannot set backend:', this.config.backend, err);
|
log('error: cannot set backend:', this.config.backend, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.tf.enableProdMode();
|
|
||||||
// this.tf.enableDebugMode();
|
// handle webgl & humangl
|
||||||
if (this.tf.getBackend() === 'webgl' || this.tf.getBackend() === 'humangl') {
|
if (this.tf.getBackend() === 'webgl' || this.tf.getBackend() === 'humangl') {
|
||||||
this.tf.ENV.set('CHECK_COMPUTATION_FOR_ERRORS', false);
|
this.tf.ENV.set('CHECK_COMPUTATION_FOR_ERRORS', false);
|
||||||
this.tf.ENV.set('WEBGL_CPU_FORWARD', true);
|
this.tf.ENV.set('WEBGL_CPU_FORWARD', true);
|
||||||
|
@ -355,6 +372,9 @@ export class Human {
|
||||||
const gl = await this.tf.backend().getGPGPUContext().gl;
|
const gl = await this.tf.backend().getGPGPUContext().gl;
|
||||||
if (this.config.debug) log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
|
if (this.config.debug) log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait for ready
|
||||||
|
this.tf.enableProdMode();
|
||||||
await this.tf.ready();
|
await this.tf.ready();
|
||||||
this.performance.backend = Math.trunc(now() - timeStamp);
|
this.performance.backend = Math.trunc(now() - timeStamp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@
|
||||||
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface">
|
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface">
|
||||||
<a name="backend" class="tsd-anchor"></a>
|
<a name="backend" class="tsd-anchor"></a>
|
||||||
<h3>backend</h3>
|
<h3>backend</h3>
|
||||||
<div class="tsd-signature tsd-kind-icon">backend<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">""</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"cpu"</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"wasm"</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"webgl"</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"humangl"</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"tensorflow"</span></div>
|
<div class="tsd-signature tsd-kind-icon">backend<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">""</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"cpu"</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"wasm"</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"webgl"</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"humangl"</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"tensorflow"</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">"webgpu"</span></div>
|
||||||
<aside class="tsd-sources">
|
<aside class="tsd-sources">
|
||||||
</aside>
|
</aside>
|
||||||
<div class="tsd-comment tsd-typography">
|
<div class="tsd-comment tsd-typography">
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
export interface Config {
|
export interface Config {
|
||||||
/** Backend used for TFJS operations */
|
/** Backend used for TFJS operations */
|
||||||
backend: null | '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow';
|
backend: null | '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow' | 'webgpu';
|
||||||
/** Path to *.wasm files if backend is set to `wasm` */
|
/** Path to *.wasm files if backend is set to `wasm` */
|
||||||
wasmPath: string;
|
wasmPath: string;
|
||||||
/** Print debug statements to console */
|
/** Print debug statements to console */
|
||||||
|
|
Loading…
Reference in New Issue