fix box clamping and raw output

pull/280/head
Vladimir Mandic 2021-03-17 14:35:11 -04:00
parent 4819930e43
commit 8523da07b5
11 changed files with 88 additions and 19 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules node_modules
private private
pnpm-lock.yaml

View File

@ -1,6 +1,6 @@
# @vladmandic/human # @vladmandic/human
Version: **1.1.7** Version: **1.1.8**
Description: **Human: AI-powered 3D Face Detection, Face Embedding & Recognition, Body Pose Tracking, Hand & Finger Tracking, Iris Analysis, Age & Gender & Emotion Prediction & Gesture Recognition** Description: **Human: AI-powered 3D Face Detection, Face Embedding & 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>**
@ -11,9 +11,12 @@ Repository: **<git+https://github.com/vladmandic/human.git>**
### **HEAD -> main** 2021/03/17 mandic00@live.com ### **HEAD -> main** 2021/03/17 mandic00@live.com
- hierarchical readme notes
### **origin/main** 2021/03/17 mandic00@live.com ### **1.1.8** 2021/03/17 mandic00@live.com
- add experimental nanodet object detection
- full models signature
- cleanup - cleanup
### **1.1.7** 2021/03/16 mandic00@live.com ### **1.1.7** 2021/03/16 mandic00@live.com

View File

@ -2,3 +2,24 @@
<br> <br>
Use your best judgement
If it will possibly make others uncomfortable, do not post it
- Be respectful
Disagreement is not an opportunity to attack someone else's thoughts or opinions. Although views may differ, remember to approach every situation with patience and care
- Be considerate
Think about how your contribution will affect others in the community
- Be open minded
Embrace new people and new ideas. Our community is continually evolving and we welcome positive change
Be mindful of your language
Any of the following behavior is unacceptable:
- Offensive comments of any kind
- Threats or intimidation
- Sexually explicit material
- Or any other kinds of harassment
If you believe someone is violating the code of conduct, we ask that you report it
Participants asked to stop any harassing behavior are expected to comply immediately

View File

@ -1,3 +1,23 @@
# Human Library: Contributing Guidelines # Human Library: Contributing Guidelines
<br> <br>
Pull requests from everyone are welcome
<br>
Procedure for contributing:
- Create a fork of the repository on github
In a top right corner of a GitHub, select "Fork"
- Clone your forked repository to your local system
`git clone https://github.com/<your-username>/<your-fork>
- Make your changes
- Test your changes against code guidelines
`npm run lint`
- Push changes to your fork
- Submit a PR (pull request) to `Human`
<https://github.com/vladmandic/human/pulls>
<br>
Your pull request will be reviewed and pending review results, merged into main branch

View File

@ -1,3 +1,7 @@
# Human Library: Security Policy # Human Library: Security Policy
<br> <br>
All issues are tracked publicly on GitHub
Entire code base and indluded dependencies is automatically scanned against known security vulnerabilities

View File

@ -5,8 +5,8 @@ After=network.target network-online.target
[Service] [Service]
Type=simple Type=simple
Environment="NODE_ENV=production" Environment="NODE_ENV=production"
ExecStart=/home/vlado/.nvm/versions/node/v15.7.0/bin/node server/serve.js ExecStart=<path-to-node> server/serve.js
WorkingDirectory=/home/vlado/dev/human WorkingDirectory=<your-project-folder>
StandardOutput=inherit StandardOutput=inherit
StandardError=inherit StandardError=inherit
Restart=always Restart=always

View File

@ -18,6 +18,7 @@ export const drawOptions = {
useDepth: <Boolean>true, useDepth: <Boolean>true,
useCurves: <Boolean>false, useCurves: <Boolean>false,
bufferedOutput: <Boolean>false, bufferedOutput: <Boolean>false,
useRawBoxes: <Boolean>false,
}; };
function point(ctx, x, y, z = null) { function point(ctx, x, y, z = null) {
@ -121,8 +122,8 @@ export async function face(inCanvas, result) {
ctx.strokeStyle = drawOptions.color; ctx.strokeStyle = drawOptions.color;
ctx.fillStyle = drawOptions.color; ctx.fillStyle = drawOptions.color;
if (drawOptions.drawBoxes) { if (drawOptions.drawBoxes) {
rect(ctx, f.box[0], f.box[1], f.box[2], f.box[3]); if (drawOptions.useRawBoxes) rect(ctx, inCanvas.width * f.boxRaw[0], inCanvas.height * f.boxRaw[1], inCanvas.width * f.boxRaw[2], inCanvas.height * f.boxRaw[3]);
// rect(ctx, inCanvas.width * f.boxRaw[0], inCanvas.height * f.boxRaw[1], inCanvas.width * f.boxRaw[2], inCanvas.height * f.boxRaw[3]); else rect(ctx, f.box[0], f.box[1], f.box[2], f.box[3]);
} }
// silly hack since fillText does not suport new line // silly hack since fillText does not suport new line
const labels:string[] = []; const labels:string[] = [];
@ -305,7 +306,8 @@ export async function hand(inCanvas, result) {
if (drawOptions.drawBoxes) { if (drawOptions.drawBoxes) {
ctx.strokeStyle = drawOptions.color; ctx.strokeStyle = drawOptions.color;
ctx.fillStyle = drawOptions.color; ctx.fillStyle = drawOptions.color;
rect(ctx, h.box[0], h.box[1], h.box[2], h.box[3]); if (drawOptions.useRawBoxes) rect(ctx, inCanvas.width * h.boxRaw[0], inCanvas.height * h.boxRaw[1], inCanvas.width * h.boxRaw[2], inCanvas.height * h.boxRaw[3]);
else rect(ctx, h.box[0], h.box[1], h.box[2], h.box[3]);
if (drawOptions.drawLabels) { if (drawOptions.drawLabels) {
if (drawOptions.shadowColor && drawOptions.shadowColor !== '') { if (drawOptions.shadowColor && drawOptions.shadowColor !== '') {
ctx.fillStyle = drawOptions.shadowColor; ctx.fillStyle = drawOptions.shadowColor;
@ -357,7 +359,8 @@ export async function object(inCanvas, result) {
if (drawOptions.drawBoxes) { if (drawOptions.drawBoxes) {
ctx.strokeStyle = drawOptions.color; ctx.strokeStyle = drawOptions.color;
ctx.fillStyle = drawOptions.color; ctx.fillStyle = drawOptions.color;
rect(ctx, h.box[0], h.box[1], h.box[2] - h.box[0], h.box[3] - h.box[1]); if (drawOptions.useRawBoxes) rect(ctx, inCanvas.width * h.boxRaw[0], inCanvas.height * h.boxRaw[1], inCanvas.width * h.boxRaw[2], inCanvas.height * h.boxRaw[3]);
else rect(ctx, h.box[0], h.box[1], h.box[2], h.box[3]);
if (drawOptions.drawLabels) { if (drawOptions.drawLabels) {
const label = `${Math.round(100 * h.score)}% ${h.label}`; const label = `${Math.round(100 * h.score)}% ${h.label}`;
if (drawOptions.shadowColor && drawOptions.shadowColor !== '') { if (drawOptions.shadowColor && drawOptions.shadowColor !== '') {

View File

@ -29,7 +29,7 @@ export class HandPose {
async estimateHands(input, config) { async estimateHands(input, config) {
const predictions = await this.handPipeline.estimateHands(input, config); const predictions = await this.handPipeline.estimateHands(input, config);
if (!predictions) return []; if (!predictions) return [];
const hands: Array<{ confidence: number, box: any, landmarks: any, annotations: any }> = []; const hands: Array<{ confidence: number, box: any, boxRaw: any, landmarks: any, annotations: any }> = [];
for (const prediction of predictions) { for (const prediction of predictions) {
const annotations = {}; const annotations = {};
if (prediction.landmarks) { if (prediction.landmarks) {
@ -40,10 +40,16 @@ export class HandPose {
const box = prediction.box ? [ const box = prediction.box ? [
Math.max(0, prediction.box.topLeft[0]), Math.max(0, prediction.box.topLeft[0]),
Math.max(0, prediction.box.topLeft[1]), Math.max(0, prediction.box.topLeft[1]),
Math.min(input.shape[2], prediction.box.bottomRight[0]) - prediction.box.topLeft[0], Math.min(input.shape[2], prediction.box.bottomRight[0]) - Math.max(0, prediction.box.topLeft[0]),
Math.min(input.shape[1], prediction.box.bottomRight[1]) - prediction.box.topLeft[1], Math.min(input.shape[1], prediction.box.bottomRight[1]) - Math.max(0, prediction.box.topLeft[1]),
] : 0; ] : [];
hands.push({ confidence: prediction.confidence, box, landmarks: prediction.landmarks, annotations }); const boxRaw = [
(prediction.box.topLeft[0]) / input.shape[2],
(prediction.box.topLeft[1]) / input.shape[1],
(prediction.box.bottomRight[0] - prediction.box.topLeft[0]) / input.shape[2],
(prediction.box.bottomRight[1] - prediction.box.topLeft[1]) / input.shape[1],
];
hands.push({ confidence: prediction.confidence, box, boxRaw, landmarks: prediction.landmarks, annotations });
} }
return hands; return hands;
} }

View File

@ -54,6 +54,7 @@ export type Result = {
hand: Array<{ hand: Array<{
confidence: Number, confidence: Number,
box: [Number, Number, Number, Number], box: [Number, Number, Number, Number],
boxRaw: [Number, Number, Number, Number],
landmarks: Array<[Number, Number, Number]>, landmarks: Array<[Number, Number, Number]>,
annotations: Array<{ part: String, points: Array<[Number, Number, Number]>[] }>, annotations: Array<{ part: String, points: Array<[Number, Number, Number]>[] }>,
}>, }>,
@ -595,7 +596,17 @@ export class Human {
this.#perf.total = Math.trunc(now() - timeStart); this.#perf.total = Math.trunc(now() - timeStart);
this.state = 'idle'; this.state = 'idle';
resolve({ face: faceRes, body: bodyRes, hand: handRes, gesture: gestureRes, object: objectRes, performance: this.#perf, canvas: process.canvas }); const result = {
face: faceRes,
body: bodyRes,
hand: handRes,
gesture: gestureRes,
object: objectRes,
performance: this.#perf,
canvas: process.canvas,
};
// log('Result:', result);
resolve(result);
}); });
} }

View File

@ -49,10 +49,10 @@ async function process(res, inputSize, outputShape, config) {
]; ];
boxRaw = boxRaw.map((a) => Math.max(0, Math.min(a, 1))); // fix out-of-bounds coords boxRaw = boxRaw.map((a) => Math.max(0, Math.min(a, 1))); // fix out-of-bounds coords
const box = [ // results normalized to input image pixels const box = [ // results normalized to input image pixels
boxRaw[0] * outputShape[0], Math.max(0, (boxRaw[0] * outputShape[0])),
boxRaw[1] * outputShape[1], Math.max(0, (boxRaw[1] * outputShape[1])),
boxRaw[2] * outputShape[0], Math.min(1, (boxRaw[2] * outputShape[0]) - (boxRaw[0] * outputShape[0])),
boxRaw[3] * outputShape[1], Math.min(1, (boxRaw[3] * outputShape[1]) - (boxRaw[1] * outputShape[1])),
]; ];
const result = { const result = {
score: scoresMax[i], score: scoresMax[i],

2
wiki

@ -1 +1 @@
Subproject commit 99c3d70ec78fbbe0d12528c1d4b18ba1d27fef0d Subproject commit 91af84e9543762c4f31be41dda15fb2a5549d8a6