@camstack/vision 0.1.0

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 (104) hide show
  1. package/dist/addons/animal-classifier/index.d.mts +25 -0
  2. package/dist/addons/animal-classifier/index.d.ts +25 -0
  3. package/dist/addons/animal-classifier/index.js +469 -0
  4. package/dist/addons/animal-classifier/index.js.map +1 -0
  5. package/dist/addons/animal-classifier/index.mjs +9 -0
  6. package/dist/addons/animal-classifier/index.mjs.map +1 -0
  7. package/dist/addons/audio-classification/index.d.mts +31 -0
  8. package/dist/addons/audio-classification/index.d.ts +31 -0
  9. package/dist/addons/audio-classification/index.js +411 -0
  10. package/dist/addons/audio-classification/index.js.map +1 -0
  11. package/dist/addons/audio-classification/index.mjs +8 -0
  12. package/dist/addons/audio-classification/index.mjs.map +1 -0
  13. package/dist/addons/bird-global-classifier/index.d.mts +26 -0
  14. package/dist/addons/bird-global-classifier/index.d.ts +26 -0
  15. package/dist/addons/bird-global-classifier/index.js +475 -0
  16. package/dist/addons/bird-global-classifier/index.js.map +1 -0
  17. package/dist/addons/bird-global-classifier/index.mjs +9 -0
  18. package/dist/addons/bird-global-classifier/index.mjs.map +1 -0
  19. package/dist/addons/bird-nabirds-classifier/index.d.mts +28 -0
  20. package/dist/addons/bird-nabirds-classifier/index.d.ts +28 -0
  21. package/dist/addons/bird-nabirds-classifier/index.js +517 -0
  22. package/dist/addons/bird-nabirds-classifier/index.js.map +1 -0
  23. package/dist/addons/bird-nabirds-classifier/index.mjs +9 -0
  24. package/dist/addons/bird-nabirds-classifier/index.mjs.map +1 -0
  25. package/dist/addons/camera-native-detection/index.d.mts +32 -0
  26. package/dist/addons/camera-native-detection/index.d.ts +32 -0
  27. package/dist/addons/camera-native-detection/index.js +99 -0
  28. package/dist/addons/camera-native-detection/index.js.map +1 -0
  29. package/dist/addons/camera-native-detection/index.mjs +7 -0
  30. package/dist/addons/camera-native-detection/index.mjs.map +1 -0
  31. package/dist/addons/face-detection/index.d.mts +24 -0
  32. package/dist/addons/face-detection/index.d.ts +24 -0
  33. package/dist/addons/face-detection/index.js +513 -0
  34. package/dist/addons/face-detection/index.js.map +1 -0
  35. package/dist/addons/face-detection/index.mjs +10 -0
  36. package/dist/addons/face-detection/index.mjs.map +1 -0
  37. package/dist/addons/face-recognition/index.d.mts +24 -0
  38. package/dist/addons/face-recognition/index.d.ts +24 -0
  39. package/dist/addons/face-recognition/index.js +437 -0
  40. package/dist/addons/face-recognition/index.js.map +1 -0
  41. package/dist/addons/face-recognition/index.mjs +9 -0
  42. package/dist/addons/face-recognition/index.mjs.map +1 -0
  43. package/dist/addons/motion-detection/index.d.mts +26 -0
  44. package/dist/addons/motion-detection/index.d.ts +26 -0
  45. package/dist/addons/motion-detection/index.js +273 -0
  46. package/dist/addons/motion-detection/index.js.map +1 -0
  47. package/dist/addons/motion-detection/index.mjs +8 -0
  48. package/dist/addons/motion-detection/index.mjs.map +1 -0
  49. package/dist/addons/object-detection/index.d.mts +25 -0
  50. package/dist/addons/object-detection/index.d.ts +25 -0
  51. package/dist/addons/object-detection/index.js +673 -0
  52. package/dist/addons/object-detection/index.js.map +1 -0
  53. package/dist/addons/object-detection/index.mjs +10 -0
  54. package/dist/addons/object-detection/index.mjs.map +1 -0
  55. package/dist/addons/plate-detection/index.d.mts +25 -0
  56. package/dist/addons/plate-detection/index.d.ts +25 -0
  57. package/dist/addons/plate-detection/index.js +477 -0
  58. package/dist/addons/plate-detection/index.js.map +1 -0
  59. package/dist/addons/plate-detection/index.mjs +10 -0
  60. package/dist/addons/plate-detection/index.mjs.map +1 -0
  61. package/dist/addons/plate-recognition/index.d.mts +25 -0
  62. package/dist/addons/plate-recognition/index.d.ts +25 -0
  63. package/dist/addons/plate-recognition/index.js +470 -0
  64. package/dist/addons/plate-recognition/index.js.map +1 -0
  65. package/dist/addons/plate-recognition/index.mjs +9 -0
  66. package/dist/addons/plate-recognition/index.mjs.map +1 -0
  67. package/dist/chunk-3BKYLBBH.mjs +229 -0
  68. package/dist/chunk-3BKYLBBH.mjs.map +1 -0
  69. package/dist/chunk-4PC262GU.mjs +203 -0
  70. package/dist/chunk-4PC262GU.mjs.map +1 -0
  71. package/dist/chunk-6OR5TE7A.mjs +101 -0
  72. package/dist/chunk-6OR5TE7A.mjs.map +1 -0
  73. package/dist/chunk-7SZAISGP.mjs +210 -0
  74. package/dist/chunk-7SZAISGP.mjs.map +1 -0
  75. package/dist/chunk-AD2TFYZA.mjs +235 -0
  76. package/dist/chunk-AD2TFYZA.mjs.map +1 -0
  77. package/dist/chunk-CGYSSHHM.mjs +363 -0
  78. package/dist/chunk-CGYSSHHM.mjs.map +1 -0
  79. package/dist/chunk-IYHMGYGP.mjs +79 -0
  80. package/dist/chunk-IYHMGYGP.mjs.map +1 -0
  81. package/dist/chunk-J3IUBPRE.mjs +187 -0
  82. package/dist/chunk-J3IUBPRE.mjs.map +1 -0
  83. package/dist/chunk-KFZDJPYL.mjs +190 -0
  84. package/dist/chunk-KFZDJPYL.mjs.map +1 -0
  85. package/dist/chunk-KUO2BVFY.mjs +90 -0
  86. package/dist/chunk-KUO2BVFY.mjs.map +1 -0
  87. package/dist/chunk-PXBY3QOA.mjs +152 -0
  88. package/dist/chunk-PXBY3QOA.mjs.map +1 -0
  89. package/dist/chunk-XUKDL23Y.mjs +216 -0
  90. package/dist/chunk-XUKDL23Y.mjs.map +1 -0
  91. package/dist/chunk-Z26BVC7S.mjs +214 -0
  92. package/dist/chunk-Z26BVC7S.mjs.map +1 -0
  93. package/dist/chunk-Z5AHZQEZ.mjs +258 -0
  94. package/dist/chunk-Z5AHZQEZ.mjs.map +1 -0
  95. package/dist/index.d.mts +152 -0
  96. package/dist/index.d.ts +152 -0
  97. package/dist/index.js +2775 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/index.mjs +205 -0
  100. package/dist/index.mjs.map +1 -0
  101. package/package.json +43 -0
  102. package/python/coreml_inference.py +67 -0
  103. package/python/openvino_inference.py +76 -0
  104. package/python/pytorch_inference.py +74 -0
@@ -0,0 +1,475 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/addons/bird-global-classifier/index.ts
31
+ var bird_global_classifier_exports = {};
32
+ __export(bird_global_classifier_exports, {
33
+ default: () => BirdGlobalClassifierAddon
34
+ });
35
+ module.exports = __toCommonJS(bird_global_classifier_exports);
36
+ var import_types = require("@camstack/types");
37
+
38
+ // src/shared/image-utils.ts
39
+ var import_sharp = __toESM(require("sharp"));
40
+ async function cropRegion(jpeg, roi) {
41
+ return (0, import_sharp.default)(jpeg).extract({
42
+ left: Math.round(roi.x),
43
+ top: Math.round(roi.y),
44
+ width: Math.round(roi.w),
45
+ height: Math.round(roi.h)
46
+ }).jpeg().toBuffer();
47
+ }
48
+ async function resizeAndNormalize(jpeg, targetWidth, targetHeight, normalization, layout) {
49
+ const { data } = await (0, import_sharp.default)(jpeg).resize(targetWidth, targetHeight).removeAlpha().raw().toBuffer({ resolveWithObject: true });
50
+ const numPixels = targetWidth * targetHeight;
51
+ const float32 = new Float32Array(3 * numPixels);
52
+ const mean = [0.485, 0.456, 0.406];
53
+ const std = [0.229, 0.224, 0.225];
54
+ if (layout === "nchw") {
55
+ for (let i = 0; i < numPixels; i++) {
56
+ const srcBase = i * 3;
57
+ for (let c = 0; c < 3; c++) {
58
+ const raw = data[srcBase + c] / 255;
59
+ let val;
60
+ if (normalization === "zero-one") {
61
+ val = raw;
62
+ } else if (normalization === "imagenet") {
63
+ val = (raw - mean[c]) / std[c];
64
+ } else {
65
+ val = data[srcBase + c];
66
+ }
67
+ float32[c * numPixels + i] = val;
68
+ }
69
+ }
70
+ } else {
71
+ for (let i = 0; i < numPixels; i++) {
72
+ const srcBase = i * 3;
73
+ for (let c = 0; c < 3; c++) {
74
+ const raw = data[srcBase + c] / 255;
75
+ let val;
76
+ if (normalization === "zero-one") {
77
+ val = raw;
78
+ } else if (normalization === "imagenet") {
79
+ val = (raw - mean[c]) / std[c];
80
+ } else {
81
+ val = data[srcBase + c];
82
+ }
83
+ float32[i * 3 + c] = val;
84
+ }
85
+ }
86
+ }
87
+ return float32;
88
+ }
89
+
90
+ // src/shared/engine-resolver.ts
91
+ var fs = __toESM(require("fs"));
92
+ var path2 = __toESM(require("path"));
93
+
94
+ // src/shared/node-engine.ts
95
+ var path = __toESM(require("path"));
96
+ var BACKEND_TO_PROVIDER = {
97
+ cpu: "cpu",
98
+ coreml: "coreml",
99
+ cuda: "cuda",
100
+ tensorrt: "tensorrt",
101
+ dml: "dml"
102
+ };
103
+ var BACKEND_TO_DEVICE = {
104
+ cpu: "cpu",
105
+ coreml: "gpu-mps",
106
+ cuda: "gpu-cuda",
107
+ tensorrt: "tensorrt"
108
+ };
109
+ var NodeInferenceEngine = class {
110
+ constructor(modelPath, backend) {
111
+ this.modelPath = modelPath;
112
+ this.backend = backend;
113
+ this.device = BACKEND_TO_DEVICE[backend] ?? "cpu";
114
+ }
115
+ runtime = "onnx";
116
+ device;
117
+ session = null;
118
+ async initialize() {
119
+ const ort = await import("onnxruntime-node");
120
+ const provider = BACKEND_TO_PROVIDER[this.backend] ?? "cpu";
121
+ const absModelPath = path.isAbsolute(this.modelPath) ? this.modelPath : path.resolve(process.cwd(), this.modelPath);
122
+ const sessionOptions = {
123
+ executionProviders: [provider]
124
+ };
125
+ this.session = await ort.InferenceSession.create(absModelPath, sessionOptions);
126
+ }
127
+ async run(input, inputShape) {
128
+ if (!this.session) {
129
+ throw new Error("NodeInferenceEngine: not initialized \u2014 call initialize() first");
130
+ }
131
+ const ort = await import("onnxruntime-node");
132
+ const sess = this.session;
133
+ const inputName = sess.inputNames[0];
134
+ const tensor = new ort.Tensor("float32", input, [...inputShape]);
135
+ const feeds = { [inputName]: tensor };
136
+ const results = await sess.run(feeds);
137
+ const outputName = sess.outputNames[0];
138
+ const outputTensor = results[outputName];
139
+ return outputTensor.data;
140
+ }
141
+ async runMultiOutput(input, inputShape) {
142
+ if (!this.session) {
143
+ throw new Error("NodeInferenceEngine: not initialized \u2014 call initialize() first");
144
+ }
145
+ const ort = await import("onnxruntime-node");
146
+ const sess = this.session;
147
+ const inputName = sess.inputNames[0];
148
+ const tensor = new ort.Tensor("float32", input, [...inputShape]);
149
+ const feeds = { [inputName]: tensor };
150
+ const results = await sess.run(feeds);
151
+ const out = {};
152
+ for (const name of sess.outputNames) {
153
+ out[name] = results[name].data;
154
+ }
155
+ return out;
156
+ }
157
+ async dispose() {
158
+ this.session = null;
159
+ }
160
+ };
161
+
162
+ // src/shared/engine-resolver.ts
163
+ var AUTO_BACKEND_PRIORITY = ["coreml", "cuda", "tensorrt", "cpu"];
164
+ var BACKEND_TO_FORMAT = {
165
+ cpu: "onnx",
166
+ coreml: "coreml",
167
+ cuda: "onnx",
168
+ tensorrt: "onnx"
169
+ };
170
+ var RUNTIME_TO_FORMAT = {
171
+ onnx: "onnx",
172
+ coreml: "coreml",
173
+ openvino: "openvino",
174
+ tflite: "tflite",
175
+ pytorch: "pt"
176
+ };
177
+ function modelFilePath(modelsDir, modelEntry, format) {
178
+ const formatEntry = modelEntry.formats[format];
179
+ if (!formatEntry) {
180
+ throw new Error(`Model ${modelEntry.id} has no ${format} format`);
181
+ }
182
+ const urlParts = formatEntry.url.split("/");
183
+ const filename = urlParts[urlParts.length - 1] ?? `${modelEntry.id}.${format}`;
184
+ return path2.join(modelsDir, filename);
185
+ }
186
+ function modelExists(filePath) {
187
+ try {
188
+ return fs.existsSync(filePath);
189
+ } catch {
190
+ return false;
191
+ }
192
+ }
193
+ async function resolveEngine(options) {
194
+ const { runtime, backend, modelEntry, modelsDir, downloadModel } = options;
195
+ let selectedFormat;
196
+ let selectedBackend;
197
+ if (runtime === "auto") {
198
+ const available = await probeOnnxBackends();
199
+ let chosen = null;
200
+ for (const b of AUTO_BACKEND_PRIORITY) {
201
+ if (!available.includes(b)) continue;
202
+ const fmt = BACKEND_TO_FORMAT[b];
203
+ if (!fmt) continue;
204
+ if (!modelEntry.formats[fmt]) continue;
205
+ chosen = { backend: b, format: fmt };
206
+ break;
207
+ }
208
+ if (!chosen) {
209
+ throw new Error(
210
+ `resolveEngine: no compatible backend found for model ${modelEntry.id}. Available backends: ${available.join(", ")}`
211
+ );
212
+ }
213
+ selectedFormat = chosen.format;
214
+ selectedBackend = chosen.backend;
215
+ } else {
216
+ const fmt = RUNTIME_TO_FORMAT[runtime];
217
+ if (!fmt) {
218
+ throw new Error(`resolveEngine: unsupported runtime "${runtime}"`);
219
+ }
220
+ if (!modelEntry.formats[fmt]) {
221
+ throw new Error(
222
+ `resolveEngine: model ${modelEntry.id} has no ${fmt} format for runtime ${runtime}`
223
+ );
224
+ }
225
+ selectedFormat = fmt;
226
+ selectedBackend = runtime === "onnx" ? backend || "cpu" : runtime;
227
+ }
228
+ let modelPath = modelFilePath(modelsDir, modelEntry, selectedFormat);
229
+ if (!modelExists(modelPath)) {
230
+ if (downloadModel) {
231
+ const formatEntry = modelEntry.formats[selectedFormat];
232
+ modelPath = await downloadModel(formatEntry.url, modelsDir);
233
+ } else {
234
+ throw new Error(
235
+ `resolveEngine: model file not found at ${modelPath} and no downloadModel function provided`
236
+ );
237
+ }
238
+ }
239
+ if (selectedFormat === "onnx" || selectedFormat === "coreml") {
240
+ const engine = new NodeInferenceEngine(modelPath, selectedBackend);
241
+ await engine.initialize();
242
+ return { engine, format: selectedFormat, modelPath };
243
+ }
244
+ const fallbackPath = modelFilePath(modelsDir, modelEntry, "onnx");
245
+ if (modelEntry.formats["onnx"] && modelExists(fallbackPath)) {
246
+ const engine = new NodeInferenceEngine(fallbackPath, "cpu");
247
+ await engine.initialize();
248
+ return { engine, format: "onnx", modelPath: fallbackPath };
249
+ }
250
+ throw new Error(
251
+ `resolveEngine: format ${selectedFormat} is not yet supported by NodeInferenceEngine and no ONNX fallback is available`
252
+ );
253
+ }
254
+ async function probeOnnxBackends() {
255
+ const available = ["cpu"];
256
+ try {
257
+ const ort = await import("onnxruntime-node");
258
+ const providers = ort.env?.webgl?.disabled !== void 0 ? ort.InferenceSession?.getAvailableProviders?.() ?? [] : [];
259
+ for (const p of providers) {
260
+ const normalized = p.toLowerCase().replace("executionprovider", "");
261
+ if (normalized === "coreml") available.push("coreml");
262
+ else if (normalized === "cuda") available.push("cuda");
263
+ else if (normalized === "tensorrt") available.push("tensorrt");
264
+ }
265
+ } catch {
266
+ }
267
+ if (process.platform === "darwin" && !available.includes("coreml")) {
268
+ available.push("coreml");
269
+ }
270
+ return [...new Set(available)];
271
+ }
272
+
273
+ // src/addons/bird-global-classifier/index.ts
274
+ var fs2 = __toESM(require("fs"));
275
+ var path3 = __toESM(require("path"));
276
+ var SPECIES_LABEL = { id: "species", name: "Bird Species" };
277
+ var SPECIES_LABELS = [SPECIES_LABEL];
278
+ var BIRD_CLASS_MAP = { mapping: {}, preserveOriginal: true };
279
+ function loadLabels(modelsDir, modelId) {
280
+ const labelNames = [
281
+ `camstack-${modelId}-labels.json`,
282
+ `camstack-bird-species-525-labels.json`
283
+ ];
284
+ for (const name of labelNames) {
285
+ const labelPath = path3.join(modelsDir, name);
286
+ if (fs2.existsSync(labelPath)) {
287
+ const raw = fs2.readFileSync(labelPath, "utf-8");
288
+ return JSON.parse(raw);
289
+ }
290
+ }
291
+ throw new Error(`BirdGlobalClassifierAddon: labels JSON not found in ${modelsDir}`);
292
+ }
293
+ function softmax(logits) {
294
+ const max = logits.reduce((a, b) => Math.max(a, b), -Infinity);
295
+ const exps = logits.map((v) => Math.exp(v - max));
296
+ const sum = exps.reduce((a, b) => a + b, 0);
297
+ return exps.map((v) => v / sum);
298
+ }
299
+ var BirdGlobalClassifierAddon = class {
300
+ id = "bird-global-classifier";
301
+ slot = "classifier";
302
+ inputClasses = ["animal"];
303
+ outputClasses = ["species:*"];
304
+ slotPriority = 0;
305
+ requiredSteps = [];
306
+ manifest = {
307
+ id: "bird-global-classifier",
308
+ name: "Bird Classifier (Global, 525 species)",
309
+ version: "0.1.0",
310
+ description: "EfficientNet \u2014 525 worldwide bird species (MIT license, ONNX only)",
311
+ packageName: "@camstack/vision",
312
+ slot: "classifier",
313
+ inputClasses: ["animal"],
314
+ outputClasses: ["species:*"],
315
+ supportsCustomModels: false,
316
+ mayRequirePython: false,
317
+ defaultConfig: {
318
+ modelId: "bird-species-525",
319
+ runtime: "auto",
320
+ backend: "cpu",
321
+ minConfidence: 0.3
322
+ }
323
+ };
324
+ engine;
325
+ modelEntry;
326
+ labels = [];
327
+ minConfidence = 0.3;
328
+ async initialize(ctx) {
329
+ const cfg = ctx.addonConfig;
330
+ const modelId = cfg["modelId"] ?? "bird-species-525";
331
+ const runtime = cfg["runtime"] ?? "auto";
332
+ const backend = cfg["backend"] ?? "cpu";
333
+ this.minConfidence = cfg["minConfidence"] ?? 0.3;
334
+ const entry = import_types.BIRD_SPECIES_MODELS.find((m) => m.id === modelId);
335
+ if (!entry) {
336
+ throw new Error(`BirdGlobalClassifierAddon: unknown modelId "${modelId}"`);
337
+ }
338
+ this.modelEntry = entry;
339
+ this.labels = loadLabels(ctx.locationPaths.models, modelId);
340
+ const resolved = await resolveEngine({
341
+ runtime,
342
+ backend,
343
+ modelEntry: entry,
344
+ modelsDir: ctx.locationPaths.models
345
+ });
346
+ this.engine = resolved.engine;
347
+ }
348
+ async classify(input) {
349
+ const start = Date.now();
350
+ const { width: inputW, height: inputH } = this.modelEntry.inputSize;
351
+ const animalCrop = await cropRegion(input.frame.data, input.roi);
352
+ const normalized = await resizeAndNormalize(animalCrop, inputW, inputH, "imagenet", "nchw");
353
+ const rawOutput = await this.engine.run(normalized, [1, 3, inputH, inputW]);
354
+ const probs = softmax(rawOutput);
355
+ let maxIdx = 0;
356
+ let maxScore = probs[0] ?? 0;
357
+ for (let i = 1; i < probs.length; i++) {
358
+ const score = probs[i] ?? 0;
359
+ if (score > maxScore) {
360
+ maxScore = score;
361
+ maxIdx = i;
362
+ }
363
+ }
364
+ if (maxScore < this.minConfidence) {
365
+ return {
366
+ classifications: [],
367
+ inferenceMs: Date.now() - start,
368
+ modelId: this.modelEntry.id
369
+ };
370
+ }
371
+ const label = this.labels[maxIdx] ?? `species_${maxIdx}`;
372
+ return {
373
+ classifications: [
374
+ {
375
+ class: label,
376
+ score: maxScore
377
+ }
378
+ ],
379
+ inferenceMs: Date.now() - start,
380
+ modelId: this.modelEntry.id
381
+ };
382
+ }
383
+ async shutdown() {
384
+ await this.engine?.dispose();
385
+ }
386
+ getConfigSchema() {
387
+ return {
388
+ sections: [
389
+ {
390
+ id: "model",
391
+ title: "Model",
392
+ columns: 1,
393
+ fields: [
394
+ {
395
+ key: "modelId",
396
+ label: "Model",
397
+ type: "model-selector",
398
+ catalog: [...import_types.BIRD_SPECIES_MODELS],
399
+ allowCustom: false,
400
+ allowConversion: false,
401
+ acceptFormats: ["onnx", "coreml", "openvino"],
402
+ requiredMetadata: ["inputSize", "labels"],
403
+ outputFormatHint: "classification"
404
+ }
405
+ ]
406
+ },
407
+ {
408
+ id: "thresholds",
409
+ title: "Classification Settings",
410
+ columns: 1,
411
+ fields: [
412
+ {
413
+ key: "minConfidence",
414
+ label: "Minimum Confidence",
415
+ type: "slider",
416
+ min: 0.05,
417
+ max: 1,
418
+ step: 0.05,
419
+ default: 0.3
420
+ }
421
+ ]
422
+ },
423
+ {
424
+ id: "runtime",
425
+ title: "Runtime",
426
+ columns: 2,
427
+ fields: [
428
+ {
429
+ key: "runtime",
430
+ label: "Runtime",
431
+ type: "select",
432
+ options: [
433
+ { value: "auto", label: "Auto (recommended)" },
434
+ { value: "onnx", label: "ONNX Runtime" },
435
+ { value: "coreml", label: "CoreML (Apple)" }
436
+ ]
437
+ },
438
+ {
439
+ key: "backend",
440
+ label: "Backend",
441
+ type: "select",
442
+ dependsOn: { runtime: "onnx" },
443
+ options: [
444
+ { value: "cpu", label: "CPU" },
445
+ { value: "coreml", label: "CoreML" },
446
+ { value: "cuda", label: "CUDA (NVIDIA)" }
447
+ ]
448
+ }
449
+ ]
450
+ }
451
+ ]
452
+ };
453
+ }
454
+ getClassMap() {
455
+ return BIRD_CLASS_MAP;
456
+ }
457
+ getModelCatalog() {
458
+ return [...import_types.BIRD_SPECIES_MODELS];
459
+ }
460
+ getAvailableModels() {
461
+ return [];
462
+ }
463
+ getActiveLabels() {
464
+ return SPECIES_LABELS;
465
+ }
466
+ async probe() {
467
+ return {
468
+ available: true,
469
+ runtime: this.engine?.runtime ?? "onnx",
470
+ device: this.engine?.device ?? "cpu",
471
+ capabilities: ["fp32"]
472
+ };
473
+ }
474
+ };
475
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/addons/bird-global-classifier/index.ts","../../../src/shared/image-utils.ts","../../../src/shared/engine-resolver.ts","../../../src/shared/node-engine.ts"],"sourcesContent":["import type {\n IClassifierProvider,\n IDetectionAddon,\n AddonManifest,\n AddonContext,\n CropInput,\n ClassifierOutput,\n ConfigUISchema,\n ClassMapDefinition,\n ProbeResult,\n ModelCatalogEntry,\n DetectionModel,\n LabelDefinition,\n IInferenceEngine,\n} from '@camstack/types'\nimport { BIRD_SPECIES_MODELS } from '@camstack/types'\nimport { cropRegion, resizeAndNormalize } from '../../shared/image-utils.js'\nimport { resolveEngine } from '../../shared/engine-resolver.js'\n\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\n\nconst SPECIES_LABEL: LabelDefinition = { id: 'species', name: 'Bird Species' }\nconst SPECIES_LABELS: readonly LabelDefinition[] = [SPECIES_LABEL]\nconst BIRD_CLASS_MAP: ClassMapDefinition = { mapping: {}, preserveOriginal: true }\n\n/** Load bird species labels from JSON file in modelsDir */\nfunction loadLabels(modelsDir: string, modelId: string): readonly string[] {\n const labelNames = [\n `camstack-${modelId}-labels.json`,\n `camstack-bird-species-525-labels.json`,\n ]\n for (const name of labelNames) {\n const labelPath = path.join(modelsDir, name)\n if (fs.existsSync(labelPath)) {\n const raw = fs.readFileSync(labelPath, 'utf-8')\n return JSON.parse(raw) as string[]\n }\n }\n throw new Error(`BirdGlobalClassifierAddon: labels JSON not found in ${modelsDir}`)\n}\n\nfunction softmax(logits: Float32Array): Float32Array {\n const max = logits.reduce((a, b) => Math.max(a, b), -Infinity)\n const exps = logits.map((v) => Math.exp(v - max))\n const sum = exps.reduce((a, b) => a + b, 0)\n return exps.map((v) => v / sum) as unknown as Float32Array\n}\n\nexport default class BirdGlobalClassifierAddon implements IClassifierProvider, IDetectionAddon {\n readonly id = 'bird-global-classifier'\n readonly slot = 'classifier' as const\n readonly inputClasses = ['animal'] as const\n readonly outputClasses = ['species:*'] as const\n readonly slotPriority = 0\n readonly requiredSteps = [] as const\n readonly manifest: AddonManifest = {\n id: 'bird-global-classifier',\n name: 'Bird Classifier (Global, 525 species)',\n version: '0.1.0',\n description: 'EfficientNet — 525 worldwide bird species (MIT license, ONNX only)',\n packageName: '@camstack/vision',\n slot: 'classifier',\n inputClasses: ['animal'],\n outputClasses: ['species:*'],\n supportsCustomModels: false,\n mayRequirePython: false,\n defaultConfig: {\n modelId: 'bird-species-525',\n runtime: 'auto',\n backend: 'cpu',\n minConfidence: 0.3,\n },\n }\n\n private engine!: IInferenceEngine\n private modelEntry!: ModelCatalogEntry\n private labels: readonly string[] = []\n private minConfidence = 0.3\n\n async initialize(ctx: AddonContext): Promise<void> {\n const cfg = ctx.addonConfig\n const modelId = (cfg['modelId'] as string | undefined) ?? 'bird-species-525'\n const runtime = (cfg['runtime'] as string | undefined) ?? 'auto'\n const backend = (cfg['backend'] as string | undefined) ?? 'cpu'\n this.minConfidence = (cfg['minConfidence'] as number | undefined) ?? 0.3\n\n const entry = BIRD_SPECIES_MODELS.find((m) => m.id === modelId)\n if (!entry) {\n throw new Error(`BirdGlobalClassifierAddon: unknown modelId \"${modelId}\"`)\n }\n this.modelEntry = entry\n\n // Load labels from JSON file\n this.labels = loadLabels(ctx.locationPaths.models, modelId)\n\n const resolved = await resolveEngine({\n runtime: runtime as 'auto',\n backend,\n modelEntry: entry,\n modelsDir: ctx.locationPaths.models,\n })\n this.engine = resolved.engine\n }\n\n async classify(input: CropInput): Promise<ClassifierOutput> {\n const start = Date.now()\n const { width: inputW, height: inputH } = this.modelEntry.inputSize\n\n // Crop the animal region\n const animalCrop = await cropRegion(input.frame.data, input.roi)\n\n // Resize to 224x224, ImageNet normalization, NCHW\n const normalized = await resizeAndNormalize(animalCrop, inputW, inputH, 'imagenet', 'nchw')\n\n // Run inference — output shape: [1, 525]\n const rawOutput = await this.engine.run(normalized, [1, 3, inputH, inputW])\n\n // Softmax to get probabilities\n const probs = softmax(rawOutput)\n\n // Find argmax\n let maxIdx = 0\n let maxScore = probs[0] ?? 0\n for (let i = 1; i < probs.length; i++) {\n const score = probs[i] ?? 0\n if (score > maxScore) {\n maxScore = score\n maxIdx = i\n }\n }\n\n if (maxScore < this.minConfidence) {\n return {\n classifications: [],\n inferenceMs: Date.now() - start,\n modelId: this.modelEntry.id,\n }\n }\n\n const label = this.labels[maxIdx] ?? `species_${maxIdx}`\n\n return {\n classifications: [\n {\n class: label,\n score: maxScore,\n },\n ],\n inferenceMs: Date.now() - start,\n modelId: this.modelEntry.id,\n }\n }\n\n async shutdown(): Promise<void> {\n await this.engine?.dispose()\n }\n\n getConfigSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'model',\n title: 'Model',\n columns: 1,\n fields: [\n {\n key: 'modelId',\n label: 'Model',\n type: 'model-selector',\n catalog: [...BIRD_SPECIES_MODELS],\n allowCustom: false,\n allowConversion: false,\n acceptFormats: ['onnx', 'coreml', 'openvino'],\n requiredMetadata: ['inputSize', 'labels'],\n outputFormatHint: 'classification',\n },\n ],\n },\n {\n id: 'thresholds',\n title: 'Classification Settings',\n columns: 1,\n fields: [\n {\n key: 'minConfidence',\n label: 'Minimum Confidence',\n type: 'slider',\n min: 0.05,\n max: 1.0,\n step: 0.05,\n default: 0.3,\n },\n ],\n },\n {\n id: 'runtime',\n title: 'Runtime',\n columns: 2,\n fields: [\n {\n key: 'runtime',\n label: 'Runtime',\n type: 'select',\n options: [\n { value: 'auto', label: 'Auto (recommended)' },\n { value: 'onnx', label: 'ONNX Runtime' },\n { value: 'coreml', label: 'CoreML (Apple)' },\n ],\n },\n {\n key: 'backend',\n label: 'Backend',\n type: 'select',\n dependsOn: { runtime: 'onnx' },\n options: [\n { value: 'cpu', label: 'CPU' },\n { value: 'coreml', label: 'CoreML' },\n { value: 'cuda', label: 'CUDA (NVIDIA)' },\n ],\n },\n ],\n },\n ],\n }\n }\n\n getClassMap(): ClassMapDefinition {\n return BIRD_CLASS_MAP\n }\n\n getModelCatalog(): ModelCatalogEntry[] {\n return [...BIRD_SPECIES_MODELS]\n }\n\n getAvailableModels(): DetectionModel[] {\n return []\n }\n\n getActiveLabels(): readonly LabelDefinition[] {\n return SPECIES_LABELS\n }\n\n async probe(): Promise<ProbeResult> {\n return {\n available: true,\n runtime: this.engine?.runtime ?? 'onnx',\n device: this.engine?.device ?? 'cpu',\n capabilities: ['fp32'],\n }\n }\n}\n","import sharp from 'sharp'\nimport type { BoundingBox } from '@camstack/types'\n\n/** Decode JPEG to raw RGB pixels */\nexport async function jpegToRgb(\n jpeg: Buffer,\n): Promise<{ data: Buffer; width: number; height: number }> {\n const { data, info } = await sharp(jpeg)\n .removeAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true })\n return { data, width: info.width, height: info.height }\n}\n\n/** Crop a region from a JPEG buffer */\nexport async function cropRegion(jpeg: Buffer, roi: BoundingBox): Promise<Buffer> {\n return sharp(jpeg)\n .extract({\n left: Math.round(roi.x),\n top: Math.round(roi.y),\n width: Math.round(roi.w),\n height: Math.round(roi.h),\n })\n .jpeg()\n .toBuffer()\n}\n\n/** Letterbox resize for YOLO: resize preserving aspect ratio, pad to square */\nexport async function letterbox(\n jpeg: Buffer,\n targetSize: number,\n): Promise<{\n data: Float32Array\n scale: number\n padX: number\n padY: number\n originalWidth: number\n originalHeight: number\n}> {\n const meta = await sharp(jpeg).metadata()\n const originalWidth = meta.width ?? 0\n const originalHeight = meta.height ?? 0\n\n const scale = Math.min(targetSize / originalWidth, targetSize / originalHeight)\n const scaledWidth = Math.round(originalWidth * scale)\n const scaledHeight = Math.round(originalHeight * scale)\n\n const padX = Math.floor((targetSize - scaledWidth) / 2)\n const padY = Math.floor((targetSize - scaledHeight) / 2)\n\n const { data } = await sharp(jpeg)\n .resize(scaledWidth, scaledHeight)\n .extend({\n top: padY,\n bottom: targetSize - scaledHeight - padY,\n left: padX,\n right: targetSize - scaledWidth - padX,\n background: { r: 114, g: 114, b: 114 },\n })\n .removeAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true })\n\n // Convert HWC uint8 to CHW float [0,1]\n const numPixels = targetSize * targetSize\n const float32 = new Float32Array(3 * numPixels)\n for (let i = 0; i < numPixels; i++) {\n const srcBase = i * 3\n float32[0 * numPixels + i] = (data[srcBase]! / 255)\n float32[1 * numPixels + i] = (data[srcBase + 1]! / 255)\n float32[2 * numPixels + i] = (data[srcBase + 2]! / 255)\n }\n\n return { data: float32, scale, padX, padY, originalWidth, originalHeight }\n}\n\n/** Resize and normalize to Float32Array */\nexport async function resizeAndNormalize(\n jpeg: Buffer,\n targetWidth: number,\n targetHeight: number,\n normalization: 'zero-one' | 'imagenet' | 'none',\n layout: 'nchw' | 'nhwc',\n): Promise<Float32Array> {\n const { data } = await sharp(jpeg)\n .resize(targetWidth, targetHeight)\n .removeAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true })\n\n const numPixels = targetWidth * targetHeight\n const float32 = new Float32Array(3 * numPixels)\n\n // ImageNet mean and std per channel\n const mean = [0.485, 0.456, 0.406]\n const std = [0.229, 0.224, 0.225]\n\n if (layout === 'nchw') {\n for (let i = 0; i < numPixels; i++) {\n const srcBase = i * 3\n for (let c = 0; c < 3; c++) {\n const raw = data[srcBase + c]! / 255\n let val: number\n if (normalization === 'zero-one') {\n val = raw\n } else if (normalization === 'imagenet') {\n val = (raw - mean[c]!) / std[c]!\n } else {\n val = data[srcBase + c]!\n }\n float32[c * numPixels + i] = val\n }\n }\n } else {\n // nhwc\n for (let i = 0; i < numPixels; i++) {\n const srcBase = i * 3\n for (let c = 0; c < 3; c++) {\n const raw = data[srcBase + c]! / 255\n let val: number\n if (normalization === 'zero-one') {\n val = raw\n } else if (normalization === 'imagenet') {\n val = (raw - mean[c]!) / std[c]!\n } else {\n val = data[srcBase + c]!\n }\n float32[i * 3 + c] = val\n }\n }\n }\n\n return float32\n}\n\n/** Convert raw RGB to grayscale Uint8Array */\nexport function rgbToGrayscale(rgb: Buffer, width: number, height: number): Uint8Array {\n const numPixels = width * height\n const gray = new Uint8Array(numPixels)\n for (let i = 0; i < numPixels; i++) {\n const r = rgb[i * 3]!\n const g = rgb[i * 3 + 1]!\n const b = rgb[i * 3 + 2]!\n // BT.601 luma\n gray[i] = Math.round(0.299 * r + 0.587 * g + 0.114 * b)\n }\n return gray\n}\n","import type {\n IInferenceEngine,\n DetectionRuntime,\n ModelCatalogEntry,\n ModelFormat,\n} from '@camstack/types'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { NodeInferenceEngine } from './node-engine.js'\n\nexport interface EngineResolverOptions {\n readonly runtime: DetectionRuntime | 'auto'\n readonly backend: string\n readonly modelEntry: ModelCatalogEntry\n readonly modelsDir: string\n readonly pythonPath?: string\n readonly downloadModel?: (url: string, destDir: string) => Promise<string>\n}\n\nexport interface ResolvedEngine {\n readonly engine: IInferenceEngine\n readonly format: ModelFormat\n readonly modelPath: string\n}\n\n/** Priority order for auto-selection of ONNX backends */\nconst AUTO_BACKEND_PRIORITY = ['coreml', 'cuda', 'tensorrt', 'cpu'] as const\n\n/** Map backend names to the model format they require */\nconst BACKEND_TO_FORMAT: Readonly<Record<string, ModelFormat>> = {\n cpu: 'onnx',\n coreml: 'coreml',\n cuda: 'onnx',\n tensorrt: 'onnx',\n} as const\n\n/** Map DetectionRuntime to ModelFormat */\nconst RUNTIME_TO_FORMAT: Readonly<Partial<Record<DetectionRuntime, ModelFormat>>> = {\n onnx: 'onnx',\n coreml: 'coreml',\n openvino: 'openvino',\n tflite: 'tflite',\n pytorch: 'pt',\n} as const\n\nfunction modelFilePath(modelsDir: string, modelEntry: ModelCatalogEntry, format: ModelFormat): string {\n const formatEntry = modelEntry.formats[format]\n if (!formatEntry) {\n throw new Error(`Model ${modelEntry.id} has no ${format} format`)\n }\n // Derive filename from URL\n const urlParts = formatEntry.url.split('/')\n const filename = urlParts[urlParts.length - 1] ?? `${modelEntry.id}.${format}`\n return path.join(modelsDir, filename)\n}\n\nfunction modelExists(filePath: string): boolean {\n try {\n return fs.existsSync(filePath)\n } catch {\n return false\n }\n}\n\nexport async function resolveEngine(options: EngineResolverOptions): Promise<ResolvedEngine> {\n const { runtime, backend, modelEntry, modelsDir, downloadModel } = options\n\n let selectedFormat: ModelFormat\n let selectedBackend: string\n\n if (runtime === 'auto') {\n // Probe available ONNX backends and pick best\n const available = await probeOnnxBackends()\n\n // Pick first priority backend that has a corresponding model format available\n let chosen: { backend: string; format: ModelFormat } | null = null\n\n for (const b of AUTO_BACKEND_PRIORITY) {\n if (!available.includes(b)) continue\n const fmt = BACKEND_TO_FORMAT[b]\n if (!fmt) continue\n if (!modelEntry.formats[fmt]) continue\n chosen = { backend: b, format: fmt }\n break\n }\n\n if (!chosen) {\n throw new Error(\n `resolveEngine: no compatible backend found for model ${modelEntry.id}. Available backends: ${available.join(', ')}`,\n )\n }\n\n selectedFormat = chosen.format\n selectedBackend = chosen.backend\n } else {\n // Explicit runtime requested\n const fmt = RUNTIME_TO_FORMAT[runtime]\n if (!fmt) {\n throw new Error(`resolveEngine: unsupported runtime \"${runtime}\"`)\n }\n if (!modelEntry.formats[fmt]) {\n throw new Error(\n `resolveEngine: model ${modelEntry.id} has no ${fmt} format for runtime ${runtime}`,\n )\n }\n selectedFormat = fmt\n // For onnx runtime, use the provided backend; otherwise use the runtime name\n selectedBackend = runtime === 'onnx' ? (backend || 'cpu') : runtime\n }\n\n // Resolve model path\n let modelPath = modelFilePath(modelsDir, modelEntry, selectedFormat)\n\n if (!modelExists(modelPath)) {\n if (downloadModel) {\n const formatEntry = modelEntry.formats[selectedFormat]!\n modelPath = await downloadModel(formatEntry.url, modelsDir)\n } else {\n throw new Error(\n `resolveEngine: model file not found at ${modelPath} and no downloadModel function provided`,\n )\n }\n }\n\n // Only ONNX runtime is handled by NodeInferenceEngine currently\n if (selectedFormat === 'onnx' || selectedFormat === 'coreml') {\n const engine = new NodeInferenceEngine(modelPath, selectedBackend)\n await engine.initialize()\n return { engine, format: selectedFormat, modelPath }\n }\n\n // For other formats (openvino, tflite, pt), fall back to ONNX cpu with a warning\n // until those engines are implemented\n const fallbackPath = modelFilePath(modelsDir, modelEntry, 'onnx')\n if (modelEntry.formats['onnx'] && modelExists(fallbackPath)) {\n const engine = new NodeInferenceEngine(fallbackPath, 'cpu')\n await engine.initialize()\n return { engine, format: 'onnx', modelPath: fallbackPath }\n }\n\n throw new Error(\n `resolveEngine: format ${selectedFormat} is not yet supported by NodeInferenceEngine and no ONNX fallback is available`,\n )\n}\n\n/** Probe which ONNX execution providers are available on this system */\nexport async function probeOnnxBackends(): Promise<string[]> {\n const available: string[] = ['cpu'] // CPU is always available\n\n try {\n const ort = await import('onnxruntime-node')\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const providers: string[] = (ort as any).env?.webgl?.disabled !== undefined\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ? ((ort as any).InferenceSession?.getAvailableProviders?.() ?? [])\n : []\n\n for (const p of providers) {\n const normalized = p.toLowerCase().replace('executionprovider', '')\n if (normalized === 'coreml') available.push('coreml')\n else if (normalized === 'cuda') available.push('cuda')\n else if (normalized === 'tensorrt') available.push('tensorrt')\n }\n } catch {\n // onnxruntime-node may not be installed; CPU only\n }\n\n // Platform-specific hints when getAvailableProviders isn't exposed\n if (process.platform === 'darwin' && !available.includes('coreml')) {\n available.push('coreml')\n }\n\n return [...new Set(available)]\n}\n","import type { IInferenceEngine, DetectionRuntime, DetectionDevice } from '@camstack/types'\nimport * as path from 'node:path'\n\nconst BACKEND_TO_PROVIDER: Readonly<Record<string, string>> = {\n cpu: 'cpu',\n coreml: 'coreml',\n cuda: 'cuda',\n tensorrt: 'tensorrt',\n dml: 'dml',\n} as const\n\nconst BACKEND_TO_DEVICE: Readonly<Record<string, DetectionDevice>> = {\n cpu: 'cpu',\n coreml: 'gpu-mps',\n cuda: 'gpu-cuda',\n tensorrt: 'tensorrt',\n} as const\n\nexport class NodeInferenceEngine implements IInferenceEngine {\n readonly runtime: DetectionRuntime = 'onnx'\n readonly device: DetectionDevice\n private session: unknown = null\n\n constructor(\n private readonly modelPath: string,\n private readonly backend: string,\n ) {\n this.device = (BACKEND_TO_DEVICE[backend] ?? 'cpu') as DetectionDevice\n }\n\n async initialize(): Promise<void> {\n const ort = await import('onnxruntime-node')\n const provider = BACKEND_TO_PROVIDER[this.backend] ?? 'cpu'\n\n // Resolve absolute path\n const absModelPath = path.isAbsolute(this.modelPath)\n ? this.modelPath\n : path.resolve(process.cwd(), this.modelPath)\n\n const sessionOptions: Record<string, unknown> = {\n executionProviders: [provider],\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.session = await (ort as any).InferenceSession.create(absModelPath, sessionOptions)\n }\n\n async run(input: Float32Array, inputShape: readonly number[]): Promise<Float32Array> {\n if (!this.session) {\n throw new Error('NodeInferenceEngine: not initialized — call initialize() first')\n }\n\n const ort = await import('onnxruntime-node')\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const sess = this.session as any\n\n // Get the first input name\n const inputName: string = sess.inputNames[0]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const tensor = new (ort as any).Tensor('float32', input, [...inputShape])\n const feeds: Record<string, unknown> = { [inputName]: tensor }\n\n const results = await sess.run(feeds)\n const outputName: string = sess.outputNames[0]\n const outputTensor = results[outputName]\n\n return outputTensor.data as Float32Array\n }\n\n async runMultiOutput(\n input: Float32Array,\n inputShape: readonly number[],\n ): Promise<Record<string, Float32Array>> {\n if (!this.session) {\n throw new Error('NodeInferenceEngine: not initialized — call initialize() first')\n }\n\n const ort = await import('onnxruntime-node')\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const sess = this.session as any\n\n const inputName: string = sess.inputNames[0]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const tensor = new (ort as any).Tensor('float32', input, [...inputShape])\n const feeds: Record<string, unknown> = { [inputName]: tensor }\n\n const results = await sess.run(feeds)\n\n const out: Record<string, Float32Array> = {}\n for (const name of sess.outputNames as string[]) {\n out[name] = results[name].data as Float32Array\n }\n return out\n }\n\n async dispose(): Promise<void> {\n // onnxruntime-node sessions don't have explicit close in all versions\n // but we clear the reference\n this.session = null\n }\n}\n"],"mappings":"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","names":["sharp","sharp","path","fs","path"]}
@@ -0,0 +1,9 @@
1
+ import {
2
+ BirdGlobalClassifierAddon
3
+ } from "../../chunk-XUKDL23Y.mjs";
4
+ import "../../chunk-6OR5TE7A.mjs";
5
+ import "../../chunk-J3IUBPRE.mjs";
6
+ export {
7
+ BirdGlobalClassifierAddon as default
8
+ };
9
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,28 @@
1
+ import { IClassifierProvider, IDetectionAddon, AddonManifest, AddonContext, CropInput, ClassifierOutput, ConfigUISchema, ClassMapDefinition, ModelCatalogEntry, DetectionModel, LabelDefinition, ProbeResult } from '@camstack/types';
2
+
3
+ declare class BirdNABirdsClassifierAddon implements IClassifierProvider, IDetectionAddon {
4
+ readonly id = "bird-nabirds-classifier";
5
+ readonly slot: "classifier";
6
+ readonly inputClasses: readonly ["animal"];
7
+ readonly outputClasses: readonly ["species:*"];
8
+ readonly slotPriority = 0;
9
+ readonly requiredSteps: readonly [];
10
+ readonly manifest: AddonManifest;
11
+ private engine;
12
+ private modelEntry;
13
+ private labels;
14
+ private minConfidence;
15
+ private allowedSpecies;
16
+ initialize(ctx: AddonContext): Promise<void>;
17
+ private applyRegionFilter;
18
+ classify(input: CropInput): Promise<ClassifierOutput>;
19
+ shutdown(): Promise<void>;
20
+ getConfigSchema(): ConfigUISchema;
21
+ getClassMap(): ClassMapDefinition;
22
+ getModelCatalog(): ModelCatalogEntry[];
23
+ getAvailableModels(): DetectionModel[];
24
+ getActiveLabels(): readonly LabelDefinition[];
25
+ probe(): Promise<ProbeResult>;
26
+ }
27
+
28
+ export { BirdNABirdsClassifierAddon as default };
@@ -0,0 +1,28 @@
1
+ import { IClassifierProvider, IDetectionAddon, AddonManifest, AddonContext, CropInput, ClassifierOutput, ConfigUISchema, ClassMapDefinition, ModelCatalogEntry, DetectionModel, LabelDefinition, ProbeResult } from '@camstack/types';
2
+
3
+ declare class BirdNABirdsClassifierAddon implements IClassifierProvider, IDetectionAddon {
4
+ readonly id = "bird-nabirds-classifier";
5
+ readonly slot: "classifier";
6
+ readonly inputClasses: readonly ["animal"];
7
+ readonly outputClasses: readonly ["species:*"];
8
+ readonly slotPriority = 0;
9
+ readonly requiredSteps: readonly [];
10
+ readonly manifest: AddonManifest;
11
+ private engine;
12
+ private modelEntry;
13
+ private labels;
14
+ private minConfidence;
15
+ private allowedSpecies;
16
+ initialize(ctx: AddonContext): Promise<void>;
17
+ private applyRegionFilter;
18
+ classify(input: CropInput): Promise<ClassifierOutput>;
19
+ shutdown(): Promise<void>;
20
+ getConfigSchema(): ConfigUISchema;
21
+ getClassMap(): ClassMapDefinition;
22
+ getModelCatalog(): ModelCatalogEntry[];
23
+ getAvailableModels(): DetectionModel[];
24
+ getActiveLabels(): readonly LabelDefinition[];
25
+ probe(): Promise<ProbeResult>;
26
+ }
27
+
28
+ export { BirdNABirdsClassifierAddon as default };