mirror of https://github.com/vladmandic/human
added support for multiple instances of human
parent
6238e1c612
commit
b74eab5aac
|
@ -1,7 +1,7 @@
|
||||||
# @vladmandic/human
|
# @vladmandic/human
|
||||||
|
|
||||||
Version: **1.4.1**
|
Version: **1.4.1**
|
||||||
Description: **Human: AI-powered 3D Face Detection, Face Description & Recognition, Body Pose Tracking, Hand & Finger Tracking, Iris Analysis, Age & Gender & Emotion Prediction & Gesture Recognition**
|
Description: **Human: AI-powered 3D Face Detection & Rotation Tracking, Face Description & Recognition, Body Pose Tracking, 3D Hand & Finger Tracking, Iris Analysis, Age & Gender & Emotion Prediction, Gesture Recognition**
|
||||||
|
|
||||||
Author: **Vladimir Mandic <mandic00@live.com>**
|
Author: **Vladimir Mandic <mandic00@live.com>**
|
||||||
License: **MIT** </LICENSE>
|
License: **MIT** </LICENSE>
|
||||||
|
@ -9,8 +9,9 @@ Repository: **<git+https://github.com/vladmandic/human.git>**
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
### **HEAD -> main** 2021/04/09 mandic00@live.com
|
### **HEAD -> main** 2021/04/10 mandic00@live.com
|
||||||
|
|
||||||
|
- fix typedoc
|
||||||
- exception handling
|
- exception handling
|
||||||
|
|
||||||
### **1.4.1** 2021/04/09 mandic00@live.com
|
### **1.4.1** 2021/04/09 mandic00@live.com
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
import { DoubleSide, Mesh, MeshBasicMaterial, OrthographicCamera, Scene, sRGBEncoding, VideoTexture, WebGLRenderer, BufferGeometry, BufferAttribute } from './helpers/three.js';
|
import { DoubleSide, Mesh, MeshBasicMaterial, OrthographicCamera, Scene, sRGBEncoding, VideoTexture, WebGLRenderer, BufferGeometry, BufferAttribute } from './helpers/three.js';
|
||||||
import { OrbitControls } from './helpers/three-orbitControls.js';
|
import { OrbitControls } from './helpers/three-orbitControls.js';
|
||||||
import Human from '../dist/human.esm.js'; // equivalent of @vladmandic/human
|
import Human from '../dist/human.esm.js'; // equivalent of @vladmandic/human
|
||||||
|
@ -7,7 +9,7 @@ const userConfig = {
|
||||||
async: false,
|
async: false,
|
||||||
profile: false,
|
profile: false,
|
||||||
warmup: 'full',
|
warmup: 'full',
|
||||||
videoOptimized: false,
|
videoOptimized: true,
|
||||||
filter: { enabled: false },
|
filter: { enabled: false },
|
||||||
face: { enabled: true,
|
face: { enabled: true,
|
||||||
detector: { rotation: false, maxFaces: 1 },
|
detector: { rotation: false, maxFaces: 1 },
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
import Human from '../dist/human.esm.js';
|
import Human from '../dist/human.esm.js';
|
||||||
|
|
||||||
const userConfig = {
|
const userConfig = {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
/* global tf */
|
/* global tf */
|
||||||
import Human from '../dist/human.esm.js'; // equivalent of @vladmandic/human
|
import Human from '../dist/human.esm.js'; // equivalent of @vladmandic/human
|
||||||
// import Human from '../dist/human.esm-nobundle.js'; // this requires that tf is loaded manually and bundled before human can be used
|
// import Human from '../dist/human.esm-nobundle.js'; // this requires that tf is loaded manually and bundled before human can be used
|
||||||
|
|
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
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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -67,13 +67,13 @@
|
||||||
"@vladmandic/pilogger": "^0.2.16",
|
"@vladmandic/pilogger": "^0.2.16",
|
||||||
"chokidar": "^3.5.1",
|
"chokidar": "^3.5.1",
|
||||||
"dayjs": "^1.10.4",
|
"dayjs": "^1.10.4",
|
||||||
"esbuild": "^0.11.6",
|
"esbuild": "^0.11.9",
|
||||||
"eslint": "^7.23.0",
|
"eslint": "^7.24.0",
|
||||||
"eslint-config-airbnb-base": "^14.2.1",
|
"eslint-config-airbnb-base": "^14.2.1",
|
||||||
"eslint-plugin-import": "^2.22.1",
|
"eslint-plugin-import": "^2.22.1",
|
||||||
"eslint-plugin-json": "^2.1.2",
|
"eslint-plugin-json": "^2.1.2",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-promise": "^4.3.1",
|
"eslint-plugin-promise": "^5.1.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"seedrandom": "^3.0.5",
|
"seedrandom": "^3.0.5",
|
||||||
"simple-git": "^2.37.0",
|
"simple-git": "^2.37.0",
|
||||||
|
|
|
@ -11,7 +11,7 @@ export async function load(config) {
|
||||||
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.age.modelPath));
|
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.age.modelPath));
|
||||||
if (!model || !model.modelUrl) log('load model failed:', config.face.age.modelPath);
|
if (!model || !model.modelUrl) log('load model failed:', config.face.age.modelPath);
|
||||||
else if (config.debug) log('load model:', model.modelUrl);
|
else if (config.debug) log('load model:', model.modelUrl);
|
||||||
}
|
} else if (config.debug) log('cached model:', model.modelUrl);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,20 +60,26 @@ export class MediaPipeFaceMesh {
|
||||||
|
|
||||||
let faceModels:[any, any, any] = [null, null, null];
|
let faceModels:[any, any, any] = [null, null, null];
|
||||||
export async function load(config): Promise<MediaPipeFaceMesh> {
|
export async function load(config): Promise<MediaPipeFaceMesh> {
|
||||||
|
if ((!faceModels[0] && config.face.enabled) || (!faceModels[1] && config.face.mesh.enabled) || (!faceModels[2] && config.face.iris.enabled)) {
|
||||||
faceModels = await Promise.all([
|
faceModels = await Promise.all([
|
||||||
(!faceModels[0] && config.face.enabled) ? blazeface.load(config) : null,
|
(!faceModels[0] && config.face.enabled) ? blazeface.load(config) : null,
|
||||||
(!faceModels[1] && config.face.mesh.enabled) ? tf.loadGraphModel(join(config.modelBasePath, config.face.mesh.modelPath), { fromTFHub: config.face.mesh.modelPath.includes('tfhub.dev') }) : null,
|
(!faceModels[1] && config.face.mesh.enabled) ? tf.loadGraphModel(join(config.modelBasePath, config.face.mesh.modelPath), { fromTFHub: config.face.mesh.modelPath.includes('tfhub.dev') }) : null,
|
||||||
(!faceModels[2] && config.face.iris.enabled) ? tf.loadGraphModel(join(config.modelBasePath, config.face.iris.modelPath), { fromTFHub: config.face.iris.modelPath.includes('tfhub.dev') }) : null,
|
(!faceModels[2] && config.face.iris.enabled) ? tf.loadGraphModel(join(config.modelBasePath, config.face.iris.modelPath), { fromTFHub: config.face.iris.modelPath.includes('tfhub.dev') }) : null,
|
||||||
]);
|
]);
|
||||||
const faceMesh = new MediaPipeFaceMesh(faceModels[0], faceModels[1], faceModels[2], config);
|
|
||||||
if (config.face.mesh.enabled) {
|
if (config.face.mesh.enabled) {
|
||||||
if (!faceModels[1] || !faceModels[1].modelUrl) log('load model failed:', config.face.age.modelPath);
|
if (!faceModels[1] || !faceModels[1].modelUrl) log('load model failed:', config.face.mesh.modelPath);
|
||||||
else if (config.debug) log('load model:', faceModels[1].modelUrl);
|
else if (config.debug) log('load model:', faceModels[1].modelUrl);
|
||||||
}
|
}
|
||||||
if (config.face.iris.enabled) {
|
if (config.face.iris.enabled) {
|
||||||
if (!faceModels[2] || !faceModels[1].modelUrl) log('load model failed:', config.face.age.modelPath);
|
if (!faceModels[2] || !faceModels[1].modelUrl) log('load model failed:', config.face.iris.modelPath);
|
||||||
else if (config.debug) log('load model:', faceModels[2].modelUrl);
|
else if (config.debug) log('load model:', faceModels[2].modelUrl);
|
||||||
}
|
}
|
||||||
|
} else if (config.debug) {
|
||||||
|
log('cached model:', faceModels[0].model.modelUrl);
|
||||||
|
log('cached model:', faceModels[1].modelUrl);
|
||||||
|
log('cached model:', faceModels[2].modelUrl);
|
||||||
|
}
|
||||||
|
const faceMesh = new MediaPipeFaceMesh(faceModels[0], faceModels[1], faceModels[2], config);
|
||||||
return faceMesh;
|
return faceMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ export async function load(config) {
|
||||||
model.height = parseInt(model.signature.inputs['input_1:0'].tensorShape.dim[1].size);
|
model.height = parseInt(model.signature.inputs['input_1:0'].tensorShape.dim[1].size);
|
||||||
if (!model || !model.modelUrl) log('load model failed:', config.body.modelPath);
|
if (!model || !model.modelUrl) log('load model failed:', config.body.modelPath);
|
||||||
else if (config.debug) log('load model:', model.modelUrl);
|
else if (config.debug) log('load model:', model.modelUrl);
|
||||||
}
|
} else if (config.debug) log('cached model:', model.modelUrl);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ export async function load(config) {
|
||||||
model = await tf.loadGraphModel(join(config.modelBasePath, config.body.modelPath));
|
model = await tf.loadGraphModel(join(config.modelBasePath, config.body.modelPath));
|
||||||
if (!model || !model.modelUrl) log('load model failed:', config.body.modelPath);
|
if (!model || !model.modelUrl) log('load model failed:', config.body.modelPath);
|
||||||
else if (config.debug) log('load model:', model.modelUrl);
|
else if (config.debug) log('load model:', model.modelUrl);
|
||||||
}
|
} else if (config.debug) log('cached model:', model.modelUrl);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ export async function load(config) {
|
||||||
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.embedding.modelPath));
|
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.embedding.modelPath));
|
||||||
if (!model || !model.modelUrl) log('load model failed:', config.face.embedding.modelPath);
|
if (!model || !model.modelUrl) log('load model failed:', config.face.embedding.modelPath);
|
||||||
else if (config.debug) log('load model:', model.modelUrl);
|
else if (config.debug) log('load model:', model.modelUrl);
|
||||||
}
|
} else if (config.debug) log('cached model:', model.modelUrl);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ export async function load(config) {
|
||||||
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.emotion.modelPath));
|
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.emotion.modelPath));
|
||||||
if (!model || !model.modelUrl) log('load model failed:', config.face.emotion.modelPath);
|
if (!model || !model.modelUrl) log('load model failed:', config.face.emotion.modelPath);
|
||||||
else if (config.debug) log('load model:', model.modelUrl);
|
else if (config.debug) log('load model:', model.modelUrl);
|
||||||
}
|
} else if (config.debug) log('cached model:', model.modelUrl);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ export async function load(config) {
|
||||||
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.description.modelPath));
|
model = await tf.loadGraphModel(join(config.modelBasePath, config.face.description.modelPath));
|
||||||
if (!model || !model.modelUrl) log('load model failed:', config.face.description.modelPath);
|
if (!model || !model.modelUrl) log('load model failed:', config.face.description.modelPath);
|
||||||
else if (config.debug) log('load model:', model.modelUrl);
|
else if (config.debug) log('load model:', model.modelUrl);
|
||||||
}
|
} else if (config.debug) log('cached model:', model.modelUrl);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ export async function load(config) {
|
||||||
alternative = model.inputs[0].shape[3] === 1;
|
alternative = model.inputs[0].shape[3] === 1;
|
||||||
if (!model || !model.modelUrl) log('load model failed:', config.face.gender.modelPath);
|
if (!model || !model.modelUrl) log('load model failed:', config.face.gender.modelPath);
|
||||||
else if (config.debug) log('load model:', model.modelUrl);
|
else if (config.debug) log('load model:', model.modelUrl);
|
||||||
}
|
} else if (config.debug) log('cached model:', model.modelUrl);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,20 +53,26 @@ export class HandPose {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let handDetectorModel;
|
||||||
|
let handPoseModel;
|
||||||
export async function load(config): Promise<HandPose> {
|
export async function load(config): Promise<HandPose> {
|
||||||
const [handDetectorModel, handPoseModel] = await Promise.all([
|
if (!handDetectorModel || !handPoseModel) {
|
||||||
|
[handDetectorModel, handPoseModel] = await Promise.all([
|
||||||
config.hand.enabled ? tf.loadGraphModel(join(config.modelBasePath, config.hand.detector.modelPath), { fromTFHub: config.hand.detector.modelPath.includes('tfhub.dev') }) : null,
|
config.hand.enabled ? tf.loadGraphModel(join(config.modelBasePath, config.hand.detector.modelPath), { fromTFHub: config.hand.detector.modelPath.includes('tfhub.dev') }) : null,
|
||||||
config.hand.landmarks ? tf.loadGraphModel(join(config.modelBasePath, config.hand.skeleton.modelPath), { fromTFHub: config.hand.skeleton.modelPath.includes('tfhub.dev') }) : null,
|
config.hand.landmarks ? tf.loadGraphModel(join(config.modelBasePath, config.hand.skeleton.modelPath), { fromTFHub: config.hand.skeleton.modelPath.includes('tfhub.dev') }) : null,
|
||||||
]);
|
]);
|
||||||
const handDetector = new handdetector.HandDetector(handDetectorModel, handDetectorModel?.inputs[0].shape[2], anchors.anchors);
|
|
||||||
const handPipeline = new handpipeline.HandPipeline(handDetector, handPoseModel, handPoseModel?.inputs[0].shape[2]);
|
|
||||||
const handPose = new HandPose(handPipeline);
|
|
||||||
|
|
||||||
if (config.hand.enabled) {
|
if (config.hand.enabled) {
|
||||||
if (!handDetectorModel || !handDetectorModel.modelUrl) log('load model failed:', config.hand.detector.modelPath);
|
if (!handDetectorModel || !handDetectorModel.modelUrl) log('load model failed:', config.hand.detector.modelPath);
|
||||||
else if (config.debug) log('load model:', handDetectorModel.modelUrl);
|
else if (config.debug) log('load model:', handDetectorModel.modelUrl);
|
||||||
if (!handPoseModel || !handPoseModel.modelUrl) log('load model failed:', config.hand.skeleton.modelPath);
|
if (!handPoseModel || !handPoseModel.modelUrl) log('load model failed:', config.hand.skeleton.modelPath);
|
||||||
else if (config.debug) log('load model:', handPoseModel.modelUrl);
|
else if (config.debug) log('load model:', handPoseModel.modelUrl);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (config.debug) log('cached model:', handDetectorModel.modelUrl);
|
||||||
|
if (config.debug) log('cached model:', handPoseModel.modelUrl);
|
||||||
|
}
|
||||||
|
const handDetector = new handdetector.HandDetector(handDetectorModel, handDetectorModel?.inputs[0].shape[2], anchors.anchors);
|
||||||
|
const handPipeline = new handpipeline.HandPipeline(handDetector, handPoseModel, handPoseModel?.inputs[0].shape[2]);
|
||||||
|
const handPose = new HandPose(handPipeline);
|
||||||
return handPose;
|
return handPose;
|
||||||
}
|
}
|
||||||
|
|
12
src/human.ts
12
src/human.ts
|
@ -343,6 +343,14 @@ export class Human {
|
||||||
if (this.config.scoped) this.tf.engine().startScope();
|
if (this.config.scoped) this.tf.engine().startScope();
|
||||||
this.analyze('Start Scope:');
|
this.analyze('Start Scope:');
|
||||||
|
|
||||||
|
// disable video optimization for inputs of type image
|
||||||
|
let previousVideoOptimized;
|
||||||
|
if (input && this.config.videoOptimized && (input instanceof HTMLImageElement || input instanceof Image || input instanceof ImageData || input instanceof ImageBitmap || input instanceof tf.Tensor)) {
|
||||||
|
log('disabling video optimization');
|
||||||
|
previousVideoOptimized = this.config.videoOptimized;
|
||||||
|
this.config.videoOptimized = false;
|
||||||
|
}
|
||||||
|
|
||||||
timeStamp = now();
|
timeStamp = now();
|
||||||
const process = image.process(input, this.config);
|
const process = image.process(input, this.config);
|
||||||
if (!process || !process.tensor) {
|
if (!process || !process.tensor) {
|
||||||
|
@ -427,6 +435,7 @@ export class Human {
|
||||||
if (this.config.scoped) this.tf.engine().endScope();
|
if (this.config.scoped) this.tf.engine().endScope();
|
||||||
this.analyze('End Scope:');
|
this.analyze('End Scope:');
|
||||||
|
|
||||||
|
// run gesture analysis last
|
||||||
let gestureRes: any[] = [];
|
let gestureRes: any[] = [];
|
||||||
if (this.config.gesture.enabled) {
|
if (this.config.gesture.enabled) {
|
||||||
timeStamp = now();
|
timeStamp = now();
|
||||||
|
@ -435,6 +444,9 @@ export class Human {
|
||||||
else if (this.perf.gesture) delete this.perf.gesture;
|
else if (this.perf.gesture) delete this.perf.gesture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restore video optimizations if previously disabled
|
||||||
|
if (previousVideoOptimized) this.config.videoOptimized = previousVideoOptimized;
|
||||||
|
|
||||||
this.perf.total = Math.trunc(now() - timeStart);
|
this.perf.total = Math.trunc(now() - timeStart);
|
||||||
this.state = 'idle';
|
this.state = 'idle';
|
||||||
const result = {
|
const result = {
|
||||||
|
|
|
@ -28,7 +28,8 @@ export function process(input, config): { tensor: typeof tf.Tensor | null, canva
|
||||||
throw new Error('Human: Input type is not recognized');
|
throw new Error('Human: Input type is not recognized');
|
||||||
}
|
}
|
||||||
if (input instanceof tf.Tensor) {
|
if (input instanceof tf.Tensor) {
|
||||||
tensor = tf.clone(input);
|
if (input.shape && input.shape.length === 4 && input.shape[0] === 1 && input.shape[3] === 3) tensor = tf.clone(input);
|
||||||
|
else throw new Error(`Human: Input tensor shape must be [1, height, width, 3] and instead was ${input.shape}`);
|
||||||
} else {
|
} else {
|
||||||
const originalWidth = input['naturalWidth'] || input['videoWidth'] || input['width'] || (input['shape'] && (input['shape'][1] > 0));
|
const originalWidth = input['naturalWidth'] || input['videoWidth'] || input['width'] || (input['shape'] && (input['shape'][1] > 0));
|
||||||
const originalHeight = input['naturalHeight'] || input['videoHeight'] || input['height'] || (input['shape'] && (input['shape'][2] > 0));
|
const originalHeight = input['naturalHeight'] || input['videoHeight'] || input['height'] || (input['shape'] && (input['shape'][2] > 0));
|
||||||
|
|
|
@ -17,7 +17,7 @@ export async function load(config) {
|
||||||
if (!model.inputSize) throw new Error(`Human: Cannot determine model inputSize: ${config.object.modelPath}`);
|
if (!model.inputSize) throw new Error(`Human: Cannot determine model inputSize: ${config.object.modelPath}`);
|
||||||
if (!model || !model.modelUrl) log('load model failed:', config.object.modelPath);
|
if (!model || !model.modelUrl) log('load model failed:', config.object.modelPath);
|
||||||
else if (config.debug) log('load model:', model.modelUrl);
|
else if (config.debug) log('load model:', model.modelUrl);
|
||||||
}
|
} else if (config.debug) log('cached model:', model.modelUrl);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ import * as decodeMultiple from './decodeMultiple';
|
||||||
import * as decodePose from './decodePose';
|
import * as decodePose from './decodePose';
|
||||||
import * as util from './util';
|
import * as util from './util';
|
||||||
|
|
||||||
|
let model;
|
||||||
|
|
||||||
async function estimateMultiple(input, res, config, inputSize) {
|
async function estimateMultiple(input, res, config, inputSize) {
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
const allTensorBuffers = await util.toTensorBuffers3D([res.heatmapScores, res.offsets, res.displacementFwd, res.displacementBwd]);
|
const allTensorBuffers = await util.toTensorBuffers3D([res.heatmapScores, res.offsets, res.displacementFwd, res.displacementBwd]);
|
||||||
|
@ -29,9 +31,9 @@ async function estimateSingle(input, res, config, inputSize) {
|
||||||
export class PoseNet {
|
export class PoseNet {
|
||||||
baseModel: any;
|
baseModel: any;
|
||||||
inputSize: number
|
inputSize: number
|
||||||
constructor(model) {
|
constructor(mobilenet) {
|
||||||
this.baseModel = model;
|
this.baseModel = mobilenet;
|
||||||
this.inputSize = model.model.inputs[0].shape[1];
|
this.inputSize = mobilenet.model.inputs[0].shape[1];
|
||||||
if (this.inputSize < 128) this.inputSize = 257;
|
if (this.inputSize < 128) this.inputSize = 257;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,9 +60,12 @@ export class PoseNet {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function load(config) {
|
export async function load(config) {
|
||||||
const model = await tf.loadGraphModel(join(config.modelBasePath, config.body.modelPath));
|
if (!model) {
|
||||||
const mobilenet = new modelBase.BaseModel(model);
|
model = await tf.loadGraphModel(join(config.modelBasePath, config.body.modelPath));
|
||||||
if (!model || !model.modelUrl) log('load model failed:', config.body.modelPath);
|
if (!model || !model.modelUrl) log('load model failed:', config.body.modelPath);
|
||||||
else if (config.debug) log('load model:', model.modelUrl);
|
else if (config.debug) log('load model:', model.modelUrl);
|
||||||
return new PoseNet(mobilenet);
|
} else if (config.debug) log('cached model:', model.modelUrl);
|
||||||
|
const mobilenet = new modelBase.BaseModel(model);
|
||||||
|
const poseNet = new PoseNet(mobilenet);
|
||||||
|
return poseNet;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,10 @@ export interface Result {
|
||||||
emotion: Array<{ score: number, emotion: string }>,
|
emotion: Array<{ score: number, emotion: string }>,
|
||||||
embedding: Array<number>,
|
embedding: Array<number>,
|
||||||
iris: number,
|
iris: number,
|
||||||
|
rotation: {
|
||||||
angle: { roll: number, yaw: number, pitch: number },
|
angle: { roll: number, yaw: number, pitch: number },
|
||||||
|
matrix: Array<[number, number, number, number, number, number, number, number, number]>
|
||||||
|
}
|
||||||
}>,
|
}>,
|
||||||
/** Body results
|
/** Body results
|
||||||
*
|
*
|
||||||
|
|
|
@ -30,11 +30,16 @@ const config = {
|
||||||
object: { enabled: true },
|
object: { enabled: true },
|
||||||
};
|
};
|
||||||
|
|
||||||
async function test() {
|
async function testInstance(human) {
|
||||||
const human = new Human(config);
|
|
||||||
if (human) log.state('passed: create human');
|
if (human) log.state('passed: create human');
|
||||||
else log.error('failed: create human');
|
else log.error('failed: create human');
|
||||||
|
|
||||||
|
// if (!human.tf) human.tf = tf;
|
||||||
|
log.info('human version:', human.version);
|
||||||
|
log.info('tfjs version:', human.tf.version_core);
|
||||||
|
log.info('platform:', human.sysinfo.platform);
|
||||||
|
log.info('agent:', human.sysinfo.agent);
|
||||||
|
|
||||||
await human.load();
|
await human.load();
|
||||||
if (human.models) {
|
if (human.models) {
|
||||||
log.state('passed: load models');
|
log.state('passed: load models');
|
||||||
|
@ -53,6 +58,28 @@ async function test() {
|
||||||
} else {
|
} else {
|
||||||
log.error('failed: warmup');
|
log.error('failed: warmup');
|
||||||
}
|
}
|
||||||
|
const random = tf.randomNormal([1, 1024, 1024, 3]);
|
||||||
|
const detect = await human.detect(random);
|
||||||
|
tf.dispose(random);
|
||||||
|
if (detect) {
|
||||||
|
log.state('passed: detect:', 'random');
|
||||||
|
log.data(' result: face:', detect.face.length, 'body:', detect.body.length, 'hand:', detect.hand.length, 'gesture:', detect.gesture.length, 'object:', detect.object.length);
|
||||||
|
log.data(' result: performance:', 'load:', detect.performance.load, 'total:', detect.performance.total);
|
||||||
|
} else {
|
||||||
|
log.error('failed: detect');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function test() {
|
||||||
|
log.info('testing instance#1');
|
||||||
|
config.warmup = 'face';
|
||||||
|
const human1 = new Human(config);
|
||||||
|
await testInstance(human1);
|
||||||
|
|
||||||
|
log.info('testing instance#2');
|
||||||
|
config.warmup = 'body';
|
||||||
|
const human2 = new Human(config);
|
||||||
|
await testInstance(human2);
|
||||||
}
|
}
|
||||||
|
|
||||||
test();
|
test();
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
||||||
export declare class PoseNet {
|
export declare class PoseNet {
|
||||||
baseModel: any;
|
baseModel: any;
|
||||||
inputSize: number;
|
inputSize: number;
|
||||||
constructor(model: any);
|
constructor(mobilenet: any);
|
||||||
estimatePoses(input: any, config: any): Promise<unknown>;
|
estimatePoses(input: any, config: any): Promise<unknown>;
|
||||||
dispose(): void;
|
dispose(): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,11 +46,14 @@ export interface Result {
|
||||||
}>;
|
}>;
|
||||||
embedding: Array<number>;
|
embedding: Array<number>;
|
||||||
iris: number;
|
iris: number;
|
||||||
|
rotation: {
|
||||||
angle: {
|
angle: {
|
||||||
roll: number;
|
roll: number;
|
||||||
yaw: number;
|
yaw: number;
|
||||||
pitch: number;
|
pitch: number;
|
||||||
};
|
};
|
||||||
|
matrix: Array<[number, number, number, number, number, number, number, number, number]>;
|
||||||
|
};
|
||||||
}>;
|
}>;
|
||||||
/** Body results
|
/** Body results
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue