mirror of https://github.com/vladmandic/human
add benchmark info
parent
b0bd103db2
commit
ce703f48fd
1
TODO.md
1
TODO.md
|
@ -6,6 +6,7 @@ WebGL shader optimizations for faster load and initial detection
|
|||
|
||||
- Implement WebGL uniforms for shaders: <https://github.com/tensorflow/tfjs/issues/5205>
|
||||
- Fix shader packing: <https://github.com/tensorflow/tfjs/issues/5343>
|
||||
- Event emitters
|
||||
|
||||
<br>
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Human</title>
|
||||
<meta name="viewport" content="width=device-width" id="viewport">
|
||||
<meta name="keywords" content="Human">
|
||||
<meta name="application-name" content="Human">
|
||||
<meta name="description" content="Human: 3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction, Emotion Prediction & Gesture Recognition; Author: Vladimir Mandic <https://github.com/vladmandic>">
|
||||
<meta name="msapplication-tooltip" content="Human: 3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction, Emotion Prediction & Gesture Recognition; Author: Vladimir Mandic <https://github.com/vladmandic>">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<link rel="manifest" href="../manifest.webmanifest">
|
||||
<link rel="shortcut icon" href="../../favicon.ico" type="image/x-icon">
|
||||
<link rel="apple-touch-icon" href="../../assets/icon.png">
|
||||
<script type="module" src="browser.js"></script>
|
||||
<style>
|
||||
@font-face { font-family: 'Lato'; font-display: swap; font-style: normal; font-weight: 100; src: local('Lato'), url('../../assets/lato-light.woff2') }
|
||||
html { font-family: 'Lato', 'Segoe UI'; font-size: 16px; font-variant: small-caps; }
|
||||
body { margin: 0; background: black; color: white; overflow-x: hidden; width: 100vw; height: 100vh; }
|
||||
body::-webkit-scrollbar { display: none; }
|
||||
.status { position: absolute; width: 100vw; bottom: 10%; text-align: center; font-size: 3rem; font-weight: 100; text-shadow: 2px 2px #303030; }
|
||||
.log { position: absolute; bottom: 0; margin: 0.4rem 0.4rem 0 0.4rem; font-size: 0.9rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="status" class="status"></div>
|
||||
<img id="image" src="../../samples/groups/group1.jpg" style="display: none"></img>
|
||||
<div id="log" class="log"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,71 @@
|
|||
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
||||
const tf = require('@tensorflow/tfjs-node-gpu');
|
||||
const log = require('@vladmandic/pilogger');
|
||||
const canvasJS = require('canvas');
|
||||
const Human = require('../../dist/human.node-gpu.js').default;
|
||||
|
||||
const input = 'samples/groups/group1.jpg';
|
||||
const loop = 20;
|
||||
|
||||
const myConfig = {
|
||||
backend: 'tensorflow',
|
||||
modelBasePath: 'https://vladmandic.github.io/human/models',
|
||||
wasmPath: 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@3.9.0/dist/',
|
||||
debug: true,
|
||||
async: true,
|
||||
cacheSensitivity: 0,
|
||||
filter: { enabled: false },
|
||||
face: {
|
||||
enabled: true,
|
||||
detector: { enabled: true, rotation: false },
|
||||
mesh: { enabled: true },
|
||||
iris: { enabled: true },
|
||||
description: { enabled: true },
|
||||
emotion: { enabled: true },
|
||||
},
|
||||
hand: {
|
||||
enabled: true,
|
||||
},
|
||||
body: { enabled: true },
|
||||
object: { enabled: false },
|
||||
};
|
||||
|
||||
async function getImage(human) {
|
||||
const img = await canvasJS.loadImage(input);
|
||||
const canvas = canvasJS.createCanvas(img.width, img.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0, img.width, img.height);
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
const res = human.tf.tidy(() => {
|
||||
const tensor = human.tf.tensor(Array.from(imageData.data), [canvas.height, canvas.width, 4], 'int32'); // create rgba image tensor from flat array
|
||||
const channels = human.tf.split(tensor, 4, 2); // split rgba to channels
|
||||
const rgb = human.tf.stack([channels[0], channels[1], channels[2]], 2); // stack channels back to rgb
|
||||
const reshape = human.tf.reshape(rgb, [1, canvas.height, canvas.width, 3]); // move extra dim from the end of tensor and use it as batch number instead
|
||||
return reshape;
|
||||
});
|
||||
log.info('Image:', input, res.shape);
|
||||
return res;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
log.header();
|
||||
const human = new Human(myConfig);
|
||||
await human.tf.ready();
|
||||
log.info('Human:', human.version);
|
||||
await human.load();
|
||||
const loaded = Object.keys(human.models).filter((a) => human.models[a]);
|
||||
log.info('Loaded:', loaded);
|
||||
log.info('Memory state:', human.tf.engine().memory());
|
||||
const tensor = await getImage(human);
|
||||
log.state('Processing:', tensor['shape']);
|
||||
const t0 = performance.now();
|
||||
await human.detect(tensor, myConfig);
|
||||
const t1 = performance.now();
|
||||
log.state('Backend:', human.tf.getBackend());
|
||||
log.data('Warmup:', Math.round(t1 - t0));
|
||||
for (let i = 0; i < loop; i++) await human.detect(tensor, myConfig);
|
||||
const t2 = performance.now();
|
||||
log.data('Average:', Math.round((t2 - t1) / loop));
|
||||
}
|
||||
|
||||
main();
|
|
@ -73,7 +73,7 @@
|
|||
"canvas": "^2.8.0",
|
||||
"chokidar": "^3.5.2",
|
||||
"dayjs": "^1.10.6",
|
||||
"esbuild": "^0.12.24",
|
||||
"esbuild": "^0.12.25",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-airbnb-base": "^14.2.1",
|
||||
"eslint-plugin-import": "^2.24.2",
|
||||
|
@ -83,7 +83,7 @@
|
|||
"node-fetch": "^3.0.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"seedrandom": "^3.0.5",
|
||||
"simple-git": "^2.45.0",
|
||||
"simple-git": "^2.45.1",
|
||||
"tslib": "^2.3.1",
|
||||
"typedoc": "0.21.9",
|
||||
"typescript": "4.4.2"
|
||||
|
|
|
@ -62,7 +62,7 @@ export type TensorFlow = typeof tf;
|
|||
*/
|
||||
export class Human {
|
||||
/** Current version of Human library in *semver* format */
|
||||
static version: string;
|
||||
version: string;
|
||||
/** Current configuration
|
||||
* - Details: {@link Config}
|
||||
*/
|
||||
|
@ -148,7 +148,7 @@ export class Human {
|
|||
* @param userConfig: {@link Config}
|
||||
*/
|
||||
constructor(userConfig?: Config | Record<string, unknown>) {
|
||||
Human.version = app.version; // expose version property on instance of class
|
||||
this.version = app.version; // expose version property on instance of class
|
||||
Object.defineProperty(this, 'version', { value: app.version }); // expose version property directly on class itself
|
||||
defaults.wasmPath = `https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@${tf.version_core}/dist/`;
|
||||
this.config = mergeDeep(defaults, userConfig || {});
|
||||
|
@ -270,7 +270,7 @@ export class Human {
|
|||
if (userConfig) this.config = mergeDeep(this.config, userConfig) as Config;
|
||||
|
||||
if (this.#firstRun) { // print version info on first run and check for correct backend setup
|
||||
if (this.config.debug) log(`version: ${Human.version}`);
|
||||
if (this.config.debug) log(`version: ${this.version}`);
|
||||
if (this.config.debug) log(`tfjs version: ${this.tf.version_core}`);
|
||||
if (this.config.debug) log('platform:', this.sysinfo.platform);
|
||||
if (this.config.debug) log('agent:', this.sysinfo.agent);
|
||||
|
|
2
wiki
2
wiki
|
@ -1 +1 @@
|
|||
Subproject commit 7f55fd1c8aea22f33a767da840147b15aeeed034
|
||||
Subproject commit 82ce7a69656a11fa4cd5c5bea447cd1a2797b903
|
Loading…
Reference in New Issue