@camstack/addon-vision 0.1.2 → 0.1.4

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 (110) hide show
  1. package/dist/addons/animal-classifier/index.js +999 -822
  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 -378
  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 -825
  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 -825
  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 -934
  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 -807
  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 -1082
  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 -868
  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 -505
  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 -790
  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 -410
  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-2IOKI4ES.mjs.map → chunk-PIFS7AIT.mjs.map} +1 -1
  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 -3924
  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 +3 -2
  83. package/dist/chunk-22BHCDT5.mjs +0 -101
  84. package/dist/chunk-2IOKI4ES.mjs +0 -335
  85. package/dist/chunk-7DYHXUPZ.mjs +0 -36
  86. package/dist/chunk-BJTO5JO5.mjs +0 -11
  87. package/dist/chunk-BP7H4NFS.mjs +0 -412
  88. package/dist/chunk-BR2FPGOX.mjs +0 -98
  89. package/dist/chunk-D6WEHN33.mjs +0 -276
  90. package/dist/chunk-D6WEHN33.mjs.map +0 -1
  91. package/dist/chunk-DRYFGARD.mjs +0 -289
  92. package/dist/chunk-DRYFGARD.mjs.map +0 -1
  93. package/dist/chunk-DUN6XU3N.mjs +0 -72
  94. package/dist/chunk-ESLHNWWE.mjs +0 -387
  95. package/dist/chunk-ESLHNWWE.mjs.map +0 -1
  96. package/dist/chunk-JUQEW6ON.mjs +0 -256
  97. package/dist/chunk-JUQEW6ON.mjs.map +0 -1
  98. package/dist/chunk-KUO2BVFY.mjs +0 -90
  99. package/dist/chunk-R5J3WAUI.mjs +0 -645
  100. package/dist/chunk-R5J3WAUI.mjs.map +0 -1
  101. package/dist/chunk-XZ6ZMXXU.mjs +0 -39
  102. package/dist/chunk-YPU4WTXZ.mjs +0 -269
  103. package/dist/chunk-YPU4WTXZ.mjs.map +0 -1
  104. package/dist/chunk-YUCD2TFH.mjs +0 -242
  105. package/dist/chunk-YUCD2TFH.mjs.map +0 -1
  106. package/dist/chunk-ZTJENCFC.mjs +0 -379
  107. package/dist/chunk-ZTJENCFC.mjs.map +0 -1
  108. package/dist/chunk-ZWYXXCXP.mjs +0 -248
  109. package/dist/chunk-ZWYXXCXP.mjs.map +0 -1
  110. /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-2IOKI4ES.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-R5J3WAUI.mjs.map