mirror of https://github.com/vladmandic/human
normalize all scores
parent
942fa18b52
commit
5931a6f541
|
@ -1,6 +1,6 @@
|
||||||
# @vladmandic/human
|
# @vladmandic/human
|
||||||
|
|
||||||
Version: **1.3.0**
|
Version: **1.3.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, Face Description & Recognition, Body Pose Tracking, Hand & Finger Tracking, Iris Analysis, Age & Gender & Emotion Prediction & Gesture Recognition**
|
||||||
|
|
||||||
Author: **Vladimir Mandic <mandic00@live.com>**
|
Author: **Vladimir Mandic <mandic00@live.com>**
|
||||||
|
@ -9,8 +9,9 @@ Repository: **<git+https://github.com/vladmandic/human.git>**
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
### **HEAD -> main** 2021/03/30 mandic00@live.com
|
### **1.3.1** 2021/03/30 mandic00@live.com
|
||||||
|
|
||||||
|
- added face3d demo
|
||||||
- initial work on face3d three.js demo
|
- initial work on face3d three.js demo
|
||||||
- enable buffering
|
- enable buffering
|
||||||
- new icons
|
- new icons
|
||||||
|
|
|
@ -12,7 +12,7 @@ const userConfig = {
|
||||||
profile: false,
|
profile: false,
|
||||||
warmup: 'full',
|
warmup: 'full',
|
||||||
videoOptimized: false,
|
videoOptimized: false,
|
||||||
filter: { enabled: true },
|
filter: { enabled: false },
|
||||||
face: { enabled: false,
|
face: { enabled: false,
|
||||||
mesh: { enabled: true },
|
mesh: { enabled: true },
|
||||||
iris: { enabled: true },
|
iris: { enabled: true },
|
||||||
|
|
35
demo/node.js
35
demo/node.js
|
@ -11,8 +11,8 @@ const Human = require('../dist/human.node.js').default; // or const Human = requ
|
||||||
let human = null;
|
let human = null;
|
||||||
|
|
||||||
const myConfig = {
|
const myConfig = {
|
||||||
// backend: 'tensorflow',
|
backend: 'tensorflow',
|
||||||
console: true,
|
debug: true,
|
||||||
videoOptimized: false,
|
videoOptimized: false,
|
||||||
async: false,
|
async: false,
|
||||||
face: {
|
face: {
|
||||||
|
@ -22,17 +22,15 @@ const myConfig = {
|
||||||
iris: { modelPath: 'file://models/iris.json', enabled: true },
|
iris: { modelPath: 'file://models/iris.json', enabled: true },
|
||||||
description: { modelPath: 'file://models/faceres.json', enabled: true },
|
description: { modelPath: 'file://models/faceres.json', enabled: true },
|
||||||
emotion: { modelPath: 'file://models/emotion.json', enabled: true },
|
emotion: { modelPath: 'file://models/emotion.json', enabled: true },
|
||||||
age: { modelPath: 'file://models/age.json', enabled: false },
|
|
||||||
gender: { modelPath: 'file://models/gender.json', enabled: false },
|
|
||||||
embedding: { modelPath: 'file://models/mobileface.json', enabled: false },
|
|
||||||
},
|
},
|
||||||
// body: { modelPath: 'file://models/blazepose.json', enabled: true },
|
|
||||||
body: { modelPath: 'file://models/posenet.json', enabled: true },
|
|
||||||
hand: {
|
hand: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
detector: { modelPath: 'file://models/handdetect.json' },
|
detector: { modelPath: 'file://models/handdetect.json' },
|
||||||
skeleton: { modelPath: 'file://models/handskeleton.json' },
|
skeleton: { modelPath: 'file://models/handskeleton.json' },
|
||||||
},
|
},
|
||||||
|
// body: { modelPath: 'file://models/efficientpose.json', enabled: true },
|
||||||
|
// body: { modelPath: 'file://models/blazepose.json', enabled: true },
|
||||||
|
body: { modelPath: 'file://models/posenet.json', enabled: true },
|
||||||
object: { modelPath: 'file://models/nanodet.json', enabled: true },
|
object: { modelPath: 'file://models/nanodet.json', enabled: true },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,6 +64,29 @@ async function detect(input) {
|
||||||
// dispose image tensor as we no longer need it
|
// dispose image tensor as we no longer need it
|
||||||
image.dispose();
|
image.dispose();
|
||||||
// print data to console
|
// print data to console
|
||||||
|
log.data('Results:');
|
||||||
|
for (let i = 0; i < result.face.length; i++) {
|
||||||
|
const face = result.face[i];
|
||||||
|
const emotion = face.emotion.reduce((prev, curr) => (prev.score > curr.score ? prev : curr));
|
||||||
|
log.data(` Face: #${i} boxConfidence:${face.boxConfidence} faceConfidence:${face.boxConfidence} age:${face.age} genderConfidence:${face.genderConfidence} gender:${face.gender} emotionScore:${emotion.score} emotion:${emotion.emotion} iris:${face.iris}`);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < result.body.length; i++) {
|
||||||
|
const body = result.body[i];
|
||||||
|
log.data(` Body: #${i} score:${body.score}`);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < result.hand.length; i++) {
|
||||||
|
const hand = result.hand[i];
|
||||||
|
log.data(` Hand: #${i} confidence:${hand.confidence}`);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < result.gesture.length; i++) {
|
||||||
|
const [key, val] = Object.entries(result.gesture[i]);
|
||||||
|
log.data(` Gesture: ${key[0]}#${key[1]} gesture:${val[1]}`);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < result.object.length; i++) {
|
||||||
|
const object = result.object[i];
|
||||||
|
log.data(` Object: #${i} score:${object.score} label:${object.label}`);
|
||||||
|
}
|
||||||
|
result.face.length = 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as tf from '../../dist/tfjs.esm.js';
|
||||||
import * as profile from '../profile';
|
import * as profile from '../profile';
|
||||||
|
|
||||||
let model;
|
let model;
|
||||||
let keypoints = { };
|
let keypoints: Array<any> = [];
|
||||||
let skipped = Number.MAX_SAFE_INTEGER;
|
let skipped = Number.MAX_SAFE_INTEGER;
|
||||||
|
|
||||||
const bodyParts = ['head', 'neck', 'rightShoulder', 'rightElbow', 'rightWrist', 'chest', 'leftShoulder', 'leftElbow', 'leftWrist', 'pelvis', 'rightHip', 'rightKnee', 'rightAnkle', 'leftHip', 'leftKnee', 'leftAnkle'];
|
const bodyParts = ['head', 'neck', 'rightShoulder', 'rightElbow', 'rightWrist', 'chest', 'leftShoulder', 'leftElbow', 'leftWrist', 'pelvis', 'rightHip', 'rightKnee', 'rightAnkle', 'leftHip', 'leftKnee', 'leftAnkle'];
|
||||||
|
@ -56,9 +56,9 @@ export async function predict(image, config) {
|
||||||
let resT;
|
let resT;
|
||||||
|
|
||||||
if (!config.profile) {
|
if (!config.profile) {
|
||||||
if (config.body.enabled) resT = await model.executeAsync(tensor);
|
if (config.body.enabled) resT = await model.predict(tensor);
|
||||||
} else {
|
} else {
|
||||||
const profileT = config.body.enabled ? await tf.profile(() => model.executeAsync(tensor)) : {};
|
const profileT = config.body.enabled ? await tf.profile(() => model.predict(tensor)) : {};
|
||||||
resT = profileT.result.clone();
|
resT = profileT.result.clone();
|
||||||
profileT.result.dispose();
|
profileT.result.dispose();
|
||||||
profile.run('body', profileT);
|
profile.run('body', profileT);
|
||||||
|
@ -79,7 +79,7 @@ export async function predict(image, config) {
|
||||||
if (score > config.body.scoreThreshold) {
|
if (score > config.body.scoreThreshold) {
|
||||||
parts.push({
|
parts.push({
|
||||||
id,
|
id,
|
||||||
score,
|
score: Math.round(100 * score) / 100,
|
||||||
part: bodyParts[id],
|
part: bodyParts[id],
|
||||||
positionRaw: {
|
positionRaw: {
|
||||||
xRaw: x / model.inputs[0].shape[2], // x normalized to 0..1
|
xRaw: x / model.inputs[0].shape[2], // x normalized to 0..1
|
||||||
|
@ -95,6 +95,7 @@ export async function predict(image, config) {
|
||||||
stack.forEach((s) => tf.dispose(s));
|
stack.forEach((s) => tf.dispose(s));
|
||||||
keypoints = parts;
|
keypoints = parts;
|
||||||
}
|
}
|
||||||
resolve([{ keypoints }]);
|
const score = keypoints.reduce((prev, curr) => (curr.score > prev ? curr.score : prev), 0);
|
||||||
|
resolve([{ score, keypoints }]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ export class HandPose {
|
||||||
(prediction.box.bottomRight[0] - prediction.box.topLeft[0]) / input.shape[2],
|
(prediction.box.bottomRight[0] - prediction.box.topLeft[0]) / input.shape[2],
|
||||||
(prediction.box.bottomRight[1] - prediction.box.topLeft[1]) / input.shape[1],
|
(prediction.box.bottomRight[1] - prediction.box.topLeft[1]) / input.shape[1],
|
||||||
];
|
];
|
||||||
hands.push({ confidence: prediction.confidence, box, boxRaw, landmarks: prediction.landmarks, annotations });
|
hands.push({ confidence: Math.round(100 * prediction.confidence) / 100, box, boxRaw, landmarks: prediction.landmarks, annotations });
|
||||||
}
|
}
|
||||||
return hands;
|
return hands;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ async function process(res, inputSize, outputShape, config) {
|
||||||
const result = {
|
const result = {
|
||||||
id: id++,
|
id: id++,
|
||||||
strideSize,
|
strideSize,
|
||||||
score,
|
score: Math.round(100 * score) / 100,
|
||||||
class: j + 1,
|
class: j + 1,
|
||||||
label: labels[j].label,
|
label: labels[j].label,
|
||||||
center: [Math.trunc(outputShape[0] * cx), Math.trunc(outputShape[1] * cy)],
|
center: [Math.trunc(outputShape[0] * cx), Math.trunc(outputShape[1] * cy)],
|
||||||
|
@ -113,9 +113,9 @@ export async function predict(image, config) {
|
||||||
|
|
||||||
let objectT;
|
let objectT;
|
||||||
if (!config.profile) {
|
if (!config.profile) {
|
||||||
if (config.object.enabled) objectT = await model.executeAsync(transpose);
|
if (config.object.enabled) objectT = await model.predict(transpose);
|
||||||
} else {
|
} else {
|
||||||
const profileObject = config.object.enabled ? await tf.profile(() => model.executeAsync(transpose)) : {};
|
const profileObject = config.object.enabled ? await tf.profile(() => model.predict(transpose)) : {};
|
||||||
objectT = profileObject.result;
|
objectT = profileObject.result;
|
||||||
profile.run('object', profileObject);
|
profile.run('object', profileObject);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue