@camstack/addon-vision 0.1.2 → 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 (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 +1 -1
  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,11 +1,377 @@
1
1
  import {
2
- ObjectDetectionAddon
3
- } from "../../chunk-R5J3WAUI.mjs";
4
- import "../../chunk-KUO2BVFY.mjs";
5
- import "../../chunk-BP7H4NFS.mjs";
6
- import "../../chunk-22BHCDT5.mjs";
7
- import "../../chunk-2IOKI4ES.mjs";
8
- import "../../chunk-BJTO5JO5.mjs";
2
+ require_segmentation_models,
3
+ require_yolo_seg
4
+ } from "../../chunk-ZK7P3TZN.mjs";
5
+ import {
6
+ require_yolo
7
+ } from "../../chunk-DE7I3VHO.mjs";
8
+ import {
9
+ require_object_detection_models
10
+ } from "../../chunk-MGT6RUVX.mjs";
11
+ import {
12
+ require_image_utils
13
+ } from "../../chunk-WG66JYYW.mjs";
14
+ import {
15
+ require_engine_resolver
16
+ } from "../../chunk-PIFS7AIT.mjs";
17
+ import {
18
+ __toESM
19
+ } from "../../chunk-3IIFBJCD.mjs";
20
+
21
+ // src/addons/object-detection/index.ts
22
+ var import_object_detection_models = __toESM(require_object_detection_models());
23
+ var import_segmentation_models = __toESM(require_segmentation_models());
24
+ var import_image_utils = __toESM(require_image_utils());
25
+ var import_yolo = __toESM(require_yolo());
26
+ var import_yolo_seg = __toESM(require_yolo_seg());
27
+ var import_engine_resolver = __toESM(require_engine_resolver());
28
+ import { COCO_TO_MACRO, MACRO_LABELS, COCO_80_LABELS } from "@camstack/types";
29
+ function isSegModel(modelId) {
30
+ return modelId.includes("-seg");
31
+ }
32
+ var ALL_DETECTION_MODELS = [
33
+ ...import_object_detection_models.OBJECT_DETECTION_MODELS,
34
+ ...import_segmentation_models.SEGMENTATION_MODELS
35
+ ];
36
+ function applyClassMap(detections, classMap) {
37
+ return detections.filter((d) => classMap.mapping[d.class] !== void 0).map((d) => ({
38
+ ...d,
39
+ originalClass: d.class,
40
+ class: classMap.mapping[d.class]
41
+ }));
42
+ }
43
+ var RAM_ESTIMATES = {
44
+ "yolov8n": 80,
45
+ "yolov8s": 150,
46
+ "yolov8s-relu": 150,
47
+ "yolov8m": 300,
48
+ "yolov8l": 500,
49
+ "yolov8x": 800,
50
+ "yolov9t": 60,
51
+ "yolov9s": 120,
52
+ "yolov9c": 300,
53
+ "yolo11n": 70,
54
+ "yolo11s": 130,
55
+ "yolo11m": 280,
56
+ "yolo11l": 450,
57
+ "yolo11x": 750,
58
+ "yolo11n-seg": 84,
59
+ "yolo11s-seg": 156,
60
+ "yolo11m-seg": 336,
61
+ "yolov8n-seg": 96,
62
+ "yolov8s-seg": 180,
63
+ "yolov8m-seg": 360
64
+ };
65
+ var ACCURACY_SCORES = {
66
+ "yolov8n": 55,
67
+ "yolov8s": 70,
68
+ "yolov8s-relu": 68,
69
+ "yolov8m": 82,
70
+ "yolov8l": 88,
71
+ "yolov8x": 92,
72
+ "yolov9t": 58,
73
+ "yolov9s": 73,
74
+ "yolov9c": 86,
75
+ "yolo11n": 62,
76
+ "yolo11s": 78,
77
+ "yolo11m": 88,
78
+ "yolo11l": 93,
79
+ "yolo11x": 97,
80
+ "yolo11n-seg": 62,
81
+ "yolo11s-seg": 78,
82
+ "yolo11m-seg": 88,
83
+ "yolov8n-seg": 55,
84
+ "yolov8s-seg": 70,
85
+ "yolov8m-seg": 82
86
+ };
87
+ var ObjectDetectionAddon = class {
88
+ id = "object-detection";
89
+ slot = "detector";
90
+ inputClasses = null;
91
+ outputClasses = ["person", "vehicle", "animal"];
92
+ slotPriority = 0;
93
+ manifest = {
94
+ id: "object-detection",
95
+ name: "Object Detection",
96
+ version: "0.1.0",
97
+ description: "YOLO-based object detection \u2014 detects persons, vehicles, and animals",
98
+ slot: "detector",
99
+ inputClasses: void 0,
100
+ outputClasses: ["person", "vehicle", "animal"],
101
+ supportsCustomModels: true,
102
+ mayRequirePython: false,
103
+ defaultConfig: {
104
+ modelId: "yolo11n",
105
+ runtime: "node",
106
+ backend: "cpu",
107
+ confidence: 0.5,
108
+ iouThreshold: 0.45,
109
+ classMapMode: "macro"
110
+ }
111
+ };
112
+ engine = null;
113
+ modelEntry;
114
+ confidence = 0.5;
115
+ iouThreshold = 0.45;
116
+ classMapMode = "macro";
117
+ resolvedConfig = null;
118
+ ctx = null;
119
+ getModelRequirements() {
120
+ return ALL_DETECTION_MODELS.map((m) => ({
121
+ modelId: m.id,
122
+ name: m.name,
123
+ minRAM_MB: RAM_ESTIMATES[m.id] ?? 100,
124
+ accuracyScore: ACCURACY_SCORES[m.id] ?? 60,
125
+ formats: Object.keys(m.formats)
126
+ }));
127
+ }
128
+ configure(config) {
129
+ this.resolvedConfig = config;
130
+ }
131
+ async initialize(ctx) {
132
+ this.ctx = ctx;
133
+ const cfg = ctx.addonConfig;
134
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "yolo11n";
135
+ this.confidence = cfg["confidence"] ?? 0.5;
136
+ this.iouThreshold = cfg["iouThreshold"] ?? 0.45;
137
+ this.classMapMode = cfg["classMapMode"] ?? "macro";
138
+ const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId);
139
+ if (!entry) {
140
+ throw new Error(`ObjectDetectionAddon: unknown modelId "${modelId}"`);
141
+ }
142
+ this.modelEntry = entry;
143
+ }
144
+ async detect(frame) {
145
+ if (!this.engine) await this.ensureEngine();
146
+ const start = Date.now();
147
+ if ("runJpeg" in this.engine && typeof this.engine.runJpeg === "function") {
148
+ const result = await this.engine.runJpeg(frame.data);
149
+ const rawDets = result.detections ?? [];
150
+ const detections2 = rawDets.map((d) => ({
151
+ class: this.classMapMode === "all" ? d.className : COCO_TO_MACRO.mapping[d.className] ?? d.className,
152
+ originalClass: d.className,
153
+ score: d.score,
154
+ bbox: {
155
+ x: d.bbox[0] * frame.width,
156
+ y: d.bbox[1] * frame.height,
157
+ w: (d.bbox[2] - d.bbox[0]) * frame.width,
158
+ h: (d.bbox[3] - d.bbox[1]) * frame.height
159
+ }
160
+ })).filter((d) => this.classMapMode === "all" || COCO_TO_MACRO.mapping[d.originalClass] !== void 0);
161
+ return {
162
+ detections: detections2,
163
+ inferenceMs: result.inferenceMs ?? Date.now() - start,
164
+ modelId: this.modelEntry.id
165
+ };
166
+ }
167
+ const { width: inputW, height: inputH } = this.modelEntry.inputSize;
168
+ const targetSize = Math.max(inputW, inputH);
169
+ const lb = await (0, import_image_utils.letterbox)(frame.data, targetSize);
170
+ const numClasses = this.modelEntry.labels.length;
171
+ const labels = this.modelEntry.labels.map((l) => l.id);
172
+ const postprocessOpts = {
173
+ confidence: this.confidence,
174
+ iouThreshold: this.iouThreshold,
175
+ labels,
176
+ scale: lb.scale,
177
+ padX: lb.padX,
178
+ padY: lb.padY,
179
+ originalWidth: lb.originalWidth,
180
+ originalHeight: lb.originalHeight
181
+ };
182
+ let rawDetections;
183
+ if (isSegModel(this.modelEntry.id)) {
184
+ const outputs = await this.engine.runMultiOutput(lb.data, [1, 3, targetSize, targetSize]);
185
+ const outputNames = Object.keys(outputs);
186
+ if (outputNames.length < 2) {
187
+ throw new Error(
188
+ `ObjectDetectionAddon: seg model "${this.modelEntry.id}" returned ${outputNames.length} output(s); expected 2`
189
+ );
190
+ }
191
+ const detectionOutput = outputs[outputNames[0]];
192
+ const protoOutput = outputs[outputNames[1]];
193
+ const numMaskCoeffs = 32;
194
+ const numBoxes = detectionOutput.length / (4 + numClasses + numMaskCoeffs);
195
+ const maskHeight = 160;
196
+ const maskWidth = 160;
197
+ rawDetections = (0, import_yolo_seg.yoloSegPostprocess)(
198
+ {
199
+ detectionOutput,
200
+ protoOutput,
201
+ numClasses,
202
+ numBoxes,
203
+ numMaskCoeffs,
204
+ maskHeight,
205
+ maskWidth
206
+ },
207
+ postprocessOpts
208
+ );
209
+ } else {
210
+ const output = await this.engine.run(lb.data, [1, 3, targetSize, targetSize]);
211
+ const numBoxes = output.length / (4 + numClasses);
212
+ rawDetections = (0, import_yolo.yoloPostprocess)(output, numClasses, numBoxes, postprocessOpts);
213
+ }
214
+ const detections = this.classMapMode === "all" ? rawDetections : applyClassMap(rawDetections, COCO_TO_MACRO);
215
+ return {
216
+ detections,
217
+ inferenceMs: Date.now() - start,
218
+ modelId: this.modelEntry.id
219
+ };
220
+ }
221
+ async ensureEngine() {
222
+ const config = this.resolvedConfig;
223
+ const modelId = config?.modelId ?? this.modelEntry.id;
224
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
225
+ const backend = config?.backend ?? "cpu";
226
+ const format = config?.format ?? "onnx";
227
+ const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
228
+ this.modelEntry = entry;
229
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
230
+ if (this.ctx.models) {
231
+ await this.ctx.models.ensure(modelId, format);
232
+ }
233
+ let pythonPath;
234
+ if (config?.runtime === "python") {
235
+ for (const cmd of ["python3", "python"]) {
236
+ try {
237
+ const { execSync } = await import("child_process");
238
+ execSync(`${cmd} --version`, { timeout: 3e3, stdio: "ignore" });
239
+ pythonPath = cmd;
240
+ break;
241
+ } catch {
242
+ }
243
+ }
244
+ }
245
+ const resolved = await (0, import_engine_resolver.resolveEngine)({
246
+ runtime,
247
+ backend,
248
+ modelEntry: entry,
249
+ modelsDir,
250
+ pythonPath,
251
+ models: this.ctx.models
252
+ });
253
+ this.engine = resolved.engine;
254
+ }
255
+ async shutdown() {
256
+ await this.engine?.dispose();
257
+ }
258
+ getConfigSchema() {
259
+ return {
260
+ sections: [
261
+ {
262
+ id: "model",
263
+ title: "Model",
264
+ columns: 1,
265
+ fields: [
266
+ {
267
+ key: "modelId",
268
+ label: "Model",
269
+ type: "model-selector",
270
+ catalog: [...ALL_DETECTION_MODELS],
271
+ allowCustom: true,
272
+ allowConversion: true,
273
+ acceptFormats: ["onnx", "coreml", "openvino", "tflite"],
274
+ requiredMetadata: ["inputSize", "labels", "outputFormat"],
275
+ outputFormatHint: "yolo"
276
+ }
277
+ ]
278
+ },
279
+ {
280
+ id: "runtime",
281
+ title: "Runtime",
282
+ columns: 2,
283
+ fields: [
284
+ {
285
+ key: "runtime",
286
+ label: "Runtime",
287
+ type: "select",
288
+ options: [
289
+ { value: "auto", label: "Auto" },
290
+ { value: "onnx", label: "ONNX Runtime" },
291
+ { value: "coreml", label: "CoreML (Apple)" },
292
+ { value: "openvino", label: "OpenVINO (Intel)" }
293
+ ]
294
+ },
295
+ {
296
+ key: "backend",
297
+ label: "Backend",
298
+ type: "select",
299
+ showWhen: { field: "runtime", equals: "onnx" },
300
+ options: [
301
+ { value: "auto", label: "Auto" },
302
+ { value: "cpu", label: "CPU" },
303
+ { value: "coreml", label: "CoreML" },
304
+ { value: "cuda", label: "CUDA (NVIDIA)" },
305
+ { value: "tensorrt", label: "TensorRT (NVIDIA)" }
306
+ ]
307
+ }
308
+ ]
309
+ },
310
+ {
311
+ id: "thresholds",
312
+ title: "Detection Thresholds",
313
+ columns: 2,
314
+ fields: [
315
+ {
316
+ key: "confidence",
317
+ label: "Confidence Threshold",
318
+ type: "slider",
319
+ min: 0.1,
320
+ max: 1,
321
+ step: 0.05,
322
+ default: 0.5
323
+ },
324
+ {
325
+ key: "iouThreshold",
326
+ label: "IoU Threshold (NMS)",
327
+ type: "slider",
328
+ min: 0.1,
329
+ max: 1,
330
+ step: 0.05,
331
+ default: 0.45
332
+ }
333
+ ]
334
+ },
335
+ {
336
+ id: "classmap",
337
+ title: "Class Mapping",
338
+ columns: 1,
339
+ fields: [
340
+ {
341
+ key: "classMapMode",
342
+ label: "Output classes",
343
+ type: "select",
344
+ options: [
345
+ { value: "macro", label: "Macro (person / vehicle / animal)" },
346
+ { value: "all", label: "All COCO classes (80)" }
347
+ ]
348
+ }
349
+ ]
350
+ }
351
+ ]
352
+ };
353
+ }
354
+ getClassMap() {
355
+ return COCO_TO_MACRO;
356
+ }
357
+ getModelCatalog() {
358
+ return [...ALL_DETECTION_MODELS];
359
+ }
360
+ getAvailableModels() {
361
+ return [];
362
+ }
363
+ getActiveLabels() {
364
+ return this.classMapMode === "all" ? COCO_80_LABELS : MACRO_LABELS;
365
+ }
366
+ async probe() {
367
+ return {
368
+ available: true,
369
+ runtime: this.engine?.runtime ?? "onnx",
370
+ device: this.engine?.device ?? "cpu",
371
+ capabilities: ["fp32"]
372
+ };
373
+ }
374
+ };
9
375
  export {
10
376
  ObjectDetectionAddon as default
11
377
  };
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../../../src/addons/object-detection/index.ts"],"sourcesContent":["import type {\n IDetectorProvider,\n IDetectionAddon,\n AddonManifest,\n AddonContext,\n FrameInput,\n DetectorOutput,\n SpatialDetection,\n ConfigUISchema,\n ClassMapDefinition,\n ProbeResult,\n ModelCatalogEntry,\n DetectionModel,\n LabelDefinition,\n IInferenceEngine,\n ModelRequirement,\n ResolvedInferenceConfig,\n} from '@camstack/types'\nimport { OBJECT_DETECTION_MODELS } from '../../catalogs/object-detection-models.js'\nimport { SEGMENTATION_MODELS } from '../../catalogs/segmentation-models.js'\nimport { COCO_TO_MACRO, MACRO_LABELS, COCO_80_LABELS } from '@camstack/types'\nimport { letterbox } from '../../shared/image-utils.js'\nimport { yoloPostprocess } from '../../shared/postprocess/yolo.js'\nimport { yoloSegPostprocess } from '../../shared/postprocess/yolo-seg.js'\nimport { resolveEngine } from '../../shared/engine-resolver.js'\n\n/** Returns true when the model id identifies a YOLO segmentation model (e.g. yolov8n-seg, yolo11m-seg) */\nfunction isSegModel(modelId: string): boolean {\n return modelId.includes('-seg')\n}\n\n/** Combined catalog: regular detection models + segmentation models */\nconst ALL_DETECTION_MODELS: readonly ModelCatalogEntry[] = [\n ...OBJECT_DETECTION_MODELS,\n ...SEGMENTATION_MODELS,\n]\n\n/**\n * classMapMode controls how raw COCO labels are mapped after inference:\n *\n * - 'macro' (default): apply COCO_TO_MACRO — only person / vehicle / animal\n * survive, all other classes are dropped.\n * - 'all': keep every raw COCO label (80 classes). originalClass === class.\n */\ntype ClassMapMode = 'macro' | 'all'\n\n/** Map COCO-class detections to macro categories (person/vehicle/animal) */\nfunction applyClassMap(\n detections: SpatialDetection[],\n classMap: ClassMapDefinition,\n): SpatialDetection[] {\n return detections\n .filter((d) => classMap.mapping[d.class] !== undefined)\n .map((d) => ({\n ...d,\n originalClass: d.class,\n class: classMap.mapping[d.class]!,\n }))\n}\n\n/** RAM estimates per model (MB) */\nconst RAM_ESTIMATES: Record<string, number> = {\n 'yolov8n': 80, 'yolov8s': 150, 'yolov8s-relu': 150, 'yolov8m': 300, 'yolov8l': 500, 'yolov8x': 800,\n 'yolov9t': 60, 'yolov9s': 120, 'yolov9c': 300,\n 'yolo11n': 70, 'yolo11s': 130, 'yolo11m': 280, 'yolo11l': 450, 'yolo11x': 750,\n 'yolo11n-seg': 84, 'yolo11s-seg': 156, 'yolo11m-seg': 336,\n 'yolov8n-seg': 96, 'yolov8s-seg': 180, 'yolov8m-seg': 360,\n}\n\n/**\n * Accuracy scores per model (0-100).\n * YOLO11 scores are higher than YOLOv8 equivalents to reflect the\n * ~2 mAP improvement at same parameter count (e.g. YOLO11n 39.5 vs YOLOv8n 37.3).\n * This ensures the resolver prefers YOLO11 when both families are available.\n */\nconst ACCURACY_SCORES: Record<string, number> = {\n 'yolov8n': 55, 'yolov8s': 70, 'yolov8s-relu': 68, 'yolov8m': 82, 'yolov8l': 88, 'yolov8x': 92,\n 'yolov9t': 58, 'yolov9s': 73, 'yolov9c': 86,\n 'yolo11n': 62, 'yolo11s': 78, 'yolo11m': 88, 'yolo11l': 93, 'yolo11x': 97,\n 'yolo11n-seg': 62, 'yolo11s-seg': 78, 'yolo11m-seg': 88,\n 'yolov8n-seg': 55, 'yolov8s-seg': 70, 'yolov8m-seg': 82,\n}\n\nexport default class ObjectDetectionAddon implements IDetectorProvider, IDetectionAddon {\n readonly id = 'object-detection'\n readonly slot = 'detector' as const\n readonly inputClasses: readonly string[] | null = null\n readonly outputClasses = ['person', 'vehicle', 'animal'] as const\n readonly slotPriority = 0\n readonly manifest: AddonManifest = {\n id: 'object-detection',\n name: 'Object Detection',\n version: '0.1.0',\n\n description: 'YOLO-based object detection — detects persons, vehicles, and animals',\n\n slot: 'detector',\n inputClasses: undefined,\n outputClasses: ['person', 'vehicle', 'animal'],\n supportsCustomModels: true,\n mayRequirePython: false,\n defaultConfig: {\n modelId: 'yolo11n',\n runtime: 'node',\n backend: 'cpu',\n confidence: 0.5,\n iouThreshold: 0.45,\n classMapMode: 'macro',\n },\n }\n\n private engine: IInferenceEngine | null = null\n private modelEntry!: ModelCatalogEntry\n private confidence = 0.5\n private iouThreshold = 0.45\n private classMapMode: ClassMapMode = 'macro'\n private resolvedConfig: ResolvedInferenceConfig | null = null\n private ctx: AddonContext | null = null\n\n getModelRequirements(): ModelRequirement[] {\n return ALL_DETECTION_MODELS.map((m) => ({\n modelId: m.id,\n name: m.name,\n minRAM_MB: RAM_ESTIMATES[m.id] ?? 100,\n accuracyScore: ACCURACY_SCORES[m.id] ?? 60,\n formats: Object.keys(m.formats) as readonly string[],\n }))\n }\n\n configure(config: ResolvedInferenceConfig): void {\n this.resolvedConfig = config\n }\n\n async initialize(ctx: AddonContext): Promise<void> {\n this.ctx = ctx\n const cfg = ctx.addonConfig\n const modelId = (cfg['modelId'] as string | undefined) ?? this.resolvedConfig?.modelId ?? 'yolo11n'\n this.confidence = (cfg['confidence'] as number | undefined) ?? 0.5\n this.iouThreshold = (cfg['iouThreshold'] as number | undefined) ?? 0.45\n this.classMapMode = (cfg['classMapMode'] as ClassMapMode | undefined) ?? 'macro'\n\n const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId)\n if (!entry) {\n throw new Error(`ObjectDetectionAddon: unknown modelId \"${modelId}\"`)\n }\n this.modelEntry = entry\n }\n\n async detect(frame: FrameInput): Promise<DetectorOutput> {\n if (!this.engine) await this.ensureEngine()\n const start = Date.now()\n\n // Python engine path — send JPEG directly, Python handles preprocess + inference + postprocess\n if ('runJpeg' in this.engine! && typeof (this.engine as any).runJpeg === 'function') {\n const result = await (this.engine as any).runJpeg(frame.data) as Record<string, unknown>\n const rawDets = (result.detections ?? []) as Array<{ className: string; score: number; bbox: number[] }>\n const detections: SpatialDetection[] = rawDets.map((d) => ({\n class: this.classMapMode === 'all' ? d.className : (COCO_TO_MACRO.mapping[d.className] ?? d.className),\n originalClass: d.className,\n score: d.score,\n bbox: {\n x: d.bbox[0]! * frame.width,\n y: d.bbox[1]! * frame.height,\n w: (d.bbox[2]! - d.bbox[0]!) * frame.width,\n h: (d.bbox[3]! - d.bbox[1]!) * frame.height,\n },\n })).filter((d) => this.classMapMode === 'all' || COCO_TO_MACRO.mapping[d.originalClass!] !== undefined)\n\n return {\n detections,\n inferenceMs: (result.inferenceMs as number) ?? (Date.now() - start),\n modelId: this.modelEntry.id,\n }\n }\n\n // Node.js engine path — letterbox + run tensor + postprocess\n const { width: inputW, height: inputH } = this.modelEntry.inputSize\n const targetSize = Math.max(inputW, inputH)\n\n const lb = await letterbox(frame.data, targetSize)\n\n const numClasses = this.modelEntry.labels.length\n const labels = this.modelEntry.labels.map((l) => l.id)\n const postprocessOpts = {\n confidence: this.confidence,\n iouThreshold: this.iouThreshold,\n labels,\n scale: lb.scale,\n padX: lb.padX,\n padY: lb.padY,\n originalWidth: lb.originalWidth,\n originalHeight: lb.originalHeight,\n }\n\n let rawDetections: SpatialDetection[]\n\n if (isSegModel(this.modelEntry.id)) {\n // YOLO-seg models produce two outputs:\n // output0: [1, 4 + numClasses + 32, numBoxes] (detection + mask coefficients)\n // output1: [1, 32, 160, 160] (prototype masks)\n const outputs = await this.engine!.runMultiOutput(lb.data, [1, 3, targetSize, targetSize])\n const outputNames = Object.keys(outputs)\n\n if (outputNames.length < 2) {\n throw new Error(\n `ObjectDetectionAddon: seg model \"${this.modelEntry.id}\" returned ${outputNames.length} output(s); expected 2`,\n )\n }\n\n // ONNX output order is deterministic; first output is the detection tensor, second is protos\n const detectionOutput = outputs[outputNames[0]!]!\n const protoOutput = outputs[outputNames[1]!]!\n\n // Infer dims from tensor sizes\n const numMaskCoeffs = 32\n const numBoxes = detectionOutput.length / (4 + numClasses + numMaskCoeffs)\n const maskHeight = 160\n const maskWidth = 160\n\n rawDetections = yoloSegPostprocess(\n {\n detectionOutput,\n protoOutput,\n numClasses,\n numBoxes,\n numMaskCoeffs,\n maskHeight,\n maskWidth,\n },\n postprocessOpts,\n )\n } else {\n // Standard YOLO output: [1, 4+numClasses, numBoxes]\n const output = await this.engine!.run(lb.data, [1, 3, targetSize, targetSize])\n const numBoxes = output.length / (4 + numClasses)\n rawDetections = yoloPostprocess(output, numClasses, numBoxes, postprocessOpts)\n }\n\n const detections = this.classMapMode === 'all'\n ? rawDetections\n : applyClassMap(rawDetections, COCO_TO_MACRO)\n\n return {\n detections,\n inferenceMs: Date.now() - start,\n modelId: this.modelEntry.id,\n }\n }\n\n private async ensureEngine(): Promise<void> {\n const config = this.resolvedConfig\n const modelId = config?.modelId ?? this.modelEntry.id\n const runtime = config?.runtime === 'python' ? 'coreml' : (config?.runtime === 'node' ? 'onnx' : 'auto')\n const backend = config?.backend ?? 'cpu'\n const format = config?.format ?? 'onnx'\n\n const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry\n this.modelEntry = entry\n\n const modelsDir = this.ctx!.models?.getModelsDir() ?? this.ctx!.locationPaths.models\n\n // Download model if needed\n if (this.ctx!.models) {\n await this.ctx!.models.ensure(modelId, format as any)\n }\n\n // Discover Python path for Python-based runtimes\n let pythonPath: string | undefined\n if (config?.runtime === 'python') {\n for (const cmd of ['python3', 'python']) {\n try {\n const { execSync } = await import('node:child_process')\n execSync(`${cmd} --version`, { timeout: 3000, stdio: 'ignore' })\n pythonPath = cmd\n break\n } catch { /* not found */ }\n }\n }\n\n const resolved = await resolveEngine({\n runtime: runtime as 'auto',\n backend,\n modelEntry: entry,\n modelsDir,\n pythonPath,\n models: this.ctx!.models,\n })\n this.engine = resolved.engine\n }\n\n async shutdown(): Promise<void> {\n await this.engine?.dispose()\n }\n\n getConfigSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'model',\n title: 'Model',\n columns: 1,\n fields: [\n {\n key: 'modelId',\n label: 'Model',\n type: 'model-selector',\n catalog: [...ALL_DETECTION_MODELS],\n allowCustom: true,\n allowConversion: true,\n acceptFormats: ['onnx', 'coreml', 'openvino', 'tflite'],\n requiredMetadata: ['inputSize', 'labels', 'outputFormat'],\n outputFormatHint: 'yolo',\n },\n ],\n },\n {\n id: 'runtime',\n title: 'Runtime',\n columns: 2,\n fields: [\n {\n key: 'runtime',\n label: 'Runtime',\n type: 'select',\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'onnx', label: 'ONNX Runtime' },\n { value: 'coreml', label: 'CoreML (Apple)' },\n { value: 'openvino', label: 'OpenVINO (Intel)' },\n ],\n },\n {\n key: 'backend',\n label: 'Backend',\n type: 'select',\n showWhen: { field: 'runtime', equals: 'onnx' },\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'cpu', label: 'CPU' },\n { value: 'coreml', label: 'CoreML' },\n { value: 'cuda', label: 'CUDA (NVIDIA)' },\n { value: 'tensorrt', label: 'TensorRT (NVIDIA)' },\n ],\n },\n ],\n },\n {\n id: 'thresholds',\n title: 'Detection Thresholds',\n columns: 2,\n fields: [\n {\n key: 'confidence',\n label: 'Confidence Threshold',\n type: 'slider',\n min: 0.1,\n max: 1.0,\n step: 0.05,\n default: 0.5,\n },\n {\n key: 'iouThreshold',\n label: 'IoU Threshold (NMS)',\n type: 'slider',\n min: 0.1,\n max: 1.0,\n step: 0.05,\n default: 0.45,\n },\n ],\n },\n {\n id: 'classmap',\n title: 'Class Mapping',\n columns: 1,\n fields: [\n {\n key: 'classMapMode',\n label: 'Output classes',\n type: 'select',\n options: [\n { value: 'macro', label: 'Macro (person / vehicle / animal)' },\n { value: 'all', label: 'All COCO classes (80)' },\n ],\n },\n ],\n },\n ],\n }\n }\n\n getClassMap(): ClassMapDefinition {\n return COCO_TO_MACRO\n }\n\n getModelCatalog(): ModelCatalogEntry[] {\n return [...ALL_DETECTION_MODELS]\n }\n\n getAvailableModels(): DetectionModel[] {\n // TODO: check downloaded models in modelsDir\n return []\n }\n\n getActiveLabels(): readonly LabelDefinition[] {\n return this.classMapMode === 'all' ? COCO_80_LABELS : MACRO_LABELS\n }\n\n async probe(): Promise<ProbeResult> {\n return {\n available: true,\n runtime: this.engine?.runtime ?? 'onnx',\n device: this.engine?.device ?? 'cpu',\n capabilities: ['fp32'],\n }\n }\n}\n"],"mappings":"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","names":["detections"]}