rtmlib-ts 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +1 -0
- package/README.md +202 -0
- package/dist/core/base.d.ts +20 -0
- package/dist/core/base.d.ts.map +1 -0
- package/dist/core/base.js +40 -0
- package/dist/core/file.d.ts +11 -0
- package/dist/core/file.d.ts.map +1 -0
- package/dist/core/file.js +111 -0
- package/dist/core/modelCache.d.ts +35 -0
- package/dist/core/modelCache.d.ts.map +1 -0
- package/dist/core/modelCache.js +161 -0
- package/dist/core/posePostprocessing.d.ts +12 -0
- package/dist/core/posePostprocessing.d.ts.map +1 -0
- package/dist/core/posePostprocessing.js +76 -0
- package/dist/core/postprocessing.d.ts +10 -0
- package/dist/core/postprocessing.d.ts.map +1 -0
- package/dist/core/postprocessing.js +70 -0
- package/dist/core/preprocessing.d.ts +14 -0
- package/dist/core/preprocessing.d.ts.map +1 -0
- package/dist/core/preprocessing.js +79 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/models/rtmpose.d.ts +25 -0
- package/dist/models/rtmpose.d.ts.map +1 -0
- package/dist/models/rtmpose.js +185 -0
- package/dist/models/rtmpose3d.d.ts +28 -0
- package/dist/models/rtmpose3d.d.ts.map +1 -0
- package/dist/models/rtmpose3d.js +184 -0
- package/dist/models/yolo12.d.ts +23 -0
- package/dist/models/yolo12.d.ts.map +1 -0
- package/dist/models/yolo12.js +165 -0
- package/dist/models/yolox.d.ts +18 -0
- package/dist/models/yolox.d.ts.map +1 -0
- package/dist/models/yolox.js +167 -0
- package/dist/solution/animalDetector.d.ts +229 -0
- package/dist/solution/animalDetector.d.ts.map +1 -0
- package/dist/solution/animalDetector.js +663 -0
- package/dist/solution/body.d.ts +16 -0
- package/dist/solution/body.d.ts.map +1 -0
- package/dist/solution/body.js +52 -0
- package/dist/solution/bodyWithFeet.d.ts +16 -0
- package/dist/solution/bodyWithFeet.d.ts.map +1 -0
- package/dist/solution/bodyWithFeet.js +52 -0
- package/dist/solution/customDetector.d.ts +137 -0
- package/dist/solution/customDetector.d.ts.map +1 -0
- package/dist/solution/customDetector.js +342 -0
- package/dist/solution/hand.d.ts +14 -0
- package/dist/solution/hand.d.ts.map +1 -0
- package/dist/solution/hand.js +20 -0
- package/dist/solution/index.d.ts +10 -0
- package/dist/solution/index.d.ts.map +1 -0
- package/dist/solution/index.js +9 -0
- package/dist/solution/objectDetector.d.ts +172 -0
- package/dist/solution/objectDetector.d.ts.map +1 -0
- package/dist/solution/objectDetector.js +606 -0
- package/dist/solution/pose3dDetector.d.ts +145 -0
- package/dist/solution/pose3dDetector.d.ts.map +1 -0
- package/dist/solution/pose3dDetector.js +611 -0
- package/dist/solution/poseDetector.d.ts +198 -0
- package/dist/solution/poseDetector.d.ts.map +1 -0
- package/dist/solution/poseDetector.js +622 -0
- package/dist/solution/poseTracker.d.ts +22 -0
- package/dist/solution/poseTracker.d.ts.map +1 -0
- package/dist/solution/poseTracker.js +106 -0
- package/dist/solution/wholebody.d.ts +19 -0
- package/dist/solution/wholebody.d.ts.map +1 -0
- package/dist/solution/wholebody.js +82 -0
- package/dist/solution/wholebody3d.d.ts +22 -0
- package/dist/solution/wholebody3d.d.ts.map +1 -0
- package/dist/solution/wholebody3d.js +75 -0
- package/dist/types/index.d.ts +52 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/visualization/draw.d.ts +57 -0
- package/dist/visualization/draw.d.ts.map +1 -0
- package/dist/visualization/draw.js +400 -0
- package/dist/visualization/skeleton/coco133.d.ts +350 -0
- package/dist/visualization/skeleton/coco133.d.ts.map +1 -0
- package/dist/visualization/skeleton/coco133.js +120 -0
- package/dist/visualization/skeleton/coco17.d.ts +180 -0
- package/dist/visualization/skeleton/coco17.d.ts.map +1 -0
- package/dist/visualization/skeleton/coco17.js +48 -0
- package/dist/visualization/skeleton/halpe26.d.ts +278 -0
- package/dist/visualization/skeleton/halpe26.d.ts.map +1 -0
- package/dist/visualization/skeleton/halpe26.js +70 -0
- package/dist/visualization/skeleton/hand21.d.ts +196 -0
- package/dist/visualization/skeleton/hand21.d.ts.map +1 -0
- package/dist/visualization/skeleton/hand21.js +51 -0
- package/dist/visualization/skeleton/index.d.ts +10 -0
- package/dist/visualization/skeleton/index.d.ts.map +1 -0
- package/dist/visualization/skeleton/index.js +9 -0
- package/dist/visualization/skeleton/openpose134.d.ts +357 -0
- package/dist/visualization/skeleton/openpose134.d.ts.map +1 -0
- package/dist/visualization/skeleton/openpose134.js +116 -0
- package/dist/visualization/skeleton/openpose18.d.ts +177 -0
- package/dist/visualization/skeleton/openpose18.d.ts.map +1 -0
- package/dist/visualization/skeleton/openpose18.js +47 -0
- package/docs/ANIMAL_DETECTOR.md +450 -0
- package/docs/CUSTOM_DETECTOR.md +568 -0
- package/docs/OBJECT_DETECTOR.md +373 -0
- package/docs/POSE3D_DETECTOR.md +458 -0
- package/docs/POSE_DETECTOR.md +442 -0
- package/examples/README.md +119 -0
- package/examples/index.html +746 -0
- package/package.json +51 -0
- package/playground/README.md +114 -0
- package/playground/app/favicon.ico +0 -0
- package/playground/app/globals.css +17 -0
- package/playground/app/layout.tsx +19 -0
- package/playground/app/page.tsx +1338 -0
- package/playground/eslint.config.mjs +18 -0
- package/playground/next.config.ts +34 -0
- package/playground/package-lock.json +6723 -0
- package/playground/package.json +27 -0
- package/playground/postcss.config.mjs +7 -0
- package/playground/tsconfig.json +34 -0
- package/src/core/base.ts +66 -0
- package/src/core/file.ts +141 -0
- package/src/core/modelCache.ts +189 -0
- package/src/core/posePostprocessing.ts +91 -0
- package/src/core/postprocessing.ts +93 -0
- package/src/core/preprocessing.ts +127 -0
- package/src/index.ts +69 -0
- package/src/models/rtmpose.ts +265 -0
- package/src/models/rtmpose3d.ts +289 -0
- package/src/models/yolo12.ts +220 -0
- package/src/models/yolox.ts +214 -0
- package/src/solution/animalDetector.ts +955 -0
- package/src/solution/body.ts +89 -0
- package/src/solution/bodyWithFeet.ts +89 -0
- package/src/solution/customDetector.ts +474 -0
- package/src/solution/hand.ts +52 -0
- package/src/solution/index.ts +10 -0
- package/src/solution/objectDetector.ts +816 -0
- package/src/solution/pose3dDetector.ts +890 -0
- package/src/solution/poseDetector.ts +892 -0
- package/src/solution/poseTracker.ts +172 -0
- package/src/solution/wholebody.ts +130 -0
- package/src/solution/wholebody3d.ts +125 -0
- package/src/types/index.ts +62 -0
- package/src/visualization/draw.ts +543 -0
- package/src/visualization/skeleton/coco133.ts +131 -0
- package/src/visualization/skeleton/coco17.ts +49 -0
- package/src/visualization/skeleton/halpe26.ts +71 -0
- package/src/visualization/skeleton/hand21.ts +52 -0
- package/src/visualization/skeleton/index.ts +10 -0
- package/src/visualization/skeleton/openpose134.ts +125 -0
- package/src/visualization/skeleton/openpose18.ts +48 -0
- package/tsconfig.json +32 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-processing utilities for object detection
|
|
3
|
+
*/
|
|
4
|
+
export declare function multiclassNms(boxes: number[][], scores: number[][], nmsThr: number, scoreThr: number): {
|
|
5
|
+
boxes: number[][];
|
|
6
|
+
scores: number[];
|
|
7
|
+
classIds: number[];
|
|
8
|
+
} | null;
|
|
9
|
+
export declare function nms(boxes: number[][], scores: number[], nmsThr: number): number[];
|
|
10
|
+
//# sourceMappingURL=postprocessing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postprocessing.d.ts","sourceRoot":"","sources":["../../src/core/postprocessing.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EAAE,EAAE,EACjB,MAAM,EAAE,MAAM,EAAE,EAAE,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CA4CpE;AAmBD,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBjF"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-processing utilities for object detection
|
|
3
|
+
*/
|
|
4
|
+
export function multiclassNms(boxes, scores, nmsThr, scoreThr) {
|
|
5
|
+
const numClasses = scores[0].length;
|
|
6
|
+
const numBoxes = boxes.length;
|
|
7
|
+
const allDetections = [];
|
|
8
|
+
for (let c = 0; c < numClasses; c++) {
|
|
9
|
+
for (let i = 0; i < numBoxes; i++) {
|
|
10
|
+
if (scores[i][c] > scoreThr) {
|
|
11
|
+
allDetections.push({
|
|
12
|
+
box: boxes[i],
|
|
13
|
+
score: scores[i][c],
|
|
14
|
+
classId: c,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
allDetections.sort((a, b) => b.score - a.score);
|
|
20
|
+
const keep = [];
|
|
21
|
+
while (allDetections.length > 0) {
|
|
22
|
+
const current = allDetections.shift();
|
|
23
|
+
keep.push(current);
|
|
24
|
+
for (let i = allDetections.length - 1; i >= 0; i--) {
|
|
25
|
+
const other = allDetections[i];
|
|
26
|
+
if (current.classId !== other.classId)
|
|
27
|
+
continue;
|
|
28
|
+
const iou = calculateIoU(current.box, other.box);
|
|
29
|
+
if (iou > nmsThr) {
|
|
30
|
+
allDetections.splice(i, 1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (keep.length === 0)
|
|
35
|
+
return null;
|
|
36
|
+
return {
|
|
37
|
+
boxes: keep.map(d => d.box),
|
|
38
|
+
scores: keep.map(d => d.score),
|
|
39
|
+
classIds: keep.map(d => d.classId),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function calculateIoU(box1, box2) {
|
|
43
|
+
const x1 = Math.max(box1[0], box2[0]);
|
|
44
|
+
const y1 = Math.max(box1[1], box2[1]);
|
|
45
|
+
const x2 = Math.min(box1[2], box2[2]);
|
|
46
|
+
const y2 = Math.min(box1[3], box2[3]);
|
|
47
|
+
const interWidth = Math.max(0, x2 - x1);
|
|
48
|
+
const interHeight = Math.max(0, y2 - y1);
|
|
49
|
+
const interArea = interWidth * interHeight;
|
|
50
|
+
const box1Area = (box1[2] - box1[0]) * (box1[3] - box1[1]);
|
|
51
|
+
const box2Area = (box2[2] - box2[0]) * (box2[3] - box2[1]);
|
|
52
|
+
const unionArea = box1Area + box2Area - interArea;
|
|
53
|
+
return unionArea > 0 ? interArea / unionArea : 0;
|
|
54
|
+
}
|
|
55
|
+
export function nms(boxes, scores, nmsThr) {
|
|
56
|
+
const indices = [];
|
|
57
|
+
const sortedIndices = scores.map((s, i) => i).sort((a, b) => scores[b] - scores[a]);
|
|
58
|
+
while (sortedIndices.length > 0) {
|
|
59
|
+
const current = sortedIndices.shift();
|
|
60
|
+
indices.push(current);
|
|
61
|
+
for (let i = sortedIndices.length - 1; i >= 0; i--) {
|
|
62
|
+
const other = sortedIndices[i];
|
|
63
|
+
const iou = calculateIoU(boxes[current], boxes[other]);
|
|
64
|
+
if (iou > nmsThr) {
|
|
65
|
+
sortedIndices.splice(i, 1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return indices;
|
|
70
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-processing utilities for pose estimation
|
|
3
|
+
*/
|
|
4
|
+
export declare function bboxXyxy2cs(bbox: [number, number, number, number], padding?: number): {
|
|
5
|
+
center: [number, number];
|
|
6
|
+
scale: [number, number];
|
|
7
|
+
};
|
|
8
|
+
export declare function topDownAffine(imageSize: [number, number], scale: [number, number], center: [number, number], img: Uint8Array, imgWidth: number, imgHeight: number): {
|
|
9
|
+
resizedImg: Float32Array;
|
|
10
|
+
scale: [number, number];
|
|
11
|
+
};
|
|
12
|
+
export declare function normalizeImage(img: Float32Array, mean: number[], std: number[]): Float32Array;
|
|
13
|
+
export declare function transposeImage(img: Float32Array, height: number, width: number): Float32Array;
|
|
14
|
+
//# sourceMappingURL=preprocessing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preprocessing.d.ts","sourceRoot":"","sources":["../../src/core/preprocessing.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,WAAW,CACzB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACtC,OAAO,GAAE,MAAa,GACrB;IAAE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAYvD;AAED,wBAAgB,aAAa,CAC3B,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EACvB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EACxB,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB;IAAE,UAAU,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAkDvD;AAgBD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EAAE,GACZ,YAAY,CASd;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,YAAY,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,YAAY,CAad"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-processing utilities for pose estimation
|
|
3
|
+
*/
|
|
4
|
+
export function bboxXyxy2cs(bbox, padding = 1.25) {
|
|
5
|
+
const [x1, y1, x2, y2] = bbox;
|
|
6
|
+
const center = [(x1 + x2) / 2, (y1 + y2) / 2];
|
|
7
|
+
const w = x2 - x1;
|
|
8
|
+
const h = y2 - y1;
|
|
9
|
+
// Python: scale = w * padding, h * padding (different values!)
|
|
10
|
+
const scale = [w * padding, h * padding];
|
|
11
|
+
return { center, scale };
|
|
12
|
+
}
|
|
13
|
+
export function topDownAffine(imageSize, scale, center, img, imgWidth, imgHeight) {
|
|
14
|
+
const [w, h] = imageSize;
|
|
15
|
+
const srcW = scale[0];
|
|
16
|
+
const srcH = scale[1];
|
|
17
|
+
// Calculate transformation matrix
|
|
18
|
+
const scaleX = w / srcW;
|
|
19
|
+
const scaleY = h / srcH;
|
|
20
|
+
// Create output array
|
|
21
|
+
const outputSize = w * h * 3;
|
|
22
|
+
const resizedImg = new Float32Array(outputSize);
|
|
23
|
+
// Simple bilinear interpolation
|
|
24
|
+
for (let y = 0; y < h; y++) {
|
|
25
|
+
for (let x = 0; x < w; x++) {
|
|
26
|
+
// Map output coordinates to input coordinates
|
|
27
|
+
const srcX = (x / w) * srcW + (center[0] - srcW / 2);
|
|
28
|
+
const srcY = (y / h) * srcH + (center[1] - srcH / 2);
|
|
29
|
+
// Get the four nearest pixels
|
|
30
|
+
const x0 = Math.floor(srcX);
|
|
31
|
+
const y0 = Math.floor(srcY);
|
|
32
|
+
const x1 = x0 + 1;
|
|
33
|
+
const y1 = y0 + 1;
|
|
34
|
+
const dx = srcX - x0;
|
|
35
|
+
const dy = srcY - y0;
|
|
36
|
+
// Sample from input image with bounds checking
|
|
37
|
+
for (let c = 0; c < 3; c++) {
|
|
38
|
+
const p00 = getPixel(img, imgWidth, imgHeight, x0, y0, c);
|
|
39
|
+
const p10 = getPixel(img, imgWidth, imgHeight, x1, y0, c);
|
|
40
|
+
const p01 = getPixel(img, imgWidth, imgHeight, x0, y1, c);
|
|
41
|
+
const p11 = getPixel(img, imgWidth, imgHeight, x1, y1, c);
|
|
42
|
+
// Bilinear interpolation
|
|
43
|
+
const value = p00 * (1 - dx) * (1 - dy) +
|
|
44
|
+
p10 * dx * (1 - dy) +
|
|
45
|
+
p01 * (1 - dx) * dy +
|
|
46
|
+
p11 * dx * dy;
|
|
47
|
+
resizedImg[y * w * 3 + x * 3 + c] = value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Return original scale (not model dimensions) for postprocess
|
|
52
|
+
return { resizedImg, scale };
|
|
53
|
+
}
|
|
54
|
+
function getPixel(img, width, height, x, y, channel) {
|
|
55
|
+
if (x < 0 || x >= width || y < 0 || y >= height) {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
return img[y * width * 3 + x * 3 + channel];
|
|
59
|
+
}
|
|
60
|
+
export function normalizeImage(img, mean, std) {
|
|
61
|
+
const normalized = new Float32Array(img.length);
|
|
62
|
+
for (let i = 0; i < img.length; i++) {
|
|
63
|
+
const channel = i % 3;
|
|
64
|
+
normalized[i] = (img[i] - mean[channel]) / std[channel];
|
|
65
|
+
}
|
|
66
|
+
return normalized;
|
|
67
|
+
}
|
|
68
|
+
export function transposeImage(img, height, width) {
|
|
69
|
+
// HWC to CHW
|
|
70
|
+
const transposed = new Float32Array(img.length);
|
|
71
|
+
for (let c = 0; c < 3; c++) {
|
|
72
|
+
for (let h = 0; h < height; h++) {
|
|
73
|
+
for (let w = 0; w < width; w++) {
|
|
74
|
+
transposed[c * height * width + h * width + w] = img[h * width * 3 + w * 3 + c];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return transposed;
|
|
79
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rtmlib-ts - Real-Time Multi-Person Pose Estimation Library
|
|
3
|
+
*
|
|
4
|
+
* TypeScript port of rtmlib Python library
|
|
5
|
+
* Based on RTMPose, DWPose, RTMO, RTMW models
|
|
6
|
+
*/
|
|
7
|
+
export { YOLOX } from './models/yolox';
|
|
8
|
+
export { YOLO12 } from './models/yolo12';
|
|
9
|
+
export { RTMPose } from './models/rtmpose';
|
|
10
|
+
export { RTMPose3D } from './models/rtmpose3d';
|
|
11
|
+
export { ObjectDetector, COCO_CLASSES } from './solution/objectDetector';
|
|
12
|
+
export { PoseDetector } from './solution/poseDetector';
|
|
13
|
+
export { Pose3DDetector, type Person3D, type Pose3DStats } from './solution/pose3dDetector';
|
|
14
|
+
export { CustomDetector, type CustomDetectorConfig, type DetectionResult } from './solution/customDetector';
|
|
15
|
+
export { AnimalDetector, ANIMAL_CLASSES, VITPOSE_MODELS, type VitPoseModelType, type DetectedAnimal, type AnimalKeypoint } from './solution/animalDetector';
|
|
16
|
+
export { Wholebody } from './solution/wholebody';
|
|
17
|
+
export { Wholebody3D, type Wholebody3DResult } from './solution/wholebody3d';
|
|
18
|
+
export { Body } from './solution/body';
|
|
19
|
+
export { Hand } from './solution/hand';
|
|
20
|
+
export { BodyWithFeet } from './solution/bodyWithFeet';
|
|
21
|
+
export { PoseTracker } from './solution/poseTracker';
|
|
22
|
+
export { drawBbox, drawSkeleton, drawDetectionsOnCanvas, drawPoseOnCanvas, drawResultsOnCanvas } from './visualization/draw';
|
|
23
|
+
export { getCachedModel, isModelCached, preloadModels, clearModelCache, getCacheSize, getCacheInfo, } from './core/modelCache';
|
|
24
|
+
export type { Keypoint, BodyResult, HandResult, FaceResult, PoseResult, BBox, Detection, ModelConfig, ModeType, BackendType, DeviceType, ImageData, RGBImage, BGRImage, } from './types/index';
|
|
25
|
+
export { coco17, coco133, hand21, halpe26, openpose18, openpose134, } from './visualization/skeleton/index';
|
|
26
|
+
export declare const VERSION = "0.0.1";
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5G,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC5J,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG7H,OAAO,EACL,cAAc,EACd,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EACV,QAAQ,EACR,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,IAAI,EACJ,SAAS,EACT,WAAW,EACX,QAAQ,EACR,WAAW,EACX,UAAU,EACV,SAAS,EACT,QAAQ,EACR,QAAQ,GACT,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,MAAM,EACN,OAAO,EACP,MAAM,EACN,OAAO,EACP,UAAU,EACV,WAAW,GACZ,MAAM,gCAAgC,CAAC;AAGxC,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rtmlib-ts - Real-Time Multi-Person Pose Estimation Library
|
|
3
|
+
*
|
|
4
|
+
* TypeScript port of rtmlib Python library
|
|
5
|
+
* Based on RTMPose, DWPose, RTMO, RTMW models
|
|
6
|
+
*/
|
|
7
|
+
// Models
|
|
8
|
+
export { YOLOX } from './models/yolox';
|
|
9
|
+
export { YOLO12 } from './models/yolo12';
|
|
10
|
+
export { RTMPose } from './models/rtmpose';
|
|
11
|
+
export { RTMPose3D } from './models/rtmpose3d';
|
|
12
|
+
// Solutions (High-level APIs)
|
|
13
|
+
export { ObjectDetector, COCO_CLASSES } from './solution/objectDetector';
|
|
14
|
+
export { PoseDetector } from './solution/poseDetector';
|
|
15
|
+
export { Pose3DDetector } from './solution/pose3dDetector';
|
|
16
|
+
export { CustomDetector } from './solution/customDetector';
|
|
17
|
+
export { AnimalDetector, ANIMAL_CLASSES, VITPOSE_MODELS } from './solution/animalDetector';
|
|
18
|
+
export { Wholebody } from './solution/wholebody';
|
|
19
|
+
export { Wholebody3D } from './solution/wholebody3d';
|
|
20
|
+
export { Body } from './solution/body';
|
|
21
|
+
export { Hand } from './solution/hand';
|
|
22
|
+
export { BodyWithFeet } from './solution/bodyWithFeet';
|
|
23
|
+
export { PoseTracker } from './solution/poseTracker';
|
|
24
|
+
// Visualization
|
|
25
|
+
export { drawBbox, drawSkeleton, drawDetectionsOnCanvas, drawPoseOnCanvas, drawResultsOnCanvas } from './visualization/draw';
|
|
26
|
+
// Model caching utilities
|
|
27
|
+
export { getCachedModel, isModelCached, preloadModels, clearModelCache, getCacheSize, getCacheInfo, } from './core/modelCache';
|
|
28
|
+
// Skeleton configurations
|
|
29
|
+
export { coco17, coco133, hand21, halpe26, openpose18, openpose134, } from './visualization/skeleton/index';
|
|
30
|
+
// Version
|
|
31
|
+
export const VERSION = '0.0.1';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RTMPose model for pose estimation
|
|
3
|
+
* Supports RTMPose, DWPose, RTMW variants
|
|
4
|
+
* Uses onnxruntime-web for browser compatibility
|
|
5
|
+
*/
|
|
6
|
+
import { BaseTool } from '../core/base';
|
|
7
|
+
import { BBox, BackendType } from '../types/index';
|
|
8
|
+
export declare class RTMPose extends BaseTool {
|
|
9
|
+
private toOpenpose;
|
|
10
|
+
private simccSplitRatio;
|
|
11
|
+
private initialized;
|
|
12
|
+
private readonly defaultMean;
|
|
13
|
+
private readonly defaultStd;
|
|
14
|
+
constructor(onnxModel: string, modelInputSize?: [number, number], // [height, width]
|
|
15
|
+
toOpenpose?: boolean, backend?: BackendType);
|
|
16
|
+
init(): Promise<void>;
|
|
17
|
+
call(image: Uint8Array, imgWidth: number, imgHeight: number, bboxes?: BBox[]): Promise<{
|
|
18
|
+
keypoints: number[][];
|
|
19
|
+
scores: number[];
|
|
20
|
+
}>;
|
|
21
|
+
private preprocess;
|
|
22
|
+
private postprocess;
|
|
23
|
+
private convertCocoToOpenpose;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=rtmpose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtmpose.d.ts","sourceRoot":"","sources":["../../src/models/rtmpose.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEnD,qBAAa,OAAQ,SAAQ,QAAQ;IACnC,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,WAAW,CAAkB;IAErC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;IACnE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqC;gBAG9D,SAAS,EAAE,MAAM,EACjB,cAAc,GAAE,CAAC,MAAM,EAAE,MAAM,CAAc,EAAG,kBAAkB;IAClE,UAAU,GAAE,OAAe,EAC3B,OAAO,GAAE,WAAsB;IAM3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrB,IAAI,CACR,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,IAAI,EAAO,GAClB,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAuCvD,OAAO,CAAC,UAAU;IAsFlB,OAAO,CAAC,WAAW;IAsDnB,OAAO,CAAC,qBAAqB;CA+C9B"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RTMPose model for pose estimation
|
|
3
|
+
* Supports RTMPose, DWPose, RTMW variants
|
|
4
|
+
* Uses onnxruntime-web for browser compatibility
|
|
5
|
+
*/
|
|
6
|
+
import { BaseTool } from '../core/base';
|
|
7
|
+
export class RTMPose extends BaseTool {
|
|
8
|
+
constructor(onnxModel, modelInputSize = [384, 288], // [height, width]
|
|
9
|
+
toOpenpose = false, backend = 'webgpu') {
|
|
10
|
+
super(onnxModel, modelInputSize, null, null, backend);
|
|
11
|
+
this.simccSplitRatio = 2.0;
|
|
12
|
+
this.initialized = false;
|
|
13
|
+
this.defaultMean = [123.675, 116.28, 103.53];
|
|
14
|
+
this.defaultStd = [58.395, 57.12, 57.375];
|
|
15
|
+
this.toOpenpose = toOpenpose;
|
|
16
|
+
}
|
|
17
|
+
async init() {
|
|
18
|
+
// Web version - model path is direct URL
|
|
19
|
+
await super.init();
|
|
20
|
+
this.initialized = true;
|
|
21
|
+
}
|
|
22
|
+
async call(image, imgWidth, imgHeight, bboxes = []) {
|
|
23
|
+
if (!this.initialized) {
|
|
24
|
+
await this.init();
|
|
25
|
+
}
|
|
26
|
+
if (bboxes.length === 0) {
|
|
27
|
+
bboxes = [{ x1: 0, y1: 0, x2: imgWidth, y2: imgHeight }];
|
|
28
|
+
}
|
|
29
|
+
const allKeypoints = [];
|
|
30
|
+
const allScores = [];
|
|
31
|
+
for (const bbox of bboxes) {
|
|
32
|
+
const { tensor, center, scale, inputSize } = this.preprocess(image, imgWidth, imgHeight, bbox);
|
|
33
|
+
const outputs = await this.inference(tensor, inputSize);
|
|
34
|
+
const { keypoints, scores } = this.postprocess(outputs[0].data, outputs[1].data, outputs[0].dims, outputs[1].dims, center, scale);
|
|
35
|
+
allKeypoints.push(keypoints);
|
|
36
|
+
allScores.push(scores);
|
|
37
|
+
}
|
|
38
|
+
// Flatten results
|
|
39
|
+
const keypoints = allKeypoints.flat();
|
|
40
|
+
const scores = allScores.flat();
|
|
41
|
+
if (this.toOpenpose) {
|
|
42
|
+
const converted = this.convertCocoToOpenpose(keypoints, scores);
|
|
43
|
+
return converted;
|
|
44
|
+
}
|
|
45
|
+
return { keypoints, scores };
|
|
46
|
+
}
|
|
47
|
+
preprocess(img, imgWidth, imgHeight, bbox) {
|
|
48
|
+
const [inputH, inputW] = this.modelInputSize; // H=384, W=288
|
|
49
|
+
// Center and scale from bbox with padding
|
|
50
|
+
const center = [
|
|
51
|
+
bbox.x1 + (bbox.x2 - bbox.x1) / 2,
|
|
52
|
+
bbox.y1 + (bbox.y2 - bbox.y1) / 2,
|
|
53
|
+
];
|
|
54
|
+
const bboxWidth = bbox.x2 - bbox.x1;
|
|
55
|
+
const bboxHeight = bbox.y2 - bbox.y1;
|
|
56
|
+
const bboxAspectRatio = bboxWidth / bboxHeight;
|
|
57
|
+
const modelAspectRatio = inputW / inputH;
|
|
58
|
+
let scaleW, scaleH;
|
|
59
|
+
if (bboxAspectRatio > modelAspectRatio) {
|
|
60
|
+
scaleW = bboxWidth * 1.25;
|
|
61
|
+
scaleH = scaleW / modelAspectRatio;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
scaleH = bboxHeight * 1.25;
|
|
65
|
+
scaleW = scaleH * modelAspectRatio;
|
|
66
|
+
}
|
|
67
|
+
const scale = [scaleW, scaleH];
|
|
68
|
+
// Create canvas for cropping
|
|
69
|
+
const canvas = document.createElement('canvas');
|
|
70
|
+
const ctx = canvas.getContext('2d');
|
|
71
|
+
canvas.width = inputW;
|
|
72
|
+
canvas.height = inputH;
|
|
73
|
+
ctx.fillStyle = '#FFFFFF';
|
|
74
|
+
ctx.fillRect(0, 0, inputW, inputH);
|
|
75
|
+
// Create source canvas from image data
|
|
76
|
+
const srcCanvas = document.createElement('canvas');
|
|
77
|
+
const srcCtx = srcCanvas.getContext('2d');
|
|
78
|
+
srcCanvas.width = imgWidth;
|
|
79
|
+
srcCanvas.height = imgHeight;
|
|
80
|
+
const srcImageData = srcCtx.createImageData(imgWidth, imgHeight);
|
|
81
|
+
srcImageData.data.set(img);
|
|
82
|
+
srcCtx.putImageData(srcImageData, 0, 0);
|
|
83
|
+
// Calculate source region
|
|
84
|
+
const srcX = center[0] - scaleW / 2;
|
|
85
|
+
const srcY = center[1] - scaleH / 2;
|
|
86
|
+
// Draw cropped and scaled region
|
|
87
|
+
ctx.drawImage(srcCanvas, srcX, srcY, scaleW, scaleH, 0, 0, inputW, inputH);
|
|
88
|
+
const imageData = ctx.getImageData(0, 0, inputW, inputH);
|
|
89
|
+
// Normalize with mean/std
|
|
90
|
+
const data = new Float32Array(inputW * inputH * 3);
|
|
91
|
+
for (let i = 0; i < imageData.data.length; i += 4) {
|
|
92
|
+
const pixelIndex = i / 4;
|
|
93
|
+
for (let c = 0; c < 3; c++) {
|
|
94
|
+
const value = imageData.data[i + c];
|
|
95
|
+
data[c * inputW * inputH + pixelIndex] = (value - this.defaultMean[c]) / this.defaultStd[c];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
tensor: data,
|
|
100
|
+
center,
|
|
101
|
+
scale,
|
|
102
|
+
inputSize: [inputH, inputW],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
postprocess(simccX, simccY, outputShapeX, outputShapeY, center, scale) {
|
|
106
|
+
const numKeypoints = outputShapeX[1];
|
|
107
|
+
const wx = outputShapeX[2];
|
|
108
|
+
const wy = outputShapeY[2];
|
|
109
|
+
const keypoints = [];
|
|
110
|
+
const scores = [];
|
|
111
|
+
for (let k = 0; k < numKeypoints; k++) {
|
|
112
|
+
// Find argmax for x
|
|
113
|
+
let maxX = -Infinity;
|
|
114
|
+
let argmaxX = 0;
|
|
115
|
+
for (let i = 0; i < wx; i++) {
|
|
116
|
+
const val = simccX[k * wx + i];
|
|
117
|
+
if (val > maxX) {
|
|
118
|
+
maxX = val;
|
|
119
|
+
argmaxX = i;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Find argmax for y
|
|
123
|
+
let maxY = -Infinity;
|
|
124
|
+
let argmaxY = 0;
|
|
125
|
+
for (let i = 0; i < wy; i++) {
|
|
126
|
+
const val = simccY[k * wy + i];
|
|
127
|
+
if (val > maxY) {
|
|
128
|
+
maxY = val;
|
|
129
|
+
argmaxY = i;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const score = 0.5 * (maxX + maxY);
|
|
133
|
+
// Normalize to [0, 1] and transform to original image coordinates
|
|
134
|
+
const normX = argmaxX / wx;
|
|
135
|
+
const normY = argmaxY / wy;
|
|
136
|
+
const kptX = (normX - 0.5) * scale[0] + center[0];
|
|
137
|
+
const kptY = (normY - 0.5) * scale[1] + center[1];
|
|
138
|
+
keypoints.push([kptX, kptY]);
|
|
139
|
+
scores.push(score);
|
|
140
|
+
}
|
|
141
|
+
return { keypoints, scores };
|
|
142
|
+
}
|
|
143
|
+
convertCocoToOpenpose(keypoints, scores) {
|
|
144
|
+
// COCO 17 keypoints to OpenPose 18 keypoints mapping
|
|
145
|
+
const cocoToOpenpose = [
|
|
146
|
+
0, // nose
|
|
147
|
+
1, // neck (average of shoulders)
|
|
148
|
+
2, // right_shoulder
|
|
149
|
+
3, // right_elbow
|
|
150
|
+
4, // right_wrist
|
|
151
|
+
5, // left_shoulder
|
|
152
|
+
6, // left_elbow
|
|
153
|
+
7, // left_wrist
|
|
154
|
+
8, // right_hip
|
|
155
|
+
9, // right_knee
|
|
156
|
+
10, // right_ankle
|
|
157
|
+
11, // left_hip
|
|
158
|
+
12, // left_knee
|
|
159
|
+
13, // left_ankle
|
|
160
|
+
14, // right_eye
|
|
161
|
+
15, // left_eye
|
|
162
|
+
16, // left_ear
|
|
163
|
+
];
|
|
164
|
+
const openposeKeypoints = [];
|
|
165
|
+
const openposeScores = [];
|
|
166
|
+
for (let i = 0; i < 17; i++) {
|
|
167
|
+
if (i === 1) {
|
|
168
|
+
// Neck is average of shoulders
|
|
169
|
+
const rightShoulder = keypoints[2];
|
|
170
|
+
const leftShoulder = keypoints[5];
|
|
171
|
+
openposeKeypoints.push([
|
|
172
|
+
(rightShoulder[0] + leftShoulder[0]) / 2,
|
|
173
|
+
(rightShoulder[1] + leftShoulder[1]) / 2,
|
|
174
|
+
]);
|
|
175
|
+
openposeScores.push((scores[2] + scores[5]) / 2);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
const cocoIdx = cocoToOpenpose[i];
|
|
179
|
+
openposeKeypoints.push([...keypoints[cocoIdx]]);
|
|
180
|
+
openposeScores.push(scores[cocoIdx]);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return { keypoints: openposeKeypoints, scores: openposeScores };
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RTMPose3D model for 3D pose estimation
|
|
3
|
+
* Extends RTMPose with Z-axis prediction
|
|
4
|
+
* Based on rtmlib RTMPose3d class
|
|
5
|
+
*/
|
|
6
|
+
import { BaseTool } from '../core/base';
|
|
7
|
+
import { BBox, BackendType } from '../types/index';
|
|
8
|
+
export declare class RTMPose3D extends BaseTool {
|
|
9
|
+
private toOpenpose;
|
|
10
|
+
private simccSplitRatio;
|
|
11
|
+
private zRange;
|
|
12
|
+
private initialized;
|
|
13
|
+
private readonly defaultMean;
|
|
14
|
+
private readonly defaultStd;
|
|
15
|
+
constructor(onnxModel: string, modelInputSize?: [number, number], // [width=288, height=384] - creates tensor [1,3,384,288]
|
|
16
|
+
toOpenpose?: boolean, backend?: BackendType, zRange?: number);
|
|
17
|
+
init(): Promise<void>;
|
|
18
|
+
call(image: Uint8Array, imgWidth: number, imgHeight: number, bboxes?: BBox[]): Promise<{
|
|
19
|
+
keypoints: number[][][];
|
|
20
|
+
scores: number[][];
|
|
21
|
+
keypointsSimcc: number[][][];
|
|
22
|
+
keypoints2d: number[][][];
|
|
23
|
+
}>;
|
|
24
|
+
private preprocess;
|
|
25
|
+
private warpAffine;
|
|
26
|
+
private postprocess;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=rtmpose3d.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtmpose3d.d.ts","sourceRoot":"","sources":["../../src/models/rtmpose3d.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEnD,qBAAa,SAAU,SAAQ,QAAQ;IACrC,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,WAAW,CAAkB;IAErC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;IACnE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqC;gBAG9D,SAAS,EAAE,MAAM,EACjB,cAAc,GAAE,CAAC,MAAM,EAAE,MAAM,CAAc,EAAE,yDAAyD;IACxG,UAAU,GAAE,OAAe,EAC3B,OAAO,GAAE,WAAsB,EAC/B,MAAM,CAAC,EAAE,MAAM;IASX,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrB,IAAI,CACR,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,IAAI,EAAO,GAClB,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACxB,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;QACnB,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC7B,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;KAC3B,CAAC;IAgDF,OAAO,CAAC,UAAU;IAqFlB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,WAAW;CA6FpB"}
|