@camstack/addon-vision 0.1.7 → 0.1.9

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 (136) hide show
  1. package/dist/addons/animal-classifier/index.d.mts +30 -0
  2. package/dist/addons/animal-classifier/index.d.ts +30 -0
  3. package/dist/addons/animal-classifier/index.js +822 -999
  4. package/dist/addons/animal-classifier/index.js.map +1 -1
  5. package/dist/addons/animal-classifier/index.mjs +7 -242
  6. package/dist/addons/animal-classifier/index.mjs.map +1 -1
  7. package/dist/addons/audio-classification/index.d.mts +36 -0
  8. package/dist/addons/audio-classification/index.d.ts +36 -0
  9. package/dist/addons/audio-classification/index.js +378 -501
  10. package/dist/addons/audio-classification/index.js.map +1 -1
  11. package/dist/addons/audio-classification/index.mjs +4 -224
  12. package/dist/addons/audio-classification/index.mjs.map +1 -1
  13. package/dist/addons/bird-global-classifier/index.d.mts +31 -0
  14. package/dist/addons/bird-global-classifier/index.d.ts +31 -0
  15. package/dist/addons/bird-global-classifier/index.js +825 -1002
  16. package/dist/addons/bird-global-classifier/index.js.map +1 -1
  17. package/dist/addons/bird-global-classifier/index.mjs +7 -248
  18. package/dist/addons/bird-global-classifier/index.mjs.map +1 -1
  19. package/dist/addons/bird-nabirds-classifier/index.d.mts +33 -0
  20. package/dist/addons/bird-nabirds-classifier/index.d.ts +33 -0
  21. package/dist/addons/bird-nabirds-classifier/index.js +825 -1002
  22. package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
  23. package/dist/addons/bird-nabirds-classifier/index.mjs +7 -289
  24. package/dist/addons/bird-nabirds-classifier/index.mjs.map +1 -1
  25. package/dist/addons/face-detection/index.d.mts +29 -0
  26. package/dist/addons/face-detection/index.d.ts +29 -0
  27. package/dist/addons/face-detection/index.js +934 -1196
  28. package/dist/addons/face-detection/index.js.map +1 -1
  29. package/dist/addons/face-detection/index.mjs +7 -227
  30. package/dist/addons/face-detection/index.mjs.map +1 -1
  31. package/dist/addons/face-recognition/index.d.mts +29 -0
  32. package/dist/addons/face-recognition/index.d.ts +29 -0
  33. package/dist/addons/face-recognition/index.js +807 -1003
  34. package/dist/addons/face-recognition/index.js.map +1 -1
  35. package/dist/addons/face-recognition/index.mjs +6 -197
  36. package/dist/addons/face-recognition/index.mjs.map +1 -1
  37. package/dist/addons/motion-detection/index.d.mts +28 -0
  38. package/dist/addons/motion-detection/index.d.ts +28 -0
  39. package/dist/addons/motion-detection/index.js +111 -214
  40. package/dist/addons/motion-detection/index.js.map +1 -1
  41. package/dist/addons/motion-detection/index.mjs +9 -12
  42. package/dist/addons/motion-detection/index.mjs.map +1 -1
  43. package/dist/addons/object-detection/index.d.mts +31 -0
  44. package/dist/addons/object-detection/index.d.ts +31 -0
  45. package/dist/addons/object-detection/index.js +1082 -1287
  46. package/dist/addons/object-detection/index.js.map +1 -1
  47. package/dist/addons/object-detection/index.mjs +7 -373
  48. package/dist/addons/object-detection/index.mjs.map +1 -1
  49. package/dist/addons/plate-detection/index.d.mts +30 -0
  50. package/dist/addons/plate-detection/index.d.ts +30 -0
  51. package/dist/addons/plate-detection/index.js +868 -1075
  52. package/dist/addons/plate-detection/index.js.map +1 -1
  53. package/dist/addons/plate-detection/index.mjs +7 -230
  54. package/dist/addons/plate-detection/index.mjs.map +1 -1
  55. package/dist/addons/plate-recognition/index.d.mts +31 -0
  56. package/dist/addons/plate-recognition/index.d.ts +31 -0
  57. package/dist/addons/plate-recognition/index.js +505 -684
  58. package/dist/addons/plate-recognition/index.js.map +1 -1
  59. package/dist/addons/plate-recognition/index.mjs +5 -244
  60. package/dist/addons/plate-recognition/index.mjs.map +1 -1
  61. package/dist/addons/segmentation-refiner/index.d.mts +30 -0
  62. package/dist/addons/segmentation-refiner/index.d.ts +30 -0
  63. package/dist/addons/segmentation-refiner/index.js +790 -967
  64. package/dist/addons/segmentation-refiner/index.js.map +1 -1
  65. package/dist/addons/segmentation-refiner/index.mjs +17 -21
  66. package/dist/addons/segmentation-refiner/index.mjs.map +1 -1
  67. package/dist/addons/vehicle-classifier/index.d.mts +31 -0
  68. package/dist/addons/vehicle-classifier/index.d.ts +31 -0
  69. package/dist/addons/vehicle-classifier/index.js +410 -581
  70. package/dist/addons/vehicle-classifier/index.js.map +1 -1
  71. package/dist/addons/vehicle-classifier/index.mjs +16 -20
  72. package/dist/addons/vehicle-classifier/index.mjs.map +1 -1
  73. package/dist/chunk-22BHCDT5.mjs +101 -0
  74. package/dist/{chunk-WG66JYYW.mjs.map → chunk-22BHCDT5.mjs.map} +1 -1
  75. package/dist/chunk-2IOKI4ES.mjs +335 -0
  76. package/dist/{chunk-PIFS7AIT.mjs.map → chunk-2IOKI4ES.mjs.map} +1 -1
  77. package/dist/chunk-7DYHXUPZ.mjs +36 -0
  78. package/dist/{chunk-BS4DKYGN.mjs.map → chunk-7DYHXUPZ.mjs.map} +1 -1
  79. package/dist/chunk-BJTO5JO5.mjs +11 -0
  80. package/dist/chunk-BP7H4NFS.mjs +412 -0
  81. package/dist/{chunk-MGT6RUVX.mjs.map → chunk-BP7H4NFS.mjs.map} +1 -1
  82. package/dist/chunk-BR2FPGOX.mjs +98 -0
  83. package/dist/{chunk-YYDM6V2F.mjs.map → chunk-BR2FPGOX.mjs.map} +1 -1
  84. package/dist/chunk-D6WEHN33.mjs +276 -0
  85. package/dist/chunk-D6WEHN33.mjs.map +1 -0
  86. package/dist/chunk-DRYFGARD.mjs +289 -0
  87. package/dist/chunk-DRYFGARD.mjs.map +1 -0
  88. package/dist/chunk-DUN6XU3N.mjs +72 -0
  89. package/dist/{chunk-XD7WGXHZ.mjs.map → chunk-DUN6XU3N.mjs.map} +1 -1
  90. package/dist/chunk-ESLHNWWE.mjs +387 -0
  91. package/dist/chunk-ESLHNWWE.mjs.map +1 -0
  92. package/dist/chunk-JUQEW6ON.mjs +256 -0
  93. package/dist/chunk-JUQEW6ON.mjs.map +1 -0
  94. package/dist/chunk-KUO2BVFY.mjs +90 -0
  95. package/dist/{chunk-DE7I3VHO.mjs.map → chunk-KUO2BVFY.mjs.map} +1 -1
  96. package/dist/chunk-R5J3WAUI.mjs +645 -0
  97. package/dist/chunk-R5J3WAUI.mjs.map +1 -0
  98. package/dist/chunk-XZ6ZMXXU.mjs +39 -0
  99. package/dist/{chunk-K36R6HWY.mjs.map → chunk-XZ6ZMXXU.mjs.map} +1 -1
  100. package/dist/chunk-YPU4WTXZ.mjs +269 -0
  101. package/dist/chunk-YPU4WTXZ.mjs.map +1 -0
  102. package/dist/chunk-YUCD2TFH.mjs +242 -0
  103. package/dist/chunk-YUCD2TFH.mjs.map +1 -0
  104. package/dist/chunk-ZTJENCFC.mjs +379 -0
  105. package/dist/chunk-ZTJENCFC.mjs.map +1 -0
  106. package/dist/chunk-ZWYXXCXP.mjs +248 -0
  107. package/dist/chunk-ZWYXXCXP.mjs.map +1 -0
  108. package/dist/index.d.mts +183 -0
  109. package/dist/index.d.ts +183 -0
  110. package/dist/index.js +3930 -4449
  111. package/dist/index.js.map +1 -1
  112. package/dist/index.mjs +250 -2698
  113. package/dist/index.mjs.map +1 -1
  114. package/package.json +5 -5
  115. package/dist/chunk-2YMA6QOV.mjs +0 -193
  116. package/dist/chunk-2YMA6QOV.mjs.map +0 -1
  117. package/dist/chunk-3IIFBJCD.mjs +0 -45
  118. package/dist/chunk-BS4DKYGN.mjs +0 -48
  119. package/dist/chunk-DE7I3VHO.mjs +0 -106
  120. package/dist/chunk-F6D2OZ36.mjs +0 -89
  121. package/dist/chunk-F6D2OZ36.mjs.map +0 -1
  122. package/dist/chunk-GAOIFQDX.mjs +0 -59
  123. package/dist/chunk-GAOIFQDX.mjs.map +0 -1
  124. package/dist/chunk-HUIX2XVR.mjs +0 -159
  125. package/dist/chunk-HUIX2XVR.mjs.map +0 -1
  126. package/dist/chunk-K36R6HWY.mjs +0 -51
  127. package/dist/chunk-MBTAI3WE.mjs +0 -78
  128. package/dist/chunk-MBTAI3WE.mjs.map +0 -1
  129. package/dist/chunk-MGT6RUVX.mjs +0 -423
  130. package/dist/chunk-PIFS7AIT.mjs +0 -446
  131. package/dist/chunk-WG66JYYW.mjs +0 -116
  132. package/dist/chunk-XD7WGXHZ.mjs +0 -82
  133. package/dist/chunk-YYDM6V2F.mjs +0 -113
  134. package/dist/chunk-ZK7P3TZN.mjs +0 -286
  135. package/dist/chunk-ZK7P3TZN.mjs.map +0 -1
  136. /package/dist/{chunk-3IIFBJCD.mjs.map → chunk-BJTO5JO5.mjs.map} +0 -0
@@ -0,0 +1,645 @@
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