mirror of https://github.com/vladmandic/human
40 lines
1.7 KiB
TypeScript
40 lines
1.7 KiB
TypeScript
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;
|
|
}
|