@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
package/dist/index.mjs CHANGED
@@ -1,282 +1,2730 @@
1
1
  import {
2
- BirdGlobalClassifierAddon
3
- } from "./chunk-ZWYXXCXP.mjs";
2
+ require_animal_classification_models
3
+ } from "./chunk-XD7WGXHZ.mjs";
4
4
  import {
5
- BirdNABirdsClassifierAddon
6
- } from "./chunk-DRYFGARD.mjs";
5
+ require_vehicle_classification_models
6
+ } from "./chunk-K36R6HWY.mjs";
7
7
  import {
8
- AnimalClassifierAddon
9
- } from "./chunk-YUCD2TFH.mjs";
8
+ require_segmentation_refiner_models
9
+ } from "./chunk-BS4DKYGN.mjs";
10
10
  import {
11
- ANIMAL_TYPE_MODELS,
12
- BIRD_NABIRDS_MODELS,
13
- BIRD_SPECIES_MODELS
14
- } from "./chunk-DUN6XU3N.mjs";
11
+ require_frame_diff
12
+ } from "./chunk-YYDM6V2F.mjs";
15
13
  import {
16
- VEHICLE_TYPE_MODELS
17
- } from "./chunk-XZ6ZMXXU.mjs";
14
+ require_segmentation_models,
15
+ require_yolo_seg
16
+ } from "./chunk-ZK7P3TZN.mjs";
18
17
  import {
19
- SEGMENTATION_REFINER_MODELS
20
- } from "./chunk-7DYHXUPZ.mjs";
18
+ require_face_detection_models,
19
+ require_scrfd
20
+ } from "./chunk-2YMA6QOV.mjs";
21
21
  import {
22
- detectMotion
23
- } from "./chunk-BR2FPGOX.mjs";
22
+ require_arcface,
23
+ require_face_recognition_models
24
+ } from "./chunk-F6D2OZ36.mjs";
24
25
  import {
25
- ObjectDetectionAddon,
26
- SEGMENTATION_MODELS
27
- } from "./chunk-R5J3WAUI.mjs";
26
+ require_plate_detection_models
27
+ } from "./chunk-GAOIFQDX.mjs";
28
28
  import {
29
- FACE_DETECTION_MODELS,
30
- FaceDetectionAddon,
31
- scrfdPostprocess
32
- } from "./chunk-ESLHNWWE.mjs";
29
+ require_yolo
30
+ } from "./chunk-DE7I3VHO.mjs";
33
31
  import {
34
- FACE_RECOGNITION_MODELS,
35
- FaceRecognitionAddon,
36
- cosineSimilarity,
37
- l2Normalize
38
- } from "./chunk-JUQEW6ON.mjs";
32
+ require_object_detection_models
33
+ } from "./chunk-MGT6RUVX.mjs";
39
34
  import {
40
- PLATE_DETECTION_MODELS,
41
- PlateDetectionAddon
42
- } from "./chunk-YPU4WTXZ.mjs";
35
+ require_paddleocr,
36
+ require_plate_recognition_models
37
+ } from "./chunk-HUIX2XVR.mjs";
43
38
  import {
44
- iou,
45
- nms,
46
- yoloPostprocess
47
- } from "./chunk-KUO2BVFY.mjs";
39
+ require_image_utils
40
+ } from "./chunk-WG66JYYW.mjs";
48
41
  import {
49
- MLPACKAGE_FILES,
50
- OBJECT_DETECTION_MODELS
51
- } from "./chunk-BP7H4NFS.mjs";
42
+ require_audio_classification_models,
43
+ require_yamnet
44
+ } from "./chunk-MBTAI3WE.mjs";
52
45
  import {
53
- PLATE_RECOGNITION_MODELS,
54
- PlateRecognitionAddon,
55
- ctcDecode
56
- } from "./chunk-ZTJENCFC.mjs";
46
+ require_engine_resolver,
47
+ require_node_engine,
48
+ require_python_engine
49
+ } from "./chunk-PIFS7AIT.mjs";
57
50
  import {
58
- cropRegion,
59
- jpegToRgb,
60
- letterbox,
61
- resizeAndNormalize,
62
- rgbToGrayscale
63
- } from "./chunk-22BHCDT5.mjs";
64
- import {
65
- AUDIO_CLASSIFICATION_MODELS,
66
- AudioClassificationAddon,
67
- yamnetPostprocess
68
- } from "./chunk-D6WEHN33.mjs";
69
- import {
70
- NodeInferenceEngine,
71
- PythonInferenceEngine,
72
- probeOnnxBackends,
73
- resolveEngine
74
- } from "./chunk-2IOKI4ES.mjs";
75
- import "./chunk-BJTO5JO5.mjs";
51
+ __commonJS,
52
+ __export,
53
+ __reExport,
54
+ __require,
55
+ __toESM
56
+ } from "./chunk-3IIFBJCD.mjs";
76
57
 
77
- // src/catalogs/general-ocr-models.ts
78
- import { hfModelUrl } from "@camstack/types";
79
- var HF_REPO = "camstack/camstack-models";
80
- var OCR_TEXT_LABELS = [
81
- { id: "text", name: "Scene Text" }
82
- ];
83
- var GENERAL_OCR_MODELS = [
84
- // ── OnnxTR / docTR — lightweight general scene text recognition ──
85
- {
86
- id: "doctr-det-db-mobilenet",
87
- name: "docTR Detection MobileNet",
88
- description: "docTR DBNet MobileNet V3 \u2014 lightweight text region detection for scene text",
89
- inputSize: { width: 1024, height: 1024 },
90
- labels: OCR_TEXT_LABELS,
91
- formats: {
92
- onnx: {
93
- url: hfModelUrl(HF_REPO, "generalOcr/doctr/onnx/camstack-doctr-det-db-mobilenet-v3.onnx"),
94
- sizeMB: 15
58
+ // src/catalogs/general-ocr-models.js
59
+ var require_general_ocr_models = __commonJS({
60
+ "src/catalogs/general-ocr-models.js"(exports) {
61
+ "use strict";
62
+ Object.defineProperty(exports, "__esModule", { value: true });
63
+ exports.GENERAL_OCR_MODELS = void 0;
64
+ var types_1 = __require("@camstack/types");
65
+ var HF_REPO = "camstack/camstack-models";
66
+ var OCR_TEXT_LABELS = [
67
+ { id: "text", name: "Scene Text" }
68
+ ];
69
+ exports.GENERAL_OCR_MODELS = [
70
+ // ── OnnxTR / docTR lightweight general scene text recognition ──
71
+ {
72
+ id: "doctr-det-db-mobilenet",
73
+ name: "docTR Detection MobileNet",
74
+ description: "docTR DBNet MobileNet V3 \u2014 lightweight text region detection for scene text",
75
+ inputSize: { width: 1024, height: 1024 },
76
+ labels: OCR_TEXT_LABELS,
77
+ formats: {
78
+ onnx: {
79
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/doctr/onnx/camstack-doctr-det-db-mobilenet-v3.onnx"),
80
+ sizeMB: 15
81
+ },
82
+ coreml: {
83
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/doctr/coreml/camstack-doctr-det-db-mobilenet-v3.mlpackage"),
84
+ sizeMB: 8,
85
+ isDirectory: true,
86
+ files: [
87
+ "Manifest.json",
88
+ "Data/com.apple.CoreML/model.mlmodel",
89
+ "Data/com.apple.CoreML/weights/weight.bin"
90
+ ],
91
+ runtimes: ["python"]
92
+ },
93
+ openvino: {
94
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/doctr/openvino/camstack-doctr-det-db-mobilenet-v3.xml"),
95
+ sizeMB: 8,
96
+ runtimes: ["python"]
97
+ }
98
+ }
95
99
  },
96
- coreml: {
97
- url: hfModelUrl(HF_REPO, "generalOcr/doctr/coreml/camstack-doctr-det-db-mobilenet-v3.mlpackage"),
98
- sizeMB: 8,
99
- isDirectory: true,
100
- files: [
101
- "Manifest.json",
102
- "Data/com.apple.CoreML/model.mlmodel",
103
- "Data/com.apple.CoreML/weights/weight.bin"
104
- ],
105
- runtimes: ["python"]
100
+ {
101
+ id: "doctr-rec-crnn-mobilenet",
102
+ name: "docTR Recognition CRNN MobileNet",
103
+ description: "docTR CRNN MobileNet V3 \u2014 lightweight text recognition for detected regions",
104
+ inputSize: { width: 128, height: 32 },
105
+ labels: OCR_TEXT_LABELS,
106
+ formats: {
107
+ onnx: {
108
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/doctr/onnx/camstack-doctr-rec-crnn-mobilenet-v3.onnx"),
109
+ sizeMB: 5
110
+ },
111
+ coreml: {
112
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/doctr/coreml/camstack-doctr-rec-crnn-mobilenet-v3.mlpackage"),
113
+ sizeMB: 3,
114
+ isDirectory: true,
115
+ files: [
116
+ "Manifest.json",
117
+ "Data/com.apple.CoreML/model.mlmodel",
118
+ "Data/com.apple.CoreML/weights/weight.bin"
119
+ ],
120
+ runtimes: ["python"]
121
+ },
122
+ openvino: {
123
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/doctr/openvino/camstack-doctr-rec-crnn-mobilenet-v3.xml"),
124
+ sizeMB: 3,
125
+ runtimes: ["python"]
126
+ }
127
+ }
106
128
  },
107
- openvino: {
108
- url: hfModelUrl(HF_REPO, "generalOcr/doctr/openvino/camstack-doctr-det-db-mobilenet-v3.xml"),
109
- sizeMB: 8,
110
- runtimes: ["python"]
111
- }
112
- }
113
- },
114
- {
115
- id: "doctr-rec-crnn-mobilenet",
116
- name: "docTR Recognition CRNN MobileNet",
117
- description: "docTR CRNN MobileNet V3 \u2014 lightweight text recognition for detected regions",
118
- inputSize: { width: 128, height: 32 },
119
- labels: OCR_TEXT_LABELS,
120
- formats: {
121
- onnx: {
122
- url: hfModelUrl(HF_REPO, "generalOcr/doctr/onnx/camstack-doctr-rec-crnn-mobilenet-v3.onnx"),
123
- sizeMB: 5
129
+ {
130
+ id: "doctr-rec-parseq",
131
+ name: "docTR Recognition PARSeq",
132
+ description: "docTR PARSeq \u2014 high-accuracy scene text recognition (top ICDAR scores)",
133
+ inputSize: { width: 128, height: 32 },
134
+ labels: OCR_TEXT_LABELS,
135
+ formats: {
136
+ onnx: {
137
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/doctr/onnx/camstack-doctr-rec-parseq.onnx"),
138
+ sizeMB: 25
139
+ },
140
+ coreml: {
141
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/doctr/coreml/camstack-doctr-rec-parseq.mlpackage"),
142
+ sizeMB: 13,
143
+ isDirectory: true,
144
+ files: [
145
+ "Manifest.json",
146
+ "Data/com.apple.CoreML/model.mlmodel",
147
+ "Data/com.apple.CoreML/weights/weight.bin"
148
+ ],
149
+ runtimes: ["python"]
150
+ },
151
+ openvino: {
152
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/doctr/openvino/camstack-doctr-rec-parseq.xml"),
153
+ sizeMB: 13,
154
+ runtimes: ["python"]
155
+ }
156
+ }
124
157
  },
125
- coreml: {
126
- url: hfModelUrl(HF_REPO, "generalOcr/doctr/coreml/camstack-doctr-rec-crnn-mobilenet-v3.mlpackage"),
127
- sizeMB: 3,
128
- isDirectory: true,
129
- files: [
130
- "Manifest.json",
131
- "Data/com.apple.CoreML/model.mlmodel",
132
- "Data/com.apple.CoreML/weights/weight.bin"
133
- ],
134
- runtimes: ["python"]
158
+ // ── PaddleOCR PP-OCRv5 Mobile — general-purpose text detection + recognition ──
159
+ {
160
+ id: "ppocr-v5-det-mobile",
161
+ name: "PP-OCRv5 Detection Mobile",
162
+ description: "PP-OCRv5 mobile text detection \u2014 optimized for edge, 100+ languages",
163
+ inputSize: { width: 640, height: 640 },
164
+ labels: OCR_TEXT_LABELS,
165
+ formats: {
166
+ onnx: {
167
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/ppocr-v5/onnx/camstack-ppocr-v5-det-mobile.onnx"),
168
+ sizeMB: 6
169
+ },
170
+ coreml: {
171
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/ppocr-v5/coreml/camstack-ppocr-v5-det-mobile.mlpackage"),
172
+ sizeMB: 3,
173
+ isDirectory: true,
174
+ files: [
175
+ "Manifest.json",
176
+ "Data/com.apple.CoreML/model.mlmodel",
177
+ "Data/com.apple.CoreML/weights/weight.bin"
178
+ ],
179
+ runtimes: ["python"]
180
+ },
181
+ openvino: {
182
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/ppocr-v5/openvino/camstack-ppocr-v5-det-mobile.xml"),
183
+ sizeMB: 3,
184
+ runtimes: ["python"]
185
+ }
186
+ }
135
187
  },
136
- openvino: {
137
- url: hfModelUrl(HF_REPO, "generalOcr/doctr/openvino/camstack-doctr-rec-crnn-mobilenet-v3.xml"),
138
- sizeMB: 3,
139
- runtimes: ["python"]
188
+ {
189
+ id: "ppocr-v5-rec-mobile",
190
+ name: "PP-OCRv5 Recognition Mobile",
191
+ description: "PP-OCRv5 mobile text recognition \u2014 100+ languages, CTC decoding",
192
+ inputSize: { width: 320, height: 48 },
193
+ labels: OCR_TEXT_LABELS,
194
+ formats: {
195
+ onnx: {
196
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/ppocr-v5/onnx/camstack-ppocr-v5-rec-mobile.onnx"),
197
+ sizeMB: 8
198
+ },
199
+ coreml: {
200
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/ppocr-v5/coreml/camstack-ppocr-v5-rec-mobile.mlpackage"),
201
+ sizeMB: 4,
202
+ isDirectory: true,
203
+ files: [
204
+ "Manifest.json",
205
+ "Data/com.apple.CoreML/model.mlmodel",
206
+ "Data/com.apple.CoreML/weights/weight.bin"
207
+ ],
208
+ runtimes: ["python"]
209
+ },
210
+ openvino: {
211
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/ppocr-v5/openvino/camstack-ppocr-v5-rec-mobile.xml"),
212
+ sizeMB: 4,
213
+ runtimes: ["python"]
214
+ }
215
+ },
216
+ extraFiles: [
217
+ {
218
+ url: (0, types_1.hfModelUrl)(HF_REPO, "generalOcr/ppocr-v5/camstack-ppocr-v5-keys.txt"),
219
+ filename: "camstack-ppocr-v5-keys.txt",
220
+ sizeMB: 0.1
221
+ }
222
+ ]
223
+ }
224
+ ];
225
+ }
226
+ });
227
+
228
+ // src/catalogs/index.js
229
+ var require_catalogs = __commonJS({
230
+ "src/catalogs/index.js"(exports) {
231
+ "use strict";
232
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
233
+ if (k2 === void 0) k2 = k;
234
+ var desc = Object.getOwnPropertyDescriptor(m, k);
235
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
236
+ desc = { enumerable: true, get: function() {
237
+ return m[k];
238
+ } };
239
+ }
240
+ Object.defineProperty(o, k2, desc);
241
+ }) : (function(o, m, k, k2) {
242
+ if (k2 === void 0) k2 = k;
243
+ o[k2] = m[k];
244
+ }));
245
+ var __exportStar = exports && exports.__exportStar || function(m, exports2) {
246
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
247
+ };
248
+ Object.defineProperty(exports, "__esModule", { value: true });
249
+ __exportStar(require_object_detection_models(), exports);
250
+ __exportStar(require_face_detection_models(), exports);
251
+ __exportStar(require_face_recognition_models(), exports);
252
+ __exportStar(require_plate_detection_models(), exports);
253
+ __exportStar(require_plate_recognition_models(), exports);
254
+ __exportStar(require_general_ocr_models(), exports);
255
+ __exportStar(require_audio_classification_models(), exports);
256
+ __exportStar(require_segmentation_models(), exports);
257
+ __exportStar(require_animal_classification_models(), exports);
258
+ __exportStar(require_vehicle_classification_models(), exports);
259
+ __exportStar(require_segmentation_refiner_models(), exports);
260
+ }
261
+ });
262
+
263
+ // src/addons/object-detection/index.js
264
+ var require_object_detection = __commonJS({
265
+ "src/addons/object-detection/index.js"(exports) {
266
+ "use strict";
267
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
268
+ if (k2 === void 0) k2 = k;
269
+ var desc = Object.getOwnPropertyDescriptor(m, k);
270
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
271
+ desc = { enumerable: true, get: function() {
272
+ return m[k];
273
+ } };
140
274
  }
275
+ Object.defineProperty(o, k2, desc);
276
+ }) : (function(o, m, k, k2) {
277
+ if (k2 === void 0) k2 = k;
278
+ o[k2] = m[k];
279
+ }));
280
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
281
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
282
+ }) : function(o, v) {
283
+ o["default"] = v;
284
+ });
285
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
286
+ var ownKeys = function(o) {
287
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
288
+ var ar = [];
289
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
290
+ return ar;
291
+ };
292
+ return ownKeys(o);
293
+ };
294
+ return function(mod) {
295
+ if (mod && mod.__esModule) return mod;
296
+ var result = {};
297
+ if (mod != null) {
298
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
299
+ }
300
+ __setModuleDefault(result, mod);
301
+ return result;
302
+ };
303
+ })();
304
+ Object.defineProperty(exports, "__esModule", { value: true });
305
+ var object_detection_models_js_1 = require_object_detection_models();
306
+ var segmentation_models_js_1 = require_segmentation_models();
307
+ var types_1 = __require("@camstack/types");
308
+ var image_utils_js_1 = require_image_utils();
309
+ var yolo_js_1 = require_yolo();
310
+ var yolo_seg_js_1 = require_yolo_seg();
311
+ var engine_resolver_js_1 = require_engine_resolver();
312
+ function isSegModel(modelId) {
313
+ return modelId.includes("-seg");
141
314
  }
142
- },
143
- {
144
- id: "doctr-rec-parseq",
145
- name: "docTR Recognition PARSeq",
146
- description: "docTR PARSeq \u2014 high-accuracy scene text recognition (top ICDAR scores)",
147
- inputSize: { width: 128, height: 32 },
148
- labels: OCR_TEXT_LABELS,
149
- formats: {
150
- onnx: {
151
- url: hfModelUrl(HF_REPO, "generalOcr/doctr/onnx/camstack-doctr-rec-parseq.onnx"),
152
- sizeMB: 25
153
- },
154
- coreml: {
155
- url: hfModelUrl(HF_REPO, "generalOcr/doctr/coreml/camstack-doctr-rec-parseq.mlpackage"),
156
- sizeMB: 13,
157
- isDirectory: true,
158
- files: [
159
- "Manifest.json",
160
- "Data/com.apple.CoreML/model.mlmodel",
161
- "Data/com.apple.CoreML/weights/weight.bin"
162
- ],
163
- runtimes: ["python"]
164
- },
165
- openvino: {
166
- url: hfModelUrl(HF_REPO, "generalOcr/doctr/openvino/camstack-doctr-rec-parseq.xml"),
167
- sizeMB: 13,
168
- runtimes: ["python"]
315
+ var ALL_DETECTION_MODELS = [
316
+ ...object_detection_models_js_1.OBJECT_DETECTION_MODELS,
317
+ ...segmentation_models_js_1.SEGMENTATION_MODELS
318
+ ];
319
+ function applyClassMap(detections, classMap) {
320
+ return detections.filter((d) => classMap.mapping[d.class] !== void 0).map((d) => ({
321
+ ...d,
322
+ originalClass: d.class,
323
+ class: classMap.mapping[d.class]
324
+ }));
325
+ }
326
+ var RAM_ESTIMATES = {
327
+ "yolov8n": 80,
328
+ "yolov8s": 150,
329
+ "yolov8s-relu": 150,
330
+ "yolov8m": 300,
331
+ "yolov8l": 500,
332
+ "yolov8x": 800,
333
+ "yolov9t": 60,
334
+ "yolov9s": 120,
335
+ "yolov9c": 300,
336
+ "yolo11n": 70,
337
+ "yolo11s": 130,
338
+ "yolo11m": 280,
339
+ "yolo11l": 450,
340
+ "yolo11x": 750,
341
+ "yolo11n-seg": 84,
342
+ "yolo11s-seg": 156,
343
+ "yolo11m-seg": 336,
344
+ "yolov8n-seg": 96,
345
+ "yolov8s-seg": 180,
346
+ "yolov8m-seg": 360
347
+ };
348
+ var ACCURACY_SCORES = {
349
+ "yolov8n": 55,
350
+ "yolov8s": 70,
351
+ "yolov8s-relu": 68,
352
+ "yolov8m": 82,
353
+ "yolov8l": 88,
354
+ "yolov8x": 92,
355
+ "yolov9t": 58,
356
+ "yolov9s": 73,
357
+ "yolov9c": 86,
358
+ "yolo11n": 62,
359
+ "yolo11s": 78,
360
+ "yolo11m": 88,
361
+ "yolo11l": 93,
362
+ "yolo11x": 97,
363
+ "yolo11n-seg": 62,
364
+ "yolo11s-seg": 78,
365
+ "yolo11m-seg": 88,
366
+ "yolov8n-seg": 55,
367
+ "yolov8s-seg": 70,
368
+ "yolov8m-seg": 82
369
+ };
370
+ var ObjectDetectionAddon = class {
371
+ id = "object-detection";
372
+ slot = "detector";
373
+ inputClasses = null;
374
+ outputClasses = ["person", "vehicle", "animal"];
375
+ slotPriority = 0;
376
+ manifest = {
377
+ id: "object-detection",
378
+ name: "Object Detection",
379
+ version: "0.1.0",
380
+ description: "YOLO-based object detection \u2014 detects persons, vehicles, and animals",
381
+ slot: "detector",
382
+ inputClasses: void 0,
383
+ outputClasses: ["person", "vehicle", "animal"],
384
+ supportsCustomModels: true,
385
+ mayRequirePython: false,
386
+ defaultConfig: {
387
+ modelId: "yolo11n",
388
+ runtime: "node",
389
+ backend: "cpu",
390
+ confidence: 0.5,
391
+ iouThreshold: 0.45,
392
+ classMapMode: "macro"
393
+ }
394
+ };
395
+ engine = null;
396
+ modelEntry;
397
+ confidence = 0.5;
398
+ iouThreshold = 0.45;
399
+ classMapMode = "macro";
400
+ resolvedConfig = null;
401
+ ctx = null;
402
+ getModelRequirements() {
403
+ return ALL_DETECTION_MODELS.map((m) => ({
404
+ modelId: m.id,
405
+ name: m.name,
406
+ minRAM_MB: RAM_ESTIMATES[m.id] ?? 100,
407
+ accuracyScore: ACCURACY_SCORES[m.id] ?? 60,
408
+ formats: Object.keys(m.formats)
409
+ }));
410
+ }
411
+ configure(config) {
412
+ this.resolvedConfig = config;
413
+ }
414
+ async initialize(ctx) {
415
+ this.ctx = ctx;
416
+ const cfg = ctx.addonConfig;
417
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "yolo11n";
418
+ this.confidence = cfg["confidence"] ?? 0.5;
419
+ this.iouThreshold = cfg["iouThreshold"] ?? 0.45;
420
+ this.classMapMode = cfg["classMapMode"] ?? "macro";
421
+ const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId);
422
+ if (!entry) {
423
+ throw new Error(`ObjectDetectionAddon: unknown modelId "${modelId}"`);
424
+ }
425
+ this.modelEntry = entry;
426
+ }
427
+ async detect(frame) {
428
+ if (!this.engine)
429
+ await this.ensureEngine();
430
+ const start = Date.now();
431
+ if ("runJpeg" in this.engine && typeof this.engine.runJpeg === "function") {
432
+ const result = await this.engine.runJpeg(frame.data);
433
+ const rawDets = result.detections ?? [];
434
+ const detections2 = rawDets.map((d) => ({
435
+ class: this.classMapMode === "all" ? d.className : types_1.COCO_TO_MACRO.mapping[d.className] ?? d.className,
436
+ originalClass: d.className,
437
+ score: d.score,
438
+ bbox: {
439
+ x: d.bbox[0] * frame.width,
440
+ y: d.bbox[1] * frame.height,
441
+ w: (d.bbox[2] - d.bbox[0]) * frame.width,
442
+ h: (d.bbox[3] - d.bbox[1]) * frame.height
443
+ }
444
+ })).filter((d) => this.classMapMode === "all" || types_1.COCO_TO_MACRO.mapping[d.originalClass] !== void 0);
445
+ return {
446
+ detections: detections2,
447
+ inferenceMs: result.inferenceMs ?? Date.now() - start,
448
+ modelId: this.modelEntry.id
449
+ };
450
+ }
451
+ const { width: inputW, height: inputH } = this.modelEntry.inputSize;
452
+ const targetSize = Math.max(inputW, inputH);
453
+ const lb = await (0, image_utils_js_1.letterbox)(frame.data, targetSize);
454
+ const numClasses = this.modelEntry.labels.length;
455
+ const labels = this.modelEntry.labels.map((l) => l.id);
456
+ const postprocessOpts = {
457
+ confidence: this.confidence,
458
+ iouThreshold: this.iouThreshold,
459
+ labels,
460
+ scale: lb.scale,
461
+ padX: lb.padX,
462
+ padY: lb.padY,
463
+ originalWidth: lb.originalWidth,
464
+ originalHeight: lb.originalHeight
465
+ };
466
+ let rawDetections;
467
+ if (isSegModel(this.modelEntry.id)) {
468
+ const outputs = await this.engine.runMultiOutput(lb.data, [1, 3, targetSize, targetSize]);
469
+ const outputNames = Object.keys(outputs);
470
+ if (outputNames.length < 2) {
471
+ throw new Error(`ObjectDetectionAddon: seg model "${this.modelEntry.id}" returned ${outputNames.length} output(s); expected 2`);
472
+ }
473
+ const detectionOutput = outputs[outputNames[0]];
474
+ const protoOutput = outputs[outputNames[1]];
475
+ const numMaskCoeffs = 32;
476
+ const numBoxes = detectionOutput.length / (4 + numClasses + numMaskCoeffs);
477
+ const maskHeight = 160;
478
+ const maskWidth = 160;
479
+ rawDetections = (0, yolo_seg_js_1.yoloSegPostprocess)({
480
+ detectionOutput,
481
+ protoOutput,
482
+ numClasses,
483
+ numBoxes,
484
+ numMaskCoeffs,
485
+ maskHeight,
486
+ maskWidth
487
+ }, postprocessOpts);
488
+ } else {
489
+ const output = await this.engine.run(lb.data, [1, 3, targetSize, targetSize]);
490
+ const numBoxes = output.length / (4 + numClasses);
491
+ rawDetections = (0, yolo_js_1.yoloPostprocess)(output, numClasses, numBoxes, postprocessOpts);
492
+ }
493
+ const detections = this.classMapMode === "all" ? rawDetections : applyClassMap(rawDetections, types_1.COCO_TO_MACRO);
494
+ return {
495
+ detections,
496
+ inferenceMs: Date.now() - start,
497
+ modelId: this.modelEntry.id
498
+ };
499
+ }
500
+ async ensureEngine() {
501
+ const config = this.resolvedConfig;
502
+ const modelId = config?.modelId ?? this.modelEntry.id;
503
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
504
+ const backend = config?.backend ?? "cpu";
505
+ const format = config?.format ?? "onnx";
506
+ const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
507
+ this.modelEntry = entry;
508
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
509
+ if (this.ctx.models) {
510
+ await this.ctx.models.ensure(modelId, format);
511
+ }
512
+ let pythonPath;
513
+ if (config?.runtime === "python") {
514
+ for (const cmd of ["python3", "python"]) {
515
+ try {
516
+ const { execSync } = await Promise.resolve().then(() => __importStar(__require("child_process")));
517
+ execSync(`${cmd} --version`, { timeout: 3e3, stdio: "ignore" });
518
+ pythonPath = cmd;
519
+ break;
520
+ } catch {
521
+ }
522
+ }
523
+ }
524
+ const resolved = await (0, engine_resolver_js_1.resolveEngine)({
525
+ runtime,
526
+ backend,
527
+ modelEntry: entry,
528
+ modelsDir,
529
+ pythonPath,
530
+ models: this.ctx.models
531
+ });
532
+ this.engine = resolved.engine;
533
+ }
534
+ async shutdown() {
535
+ await this.engine?.dispose();
536
+ }
537
+ getConfigSchema() {
538
+ return {
539
+ sections: [
540
+ {
541
+ id: "model",
542
+ title: "Model",
543
+ columns: 1,
544
+ fields: [
545
+ {
546
+ key: "modelId",
547
+ label: "Model",
548
+ type: "model-selector",
549
+ catalog: [...ALL_DETECTION_MODELS],
550
+ allowCustom: true,
551
+ allowConversion: true,
552
+ acceptFormats: ["onnx", "coreml", "openvino", "tflite"],
553
+ requiredMetadata: ["inputSize", "labels", "outputFormat"],
554
+ outputFormatHint: "yolo"
555
+ }
556
+ ]
557
+ },
558
+ {
559
+ id: "runtime",
560
+ title: "Runtime",
561
+ columns: 2,
562
+ fields: [
563
+ {
564
+ key: "runtime",
565
+ label: "Runtime",
566
+ type: "select",
567
+ options: [
568
+ { value: "auto", label: "Auto" },
569
+ { value: "onnx", label: "ONNX Runtime" },
570
+ { value: "coreml", label: "CoreML (Apple)" },
571
+ { value: "openvino", label: "OpenVINO (Intel)" }
572
+ ]
573
+ },
574
+ {
575
+ key: "backend",
576
+ label: "Backend",
577
+ type: "select",
578
+ showWhen: { field: "runtime", equals: "onnx" },
579
+ options: [
580
+ { value: "auto", label: "Auto" },
581
+ { value: "cpu", label: "CPU" },
582
+ { value: "coreml", label: "CoreML" },
583
+ { value: "cuda", label: "CUDA (NVIDIA)" },
584
+ { value: "tensorrt", label: "TensorRT (NVIDIA)" }
585
+ ]
586
+ }
587
+ ]
588
+ },
589
+ {
590
+ id: "thresholds",
591
+ title: "Detection Thresholds",
592
+ columns: 2,
593
+ fields: [
594
+ {
595
+ key: "confidence",
596
+ label: "Confidence Threshold",
597
+ type: "slider",
598
+ min: 0.1,
599
+ max: 1,
600
+ step: 0.05,
601
+ default: 0.5
602
+ },
603
+ {
604
+ key: "iouThreshold",
605
+ label: "IoU Threshold (NMS)",
606
+ type: "slider",
607
+ min: 0.1,
608
+ max: 1,
609
+ step: 0.05,
610
+ default: 0.45
611
+ }
612
+ ]
613
+ },
614
+ {
615
+ id: "classmap",
616
+ title: "Class Mapping",
617
+ columns: 1,
618
+ fields: [
619
+ {
620
+ key: "classMapMode",
621
+ label: "Output classes",
622
+ type: "select",
623
+ options: [
624
+ { value: "macro", label: "Macro (person / vehicle / animal)" },
625
+ { value: "all", label: "All COCO classes (80)" }
626
+ ]
627
+ }
628
+ ]
629
+ }
630
+ ]
631
+ };
632
+ }
633
+ getClassMap() {
634
+ return types_1.COCO_TO_MACRO;
635
+ }
636
+ getModelCatalog() {
637
+ return [...ALL_DETECTION_MODELS];
638
+ }
639
+ getAvailableModels() {
640
+ return [];
641
+ }
642
+ getActiveLabels() {
643
+ return this.classMapMode === "all" ? types_1.COCO_80_LABELS : types_1.MACRO_LABELS;
644
+ }
645
+ async probe() {
646
+ return {
647
+ available: true,
648
+ runtime: this.engine?.runtime ?? "onnx",
649
+ device: this.engine?.device ?? "cpu",
650
+ capabilities: ["fp32"]
651
+ };
652
+ }
653
+ };
654
+ exports.default = ObjectDetectionAddon;
655
+ }
656
+ });
657
+
658
+ // src/addons/face-detection/index.js
659
+ var require_face_detection = __commonJS({
660
+ "src/addons/face-detection/index.js"(exports) {
661
+ "use strict";
662
+ Object.defineProperty(exports, "__esModule", { value: true });
663
+ var face_detection_models_js_1 = require_face_detection_models();
664
+ var image_utils_js_1 = require_image_utils();
665
+ var scrfd_js_1 = require_scrfd();
666
+ var engine_resolver_js_1 = require_engine_resolver();
667
+ var FACE_LABEL = { id: "face", name: "Face" };
668
+ var FACE_LABELS = [FACE_LABEL];
669
+ var FACE_CLASS_MAP = { mapping: {}, preserveOriginal: true };
670
+ var RAM_ESTIMATES = {
671
+ "scrfd-500m": 50,
672
+ "scrfd-2.5g": 80,
673
+ "scrfd-10g": 200
674
+ };
675
+ var ACCURACY_SCORES = {
676
+ "scrfd-500m": 70,
677
+ "scrfd-2.5g": 82,
678
+ "scrfd-10g": 92
679
+ };
680
+ var FaceDetectionAddon = class {
681
+ id = "face-detection";
682
+ slot = "cropper";
683
+ inputClasses = ["person"];
684
+ outputClasses = ["face"];
685
+ slotPriority = 0;
686
+ manifest = {
687
+ id: "face-detection",
688
+ name: "Face Detection",
689
+ version: "0.1.0",
690
+ description: "SCRFD-based face detector \u2014 crops face regions from person detections",
691
+ slot: "cropper",
692
+ inputClasses: ["person"],
693
+ outputClasses: ["face"],
694
+ supportsCustomModels: false,
695
+ mayRequirePython: false,
696
+ defaultConfig: {
697
+ modelId: "scrfd-500m",
698
+ runtime: "node",
699
+ backend: "cpu",
700
+ confidence: 0.5
701
+ }
702
+ };
703
+ engine = null;
704
+ modelEntry;
705
+ confidence = 0.5;
706
+ resolvedConfig = null;
707
+ ctx = null;
708
+ getModelRequirements() {
709
+ return face_detection_models_js_1.FACE_DETECTION_MODELS.map((m) => ({
710
+ modelId: m.id,
711
+ name: m.name,
712
+ minRAM_MB: RAM_ESTIMATES[m.id] ?? 50,
713
+ accuracyScore: ACCURACY_SCORES[m.id] ?? 70,
714
+ formats: Object.keys(m.formats)
715
+ }));
716
+ }
717
+ configure(config) {
718
+ this.resolvedConfig = config;
719
+ }
720
+ async initialize(ctx) {
721
+ this.ctx = ctx;
722
+ const cfg = ctx.addonConfig;
723
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "scrfd-500m";
724
+ this.confidence = cfg["confidence"] ?? 0.5;
725
+ const entry = face_detection_models_js_1.FACE_DETECTION_MODELS.find((m) => m.id === modelId);
726
+ if (!entry) {
727
+ throw new Error(`FaceDetectionAddon: unknown modelId "${modelId}"`);
728
+ }
729
+ this.modelEntry = entry;
730
+ }
731
+ async crop(input) {
732
+ if (!this.engine)
733
+ await this.ensureEngine();
734
+ const start = Date.now();
735
+ const { width: inputW, height: inputH } = this.modelEntry.inputSize;
736
+ const targetSize = Math.max(inputW, inputH);
737
+ const personCrop = await (0, image_utils_js_1.cropRegion)(input.frame.data, input.roi);
738
+ const lb = await (0, image_utils_js_1.letterbox)(personCrop, targetSize);
739
+ const engineWithMulti = this.engine;
740
+ let outputs;
741
+ if (typeof engineWithMulti.runMultiOutput === "function") {
742
+ outputs = await engineWithMulti.runMultiOutput(lb.data, [1, 3, targetSize, targetSize]);
743
+ } else {
744
+ const single = await this.engine.run(lb.data, [1, 3, targetSize, targetSize]);
745
+ outputs = { output0: single };
746
+ }
747
+ const crops = (0, scrfd_js_1.scrfdPostprocess)(outputs, this.confidence, targetSize, lb.originalWidth, lb.originalHeight);
748
+ return {
749
+ crops,
750
+ inferenceMs: Date.now() - start,
751
+ modelId: this.modelEntry.id
752
+ };
753
+ }
754
+ async ensureEngine() {
755
+ const config = this.resolvedConfig;
756
+ const modelId = config?.modelId ?? this.modelEntry.id;
757
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
758
+ const backend = config?.backend ?? "cpu";
759
+ const format = config?.format ?? "onnx";
760
+ const entry = face_detection_models_js_1.FACE_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
761
+ this.modelEntry = entry;
762
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
763
+ if (this.ctx.models) {
764
+ await this.ctx.models.ensure(modelId, format);
765
+ }
766
+ const resolved = await (0, engine_resolver_js_1.resolveEngine)({
767
+ runtime,
768
+ backend,
769
+ modelEntry: entry,
770
+ modelsDir,
771
+ models: this.ctx.models
772
+ });
773
+ this.engine = resolved.engine;
774
+ }
775
+ async shutdown() {
776
+ await this.engine?.dispose();
777
+ }
778
+ getConfigSchema() {
779
+ return {
780
+ sections: [
781
+ {
782
+ id: "model",
783
+ title: "Model",
784
+ columns: 1,
785
+ fields: [
786
+ {
787
+ key: "modelId",
788
+ label: "Model",
789
+ type: "model-selector",
790
+ catalog: [...face_detection_models_js_1.FACE_DETECTION_MODELS],
791
+ allowCustom: false,
792
+ allowConversion: false,
793
+ acceptFormats: ["onnx", "coreml", "openvino"],
794
+ requiredMetadata: ["inputSize", "labels", "outputFormat"],
795
+ outputFormatHint: "ssd"
796
+ }
797
+ ]
798
+ },
799
+ {
800
+ id: "runtime",
801
+ title: "Runtime",
802
+ columns: 2,
803
+ fields: [
804
+ {
805
+ key: "runtime",
806
+ label: "Runtime",
807
+ type: "select",
808
+ options: [
809
+ { value: "auto", label: "Auto" },
810
+ { value: "onnx", label: "ONNX Runtime" },
811
+ { value: "coreml", label: "CoreML (Apple)" },
812
+ { value: "openvino", label: "OpenVINO (Intel)" }
813
+ ]
814
+ },
815
+ {
816
+ key: "backend",
817
+ label: "Backend",
818
+ type: "select",
819
+ showWhen: { field: "runtime", equals: "onnx" },
820
+ options: [
821
+ { value: "auto", label: "Auto" },
822
+ { value: "cpu", label: "CPU" },
823
+ { value: "coreml", label: "CoreML" },
824
+ { value: "cuda", label: "CUDA (NVIDIA)" }
825
+ ]
826
+ }
827
+ ]
828
+ },
829
+ {
830
+ id: "thresholds",
831
+ title: "Detection Thresholds",
832
+ columns: 1,
833
+ fields: [
834
+ {
835
+ key: "confidence",
836
+ label: "Confidence Threshold",
837
+ type: "slider",
838
+ min: 0.1,
839
+ max: 1,
840
+ step: 0.05,
841
+ default: 0.5
842
+ }
843
+ ]
844
+ }
845
+ ]
846
+ };
847
+ }
848
+ getClassMap() {
849
+ return FACE_CLASS_MAP;
169
850
  }
851
+ getModelCatalog() {
852
+ return [...face_detection_models_js_1.FACE_DETECTION_MODELS];
853
+ }
854
+ getAvailableModels() {
855
+ return [];
856
+ }
857
+ getActiveLabels() {
858
+ return FACE_LABELS;
859
+ }
860
+ async probe() {
861
+ return {
862
+ available: true,
863
+ runtime: this.engine?.runtime ?? "onnx",
864
+ device: this.engine?.device ?? "cpu",
865
+ capabilities: ["fp32"]
866
+ };
867
+ }
868
+ };
869
+ exports.default = FaceDetectionAddon;
870
+ }
871
+ });
872
+
873
+ // src/addons/face-recognition/index.js
874
+ var require_face_recognition = __commonJS({
875
+ "src/addons/face-recognition/index.js"(exports) {
876
+ "use strict";
877
+ Object.defineProperty(exports, "__esModule", { value: true });
878
+ var face_recognition_models_js_1 = require_face_recognition_models();
879
+ var image_utils_js_1 = require_image_utils();
880
+ var arcface_js_1 = require_arcface();
881
+ var engine_resolver_js_1 = require_engine_resolver();
882
+ var IDENTITY_LABEL = { id: "identity", name: "Identity" };
883
+ var IDENTITY_LABELS = [IDENTITY_LABEL];
884
+ var FACE_REC_CLASS_MAP = { mapping: {}, preserveOriginal: true };
885
+ var REQUIRED_STEPS = [
886
+ { slot: "cropper", outputClasses: ["face"], description: "Requires a face detector" }
887
+ ];
888
+ var FaceRecognitionAddon = class {
889
+ id = "face-recognition";
890
+ slot = "classifier";
891
+ inputClasses = ["face"];
892
+ outputClasses = ["identity:*"];
893
+ slotPriority = 0;
894
+ requiredSteps = REQUIRED_STEPS;
895
+ manifest = {
896
+ id: "face-recognition",
897
+ name: "Face Recognition",
898
+ version: "0.1.0",
899
+ description: "ArcFace-based face recognition \u2014 produces 512-d identity embeddings",
900
+ slot: "classifier",
901
+ labelOutputType: "face",
902
+ inputClasses: ["face"],
903
+ outputClasses: ["identity:*"],
904
+ requiredSteps: REQUIRED_STEPS,
905
+ supportsCustomModels: false,
906
+ mayRequirePython: false,
907
+ defaultConfig: {
908
+ modelId: "arcface-r100",
909
+ runtime: "node",
910
+ backend: "cpu"
911
+ }
912
+ };
913
+ engine = null;
914
+ modelEntry;
915
+ resolvedConfig = null;
916
+ ctx = null;
917
+ getModelRequirements() {
918
+ return face_recognition_models_js_1.FACE_RECOGNITION_MODELS.map((m) => ({
919
+ modelId: m.id,
920
+ name: m.name,
921
+ minRAM_MB: 400,
922
+ accuracyScore: 90,
923
+ formats: Object.keys(m.formats)
924
+ }));
925
+ }
926
+ configure(config) {
927
+ this.resolvedConfig = config;
928
+ }
929
+ async initialize(ctx) {
930
+ this.ctx = ctx;
931
+ const cfg = ctx.addonConfig;
932
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "arcface-r100";
933
+ const entry = face_recognition_models_js_1.FACE_RECOGNITION_MODELS.find((m) => m.id === modelId);
934
+ if (!entry) {
935
+ throw new Error(`FaceRecognitionAddon: unknown modelId "${modelId}"`);
936
+ }
937
+ this.modelEntry = entry;
938
+ }
939
+ async classify(input) {
940
+ if (!this.engine)
941
+ await this.ensureEngine();
942
+ const start = Date.now();
943
+ const { width: inputW, height: inputH } = this.modelEntry.inputSize;
944
+ const faceCrop = await (0, image_utils_js_1.cropRegion)(input.frame.data, input.roi);
945
+ const layout = this.modelEntry.inputLayout ?? "nhwc";
946
+ const normalization = this.modelEntry.inputNormalization ?? "zero-one";
947
+ const normalized = await (0, image_utils_js_1.resizeAndNormalize)(faceCrop, inputW, inputH, normalization, layout);
948
+ const rawEmbedding = await this.engine.run(normalized, [1, inputH, inputW, 3]);
949
+ const embedding = (0, arcface_js_1.l2Normalize)(rawEmbedding);
950
+ return {
951
+ classifications: [
952
+ {
953
+ class: "identity",
954
+ score: 1,
955
+ embedding
956
+ }
957
+ ],
958
+ inferenceMs: Date.now() - start,
959
+ modelId: this.modelEntry.id
960
+ };
961
+ }
962
+ async ensureEngine() {
963
+ const config = this.resolvedConfig;
964
+ const modelId = config?.modelId ?? this.modelEntry.id;
965
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
966
+ const backend = config?.backend ?? "cpu";
967
+ const format = config?.format ?? "onnx";
968
+ const entry = face_recognition_models_js_1.FACE_RECOGNITION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
969
+ this.modelEntry = entry;
970
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
971
+ if (this.ctx.models) {
972
+ await this.ctx.models.ensure(modelId, format);
973
+ }
974
+ const resolved = await (0, engine_resolver_js_1.resolveEngine)({
975
+ runtime,
976
+ backend,
977
+ modelEntry: entry,
978
+ modelsDir,
979
+ models: this.ctx.models
980
+ });
981
+ this.engine = resolved.engine;
982
+ }
983
+ async shutdown() {
984
+ await this.engine?.dispose();
985
+ }
986
+ getConfigSchema() {
987
+ return {
988
+ sections: [
989
+ {
990
+ id: "model",
991
+ title: "Model",
992
+ columns: 1,
993
+ fields: [
994
+ {
995
+ key: "modelId",
996
+ label: "Model",
997
+ type: "model-selector",
998
+ catalog: [...face_recognition_models_js_1.FACE_RECOGNITION_MODELS],
999
+ allowCustom: false,
1000
+ allowConversion: false,
1001
+ acceptFormats: ["onnx", "coreml", "openvino"],
1002
+ requiredMetadata: ["inputSize", "labels", "outputFormat"],
1003
+ outputFormatHint: "embedding"
1004
+ }
1005
+ ]
1006
+ },
1007
+ {
1008
+ id: "runtime",
1009
+ title: "Runtime",
1010
+ columns: 2,
1011
+ fields: [
1012
+ {
1013
+ key: "runtime",
1014
+ label: "Runtime",
1015
+ type: "select",
1016
+ options: [
1017
+ { value: "auto", label: "Auto" },
1018
+ { value: "onnx", label: "ONNX Runtime" },
1019
+ { value: "coreml", label: "CoreML (Apple)" },
1020
+ { value: "openvino", label: "OpenVINO (Intel)" }
1021
+ ]
1022
+ },
1023
+ {
1024
+ key: "backend",
1025
+ label: "Backend",
1026
+ type: "select",
1027
+ showWhen: { field: "runtime", equals: "onnx" },
1028
+ options: [
1029
+ { value: "auto", label: "Auto" },
1030
+ { value: "cpu", label: "CPU" },
1031
+ { value: "coreml", label: "CoreML" },
1032
+ { value: "cuda", label: "CUDA (NVIDIA)" }
1033
+ ]
1034
+ }
1035
+ ]
1036
+ }
1037
+ ]
1038
+ };
1039
+ }
1040
+ getClassMap() {
1041
+ return FACE_REC_CLASS_MAP;
1042
+ }
1043
+ getModelCatalog() {
1044
+ return [...face_recognition_models_js_1.FACE_RECOGNITION_MODELS];
1045
+ }
1046
+ getAvailableModels() {
1047
+ return [];
1048
+ }
1049
+ getActiveLabels() {
1050
+ return IDENTITY_LABELS;
1051
+ }
1052
+ async probe() {
1053
+ return {
1054
+ available: true,
1055
+ runtime: this.engine?.runtime ?? "onnx",
1056
+ device: this.engine?.device ?? "cpu",
1057
+ capabilities: ["fp32"]
1058
+ };
1059
+ }
1060
+ };
1061
+ exports.default = FaceRecognitionAddon;
1062
+ }
1063
+ });
1064
+
1065
+ // src/addons/plate-detection/index.js
1066
+ var require_plate_detection = __commonJS({
1067
+ "src/addons/plate-detection/index.js"(exports) {
1068
+ "use strict";
1069
+ Object.defineProperty(exports, "__esModule", { value: true });
1070
+ var plate_detection_models_js_1 = require_plate_detection_models();
1071
+ var image_utils_js_1 = require_image_utils();
1072
+ var yolo_js_1 = require_yolo();
1073
+ var engine_resolver_js_1 = require_engine_resolver();
1074
+ var PLATE_LABEL = { id: "plate", name: "License Plate" };
1075
+ var PLATE_LABELS = [PLATE_LABEL];
1076
+ var PLATE_CLASS_MAP = { mapping: {}, preserveOriginal: true };
1077
+ var PlateDetectionAddon = class {
1078
+ id = "plate-detection";
1079
+ slot = "cropper";
1080
+ inputClasses = ["vehicle"];
1081
+ outputClasses = ["plate"];
1082
+ slotPriority = 0;
1083
+ manifest = {
1084
+ id: "plate-detection",
1085
+ name: "License Plate Detection",
1086
+ version: "0.1.0",
1087
+ description: "YOLO-based license plate detector \u2014 crops plate regions from vehicle detections",
1088
+ slot: "cropper",
1089
+ inputClasses: ["vehicle"],
1090
+ outputClasses: ["plate"],
1091
+ supportsCustomModels: false,
1092
+ mayRequirePython: false,
1093
+ defaultConfig: {
1094
+ modelId: "yolov8n-plate",
1095
+ runtime: "node",
1096
+ backend: "cpu",
1097
+ confidence: 0.5,
1098
+ iouThreshold: 0.45
1099
+ }
1100
+ };
1101
+ engine = null;
1102
+ modelEntry;
1103
+ confidence = 0.5;
1104
+ iouThreshold = 0.45;
1105
+ resolvedConfig = null;
1106
+ ctx = null;
1107
+ getModelRequirements() {
1108
+ return plate_detection_models_js_1.PLATE_DETECTION_MODELS.map((m) => ({
1109
+ modelId: m.id,
1110
+ name: m.name,
1111
+ minRAM_MB: 80,
1112
+ accuracyScore: 60,
1113
+ formats: Object.keys(m.formats)
1114
+ }));
1115
+ }
1116
+ configure(config) {
1117
+ this.resolvedConfig = config;
1118
+ }
1119
+ async initialize(ctx) {
1120
+ this.ctx = ctx;
1121
+ const cfg = ctx.addonConfig;
1122
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "yolov8n-plate";
1123
+ this.confidence = cfg["confidence"] ?? 0.5;
1124
+ this.iouThreshold = cfg["iouThreshold"] ?? 0.45;
1125
+ const entry = plate_detection_models_js_1.PLATE_DETECTION_MODELS.find((m) => m.id === modelId);
1126
+ if (!entry) {
1127
+ throw new Error(`PlateDetectionAddon: unknown modelId "${modelId}"`);
1128
+ }
1129
+ this.modelEntry = entry;
1130
+ }
1131
+ async crop(input) {
1132
+ if (!this.engine)
1133
+ await this.ensureEngine();
1134
+ const start = Date.now();
1135
+ const { width: inputW, height: inputH } = this.modelEntry.inputSize;
1136
+ const targetSize = Math.max(inputW, inputH);
1137
+ const vehicleCrop = await (0, image_utils_js_1.cropRegion)(input.frame.data, input.roi);
1138
+ const lb = await (0, image_utils_js_1.letterbox)(vehicleCrop, targetSize);
1139
+ const output = await this.engine.run(lb.data, [1, 3, targetSize, targetSize]);
1140
+ const numClasses = this.modelEntry.labels.length;
1141
+ const numBoxes = output.length / (4 + numClasses);
1142
+ const labels = this.modelEntry.labels.map((l) => l.id);
1143
+ const plates = (0, yolo_js_1.yoloPostprocess)(output, numClasses, numBoxes, {
1144
+ confidence: this.confidence,
1145
+ iouThreshold: this.iouThreshold,
1146
+ labels,
1147
+ scale: lb.scale,
1148
+ padX: lb.padX,
1149
+ padY: lb.padY,
1150
+ originalWidth: lb.originalWidth,
1151
+ originalHeight: lb.originalHeight
1152
+ });
1153
+ const crops = plates.map((p) => ({ ...p, class: "plate", originalClass: p.originalClass }));
1154
+ return {
1155
+ crops,
1156
+ inferenceMs: Date.now() - start,
1157
+ modelId: this.modelEntry.id
1158
+ };
1159
+ }
1160
+ async ensureEngine() {
1161
+ const config = this.resolvedConfig;
1162
+ const modelId = config?.modelId ?? this.modelEntry.id;
1163
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
1164
+ const backend = config?.backend ?? "cpu";
1165
+ const format = config?.format ?? "onnx";
1166
+ const entry = plate_detection_models_js_1.PLATE_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
1167
+ this.modelEntry = entry;
1168
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
1169
+ if (this.ctx.models) {
1170
+ await this.ctx.models.ensure(modelId, format);
1171
+ }
1172
+ const resolved = await (0, engine_resolver_js_1.resolveEngine)({
1173
+ runtime,
1174
+ backend,
1175
+ modelEntry: entry,
1176
+ modelsDir,
1177
+ models: this.ctx.models
1178
+ });
1179
+ this.engine = resolved.engine;
1180
+ }
1181
+ async shutdown() {
1182
+ await this.engine?.dispose();
1183
+ }
1184
+ getConfigSchema() {
1185
+ return {
1186
+ sections: [
1187
+ {
1188
+ id: "model",
1189
+ title: "Model",
1190
+ columns: 1,
1191
+ fields: [
1192
+ {
1193
+ key: "modelId",
1194
+ label: "Model",
1195
+ type: "model-selector",
1196
+ catalog: [...plate_detection_models_js_1.PLATE_DETECTION_MODELS],
1197
+ allowCustom: false,
1198
+ allowConversion: false,
1199
+ acceptFormats: ["onnx", "coreml", "openvino"],
1200
+ requiredMetadata: ["inputSize", "labels", "outputFormat"],
1201
+ outputFormatHint: "yolo"
1202
+ }
1203
+ ]
1204
+ },
1205
+ {
1206
+ id: "runtime",
1207
+ title: "Runtime",
1208
+ columns: 2,
1209
+ fields: [
1210
+ {
1211
+ key: "runtime",
1212
+ label: "Runtime",
1213
+ type: "select",
1214
+ options: [
1215
+ { value: "auto", label: "Auto" },
1216
+ { value: "onnx", label: "ONNX Runtime" },
1217
+ { value: "coreml", label: "CoreML (Apple)" },
1218
+ { value: "openvino", label: "OpenVINO (Intel)" }
1219
+ ]
1220
+ },
1221
+ {
1222
+ key: "backend",
1223
+ label: "Backend",
1224
+ type: "select",
1225
+ showWhen: { field: "runtime", equals: "onnx" },
1226
+ options: [
1227
+ { value: "auto", label: "Auto" },
1228
+ { value: "cpu", label: "CPU" },
1229
+ { value: "coreml", label: "CoreML" },
1230
+ { value: "cuda", label: "CUDA (NVIDIA)" }
1231
+ ]
1232
+ }
1233
+ ]
1234
+ },
1235
+ {
1236
+ id: "thresholds",
1237
+ title: "Detection Thresholds",
1238
+ columns: 2,
1239
+ fields: [
1240
+ {
1241
+ key: "confidence",
1242
+ label: "Confidence Threshold",
1243
+ type: "slider",
1244
+ min: 0.1,
1245
+ max: 1,
1246
+ step: 0.05,
1247
+ default: 0.5
1248
+ },
1249
+ {
1250
+ key: "iouThreshold",
1251
+ label: "IoU Threshold (NMS)",
1252
+ type: "slider",
1253
+ min: 0.1,
1254
+ max: 1,
1255
+ step: 0.05,
1256
+ default: 0.45
1257
+ }
1258
+ ]
1259
+ }
1260
+ ]
1261
+ };
1262
+ }
1263
+ getClassMap() {
1264
+ return PLATE_CLASS_MAP;
1265
+ }
1266
+ getModelCatalog() {
1267
+ return [...plate_detection_models_js_1.PLATE_DETECTION_MODELS];
1268
+ }
1269
+ getAvailableModels() {
1270
+ return [];
1271
+ }
1272
+ getActiveLabels() {
1273
+ return PLATE_LABELS;
1274
+ }
1275
+ async probe() {
1276
+ return {
1277
+ available: true,
1278
+ runtime: this.engine?.runtime ?? "onnx",
1279
+ device: this.engine?.device ?? "cpu",
1280
+ capabilities: ["fp32"]
1281
+ };
1282
+ }
1283
+ };
1284
+ exports.default = PlateDetectionAddon;
1285
+ }
1286
+ });
1287
+
1288
+ // src/addons/plate-recognition/index.js
1289
+ var require_plate_recognition = __commonJS({
1290
+ "src/addons/plate-recognition/index.js"(exports) {
1291
+ "use strict";
1292
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
1293
+ if (k2 === void 0) k2 = k;
1294
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1295
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1296
+ desc = { enumerable: true, get: function() {
1297
+ return m[k];
1298
+ } };
1299
+ }
1300
+ Object.defineProperty(o, k2, desc);
1301
+ }) : (function(o, m, k, k2) {
1302
+ if (k2 === void 0) k2 = k;
1303
+ o[k2] = m[k];
1304
+ }));
1305
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
1306
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1307
+ }) : function(o, v) {
1308
+ o["default"] = v;
1309
+ });
1310
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
1311
+ var ownKeys = function(o) {
1312
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1313
+ var ar = [];
1314
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1315
+ return ar;
1316
+ };
1317
+ return ownKeys(o);
1318
+ };
1319
+ return function(mod) {
1320
+ if (mod && mod.__esModule) return mod;
1321
+ var result = {};
1322
+ if (mod != null) {
1323
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1324
+ }
1325
+ __setModuleDefault(result, mod);
1326
+ return result;
1327
+ };
1328
+ })();
1329
+ Object.defineProperty(exports, "__esModule", { value: true });
1330
+ var plate_recognition_models_js_1 = require_plate_recognition_models();
1331
+ var image_utils_js_1 = require_image_utils();
1332
+ var paddleocr_js_1 = require_paddleocr();
1333
+ var engine_resolver_js_1 = require_engine_resolver();
1334
+ var PLATE_TEXT_LABEL = { id: "plate-text", name: "Plate Text" };
1335
+ var PLATE_TEXT_LABELS = [PLATE_TEXT_LABEL];
1336
+ var PLATE_REC_CLASS_MAP = { mapping: {}, preserveOriginal: true };
1337
+ var fs = __importStar(__require("fs"));
1338
+ var path = __importStar(__require("path"));
1339
+ function loadCharset(modelsDir, modelId) {
1340
+ const dictNames = [
1341
+ `camstack-${modelId}-dict.txt`,
1342
+ `camstack-paddleocr-latin-dict.txt`,
1343
+ `camstack-paddleocr-en-dict.txt`,
1344
+ `camstack-crnn-mobilenet-charset.txt`
1345
+ ];
1346
+ for (const name of dictNames) {
1347
+ const dictPath = path.join(modelsDir, name);
1348
+ if (fs.existsSync(dictPath)) {
1349
+ const lines = fs.readFileSync(dictPath, "utf-8").split("\n").filter((l) => l.length > 0);
1350
+ return ["", ...lines, " "];
1351
+ }
1352
+ }
1353
+ throw new Error(`PlateRecognitionAddon: dict.txt not found in ${modelsDir}`);
170
1354
  }
171
- },
172
- // ── PaddleOCR PP-OCRv5 Mobile general-purpose text detection + recognition ──
173
- {
174
- id: "ppocr-v5-det-mobile",
175
- name: "PP-OCRv5 Detection Mobile",
176
- description: "PP-OCRv5 mobile text detection \u2014 optimized for edge, 100+ languages",
177
- inputSize: { width: 640, height: 640 },
178
- labels: OCR_TEXT_LABELS,
179
- formats: {
180
- onnx: {
181
- url: hfModelUrl(HF_REPO, "generalOcr/ppocr-v5/onnx/camstack-ppocr-v5-det-mobile.onnx"),
182
- sizeMB: 6
183
- },
184
- coreml: {
185
- url: hfModelUrl(HF_REPO, "generalOcr/ppocr-v5/coreml/camstack-ppocr-v5-det-mobile.mlpackage"),
186
- sizeMB: 3,
187
- isDirectory: true,
188
- files: [
189
- "Manifest.json",
190
- "Data/com.apple.CoreML/model.mlmodel",
191
- "Data/com.apple.CoreML/weights/weight.bin"
192
- ],
193
- runtimes: ["python"]
194
- },
195
- openvino: {
196
- url: hfModelUrl(HF_REPO, "generalOcr/ppocr-v5/openvino/camstack-ppocr-v5-det-mobile.xml"),
197
- sizeMB: 3,
198
- runtimes: ["python"]
1355
+ var REQUIRED_STEPS = [
1356
+ { slot: "cropper", outputClasses: ["plate"], description: "Requires a plate detector" }
1357
+ ];
1358
+ var PlateRecognitionAddon = class {
1359
+ id = "plate-recognition";
1360
+ slot = "classifier";
1361
+ inputClasses = ["plate"];
1362
+ outputClasses = ["plate-text:*"];
1363
+ slotPriority = 0;
1364
+ requiredSteps = REQUIRED_STEPS;
1365
+ manifest = {
1366
+ id: "plate-recognition",
1367
+ name: "License Plate Recognition (OCR)",
1368
+ version: "0.1.0",
1369
+ description: "PaddleOCR-based license plate text recognition",
1370
+ slot: "classifier",
1371
+ labelOutputType: "plate",
1372
+ inputClasses: ["plate"],
1373
+ outputClasses: ["plate-text:*"],
1374
+ requiredSteps: REQUIRED_STEPS,
1375
+ supportsCustomModels: false,
1376
+ mayRequirePython: false,
1377
+ defaultConfig: {
1378
+ modelId: "paddleocr-latin",
1379
+ runtime: "node",
1380
+ backend: "cpu",
1381
+ minConfidence: 0.5
1382
+ }
1383
+ };
1384
+ engine = null;
1385
+ modelEntry;
1386
+ minConfidence = 0.5;
1387
+ charset = [];
1388
+ resolvedConfig = null;
1389
+ ctx = null;
1390
+ getModelRequirements() {
1391
+ const scores = {
1392
+ "paddleocr-latin": { ram: 100, accuracy: 80 },
1393
+ "paddleocr-en": { ram: 100, accuracy: 80 }
1394
+ };
1395
+ return plate_recognition_models_js_1.PLATE_RECOGNITION_MODELS.map((m) => ({
1396
+ modelId: m.id,
1397
+ name: m.name,
1398
+ minRAM_MB: scores[m.id]?.ram ?? 100,
1399
+ accuracyScore: scores[m.id]?.accuracy ?? 75,
1400
+ formats: Object.keys(m.formats)
1401
+ }));
1402
+ }
1403
+ configure(config) {
1404
+ this.resolvedConfig = config;
199
1405
  }
1406
+ async initialize(ctx) {
1407
+ this.ctx = ctx;
1408
+ const cfg = ctx.addonConfig;
1409
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "paddleocr-latin";
1410
+ this.minConfidence = cfg["minConfidence"] ?? 0.5;
1411
+ const entry = plate_recognition_models_js_1.PLATE_RECOGNITION_MODELS.find((m) => m.id === modelId);
1412
+ if (!entry) {
1413
+ throw new Error(`PlateRecognitionAddon: unknown modelId "${modelId}"`);
1414
+ }
1415
+ this.modelEntry = entry;
1416
+ }
1417
+ async classify(input) {
1418
+ if (!this.engine)
1419
+ await this.ensureEngine();
1420
+ const start = Date.now();
1421
+ const { width: inputW, height: inputH } = this.modelEntry.inputSize;
1422
+ console.log(`[plate-recognition] ROI: x=${input.roi?.x}, y=${input.roi?.y}, w=${input.roi?.w}, h=${input.roi?.h}, frameSize=${input.frame?.data?.length}`);
1423
+ const plateCrop = await (0, image_utils_js_1.cropRegion)(input.frame.data, input.roi);
1424
+ console.log(`[plate-recognition] Crop size: ${plateCrop.length} bytes`);
1425
+ try {
1426
+ __require("fs").writeFileSync("/tmp/plate-recognition-crop.jpg", plateCrop);
1427
+ } catch {
1428
+ }
1429
+ const normalized = await (0, image_utils_js_1.resizeAndNormalize)(plateCrop, inputW, inputH, "zero-one", "nchw");
1430
+ const output = await this.engine.run(normalized, [1, 3, inputH, inputW]);
1431
+ const numChars = this.charset.length;
1432
+ const seqLen = output.length / numChars;
1433
+ const { text, confidence } = (0, paddleocr_js_1.ctcDecode)(output, seqLen, numChars, this.charset);
1434
+ return {
1435
+ classifications: [
1436
+ {
1437
+ class: "plate-text",
1438
+ score: confidence,
1439
+ text: text.trim() || "(unreadable)"
1440
+ }
1441
+ ],
1442
+ inferenceMs: Date.now() - start,
1443
+ modelId: this.modelEntry.id
1444
+ };
1445
+ }
1446
+ async ensureEngine() {
1447
+ const config = this.resolvedConfig;
1448
+ const modelId = config?.modelId ?? this.modelEntry.id;
1449
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
1450
+ const backend = config?.backend ?? "cpu";
1451
+ const format = config?.format ?? "onnx";
1452
+ const entry = plate_recognition_models_js_1.PLATE_RECOGNITION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
1453
+ this.modelEntry = entry;
1454
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
1455
+ if (this.ctx.models) {
1456
+ await this.ctx.models.ensure(modelId, format);
1457
+ }
1458
+ this.charset = loadCharset(modelsDir, modelId);
1459
+ const resolved = await (0, engine_resolver_js_1.resolveEngine)({
1460
+ runtime,
1461
+ backend,
1462
+ modelEntry: entry,
1463
+ modelsDir,
1464
+ models: this.ctx.models
1465
+ });
1466
+ this.engine = resolved.engine;
1467
+ }
1468
+ async shutdown() {
1469
+ await this.engine?.dispose();
1470
+ }
1471
+ getConfigSchema() {
1472
+ return {
1473
+ sections: [
1474
+ {
1475
+ id: "model",
1476
+ title: "Model",
1477
+ columns: 1,
1478
+ fields: [
1479
+ {
1480
+ key: "modelId",
1481
+ label: "Model",
1482
+ type: "model-selector",
1483
+ catalog: [...plate_recognition_models_js_1.PLATE_RECOGNITION_MODELS],
1484
+ allowCustom: false,
1485
+ allowConversion: false,
1486
+ acceptFormats: ["onnx", "openvino"],
1487
+ requiredMetadata: ["inputSize", "labels", "outputFormat"],
1488
+ outputFormatHint: "ocr"
1489
+ }
1490
+ ]
1491
+ },
1492
+ {
1493
+ id: "runtime",
1494
+ title: "Runtime",
1495
+ columns: 2,
1496
+ fields: [
1497
+ {
1498
+ key: "runtime",
1499
+ label: "Runtime",
1500
+ type: "select",
1501
+ options: [
1502
+ { value: "auto", label: "Auto" },
1503
+ { value: "onnx", label: "ONNX Runtime" },
1504
+ { value: "openvino", label: "OpenVINO (Intel)" }
1505
+ ]
1506
+ },
1507
+ {
1508
+ key: "backend",
1509
+ label: "Backend",
1510
+ type: "select",
1511
+ showWhen: { field: "runtime", equals: "onnx" },
1512
+ options: [
1513
+ { value: "auto", label: "Auto" },
1514
+ { value: "cpu", label: "CPU" },
1515
+ { value: "cuda", label: "CUDA (NVIDIA)" }
1516
+ ]
1517
+ }
1518
+ ]
1519
+ },
1520
+ {
1521
+ id: "thresholds",
1522
+ title: "Recognition Settings",
1523
+ columns: 1,
1524
+ fields: [
1525
+ {
1526
+ key: "minConfidence",
1527
+ label: "Minimum Confidence",
1528
+ type: "slider",
1529
+ min: 0.1,
1530
+ max: 1,
1531
+ step: 0.05,
1532
+ default: 0.5
1533
+ }
1534
+ ]
1535
+ }
1536
+ ]
1537
+ };
1538
+ }
1539
+ getClassMap() {
1540
+ return PLATE_REC_CLASS_MAP;
1541
+ }
1542
+ getModelCatalog() {
1543
+ return [...plate_recognition_models_js_1.PLATE_RECOGNITION_MODELS];
1544
+ }
1545
+ getAvailableModels() {
1546
+ return [];
1547
+ }
1548
+ getActiveLabels() {
1549
+ return PLATE_TEXT_LABELS;
1550
+ }
1551
+ async probe() {
1552
+ return {
1553
+ available: true,
1554
+ runtime: this.engine?.runtime ?? "onnx",
1555
+ device: this.engine?.device ?? "cpu",
1556
+ capabilities: ["fp32"]
1557
+ };
1558
+ }
1559
+ };
1560
+ exports.default = PlateRecognitionAddon;
1561
+ }
1562
+ });
1563
+
1564
+ // src/addons/audio-classification/index.js
1565
+ var require_audio_classification = __commonJS({
1566
+ "src/addons/audio-classification/index.js"(exports) {
1567
+ "use strict";
1568
+ Object.defineProperty(exports, "__esModule", { value: true });
1569
+ var audio_classification_models_js_1 = require_audio_classification_models();
1570
+ var yamnet_js_1 = require_yamnet();
1571
+ var engine_resolver_js_1 = require_engine_resolver();
1572
+ var YAMNET_NUM_CLASSES = 521;
1573
+ var AUDIO_EVENT_LABEL = { id: "audio-event", name: "Audio Event" };
1574
+ var AUDIO_LABELS = [AUDIO_EVENT_LABEL];
1575
+ var AUDIO_CLASS_MAP = { mapping: {}, preserveOriginal: true };
1576
+ var AudioClassificationAddon = class {
1577
+ id = "audio-classification";
1578
+ slot = "classifier";
1579
+ inputClasses = null;
1580
+ outputClasses = ["audio-event:*"];
1581
+ slotPriority = 0;
1582
+ manifest = {
1583
+ id: "audio-classification",
1584
+ name: "Audio Classification",
1585
+ version: "0.1.0",
1586
+ description: "YAMNet-based audio event classification from audio waveform",
1587
+ slot: "classifier",
1588
+ labelOutputType: "classification",
1589
+ inputClasses: void 0,
1590
+ outputClasses: ["audio-event:*"],
1591
+ supportsCustomModels: false,
1592
+ mayRequirePython: false,
1593
+ defaultConfig: {
1594
+ modelId: "yamnet",
1595
+ runtime: "node",
1596
+ backend: "cpu",
1597
+ minScore: 0.3
1598
+ }
1599
+ };
1600
+ engine = null;
1601
+ modelEntry;
1602
+ minScore = 0.3;
1603
+ resolvedConfig = null;
1604
+ ctx = null;
1605
+ getModelRequirements() {
1606
+ return audio_classification_models_js_1.AUDIO_CLASSIFICATION_MODELS.map((m) => ({
1607
+ modelId: m.id,
1608
+ name: m.name,
1609
+ minRAM_MB: 100,
1610
+ accuracyScore: 80,
1611
+ formats: Object.keys(m.formats)
1612
+ }));
1613
+ }
1614
+ configure(config) {
1615
+ this.resolvedConfig = config;
1616
+ }
1617
+ async initialize(ctx) {
1618
+ this.ctx = ctx;
1619
+ const cfg = ctx.addonConfig;
1620
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "yamnet";
1621
+ this.minScore = cfg["minScore"] ?? 0.3;
1622
+ const entry = audio_classification_models_js_1.AUDIO_CLASSIFICATION_MODELS.find((m) => m.id === modelId);
1623
+ if (!entry) {
1624
+ throw new Error(`AudioClassificationAddon: unknown modelId "${modelId}"`);
1625
+ }
1626
+ this.modelEntry = entry;
1627
+ }
1628
+ /**
1629
+ * classify() receives a CropInput but internally treats input.frame.data as raw audio context.
1630
+ * For audio, the actual audio chunk data should be stored in frame.data as a Float32Array
1631
+ * serialized into a Buffer (little-endian float32 samples at 16 kHz).
1632
+ *
1633
+ * The CropInput.roi is not used for audio — it is ignored.
1634
+ */
1635
+ async classify(input) {
1636
+ if (!this.engine)
1637
+ await this.ensureEngine();
1638
+ const start = Date.now();
1639
+ const buf = input.frame.data;
1640
+ const numSamples = Math.floor(buf.length / 4);
1641
+ const audioData = new Float32Array(numSamples);
1642
+ for (let i = 0; i < numSamples; i++) {
1643
+ audioData[i] = buf.readFloatLE(i * 4);
1644
+ }
1645
+ const output = await this.engine.run(audioData, [numSamples]);
1646
+ const numFrames = output.length / YAMNET_NUM_CLASSES;
1647
+ const classNames = this.modelEntry.labels.map((l) => l.id);
1648
+ while (classNames.length < YAMNET_NUM_CLASSES) {
1649
+ classNames.push(`class_${classNames.length}`);
1650
+ }
1651
+ const results = (0, yamnet_js_1.yamnetPostprocess)(output, Math.round(numFrames), YAMNET_NUM_CLASSES, classNames, this.minScore);
1652
+ const classifications = results.map((r) => ({
1653
+ class: `audio-event:${r.className}`,
1654
+ score: r.score
1655
+ }));
1656
+ return {
1657
+ classifications,
1658
+ inferenceMs: Date.now() - start,
1659
+ modelId: this.modelEntry.id
1660
+ };
1661
+ }
1662
+ async ensureEngine() {
1663
+ const config = this.resolvedConfig;
1664
+ const modelId = config?.modelId ?? this.modelEntry.id;
1665
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
1666
+ const backend = config?.backend ?? "cpu";
1667
+ const format = config?.format ?? "onnx";
1668
+ const entry = audio_classification_models_js_1.AUDIO_CLASSIFICATION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
1669
+ this.modelEntry = entry;
1670
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
1671
+ if (this.ctx.models) {
1672
+ await this.ctx.models.ensure(modelId, format);
1673
+ }
1674
+ const resolved = await (0, engine_resolver_js_1.resolveEngine)({
1675
+ runtime,
1676
+ backend,
1677
+ modelEntry: entry,
1678
+ modelsDir,
1679
+ models: this.ctx.models
1680
+ });
1681
+ this.engine = resolved.engine;
1682
+ }
1683
+ async shutdown() {
1684
+ await this.engine?.dispose();
1685
+ }
1686
+ getConfigSchema() {
1687
+ return {
1688
+ sections: [
1689
+ {
1690
+ id: "model",
1691
+ title: "Model",
1692
+ columns: 1,
1693
+ fields: [
1694
+ {
1695
+ key: "modelId",
1696
+ label: "Model",
1697
+ type: "model-selector",
1698
+ catalog: [...audio_classification_models_js_1.AUDIO_CLASSIFICATION_MODELS],
1699
+ allowCustom: false,
1700
+ allowConversion: false,
1701
+ acceptFormats: ["onnx", "openvino"],
1702
+ requiredMetadata: ["inputSize", "labels", "outputFormat"],
1703
+ outputFormatHint: "classification"
1704
+ }
1705
+ ]
1706
+ },
1707
+ {
1708
+ id: "runtime",
1709
+ title: "Runtime",
1710
+ columns: 2,
1711
+ fields: [
1712
+ {
1713
+ key: "runtime",
1714
+ label: "Runtime",
1715
+ type: "select",
1716
+ options: [
1717
+ { value: "auto", label: "Auto" },
1718
+ { value: "onnx", label: "ONNX Runtime" },
1719
+ { value: "coreml", label: "CoreML (Apple)" },
1720
+ { value: "openvino", label: "OpenVINO (Intel)" }
1721
+ ]
1722
+ },
1723
+ {
1724
+ key: "backend",
1725
+ label: "Backend",
1726
+ type: "select",
1727
+ showWhen: { field: "runtime", equals: "onnx" },
1728
+ options: [
1729
+ { value: "auto", label: "Auto" },
1730
+ { value: "cpu", label: "CPU" },
1731
+ { value: "coreml", label: "CoreML" },
1732
+ { value: "cuda", label: "CUDA (NVIDIA)" }
1733
+ ]
1734
+ }
1735
+ ]
1736
+ },
1737
+ {
1738
+ id: "thresholds",
1739
+ title: "Classification Settings",
1740
+ columns: 1,
1741
+ fields: [
1742
+ {
1743
+ key: "minScore",
1744
+ label: "Minimum Score",
1745
+ type: "slider",
1746
+ min: 0.05,
1747
+ max: 1,
1748
+ step: 0.05,
1749
+ default: 0.3
1750
+ }
1751
+ ]
1752
+ }
1753
+ ]
1754
+ };
1755
+ }
1756
+ getClassMap() {
1757
+ return AUDIO_CLASS_MAP;
1758
+ }
1759
+ getModelCatalog() {
1760
+ return [...audio_classification_models_js_1.AUDIO_CLASSIFICATION_MODELS];
1761
+ }
1762
+ getAvailableModels() {
1763
+ return [];
1764
+ }
1765
+ getActiveLabels() {
1766
+ return AUDIO_LABELS;
1767
+ }
1768
+ async probe() {
1769
+ return {
1770
+ available: true,
1771
+ runtime: this.engine?.runtime ?? "onnx",
1772
+ device: this.engine?.device ?? "cpu",
1773
+ capabilities: ["fp32"]
1774
+ };
1775
+ }
1776
+ };
1777
+ exports.default = AudioClassificationAddon;
1778
+ }
1779
+ });
1780
+
1781
+ // src/addons/bird-global-classifier/index.js
1782
+ var require_bird_global_classifier = __commonJS({
1783
+ "src/addons/bird-global-classifier/index.js"(exports) {
1784
+ "use strict";
1785
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
1786
+ if (k2 === void 0) k2 = k;
1787
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1788
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1789
+ desc = { enumerable: true, get: function() {
1790
+ return m[k];
1791
+ } };
1792
+ }
1793
+ Object.defineProperty(o, k2, desc);
1794
+ }) : (function(o, m, k, k2) {
1795
+ if (k2 === void 0) k2 = k;
1796
+ o[k2] = m[k];
1797
+ }));
1798
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
1799
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1800
+ }) : function(o, v) {
1801
+ o["default"] = v;
1802
+ });
1803
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
1804
+ var ownKeys = function(o) {
1805
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1806
+ var ar = [];
1807
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1808
+ return ar;
1809
+ };
1810
+ return ownKeys(o);
1811
+ };
1812
+ return function(mod) {
1813
+ if (mod && mod.__esModule) return mod;
1814
+ var result = {};
1815
+ if (mod != null) {
1816
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1817
+ }
1818
+ __setModuleDefault(result, mod);
1819
+ return result;
1820
+ };
1821
+ })();
1822
+ Object.defineProperty(exports, "__esModule", { value: true });
1823
+ var animal_classification_models_js_1 = require_animal_classification_models();
1824
+ var image_utils_js_1 = require_image_utils();
1825
+ var engine_resolver_js_1 = require_engine_resolver();
1826
+ var fs = __importStar(__require("fs"));
1827
+ var path = __importStar(__require("path"));
1828
+ var SPECIES_LABEL = { id: "species", name: "Bird Species" };
1829
+ var SPECIES_LABELS = [SPECIES_LABEL];
1830
+ var BIRD_CLASS_MAP = { mapping: {}, preserveOriginal: true };
1831
+ function loadLabels(modelsDir, modelId) {
1832
+ const labelNames = [
1833
+ `camstack-${modelId}-labels.json`,
1834
+ `camstack-bird-species-525-labels.json`
1835
+ ];
1836
+ for (const name of labelNames) {
1837
+ const labelPath = path.join(modelsDir, name);
1838
+ if (fs.existsSync(labelPath)) {
1839
+ const raw = fs.readFileSync(labelPath, "utf-8");
1840
+ return JSON.parse(raw);
1841
+ }
1842
+ }
1843
+ throw new Error(`BirdGlobalClassifierAddon: labels JSON not found in ${modelsDir}`);
200
1844
  }
201
- },
202
- {
203
- id: "ppocr-v5-rec-mobile",
204
- name: "PP-OCRv5 Recognition Mobile",
205
- description: "PP-OCRv5 mobile text recognition \u2014 100+ languages, CTC decoding",
206
- inputSize: { width: 320, height: 48 },
207
- labels: OCR_TEXT_LABELS,
208
- formats: {
209
- onnx: {
210
- url: hfModelUrl(HF_REPO, "generalOcr/ppocr-v5/onnx/camstack-ppocr-v5-rec-mobile.onnx"),
211
- sizeMB: 8
212
- },
213
- coreml: {
214
- url: hfModelUrl(HF_REPO, "generalOcr/ppocr-v5/coreml/camstack-ppocr-v5-rec-mobile.mlpackage"),
215
- sizeMB: 4,
216
- isDirectory: true,
217
- files: [
218
- "Manifest.json",
219
- "Data/com.apple.CoreML/model.mlmodel",
220
- "Data/com.apple.CoreML/weights/weight.bin"
221
- ],
222
- runtimes: ["python"]
223
- },
224
- openvino: {
225
- url: hfModelUrl(HF_REPO, "generalOcr/ppocr-v5/openvino/camstack-ppocr-v5-rec-mobile.xml"),
226
- sizeMB: 4,
227
- runtimes: ["python"]
1845
+ function softmax(logits) {
1846
+ const max = logits.reduce((a, b) => Math.max(a, b), -Infinity);
1847
+ const exps = logits.map((v) => Math.exp(v - max));
1848
+ const sum = exps.reduce((a, b) => a + b, 0);
1849
+ return exps.map((v) => v / sum);
1850
+ }
1851
+ var BirdGlobalClassifierAddon = class {
1852
+ id = "bird-global-classifier";
1853
+ slot = "classifier";
1854
+ inputClasses = ["animal"];
1855
+ outputClasses = ["species:*"];
1856
+ slotPriority = 0;
1857
+ requiredSteps = [];
1858
+ manifest = {
1859
+ id: "bird-global-classifier",
1860
+ name: "Bird Classifier (Global, 525 species)",
1861
+ version: "0.1.0",
1862
+ description: "EfficientNet \u2014 525 worldwide bird species (MIT license, ONNX only)",
1863
+ slot: "classifier",
1864
+ labelOutputType: "classification",
1865
+ inputClasses: ["animal"],
1866
+ outputClasses: ["species:*"],
1867
+ supportsCustomModels: false,
1868
+ mayRequirePython: false,
1869
+ defaultConfig: {
1870
+ modelId: "bird-species-525",
1871
+ runtime: "node",
1872
+ backend: "cpu",
1873
+ minConfidence: 0.3
1874
+ }
1875
+ };
1876
+ engine = null;
1877
+ modelEntry;
1878
+ labels = [];
1879
+ minConfidence = 0.3;
1880
+ resolvedConfig = null;
1881
+ ctx = null;
1882
+ getModelRequirements() {
1883
+ return animal_classification_models_js_1.BIRD_SPECIES_MODELS.map((m) => ({
1884
+ modelId: m.id,
1885
+ name: m.name,
1886
+ minRAM_MB: 120,
1887
+ accuracyScore: 80,
1888
+ formats: Object.keys(m.formats)
1889
+ }));
228
1890
  }
229
- },
230
- extraFiles: [
231
- {
232
- url: hfModelUrl(HF_REPO, "generalOcr/ppocr-v5/camstack-ppocr-v5-keys.txt"),
233
- filename: "camstack-ppocr-v5-keys.txt",
234
- sizeMB: 0.1
1891
+ configure(config) {
1892
+ this.resolvedConfig = config;
1893
+ }
1894
+ async initialize(ctx) {
1895
+ this.ctx = ctx;
1896
+ const cfg = ctx.addonConfig;
1897
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "bird-species-525";
1898
+ this.minConfidence = cfg["minConfidence"] ?? 0.3;
1899
+ const entry = animal_classification_models_js_1.BIRD_SPECIES_MODELS.find((m) => m.id === modelId);
1900
+ if (!entry) {
1901
+ throw new Error(`BirdGlobalClassifierAddon: unknown modelId "${modelId}"`);
1902
+ }
1903
+ this.modelEntry = entry;
1904
+ }
1905
+ async classify(input) {
1906
+ if (!this.engine)
1907
+ await this.ensureEngine();
1908
+ const start = Date.now();
1909
+ const { width: inputW, height: inputH } = this.modelEntry.inputSize;
1910
+ const animalCrop = await (0, image_utils_js_1.cropRegion)(input.frame.data, input.roi);
1911
+ const normalized = await (0, image_utils_js_1.resizeAndNormalize)(animalCrop, inputW, inputH, "imagenet", "nchw");
1912
+ const rawOutput = await this.engine.run(normalized, [1, 3, inputH, inputW]);
1913
+ const probs = softmax(rawOutput);
1914
+ let maxIdx = 0;
1915
+ let maxScore = probs[0] ?? 0;
1916
+ for (let i = 1; i < probs.length; i++) {
1917
+ const score = probs[i] ?? 0;
1918
+ if (score > maxScore) {
1919
+ maxScore = score;
1920
+ maxIdx = i;
1921
+ }
1922
+ }
1923
+ if (maxScore < this.minConfidence) {
1924
+ return {
1925
+ classifications: [],
1926
+ inferenceMs: Date.now() - start,
1927
+ modelId: this.modelEntry.id
1928
+ };
1929
+ }
1930
+ const label = this.labels[maxIdx] ?? `species_${maxIdx}`;
1931
+ return {
1932
+ classifications: [
1933
+ {
1934
+ class: label,
1935
+ score: maxScore
1936
+ }
1937
+ ],
1938
+ inferenceMs: Date.now() - start,
1939
+ modelId: this.modelEntry.id
1940
+ };
1941
+ }
1942
+ async ensureEngine() {
1943
+ const config = this.resolvedConfig;
1944
+ const modelId = config?.modelId ?? this.modelEntry.id;
1945
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
1946
+ const backend = config?.backend ?? "cpu";
1947
+ const format = config?.format ?? "onnx";
1948
+ const entry = animal_classification_models_js_1.BIRD_SPECIES_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
1949
+ this.modelEntry = entry;
1950
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
1951
+ if (this.ctx.models) {
1952
+ await this.ctx.models.ensure(modelId, format);
1953
+ }
1954
+ this.labels = loadLabels(modelsDir, modelId);
1955
+ const resolved = await (0, engine_resolver_js_1.resolveEngine)({
1956
+ runtime,
1957
+ backend,
1958
+ modelEntry: entry,
1959
+ modelsDir,
1960
+ models: this.ctx.models
1961
+ });
1962
+ this.engine = resolved.engine;
1963
+ }
1964
+ async shutdown() {
1965
+ await this.engine?.dispose();
1966
+ }
1967
+ getConfigSchema() {
1968
+ return {
1969
+ sections: [
1970
+ {
1971
+ id: "model",
1972
+ title: "Model",
1973
+ columns: 1,
1974
+ fields: [
1975
+ {
1976
+ key: "modelId",
1977
+ label: "Model",
1978
+ type: "model-selector",
1979
+ catalog: [...animal_classification_models_js_1.BIRD_SPECIES_MODELS],
1980
+ allowCustom: false,
1981
+ allowConversion: false,
1982
+ acceptFormats: ["onnx", "coreml", "openvino"],
1983
+ requiredMetadata: ["inputSize", "labels"],
1984
+ outputFormatHint: "classification"
1985
+ }
1986
+ ]
1987
+ },
1988
+ {
1989
+ id: "runtime",
1990
+ title: "Runtime",
1991
+ columns: 2,
1992
+ fields: [
1993
+ {
1994
+ key: "runtime",
1995
+ label: "Runtime",
1996
+ type: "select",
1997
+ options: [
1998
+ { value: "auto", label: "Auto" },
1999
+ { value: "onnx", label: "ONNX Runtime" },
2000
+ { value: "coreml", label: "CoreML (Apple)" },
2001
+ { value: "openvino", label: "OpenVINO (Intel)" }
2002
+ ]
2003
+ },
2004
+ {
2005
+ key: "backend",
2006
+ label: "Backend",
2007
+ type: "select",
2008
+ showWhen: { field: "runtime", equals: "onnx" },
2009
+ options: [
2010
+ { value: "auto", label: "Auto" },
2011
+ { value: "cpu", label: "CPU" },
2012
+ { value: "coreml", label: "CoreML" },
2013
+ { value: "cuda", label: "CUDA (NVIDIA)" }
2014
+ ]
2015
+ }
2016
+ ]
2017
+ },
2018
+ {
2019
+ id: "thresholds",
2020
+ title: "Classification Settings",
2021
+ columns: 1,
2022
+ fields: [
2023
+ {
2024
+ key: "minConfidence",
2025
+ label: "Minimum Confidence",
2026
+ type: "slider",
2027
+ min: 0.05,
2028
+ max: 1,
2029
+ step: 0.05,
2030
+ default: 0.3
2031
+ }
2032
+ ]
2033
+ }
2034
+ ]
2035
+ };
2036
+ }
2037
+ getClassMap() {
2038
+ return BIRD_CLASS_MAP;
2039
+ }
2040
+ getModelCatalog() {
2041
+ return [...animal_classification_models_js_1.BIRD_SPECIES_MODELS];
235
2042
  }
236
- ]
2043
+ getAvailableModels() {
2044
+ return [];
2045
+ }
2046
+ getActiveLabels() {
2047
+ return SPECIES_LABELS;
2048
+ }
2049
+ async probe() {
2050
+ return {
2051
+ available: true,
2052
+ runtime: this.engine?.runtime ?? "onnx",
2053
+ device: this.engine?.device ?? "cpu",
2054
+ capabilities: ["fp32"]
2055
+ };
2056
+ }
2057
+ };
2058
+ exports.default = BirdGlobalClassifierAddon;
2059
+ }
2060
+ });
2061
+
2062
+ // src/addons/bird-nabirds-classifier/index.js
2063
+ var require_bird_nabirds_classifier = __commonJS({
2064
+ "src/addons/bird-nabirds-classifier/index.js"(exports) {
2065
+ "use strict";
2066
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
2067
+ if (k2 === void 0) k2 = k;
2068
+ var desc = Object.getOwnPropertyDescriptor(m, k);
2069
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
2070
+ desc = { enumerable: true, get: function() {
2071
+ return m[k];
2072
+ } };
2073
+ }
2074
+ Object.defineProperty(o, k2, desc);
2075
+ }) : (function(o, m, k, k2) {
2076
+ if (k2 === void 0) k2 = k;
2077
+ o[k2] = m[k];
2078
+ }));
2079
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
2080
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
2081
+ }) : function(o, v) {
2082
+ o["default"] = v;
2083
+ });
2084
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
2085
+ var ownKeys = function(o) {
2086
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
2087
+ var ar = [];
2088
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
2089
+ return ar;
2090
+ };
2091
+ return ownKeys(o);
2092
+ };
2093
+ return function(mod) {
2094
+ if (mod && mod.__esModule) return mod;
2095
+ var result = {};
2096
+ if (mod != null) {
2097
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
2098
+ }
2099
+ __setModuleDefault(result, mod);
2100
+ return result;
2101
+ };
2102
+ })();
2103
+ Object.defineProperty(exports, "__esModule", { value: true });
2104
+ var animal_classification_models_js_1 = require_animal_classification_models();
2105
+ var image_utils_js_1 = require_image_utils();
2106
+ var engine_resolver_js_1 = require_engine_resolver();
2107
+ var fs = __importStar(__require("fs"));
2108
+ var path = __importStar(__require("path"));
2109
+ var SPECIES_LABEL = { id: "species", name: "Bird Species" };
2110
+ var SPECIES_LABELS = [SPECIES_LABEL];
2111
+ var BIRD_CLASS_MAP = { mapping: {}, preserveOriginal: true };
2112
+ function loadLabels(modelsDir, modelId) {
2113
+ const labelNames = [
2114
+ `camstack-${modelId}-labels.json`,
2115
+ `camstack-bird-nabirds-404-labels.json`
2116
+ ];
2117
+ for (const name of labelNames) {
2118
+ const labelPath = path.join(modelsDir, name);
2119
+ if (fs.existsSync(labelPath)) {
2120
+ const raw = fs.readFileSync(labelPath, "utf-8");
2121
+ return JSON.parse(raw);
2122
+ }
2123
+ }
2124
+ throw new Error(`BirdNABirdsClassifierAddon: labels JSON not found in ${modelsDir}`);
2125
+ }
2126
+ function softmax(logits) {
2127
+ const max = logits.reduce((a, b) => Math.max(a, b), -Infinity);
2128
+ const exps = logits.map((v) => Math.exp(v - max));
2129
+ const sum = exps.reduce((a, b) => a + b, 0);
2130
+ return exps.map((v) => v / sum);
2131
+ }
2132
+ var BirdNABirdsClassifierAddon = class {
2133
+ id = "bird-nabirds-classifier";
2134
+ slot = "classifier";
2135
+ inputClasses = ["animal"];
2136
+ outputClasses = ["species:*"];
2137
+ slotPriority = 0;
2138
+ requiredSteps = [];
2139
+ manifest = {
2140
+ id: "bird-nabirds-classifier",
2141
+ name: "Bird Classifier (NABirds, 404 species)",
2142
+ version: "0.1.0",
2143
+ description: "ResNet50 \u2014 404 North American bird species (NABirds dataset, ONNX + CoreML + OpenVINO)",
2144
+ slot: "classifier",
2145
+ labelOutputType: "classification",
2146
+ inputClasses: ["animal"],
2147
+ outputClasses: ["species:*"],
2148
+ supportsCustomModels: false,
2149
+ mayRequirePython: false,
2150
+ defaultConfig: {
2151
+ modelId: "bird-nabirds-404",
2152
+ runtime: "node",
2153
+ backend: "cpu",
2154
+ minConfidence: 0.3
2155
+ }
2156
+ };
2157
+ engine = null;
2158
+ modelEntry;
2159
+ labels = [];
2160
+ minConfidence = 0.3;
2161
+ allowedSpecies;
2162
+ resolvedConfig = null;
2163
+ ctx = null;
2164
+ getModelRequirements() {
2165
+ return animal_classification_models_js_1.BIRD_NABIRDS_MODELS.map((m) => ({
2166
+ modelId: m.id,
2167
+ name: m.name,
2168
+ minRAM_MB: 300,
2169
+ accuracyScore: 80,
2170
+ formats: Object.keys(m.formats)
2171
+ }));
2172
+ }
2173
+ configure(config) {
2174
+ this.resolvedConfig = config;
2175
+ }
2176
+ async initialize(ctx) {
2177
+ this.ctx = ctx;
2178
+ const cfg = ctx.addonConfig;
2179
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "bird-nabirds-404";
2180
+ this.minConfidence = cfg["minConfidence"] ?? 0.3;
2181
+ this.allowedSpecies = cfg["allowedSpecies"];
2182
+ const entry = animal_classification_models_js_1.BIRD_NABIRDS_MODELS.find((m) => m.id === modelId);
2183
+ if (!entry) {
2184
+ throw new Error(`BirdNABirdsClassifierAddon: unknown modelId "${modelId}"`);
2185
+ }
2186
+ this.modelEntry = entry;
2187
+ }
2188
+ applyRegionFilter(scores, labels) {
2189
+ if (!this.allowedSpecies || this.allowedSpecies.length === 0)
2190
+ return;
2191
+ const allowedSet = new Set(this.allowedSpecies.map((s) => s.toLowerCase()));
2192
+ for (let i = 0; i < scores.length; i++) {
2193
+ if (!allowedSet.has(labels[i].toLowerCase())) {
2194
+ scores[i] = 0;
2195
+ }
2196
+ }
2197
+ }
2198
+ async classify(input) {
2199
+ if (!this.engine)
2200
+ await this.ensureEngine();
2201
+ const start = Date.now();
2202
+ const { width: inputW, height: inputH } = this.modelEntry.inputSize;
2203
+ const animalCrop = await (0, image_utils_js_1.cropRegion)(input.frame.data, input.roi);
2204
+ const normalized = await (0, image_utils_js_1.resizeAndNormalize)(animalCrop, inputW, inputH, "imagenet", "nchw");
2205
+ const rawOutput = await this.engine.run(normalized, [1, 3, inputH, inputW]);
2206
+ const probs = softmax(rawOutput);
2207
+ this.applyRegionFilter(probs, this.labels);
2208
+ const filteredSum = probs.reduce((a, b) => a + b, 0);
2209
+ if (filteredSum > 0) {
2210
+ for (let i = 0; i < probs.length; i++) {
2211
+ probs[i] = (probs[i] ?? 0) / filteredSum;
2212
+ }
2213
+ }
2214
+ let maxIdx = 0;
2215
+ let maxScore = probs[0] ?? 0;
2216
+ for (let i = 1; i < probs.length; i++) {
2217
+ const score = probs[i] ?? 0;
2218
+ if (score > maxScore) {
2219
+ maxScore = score;
2220
+ maxIdx = i;
2221
+ }
2222
+ }
2223
+ if (maxScore < this.minConfidence) {
2224
+ return {
2225
+ classifications: [],
2226
+ inferenceMs: Date.now() - start,
2227
+ modelId: this.modelEntry.id
2228
+ };
2229
+ }
2230
+ const label = this.labels[maxIdx] ?? `species_${maxIdx}`;
2231
+ return {
2232
+ classifications: [
2233
+ {
2234
+ class: label,
2235
+ score: maxScore
2236
+ }
2237
+ ],
2238
+ inferenceMs: Date.now() - start,
2239
+ modelId: this.modelEntry.id
2240
+ };
2241
+ }
2242
+ async ensureEngine() {
2243
+ const config = this.resolvedConfig;
2244
+ const modelId = config?.modelId ?? this.modelEntry.id;
2245
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
2246
+ const backend = config?.backend ?? "cpu";
2247
+ const format = config?.format ?? "onnx";
2248
+ const entry = animal_classification_models_js_1.BIRD_NABIRDS_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
2249
+ this.modelEntry = entry;
2250
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
2251
+ if (this.ctx.models) {
2252
+ await this.ctx.models.ensure(modelId, format);
2253
+ }
2254
+ this.labels = loadLabels(modelsDir, modelId);
2255
+ const resolved = await (0, engine_resolver_js_1.resolveEngine)({
2256
+ runtime,
2257
+ backend,
2258
+ modelEntry: entry,
2259
+ modelsDir,
2260
+ models: this.ctx.models
2261
+ });
2262
+ this.engine = resolved.engine;
2263
+ }
2264
+ async shutdown() {
2265
+ await this.engine?.dispose();
2266
+ }
2267
+ getConfigSchema() {
2268
+ return {
2269
+ sections: [
2270
+ {
2271
+ id: "model",
2272
+ title: "Model",
2273
+ columns: 1,
2274
+ fields: [
2275
+ {
2276
+ key: "modelId",
2277
+ label: "Model",
2278
+ type: "model-selector",
2279
+ catalog: [...animal_classification_models_js_1.BIRD_NABIRDS_MODELS],
2280
+ allowCustom: false,
2281
+ allowConversion: false,
2282
+ acceptFormats: ["onnx", "coreml", "openvino"],
2283
+ requiredMetadata: ["inputSize", "labels"],
2284
+ outputFormatHint: "classification"
2285
+ }
2286
+ ]
2287
+ },
2288
+ {
2289
+ id: "runtime",
2290
+ title: "Runtime",
2291
+ columns: 2,
2292
+ fields: [
2293
+ {
2294
+ key: "runtime",
2295
+ label: "Runtime",
2296
+ type: "select",
2297
+ options: [
2298
+ { value: "auto", label: "Auto" },
2299
+ { value: "onnx", label: "ONNX Runtime" },
2300
+ { value: "coreml", label: "CoreML (Apple)" },
2301
+ { value: "openvino", label: "OpenVINO (Intel)" }
2302
+ ]
2303
+ },
2304
+ {
2305
+ key: "backend",
2306
+ label: "Backend",
2307
+ type: "select",
2308
+ showWhen: { field: "runtime", equals: "onnx" },
2309
+ options: [
2310
+ { value: "auto", label: "Auto" },
2311
+ { value: "cpu", label: "CPU" },
2312
+ { value: "coreml", label: "CoreML" },
2313
+ { value: "cuda", label: "CUDA (NVIDIA)" }
2314
+ ]
2315
+ }
2316
+ ]
2317
+ },
2318
+ {
2319
+ id: "thresholds",
2320
+ title: "Classification Settings",
2321
+ columns: 1,
2322
+ fields: [
2323
+ {
2324
+ key: "minConfidence",
2325
+ label: "Minimum Confidence",
2326
+ type: "slider",
2327
+ min: 0.05,
2328
+ max: 1,
2329
+ step: 0.05,
2330
+ default: 0.3
2331
+ }
2332
+ ]
2333
+ },
2334
+ {
2335
+ id: "region",
2336
+ title: "Regional Filter",
2337
+ columns: 1,
2338
+ fields: [
2339
+ {
2340
+ key: "regionFilter",
2341
+ label: "Region Preset",
2342
+ type: "select",
2343
+ options: [
2344
+ { value: "", label: "None (all 404 species)" },
2345
+ { value: "north-america-east", label: "North America \u2014 Eastern" },
2346
+ { value: "north-america-west", label: "North America \u2014 Western" },
2347
+ { value: "north-america-south", label: "North America \u2014 Southern" }
2348
+ ]
2349
+ },
2350
+ {
2351
+ key: "allowedSpecies",
2352
+ label: "Custom Allowed Species (comma-separated)",
2353
+ type: "text"
2354
+ }
2355
+ ]
2356
+ }
2357
+ ]
2358
+ };
2359
+ }
2360
+ getClassMap() {
2361
+ return BIRD_CLASS_MAP;
2362
+ }
2363
+ getModelCatalog() {
2364
+ return [...animal_classification_models_js_1.BIRD_NABIRDS_MODELS];
2365
+ }
2366
+ getAvailableModels() {
2367
+ return [];
2368
+ }
2369
+ getActiveLabels() {
2370
+ return SPECIES_LABELS;
2371
+ }
2372
+ async probe() {
2373
+ return {
2374
+ available: true,
2375
+ runtime: this.engine?.runtime ?? "onnx",
2376
+ device: this.engine?.device ?? "cpu",
2377
+ capabilities: ["fp32"]
2378
+ };
2379
+ }
2380
+ };
2381
+ exports.default = BirdNABirdsClassifierAddon;
237
2382
  }
238
- ];
2383
+ });
2384
+
2385
+ // src/addons/animal-classifier/index.js
2386
+ var require_animal_classifier = __commonJS({
2387
+ "src/addons/animal-classifier/index.js"(exports) {
2388
+ "use strict";
2389
+ Object.defineProperty(exports, "__esModule", { value: true });
2390
+ var animal_classification_models_js_1 = require_animal_classification_models();
2391
+ var image_utils_js_1 = require_image_utils();
2392
+ var engine_resolver_js_1 = require_engine_resolver();
2393
+ var ANIMAL_TYPE_LABEL = { id: "animal-type", name: "Animal Type" };
2394
+ var ANIMAL_TYPE_LABELS = [ANIMAL_TYPE_LABEL];
2395
+ var ANIMAL_CLASS_MAP = { mapping: {}, preserveOriginal: true };
2396
+ var ANIMAL_10_CLASSES = [
2397
+ "cat",
2398
+ "cow",
2399
+ "dog",
2400
+ "dolphin",
2401
+ "eagle",
2402
+ "giant panda",
2403
+ "horse",
2404
+ "monkey",
2405
+ "sheep",
2406
+ "spider"
2407
+ ];
2408
+ function softmax(logits) {
2409
+ const max = logits.reduce((a, b) => Math.max(a, b), -Infinity);
2410
+ const exps = logits.map((v) => Math.exp(v - max));
2411
+ const sum = exps.reduce((a, b) => a + b, 0);
2412
+ return exps.map((v) => v / sum);
2413
+ }
2414
+ var AnimalClassifierAddon = class {
2415
+ id = "animal-classifier";
2416
+ slot = "classifier";
2417
+ inputClasses = ["animal"];
2418
+ outputClasses = ["animal-type:*"];
2419
+ slotPriority = 0;
2420
+ requiredSteps = [];
2421
+ manifest = {
2422
+ id: "animal-classifier",
2423
+ name: "Animal Classifier",
2424
+ version: "0.1.0",
2425
+ description: "ViT-based animal type classifier \u2014 10 common species",
2426
+ slot: "classifier",
2427
+ labelOutputType: "classification",
2428
+ inputClasses: ["animal"],
2429
+ outputClasses: ["animal-type:*"],
2430
+ supportsCustomModels: false,
2431
+ mayRequirePython: false,
2432
+ defaultConfig: {
2433
+ modelId: "animals-10",
2434
+ runtime: "node",
2435
+ backend: "cpu",
2436
+ minConfidence: 0.3
2437
+ }
2438
+ };
2439
+ engine = null;
2440
+ modelEntry;
2441
+ minConfidence = 0.3;
2442
+ resolvedConfig = null;
2443
+ ctx = null;
2444
+ getModelRequirements() {
2445
+ return animal_classification_models_js_1.ANIMAL_TYPE_MODELS.map((m) => ({
2446
+ modelId: m.id,
2447
+ name: m.name,
2448
+ minRAM_MB: 800,
2449
+ accuracyScore: 75,
2450
+ formats: Object.keys(m.formats)
2451
+ }));
2452
+ }
2453
+ configure(config) {
2454
+ this.resolvedConfig = config;
2455
+ }
2456
+ async initialize(ctx) {
2457
+ this.ctx = ctx;
2458
+ const cfg = ctx.addonConfig;
2459
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "animals-10";
2460
+ this.minConfidence = cfg["minConfidence"] ?? 0.3;
2461
+ const entry = animal_classification_models_js_1.ANIMAL_TYPE_MODELS.find((m) => m.id === modelId);
2462
+ if (!entry) {
2463
+ throw new Error(`AnimalClassifierAddon: unknown modelId "${modelId}"`);
2464
+ }
2465
+ this.modelEntry = entry;
2466
+ }
2467
+ async classify(input) {
2468
+ if (!this.engine)
2469
+ await this.ensureEngine();
2470
+ const start = Date.now();
2471
+ const { width: inputW, height: inputH } = this.modelEntry.inputSize;
2472
+ const animalCrop = await (0, image_utils_js_1.cropRegion)(input.frame.data, input.roi);
2473
+ const normalized = await (0, image_utils_js_1.resizeAndNormalize)(animalCrop, inputW, inputH, "imagenet", "nchw");
2474
+ const rawOutput = await this.engine.run(normalized, [1, 3, inputH, inputW]);
2475
+ const probs = softmax(rawOutput);
2476
+ let maxIdx = 0;
2477
+ let maxScore = probs[0] ?? 0;
2478
+ for (let i = 1; i < probs.length; i++) {
2479
+ const score = probs[i] ?? 0;
2480
+ if (score > maxScore) {
2481
+ maxScore = score;
2482
+ maxIdx = i;
2483
+ }
2484
+ }
2485
+ if (maxScore < this.minConfidence) {
2486
+ return {
2487
+ classifications: [],
2488
+ inferenceMs: Date.now() - start,
2489
+ modelId: this.modelEntry.id
2490
+ };
2491
+ }
2492
+ const label = ANIMAL_10_CLASSES[maxIdx] ?? `animal_${maxIdx}`;
2493
+ return {
2494
+ classifications: [
2495
+ {
2496
+ class: label,
2497
+ score: maxScore
2498
+ }
2499
+ ],
2500
+ inferenceMs: Date.now() - start,
2501
+ modelId: this.modelEntry.id
2502
+ };
2503
+ }
2504
+ async ensureEngine() {
2505
+ const config = this.resolvedConfig;
2506
+ const modelId = config?.modelId ?? this.modelEntry.id;
2507
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
2508
+ const backend = config?.backend ?? "cpu";
2509
+ const format = config?.format ?? "onnx";
2510
+ const entry = animal_classification_models_js_1.ANIMAL_TYPE_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
2511
+ this.modelEntry = entry;
2512
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
2513
+ if (this.ctx.models) {
2514
+ await this.ctx.models.ensure(modelId, format);
2515
+ }
2516
+ const resolved = await (0, engine_resolver_js_1.resolveEngine)({
2517
+ runtime,
2518
+ backend,
2519
+ modelEntry: entry,
2520
+ modelsDir,
2521
+ models: this.ctx.models
2522
+ });
2523
+ this.engine = resolved.engine;
2524
+ }
2525
+ async shutdown() {
2526
+ await this.engine?.dispose();
2527
+ }
2528
+ getConfigSchema() {
2529
+ return {
2530
+ sections: [
2531
+ {
2532
+ id: "model",
2533
+ title: "Model",
2534
+ columns: 1,
2535
+ fields: [
2536
+ {
2537
+ key: "modelId",
2538
+ label: "Model",
2539
+ type: "model-selector",
2540
+ catalog: [...animal_classification_models_js_1.ANIMAL_TYPE_MODELS],
2541
+ allowCustom: false,
2542
+ allowConversion: false,
2543
+ acceptFormats: ["onnx", "coreml", "openvino"],
2544
+ requiredMetadata: ["inputSize", "labels"],
2545
+ outputFormatHint: "classification"
2546
+ }
2547
+ ]
2548
+ },
2549
+ {
2550
+ id: "runtime",
2551
+ title: "Runtime",
2552
+ columns: 2,
2553
+ fields: [
2554
+ {
2555
+ key: "runtime",
2556
+ label: "Runtime",
2557
+ type: "select",
2558
+ options: [
2559
+ { value: "auto", label: "Auto" },
2560
+ { value: "onnx", label: "ONNX Runtime" },
2561
+ { value: "coreml", label: "CoreML (Apple)" },
2562
+ { value: "openvino", label: "OpenVINO (Intel)" }
2563
+ ]
2564
+ },
2565
+ {
2566
+ key: "backend",
2567
+ label: "Backend",
2568
+ type: "select",
2569
+ showWhen: { field: "runtime", equals: "onnx" },
2570
+ options: [
2571
+ { value: "auto", label: "Auto" },
2572
+ { value: "cpu", label: "CPU" },
2573
+ { value: "coreml", label: "CoreML" },
2574
+ { value: "cuda", label: "CUDA (NVIDIA)" }
2575
+ ]
2576
+ }
2577
+ ]
2578
+ },
2579
+ {
2580
+ id: "thresholds",
2581
+ title: "Classification Settings",
2582
+ columns: 1,
2583
+ fields: [
2584
+ {
2585
+ key: "minConfidence",
2586
+ label: "Minimum Confidence",
2587
+ type: "slider",
2588
+ min: 0.05,
2589
+ max: 1,
2590
+ step: 0.05,
2591
+ default: 0.3
2592
+ }
2593
+ ]
2594
+ }
2595
+ ]
2596
+ };
2597
+ }
2598
+ getClassMap() {
2599
+ return ANIMAL_CLASS_MAP;
2600
+ }
2601
+ getModelCatalog() {
2602
+ return [...animal_classification_models_js_1.ANIMAL_TYPE_MODELS];
2603
+ }
2604
+ getAvailableModels() {
2605
+ return [];
2606
+ }
2607
+ getActiveLabels() {
2608
+ return ANIMAL_TYPE_LABELS;
2609
+ }
2610
+ async probe() {
2611
+ return {
2612
+ available: true,
2613
+ runtime: this.engine?.runtime ?? "onnx",
2614
+ device: this.engine?.device ?? "cpu",
2615
+ capabilities: ["fp32"]
2616
+ };
2617
+ }
2618
+ };
2619
+ exports.default = AnimalClassifierAddon;
2620
+ }
2621
+ });
2622
+
2623
+ // src/index.ts
2624
+ var src_exports = {};
2625
+ __export(src_exports, {
2626
+ AnimalClassifierAddon: () => import_animal_classifier.default,
2627
+ AudioClassificationAddon: () => import_audio_classification.default,
2628
+ BirdGlobalClassifierAddon: () => import_bird_global_classifier.default,
2629
+ BirdNABirdsClassifierAddon: () => import_bird_nabirds_classifier.default,
2630
+ FaceDetectionAddon: () => import_face_detection.default,
2631
+ FaceRecognitionAddon: () => import_face_recognition.default,
2632
+ NodeInferenceEngine: () => import_node_engine.NodeInferenceEngine,
2633
+ ObjectDetectionAddon: () => import_object_detection.default,
2634
+ PlateDetectionAddon: () => import_plate_detection.default,
2635
+ PlateRecognitionAddon: () => import_plate_recognition.default,
2636
+ PythonInferenceEngine: () => import_python_engine.PythonInferenceEngine,
2637
+ cosineSimilarity: () => import_arcface.cosineSimilarity,
2638
+ cropRegion: () => import_image_utils.cropRegion,
2639
+ ctcDecode: () => import_paddleocr.ctcDecode,
2640
+ detectMotion: () => import_frame_diff.detectMotion,
2641
+ iou: () => import_yolo.iou,
2642
+ jpegToRgb: () => import_image_utils.jpegToRgb,
2643
+ l2Normalize: () => import_arcface.l2Normalize,
2644
+ letterbox: () => import_image_utils.letterbox,
2645
+ nms: () => import_yolo.nms,
2646
+ probeOnnxBackends: () => import_engine_resolver.probeOnnxBackends,
2647
+ resizeAndNormalize: () => import_image_utils.resizeAndNormalize,
2648
+ resolveEngine: () => import_engine_resolver.resolveEngine,
2649
+ rgbToGrayscale: () => import_image_utils.rgbToGrayscale,
2650
+ scrfdPostprocess: () => import_scrfd.scrfdPostprocess,
2651
+ yamnetPostprocess: () => import_yamnet.yamnetPostprocess,
2652
+ yoloPostprocess: () => import_yolo.yoloPostprocess
2653
+ });
2654
+ var import_image_utils = __toESM(require_image_utils());
2655
+ var import_yolo = __toESM(require_yolo());
2656
+ var import_scrfd = __toESM(require_scrfd());
2657
+ var import_arcface = __toESM(require_arcface());
2658
+ var import_paddleocr = __toESM(require_paddleocr());
2659
+ var import_yamnet = __toESM(require_yamnet());
2660
+ var import_node_engine = __toESM(require_node_engine());
2661
+ var import_python_engine = __toESM(require_python_engine());
2662
+ var import_engine_resolver = __toESM(require_engine_resolver());
2663
+ var import_frame_diff = __toESM(require_frame_diff());
2664
+ __reExport(src_exports, __toESM(require_catalogs()));
2665
+ var import_object_detection = __toESM(require_object_detection());
2666
+ var import_face_detection = __toESM(require_face_detection());
2667
+ var import_face_recognition = __toESM(require_face_recognition());
2668
+ var import_plate_detection = __toESM(require_plate_detection());
2669
+ var import_plate_recognition = __toESM(require_plate_recognition());
2670
+ var import_audio_classification = __toESM(require_audio_classification());
2671
+ var import_bird_global_classifier = __toESM(require_bird_global_classifier());
2672
+ var import_bird_nabirds_classifier = __toESM(require_bird_nabirds_classifier());
2673
+ var import_animal_classifier = __toESM(require_animal_classifier());
2674
+ var export_AnimalClassifierAddon = import_animal_classifier.default;
2675
+ var export_AudioClassificationAddon = import_audio_classification.default;
2676
+ var export_BirdGlobalClassifierAddon = import_bird_global_classifier.default;
2677
+ var export_BirdNABirdsClassifierAddon = import_bird_nabirds_classifier.default;
2678
+ var export_FaceDetectionAddon = import_face_detection.default;
2679
+ var export_FaceRecognitionAddon = import_face_recognition.default;
2680
+ var export_NodeInferenceEngine = import_node_engine.NodeInferenceEngine;
2681
+ var export_ObjectDetectionAddon = import_object_detection.default;
2682
+ var export_PlateDetectionAddon = import_plate_detection.default;
2683
+ var export_PlateRecognitionAddon = import_plate_recognition.default;
2684
+ var export_PythonInferenceEngine = import_python_engine.PythonInferenceEngine;
2685
+ var export_cosineSimilarity = import_arcface.cosineSimilarity;
2686
+ var export_cropRegion = import_image_utils.cropRegion;
2687
+ var export_ctcDecode = import_paddleocr.ctcDecode;
2688
+ var export_detectMotion = import_frame_diff.detectMotion;
2689
+ var export_iou = import_yolo.iou;
2690
+ var export_jpegToRgb = import_image_utils.jpegToRgb;
2691
+ var export_l2Normalize = import_arcface.l2Normalize;
2692
+ var export_letterbox = import_image_utils.letterbox;
2693
+ var export_nms = import_yolo.nms;
2694
+ var export_probeOnnxBackends = import_engine_resolver.probeOnnxBackends;
2695
+ var export_resizeAndNormalize = import_image_utils.resizeAndNormalize;
2696
+ var export_resolveEngine = import_engine_resolver.resolveEngine;
2697
+ var export_rgbToGrayscale = import_image_utils.rgbToGrayscale;
2698
+ var export_scrfdPostprocess = import_scrfd.scrfdPostprocess;
2699
+ var export_yamnetPostprocess = import_yamnet.yamnetPostprocess;
2700
+ var export_yoloPostprocess = import_yolo.yoloPostprocess;
239
2701
  export {
240
- ANIMAL_TYPE_MODELS,
241
- AUDIO_CLASSIFICATION_MODELS,
242
- AnimalClassifierAddon,
243
- AudioClassificationAddon,
244
- BIRD_NABIRDS_MODELS,
245
- BIRD_SPECIES_MODELS,
246
- BirdGlobalClassifierAddon,
247
- BirdNABirdsClassifierAddon,
248
- FACE_DETECTION_MODELS,
249
- FACE_RECOGNITION_MODELS,
250
- FaceDetectionAddon,
251
- FaceRecognitionAddon,
252
- GENERAL_OCR_MODELS,
253
- MLPACKAGE_FILES,
254
- NodeInferenceEngine,
255
- OBJECT_DETECTION_MODELS,
256
- ObjectDetectionAddon,
257
- PLATE_DETECTION_MODELS,
258
- PLATE_RECOGNITION_MODELS,
259
- PlateDetectionAddon,
260
- PlateRecognitionAddon,
261
- PythonInferenceEngine,
262
- SEGMENTATION_MODELS,
263
- SEGMENTATION_REFINER_MODELS,
264
- VEHICLE_TYPE_MODELS,
265
- cosineSimilarity,
266
- cropRegion,
267
- ctcDecode,
268
- detectMotion,
269
- iou,
270
- jpegToRgb,
271
- l2Normalize,
272
- letterbox,
273
- nms,
274
- probeOnnxBackends,
275
- resizeAndNormalize,
276
- resolveEngine,
277
- rgbToGrayscale,
278
- scrfdPostprocess,
279
- yamnetPostprocess,
280
- yoloPostprocess
2702
+ export_AnimalClassifierAddon as AnimalClassifierAddon,
2703
+ export_AudioClassificationAddon as AudioClassificationAddon,
2704
+ export_BirdGlobalClassifierAddon as BirdGlobalClassifierAddon,
2705
+ export_BirdNABirdsClassifierAddon as BirdNABirdsClassifierAddon,
2706
+ export_FaceDetectionAddon as FaceDetectionAddon,
2707
+ export_FaceRecognitionAddon as FaceRecognitionAddon,
2708
+ export_NodeInferenceEngine as NodeInferenceEngine,
2709
+ export_ObjectDetectionAddon as ObjectDetectionAddon,
2710
+ export_PlateDetectionAddon as PlateDetectionAddon,
2711
+ export_PlateRecognitionAddon as PlateRecognitionAddon,
2712
+ export_PythonInferenceEngine as PythonInferenceEngine,
2713
+ export_cosineSimilarity as cosineSimilarity,
2714
+ export_cropRegion as cropRegion,
2715
+ export_ctcDecode as ctcDecode,
2716
+ export_detectMotion as detectMotion,
2717
+ export_iou as iou,
2718
+ export_jpegToRgb as jpegToRgb,
2719
+ export_l2Normalize as l2Normalize,
2720
+ export_letterbox as letterbox,
2721
+ export_nms as nms,
2722
+ export_probeOnnxBackends as probeOnnxBackends,
2723
+ export_resizeAndNormalize as resizeAndNormalize,
2724
+ export_resolveEngine as resolveEngine,
2725
+ export_rgbToGrayscale as rgbToGrayscale,
2726
+ export_scrfdPostprocess as scrfdPostprocess,
2727
+ export_yamnetPostprocess as yamnetPostprocess,
2728
+ export_yoloPostprocess as yoloPostprocess
281
2729
  };
282
2730
  //# sourceMappingURL=index.mjs.map