update posenet model

pull/134/head
Vladimir Mandic 2021-04-24 11:49:26 -04:00
parent 59cf501bcd
commit 8440d78d5f
47 changed files with 1176 additions and 1108 deletions

View File

@ -9,11 +9,15 @@ Repository: **<git+https://github.com/vladmandic/human.git>**
## Changelog ## Changelog
### **HEAD -> main** 2021/04/24 mandic00@live.com
### **origin/main** 2021/04/22 mandic00@live.com
### **1.6.1** 2021/04/22 mandic00@live.com ### **1.6.1** 2021/04/22 mandic00@live.com
- add npmrc
### **origin/main** 2021/04/20 mandic00@live.com
- added filter.flip feature - added filter.flip feature
- added demo load image from http - added demo load image from http
- mobile demo optimization and iris gestures - mobile demo optimization and iris gestures

View File

@ -208,7 +208,7 @@ Default models in Human library are:
- **Face Description**: HSE FaceRes - **Face Description**: HSE FaceRes
- **Face Iris Analysis**: MediaPipe Iris - **Face Iris Analysis**: MediaPipe Iris
- **Emotion Detection**: Oarriaga Emotion - **Emotion Detection**: Oarriaga Emotion
- **Body Analysis**: PoseNet - **Body Analysis**: PoseNet (AtomicBits version)
Note that alternative models are provided and can be enabled via configuration Note that alternative models are provided and can be enabled via configuration
For example, `PoseNet` model can be switched for `BlazePose` model depending on the use case For example, `PoseNet` model can be switched for `BlazePose` model depending on the use case

View File

@ -29,7 +29,7 @@ const userConfig = {
}, },
hand: { enabled: false }, hand: { enabled: false },
gesture: { enabled: true }, gesture: { enabled: true },
body: { enabled: false }, body: { enabled: true, modelPath: 'posenet.json' },
// body: { enabled: true, modelPath: 'blazepose.json' }, // body: { enabled: true, modelPath: 'blazepose.json' },
// object: { enabled: true }, // object: { enabled: true },
}; };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

456
dist/human.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

456
dist/human.js vendored

File diff suppressed because one or more lines are too long

6
dist/human.js.map vendored

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

14
dist/human.node.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -68,8 +68,8 @@
"canvas": "^2.7.0", "canvas": "^2.7.0",
"chokidar": "^3.5.1", "chokidar": "^3.5.1",
"dayjs": "^1.10.4", "dayjs": "^1.10.4",
"esbuild": "^0.11.12", "esbuild": "^0.11.14",
"eslint": "^7.24.0", "eslint": "^7.25.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",
@ -80,7 +80,7 @@
"seedrandom": "^3.0.5", "seedrandom": "^3.0.5",
"simple-git": "^2.38.0", "simple-git": "^2.38.0",
"tslib": "^2.2.0", "tslib": "^2.2.0",
"typedoc": "^0.20.35", "typedoc": "^0.20.36",
"typescript": "^4.2.4" "typescript": "^4.2.4"
} }
} }

View File

@ -134,3 +134,20 @@
2021-04-22 19:46:37 INFO:  Generate types: ["src/human.ts"] 2021-04-22 19:46:37 INFO:  Generate types: ["src/human.ts"]
2021-04-22 19:46:41 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"] 2021-04-22 19:46:41 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-22 19:46:41 INFO:  Generate TypeDocs: ["src/human.ts"] 2021-04-22 19:46:41 INFO:  Generate TypeDocs: ["src/human.ts"]
2021-04-24 11:48:49 INFO:  @vladmandic/human version 1.6.1
2021-04-24 11:48:49 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-24 11:48:49 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true,"sourcemap":true,"bundle":true,"metafile":true,"target":"es2018"}
2021-04-24 11:48:49 STATE: Build for: node type: tfjs: {"imports":1,"importBytes":39,"outputBytes":733,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 11:48:49 STATE: Build for: node type: node: {"imports":43,"importBytes":547909,"outputBytes":306333,"outputFiles":"dist/human.node.js"}
2021-04-24 11:48:49 STATE: Build for: nodeGPU type: tfjs: {"imports":1,"importBytes":43,"outputBytes":737,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 11:48:49 STATE: Build for: nodeGPU type: node: {"imports":43,"importBytes":547913,"outputBytes":306341,"outputFiles":"dist/human.node-gpu.js"}
2021-04-24 11:48:49 STATE: Build for: nodeWASM type: tfjs: {"imports":1,"importBytes":81,"outputBytes":783,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 11:48:49 STATE: Build for: nodeWASM type: node: {"imports":43,"importBytes":547959,"outputBytes":306385,"outputFiles":"dist/human.node-wasm.js"}
2021-04-24 11:48:49 STATE: Build for: browserNoBundle type: tfjs: {"imports":1,"importBytes":2488,"outputBytes":1394,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 11:48:49 STATE: Build for: browserNoBundle type: esm: {"imports":43,"importBytes":548570,"outputBytes":306337,"outputFiles":"dist/human.esm-nobundle.js"}
2021-04-24 11:48:50 STATE: Build for: browserBundle type: tfjs: {"modules":1267,"moduleBytes":4085087,"imports":7,"importBytes":2488,"outputBytes":1101728,"outputFiles":"dist/tfjs.esm.js"}
2021-04-24 11:48:51 STATE: Build for: browserBundle type: iife: {"imports":43,"importBytes":1648904,"outputBytes":1404224,"outputFiles":"dist/human.js"}
2021-04-24 11:48:51 STATE: Build for: browserBundle type: esm: {"imports":43,"importBytes":1648904,"outputBytes":1404182,"outputFiles":"dist/human.esm.js"}
2021-04-24 11:48:51 INFO:  Generate types: ["src/human.ts"]
2021-04-24 11:48:56 INFO:  Update Change log: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-04-24 11:48:56 INFO:  Generate TypeDocs: ["src/human.ts"]

View File

@ -363,7 +363,7 @@ const config: Config = {
// can be either absolute path or relative to modelBasePath // can be either absolute path or relative to modelBasePath
// can be 'posenet', 'blazepose' or 'efficientpose' // can be 'posenet', 'blazepose' or 'efficientpose'
// 'blazepose' and 'efficientpose' are experimental // 'blazepose' and 'efficientpose' are experimental
maxDetections: 10, // maximum number of people detected in the input maxDetections: 1, // maximum number of people detected in the input
// should be set to the minimum number for performance // should be set to the minimum number for performance
// only valid for posenet as blazepose only detects single pose // only valid for posenet as blazepose only detects single pose
scoreThreshold: 0.3, // threshold for deciding when to remove boxes based on score scoreThreshold: 0.3, // threshold for deciding when to remove boxes based on score

View File

@ -55,7 +55,7 @@ export const options: DrawOptions = {
roundRect: <number>28, roundRect: <number>28,
drawPoints: <Boolean>false, drawPoints: <Boolean>false,
drawLabels: <Boolean>true, drawLabels: <Boolean>true,
drawBoxes: <Boolean>true, drawBoxes: <Boolean>false,
drawPolygons: <Boolean>true, drawPolygons: <Boolean>true,
fillPolygons: <Boolean>false, fillPolygons: <Boolean>false,
useDepth: <Boolean>true, useDepth: <Boolean>true,
@ -253,7 +253,20 @@ export async function body(inCanvas: HTMLCanvasElement, result: Array<any>, draw
// result[i].keypoints = result[i].keypoints.filter((a) => a.score > 0.5); // result[i].keypoints = result[i].keypoints.filter((a) => a.score > 0.5);
if (!lastDrawnPose[i] && localOptions.bufferedOutput) lastDrawnPose[i] = { ...result[i] }; if (!lastDrawnPose[i] && localOptions.bufferedOutput) lastDrawnPose[i] = { ...result[i] };
ctx.strokeStyle = localOptions.color; ctx.strokeStyle = localOptions.color;
ctx.fillStyle = localOptions.color;
ctx.lineWidth = localOptions.lineWidth; ctx.lineWidth = localOptions.lineWidth;
ctx.font = localOptions.font;
if (localOptions.drawBoxes) {
rect(ctx, result[i].box[0], result[i].box[1], result[i].box[2], result[i].box[3], localOptions);
if (localOptions.drawLabels) {
if (localOptions.shadowColor && localOptions.shadowColor !== '') {
ctx.fillStyle = localOptions.shadowColor;
ctx.fillText(`body ${100 * result[i].score}%`, result[i].box[0] + 3, 1 + result[i].box[1] + localOptions.lineHeight, result[i].box[2]);
}
ctx.fillStyle = localOptions.labelColor;
ctx.fillText(`body ${100 * result[i].score}%`, result[i].box[0] + 2, 0 + result[i].box[1] + localOptions.lineHeight, result[i].box[2]);
}
}
if (localOptions.drawPoints) { if (localOptions.drawPoints) {
for (let pt = 0; pt < result[i].keypoints.length; pt++) { for (let pt = 0; pt < result[i].keypoints.length; pt++) {
ctx.fillStyle = localOptions.useDepth && result[i].keypoints[pt].position.z ? `rgba(${127.5 + (2 * result[i].keypoints[pt].position.z)}, ${127.5 - (2 * result[i].keypoints[pt].position.z)}, 255, 0.5)` : localOptions.color; ctx.fillStyle = localOptions.useDepth && result[i].keypoints[pt].position.z ? `rgba(${127.5 + (2 * result[i].keypoints[pt].position.z)}, ${127.5 - (2 * result[i].keypoints[pt].position.z)}, 255, 0.5)` : localOptions.color;
@ -271,7 +284,7 @@ export async function body(inCanvas: HTMLCanvasElement, result: Array<any>, draw
if (result[i].keypoints) { if (result[i].keypoints) {
for (const pt of result[i].keypoints) { for (const pt of result[i].keypoints) {
ctx.fillStyle = localOptions.useDepth && pt.position.z ? `rgba(${127.5 + (2 * pt.position.z)}, ${127.5 - (2 * pt.position.z)}, 255, 0.5)` : localOptions.color; ctx.fillStyle = localOptions.useDepth && pt.position.z ? `rgba(${127.5 + (2 * pt.position.z)}, ${127.5 - (2 * pt.position.z)}, 255, 0.5)` : localOptions.color;
ctx.fillText(`${pt.part}`, pt.position.x + 4, pt.position.y + 4); ctx.fillText(`${pt.part} ${Math.trunc(100 * pt.score)}%`, pt.position.x + 4, pt.position.y + 4);
} }
} }
} }

View File

@ -1,39 +0,0 @@
import * as heapSort from './heapSort';
function scoreIsMaximumInLocalWindow(keypointId, score, heatmapY, heatmapX, localMaximumRadius, scores) {
const [height, width] = scores.shape;
let localMaximum = true;
const yStart = Math.max(heatmapY - localMaximumRadius, 0);
const yEnd = Math.min(heatmapY + localMaximumRadius + 1, height);
for (let yCurrent = yStart; yCurrent < yEnd; ++yCurrent) {
const xStart = Math.max(heatmapX - localMaximumRadius, 0);
const xEnd = Math.min(heatmapX + localMaximumRadius + 1, width);
for (let xCurrent = xStart; xCurrent < xEnd; ++xCurrent) {
if (scores.get(yCurrent, xCurrent, keypointId) > score) {
localMaximum = false;
break;
}
}
if (!localMaximum) break;
}
return localMaximum;
}
export function buildPartWithScoreQueue(scoreThreshold, localMaximumRadius, scores) {
const [height, width, numKeypoints] = scores.shape;
const queue = new heapSort.MaxHeap(height * width * numKeypoints, ({ score }) => score);
for (let heatmapY = 0; heatmapY < height; ++heatmapY) {
for (let heatmapX = 0; heatmapX < width; ++heatmapX) {
for (let keypointId = 0; keypointId < numKeypoints; ++keypointId) {
const score = scores.get(heatmapY, heatmapX, keypointId);
// Only consider parts with score greater or equal to threshold as root candidates.
if (score < scoreThreshold) continue;
// Only consider keypoints whose score is maximum in a local window.
if (scoreIsMaximumInLocalWindow(keypointId, score, heatmapY, heatmapX, localMaximumRadius, scores)) {
queue.enqueue({ score, part: { heatmapY, heatmapX, id: keypointId } });
}
}
}
}
return queue;
}

View File

@ -1,14 +1,51 @@
import * as buildParts from './buildParts'; import * as decodeSingle from './decodeSingle';
import * as decodePose from './decodePose'; import * as utils from './utils';
import * as vectors from './vectors';
const kLocalMaximumRadius = 1; const kLocalMaximumRadius = 1;
const defaultOutputStride = 16; const defaultOutputStride = 16;
function scoreIsMaximumInLocalWindow(keypointId, score, heatmapY, heatmapX, localMaximumRadius, scores) {
const [height, width] = scores.shape;
let localMaximum = true;
const yStart = Math.max(heatmapY - localMaximumRadius, 0);
const yEnd = Math.min(heatmapY + localMaximumRadius + 1, height);
for (let yCurrent = yStart; yCurrent < yEnd; ++yCurrent) {
const xStart = Math.max(heatmapX - localMaximumRadius, 0);
const xEnd = Math.min(heatmapX + localMaximumRadius + 1, width);
for (let xCurrent = xStart; xCurrent < xEnd; ++xCurrent) {
if (scores.get(yCurrent, xCurrent, keypointId) > score) {
localMaximum = false;
break;
}
}
if (!localMaximum) break;
}
return localMaximum;
}
export function buildPartWithScoreQueue(scoreThreshold, localMaximumRadius, scores) {
const [height, width, numKeypoints] = scores.shape;
const queue = new utils.MaxHeap(height * width * numKeypoints, ({ score }) => score);
for (let heatmapY = 0; heatmapY < height; ++heatmapY) {
for (let heatmapX = 0; heatmapX < width; ++heatmapX) {
for (let keypointId = 0; keypointId < numKeypoints; ++keypointId) {
const score = scores.get(heatmapY, heatmapX, keypointId);
// Only consider parts with score greater or equal to threshold as root candidates.
if (score < scoreThreshold) continue;
// Only consider keypoints whose score is maximum in a local window.
if (scoreIsMaximumInLocalWindow(keypointId, score, heatmapY, heatmapX, localMaximumRadius, scores)) {
queue.enqueue({ score, part: { heatmapY, heatmapX, id: keypointId } });
}
}
}
}
return queue;
}
function withinNmsRadiusOfCorrespondingPoint(poses, squaredNmsRadius, { x, y }, keypointId) { function withinNmsRadiusOfCorrespondingPoint(poses, squaredNmsRadius, { x, y }, keypointId) {
return poses.some(({ keypoints }) => { return poses.some(({ keypoints }) => {
const correspondingKeypoint = keypoints[keypointId].position; const correspondingKeypoint = keypoints[keypointId].position;
return vectors.squaredDistance(y, x, correspondingKeypoint.y, correspondingKeypoint.x) <= squaredNmsRadius; return utils.squaredDistance(y, x, correspondingKeypoint.y, correspondingKeypoint.x) <= squaredNmsRadius;
}); });
} }
@ -21,20 +58,21 @@ function getInstanceScore(existingPoses, squaredNmsRadius, instanceKeypoints) {
} }
export function decodeMultiplePoses(scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer, nmsRadius, maxDetections, scoreThreshold) { export function decodeMultiplePoses(scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer, nmsRadius, maxDetections, scoreThreshold) {
const poses: Array<{ keypoints: any, score: number }> = []; const poses: Array<{ keypoints: any, box: any, score: number }> = [];
const queue = buildParts.buildPartWithScoreQueue(scoreThreshold, kLocalMaximumRadius, scoresBuffer); const queue = buildPartWithScoreQueue(scoreThreshold, kLocalMaximumRadius, scoresBuffer);
const squaredNmsRadius = nmsRadius ^ 2; const squaredNmsRadius = nmsRadius ^ 2;
// Generate at most maxDetections object instances per image in decreasing root part score order. // Generate at most maxDetections object instances per image in decreasing root part score order.
while (poses.length < maxDetections && !queue.empty()) { while (poses.length < maxDetections && !queue.empty()) {
// The top element in the queue is the next root candidate. // The top element in the queue is the next root candidate.
const root = queue.dequeue(); const root = queue.dequeue();
// Part-based non-maximum suppression: We reject a root candidate if it is within a disk of `nmsRadius` pixels from the corresponding part of a previously detected instance. // Part-based non-maximum suppression: We reject a root candidate if it is within a disk of `nmsRadius` pixels from the corresponding part of a previously detected instance.
const rootImageCoords = vectors.getImageCoords(root.part, defaultOutputStride, offsetsBuffer); const rootImageCoords = utils.getImageCoords(root.part, defaultOutputStride, offsetsBuffer);
if (withinNmsRadiusOfCorrespondingPoint(poses, squaredNmsRadius, rootImageCoords, root.part.id)) continue; if (withinNmsRadiusOfCorrespondingPoint(poses, squaredNmsRadius, rootImageCoords, root.part.id)) continue;
// Else start a new detection instance at the position of the root. // Else start a new detection instance at the position of the root.
const keypoints = decodePose.decodePose(root, scoresBuffer, offsetsBuffer, defaultOutputStride, displacementsFwdBuffer, displacementsBwdBuffer); const keypoints = decodeSingle.decodePose(root, scoresBuffer, offsetsBuffer, defaultOutputStride, displacementsFwdBuffer, displacementsBwdBuffer);
const score = getInstanceScore(poses, squaredNmsRadius, keypoints); const score = getInstanceScore(poses, squaredNmsRadius, keypoints);
if (score > scoreThreshold) poses.push({ keypoints, score: Math.round(100 * score) / 100 }); const box = utils.getBoundingBox(keypoints);
if (score > scoreThreshold) poses.push({ keypoints, box, score: Math.round(100 * score) / 100 });
} }
return poses; return poses;
} }

View File

@ -0,0 +1,48 @@
import * as tf from '../../dist/tfjs.esm.js';
import * as keypoints from './keypoints';
export function getPointsConfidence(heatmapScores, heatMapCoords) {
const numKeypoints = keypoints.count; // also in heatMapCoords.shape[0];
const result:Array<number> = [];
for (let keypoint = 0; keypoint < numKeypoints; keypoint++) {
const y = heatMapCoords.get(keypoint, 0);
const x = heatMapCoords.get(keypoint, 1);
result.push(heatmapScores.get(y, x, keypoint));
}
return result;
}
export function getOffsetPoints(heatMapCoordsBuffer, outputStride, offsetsBuffer) {
const getOffsetPoint = (y, x, keypoint) => ([
offsetsBuffer.get(y, x, keypoint),
offsetsBuffer.get(y, x, keypoint + keypoints.count),
]);
const getOffsetVectors = () => {
const result: Array<number[]> = [];
for (let keypoint = 0; keypoint < keypoints.count; keypoint++) {
const heatmapY = heatMapCoordsBuffer.get(keypoint, 0);
const heatmapX = heatMapCoordsBuffer.get(keypoint, 1);
result.push(getOffsetPoint(heatmapY, heatmapX, keypoint));
}
return result;
};
return tf.tidy(() => heatMapCoordsBuffer.toTensor().mul(tf.scalar(outputStride, 'int32')).toFloat().add(getOffsetVectors()));
}
export function argmax2d(inputs) {
const mod = (a, b) => tf.tidy(() => {
const floored = a.div(tf.scalar(b, 'int32'));
return a.sub(floored.mul(tf.scalar(b, 'int32')));
});
const [height, width, depth] = inputs.shape;
return tf.tidy(() => {
const reshaped = inputs.reshape([height * width, depth]);
const coords = reshaped.argMax(0);
const yCoords = coords.div(tf.scalar(width, 'int32')).expandDims(1);
const xCoords = mod(coords, width).expandDims(1);
return tf.concat([yCoords, xCoords], 1);
});
}

View File

@ -1,6 +1,6 @@
import * as keypoints from './keypoints'; import * as keypoints from './keypoints';
import * as vectors from './vectors'; import * as decoders from './decodeParts';
import * as decoders from './decoders'; import * as utils from './utils';
const parentChildrenTuples = keypoints.poseChain.map(([parentJoinName, childJoinName]) => ([keypoints.partIds[parentJoinName], keypoints.partIds[childJoinName]])); const parentChildrenTuples = keypoints.poseChain.map(([parentJoinName, childJoinName]) => ([keypoints.partIds[parentJoinName], keypoints.partIds[childJoinName]]));
const parentToChildEdges = parentChildrenTuples.map(([, childJointId]) => childJointId); const parentToChildEdges = parentChildrenTuples.map(([, childJointId]) => childJointId);
@ -18,8 +18,8 @@ function getDisplacement(edgeId, point, displacements) {
function getStridedIndexNearPoint(point, outputStride, height, width) { function getStridedIndexNearPoint(point, outputStride, height, width) {
return { return {
y: vectors.clamp(Math.round(point.y / outputStride), 0, height - 1), y: utils.clamp(Math.round(point.y / outputStride), 0, height - 1),
x: vectors.clamp(Math.round(point.x / outputStride), 0, width - 1), x: utils.clamp(Math.round(point.x / outputStride), 0, width - 1),
}; };
} }
@ -28,12 +28,12 @@ function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scor
// Nearest neighbor interpolation for the source->target displacements. // Nearest neighbor interpolation for the source->target displacements.
const sourceKeypointIndices = getStridedIndexNearPoint(sourceKeypoint.position, outputStride, height, width); const sourceKeypointIndices = getStridedIndexNearPoint(sourceKeypoint.position, outputStride, height, width);
const displacement = getDisplacement(edgeId, sourceKeypointIndices, displacements); const displacement = getDisplacement(edgeId, sourceKeypointIndices, displacements);
const displacedPoint = vectors.addVectors(sourceKeypoint.position, displacement); const displacedPoint = utils.addVectors(sourceKeypoint.position, displacement);
let targetKeypoint = displacedPoint; let targetKeypoint = displacedPoint;
for (let i = 0; i < offsetRefineStep; i++) { for (let i = 0; i < offsetRefineStep; i++) {
const targetKeypointIndices = getStridedIndexNearPoint(targetKeypoint, outputStride, height, width); const targetKeypointIndices = getStridedIndexNearPoint(targetKeypoint, outputStride, height, width);
const offsetPoint = vectors.getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetKeypointId, offsets); const offsetPoint = utils.getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetKeypointId, offsets);
targetKeypoint = vectors.addVectors({ targetKeypoint = utils.addVectors({
x: targetKeypointIndices.x * outputStride, x: targetKeypointIndices.x * outputStride,
y: targetKeypointIndices.y * outputStride, y: targetKeypointIndices.y * outputStride,
}, { x: offsetPoint.x, y: offsetPoint.y }); }, { x: offsetPoint.x, y: offsetPoint.y });
@ -49,7 +49,7 @@ export function decodePose(root, scores, offsets, outputStride, displacementsFwd
const instanceKeypoints = new Array(numParts); const instanceKeypoints = new Array(numParts);
// Start a new detection instance at the position of the root. // Start a new detection instance at the position of the root.
const { part: rootPart, score: rootScore } = root; const { part: rootPart, score: rootScore } = root;
const rootPoint = vectors.getImageCoords(rootPart, outputStride, offsets); const rootPoint = utils.getImageCoords(rootPart, outputStride, offsets);
instanceKeypoints[rootPart.id] = { instanceKeypoints[rootPart.id] = {
score: rootScore, score: rootScore,
part: keypoints.partNames[rootPart.id], part: keypoints.partNames[rootPart.id],
@ -75,28 +75,30 @@ export function decodePose(root, scores, offsets, outputStride, displacementsFwd
} }
export async function decodeSinglePose(heatmapScores, offsets, minScore) { export async function decodeSinglePose(heatmapScores, offsets, minScore) {
let totalScore = 0.0;
const heatmapValues = decoders.argmax2d(heatmapScores); const heatmapValues = decoders.argmax2d(heatmapScores);
const allTensorBuffers = await Promise.all([heatmapScores.buffer(), offsets.buffer(), heatmapValues.buffer()]); const allTensorBuffers = await Promise.all([heatmapScores.buffer(), offsets.buffer(), heatmapValues.buffer()]);
const scoresBuffer = allTensorBuffers[0]; const scoresBuffer = allTensorBuffers[0];
const offsetsBuffer = allTensorBuffers[1]; const offsetsBuffer = allTensorBuffers[1];
const heatmapValuesBuffer = allTensorBuffers[2]; const heatmapValuesBuffer = allTensorBuffers[2];
const offsetPoints = decoders.getOffsetPoints(heatmapValuesBuffer, defaultOutputStride, offsetsBuffer); const offsetPoints = decoders.getOffsetPoints(heatmapValuesBuffer, defaultOutputStride, offsetsBuffer);
const offsetPointsBuffer = await offsetPoints.buffer(); const offsetPointsData = offsetPoints.dataSync();
const keypointConfidence = Array.from(decoders.getPointsConfidence(scoresBuffer, heatmapValuesBuffer)); const keypointConfidence = decoders.getPointsConfidence(scoresBuffer, heatmapValuesBuffer);
const instanceKeypoints = keypointConfidence.map((score, i) => { let avgScore = 0.0;
totalScore += score; const filteredKeypoints = keypointConfidence
.filter((score) => score > minScore)
.map((score, i) => {
avgScore += score;
return { return {
position: { position: {
y: offsetPointsBuffer.get(i, 0), y: offsetPointsData[2 * i + 0], // offsetPointsBuffer.get(i, 0),
x: offsetPointsBuffer.get(i, 1), x: offsetPointsData[2 * i + 1], // offsetPointsBuffer.get(i, 1),
}, },
part: keypoints.partNames[i], part: keypoints.partNames[i],
score, score,
}; };
}); });
const filteredKeypoints = instanceKeypoints.filter((kpt) => kpt.score > minScore);
heatmapValues.dispose(); heatmapValues.dispose();
offsetPoints.dispose(); offsetPoints.dispose();
return { keypoints: filteredKeypoints, score: totalScore / instanceKeypoints.length }; const box = utils.getBoundingBox(filteredKeypoints);
return { keypoints: filteredKeypoints, box, score: Math.round(100 * avgScore / filteredKeypoints.length) / 100 };
} }

View File

@ -1,54 +0,0 @@
import * as tf from '../../dist/tfjs.esm.js';
import * as kpt from './keypoints';
export function getPointsConfidence(heatmapScores, heatMapCoords) {
const numKeypoints = heatMapCoords.shape[0];
const result = new Float32Array(numKeypoints);
for (let keypoint = 0; keypoint < numKeypoints; keypoint++) {
const y = heatMapCoords.get(keypoint, 0);
const x = heatMapCoords.get(keypoint, 1);
result[keypoint] = heatmapScores.get(y, x, keypoint);
}
return result;
}
function getOffsetPoint(y, x, keypoint, offsetsBuffer) {
return {
y: offsetsBuffer.get(y, x, keypoint),
x: offsetsBuffer.get(y, x, keypoint + kpt.NUM_KEYPOINTS),
};
}
export function getOffsetVectors(heatMapCoordsBuffer, offsetsBuffer) {
const result: Array<number> = [];
for (let keypoint = 0; keypoint < kpt.NUM_KEYPOINTS; keypoint++) {
const heatmapY = heatMapCoordsBuffer.get(keypoint, 0).valueOf();
const heatmapX = heatMapCoordsBuffer.get(keypoint, 1).valueOf();
const { x, y } = getOffsetPoint(heatmapY, heatmapX, keypoint, offsetsBuffer);
result.push(y);
result.push(x);
}
return tf.tensor2d(result, [kpt.NUM_KEYPOINTS, 2]);
}
export function getOffsetPoints(heatMapCoordsBuffer, outputStride, offsetsBuffer) {
return tf.tidy(() => heatMapCoordsBuffer.toTensor().mul(tf.scalar(outputStride, 'int32')).toFloat().add(getOffsetVectors(heatMapCoordsBuffer, offsetsBuffer)));
}
function mod(a, b) {
return tf.tidy(() => {
const floored = a.div(tf.scalar(b, 'int32'));
return a.sub(floored.mul(tf.scalar(b, 'int32')));
});
}
export function argmax2d(inputs) {
const [height, width, depth] = inputs.shape;
return tf.tidy(() => {
const reshaped = inputs.reshape([height * width, depth]);
const coords = reshaped.argMax(0);
const yCoords = coords.div(tf.scalar(width, 'int32')).expandDims(1);
const xCoords = mod(coords, width).expandDims(1);
return tf.concat([yCoords, xCoords], 1);
});
}

View File

@ -1,75 +0,0 @@
// algorithm based on Coursera Lecture from Algorithms, Part 1: https://www.coursera.org/learn/algorithms-part1/lecture/ZjoSM/heapsort
function half(k) {
return Math.floor(k / 2);
}
export class MaxHeap {
priorityQueue: any;
numberOfElements: number;
getElementValue: any;
constructor(maxSize, getElementValue) {
this.priorityQueue = new Array(maxSize);
this.numberOfElements = -1;
this.getElementValue = getElementValue;
}
enqueue(x) {
this.priorityQueue[++this.numberOfElements] = x;
this.swim(this.numberOfElements);
}
dequeue() {
const max = this.priorityQueue[0];
this.exchange(0, this.numberOfElements--);
this.sink(0);
this.priorityQueue[this.numberOfElements + 1] = null;
return max;
}
empty() {
return this.numberOfElements === -1;
}
size() {
return this.numberOfElements + 1;
}
all() {
return this.priorityQueue.slice(0, this.numberOfElements + 1);
}
max() {
return this.priorityQueue[0];
}
swim(k) {
while (k > 0 && this.less(half(k), k)) {
this.exchange(k, half(k));
k = half(k);
}
}
sink(k) {
while (2 * k <= this.numberOfElements) {
let j = 2 * k;
if (j < this.numberOfElements && this.less(j, j + 1)) j++;
if (!this.less(k, j)) break;
this.exchange(k, j);
k = j;
}
}
getValueAt(i) {
return this.getElementValue(this.priorityQueue[i]);
}
less(i, j) {
return this.getValueAt(i) < this.getValueAt(j);
}
exchange(i, j) {
const t = this.priorityQueue[i];
this.priorityQueue[i] = this.priorityQueue[j];
this.priorityQueue[j] = t;
}
}

View File

@ -4,7 +4,7 @@ export const partNames = [
'leftHip', 'rightHip', 'leftKnee', 'rightKnee', 'leftAnkle', 'rightAnkle', 'leftHip', 'rightHip', 'leftKnee', 'rightKnee', 'leftAnkle', 'rightAnkle',
]; ];
export const NUM_KEYPOINTS = partNames.length; // 17 keypoints export const count = partNames.length; // 17 keypoints
export const partIds = partNames.reduce((result, jointName, i) => { export const partIds = partNames.reduce((result, jointName, i) => {
result[jointName] = i; result[jointName] = i;
@ -31,30 +31,3 @@ export const poseChain = [
['rightShoulder', 'rightHip'], ['rightHip', 'rightKnee'], ['rightShoulder', 'rightHip'], ['rightHip', 'rightKnee'],
['rightKnee', 'rightAnkle'], ['rightKnee', 'rightAnkle'],
]; ];
export const partChannels = [
'left_face',
'right_face',
'right_upper_leg_front',
'right_lower_leg_back',
'right_upper_leg_back',
'left_lower_leg_front',
'left_upper_leg_front',
'left_upper_leg_back',
'left_lower_leg_back',
'right_feet',
'right_lower_leg_front',
'left_feet',
'torso_front',
'torso_back',
'right_upper_arm_front',
'right_upper_arm_back',
'right_lower_arm_back',
'left_lower_arm_front',
'left_upper_arm_front',
'left_upper_arm_back',
'left_lower_arm_back',
'right_hand',
'right_lower_arm_front',
'left_hand',
];

View File

@ -1,26 +0,0 @@
export class ModelWeights {
variables: any;
constructor(variables) {
this.variables = variables;
}
weights(layerName) {
return this.variables[`MobilenetV1/${layerName}/weights`];
}
depthwiseBias(layerName) {
return this.variables[`MobilenetV1/${layerName}/biases`];
}
convBias(layerName) {
return this.depthwiseBias(layerName);
}
depthwiseWeights(layerName) {
return this.variables[`MobilenetV1/${layerName}/depthwise_weights`];
}
dispose() {
for (let i = 0; i < this.variables.length; i++) this.variables[i].dispose();
}
}

View File

@ -1,29 +1,31 @@
import { log, join } from '../helpers'; import { log, join } from '../helpers';
import * as tf from '../../dist/tfjs.esm.js'; import * as tf from '../../dist/tfjs.esm.js';
import * as modelBase from './modelBase'; import * as posenetModel from './posenetModel';
import * as decodeMultiple from './decodeMultiple'; import * as decodeMultiple from './decodeMultiple';
import * as decodePose from './decodePose'; import * as decodeSingle from './decodeSingle';
import * as util from './util'; import * as util from './utils';
let model; let model;
async function estimateMultiple(input, res, config, inputSize) { async function estimateMultiple(input, res, config, inputSize) {
const toTensorBuffers3D = (tensors) => Promise.all(tensors.map((tensor) => tensor.buffer()));
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 toTensorBuffers3D([res.heatmapScores, res.offsets, res.displacementFwd, res.displacementBwd]);
const scoresBuffer = allTensorBuffers[0]; const scoresBuffer = allTensorBuffers[0];
const offsetsBuffer = allTensorBuffers[1]; const offsetsBuffer = allTensorBuffers[1];
const displacementsFwdBuffer = allTensorBuffers[2]; const displacementsFwdBuffer = allTensorBuffers[2];
const displacementsBwdBuffer = allTensorBuffers[3]; const displacementsBwdBuffer = allTensorBuffers[3];
const poses = await decodeMultiple.decodeMultiplePoses(scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer, config.body.nmsRadius, config.body.maxDetections, config.body.scoreThreshold); const poses = await decodeMultiple.decodeMultiplePoses(scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer, config.body.nmsRadius, config.body.maxDetections, config.body.scoreThreshold);
const scaled = util.scaleAndFlipPoses(poses, [input.shape[1], input.shape[2]], [inputSize, inputSize]); const scaled = util.scalePoses(poses, [input.shape[1], input.shape[2]], [inputSize, inputSize]);
resolve(scaled); resolve(scaled);
}); });
} }
async function estimateSingle(input, res, config, inputSize) { async function estimateSingle(input, res, config, inputSize) {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
const pose = await decodePose.decodeSinglePose(res.heatmapScores, res.offsets, config.body.scoreThreshold); const pose = await decodeSingle.decodeSinglePose(res.heatmapScores, res.offsets, config.body.scoreThreshold);
const scaled = util.scaleAndFlipPoses([pose], [input.shape[1], input.shape[2]], [inputSize, inputSize]); const scaled = util.scalePoses([pose], [input.shape[1], input.shape[2]], [inputSize, inputSize]);
resolve(scaled); resolve(scaled);
}); });
} }
@ -31,15 +33,13 @@ async function estimateSingle(input, res, config, inputSize) {
export class PoseNet { export class PoseNet {
baseModel: any; baseModel: any;
inputSize: number inputSize: number
constructor(mobilenet) { constructor(baseModel) {
this.baseModel = mobilenet; this.baseModel = baseModel;
this.inputSize = mobilenet.model.inputs[0].shape[1]; this.inputSize = baseModel.model.inputs[0].shape[1];
if (this.inputSize < 128) this.inputSize = 257;
} }
async estimatePoses(input, config) { async estimatePoses(input, config) {
const resized = util.resizeTo(input, [this.inputSize, this.inputSize]); const res = this.baseModel.predict(input, config);
const res = this.baseModel.predict(resized, config);
const poses = (config.body.maxDetections < 2) const poses = (config.body.maxDetections < 2)
? await estimateSingle(input, res, config, this.inputSize) ? await estimateSingle(input, res, config, this.inputSize)
@ -49,7 +49,6 @@ export class PoseNet {
res.offsets.dispose(); res.offsets.dispose();
res.displacementFwd.dispose(); res.displacementFwd.dispose();
res.displacementBwd.dispose(); res.displacementBwd.dispose();
resized.dispose();
return poses; return poses;
} }
@ -65,7 +64,7 @@ export async function load(config) {
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); } else if (config.debug) log('cached model:', model.modelUrl);
const mobilenet = new modelBase.BaseModel(model); const mobilenet = new posenetModel.BaseModel(model);
const poseNet = new PoseNet(mobilenet); const poseNet = new PoseNet(mobilenet);
return poseNet; return poseNet;
} }

View File

@ -1,5 +1,7 @@
import * as tf from '../../dist/tfjs.esm.js'; import * as tf from '../../dist/tfjs.esm.js';
const poseNetOutputs = ['MobilenetV1/offset_2/BiasAdd', 'MobilenetV1/heatmap_2/BiasAdd', 'MobilenetV1/displacement_fwd_2/BiasAdd', 'MobilenetV1/displacement_bwd_2/BiasAdd'];
function nameOutputResultsMobileNet(results) { function nameOutputResultsMobileNet(results) {
const [offsets, heatmap, displacementFwd, displacementBwd] = results; const [offsets, heatmap, displacementFwd, displacementBwd] = results;
return { offsets, heatmap, displacementFwd, displacementBwd }; return { offsets, heatmap, displacementFwd, displacementBwd };
@ -7,15 +9,18 @@ function nameOutputResultsMobileNet(results) {
export class BaseModel { export class BaseModel {
model: any; model: any;
inputSize: number;
constructor(model) { constructor(model) {
this.model = model; this.model = model;
this.inputSize = model.inputs[0].shape[1];
} }
predict(input) { predict(input) {
return tf.tidy(() => { return tf.tidy(() => {
const asFloat = input.toFloat().div(127.5).sub(1.0); const resized = input.resizeBilinear([this.inputSize, this.inputSize]);
const asBatch = asFloat.expandDims(0); const normalized = resized.toFloat().div(127.5).sub(1.0);
const results = this.model.predict(asBatch); // const asBatch = asFloat.expandDims(0);
const results = this.model.execute(normalized, poseNetOutputs);
const results3d = results.map((y) => y.squeeze([0])); const results3d = results.map((y) => y.squeeze([0]));
const namedResults = nameOutputResultsMobileNet(results3d); const namedResults = nameOutputResultsMobileNet(results3d);
return { return {

View File

@ -1,62 +0,0 @@
import * as kpt from './keypoints';
export function eitherPointDoesntMeetConfidence(a, b, minConfidence) {
return (a < minConfidence || b < minConfidence);
}
export function getAdjacentKeyPoints(keypoints, minConfidence) {
return kpt.connectedPartIndices.reduce((result, [leftJoint, rightJoint]) => {
if (eitherPointDoesntMeetConfidence(keypoints[leftJoint].score, keypoints[rightJoint].score, minConfidence)) {
return result;
}
result.push([keypoints[leftJoint], keypoints[rightJoint]]);
return result;
}, []);
}
const { NEGATIVE_INFINITY, POSITIVE_INFINITY } = Number;
export function getBoundingBox(keypoints) {
return keypoints.reduce(({ maxX, maxY, minX, minY }, { position: { x, y } }) => ({
maxX: Math.max(maxX, x),
maxY: Math.max(maxY, y),
minX: Math.min(minX, x),
minY: Math.min(minY, y),
}), {
maxX: NEGATIVE_INFINITY,
maxY: NEGATIVE_INFINITY,
minX: POSITIVE_INFINITY,
minY: POSITIVE_INFINITY,
});
}
export function getBoundingBoxPoints(keypoints) {
const { minX, minY, maxX, maxY } = getBoundingBox(keypoints);
return [{ x: minX, y: minY }, { x: maxX, y: minY }, { x: maxX, y: maxY }, { x: minX, y: maxY }];
}
export async function toTensorBuffers3D(tensors) {
return Promise.all(tensors.map((tensor) => tensor.buffer()));
}
export function scalePose(pose, scaleY, scaleX) {
return {
score: pose.score,
keypoints: pose.keypoints.map(({ score, part, position }) => ({
score,
part,
position: { x: Math.trunc(position.x * scaleX), y: Math.trunc(position.y * scaleY) },
})),
};
}
export function resizeTo(image, [targetH, targetW]) {
const input = image.squeeze(0);
const resized = input.resizeBilinear([targetH, targetW]);
input.dispose();
return resized;
}
export function scaleAndFlipPoses(poses, [height, width], [inputResolutionHeight, inputResolutionWidth]) {
const scaledPoses = poses.map((pose) => scalePose(pose, height / inputResolutionHeight, width / inputResolutionWidth));
return scaledPoses;
}

154
src/posenet/utils.ts Normal file
View File

@ -0,0 +1,154 @@
import * as kpt from './keypoints';
export function eitherPointDoesntMeetConfidence(a, b, minConfidence) {
return (a < minConfidence || b < minConfidence);
}
export function getAdjacentKeyPoints(keypoints, minConfidence) {
return kpt.connectedPartIndices.reduce((result, [leftJoint, rightJoint]) => {
if (eitherPointDoesntMeetConfidence(keypoints[leftJoint].score, keypoints[rightJoint].score, minConfidence)) {
return result;
}
result.push([keypoints[leftJoint], keypoints[rightJoint]]);
return result;
}, []);
}
export function getBoundingBox(keypoints) {
const coord = keypoints.reduce(({ maxX, maxY, minX, minY }, { position: { x, y } }) => ({
maxX: Math.max(maxX, x),
maxY: Math.max(maxY, y),
minX: Math.min(minX, x),
minY: Math.min(minY, y),
}), {
maxX: Number.NEGATIVE_INFINITY,
maxY: Number.NEGATIVE_INFINITY,
minX: Number.POSITIVE_INFINITY,
minY: Number.POSITIVE_INFINITY,
});
return [coord.minX, coord.minY, coord.maxX - coord.minX, coord.maxY - coord.minY];
}
export function scalePoses(poses, [height, width], [inputResolutionHeight, inputResolutionWidth]) {
const scalePose = (pose, scaleY, scaleX) => ({
score: pose.score,
box: [Math.trunc(pose.box[0] * scaleX), Math.trunc(pose.box[1] * scaleY), Math.trunc(pose.box[2] * scaleX), Math.trunc(pose.box[3] * scaleY)],
keypoints: pose.keypoints.map(({ score, part, position }) => ({
score,
part,
position: { x: Math.trunc(position.x * scaleX), y: Math.trunc(position.y * scaleY) },
})),
});
const scaledPoses = poses.map((pose) => scalePose(pose, height / inputResolutionHeight, width / inputResolutionWidth));
return scaledPoses;
}
// algorithm based on Coursera Lecture from Algorithms, Part 1: https://www.coursera.org/learn/algorithms-part1/lecture/ZjoSM/heapsort
export class MaxHeap {
priorityQueue: any;
numberOfElements: number;
getElementValue: any;
constructor(maxSize, getElementValue) {
this.priorityQueue = new Array(maxSize);
this.numberOfElements = -1;
this.getElementValue = getElementValue;
}
enqueue(x) {
this.priorityQueue[++this.numberOfElements] = x;
this.swim(this.numberOfElements);
}
dequeue() {
const max = this.priorityQueue[0];
this.exchange(0, this.numberOfElements--);
this.sink(0);
this.priorityQueue[this.numberOfElements + 1] = null;
return max;
}
empty() { return this.numberOfElements === -1; }
size() { return this.numberOfElements + 1; }
all() { return this.priorityQueue.slice(0, this.numberOfElements + 1); }
max() { return this.priorityQueue[0]; }
swim(k) {
while (k > 0 && this.less(Math.floor(k / 2), k)) {
this.exchange(k, Math.floor(k / 2));
k = Math.floor(k / 2);
}
}
sink(k) {
while (2 * k <= this.numberOfElements) {
let j = 2 * k;
if (j < this.numberOfElements && this.less(j, j + 1)) j++;
if (!this.less(k, j)) break;
this.exchange(k, j);
k = j;
}
}
getValueAt(i) {
return this.getElementValue(this.priorityQueue[i]);
}
less(i, j) {
return this.getValueAt(i) < this.getValueAt(j);
}
exchange(i, j) {
const t = this.priorityQueue[i];
this.priorityQueue[i] = this.priorityQueue[j];
this.priorityQueue[j] = t;
}
}
export function getOffsetPoint(y, x, keypoint, offsets) {
return {
y: offsets.get(y, x, keypoint),
x: offsets.get(y, x, keypoint + kpt.count),
};
}
export function getImageCoords(part, outputStride, offsets) {
const { heatmapY, heatmapX, id: keypoint } = part;
const { y, x } = getOffsetPoint(heatmapY, heatmapX, keypoint, offsets);
return {
x: part.heatmapX * outputStride + x,
y: part.heatmapY * outputStride + y,
};
}
export function fillArray(element, size) {
const result = new Array(size);
for (let i = 0; i < size; i++) {
result[i] = element;
}
return result;
}
export function clamp(a, min, max) {
if (a < min) return min;
if (a > max) return max;
return a;
}
export function squaredDistance(y1, x1, y2, x2) {
const dy = y2 - y1;
const dx = x2 - x1;
return dy * dy + dx * dx;
}
export function addVectors(a, b) {
return { x: a.x + b.x, y: a.y + b.y };
}
export function clampVector(a, min, max) {
return { y: clamp(a.y, min, max), x: clamp(a.x, min, max) };
}

View File

@ -1,45 +0,0 @@
import * as kpt from './keypoints';
export function getOffsetPoint(y, x, keypoint, offsets) {
return {
y: offsets.get(y, x, keypoint),
x: offsets.get(y, x, keypoint + kpt.NUM_KEYPOINTS),
};
}
export function getImageCoords(part, outputStride, offsets) {
const { heatmapY, heatmapX, id: keypoint } = part;
const { y, x } = getOffsetPoint(heatmapY, heatmapX, keypoint, offsets);
return {
x: part.heatmapX * outputStride + x,
y: part.heatmapY * outputStride + y,
};
}
export function fillArray(element, size) {
const result = new Array(size);
for (let i = 0; i < size; i++) {
result[i] = element;
}
return result;
}
export function clamp(a, min, max) {
if (a < min) return min;
if (a > max) return max;
return a;
}
export function squaredDistance(y1, x1, y2, x2) {
const dy = y2 - y1;
const dx = x2 - x1;
return dy * dy + dx * dx;
}
export function addVectors(a, b) {
return { x: a.x + b.x, y: a.y + b.y };
}
export function clampVector(a, min, max) {
return { y: clamp(a.y, min, max), x: clamp(a.x, min, max) };
}

View File

@ -744,3 +744,172 @@
2021-04-19 16:20:08 ERROR: test-node-wasm.js failed: model server: request to http://localhost:10030/models/ failed, reason: connect ECONNREFUSED 127.0.0.1:10030 2021-04-19 16:20:08 ERROR: test-node-wasm.js failed: model server: request to http://localhost:10030/models/ failed, reason: connect ECONNREFUSED 127.0.0.1:10030
2021-04-19 16:20:08 ERROR: test-node-wasm.js aborting test 2021-04-19 16:20:08 ERROR: test-node-wasm.js aborting test
2021-04-19 16:20:08 INFO:  status: {"passed":50,"failed":1} 2021-04-19 16:20:08 INFO:  status: {"passed":50,"failed":1}
2021-04-24 11:45:56 INFO:  @vladmandic/human version 1.6.1
2021-04-24 11:45:56 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.0.0
2021-04-24 11:45:56 INFO:  tests: ["test-node.js","test-node-gpu.js","test-node-wasm.js"]
2021-04-24 11:45:56 INFO:  test-node.js start
2021-04-24 11:45:57 STATE: test-node.js passed: create human
2021-04-24 11:45:57 INFO:  test-node.js human version: 1.6.1
2021-04-24 11:45:57 INFO:  test-node.js platform: linux x64 agent: NodeJS v16.0.0
2021-04-24 11:45:57 INFO:  test-node.js tfjs version: 3.5.0
2021-04-24 11:45:58 STATE: test-node.js passed: set backend: tensorflow
2021-04-24 11:45:58 STATE: test-node.js passed: load models
2021-04-24 11:45:58 STATE: test-node.js result: defined models: 12 loaded models: 6
2021-04-24 11:45:58 STATE: test-node.js passed: warmup: none default
2021-04-24 11:45:59 STATE: test-node.js passed: warmup: face default
2021-04-24 11:45:59 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 5 object: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.52,"class":"person"} {"score":0.88,"keypoints":6}
2021-04-24 11:45:59 DATA:  test-node.js result: performance: load: 393 total: 1436
2021-04-24 11:46:00 STATE: test-node.js passed: warmup: body default
2021-04-24 11:46:00 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 3 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.86,"class":"person"} {"score":0.92,"keypoints":17}
2021-04-24 11:46:00 DATA:  test-node.js result: performance: load: 393 total: 1407
2021-04-24 11:46:00 INFO:  test-node.js test body variants
2021-04-24 11:46:02 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:03 STATE: test-node.js passed: detect: assets/human-sample-body.jpg posenet
2021-04-24 11:46:03 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 3 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.86,"class":"person"} {"score":0.92,"keypoints":17}
2021-04-24 11:46:03 DATA:  test-node.js result: performance: load: 393 total: 1295
2021-04-24 11:46:04 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:05 STATE: test-node.js passed: detect: assets/human-sample-body.jpg blazepose
2021-04-24 11:46:05 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 3 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.86,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:05 DATA:  test-node.js result: performance: load: 393 total: 1405
2021-04-24 11:46:06 STATE: test-node.js passed: detect: random default
2021-04-24 11:46:06 DATA:  test-node.js result: face: 0 body: 1 hand: 0 gesture: 1 object: 0 {} {} {"score":1,"keypoints":39}
2021-04-24 11:46:06 DATA:  test-node.js result: performance: load: 393 total: 734
2021-04-24 11:46:06 INFO:  test-node.js test: first instance
2021-04-24 11:46:07 STATE: test-node.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-04-24 11:46:08 STATE: test-node.js passed: detect: assets/sample-me.jpg default
2021-04-24 11:46:08 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 2 {"confidence":1,"age":39.2,"gender":"male"} {"score":0.7,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:08 DATA:  test-node.js result: performance: load: 393 total: 1126
2021-04-24 11:46:08 INFO:  test-node.js test: second instance
2021-04-24 11:46:08 STATE: test-node.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-04-24 11:46:09 STATE: test-node.js passed: detect: assets/sample-me.jpg default
2021-04-24 11:46:09 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 2 {"confidence":1,"age":39.2,"gender":"male"} {"score":0.7,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:09 DATA:  test-node.js result: performance: load: 3 total: 1008
2021-04-24 11:46:09 INFO:  test-node.js test: concurrent
2021-04-24 11:46:09 STATE: test-node.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-04-24 11:46:09 STATE: test-node.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-04-24 11:46:10 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:11 STATE: test-node.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:16 STATE: test-node.js passed: detect: assets/human-sample-face.jpg default
2021-04-24 11:46:16 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.53,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:16 DATA:  test-node.js result: performance: load: 393 total: 4598
2021-04-24 11:46:16 STATE: test-node.js passed: detect: assets/human-sample-face.jpg default
2021-04-24 11:46:16 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.53,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:16 DATA:  test-node.js result: performance: load: 3 total: 4598
2021-04-24 11:46:16 STATE: test-node.js passed: detect: assets/human-sample-body.jpg default
2021-04-24 11:46:16 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 3 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.86,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:16 DATA:  test-node.js result: performance: load: 393 total: 4598
2021-04-24 11:46:16 STATE: test-node.js passed: detect: assets/human-sample-body.jpg default
2021-04-24 11:46:16 DATA:  test-node.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 3 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.86,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:16 DATA:  test-node.js result: performance: load: 3 total: 4598
2021-04-24 11:46:16 INFO:  test-node.js test complete: 18747 ms
2021-04-24 11:46:16 INFO:  test-node-gpu.js start
2021-04-24 11:46:17 WARN:  test-node-gpu.js stderr: 2021-04-24 11:46:17.503614: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory
2021-04-24 11:46:17 WARN:  test-node-gpu.js stderr: 2021-04-24 11:46:17.721982: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory
2021-04-24 11:46:17 WARN:  test-node-gpu.js stderr: 2021-04-24 11:46:17.722060: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (wyse): /proc/driver/nvidia/version does not exist
2021-04-24 11:46:17 STATE: test-node-gpu.js passed: create human
2021-04-24 11:46:17 INFO:  test-node-gpu.js human version: 1.6.1
2021-04-24 11:46:17 INFO:  test-node-gpu.js platform: linux x64 agent: NodeJS v16.0.0
2021-04-24 11:46:17 INFO:  test-node-gpu.js tfjs version: 3.5.0
2021-04-24 11:46:18 STATE: test-node-gpu.js passed: set backend: tensorflow
2021-04-24 11:46:18 STATE: test-node-gpu.js passed: load models
2021-04-24 11:46:18 STATE: test-node-gpu.js result: defined models: 12 loaded models: 6
2021-04-24 11:46:18 STATE: test-node-gpu.js passed: warmup: none default
2021-04-24 11:46:19 STATE: test-node-gpu.js passed: warmup: face default
2021-04-24 11:46:19 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 5 object: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.52,"class":"person"} {"score":0.88,"keypoints":6}
2021-04-24 11:46:19 DATA:  test-node-gpu.js result: performance: load: 351 total: 1557
2021-04-24 11:46:21 STATE: test-node-gpu.js passed: warmup: body default
2021-04-24 11:46:21 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 3 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.86,"class":"person"} {"score":0.92,"keypoints":17}
2021-04-24 11:46:21 DATA:  test-node-gpu.js result: performance: load: 351 total: 1325
2021-04-24 11:46:21 INFO:  test-node-gpu.js test body variants
2021-04-24 11:46:22 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:23 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg posenet
2021-04-24 11:46:23 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 3 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.86,"class":"person"} {"score":0.92,"keypoints":17}
2021-04-24 11:46:23 DATA:  test-node-gpu.js result: performance: load: 351 total: 1412
2021-04-24 11:46:24 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:26 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg blazepose
2021-04-24 11:46:26 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 3 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.86,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:26 DATA:  test-node-gpu.js result: performance: load: 351 total: 1361
2021-04-24 11:46:26 STATE: test-node-gpu.js passed: detect: random default
2021-04-24 11:46:26 DATA:  test-node-gpu.js result: face: 0 body: 1 hand: 0 gesture: 1 object: 0 {} {} {"score":1,"keypoints":39}
2021-04-24 11:46:26 DATA:  test-node-gpu.js result: performance: load: 351 total: 721
2021-04-24 11:46:26 INFO:  test-node-gpu.js test: first instance
2021-04-24 11:46:27 STATE: test-node-gpu.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-04-24 11:46:28 STATE: test-node-gpu.js passed: detect: assets/sample-me.jpg default
2021-04-24 11:46:28 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 2 {"confidence":1,"age":39.2,"gender":"male"} {"score":0.7,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:28 DATA:  test-node-gpu.js result: performance: load: 351 total: 1122
2021-04-24 11:46:28 INFO:  test-node-gpu.js test: second instance
2021-04-24 11:46:28 STATE: test-node-gpu.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-04-24 11:46:29 STATE: test-node-gpu.js passed: detect: assets/sample-me.jpg default
2021-04-24 11:46:29 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 2 {"confidence":1,"age":39.2,"gender":"male"} {"score":0.7,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:29 DATA:  test-node-gpu.js result: performance: load: 3 total: 1139
2021-04-24 11:46:29 INFO:  test-node-gpu.js test: concurrent
2021-04-24 11:46:29 STATE: test-node-gpu.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-04-24 11:46:29 STATE: test-node-gpu.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-04-24 11:46:31 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:32 STATE: test-node-gpu.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:36 STATE: test-node-gpu.js passed: detect: assets/human-sample-face.jpg default
2021-04-24 11:46:36 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.53,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:36 DATA:  test-node-gpu.js result: performance: load: 351 total: 4281
2021-04-24 11:46:36 STATE: test-node-gpu.js passed: detect: assets/human-sample-face.jpg default
2021-04-24 11:46:36 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 1 {"confidence":1,"age":23.6,"gender":"female"} {"score":0.53,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:36 DATA:  test-node-gpu.js result: performance: load: 3 total: 4281
2021-04-24 11:46:36 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg default
2021-04-24 11:46:36 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 3 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.86,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:36 DATA:  test-node-gpu.js result: performance: load: 351 total: 4281
2021-04-24 11:46:36 STATE: test-node-gpu.js passed: detect: assets/human-sample-body.jpg default
2021-04-24 11:46:36 DATA:  test-node-gpu.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 3 {"confidence":1,"age":28.5,"gender":"female"} {"score":0.86,"class":"person"} {"score":1,"keypoints":39}
2021-04-24 11:46:36 DATA:  test-node-gpu.js result: performance: load: 3 total: 4281
2021-04-24 11:46:36 INFO:  test-node-gpu.js test complete: 18563 ms
2021-04-24 11:46:36 INFO:  test-node-wasm.js start
2021-04-24 11:46:36 STATE: test-node-wasm.js passed: model server: http://localhost:10030/models/
2021-04-24 11:46:36 STATE: test-node-wasm.js passed: create human
2021-04-24 11:46:36 INFO:  test-node-wasm.js human version: 1.6.1
2021-04-24 11:46:36 INFO:  test-node-wasm.js platform: linux x64 agent: NodeJS v16.0.0
2021-04-24 11:46:36 INFO:  test-node-wasm.js tfjs version: 3.5.0
2021-04-24 11:46:37 STATE: test-node-wasm.js passed: set backend: wasm
2021-04-24 11:46:37 STATE: test-node-wasm.js passed: load models
2021-04-24 11:46:37 STATE: test-node-wasm.js result: defined models: 12 loaded models: 5
2021-04-24 11:46:37 STATE: test-node-wasm.js passed: warmup: none default
2021-04-24 11:46:37 ERROR: test-node-wasm.js failed: warmup: face default
2021-04-24 11:46:37 ERROR: test-node-wasm.js failed: warmup: body default
2021-04-24 11:46:37 INFO:  test-node-wasm.js test body variants
2021-04-24 11:46:39 STATE: test-node-wasm.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:42 STATE: test-node-wasm.js passed: detect: assets/human-sample-body.jpg posenet
2021-04-24 11:46:42 DATA:  test-node-wasm.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 0 {"confidence":1,"age":28.5,"gender":"female"} {} {"score":0.95,"keypoints":17}
2021-04-24 11:46:42 DATA:  test-node-wasm.js result: performance: load: 687 total: 3290
2021-04-24 11:46:44 STATE: test-node-wasm.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:47 STATE: test-node-wasm.js passed: detect: assets/human-sample-body.jpg blazepose
2021-04-24 11:46:47 DATA:  test-node-wasm.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 0 {"confidence":1,"age":28.5,"gender":"female"} {} {"score":1,"keypoints":39}
2021-04-24 11:46:47 DATA:  test-node-wasm.js result: performance: load: 687 total: 2494
2021-04-24 11:46:48 STATE: test-node-wasm.js passed: detect: random default
2021-04-24 11:46:48 DATA:  test-node-wasm.js result: face: 0 body: 1 hand: 0 gesture: 1 object: 0 {} {} {"score":1,"keypoints":39}
2021-04-24 11:46:48 DATA:  test-node-wasm.js result: performance: load: 687 total: 1409
2021-04-24 11:46:48 INFO:  test-node-wasm.js test: first instance
2021-04-24 11:46:49 STATE: test-node-wasm.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-04-24 11:46:51 STATE: test-node-wasm.js passed: detect: assets/sample-me.jpg default
2021-04-24 11:46:51 DATA:  test-node-wasm.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 0 {"confidence":1,"age":39.2,"gender":"male"} {} {"score":1,"keypoints":39}
2021-04-24 11:46:51 DATA:  test-node-wasm.js result: performance: load: 687 total: 2061
2021-04-24 11:46:51 INFO:  test-node-wasm.js test: second instance
2021-04-24 11:46:52 STATE: test-node-wasm.js passed: load image: assets/sample-me.jpg [1,700,700,3]
2021-04-24 11:46:54 STATE: test-node-wasm.js passed: detect: assets/sample-me.jpg default
2021-04-24 11:46:54 DATA:  test-node-wasm.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 0 {"confidence":1,"age":39.2,"gender":"male"} {} {"score":1,"keypoints":39}
2021-04-24 11:46:54 DATA:  test-node-wasm.js result: performance: load: 5 total: 1998
2021-04-24 11:46:54 INFO:  test-node-wasm.js test: concurrent
2021-04-24 11:46:54 STATE: test-node-wasm.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-04-24 11:46:54 STATE: test-node-wasm.js passed: load image: assets/human-sample-face.jpg [1,256,256,3]
2021-04-24 11:46:56 STATE: test-node-wasm.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:46:58 STATE: test-node-wasm.js passed: load image: assets/human-sample-body.jpg [1,1200,1200,3]
2021-04-24 11:47:05 STATE: test-node-wasm.js passed: detect: assets/human-sample-face.jpg default
2021-04-24 11:47:05 DATA:  test-node-wasm.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 0 {"confidence":1,"age":23.6,"gender":"female"} {} {"score":1,"keypoints":39}
2021-04-24 11:47:05 DATA:  test-node-wasm.js result: performance: load: 687 total: 7833
2021-04-24 11:47:05 STATE: test-node-wasm.js passed: detect: assets/human-sample-face.jpg default
2021-04-24 11:47:05 DATA:  test-node-wasm.js result: face: 1 body: 1 hand: 0 gesture: 6 object: 0 {"confidence":1,"age":23.6,"gender":"female"} {} {"score":1,"keypoints":39}
2021-04-24 11:47:05 DATA:  test-node-wasm.js result: performance: load: 5 total: 7833
2021-04-24 11:47:05 STATE: test-node-wasm.js passed: detect: assets/human-sample-body.jpg default
2021-04-24 11:47:05 DATA:  test-node-wasm.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 0 {"confidence":1,"age":28.5,"gender":"female"} {} {"score":1,"keypoints":39}
2021-04-24 11:47:05 DATA:  test-node-wasm.js result: performance: load: 687 total: 7833
2021-04-24 11:47:05 STATE: test-node-wasm.js passed: detect: assets/human-sample-body.jpg default
2021-04-24 11:47:05 DATA:  test-node-wasm.js result: face: 1 body: 1 hand: 0 gesture: 3 object: 0 {"confidence":1,"age":28.5,"gender":"female"} {} {"score":1,"keypoints":39}
2021-04-24 11:47:05 DATA:  test-node-wasm.js result: performance: load: 5 total: 7833
2021-04-24 11:47:05 INFO:  test-node-wasm.js test complete: 29200 ms
2021-04-24 11:47:06 INFO:  status: {"passed":68,"failed":2}

View File

@ -1,2 +0,0 @@
import * as heapSort from './heapSort';
export declare function buildPartWithScoreQueue(scoreThreshold: any, localMaximumRadius: any, scores: any): heapSort.MaxHeap;

View File

@ -1,4 +1,7 @@
import * as utils from './utils';
export declare function buildPartWithScoreQueue(scoreThreshold: any, localMaximumRadius: any, scores: any): utils.MaxHeap;
export declare function decodeMultiplePoses(scoresBuffer: any, offsetsBuffer: any, displacementsFwdBuffer: any, displacementsBwdBuffer: any, nmsRadius: any, maxDetections: any, scoreThreshold: any): { export declare function decodeMultiplePoses(scoresBuffer: any, offsetsBuffer: any, displacementsFwdBuffer: any, displacementsBwdBuffer: any, nmsRadius: any, maxDetections: any, scoreThreshold: any): {
keypoints: any; keypoints: any;
box: any;
score: number; score: number;
}[]; }[];

View File

@ -1,4 +1,3 @@
export declare function getPointsConfidence(heatmapScores: any, heatMapCoords: any): Float32Array; export declare function getPointsConfidence(heatmapScores: any, heatMapCoords: any): number[];
export declare function getOffsetVectors(heatMapCoordsBuffer: any, offsetsBuffer: any): any;
export declare function getOffsetPoints(heatMapCoordsBuffer: any, outputStride: any, offsetsBuffer: any): any; export declare function getOffsetPoints(heatMapCoordsBuffer: any, outputStride: any, offsetsBuffer: any): any;
export declare function argmax2d(inputs: any): any; export declare function argmax2d(inputs: any): any;

View File

@ -8,5 +8,6 @@ export declare function decodeSinglePose(heatmapScores: any, offsets: any, minSc
part: string; part: string;
score: number; score: number;
}[]; }[];
box: any[];
score: number; score: number;
}>; }>;

View File

@ -1,17 +0,0 @@
export declare class MaxHeap {
priorityQueue: any;
numberOfElements: number;
getElementValue: any;
constructor(maxSize: any, getElementValue: any);
enqueue(x: any): void;
dequeue(): any;
empty(): boolean;
size(): number;
all(): any;
max(): any;
swim(k: any): void;
sink(k: any): void;
getValueAt(i: any): any;
less(i: any, j: any): boolean;
exchange(i: any, j: any): void;
}

View File

@ -1,6 +1,5 @@
export declare const partNames: string[]; export declare const partNames: string[];
export declare const NUM_KEYPOINTS: number; export declare const count: number;
export declare const partIds: {}; export declare const partIds: {};
export declare const connectedPartIndices: any[][]; export declare const connectedPartIndices: any[][];
export declare const poseChain: string[][]; export declare const poseChain: string[][];
export declare const partChannels: string[];

View File

@ -1,7 +1,7 @@
export declare class PoseNet { export declare class PoseNet {
baseModel: any; baseModel: any;
inputSize: number; inputSize: number;
constructor(mobilenet: any); constructor(baseModel: any);
estimatePoses(input: any, config: any): Promise<unknown>; estimatePoses(input: any, config: any): Promise<unknown>;
dispose(): void; dispose(): void;
} }

View File

@ -1,5 +1,6 @@
export declare class BaseModel { export declare class BaseModel {
model: any; model: any;
inputSize: number;
constructor(model: any); constructor(model: any);
predict(input: any): any; predict(input: any): any;
dispose(): void; dispose(): void;

View File

@ -1,14 +0,0 @@
export declare function eitherPointDoesntMeetConfidence(a: any, b: any, minConfidence: any): boolean;
export declare function getAdjacentKeyPoints(keypoints: any, minConfidence: any): any[];
export declare function getBoundingBox(keypoints: any): any;
export declare function getBoundingBoxPoints(keypoints: any): {
x: any;
y: any;
}[];
export declare function toTensorBuffers3D(tensors: any): Promise<[unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown]>;
export declare function scalePose(pose: any, scaleY: any, scaleX: any): {
score: any;
keypoints: any;
};
export declare function resizeTo(image: any, [targetH, targetW]: [any, any]): any;
export declare function scaleAndFlipPoses(poses: any, [height, width]: [any, any], [inputResolutionHeight, inputResolutionWidth]: [any, any]): any;

40
types/posenet/utils.d.ts vendored Normal file
View File

@ -0,0 +1,40 @@
export declare function eitherPointDoesntMeetConfidence(a: any, b: any, minConfidence: any): boolean;
export declare function getAdjacentKeyPoints(keypoints: any, minConfidence: any): any[];
export declare function getBoundingBox(keypoints: any): any[];
export declare function scalePoses(poses: any, [height, width]: [any, any], [inputResolutionHeight, inputResolutionWidth]: [any, any]): any;
export declare class MaxHeap {
priorityQueue: any;
numberOfElements: number;
getElementValue: any;
constructor(maxSize: any, getElementValue: any);
enqueue(x: any): void;
dequeue(): any;
empty(): boolean;
size(): number;
all(): any;
max(): any;
swim(k: any): void;
sink(k: any): void;
getValueAt(i: any): any;
less(i: any, j: any): boolean;
exchange(i: any, j: any): void;
}
export declare function getOffsetPoint(y: any, x: any, keypoint: any, offsets: any): {
y: any;
x: any;
};
export declare function getImageCoords(part: any, outputStride: any, offsets: any): {
x: any;
y: any;
};
export declare function fillArray(element: any, size: any): any[];
export declare function clamp(a: any, min: any, max: any): any;
export declare function squaredDistance(y1: any, x1: any, y2: any, x2: any): number;
export declare function addVectors(a: any, b: any): {
x: any;
y: any;
};
export declare function clampVector(a: any, min: any, max: any): {
y: any;
x: any;
};

View File

@ -1,19 +0,0 @@
export declare function getOffsetPoint(y: any, x: any, keypoint: any, offsets: any): {
y: any;
x: any;
};
export declare function getImageCoords(part: any, outputStride: any, offsets: any): {
x: any;
y: any;
};
export declare function fillArray(element: any, size: any): any[];
export declare function clamp(a: any, min: any, max: any): any;
export declare function squaredDistance(y1: any, x1: any, y2: any, x2: any): number;
export declare function addVectors(a: any, b: any): {
x: any;
y: any;
};
export declare function clampVector(a: any, min: any, max: any): {
y: any;
x: any;
};

2
wiki

@ -1 +1 @@
Subproject commit 4cb4534d2812d092946fbe51f8078df15b2c07d7 Subproject commit ee4cf3aa27940b10e275ef9e8119e220c4b2d70d