@camstack/addon-vision 0.1.1 → 0.1.3

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 (111) hide show
  1. package/dist/addons/animal-classifier/index.js +999 -823
  2. package/dist/addons/animal-classifier/index.js.map +1 -1
  3. package/dist/addons/animal-classifier/index.mjs +242 -7
  4. package/dist/addons/animal-classifier/index.mjs.map +1 -1
  5. package/dist/addons/audio-classification/index.js +501 -379
  6. package/dist/addons/audio-classification/index.js.map +1 -1
  7. package/dist/addons/audio-classification/index.mjs +224 -4
  8. package/dist/addons/audio-classification/index.mjs.map +1 -1
  9. package/dist/addons/bird-global-classifier/index.js +1002 -826
  10. package/dist/addons/bird-global-classifier/index.js.map +1 -1
  11. package/dist/addons/bird-global-classifier/index.mjs +248 -7
  12. package/dist/addons/bird-global-classifier/index.mjs.map +1 -1
  13. package/dist/addons/bird-nabirds-classifier/index.js +1002 -826
  14. package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
  15. package/dist/addons/bird-nabirds-classifier/index.mjs +289 -7
  16. package/dist/addons/bird-nabirds-classifier/index.mjs.map +1 -1
  17. package/dist/addons/face-detection/index.js +1196 -935
  18. package/dist/addons/face-detection/index.js.map +1 -1
  19. package/dist/addons/face-detection/index.mjs +227 -7
  20. package/dist/addons/face-detection/index.mjs.map +1 -1
  21. package/dist/addons/face-recognition/index.js +1003 -808
  22. package/dist/addons/face-recognition/index.js.map +1 -1
  23. package/dist/addons/face-recognition/index.mjs +197 -6
  24. package/dist/addons/face-recognition/index.mjs.map +1 -1
  25. package/dist/addons/motion-detection/index.js +214 -111
  26. package/dist/addons/motion-detection/index.js.map +1 -1
  27. package/dist/addons/motion-detection/index.mjs +12 -9
  28. package/dist/addons/motion-detection/index.mjs.map +1 -1
  29. package/dist/addons/object-detection/index.js +1287 -1083
  30. package/dist/addons/object-detection/index.js.map +1 -1
  31. package/dist/addons/object-detection/index.mjs +373 -7
  32. package/dist/addons/object-detection/index.mjs.map +1 -1
  33. package/dist/addons/plate-detection/index.js +1075 -869
  34. package/dist/addons/plate-detection/index.js.map +1 -1
  35. package/dist/addons/plate-detection/index.mjs +230 -7
  36. package/dist/addons/plate-detection/index.mjs.map +1 -1
  37. package/dist/addons/plate-recognition/index.js +684 -506
  38. package/dist/addons/plate-recognition/index.js.map +1 -1
  39. package/dist/addons/plate-recognition/index.mjs +244 -5
  40. package/dist/addons/plate-recognition/index.mjs.map +1 -1
  41. package/dist/addons/segmentation-refiner/index.js +967 -791
  42. package/dist/addons/segmentation-refiner/index.js.map +1 -1
  43. package/dist/addons/segmentation-refiner/index.mjs +21 -17
  44. package/dist/addons/segmentation-refiner/index.mjs.map +1 -1
  45. package/dist/addons/vehicle-classifier/index.js +581 -411
  46. package/dist/addons/vehicle-classifier/index.js.map +1 -1
  47. package/dist/addons/vehicle-classifier/index.mjs +20 -16
  48. package/dist/addons/vehicle-classifier/index.mjs.map +1 -1
  49. package/dist/chunk-2YMA6QOV.mjs +193 -0
  50. package/dist/chunk-2YMA6QOV.mjs.map +1 -0
  51. package/dist/chunk-3IIFBJCD.mjs +45 -0
  52. package/dist/chunk-BS4DKYGN.mjs +48 -0
  53. package/dist/{chunk-7DYHXUPZ.mjs.map → chunk-BS4DKYGN.mjs.map} +1 -1
  54. package/dist/chunk-DE7I3VHO.mjs +106 -0
  55. package/dist/{chunk-KUO2BVFY.mjs.map → chunk-DE7I3VHO.mjs.map} +1 -1
  56. package/dist/chunk-F6D2OZ36.mjs +89 -0
  57. package/dist/chunk-F6D2OZ36.mjs.map +1 -0
  58. package/dist/chunk-GAOIFQDX.mjs +59 -0
  59. package/dist/chunk-GAOIFQDX.mjs.map +1 -0
  60. package/dist/chunk-HUIX2XVR.mjs +159 -0
  61. package/dist/chunk-HUIX2XVR.mjs.map +1 -0
  62. package/dist/chunk-K36R6HWY.mjs +51 -0
  63. package/dist/{chunk-XZ6ZMXXU.mjs.map → chunk-K36R6HWY.mjs.map} +1 -1
  64. package/dist/chunk-MBTAI3WE.mjs +78 -0
  65. package/dist/chunk-MBTAI3WE.mjs.map +1 -0
  66. package/dist/chunk-MGT6RUVX.mjs +423 -0
  67. package/dist/{chunk-BP7H4NFS.mjs.map → chunk-MGT6RUVX.mjs.map} +1 -1
  68. package/dist/chunk-PIFS7AIT.mjs +446 -0
  69. package/dist/chunk-PIFS7AIT.mjs.map +1 -0
  70. package/dist/chunk-WG66JYYW.mjs +116 -0
  71. package/dist/{chunk-22BHCDT5.mjs.map → chunk-WG66JYYW.mjs.map} +1 -1
  72. package/dist/chunk-XD7WGXHZ.mjs +82 -0
  73. package/dist/{chunk-DUN6XU3N.mjs.map → chunk-XD7WGXHZ.mjs.map} +1 -1
  74. package/dist/chunk-YYDM6V2F.mjs +113 -0
  75. package/dist/{chunk-BR2FPGOX.mjs.map → chunk-YYDM6V2F.mjs.map} +1 -1
  76. package/dist/chunk-ZK7P3TZN.mjs +286 -0
  77. package/dist/chunk-ZK7P3TZN.mjs.map +1 -0
  78. package/dist/index.js +4443 -3925
  79. package/dist/index.js.map +1 -1
  80. package/dist/index.mjs +2698 -250
  81. package/dist/index.mjs.map +1 -1
  82. package/package.json +2 -3
  83. package/dist/chunk-22BHCDT5.mjs +0 -101
  84. package/dist/chunk-6DJZZR64.mjs +0 -336
  85. package/dist/chunk-6DJZZR64.mjs.map +0 -1
  86. package/dist/chunk-7DYHXUPZ.mjs +0 -36
  87. package/dist/chunk-BJTO5JO5.mjs +0 -11
  88. package/dist/chunk-BP7H4NFS.mjs +0 -412
  89. package/dist/chunk-BR2FPGOX.mjs +0 -98
  90. package/dist/chunk-DNQNGDR4.mjs +0 -256
  91. package/dist/chunk-DNQNGDR4.mjs.map +0 -1
  92. package/dist/chunk-DUN6XU3N.mjs +0 -72
  93. package/dist/chunk-EPNWLSCG.mjs +0 -387
  94. package/dist/chunk-EPNWLSCG.mjs.map +0 -1
  95. package/dist/chunk-G32RCIUI.mjs +0 -645
  96. package/dist/chunk-G32RCIUI.mjs.map +0 -1
  97. package/dist/chunk-GR65KM6X.mjs +0 -289
  98. package/dist/chunk-GR65KM6X.mjs.map +0 -1
  99. package/dist/chunk-H7LMBTS5.mjs +0 -276
  100. package/dist/chunk-H7LMBTS5.mjs.map +0 -1
  101. package/dist/chunk-IK4XIQPC.mjs +0 -242
  102. package/dist/chunk-IK4XIQPC.mjs.map +0 -1
  103. package/dist/chunk-J6VNIIYX.mjs +0 -269
  104. package/dist/chunk-J6VNIIYX.mjs.map +0 -1
  105. package/dist/chunk-KUO2BVFY.mjs +0 -90
  106. package/dist/chunk-ML2JX43J.mjs +0 -248
  107. package/dist/chunk-ML2JX43J.mjs.map +0 -1
  108. package/dist/chunk-WUMV524J.mjs +0 -379
  109. package/dist/chunk-WUMV524J.mjs.map +0 -1
  110. package/dist/chunk-XZ6ZMXXU.mjs +0 -39
  111. /package/dist/{chunk-BJTO5JO5.mjs.map → chunk-3IIFBJCD.mjs.map} +0 -0
@@ -1,645 +0,0 @@
1
- import {
2
- nms,
3
- yoloPostprocess
4
- } from "./chunk-KUO2BVFY.mjs";
5
- import {
6
- MLPACKAGE_FILES,
7
- OBJECT_DETECTION_MODELS
8
- } from "./chunk-BP7H4NFS.mjs";
9
- import {
10
- letterbox
11
- } from "./chunk-22BHCDT5.mjs";
12
- import {
13
- resolveEngine
14
- } from "./chunk-6DJZZR64.mjs";
15
-
16
- // src/catalogs/segmentation-models.ts
17
- import { hfModelUrl, COCO_80_LABELS } from "@camstack/types";
18
- var HF_REPO = "camstack/camstack-models";
19
- var SEGMENTATION_MODELS = [
20
- // ── YOLO11-seg ───────────────────────────────────────────────
21
- {
22
- id: "yolo11n-seg",
23
- name: "YOLO11 Nano Segmentation",
24
- description: "YOLO11 Nano \u2014 fastest, smallest YOLO11 instance segmentation model",
25
- inputSize: { width: 640, height: 640 },
26
- labels: COCO_80_LABELS,
27
- formats: {
28
- onnx: {
29
- url: hfModelUrl(HF_REPO, "segmentation/yolo11-seg/onnx/camstack-yolo11n-seg.onnx"),
30
- sizeMB: 11
31
- },
32
- coreml: {
33
- url: hfModelUrl(HF_REPO, "segmentation/yolo11-seg/coreml/camstack-yolo11n-seg.mlpackage"),
34
- sizeMB: 6,
35
- isDirectory: true,
36
- files: MLPACKAGE_FILES,
37
- runtimes: ["python"]
38
- },
39
- openvino: {
40
- url: hfModelUrl(HF_REPO, "segmentation/yolo11-seg/openvino/camstack-yolo11n-seg.xml"),
41
- sizeMB: 6,
42
- runtimes: ["python"]
43
- }
44
- }
45
- },
46
- {
47
- id: "yolo11s-seg",
48
- name: "YOLO11 Small Segmentation",
49
- description: "YOLO11 Small \u2014 balanced speed and accuracy for instance segmentation",
50
- inputSize: { width: 640, height: 640 },
51
- labels: COCO_80_LABELS,
52
- formats: {
53
- onnx: {
54
- url: hfModelUrl(HF_REPO, "segmentation/yolo11-seg/onnx/camstack-yolo11s-seg.onnx"),
55
- sizeMB: 39
56
- },
57
- coreml: {
58
- url: hfModelUrl(HF_REPO, "segmentation/yolo11-seg/coreml/camstack-yolo11s-seg.mlpackage"),
59
- sizeMB: 20,
60
- isDirectory: true,
61
- files: MLPACKAGE_FILES,
62
- runtimes: ["python"]
63
- },
64
- openvino: {
65
- url: hfModelUrl(HF_REPO, "segmentation/yolo11-seg/openvino/camstack-yolo11s-seg.xml"),
66
- sizeMB: 20,
67
- runtimes: ["python"]
68
- }
69
- }
70
- },
71
- {
72
- id: "yolo11m-seg",
73
- name: "YOLO11 Medium Segmentation",
74
- description: "YOLO11 Medium \u2014 higher accuracy instance segmentation",
75
- inputSize: { width: 640, height: 640 },
76
- labels: COCO_80_LABELS,
77
- formats: {
78
- onnx: {
79
- url: hfModelUrl(HF_REPO, "segmentation/yolo11-seg/onnx/camstack-yolo11m-seg.onnx"),
80
- sizeMB: 86
81
- },
82
- coreml: {
83
- url: hfModelUrl(HF_REPO, "segmentation/yolo11-seg/coreml/camstack-yolo11m-seg.mlpackage"),
84
- sizeMB: 43,
85
- isDirectory: true,
86
- files: MLPACKAGE_FILES,
87
- runtimes: ["python"]
88
- },
89
- openvino: {
90
- url: hfModelUrl(HF_REPO, "segmentation/yolo11-seg/openvino/camstack-yolo11m-seg.xml"),
91
- sizeMB: 43,
92
- runtimes: ["python"]
93
- }
94
- }
95
- },
96
- // ── YOLOv8-seg — CoreML supported ─────────────────────────────
97
- {
98
- id: "yolov8n-seg",
99
- name: "YOLOv8 Nano Segmentation",
100
- description: "YOLOv8 Nano \u2014 fastest, smallest YOLOv8 instance segmentation model",
101
- inputSize: { width: 640, height: 640 },
102
- labels: COCO_80_LABELS,
103
- formats: {
104
- onnx: {
105
- url: hfModelUrl(HF_REPO, "segmentation/yolov8-seg/onnx/camstack-yolov8n-seg.onnx"),
106
- sizeMB: 13
107
- },
108
- coreml: {
109
- url: hfModelUrl(HF_REPO, "segmentation/yolov8-seg/coreml/camstack-yolov8n-seg.mlpackage"),
110
- sizeMB: 7,
111
- isDirectory: true,
112
- files: MLPACKAGE_FILES,
113
- runtimes: ["python"]
114
- },
115
- openvino: {
116
- url: hfModelUrl(HF_REPO, "segmentation/yolov8-seg/openvino/camstack-yolov8n-seg.xml"),
117
- sizeMB: 7,
118
- runtimes: ["python"]
119
- }
120
- }
121
- },
122
- {
123
- id: "yolov8s-seg",
124
- name: "YOLOv8 Small Segmentation",
125
- description: "YOLOv8 Small \u2014 balanced speed and accuracy for instance segmentation",
126
- inputSize: { width: 640, height: 640 },
127
- labels: COCO_80_LABELS,
128
- formats: {
129
- onnx: {
130
- url: hfModelUrl(HF_REPO, "segmentation/yolov8-seg/onnx/camstack-yolov8s-seg.onnx"),
131
- sizeMB: 45
132
- },
133
- coreml: {
134
- url: hfModelUrl(HF_REPO, "segmentation/yolov8-seg/coreml/camstack-yolov8s-seg.mlpackage"),
135
- sizeMB: 23,
136
- isDirectory: true,
137
- files: MLPACKAGE_FILES,
138
- runtimes: ["python"]
139
- },
140
- openvino: {
141
- url: hfModelUrl(HF_REPO, "segmentation/yolov8-seg/openvino/camstack-yolov8s-seg.xml"),
142
- sizeMB: 23,
143
- runtimes: ["python"]
144
- }
145
- }
146
- },
147
- {
148
- id: "yolov8m-seg",
149
- name: "YOLOv8 Medium Segmentation",
150
- description: "YOLOv8 Medium \u2014 higher accuracy instance segmentation",
151
- inputSize: { width: 640, height: 640 },
152
- labels: COCO_80_LABELS,
153
- formats: {
154
- onnx: {
155
- url: hfModelUrl(HF_REPO, "segmentation/yolov8-seg/onnx/camstack-yolov8m-seg.onnx"),
156
- sizeMB: 104
157
- },
158
- coreml: {
159
- url: hfModelUrl(HF_REPO, "segmentation/yolov8-seg/coreml/camstack-yolov8m-seg.mlpackage"),
160
- sizeMB: 52,
161
- isDirectory: true,
162
- files: MLPACKAGE_FILES,
163
- runtimes: ["python"]
164
- },
165
- openvino: {
166
- url: hfModelUrl(HF_REPO, "segmentation/yolov8-seg/openvino/camstack-yolov8m-seg.xml"),
167
- sizeMB: 53,
168
- runtimes: ["python"]
169
- }
170
- }
171
- }
172
- ];
173
-
174
- // src/addons/object-detection/index.ts
175
- import { COCO_TO_MACRO, MACRO_LABELS, COCO_80_LABELS as COCO_80_LABELS2 } from "@camstack/types";
176
-
177
- // src/shared/postprocess/yolo-seg.ts
178
- function sigmoid(x) {
179
- return 1 / (1 + Math.exp(-x));
180
- }
181
- function computeRawMask(coeffs, protos, numMaskCoeffs, maskH, maskW) {
182
- const maskSize = maskH * maskW;
183
- const rawMask = new Float32Array(maskSize);
184
- for (let px = 0; px < maskSize; px++) {
185
- let val = 0;
186
- for (let k = 0; k < numMaskCoeffs; k++) {
187
- val += (coeffs[k] ?? 0) * (protos[k * maskSize + px] ?? 0);
188
- }
189
- rawMask[px] = sigmoid(val);
190
- }
191
- return rawMask;
192
- }
193
- function cropAndThresholdMask(rawMask, maskH, maskW, bbox, maskThreshold, maskScale) {
194
- const cropX1 = Math.max(0, Math.floor(bbox.x * maskScale));
195
- const cropY1 = Math.max(0, Math.floor(bbox.y * maskScale));
196
- const cropX2 = Math.min(maskW, Math.ceil((bbox.x + bbox.w) * maskScale));
197
- const cropY2 = Math.min(maskH, Math.ceil((bbox.y + bbox.h) * maskScale));
198
- const cropW = Math.max(1, cropX2 - cropX1);
199
- const cropH = Math.max(1, cropY2 - cropY1);
200
- const data = new Uint8Array(cropW * cropH);
201
- for (let row = 0; row < cropH; row++) {
202
- const srcRow = cropY1 + row;
203
- for (let col = 0; col < cropW; col++) {
204
- const srcCol = cropX1 + col;
205
- const srcIdx = srcRow * maskW + srcCol;
206
- data[row * cropW + col] = (rawMask[srcIdx] ?? 0) > maskThreshold ? 255 : 0;
207
- }
208
- }
209
- return { data, width: cropW, height: cropH };
210
- }
211
- function yoloSegPostprocess(segOutput, options) {
212
- const {
213
- detectionOutput,
214
- protoOutput,
215
- numClasses,
216
- numBoxes,
217
- numMaskCoeffs,
218
- maskHeight,
219
- maskWidth
220
- } = segOutput;
221
- const {
222
- confidence,
223
- iouThreshold,
224
- labels,
225
- scale,
226
- padX,
227
- padY,
228
- originalWidth,
229
- originalHeight,
230
- maskThreshold = 0.5
231
- } = options;
232
- const yoloInputSize = 640;
233
- const maskScale = maskHeight / yoloInputSize;
234
- const candidates = [];
235
- for (let i = 0; i < numBoxes; i++) {
236
- const cx = detectionOutput[0 * numBoxes + i] ?? 0;
237
- const cy = detectionOutput[1 * numBoxes + i] ?? 0;
238
- const w = detectionOutput[2 * numBoxes + i] ?? 0;
239
- const h = detectionOutput[3 * numBoxes + i] ?? 0;
240
- let bestScore = -Infinity;
241
- let bestClass = 0;
242
- for (let j = 0; j < numClasses; j++) {
243
- const score = detectionOutput[(4 + j) * numBoxes + i] ?? 0;
244
- if (score > bestScore) {
245
- bestScore = score;
246
- bestClass = j;
247
- }
248
- }
249
- if (bestScore < confidence) continue;
250
- const bbox = {
251
- x: cx - w / 2,
252
- y: cy - h / 2,
253
- w,
254
- h
255
- };
256
- const coeffs = new Float32Array(numMaskCoeffs);
257
- for (let k = 0; k < numMaskCoeffs; k++) {
258
- coeffs[k] = detectionOutput[(4 + numClasses + k) * numBoxes + i] ?? 0;
259
- }
260
- candidates.push({ bbox, score: bestScore, classIdx: bestClass, coeffs });
261
- }
262
- if (candidates.length === 0) return [];
263
- const keptIndices = nms(candidates, iouThreshold);
264
- return keptIndices.map((idx) => {
265
- const { bbox, score, classIdx, coeffs } = candidates[idx];
266
- const label = labels[classIdx] ?? String(classIdx);
267
- const x = Math.max(0, Math.min(originalWidth, (bbox.x - padX) / scale));
268
- const y = Math.max(0, Math.min(originalHeight, (bbox.y - padY) / scale));
269
- const x2 = Math.max(0, Math.min(originalWidth, (bbox.x + bbox.w - padX) / scale));
270
- const y2 = Math.max(0, Math.min(originalHeight, (bbox.y + bbox.h - padY) / scale));
271
- const finalBbox = { x, y, w: x2 - x, h: y2 - y };
272
- const rawMask = computeRawMask(coeffs, protoOutput, numMaskCoeffs, maskHeight, maskWidth);
273
- const { data: maskData, width: mW, height: mH } = cropAndThresholdMask(
274
- rawMask,
275
- maskHeight,
276
- maskWidth,
277
- bbox,
278
- maskThreshold,
279
- maskScale
280
- );
281
- return {
282
- class: label,
283
- originalClass: label,
284
- score,
285
- bbox: finalBbox,
286
- mask: maskData,
287
- maskWidth: mW,
288
- maskHeight: mH
289
- };
290
- });
291
- }
292
-
293
- // src/addons/object-detection/index.ts
294
- function isSegModel(modelId) {
295
- return modelId.includes("-seg");
296
- }
297
- var ALL_DETECTION_MODELS = [
298
- ...OBJECT_DETECTION_MODELS,
299
- ...SEGMENTATION_MODELS
300
- ];
301
- function applyClassMap(detections, classMap) {
302
- return detections.filter((d) => classMap.mapping[d.class] !== void 0).map((d) => ({
303
- ...d,
304
- originalClass: d.class,
305
- class: classMap.mapping[d.class]
306
- }));
307
- }
308
- var RAM_ESTIMATES = {
309
- "yolov8n": 80,
310
- "yolov8s": 150,
311
- "yolov8s-relu": 150,
312
- "yolov8m": 300,
313
- "yolov8l": 500,
314
- "yolov8x": 800,
315
- "yolov9t": 60,
316
- "yolov9s": 120,
317
- "yolov9c": 300,
318
- "yolo11n": 70,
319
- "yolo11s": 130,
320
- "yolo11m": 280,
321
- "yolo11l": 450,
322
- "yolo11x": 750,
323
- "yolo11n-seg": 84,
324
- "yolo11s-seg": 156,
325
- "yolo11m-seg": 336,
326
- "yolov8n-seg": 96,
327
- "yolov8s-seg": 180,
328
- "yolov8m-seg": 360
329
- };
330
- var ACCURACY_SCORES = {
331
- "yolov8n": 55,
332
- "yolov8s": 70,
333
- "yolov8s-relu": 68,
334
- "yolov8m": 82,
335
- "yolov8l": 88,
336
- "yolov8x": 92,
337
- "yolov9t": 58,
338
- "yolov9s": 73,
339
- "yolov9c": 86,
340
- "yolo11n": 62,
341
- "yolo11s": 78,
342
- "yolo11m": 88,
343
- "yolo11l": 93,
344
- "yolo11x": 97,
345
- "yolo11n-seg": 62,
346
- "yolo11s-seg": 78,
347
- "yolo11m-seg": 88,
348
- "yolov8n-seg": 55,
349
- "yolov8s-seg": 70,
350
- "yolov8m-seg": 82
351
- };
352
- var ObjectDetectionAddon = class {
353
- id = "object-detection";
354
- slot = "detector";
355
- inputClasses = null;
356
- outputClasses = ["person", "vehicle", "animal"];
357
- slotPriority = 0;
358
- manifest = {
359
- id: "object-detection",
360
- name: "Object Detection",
361
- version: "0.1.0",
362
- description: "YOLO-based object detection \u2014 detects persons, vehicles, and animals",
363
- slot: "detector",
364
- inputClasses: void 0,
365
- outputClasses: ["person", "vehicle", "animal"],
366
- supportsCustomModels: true,
367
- mayRequirePython: false,
368
- defaultConfig: {
369
- modelId: "yolo11n",
370
- runtime: "node",
371
- backend: "cpu",
372
- confidence: 0.5,
373
- iouThreshold: 0.45,
374
- classMapMode: "macro"
375
- }
376
- };
377
- engine = null;
378
- modelEntry;
379
- confidence = 0.5;
380
- iouThreshold = 0.45;
381
- classMapMode = "macro";
382
- resolvedConfig = null;
383
- ctx = null;
384
- getModelRequirements() {
385
- return ALL_DETECTION_MODELS.map((m) => ({
386
- modelId: m.id,
387
- name: m.name,
388
- minRAM_MB: RAM_ESTIMATES[m.id] ?? 100,
389
- accuracyScore: ACCURACY_SCORES[m.id] ?? 60,
390
- formats: Object.keys(m.formats)
391
- }));
392
- }
393
- configure(config) {
394
- this.resolvedConfig = config;
395
- }
396
- async initialize(ctx) {
397
- this.ctx = ctx;
398
- const cfg = ctx.addonConfig;
399
- const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "yolo11n";
400
- this.confidence = cfg["confidence"] ?? 0.5;
401
- this.iouThreshold = cfg["iouThreshold"] ?? 0.45;
402
- this.classMapMode = cfg["classMapMode"] ?? "macro";
403
- const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId);
404
- if (!entry) {
405
- throw new Error(`ObjectDetectionAddon: unknown modelId "${modelId}"`);
406
- }
407
- this.modelEntry = entry;
408
- }
409
- async detect(frame) {
410
- if (!this.engine) await this.ensureEngine();
411
- const start = Date.now();
412
- if ("runJpeg" in this.engine && typeof this.engine.runJpeg === "function") {
413
- const result = await this.engine.runJpeg(frame.data);
414
- const rawDets = result.detections ?? [];
415
- const detections2 = rawDets.map((d) => ({
416
- class: this.classMapMode === "all" ? d.className : COCO_TO_MACRO.mapping[d.className] ?? d.className,
417
- originalClass: d.className,
418
- score: d.score,
419
- bbox: {
420
- x: d.bbox[0] * frame.width,
421
- y: d.bbox[1] * frame.height,
422
- w: (d.bbox[2] - d.bbox[0]) * frame.width,
423
- h: (d.bbox[3] - d.bbox[1]) * frame.height
424
- }
425
- })).filter((d) => this.classMapMode === "all" || COCO_TO_MACRO.mapping[d.originalClass] !== void 0);
426
- return {
427
- detections: detections2,
428
- inferenceMs: result.inferenceMs ?? Date.now() - start,
429
- modelId: this.modelEntry.id
430
- };
431
- }
432
- const { width: inputW, height: inputH } = this.modelEntry.inputSize;
433
- const targetSize = Math.max(inputW, inputH);
434
- const lb = await letterbox(frame.data, targetSize);
435
- const numClasses = this.modelEntry.labels.length;
436
- const labels = this.modelEntry.labels.map((l) => l.id);
437
- const postprocessOpts = {
438
- confidence: this.confidence,
439
- iouThreshold: this.iouThreshold,
440
- labels,
441
- scale: lb.scale,
442
- padX: lb.padX,
443
- padY: lb.padY,
444
- originalWidth: lb.originalWidth,
445
- originalHeight: lb.originalHeight
446
- };
447
- let rawDetections;
448
- if (isSegModel(this.modelEntry.id)) {
449
- const outputs = await this.engine.runMultiOutput(lb.data, [1, 3, targetSize, targetSize]);
450
- const outputNames = Object.keys(outputs);
451
- if (outputNames.length < 2) {
452
- throw new Error(
453
- `ObjectDetectionAddon: seg model "${this.modelEntry.id}" returned ${outputNames.length} output(s); expected 2`
454
- );
455
- }
456
- const detectionOutput = outputs[outputNames[0]];
457
- const protoOutput = outputs[outputNames[1]];
458
- const numMaskCoeffs = 32;
459
- const numBoxes = detectionOutput.length / (4 + numClasses + numMaskCoeffs);
460
- const maskHeight = 160;
461
- const maskWidth = 160;
462
- rawDetections = yoloSegPostprocess(
463
- {
464
- detectionOutput,
465
- protoOutput,
466
- numClasses,
467
- numBoxes,
468
- numMaskCoeffs,
469
- maskHeight,
470
- maskWidth
471
- },
472
- postprocessOpts
473
- );
474
- } else {
475
- const output = await this.engine.run(lb.data, [1, 3, targetSize, targetSize]);
476
- const numBoxes = output.length / (4 + numClasses);
477
- rawDetections = yoloPostprocess(output, numClasses, numBoxes, postprocessOpts);
478
- }
479
- const detections = this.classMapMode === "all" ? rawDetections : applyClassMap(rawDetections, COCO_TO_MACRO);
480
- return {
481
- detections,
482
- inferenceMs: Date.now() - start,
483
- modelId: this.modelEntry.id
484
- };
485
- }
486
- async ensureEngine() {
487
- const config = this.resolvedConfig;
488
- const modelId = config?.modelId ?? this.modelEntry.id;
489
- const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
490
- const backend = config?.backend ?? "cpu";
491
- const format = config?.format ?? "onnx";
492
- const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
493
- this.modelEntry = entry;
494
- const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
495
- if (this.ctx.models) {
496
- await this.ctx.models.ensure(modelId, format);
497
- }
498
- let pythonPath;
499
- if (config?.runtime === "python") {
500
- for (const cmd of ["python3", "python"]) {
501
- try {
502
- const { execSync } = await import("child_process");
503
- execSync(`${cmd} --version`, { timeout: 3e3, stdio: "ignore" });
504
- pythonPath = cmd;
505
- break;
506
- } catch {
507
- }
508
- }
509
- }
510
- const resolved = await resolveEngine({
511
- runtime,
512
- backend,
513
- modelEntry: entry,
514
- modelsDir,
515
- pythonPath,
516
- models: this.ctx.models
517
- });
518
- this.engine = resolved.engine;
519
- }
520
- async shutdown() {
521
- await this.engine?.dispose();
522
- }
523
- getConfigSchema() {
524
- return {
525
- sections: [
526
- {
527
- id: "model",
528
- title: "Model",
529
- columns: 1,
530
- fields: [
531
- {
532
- key: "modelId",
533
- label: "Model",
534
- type: "model-selector",
535
- catalog: [...ALL_DETECTION_MODELS],
536
- allowCustom: true,
537
- allowConversion: true,
538
- acceptFormats: ["onnx", "coreml", "openvino", "tflite"],
539
- requiredMetadata: ["inputSize", "labels", "outputFormat"],
540
- outputFormatHint: "yolo"
541
- }
542
- ]
543
- },
544
- {
545
- id: "runtime",
546
- title: "Runtime",
547
- columns: 2,
548
- fields: [
549
- {
550
- key: "runtime",
551
- label: "Runtime",
552
- type: "select",
553
- options: [
554
- { value: "auto", label: "Auto" },
555
- { value: "onnx", label: "ONNX Runtime" },
556
- { value: "coreml", label: "CoreML (Apple)" },
557
- { value: "openvino", label: "OpenVINO (Intel)" }
558
- ]
559
- },
560
- {
561
- key: "backend",
562
- label: "Backend",
563
- type: "select",
564
- showWhen: { field: "runtime", equals: "onnx" },
565
- options: [
566
- { value: "auto", label: "Auto" },
567
- { value: "cpu", label: "CPU" },
568
- { value: "coreml", label: "CoreML" },
569
- { value: "cuda", label: "CUDA (NVIDIA)" },
570
- { value: "tensorrt", label: "TensorRT (NVIDIA)" }
571
- ]
572
- }
573
- ]
574
- },
575
- {
576
- id: "thresholds",
577
- title: "Detection Thresholds",
578
- columns: 2,
579
- fields: [
580
- {
581
- key: "confidence",
582
- label: "Confidence Threshold",
583
- type: "slider",
584
- min: 0.1,
585
- max: 1,
586
- step: 0.05,
587
- default: 0.5
588
- },
589
- {
590
- key: "iouThreshold",
591
- label: "IoU Threshold (NMS)",
592
- type: "slider",
593
- min: 0.1,
594
- max: 1,
595
- step: 0.05,
596
- default: 0.45
597
- }
598
- ]
599
- },
600
- {
601
- id: "classmap",
602
- title: "Class Mapping",
603
- columns: 1,
604
- fields: [
605
- {
606
- key: "classMapMode",
607
- label: "Output classes",
608
- type: "select",
609
- options: [
610
- { value: "macro", label: "Macro (person / vehicle / animal)" },
611
- { value: "all", label: "All COCO classes (80)" }
612
- ]
613
- }
614
- ]
615
- }
616
- ]
617
- };
618
- }
619
- getClassMap() {
620
- return COCO_TO_MACRO;
621
- }
622
- getModelCatalog() {
623
- return [...ALL_DETECTION_MODELS];
624
- }
625
- getAvailableModels() {
626
- return [];
627
- }
628
- getActiveLabels() {
629
- return this.classMapMode === "all" ? COCO_80_LABELS2 : MACRO_LABELS;
630
- }
631
- async probe() {
632
- return {
633
- available: true,
634
- runtime: this.engine?.runtime ?? "onnx",
635
- device: this.engine?.device ?? "cpu",
636
- capabilities: ["fp32"]
637
- };
638
- }
639
- };
640
-
641
- export {
642
- SEGMENTATION_MODELS,
643
- ObjectDetectionAddon
644
- };
645
- //# sourceMappingURL=chunk-G32RCIUI.mjs.map