@camstack/addon-vision 0.1.0 → 0.1.2
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.
- package/dist/addons/animal-classifier/index.d.mts +6 -1
- package/dist/addons/animal-classifier/index.d.ts +6 -1
- package/dist/addons/animal-classifier/index.js +513 -49
- package/dist/addons/animal-classifier/index.js.map +1 -1
- package/dist/addons/animal-classifier/index.mjs +6 -4
- package/dist/addons/audio-classification/index.d.mts +6 -1
- package/dist/addons/audio-classification/index.d.ts +6 -1
- package/dist/addons/audio-classification/index.js +86 -26
- package/dist/addons/audio-classification/index.js.map +1 -1
- package/dist/addons/audio-classification/index.mjs +3 -2
- package/dist/addons/bird-global-classifier/index.d.mts +6 -1
- package/dist/addons/bird-global-classifier/index.d.ts +6 -1
- package/dist/addons/bird-global-classifier/index.js +514 -50
- package/dist/addons/bird-global-classifier/index.js.map +1 -1
- package/dist/addons/bird-global-classifier/index.mjs +6 -4
- package/dist/addons/bird-nabirds-classifier/index.d.mts +6 -1
- package/dist/addons/bird-nabirds-classifier/index.d.ts +6 -1
- package/dist/addons/bird-nabirds-classifier/index.js +523 -60
- package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
- package/dist/addons/bird-nabirds-classifier/index.mjs +6 -4
- package/dist/addons/face-detection/index.d.mts +6 -1
- package/dist/addons/face-detection/index.d.ts +6 -1
- package/dist/addons/face-detection/index.js +538 -39
- package/dist/addons/face-detection/index.js.map +1 -1
- package/dist/addons/face-detection/index.mjs +5 -3
- package/dist/addons/face-recognition/index.d.mts +6 -1
- package/dist/addons/face-recognition/index.d.ts +6 -1
- package/dist/addons/face-recognition/index.js +487 -33
- package/dist/addons/face-recognition/index.js.map +1 -1
- package/dist/addons/face-recognition/index.mjs +5 -3
- package/dist/addons/motion-detection/index.d.mts +3 -1
- package/dist/addons/motion-detection/index.d.ts +3 -1
- package/dist/addons/motion-detection/index.js +11 -3
- package/dist/addons/motion-detection/index.js.map +1 -1
- package/dist/addons/motion-detection/index.mjs +140 -3
- package/dist/addons/motion-detection/index.mjs.map +1 -1
- package/dist/addons/object-detection/index.d.mts +6 -1
- package/dist/addons/object-detection/index.d.ts +6 -1
- package/dist/addons/object-detection/index.js +369 -72
- package/dist/addons/object-detection/index.js.map +1 -1
- package/dist/addons/object-detection/index.mjs +5 -3
- package/dist/addons/plate-detection/index.d.mts +6 -1
- package/dist/addons/plate-detection/index.d.ts +6 -1
- package/dist/addons/plate-detection/index.js +531 -31
- package/dist/addons/plate-detection/index.js.map +1 -1
- package/dist/addons/plate-detection/index.mjs +5 -3
- package/dist/addons/plate-recognition/index.d.mts +7 -1
- package/dist/addons/plate-recognition/index.d.ts +7 -1
- package/dist/addons/plate-recognition/index.js +176 -44
- package/dist/addons/plate-recognition/index.js.map +1 -1
- package/dist/addons/plate-recognition/index.mjs +4 -3
- package/dist/addons/segmentation-refiner/index.d.mts +30 -0
- package/dist/addons/segmentation-refiner/index.d.ts +30 -0
- package/dist/addons/segmentation-refiner/index.js +1048 -0
- package/dist/addons/segmentation-refiner/index.js.map +1 -0
- package/dist/addons/segmentation-refiner/index.mjs +209 -0
- package/dist/addons/segmentation-refiner/index.mjs.map +1 -0
- package/dist/addons/vehicle-classifier/index.d.mts +31 -0
- package/dist/addons/vehicle-classifier/index.d.ts +31 -0
- package/dist/addons/vehicle-classifier/index.js +688 -0
- package/dist/addons/vehicle-classifier/index.js.map +1 -0
- package/dist/addons/vehicle-classifier/index.mjs +250 -0
- package/dist/addons/vehicle-classifier/index.mjs.map +1 -0
- package/dist/{chunk-6OR5TE7A.mjs → chunk-22BHCDT5.mjs} +2 -2
- package/dist/chunk-22BHCDT5.mjs.map +1 -0
- package/dist/{chunk-LPI42WL6.mjs → chunk-2IOKI4ES.mjs} +23 -12
- package/dist/chunk-2IOKI4ES.mjs.map +1 -0
- package/dist/chunk-7DYHXUPZ.mjs +36 -0
- package/dist/chunk-7DYHXUPZ.mjs.map +1 -0
- package/dist/chunk-BJTO5JO5.mjs +11 -0
- package/dist/chunk-BP7H4NFS.mjs +412 -0
- package/dist/chunk-BP7H4NFS.mjs.map +1 -0
- package/dist/chunk-BR2FPGOX.mjs +98 -0
- package/dist/chunk-BR2FPGOX.mjs.map +1 -0
- package/dist/{chunk-5AIQSN32.mjs → chunk-D6WEHN33.mjs} +66 -17
- package/dist/chunk-D6WEHN33.mjs.map +1 -0
- package/dist/{chunk-3MQFUDRU.mjs → chunk-DRYFGARD.mjs} +76 -47
- package/dist/chunk-DRYFGARD.mjs.map +1 -0
- package/dist/{chunk-ISOIDU4U.mjs → chunk-DUN6XU3N.mjs} +23 -5
- package/dist/chunk-DUN6XU3N.mjs.map +1 -0
- package/dist/{chunk-MEVASN3P.mjs → chunk-ESLHNWWE.mjs} +104 -22
- package/dist/chunk-ESLHNWWE.mjs.map +1 -0
- package/dist/{chunk-B3R66MPF.mjs → chunk-JUQEW6ON.mjs} +58 -21
- package/dist/chunk-JUQEW6ON.mjs.map +1 -0
- package/dist/{chunk-AYBFB7ID.mjs → chunk-R5J3WAUI.mjs} +200 -318
- package/dist/chunk-R5J3WAUI.mjs.map +1 -0
- package/dist/chunk-XZ6ZMXXU.mjs +39 -0
- package/dist/chunk-XZ6ZMXXU.mjs.map +1 -0
- package/dist/{chunk-5JJZGKL7.mjs → chunk-YPU4WTXZ.mjs} +102 -19
- package/dist/chunk-YPU4WTXZ.mjs.map +1 -0
- package/dist/{chunk-J4WRYHHY.mjs → chunk-YUCD2TFH.mjs} +66 -36
- package/dist/chunk-YUCD2TFH.mjs.map +1 -0
- package/dist/{chunk-PDSHDDPV.mjs → chunk-ZTJENCFC.mjs} +159 -35
- package/dist/chunk-ZTJENCFC.mjs.map +1 -0
- package/dist/{chunk-Q3SQOYG6.mjs → chunk-ZWYXXCXP.mjs} +67 -37
- package/dist/chunk-ZWYXXCXP.mjs.map +1 -0
- package/dist/index.d.mts +17 -5
- package/dist/index.d.ts +17 -5
- package/dist/index.js +1343 -550
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +191 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +94 -18
- package/python/coreml_inference.py +61 -18
- package/python/openvino_inference.py +12 -4
- package/python/pytorch_inference.py +12 -4
- package/dist/addons/camera-native-detection/index.d.mts +0 -32
- package/dist/addons/camera-native-detection/index.d.ts +0 -32
- package/dist/addons/camera-native-detection/index.js +0 -99
- package/dist/addons/camera-native-detection/index.js.map +0 -1
- package/dist/addons/camera-native-detection/index.mjs +0 -7
- package/dist/chunk-3MQFUDRU.mjs.map +0 -1
- package/dist/chunk-5AIQSN32.mjs.map +0 -1
- package/dist/chunk-5JJZGKL7.mjs.map +0 -1
- package/dist/chunk-6OR5TE7A.mjs.map +0 -1
- package/dist/chunk-AYBFB7ID.mjs.map +0 -1
- package/dist/chunk-B3R66MPF.mjs.map +0 -1
- package/dist/chunk-DTOAB2CE.mjs +0 -79
- package/dist/chunk-DTOAB2CE.mjs.map +0 -1
- package/dist/chunk-ISOIDU4U.mjs.map +0 -1
- package/dist/chunk-J4WRYHHY.mjs.map +0 -1
- package/dist/chunk-LPI42WL6.mjs.map +0 -1
- package/dist/chunk-MEVASN3P.mjs.map +0 -1
- package/dist/chunk-PDSHDDPV.mjs.map +0 -1
- package/dist/chunk-Q3SQOYG6.mjs.map +0 -1
- package/dist/chunk-QIMDG34B.mjs +0 -229
- package/dist/chunk-QIMDG34B.mjs.map +0 -1
- package/python/__pycache__/coreml_inference.cpython-313.pyc +0 -0
- package/python/__pycache__/openvino_inference.cpython-313.pyc +0 -0
- package/python/__pycache__/pytorch_inference.cpython-313.pyc +0 -0
- /package/dist/{addons/camera-native-detection/index.mjs.map → chunk-BJTO5JO5.mjs.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveEngine
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2IOKI4ES.mjs";
|
|
4
4
|
|
|
5
5
|
// src/catalogs/audio-classification-models.ts
|
|
6
6
|
import { hfModelUrl } from "@camstack/types";
|
|
@@ -72,40 +72,46 @@ var AudioClassificationAddon = class {
|
|
|
72
72
|
name: "Audio Classification",
|
|
73
73
|
version: "0.1.0",
|
|
74
74
|
description: "YAMNet-based audio event classification from audio waveform",
|
|
75
|
-
packageName: "@camstack/addon-vision",
|
|
76
75
|
slot: "classifier",
|
|
76
|
+
labelOutputType: "classification",
|
|
77
77
|
inputClasses: void 0,
|
|
78
78
|
outputClasses: ["audio-event:*"],
|
|
79
79
|
supportsCustomModels: false,
|
|
80
80
|
mayRequirePython: false,
|
|
81
81
|
defaultConfig: {
|
|
82
82
|
modelId: "yamnet",
|
|
83
|
-
runtime: "
|
|
83
|
+
runtime: "node",
|
|
84
84
|
backend: "cpu",
|
|
85
85
|
minScore: 0.3
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
|
-
engine;
|
|
88
|
+
engine = null;
|
|
89
89
|
modelEntry;
|
|
90
90
|
minScore = 0.3;
|
|
91
|
+
resolvedConfig = null;
|
|
92
|
+
ctx = null;
|
|
93
|
+
getModelRequirements() {
|
|
94
|
+
return AUDIO_CLASSIFICATION_MODELS.map((m) => ({
|
|
95
|
+
modelId: m.id,
|
|
96
|
+
name: m.name,
|
|
97
|
+
minRAM_MB: 100,
|
|
98
|
+
accuracyScore: 80,
|
|
99
|
+
formats: Object.keys(m.formats)
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
configure(config) {
|
|
103
|
+
this.resolvedConfig = config;
|
|
104
|
+
}
|
|
91
105
|
async initialize(ctx) {
|
|
106
|
+
this.ctx = ctx;
|
|
92
107
|
const cfg = ctx.addonConfig;
|
|
93
|
-
const modelId = cfg["modelId"] ?? "yamnet";
|
|
94
|
-
const runtime = cfg["runtime"] ?? "auto";
|
|
95
|
-
const backend = cfg["backend"] ?? "cpu";
|
|
108
|
+
const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "yamnet";
|
|
96
109
|
this.minScore = cfg["minScore"] ?? 0.3;
|
|
97
110
|
const entry = AUDIO_CLASSIFICATION_MODELS.find((m) => m.id === modelId);
|
|
98
111
|
if (!entry) {
|
|
99
112
|
throw new Error(`AudioClassificationAddon: unknown modelId "${modelId}"`);
|
|
100
113
|
}
|
|
101
114
|
this.modelEntry = entry;
|
|
102
|
-
const resolved = await resolveEngine({
|
|
103
|
-
runtime,
|
|
104
|
-
backend,
|
|
105
|
-
modelEntry: entry,
|
|
106
|
-
modelsDir: ctx.locationPaths.models
|
|
107
|
-
});
|
|
108
|
-
this.engine = resolved.engine;
|
|
109
115
|
}
|
|
110
116
|
/**
|
|
111
117
|
* classify() receives a CropInput but internally treats input.frame.data as raw audio context.
|
|
@@ -115,6 +121,7 @@ var AudioClassificationAddon = class {
|
|
|
115
121
|
* The CropInput.roi is not used for audio — it is ignored.
|
|
116
122
|
*/
|
|
117
123
|
async classify(input) {
|
|
124
|
+
if (!this.engine) await this.ensureEngine();
|
|
118
125
|
const start = Date.now();
|
|
119
126
|
const buf = input.frame.data;
|
|
120
127
|
const numSamples = Math.floor(buf.length / 4);
|
|
@@ -145,12 +152,51 @@ var AudioClassificationAddon = class {
|
|
|
145
152
|
modelId: this.modelEntry.id
|
|
146
153
|
};
|
|
147
154
|
}
|
|
155
|
+
async ensureEngine() {
|
|
156
|
+
const config = this.resolvedConfig;
|
|
157
|
+
const modelId = config?.modelId ?? this.modelEntry.id;
|
|
158
|
+
const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
|
|
159
|
+
const backend = config?.backend ?? "cpu";
|
|
160
|
+
const format = config?.format ?? "onnx";
|
|
161
|
+
const entry = AUDIO_CLASSIFICATION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
|
|
162
|
+
this.modelEntry = entry;
|
|
163
|
+
const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
|
|
164
|
+
if (this.ctx.models) {
|
|
165
|
+
await this.ctx.models.ensure(modelId, format);
|
|
166
|
+
}
|
|
167
|
+
const resolved = await resolveEngine({
|
|
168
|
+
runtime,
|
|
169
|
+
backend,
|
|
170
|
+
modelEntry: entry,
|
|
171
|
+
modelsDir,
|
|
172
|
+
models: this.ctx.models
|
|
173
|
+
});
|
|
174
|
+
this.engine = resolved.engine;
|
|
175
|
+
}
|
|
148
176
|
async shutdown() {
|
|
149
177
|
await this.engine?.dispose();
|
|
150
178
|
}
|
|
151
179
|
getConfigSchema() {
|
|
152
180
|
return {
|
|
153
181
|
sections: [
|
|
182
|
+
{
|
|
183
|
+
id: "model",
|
|
184
|
+
title: "Model",
|
|
185
|
+
columns: 1,
|
|
186
|
+
fields: [
|
|
187
|
+
{
|
|
188
|
+
key: "modelId",
|
|
189
|
+
label: "Model",
|
|
190
|
+
type: "model-selector",
|
|
191
|
+
catalog: [...AUDIO_CLASSIFICATION_MODELS],
|
|
192
|
+
allowCustom: false,
|
|
193
|
+
allowConversion: false,
|
|
194
|
+
acceptFormats: ["onnx", "openvino"],
|
|
195
|
+
requiredMetadata: ["inputSize", "labels", "outputFormat"],
|
|
196
|
+
outputFormatHint: "classification"
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
},
|
|
154
200
|
{
|
|
155
201
|
id: "runtime",
|
|
156
202
|
title: "Runtime",
|
|
@@ -161,8 +207,9 @@ var AudioClassificationAddon = class {
|
|
|
161
207
|
label: "Runtime",
|
|
162
208
|
type: "select",
|
|
163
209
|
options: [
|
|
164
|
-
{ value: "auto", label: "Auto
|
|
210
|
+
{ value: "auto", label: "Auto" },
|
|
165
211
|
{ value: "onnx", label: "ONNX Runtime" },
|
|
212
|
+
{ value: "coreml", label: "CoreML (Apple)" },
|
|
166
213
|
{ value: "openvino", label: "OpenVINO (Intel)" }
|
|
167
214
|
]
|
|
168
215
|
},
|
|
@@ -170,9 +217,11 @@ var AudioClassificationAddon = class {
|
|
|
170
217
|
key: "backend",
|
|
171
218
|
label: "Backend",
|
|
172
219
|
type: "select",
|
|
173
|
-
|
|
220
|
+
showWhen: { field: "runtime", equals: "onnx" },
|
|
174
221
|
options: [
|
|
222
|
+
{ value: "auto", label: "Auto" },
|
|
175
223
|
{ value: "cpu", label: "CPU" },
|
|
224
|
+
{ value: "coreml", label: "CoreML" },
|
|
176
225
|
{ value: "cuda", label: "CUDA (NVIDIA)" }
|
|
177
226
|
]
|
|
178
227
|
}
|
|
@@ -224,4 +273,4 @@ export {
|
|
|
224
273
|
AUDIO_CLASSIFICATION_MODELS,
|
|
225
274
|
AudioClassificationAddon
|
|
226
275
|
};
|
|
227
|
-
//# sourceMappingURL=chunk-
|
|
276
|
+
//# sourceMappingURL=chunk-D6WEHN33.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/catalogs/audio-classification-models.ts","../src/shared/postprocess/yamnet.ts","../src/addons/audio-classification/index.ts"],"sourcesContent":["import type { ModelCatalogEntry, LabelDefinition } from '@camstack/types'\nimport { hfModelUrl } from '@camstack/types'\n\nconst HF_REPO = 'camstack/camstack-models'\n\nconst AUDIO_LABELS: readonly LabelDefinition[] = [\n { id: 'audio', name: 'Audio Event' },\n] as const\n\nexport const AUDIO_CLASSIFICATION_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'yamnet',\n name: 'YAMNet',\n description: 'YAMNet — audio event classification from raw waveform',\n inputSize: { width: 1, height: 16000 },\n labels: AUDIO_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'audioClassification/yamnet/onnx/camstack-yamnet.onnx'),\n sizeMB: 15,\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'audioClassification/yamnet/openvino/camstack-yamnet.xml'),\n sizeMB: 8,\n },\n },\n },\n] as const\n","export interface AudioClassification {\n readonly className: string\n readonly score: number\n}\n\n/** Average YAMNET scores across frames, return top classes above threshold */\nexport function yamnetPostprocess(\n output: Float32Array,\n numFrames: number,\n numClasses: number,\n classNames: readonly string[],\n minScore: number,\n): AudioClassification[] {\n // Average across frames\n const avgScores = new Float32Array(numClasses)\n for (let f = 0; f < numFrames; f++) {\n for (let c = 0; c < numClasses; c++) {\n const prev = avgScores[c] ?? 0\n avgScores[c] = prev + (output[f * numClasses + c] ?? 0)\n }\n }\n if (numFrames > 0) {\n for (let c = 0; c < numClasses; c++) {\n const val = avgScores[c] ?? 0\n avgScores[c] = val / numFrames\n }\n }\n\n // Collect classes above threshold\n const results: AudioClassification[] = []\n for (let c = 0; c < numClasses; c++) {\n const score = avgScores[c]!\n if (score >= minScore) {\n results.push({\n className: classNames[c] ?? String(c),\n score,\n })\n }\n }\n\n // Sort descending by score\n return results.sort((a, b) => b.score - a.score)\n}\n","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 ModelRequirement,\n ResolvedInferenceConfig,\n} from '@camstack/types'\nimport { AUDIO_CLASSIFICATION_MODELS } from '../../catalogs/audio-classification-models.js'\nimport { yamnetPostprocess } from '../../shared/postprocess/yamnet.js'\nimport { resolveEngine } from '../../shared/engine-resolver.js'\n\n// YAMNet recognizes 521 audio classes from the AudioSet ontology.\n// This is the top-level subset used for filtering. Full class list lives in the model catalog.\nconst YAMNET_NUM_CLASSES = 521\n\nconst AUDIO_EVENT_LABEL: LabelDefinition = { id: 'audio-event', name: 'Audio Event' }\nconst AUDIO_LABELS: readonly LabelDefinition[] = [AUDIO_EVENT_LABEL]\nconst AUDIO_CLASS_MAP: ClassMapDefinition = { mapping: {}, preserveOriginal: true }\n\nexport default class AudioClassificationAddon implements IClassifierProvider, IDetectionAddon {\n readonly id = 'audio-classification'\n readonly slot = 'classifier' as const\n readonly inputClasses: readonly string[] | null = null\n readonly outputClasses = ['audio-event:*'] as const\n readonly slotPriority = 0\n readonly manifest: AddonManifest = {\n id: 'audio-classification',\n name: 'Audio Classification',\n version: '0.1.0',\n\n description: 'YAMNet-based audio event classification from audio waveform',\n\n slot: 'classifier',\n labelOutputType: 'classification',\n inputClasses: undefined,\n outputClasses: ['audio-event:*'],\n supportsCustomModels: false,\n mayRequirePython: false,\n defaultConfig: {\n modelId: 'yamnet',\n runtime: 'node',\n backend: 'cpu',\n minScore: 0.3,\n },\n }\n\n private engine: IInferenceEngine | null = null\n private modelEntry!: ModelCatalogEntry\n private minScore = 0.3\n private resolvedConfig: ResolvedInferenceConfig | null = null\n private ctx: AddonContext | null = null\n\n getModelRequirements(): ModelRequirement[] {\n return AUDIO_CLASSIFICATION_MODELS.map((m) => ({\n modelId: m.id,\n name: m.name,\n minRAM_MB: 100,\n accuracyScore: 80,\n formats: Object.keys(m.formats) as readonly string[],\n }))\n }\n\n configure(config: ResolvedInferenceConfig): void {\n this.resolvedConfig = config\n }\n\n async initialize(ctx: AddonContext): Promise<void> {\n this.ctx = ctx\n const cfg = ctx.addonConfig\n const modelId = (cfg['modelId'] as string | undefined) ?? this.resolvedConfig?.modelId ?? 'yamnet'\n this.minScore = (cfg['minScore'] as number | undefined) ?? 0.3\n\n const entry = AUDIO_CLASSIFICATION_MODELS.find((m) => m.id === modelId)\n if (!entry) {\n throw new Error(`AudioClassificationAddon: unknown modelId \"${modelId}\"`)\n }\n this.modelEntry = entry\n }\n\n /**\n * classify() receives a CropInput but internally treats input.frame.data as raw audio context.\n * For audio, the actual audio chunk data should be stored in frame.data as a Float32Array\n * serialized into a Buffer (little-endian float32 samples at 16 kHz).\n *\n * The CropInput.roi is not used for audio — it is ignored.\n */\n async classify(input: CropInput): Promise<ClassifierOutput> {\n if (!this.engine) await this.ensureEngine()\n const start = Date.now()\n\n // Extract raw float32 audio samples from the buffer\n const buf = input.frame.data\n const numSamples = Math.floor(buf.length / 4)\n const audioData = new Float32Array(numSamples)\n for (let i = 0; i < numSamples; i++) {\n audioData[i] = buf.readFloatLE(i * 4)\n }\n\n // YAMNet expects 1D waveform at 16 kHz\n const output = await this.engine!.run(audioData, [numSamples])\n\n // YAMNet output shape: [numFrames, numClasses]\n const numFrames = output.length / YAMNET_NUM_CLASSES\n\n // Use model label ids as class names (or index strings if catalog is sparse)\n const classNames: string[] = this.modelEntry.labels.map((l) => l.id)\n // Pad to full 521 classes if the catalog only has a subset\n while (classNames.length < YAMNET_NUM_CLASSES) {\n classNames.push(`class_${classNames.length}`)\n }\n\n const results = yamnetPostprocess(\n output,\n Math.round(numFrames),\n YAMNET_NUM_CLASSES,\n classNames,\n this.minScore,\n )\n\n const classifications = results.map((r) => ({\n class: `audio-event:${r.className}`,\n score: r.score,\n }))\n\n return {\n classifications,\n inferenceMs: Date.now() - start,\n modelId: this.modelEntry.id,\n }\n }\n\n private async ensureEngine(): Promise<void> {\n const config = this.resolvedConfig\n const modelId = config?.modelId ?? this.modelEntry.id\n const runtime = config?.runtime === 'python' ? 'coreml' : (config?.runtime === 'node' ? 'onnx' : 'auto')\n const backend = config?.backend ?? 'cpu'\n const format = config?.format ?? 'onnx'\n\n const entry = AUDIO_CLASSIFICATION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry\n this.modelEntry = entry\n\n const modelsDir = this.ctx!.models?.getModelsDir() ?? this.ctx!.locationPaths.models\n\n if (this.ctx!.models) {\n await this.ctx!.models.ensure(modelId, format as any)\n }\n\n const resolved = await resolveEngine({\n runtime: runtime as 'auto',\n backend,\n modelEntry: entry,\n modelsDir,\n models: this.ctx!.models,\n })\n this.engine = resolved.engine\n }\n\n async shutdown(): Promise<void> {\n await this.engine?.dispose()\n }\n\n getConfigSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'model',\n title: 'Model',\n columns: 1,\n fields: [\n {\n key: 'modelId',\n label: 'Model',\n type: 'model-selector',\n catalog: [...AUDIO_CLASSIFICATION_MODELS],\n allowCustom: false,\n allowConversion: false,\n acceptFormats: ['onnx', 'openvino'],\n requiredMetadata: ['inputSize', 'labels', 'outputFormat'],\n outputFormatHint: 'classification',\n },\n ],\n },\n {\n id: 'runtime',\n title: 'Runtime',\n columns: 2,\n fields: [\n {\n key: 'runtime',\n label: 'Runtime',\n type: 'select',\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'onnx', label: 'ONNX Runtime' },\n { value: 'coreml', label: 'CoreML (Apple)' },\n { value: 'openvino', label: 'OpenVINO (Intel)' },\n ],\n },\n {\n key: 'backend',\n label: 'Backend',\n type: 'select',\n showWhen: { field: 'runtime', equals: 'onnx' },\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'cpu', label: 'CPU' },\n { value: 'coreml', label: 'CoreML' },\n { value: 'cuda', label: 'CUDA (NVIDIA)' },\n ],\n },\n ],\n },\n {\n id: 'thresholds',\n title: 'Classification Settings',\n columns: 1,\n fields: [\n {\n key: 'minScore',\n label: 'Minimum Score',\n type: 'slider',\n min: 0.05,\n max: 1.0,\n step: 0.05,\n default: 0.3,\n },\n ],\n },\n ],\n }\n }\n\n getClassMap(): ClassMapDefinition {\n return AUDIO_CLASS_MAP\n }\n\n getModelCatalog(): ModelCatalogEntry[] {\n return [...AUDIO_CLASSIFICATION_MODELS]\n }\n\n getAvailableModels(): DetectionModel[] {\n return []\n }\n\n getActiveLabels(): readonly LabelDefinition[] {\n return AUDIO_LABELS\n }\n\n async probe(): Promise<ProbeResult> {\n return {\n available: true,\n runtime: this.engine?.runtime ?? 'onnx',\n device: this.engine?.device ?? 'cpu',\n capabilities: ['fp32'],\n }\n }\n}\n"],"mappings":"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","names":["AUDIO_LABELS"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BIRD_NABIRDS_MODELS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DUN6XU3N.mjs";
|
|
4
4
|
import {
|
|
5
5
|
cropRegion,
|
|
6
6
|
resizeAndNormalize
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-22BHCDT5.mjs";
|
|
8
8
|
import {
|
|
9
9
|
resolveEngine
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-2IOKI4ES.mjs";
|
|
11
11
|
|
|
12
12
|
// src/addons/bird-nabirds-classifier/index.ts
|
|
13
13
|
import * as fs from "fs";
|
|
@@ -47,29 +47,42 @@ var BirdNABirdsClassifierAddon = class {
|
|
|
47
47
|
name: "Bird Classifier (NABirds, 404 species)",
|
|
48
48
|
version: "0.1.0",
|
|
49
49
|
description: "ResNet50 \u2014 404 North American bird species (NABirds dataset, ONNX + CoreML + OpenVINO)",
|
|
50
|
-
packageName: "@camstack/addon-vision",
|
|
51
50
|
slot: "classifier",
|
|
51
|
+
labelOutputType: "classification",
|
|
52
52
|
inputClasses: ["animal"],
|
|
53
53
|
outputClasses: ["species:*"],
|
|
54
54
|
supportsCustomModels: false,
|
|
55
55
|
mayRequirePython: false,
|
|
56
56
|
defaultConfig: {
|
|
57
57
|
modelId: "bird-nabirds-404",
|
|
58
|
-
runtime: "
|
|
58
|
+
runtime: "node",
|
|
59
59
|
backend: "cpu",
|
|
60
60
|
minConfidence: 0.3
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
|
-
engine;
|
|
63
|
+
engine = null;
|
|
64
64
|
modelEntry;
|
|
65
65
|
labels = [];
|
|
66
66
|
minConfidence = 0.3;
|
|
67
67
|
allowedSpecies;
|
|
68
|
+
resolvedConfig = null;
|
|
69
|
+
ctx = null;
|
|
70
|
+
getModelRequirements() {
|
|
71
|
+
return BIRD_NABIRDS_MODELS.map((m) => ({
|
|
72
|
+
modelId: m.id,
|
|
73
|
+
name: m.name,
|
|
74
|
+
minRAM_MB: 300,
|
|
75
|
+
accuracyScore: 80,
|
|
76
|
+
formats: Object.keys(m.formats)
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
configure(config) {
|
|
80
|
+
this.resolvedConfig = config;
|
|
81
|
+
}
|
|
68
82
|
async initialize(ctx) {
|
|
83
|
+
this.ctx = ctx;
|
|
69
84
|
const cfg = ctx.addonConfig;
|
|
70
|
-
const modelId = cfg["modelId"] ?? "bird-nabirds-404";
|
|
71
|
-
const runtime = cfg["runtime"] ?? "auto";
|
|
72
|
-
const backend = cfg["backend"] ?? "cpu";
|
|
85
|
+
const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "bird-nabirds-404";
|
|
73
86
|
this.minConfidence = cfg["minConfidence"] ?? 0.3;
|
|
74
87
|
this.allowedSpecies = cfg["allowedSpecies"];
|
|
75
88
|
const entry = BIRD_NABIRDS_MODELS.find((m) => m.id === modelId);
|
|
@@ -77,14 +90,6 @@ var BirdNABirdsClassifierAddon = class {
|
|
|
77
90
|
throw new Error(`BirdNABirdsClassifierAddon: unknown modelId "${modelId}"`);
|
|
78
91
|
}
|
|
79
92
|
this.modelEntry = entry;
|
|
80
|
-
this.labels = loadLabels(ctx.locationPaths.models, modelId);
|
|
81
|
-
const resolved = await resolveEngine({
|
|
82
|
-
runtime,
|
|
83
|
-
backend,
|
|
84
|
-
modelEntry: entry,
|
|
85
|
-
modelsDir: ctx.locationPaths.models
|
|
86
|
-
});
|
|
87
|
-
this.engine = resolved.engine;
|
|
88
93
|
}
|
|
89
94
|
applyRegionFilter(scores, labels) {
|
|
90
95
|
if (!this.allowedSpecies || this.allowedSpecies.length === 0) return;
|
|
@@ -96,6 +101,7 @@ var BirdNABirdsClassifierAddon = class {
|
|
|
96
101
|
}
|
|
97
102
|
}
|
|
98
103
|
async classify(input) {
|
|
104
|
+
if (!this.engine) await this.ensureEngine();
|
|
99
105
|
const start = Date.now();
|
|
100
106
|
const { width: inputW, height: inputH } = this.modelEntry.inputSize;
|
|
101
107
|
const animalCrop = await cropRegion(input.frame.data, input.roi);
|
|
@@ -137,6 +143,28 @@ var BirdNABirdsClassifierAddon = class {
|
|
|
137
143
|
modelId: this.modelEntry.id
|
|
138
144
|
};
|
|
139
145
|
}
|
|
146
|
+
async ensureEngine() {
|
|
147
|
+
const config = this.resolvedConfig;
|
|
148
|
+
const modelId = config?.modelId ?? this.modelEntry.id;
|
|
149
|
+
const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
|
|
150
|
+
const backend = config?.backend ?? "cpu";
|
|
151
|
+
const format = config?.format ?? "onnx";
|
|
152
|
+
const entry = BIRD_NABIRDS_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
|
|
153
|
+
this.modelEntry = entry;
|
|
154
|
+
const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
|
|
155
|
+
if (this.ctx.models) {
|
|
156
|
+
await this.ctx.models.ensure(modelId, format);
|
|
157
|
+
}
|
|
158
|
+
this.labels = loadLabels(modelsDir, modelId);
|
|
159
|
+
const resolved = await resolveEngine({
|
|
160
|
+
runtime,
|
|
161
|
+
backend,
|
|
162
|
+
modelEntry: entry,
|
|
163
|
+
modelsDir,
|
|
164
|
+
models: this.ctx.models
|
|
165
|
+
});
|
|
166
|
+
this.engine = resolved.engine;
|
|
167
|
+
}
|
|
140
168
|
async shutdown() {
|
|
141
169
|
await this.engine?.dispose();
|
|
142
170
|
}
|
|
@@ -161,6 +189,36 @@ var BirdNABirdsClassifierAddon = class {
|
|
|
161
189
|
}
|
|
162
190
|
]
|
|
163
191
|
},
|
|
192
|
+
{
|
|
193
|
+
id: "runtime",
|
|
194
|
+
title: "Runtime",
|
|
195
|
+
columns: 2,
|
|
196
|
+
fields: [
|
|
197
|
+
{
|
|
198
|
+
key: "runtime",
|
|
199
|
+
label: "Runtime",
|
|
200
|
+
type: "select",
|
|
201
|
+
options: [
|
|
202
|
+
{ value: "auto", label: "Auto" },
|
|
203
|
+
{ value: "onnx", label: "ONNX Runtime" },
|
|
204
|
+
{ value: "coreml", label: "CoreML (Apple)" },
|
|
205
|
+
{ value: "openvino", label: "OpenVINO (Intel)" }
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
key: "backend",
|
|
210
|
+
label: "Backend",
|
|
211
|
+
type: "select",
|
|
212
|
+
showWhen: { field: "runtime", equals: "onnx" },
|
|
213
|
+
options: [
|
|
214
|
+
{ value: "auto", label: "Auto" },
|
|
215
|
+
{ value: "cpu", label: "CPU" },
|
|
216
|
+
{ value: "coreml", label: "CoreML" },
|
|
217
|
+
{ value: "cuda", label: "CUDA (NVIDIA)" }
|
|
218
|
+
]
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
},
|
|
164
222
|
{
|
|
165
223
|
id: "thresholds",
|
|
166
224
|
title: "Classification Settings",
|
|
@@ -199,35 +257,6 @@ var BirdNABirdsClassifierAddon = class {
|
|
|
199
257
|
type: "text"
|
|
200
258
|
}
|
|
201
259
|
]
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
id: "runtime",
|
|
205
|
-
title: "Runtime",
|
|
206
|
-
columns: 2,
|
|
207
|
-
fields: [
|
|
208
|
-
{
|
|
209
|
-
key: "runtime",
|
|
210
|
-
label: "Runtime",
|
|
211
|
-
type: "select",
|
|
212
|
-
options: [
|
|
213
|
-
{ value: "auto", label: "Auto (recommended)" },
|
|
214
|
-
{ value: "onnx", label: "ONNX Runtime" },
|
|
215
|
-
{ value: "coreml", label: "CoreML (Apple)" },
|
|
216
|
-
{ value: "openvino", label: "OpenVINO (Intel)" }
|
|
217
|
-
]
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
key: "backend",
|
|
221
|
-
label: "Backend",
|
|
222
|
-
type: "select",
|
|
223
|
-
dependsOn: { runtime: "onnx" },
|
|
224
|
-
options: [
|
|
225
|
-
{ value: "cpu", label: "CPU" },
|
|
226
|
-
{ value: "coreml", label: "CoreML" },
|
|
227
|
-
{ value: "cuda", label: "CUDA (NVIDIA)" }
|
|
228
|
-
]
|
|
229
|
-
}
|
|
230
|
-
]
|
|
231
260
|
}
|
|
232
261
|
]
|
|
233
262
|
};
|
|
@@ -257,4 +286,4 @@ var BirdNABirdsClassifierAddon = class {
|
|
|
257
286
|
export {
|
|
258
287
|
BirdNABirdsClassifierAddon
|
|
259
288
|
};
|
|
260
|
-
//# sourceMappingURL=chunk-
|
|
289
|
+
//# sourceMappingURL=chunk-DRYFGARD.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/addons/bird-nabirds-classifier/index.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 ModelRequirement,\n ResolvedInferenceConfig,\n} from '@camstack/types'\nimport { BIRD_NABIRDS_MODELS } from '../../catalogs/animal-classification-models.js'\nimport { cropRegion, resizeAndNormalize } from '../../shared/image-utils.js'\nimport { resolveEngine } from '../../shared/engine-resolver.js'\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 NABirds 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-nabirds-404-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(`BirdNABirdsClassifierAddon: 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 BirdNABirdsClassifierAddon implements IClassifierProvider, IDetectionAddon {\n readonly id = 'bird-nabirds-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-nabirds-classifier',\n name: 'Bird Classifier (NABirds, 404 species)',\n version: '0.1.0',\n\n description: 'ResNet50 — 404 North American bird species (NABirds dataset, ONNX + CoreML + OpenVINO)',\n\n slot: 'classifier',\n labelOutputType: 'classification',\n inputClasses: ['animal'],\n outputClasses: ['species:*'],\n supportsCustomModels: false,\n mayRequirePython: false,\n defaultConfig: {\n modelId: 'bird-nabirds-404',\n runtime: 'node',\n backend: 'cpu',\n minConfidence: 0.3,\n },\n }\n\n private engine: IInferenceEngine | null = null\n private modelEntry!: ModelCatalogEntry\n private labels: readonly string[] = []\n private minConfidence = 0.3\n private allowedSpecies: string[] | undefined\n private resolvedConfig: ResolvedInferenceConfig | null = null\n private ctx: AddonContext | null = null\n\n getModelRequirements(): ModelRequirement[] {\n return BIRD_NABIRDS_MODELS.map((m) => ({\n modelId: m.id,\n name: m.name,\n minRAM_MB: 300,\n accuracyScore: 80,\n formats: Object.keys(m.formats) as readonly string[],\n }))\n }\n\n configure(config: ResolvedInferenceConfig): void {\n this.resolvedConfig = config\n }\n\n async initialize(ctx: AddonContext): Promise<void> {\n this.ctx = ctx\n const cfg = ctx.addonConfig\n const modelId = (cfg['modelId'] as string | undefined) ?? this.resolvedConfig?.modelId ?? 'bird-nabirds-404'\n this.minConfidence = (cfg['minConfidence'] as number | undefined) ?? 0.3\n this.allowedSpecies = (cfg['allowedSpecies'] as string[] | undefined)\n\n const entry = BIRD_NABIRDS_MODELS.find((m) => m.id === modelId)\n if (!entry) {\n throw new Error(`BirdNABirdsClassifierAddon: unknown modelId \"${modelId}\"`)\n }\n this.modelEntry = entry\n }\n\n private applyRegionFilter(scores: Float32Array, labels: string[]): void {\n if (!this.allowedSpecies || this.allowedSpecies.length === 0) return\n const allowedSet = new Set(this.allowedSpecies.map(s => s.toLowerCase()))\n for (let i = 0; i < scores.length; i++) {\n if (!allowedSet.has(labels[i]!.toLowerCase())) {\n scores[i] = 0\n }\n }\n }\n\n async classify(input: CropInput): Promise<ClassifierOutput> {\n if (!this.engine) await this.ensureEngine()\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, 404]\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 // Apply regional filter (zeroes out non-allowed species, then re-normalize)\n this.applyRegionFilter(probs, this.labels as string[])\n const filteredSum = probs.reduce((a, b) => a + b, 0)\n if (filteredSum > 0) {\n for (let i = 0; i < probs.length; i++) {\n probs[i] = (probs[i] ?? 0) / filteredSum\n }\n }\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 private async ensureEngine(): Promise<void> {\n const config = this.resolvedConfig\n const modelId = config?.modelId ?? this.modelEntry.id\n const runtime = config?.runtime === 'python' ? 'coreml' : (config?.runtime === 'node' ? 'onnx' : 'auto')\n const backend = config?.backend ?? 'cpu'\n const format = config?.format ?? 'onnx'\n\n const entry = BIRD_NABIRDS_MODELS.find((m) => m.id === modelId) ?? this.modelEntry\n this.modelEntry = entry\n\n const modelsDir = this.ctx!.models?.getModelsDir() ?? this.ctx!.locationPaths.models\n\n // Ensure model + extra files (labels JSON) are downloaded via unified service\n if (this.ctx!.models) {\n await this.ctx!.models.ensure(modelId, format as any)\n }\n\n // Load labels from JSON file (lazy — only on first use)\n this.labels = loadLabels(modelsDir, modelId)\n\n const resolved = await resolveEngine({\n runtime: runtime as 'auto',\n backend,\n modelEntry: entry,\n modelsDir,\n models: this.ctx!.models,\n })\n this.engine = resolved.engine\n }\n\n async shutdown(): Promise<void> {\n await this.engine?.dispose()\n }\n\n getConfigSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'model',\n title: 'Model',\n columns: 1,\n fields: [\n {\n key: 'modelId',\n label: 'Model',\n type: 'model-selector',\n catalog: [...BIRD_NABIRDS_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: 'runtime',\n title: 'Runtime',\n columns: 2,\n fields: [\n {\n key: 'runtime',\n label: 'Runtime',\n type: 'select',\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'onnx', label: 'ONNX Runtime' },\n { value: 'coreml', label: 'CoreML (Apple)' },\n { value: 'openvino', label: 'OpenVINO (Intel)' },\n ],\n },\n {\n key: 'backend',\n label: 'Backend',\n type: 'select',\n showWhen: { field: 'runtime', equals: 'onnx' },\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'cpu', label: 'CPU' },\n { value: 'coreml', label: 'CoreML' },\n { value: 'cuda', label: 'CUDA (NVIDIA)' },\n ],\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: 'region',\n title: 'Regional Filter',\n columns: 1,\n fields: [\n {\n key: 'regionFilter',\n label: 'Region Preset',\n type: 'select',\n options: [\n { value: '', label: 'None (all 404 species)' },\n { value: 'north-america-east', label: 'North America — Eastern' },\n { value: 'north-america-west', label: 'North America — Western' },\n { value: 'north-america-south', label: 'North America — Southern' },\n ],\n },\n {\n key: 'allowedSpecies',\n label: 'Custom Allowed Species (comma-separated)',\n type: 'text',\n },\n ],\n },\n ],\n }\n }\n\n getClassMap(): ClassMapDefinition {\n return BIRD_CLASS_MAP\n }\n\n getModelCatalog(): ModelCatalogEntry[] {\n return [...BIRD_NABIRDS_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"],"mappings":"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","names":[]}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MLPACKAGE_FILES
|
|
3
|
+
} from "./chunk-BP7H4NFS.mjs";
|
|
4
|
+
|
|
1
5
|
// src/catalogs/animal-classification-models.ts
|
|
2
6
|
import { hfModelUrl } from "@camstack/types";
|
|
3
7
|
var HF_REPO = "camstack/camstack-models";
|
|
@@ -14,7 +18,14 @@ var BIRD_SPECIES_MODELS = [
|
|
|
14
18
|
labels: [BIRD_LABEL],
|
|
15
19
|
formats: {
|
|
16
20
|
onnx: { url: hf("animalClassification/bird-species/onnx/camstack-bird-species-525.onnx"), sizeMB: 32 }
|
|
17
|
-
}
|
|
21
|
+
},
|
|
22
|
+
extraFiles: [
|
|
23
|
+
{
|
|
24
|
+
url: hf("animalClassification/bird-species/onnx/camstack-bird-species-525-labels.json"),
|
|
25
|
+
filename: "camstack-bird-species-525-labels.json",
|
|
26
|
+
sizeMB: 0.02
|
|
27
|
+
}
|
|
28
|
+
]
|
|
18
29
|
}
|
|
19
30
|
];
|
|
20
31
|
var BIRD_NABIRDS_MODELS = [
|
|
@@ -27,9 +38,16 @@ var BIRD_NABIRDS_MODELS = [
|
|
|
27
38
|
labels: [{ id: "species", name: "Bird Species" }],
|
|
28
39
|
formats: {
|
|
29
40
|
onnx: { url: hf("animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404.onnx"), sizeMB: 93 },
|
|
30
|
-
coreml: { url: hf("animalClassification/bird-nabirds/coreml/camstack-bird-nabirds-404.mlpackage"), sizeMB: 47 },
|
|
31
|
-
openvino: { url: hf("animalClassification/bird-nabirds/openvino/camstack-bird-nabirds-404.xml"), sizeMB: 47 }
|
|
32
|
-
}
|
|
41
|
+
coreml: { url: hf("animalClassification/bird-nabirds/coreml/camstack-bird-nabirds-404.mlpackage"), sizeMB: 47, isDirectory: true, files: MLPACKAGE_FILES, runtimes: ["python"] },
|
|
42
|
+
openvino: { url: hf("animalClassification/bird-nabirds/openvino/camstack-bird-nabirds-404.xml"), sizeMB: 47, runtimes: ["python"] }
|
|
43
|
+
},
|
|
44
|
+
extraFiles: [
|
|
45
|
+
{
|
|
46
|
+
url: hf("animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404-labels.json"),
|
|
47
|
+
filename: "camstack-bird-nabirds-404-labels.json",
|
|
48
|
+
sizeMB: 0.02
|
|
49
|
+
}
|
|
50
|
+
]
|
|
33
51
|
}
|
|
34
52
|
];
|
|
35
53
|
var ANIMAL_TYPE_MODELS = [
|
|
@@ -51,4 +69,4 @@ export {
|
|
|
51
69
|
BIRD_NABIRDS_MODELS,
|
|
52
70
|
ANIMAL_TYPE_MODELS
|
|
53
71
|
};
|
|
54
|
-
//# sourceMappingURL=chunk-
|
|
72
|
+
//# sourceMappingURL=chunk-DUN6XU3N.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/catalogs/animal-classification-models.ts"],"sourcesContent":["import type { ModelCatalogEntry, LabelDefinition } from '@camstack/types'\nimport { hfModelUrl } from '@camstack/types'\nimport { MLPACKAGE_FILES } from './object-detection-models.js'\n\nconst HF_REPO = 'camstack/camstack-models'\n\nconst hf = (path: string) => hfModelUrl(HF_REPO, path)\n\nconst BIRD_LABEL: LabelDefinition = { id: 'species', name: 'Bird Species' }\nconst ANIMAL_TYPE_LABEL: LabelDefinition = { id: 'animal-type', name: 'Animal Type' }\n\nexport const BIRD_SPECIES_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'bird-species-525',\n name: 'Bird Species (525)',\n description: 'EfficientNet bird species classifier — 525 species, MIT license',\n inputSize: { width: 224, height: 224 },\n inputNormalization: 'imagenet',\n labels: [BIRD_LABEL],\n formats: {\n onnx: { url: hf('animalClassification/bird-species/onnx/camstack-bird-species-525.onnx'), sizeMB: 32 },\n },\n extraFiles: [\n {\n url: hf('animalClassification/bird-species/onnx/camstack-bird-species-525-labels.json'),\n filename: 'camstack-bird-species-525-labels.json',\n sizeMB: 0.02,\n },\n ],\n },\n] as const\n\nexport const BIRD_NABIRDS_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'bird-nabirds-404',\n name: 'NABirds (404 species)',\n description: 'ResNet50 trained on NABirds — 404 North American species with ONNX, CoreML, OpenVINO',\n inputSize: { width: 224, height: 224 },\n inputNormalization: 'imagenet',\n labels: [{ id: 'species', name: 'Bird Species' }],\n formats: {\n onnx: { url: hf('animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404.onnx'), sizeMB: 93 },\n coreml: { url: hf('animalClassification/bird-nabirds/coreml/camstack-bird-nabirds-404.mlpackage'), sizeMB: 47, isDirectory: true, files: MLPACKAGE_FILES, runtimes: ['python'] },\n openvino: { url: hf('animalClassification/bird-nabirds/openvino/camstack-bird-nabirds-404.xml'), sizeMB: 47, runtimes: ['python'] },\n },\n extraFiles: [\n {\n url: hf('animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404-labels.json'),\n filename: 'camstack-bird-nabirds-404-labels.json',\n sizeMB: 0.02,\n },\n ],\n },\n] as const\n\nexport const ANIMAL_TYPE_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'animals-10',\n name: 'Animal Classifier (10)',\n description: 'ViT-based animal type classifier — cat, cow, dog, dolphin, eagle, panda, horse, monkey, sheep, spider',\n inputSize: { width: 224, height: 224 },\n inputNormalization: 'imagenet',\n labels: [ANIMAL_TYPE_LABEL],\n formats: {\n onnx: { url: hf('animalClassification/animals-10/onnx/camstack-animals-10.onnx'), sizeMB: 328 },\n },\n },\n] as const\n"],"mappings":";;;;;AACA,SAAS,kBAAkB;AAG3B,IAAM,UAAU;AAEhB,IAAM,KAAK,CAAC,SAAiB,WAAW,SAAS,IAAI;AAErD,IAAM,aAA8B,EAAE,IAAI,WAAW,MAAM,eAAe;AAC1E,IAAM,oBAAqC,EAAE,IAAI,eAAe,MAAM,cAAc;AAE7E,IAAM,sBAAoD;AAAA,EAC/D;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,WAAW,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,IACrC,oBAAoB;AAAA,IACpB,QAAQ,CAAC,UAAU;AAAA,IACnB,SAAS;AAAA,MACP,MAAM,EAAE,KAAK,GAAG,uEAAuE,GAAG,QAAQ,GAAG;AAAA,IACvG;AAAA,IACA,YAAY;AAAA,MACV;AAAA,QACE,KAAK,GAAG,8EAA8E;AAAA,QACtF,UAAU;AAAA,QACV,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,sBAAoD;AAAA,EAC/D;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,WAAW,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,IACrC,oBAAoB;AAAA,IACpB,QAAQ,CAAC,EAAE,IAAI,WAAW,MAAM,eAAe,CAAC;AAAA,IAChD,SAAS;AAAA,MACP,MAAM,EAAE,KAAK,GAAG,uEAAuE,GAAG,QAAQ,GAAG;AAAA,MACrG,QAAQ,EAAE,KAAK,GAAG,8EAA8E,GAAG,QAAQ,IAAI,aAAa,MAAM,OAAO,iBAAiB,UAAU,CAAC,QAAQ,EAAE;AAAA,MAC/K,UAAU,EAAE,KAAK,GAAG,0EAA0E,GAAG,QAAQ,IAAI,UAAU,CAAC,QAAQ,EAAE;AAAA,IACpI;AAAA,IACA,YAAY;AAAA,MACV;AAAA,QACE,KAAK,GAAG,8EAA8E;AAAA,QACtF,UAAU;AAAA,QACV,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,qBAAmD;AAAA,EAC9D;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,WAAW,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,IACrC,oBAAoB;AAAA,IACpB,QAAQ,CAAC,iBAAiB;AAAA,IAC1B,SAAS;AAAA,MACP,MAAM,EAAE,KAAK,GAAG,+DAA+D,GAAG,QAAQ,IAAI;AAAA,IAChG;AAAA,EACF;AACF;","names":[]}
|