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.
Files changed (150) hide show
  1. package/.gitattributes +1 -0
  2. package/README.md +202 -0
  3. package/dist/core/base.d.ts +20 -0
  4. package/dist/core/base.d.ts.map +1 -0
  5. package/dist/core/base.js +40 -0
  6. package/dist/core/file.d.ts +11 -0
  7. package/dist/core/file.d.ts.map +1 -0
  8. package/dist/core/file.js +111 -0
  9. package/dist/core/modelCache.d.ts +35 -0
  10. package/dist/core/modelCache.d.ts.map +1 -0
  11. package/dist/core/modelCache.js +161 -0
  12. package/dist/core/posePostprocessing.d.ts +12 -0
  13. package/dist/core/posePostprocessing.d.ts.map +1 -0
  14. package/dist/core/posePostprocessing.js +76 -0
  15. package/dist/core/postprocessing.d.ts +10 -0
  16. package/dist/core/postprocessing.d.ts.map +1 -0
  17. package/dist/core/postprocessing.js +70 -0
  18. package/dist/core/preprocessing.d.ts +14 -0
  19. package/dist/core/preprocessing.d.ts.map +1 -0
  20. package/dist/core/preprocessing.js +79 -0
  21. package/dist/index.d.ts +27 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +31 -0
  24. package/dist/models/rtmpose.d.ts +25 -0
  25. package/dist/models/rtmpose.d.ts.map +1 -0
  26. package/dist/models/rtmpose.js +185 -0
  27. package/dist/models/rtmpose3d.d.ts +28 -0
  28. package/dist/models/rtmpose3d.d.ts.map +1 -0
  29. package/dist/models/rtmpose3d.js +184 -0
  30. package/dist/models/yolo12.d.ts +23 -0
  31. package/dist/models/yolo12.d.ts.map +1 -0
  32. package/dist/models/yolo12.js +165 -0
  33. package/dist/models/yolox.d.ts +18 -0
  34. package/dist/models/yolox.d.ts.map +1 -0
  35. package/dist/models/yolox.js +167 -0
  36. package/dist/solution/animalDetector.d.ts +229 -0
  37. package/dist/solution/animalDetector.d.ts.map +1 -0
  38. package/dist/solution/animalDetector.js +663 -0
  39. package/dist/solution/body.d.ts +16 -0
  40. package/dist/solution/body.d.ts.map +1 -0
  41. package/dist/solution/body.js +52 -0
  42. package/dist/solution/bodyWithFeet.d.ts +16 -0
  43. package/dist/solution/bodyWithFeet.d.ts.map +1 -0
  44. package/dist/solution/bodyWithFeet.js +52 -0
  45. package/dist/solution/customDetector.d.ts +137 -0
  46. package/dist/solution/customDetector.d.ts.map +1 -0
  47. package/dist/solution/customDetector.js +342 -0
  48. package/dist/solution/hand.d.ts +14 -0
  49. package/dist/solution/hand.d.ts.map +1 -0
  50. package/dist/solution/hand.js +20 -0
  51. package/dist/solution/index.d.ts +10 -0
  52. package/dist/solution/index.d.ts.map +1 -0
  53. package/dist/solution/index.js +9 -0
  54. package/dist/solution/objectDetector.d.ts +172 -0
  55. package/dist/solution/objectDetector.d.ts.map +1 -0
  56. package/dist/solution/objectDetector.js +606 -0
  57. package/dist/solution/pose3dDetector.d.ts +145 -0
  58. package/dist/solution/pose3dDetector.d.ts.map +1 -0
  59. package/dist/solution/pose3dDetector.js +611 -0
  60. package/dist/solution/poseDetector.d.ts +198 -0
  61. package/dist/solution/poseDetector.d.ts.map +1 -0
  62. package/dist/solution/poseDetector.js +622 -0
  63. package/dist/solution/poseTracker.d.ts +22 -0
  64. package/dist/solution/poseTracker.d.ts.map +1 -0
  65. package/dist/solution/poseTracker.js +106 -0
  66. package/dist/solution/wholebody.d.ts +19 -0
  67. package/dist/solution/wholebody.d.ts.map +1 -0
  68. package/dist/solution/wholebody.js +82 -0
  69. package/dist/solution/wholebody3d.d.ts +22 -0
  70. package/dist/solution/wholebody3d.d.ts.map +1 -0
  71. package/dist/solution/wholebody3d.js +75 -0
  72. package/dist/types/index.d.ts +52 -0
  73. package/dist/types/index.d.ts.map +1 -0
  74. package/dist/types/index.js +5 -0
  75. package/dist/visualization/draw.d.ts +57 -0
  76. package/dist/visualization/draw.d.ts.map +1 -0
  77. package/dist/visualization/draw.js +400 -0
  78. package/dist/visualization/skeleton/coco133.d.ts +350 -0
  79. package/dist/visualization/skeleton/coco133.d.ts.map +1 -0
  80. package/dist/visualization/skeleton/coco133.js +120 -0
  81. package/dist/visualization/skeleton/coco17.d.ts +180 -0
  82. package/dist/visualization/skeleton/coco17.d.ts.map +1 -0
  83. package/dist/visualization/skeleton/coco17.js +48 -0
  84. package/dist/visualization/skeleton/halpe26.d.ts +278 -0
  85. package/dist/visualization/skeleton/halpe26.d.ts.map +1 -0
  86. package/dist/visualization/skeleton/halpe26.js +70 -0
  87. package/dist/visualization/skeleton/hand21.d.ts +196 -0
  88. package/dist/visualization/skeleton/hand21.d.ts.map +1 -0
  89. package/dist/visualization/skeleton/hand21.js +51 -0
  90. package/dist/visualization/skeleton/index.d.ts +10 -0
  91. package/dist/visualization/skeleton/index.d.ts.map +1 -0
  92. package/dist/visualization/skeleton/index.js +9 -0
  93. package/dist/visualization/skeleton/openpose134.d.ts +357 -0
  94. package/dist/visualization/skeleton/openpose134.d.ts.map +1 -0
  95. package/dist/visualization/skeleton/openpose134.js +116 -0
  96. package/dist/visualization/skeleton/openpose18.d.ts +177 -0
  97. package/dist/visualization/skeleton/openpose18.d.ts.map +1 -0
  98. package/dist/visualization/skeleton/openpose18.js +47 -0
  99. package/docs/ANIMAL_DETECTOR.md +450 -0
  100. package/docs/CUSTOM_DETECTOR.md +568 -0
  101. package/docs/OBJECT_DETECTOR.md +373 -0
  102. package/docs/POSE3D_DETECTOR.md +458 -0
  103. package/docs/POSE_DETECTOR.md +442 -0
  104. package/examples/README.md +119 -0
  105. package/examples/index.html +746 -0
  106. package/package.json +51 -0
  107. package/playground/README.md +114 -0
  108. package/playground/app/favicon.ico +0 -0
  109. package/playground/app/globals.css +17 -0
  110. package/playground/app/layout.tsx +19 -0
  111. package/playground/app/page.tsx +1338 -0
  112. package/playground/eslint.config.mjs +18 -0
  113. package/playground/next.config.ts +34 -0
  114. package/playground/package-lock.json +6723 -0
  115. package/playground/package.json +27 -0
  116. package/playground/postcss.config.mjs +7 -0
  117. package/playground/tsconfig.json +34 -0
  118. package/src/core/base.ts +66 -0
  119. package/src/core/file.ts +141 -0
  120. package/src/core/modelCache.ts +189 -0
  121. package/src/core/posePostprocessing.ts +91 -0
  122. package/src/core/postprocessing.ts +93 -0
  123. package/src/core/preprocessing.ts +127 -0
  124. package/src/index.ts +69 -0
  125. package/src/models/rtmpose.ts +265 -0
  126. package/src/models/rtmpose3d.ts +289 -0
  127. package/src/models/yolo12.ts +220 -0
  128. package/src/models/yolox.ts +214 -0
  129. package/src/solution/animalDetector.ts +955 -0
  130. package/src/solution/body.ts +89 -0
  131. package/src/solution/bodyWithFeet.ts +89 -0
  132. package/src/solution/customDetector.ts +474 -0
  133. package/src/solution/hand.ts +52 -0
  134. package/src/solution/index.ts +10 -0
  135. package/src/solution/objectDetector.ts +816 -0
  136. package/src/solution/pose3dDetector.ts +890 -0
  137. package/src/solution/poseDetector.ts +892 -0
  138. package/src/solution/poseTracker.ts +172 -0
  139. package/src/solution/wholebody.ts +130 -0
  140. package/src/solution/wholebody3d.ts +125 -0
  141. package/src/types/index.ts +62 -0
  142. package/src/visualization/draw.ts +543 -0
  143. package/src/visualization/skeleton/coco133.ts +131 -0
  144. package/src/visualization/skeleton/coco17.ts +49 -0
  145. package/src/visualization/skeleton/halpe26.ts +71 -0
  146. package/src/visualization/skeleton/hand21.ts +52 -0
  147. package/src/visualization/skeleton/index.ts +10 -0
  148. package/src/visualization/skeleton/openpose134.ts +125 -0
  149. package/src/visualization/skeleton/openpose18.ts +48 -0
  150. package/tsconfig.json +32 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Body solution - body pose estimation with 17 or 26 keypoints
3
+ */
4
+ import { YOLOX } from '../models/yolox';
5
+ import { RTMPose } from '../models/rtmpose';
6
+ export class Body {
7
+ constructor(det = null, detInputSize = [640, 640], pose = null, poseInputSize = [288, 384], mode = 'balanced', toOpenpose = false, backend = 'onnxruntime', device = 'cpu') {
8
+ let finalDet = det;
9
+ let finalDetInputSize = detInputSize;
10
+ let finalPose = pose;
11
+ let finalPoseInputSize = poseInputSize;
12
+ if (det === null) {
13
+ finalDet = Body.MODE[mode].det;
14
+ finalDetInputSize = Body.MODE[mode].detInputSize;
15
+ }
16
+ if (pose === null) {
17
+ finalPose = Body.MODE[mode].pose;
18
+ finalPoseInputSize = Body.MODE[mode].poseInputSize;
19
+ }
20
+ this.detModel = new YOLOX(finalDet, finalDetInputSize, 0.45, 0.7, backend);
21
+ this.poseModel = new RTMPose(finalPose, finalPoseInputSize, toOpenpose, backend);
22
+ }
23
+ async init() {
24
+ await this.detModel.init();
25
+ await this.poseModel.init();
26
+ }
27
+ async call(image, imgWidth, imgHeight) {
28
+ const bboxes = await this.detModel.call(image, imgWidth, imgHeight);
29
+ const result = await this.poseModel.call(image, imgWidth, imgHeight, bboxes);
30
+ return result;
31
+ }
32
+ }
33
+ Body.MODE = {
34
+ performance: {
35
+ det: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/yolox_l_8xb8-300e_humanart-ce1d7a62.zip',
36
+ detInputSize: [640, 640],
37
+ pose: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/rtmpose-l_simcc-body7_pt-body7_420e-384x288-3f5a1437_20230504.zip',
38
+ poseInputSize: [288, 384],
39
+ },
40
+ lightweight: {
41
+ det: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/yolox_nano_8xb8-300e_humanart-40f6f0d0.zip',
42
+ detInputSize: [416, 416],
43
+ pose: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/rtmpose-t_simcc-body7_pt-body7_420e-256x192-026a1439_20230504.zip',
44
+ poseInputSize: [192, 256],
45
+ },
46
+ balanced: {
47
+ det: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/yolox_m_8xb8-300e_humanart-c2c7a14a.zip',
48
+ detInputSize: [640, 640],
49
+ pose: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/rtmpose-m_simcc-body7_pt-body7_420e-256x192-e48f03d0_20230504.zip',
50
+ poseInputSize: [192, 256],
51
+ },
52
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * BodyWithFeet solution - body pose estimation with 26 keypoints (including feet)
3
+ */
4
+ import { ModeType } from '../types/index';
5
+ export declare class BodyWithFeet {
6
+ private detModel;
7
+ private poseModel;
8
+ private static readonly MODE;
9
+ constructor(det?: string | null, detInputSize?: [number, number], pose?: string | null, poseInputSize?: [number, number], mode?: ModeType, toOpenpose?: boolean, backend?: 'onnxruntime', device?: string);
10
+ init(): Promise<void>;
11
+ call(image: Uint8Array, imgWidth: number, imgHeight: number): Promise<{
12
+ keypoints: number[][];
13
+ scores: number[];
14
+ }>;
15
+ }
16
+ //# sourceMappingURL=bodyWithFeet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bodyWithFeet.d.ts","sourceRoot":"","sources":["../../src/solution/bodyWithFeet.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,QAAQ,EAAe,MAAM,gBAAgB,CAAC;AAEvD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,SAAS,CAAU;IAE3B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAmB1B;gBAGA,GAAG,GAAE,MAAM,GAAG,IAAW,EACzB,YAAY,GAAE,CAAC,MAAM,EAAE,MAAM,CAAc,EAC3C,IAAI,GAAE,MAAM,GAAG,IAAW,EAC1B,aAAa,GAAE,CAAC,MAAM,EAAE,MAAM,CAAc,EAC5C,IAAI,GAAE,QAAqB,EAC3B,UAAU,GAAE,OAAe,EAC3B,OAAO,GAAE,aAA6B,EACtC,MAAM,GAAE,MAAc;IAiClB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrB,IAAI,CACR,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAKxD"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * BodyWithFeet solution - body pose estimation with 26 keypoints (including feet)
3
+ */
4
+ import { YOLOX } from '../models/yolox';
5
+ import { RTMPose } from '../models/rtmpose';
6
+ export class BodyWithFeet {
7
+ constructor(det = null, detInputSize = [640, 640], pose = null, poseInputSize = [288, 384], mode = 'balanced', toOpenpose = false, backend = 'onnxruntime', device = 'cpu') {
8
+ let finalDet = det;
9
+ let finalDetInputSize = detInputSize;
10
+ let finalPose = pose;
11
+ let finalPoseInputSize = poseInputSize;
12
+ if (det === null) {
13
+ finalDet = BodyWithFeet.MODE[mode].det;
14
+ finalDetInputSize = BodyWithFeet.MODE[mode].detInputSize;
15
+ }
16
+ if (pose === null) {
17
+ finalPose = BodyWithFeet.MODE[mode].pose;
18
+ finalPoseInputSize = BodyWithFeet.MODE[mode].poseInputSize;
19
+ }
20
+ this.detModel = new YOLOX(finalDet, finalDetInputSize, 0.45, 0.7, backend);
21
+ this.poseModel = new RTMPose(finalPose, finalPoseInputSize, toOpenpose, backend);
22
+ }
23
+ async init() {
24
+ await this.detModel.init();
25
+ await this.poseModel.init();
26
+ }
27
+ async call(image, imgWidth, imgHeight) {
28
+ const bboxes = await this.detModel.call(image, imgWidth, imgHeight);
29
+ const result = await this.poseModel.call(image, imgWidth, imgHeight, bboxes);
30
+ return result;
31
+ }
32
+ }
33
+ BodyWithFeet.MODE = {
34
+ performance: {
35
+ det: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/yolox_l_8xb8-300e_humanart-ce1d7a62.zip',
36
+ detInputSize: [640, 640],
37
+ pose: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/rtmpose-l_simcc-body7_pt-body7-halpe26_700e-384x288-734182ce_20230605.zip',
38
+ poseInputSize: [288, 384],
39
+ },
40
+ lightweight: {
41
+ det: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/yolox_nano_8xb8-300e_humanart-40f6f0d0.zip',
42
+ detInputSize: [416, 416],
43
+ pose: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/rtmpose-t_simcc-body7_pt-body7-halpe26_700e-256x192-6020f8a6_20230605.zip',
44
+ poseInputSize: [192, 256],
45
+ },
46
+ balanced: {
47
+ det: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/yolox_m_8xb8-300e_humanart-c2c7a14a.zip',
48
+ detInputSize: [640, 640],
49
+ pose: 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/rtmpose-m_simcc-body7_pt-body7-halpe26_700e-256x192-4d3e73dd_20230605.zip',
50
+ poseInputSize: [192, 256],
51
+ },
52
+ };
@@ -0,0 +1,137 @@
1
+ /**
2
+ * CustomDetector - Maximum flexibility detector for any ONNX model
3
+ * Provides low-level API for custom model inference
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * // Simple usage with auto-config
8
+ * const detector = new CustomDetector({
9
+ * model: 'path/to/model.onnx',
10
+ * });
11
+ * await detector.init();
12
+ * const results = await detector.run(imageData, width, height);
13
+ *
14
+ * // Advanced usage with custom preprocessing
15
+ * const detector = new CustomDetector({
16
+ * model: 'path/to/model.onnx',
17
+ * inputName: 'input',
18
+ * outputNames: ['output1', 'output2'],
19
+ * preprocessing: (data) => customPreprocess(data),
20
+ * postprocessing: (outputs) => customPostprocess(outputs),
21
+ * });
22
+ * ```
23
+ */
24
+ import * as ort from 'onnxruntime-web';
25
+ /**
26
+ * Configuration options for CustomDetector
27
+ */
28
+ export interface CustomDetectorConfig {
29
+ /** Path to ONNX model (required) */
30
+ model: string;
31
+ /** Input tensor name (optional - auto-detected if not specified) */
32
+ inputName?: string;
33
+ /** Output tensor names (optional - auto-detected if not specified) */
34
+ outputNames?: string[];
35
+ /** Expected input shape [batch, channels, height, width] (optional) */
36
+ inputShape?: [number, number, number, number];
37
+ /** Custom preprocessing function */
38
+ preprocessing?: (data: ImageData, config: CustomDetectorConfig) => Float32Array | ort.Tensor;
39
+ /** Custom postprocessing function */
40
+ postprocessing?: (outputs: Record<string, ort.Tensor>, metadata: any) => any;
41
+ /** Execution backend (default: 'wasm') */
42
+ backend?: 'wasm' | 'webgpu';
43
+ /** Enable model caching (default: true) */
44
+ cache?: boolean;
45
+ /** Custom metadata for postprocessing */
46
+ metadata?: any;
47
+ /** Input normalization (default: { mean: [0, 0, 0], std: [1, 1, 1] }) */
48
+ normalization?: {
49
+ mean: number[];
50
+ std: number[];
51
+ };
52
+ /** Input size for automatic preprocessing (optional) */
53
+ inputSize?: [number, number];
54
+ /** Keep aspect ratio during preprocessing (default: true) */
55
+ keepAspectRatio?: boolean;
56
+ /** Background color for letterbox (default: black) */
57
+ backgroundColor?: string;
58
+ }
59
+ /**
60
+ * Detection result with metadata
61
+ */
62
+ export interface DetectionResult<T = any> {
63
+ /** Raw model outputs */
64
+ outputs: Record<string, ort.Tensor>;
65
+ /** Processed results */
66
+ data: T;
67
+ /** Inference time in ms */
68
+ inferenceTime: number;
69
+ /** Input shape used */
70
+ inputShape: number[];
71
+ }
72
+ export declare class CustomDetector {
73
+ private config;
74
+ private session;
75
+ private initialized;
76
+ private canvas;
77
+ private ctx;
78
+ constructor(config: CustomDetectorConfig);
79
+ /**
80
+ * Initialize the model
81
+ */
82
+ init(): Promise<void>;
83
+ /**
84
+ * Run inference on canvas
85
+ */
86
+ runFromCanvas<T = any>(canvas: HTMLCanvasElement): Promise<DetectionResult<T>>;
87
+ /**
88
+ * Run inference on video
89
+ */
90
+ runFromVideo<T = any>(video: HTMLVideoElement, targetCanvas?: HTMLCanvasElement): Promise<DetectionResult<T>>;
91
+ /**
92
+ * Run inference on image
93
+ */
94
+ runFromImage<T = any>(image: HTMLImageElement, targetCanvas?: HTMLCanvasElement): Promise<DetectionResult<T>>;
95
+ /**
96
+ * Run inference on bitmap
97
+ */
98
+ runFromBitmap<T = any>(bitmap: ImageBitmap, targetCanvas?: HTMLCanvasElement): Promise<DetectionResult<T>>;
99
+ /**
100
+ * Run inference on file
101
+ */
102
+ runFromFile<T = any>(file: File, targetCanvas?: HTMLCanvasElement): Promise<DetectionResult<T>>;
103
+ /**
104
+ * Run inference on blob
105
+ */
106
+ runFromBlob<T = any>(blob: Blob, targetCanvas?: HTMLCanvasElement): Promise<DetectionResult<T>>;
107
+ /**
108
+ * Run inference with custom preprocessing
109
+ */
110
+ run<T = any>(imageData: ImageData, width: number, height: number, metadata?: any): Promise<DetectionResult<T>>;
111
+ /**
112
+ * Get model info
113
+ */
114
+ getModelInfo(): {
115
+ inputNames: string[];
116
+ outputNames: string[];
117
+ inputCount: number;
118
+ outputCount: number;
119
+ };
120
+ /**
121
+ * Get tensor by name from outputs
122
+ */
123
+ getOutputTensor<T extends ort.Tensor = ort.Tensor>(outputs: Record<string, ort.Tensor>, name?: string): T;
124
+ /**
125
+ * Simple preprocessing - just normalize to [0, 1] and convert to CHW
126
+ */
127
+ private simplePreprocess;
128
+ /**
129
+ * Preprocess with letterbox and normalization
130
+ */
131
+ private preprocess;
132
+ /**
133
+ * Dispose resources
134
+ */
135
+ dispose(): void;
136
+ }
137
+ //# sourceMappingURL=customDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customDetector.d.ts","sourceRoot":"","sources":["../../src/solution/customDetector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,342 @@
1
+ /**
2
+ * CustomDetector - Maximum flexibility detector for any ONNX model
3
+ * Provides low-level API for custom model inference
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * // Simple usage with auto-config
8
+ * const detector = new CustomDetector({
9
+ * model: 'path/to/model.onnx',
10
+ * });
11
+ * await detector.init();
12
+ * const results = await detector.run(imageData, width, height);
13
+ *
14
+ * // Advanced usage with custom preprocessing
15
+ * const detector = new CustomDetector({
16
+ * model: 'path/to/model.onnx',
17
+ * inputName: 'input',
18
+ * outputNames: ['output1', 'output2'],
19
+ * preprocessing: (data) => customPreprocess(data),
20
+ * postprocessing: (outputs) => customPostprocess(outputs),
21
+ * });
22
+ * ```
23
+ */
24
+ import * as ort from 'onnxruntime-web';
25
+ import { getCachedModel, isModelCached } from '../core/modelCache';
26
+ // Configure ONNX Runtime Web
27
+ ort.env.wasm.wasmPaths = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.23.0/dist/';
28
+ ort.env.wasm.simd = true;
29
+ ort.env.wasm.proxy = false;
30
+ /**
31
+ * Default configuration
32
+ */
33
+ const DEFAULT_CONFIG = {
34
+ backend: 'webgpu', // Default to WebGPU for better performance
35
+ cache: true,
36
+ keepAspectRatio: true,
37
+ backgroundColor: '#000000',
38
+ normalization: {
39
+ mean: [0, 0, 0],
40
+ std: [1, 1, 1],
41
+ },
42
+ };
43
+ export class CustomDetector {
44
+ constructor(config) {
45
+ this.session = null;
46
+ this.initialized = false;
47
+ this.canvas = null;
48
+ this.ctx = null;
49
+ this.config = {
50
+ ...DEFAULT_CONFIG,
51
+ ...config,
52
+ outputNames: config.outputNames || [],
53
+ inputShape: config.inputShape || [1, 3, 224, 224],
54
+ normalization: config.normalization || { mean: [0, 0, 0], std: [1, 1, 1] },
55
+ };
56
+ }
57
+ /**
58
+ * Initialize the model
59
+ */
60
+ async init() {
61
+ if (this.initialized)
62
+ return;
63
+ try {
64
+ console.log(`[CustomDetector] Loading model from: ${this.config.model}`);
65
+ let modelBuffer;
66
+ if (this.config.cache) {
67
+ const cached = await isModelCached(this.config.model);
68
+ console.log(`[CustomDetector] Cache ${cached ? 'hit' : 'miss'}`);
69
+ modelBuffer = await getCachedModel(this.config.model);
70
+ }
71
+ else {
72
+ const response = await fetch(this.config.model);
73
+ if (!response.ok) {
74
+ throw new Error(`Failed to fetch model: HTTP ${response.status}`);
75
+ }
76
+ modelBuffer = await response.arrayBuffer();
77
+ }
78
+ this.session = await ort.InferenceSession.create(modelBuffer, {
79
+ executionProviders: [this.config.backend],
80
+ graphOptimizationLevel: 'all',
81
+ });
82
+ // Auto-detect input/output names if not specified
83
+ if (!this.config.inputName && this.session.inputNames.length > 0) {
84
+ console.log(`[CustomDetector] Auto-detected input name: ${this.session.inputNames[0]}`);
85
+ }
86
+ if (this.config.outputNames.length === 0 && this.session.outputNames.length > 0) {
87
+ this.config.outputNames = [...this.session.outputNames];
88
+ console.log(`[CustomDetector] Auto-detected output names: ${this.config.outputNames}`);
89
+ }
90
+ console.log(`[CustomDetector] ✅ Initialized (${this.config.backend})`);
91
+ this.initialized = true;
92
+ }
93
+ catch (error) {
94
+ console.error('[CustomDetector] ❌ Initialization failed:', error);
95
+ throw error;
96
+ }
97
+ }
98
+ /**
99
+ * Run inference on canvas
100
+ */
101
+ async runFromCanvas(canvas) {
102
+ const ctx = canvas.getContext('2d');
103
+ if (!ctx) {
104
+ throw new Error('Could not get 2D context from canvas');
105
+ }
106
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
107
+ return this.run(imageData, canvas.width, canvas.height);
108
+ }
109
+ /**
110
+ * Run inference on video
111
+ */
112
+ async runFromVideo(video, targetCanvas) {
113
+ if (video.readyState < 2) {
114
+ throw new Error('Video not ready');
115
+ }
116
+ const canvas = targetCanvas || document.createElement('canvas');
117
+ canvas.width = video.videoWidth;
118
+ canvas.height = video.videoHeight;
119
+ const ctx = canvas.getContext('2d');
120
+ if (!ctx) {
121
+ throw new Error('Could not get 2D context from canvas');
122
+ }
123
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
124
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
125
+ return this.run(imageData, canvas.width, canvas.height);
126
+ }
127
+ /**
128
+ * Run inference on image
129
+ */
130
+ async runFromImage(image, targetCanvas) {
131
+ if (!image.complete || !image.naturalWidth) {
132
+ throw new Error('Image not loaded');
133
+ }
134
+ const canvas = targetCanvas || document.createElement('canvas');
135
+ canvas.width = image.naturalWidth;
136
+ canvas.height = image.naturalHeight;
137
+ const ctx = canvas.getContext('2d');
138
+ if (!ctx) {
139
+ throw new Error('Could not get 2D context from canvas');
140
+ }
141
+ ctx.drawImage(image, 0, 0);
142
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
143
+ return this.run(imageData, canvas.width, canvas.height);
144
+ }
145
+ /**
146
+ * Run inference on bitmap
147
+ */
148
+ async runFromBitmap(bitmap, targetCanvas) {
149
+ const canvas = targetCanvas || document.createElement('canvas');
150
+ canvas.width = bitmap.width;
151
+ canvas.height = bitmap.height;
152
+ const ctx = canvas.getContext('2d');
153
+ if (!ctx) {
154
+ throw new Error('Could not get 2D context from canvas');
155
+ }
156
+ ctx.drawImage(bitmap, 0, 0);
157
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
158
+ return this.run(imageData, canvas.width, canvas.height);
159
+ }
160
+ /**
161
+ * Run inference on file
162
+ */
163
+ async runFromFile(file, targetCanvas) {
164
+ return new Promise((resolve, reject) => {
165
+ const img = new Image();
166
+ img.onload = async () => {
167
+ try {
168
+ const result = await this.runFromImage(img, targetCanvas);
169
+ resolve(result);
170
+ }
171
+ catch (error) {
172
+ reject(error);
173
+ }
174
+ };
175
+ img.onerror = () => reject(new Error('Failed to load image'));
176
+ img.src = URL.createObjectURL(file);
177
+ });
178
+ }
179
+ /**
180
+ * Run inference on blob
181
+ */
182
+ async runFromBlob(blob, targetCanvas) {
183
+ const bitmap = await createImageBitmap(blob);
184
+ const result = await this.runFromBitmap(bitmap, targetCanvas);
185
+ bitmap.close();
186
+ return result;
187
+ }
188
+ /**
189
+ * Run inference with custom preprocessing
190
+ */
191
+ async run(imageData, width, height, metadata) {
192
+ if (!this.initialized) {
193
+ await this.init();
194
+ }
195
+ const startTime = performance.now();
196
+ // Preprocess
197
+ let inputTensor;
198
+ if (this.config.preprocessing) {
199
+ // Custom preprocessing
200
+ const result = this.config.preprocessing(imageData, this.config);
201
+ if (result instanceof Float32Array) {
202
+ const [h, w] = this.config.inputSize || [height, width];
203
+ inputTensor = new ort.Tensor('float32', result, [1, 3, h, w]);
204
+ }
205
+ else {
206
+ inputTensor = result;
207
+ }
208
+ }
209
+ else if (this.config.inputSize) {
210
+ // Automatic preprocessing with letterbox
211
+ inputTensor = this.preprocess(imageData, width, height, this.config.inputSize);
212
+ }
213
+ else {
214
+ // Simple preprocessing - just normalize
215
+ inputTensor = this.simplePreprocess(imageData);
216
+ }
217
+ // Get input name
218
+ const inputName = this.config.inputName || this.session.inputNames[0];
219
+ // Run inference
220
+ const feeds = {};
221
+ feeds[inputName] = inputTensor;
222
+ const results = await this.session.run(feeds);
223
+ // Postprocess
224
+ let data;
225
+ if (this.config.postprocessing) {
226
+ data = this.config.postprocessing(results, metadata || this.config.metadata);
227
+ }
228
+ else {
229
+ // Return raw outputs
230
+ data = results;
231
+ }
232
+ const inferenceTime = performance.now() - startTime;
233
+ return {
234
+ outputs: results,
235
+ data,
236
+ inferenceTime,
237
+ inputShape: [...inputTensor.dims],
238
+ };
239
+ }
240
+ /**
241
+ * Get model info
242
+ */
243
+ getModelInfo() {
244
+ if (!this.session) {
245
+ throw new Error('Model not initialized. Call init() first.');
246
+ }
247
+ return {
248
+ inputNames: [...this.session.inputNames],
249
+ outputNames: [...this.session.outputNames],
250
+ inputCount: this.session.inputNames.length,
251
+ outputCount: this.session.outputNames.length,
252
+ };
253
+ }
254
+ /**
255
+ * Get tensor by name from outputs
256
+ */
257
+ getOutputTensor(outputs, name) {
258
+ const tensorName = name || this.config.outputNames[0] || this.session.outputNames[0];
259
+ return outputs[tensorName];
260
+ }
261
+ /**
262
+ * Simple preprocessing - just normalize to [0, 1] and convert to CHW
263
+ */
264
+ simplePreprocess(imageData) {
265
+ const { width, height, data } = imageData;
266
+ const tensor = new Float32Array(3 * width * height);
267
+ for (let i = 0; i < data.length; i += 4) {
268
+ const pixelIdx = i / 4;
269
+ tensor[pixelIdx] = data[i] / 255;
270
+ tensor[pixelIdx + width * height] = data[i + 1] / 255;
271
+ tensor[pixelIdx + 2 * width * height] = data[i + 2] / 255;
272
+ }
273
+ return new ort.Tensor('float32', tensor, [1, 3, height, width]);
274
+ }
275
+ /**
276
+ * Preprocess with letterbox and normalization
277
+ */
278
+ preprocess(imageData, imgWidth, imgHeight, inputSize) {
279
+ const [inputW, inputH] = inputSize;
280
+ if (!this.canvas || !this.ctx) {
281
+ this.canvas = document.createElement('canvas');
282
+ this.canvas.width = inputW;
283
+ this.canvas.height = inputH;
284
+ this.ctx = this.canvas.getContext('2d', { willReadFrequently: true, alpha: false });
285
+ }
286
+ const ctx = this.ctx;
287
+ ctx.fillStyle = this.config.backgroundColor;
288
+ ctx.fillRect(0, 0, inputW, inputH);
289
+ // Calculate letterbox
290
+ const aspectRatio = imgWidth / imgHeight;
291
+ const targetAspectRatio = inputW / inputH;
292
+ let drawWidth, drawHeight, offsetX, offsetY;
293
+ if (this.config.keepAspectRatio) {
294
+ if (aspectRatio > targetAspectRatio) {
295
+ drawWidth = inputW;
296
+ drawHeight = Math.floor(inputW / aspectRatio);
297
+ offsetX = 0;
298
+ offsetY = Math.floor((inputH - drawHeight) / 2);
299
+ }
300
+ else {
301
+ drawHeight = inputH;
302
+ drawWidth = Math.floor(inputH * aspectRatio);
303
+ offsetX = Math.floor((inputW - drawWidth) / 2);
304
+ offsetY = 0;
305
+ }
306
+ }
307
+ else {
308
+ drawWidth = inputW;
309
+ drawHeight = inputH;
310
+ offsetX = 0;
311
+ offsetY = 0;
312
+ }
313
+ // Create source canvas
314
+ const srcCanvas = document.createElement('canvas');
315
+ const srcCtx = srcCanvas.getContext('2d');
316
+ srcCanvas.width = imgWidth;
317
+ srcCanvas.height = imgHeight;
318
+ srcCtx.putImageData(imageData, 0, 0);
319
+ // Draw with letterbox
320
+ ctx.drawImage(srcCanvas, 0, 0, imgWidth, imgHeight, offsetX, offsetY, drawWidth, drawHeight);
321
+ const paddedData = ctx.getImageData(0, 0, inputW, inputH);
322
+ const tensor = new Float32Array(inputW * inputH * 3);
323
+ const { mean, std } = this.config.normalization;
324
+ for (let i = 0; i < paddedData.data.length; i += 4) {
325
+ const pixelIdx = i / 4;
326
+ tensor[pixelIdx] = (paddedData.data[i] - mean[0]) / std[0];
327
+ tensor[pixelIdx + inputW * inputH] = (paddedData.data[i + 1] - mean[1]) / std[1];
328
+ tensor[pixelIdx + 2 * inputW * inputH] = (paddedData.data[i + 2] - mean[2]) / std[2];
329
+ }
330
+ return new ort.Tensor('float32', tensor, [1, 3, inputH, inputW]);
331
+ }
332
+ /**
333
+ * Dispose resources
334
+ */
335
+ dispose() {
336
+ if (this.session) {
337
+ this.session.release();
338
+ this.session = null;
339
+ }
340
+ this.initialized = false;
341
+ }
342
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Hand solution - hand pose estimation with 21 keypoints
3
+ */
4
+ export declare class Hand {
5
+ private detModel;
6
+ private poseModel;
7
+ constructor(det?: string, detInputSize?: [number, number], pose?: string, poseInputSize?: [number, number], toOpenpose?: boolean, backend?: 'onnxruntime', device?: string);
8
+ init(): Promise<void>;
9
+ call(image: Uint8Array, imgWidth: number, imgHeight: number): Promise<{
10
+ keypoints: number[][];
11
+ scores: number[];
12
+ }>;
13
+ }
14
+ //# sourceMappingURL=hand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hand.d.ts","sourceRoot":"","sources":["../../src/solution/hand.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,qBAAa,IAAI;IACf,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,SAAS,CAAU;gBAGzB,GAAG,GAAE,MAAwH,EAC7H,YAAY,GAAE,CAAC,MAAM,EAAE,MAAM,CAAc,EAC3C,IAAI,GAAE,MAAmJ,EACzJ,aAAa,GAAE,CAAC,MAAM,EAAE,MAAM,CAAc,EAC5C,UAAU,GAAE,OAAe,EAC3B,OAAO,GAAE,aAA6B,EACtC,MAAM,GAAE,MAAc;IAkBlB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrB,IAAI,CACR,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAKxD"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Hand solution - hand pose estimation with 21 keypoints
3
+ */
4
+ import { YOLOX } from '../models/yolox';
5
+ import { RTMPose } from '../models/rtmpose';
6
+ export class Hand {
7
+ constructor(det = 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/rtmdet_nano_8xb32-300e_hand-267f9c8f.zip', detInputSize = [320, 320], pose = 'https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/onnx_sdk/rtmpose-m_simcc-hand5_pt-aic-coco_210e-256x256-74fb594_20230320.zip', poseInputSize = [256, 256], toOpenpose = false, backend = 'onnxruntime', device = 'cpu') {
8
+ this.detModel = new YOLOX(det, detInputSize, 0.45, 0.5, backend);
9
+ this.poseModel = new RTMPose(pose, poseInputSize, toOpenpose, backend);
10
+ }
11
+ async init() {
12
+ await this.detModel.init();
13
+ await this.poseModel.init();
14
+ }
15
+ async call(image, imgWidth, imgHeight) {
16
+ const bboxes = await this.detModel.call(image, imgWidth, imgHeight);
17
+ const result = await this.poseModel.call(image, imgWidth, imgHeight, bboxes);
18
+ return result;
19
+ }
20
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Solution exports
3
+ */
4
+ export { Wholebody } from './wholebody';
5
+ export { Wholebody3D, type Wholebody3DResult } from './wholebody3d';
6
+ export { Body } from './body';
7
+ export { Hand } from './hand';
8
+ export { BodyWithFeet } from './bodyWithFeet';
9
+ export { PoseTracker } from './poseTracker';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/solution/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Solution exports
3
+ */
4
+ export { Wholebody } from './wholebody';
5
+ export { Wholebody3D } from './wholebody3d';
6
+ export { Body } from './body';
7
+ export { Hand } from './hand';
8
+ export { BodyWithFeet } from './bodyWithFeet';
9
+ export { PoseTracker } from './poseTracker';