@camstack/addon-vision 0.1.1 → 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.
- package/dist/addons/animal-classifier/index.js +999 -823
- package/dist/addons/animal-classifier/index.js.map +1 -1
- package/dist/addons/animal-classifier/index.mjs +242 -7
- package/dist/addons/animal-classifier/index.mjs.map +1 -1
- package/dist/addons/audio-classification/index.js +501 -379
- package/dist/addons/audio-classification/index.js.map +1 -1
- package/dist/addons/audio-classification/index.mjs +224 -4
- package/dist/addons/audio-classification/index.mjs.map +1 -1
- package/dist/addons/bird-global-classifier/index.js +1002 -826
- package/dist/addons/bird-global-classifier/index.js.map +1 -1
- package/dist/addons/bird-global-classifier/index.mjs +248 -7
- package/dist/addons/bird-global-classifier/index.mjs.map +1 -1
- package/dist/addons/bird-nabirds-classifier/index.js +1002 -826
- package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
- package/dist/addons/bird-nabirds-classifier/index.mjs +289 -7
- package/dist/addons/bird-nabirds-classifier/index.mjs.map +1 -1
- package/dist/addons/face-detection/index.js +1196 -935
- package/dist/addons/face-detection/index.js.map +1 -1
- package/dist/addons/face-detection/index.mjs +227 -7
- package/dist/addons/face-detection/index.mjs.map +1 -1
- package/dist/addons/face-recognition/index.js +1003 -808
- package/dist/addons/face-recognition/index.js.map +1 -1
- package/dist/addons/face-recognition/index.mjs +197 -6
- package/dist/addons/face-recognition/index.mjs.map +1 -1
- package/dist/addons/motion-detection/index.js +214 -111
- package/dist/addons/motion-detection/index.js.map +1 -1
- package/dist/addons/motion-detection/index.mjs +12 -9
- package/dist/addons/motion-detection/index.mjs.map +1 -1
- package/dist/addons/object-detection/index.js +1287 -1083
- package/dist/addons/object-detection/index.js.map +1 -1
- package/dist/addons/object-detection/index.mjs +373 -7
- package/dist/addons/object-detection/index.mjs.map +1 -1
- package/dist/addons/plate-detection/index.js +1075 -869
- package/dist/addons/plate-detection/index.js.map +1 -1
- package/dist/addons/plate-detection/index.mjs +230 -7
- package/dist/addons/plate-detection/index.mjs.map +1 -1
- package/dist/addons/plate-recognition/index.js +684 -506
- package/dist/addons/plate-recognition/index.js.map +1 -1
- package/dist/addons/plate-recognition/index.mjs +244 -5
- package/dist/addons/plate-recognition/index.mjs.map +1 -1
- package/dist/addons/segmentation-refiner/index.js +967 -791
- package/dist/addons/segmentation-refiner/index.js.map +1 -1
- package/dist/addons/segmentation-refiner/index.mjs +21 -17
- package/dist/addons/segmentation-refiner/index.mjs.map +1 -1
- package/dist/addons/vehicle-classifier/index.js +581 -411
- package/dist/addons/vehicle-classifier/index.js.map +1 -1
- package/dist/addons/vehicle-classifier/index.mjs +20 -16
- package/dist/addons/vehicle-classifier/index.mjs.map +1 -1
- package/dist/chunk-2YMA6QOV.mjs +193 -0
- package/dist/chunk-2YMA6QOV.mjs.map +1 -0
- package/dist/chunk-3IIFBJCD.mjs +45 -0
- package/dist/chunk-BS4DKYGN.mjs +48 -0
- package/dist/{chunk-7DYHXUPZ.mjs.map → chunk-BS4DKYGN.mjs.map} +1 -1
- package/dist/chunk-DE7I3VHO.mjs +106 -0
- package/dist/{chunk-KUO2BVFY.mjs.map → chunk-DE7I3VHO.mjs.map} +1 -1
- package/dist/chunk-F6D2OZ36.mjs +89 -0
- package/dist/chunk-F6D2OZ36.mjs.map +1 -0
- package/dist/chunk-GAOIFQDX.mjs +59 -0
- package/dist/chunk-GAOIFQDX.mjs.map +1 -0
- package/dist/chunk-HUIX2XVR.mjs +159 -0
- package/dist/chunk-HUIX2XVR.mjs.map +1 -0
- package/dist/chunk-K36R6HWY.mjs +51 -0
- package/dist/{chunk-XZ6ZMXXU.mjs.map → chunk-K36R6HWY.mjs.map} +1 -1
- package/dist/chunk-MBTAI3WE.mjs +78 -0
- package/dist/chunk-MBTAI3WE.mjs.map +1 -0
- package/dist/chunk-MGT6RUVX.mjs +423 -0
- package/dist/{chunk-BP7H4NFS.mjs.map → chunk-MGT6RUVX.mjs.map} +1 -1
- package/dist/chunk-PIFS7AIT.mjs +446 -0
- package/dist/chunk-PIFS7AIT.mjs.map +1 -0
- package/dist/chunk-WG66JYYW.mjs +116 -0
- package/dist/{chunk-22BHCDT5.mjs.map → chunk-WG66JYYW.mjs.map} +1 -1
- package/dist/chunk-XD7WGXHZ.mjs +82 -0
- package/dist/{chunk-DUN6XU3N.mjs.map → chunk-XD7WGXHZ.mjs.map} +1 -1
- package/dist/chunk-YYDM6V2F.mjs +113 -0
- package/dist/{chunk-BR2FPGOX.mjs.map → chunk-YYDM6V2F.mjs.map} +1 -1
- package/dist/chunk-ZK7P3TZN.mjs +286 -0
- package/dist/chunk-ZK7P3TZN.mjs.map +1 -0
- package/dist/index.js +4443 -3925
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2698 -250
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -3
- package/dist/chunk-22BHCDT5.mjs +0 -101
- package/dist/chunk-6DJZZR64.mjs +0 -336
- package/dist/chunk-6DJZZR64.mjs.map +0 -1
- package/dist/chunk-7DYHXUPZ.mjs +0 -36
- package/dist/chunk-BJTO5JO5.mjs +0 -11
- package/dist/chunk-BP7H4NFS.mjs +0 -412
- package/dist/chunk-BR2FPGOX.mjs +0 -98
- package/dist/chunk-DNQNGDR4.mjs +0 -256
- package/dist/chunk-DNQNGDR4.mjs.map +0 -1
- package/dist/chunk-DUN6XU3N.mjs +0 -72
- package/dist/chunk-EPNWLSCG.mjs +0 -387
- package/dist/chunk-EPNWLSCG.mjs.map +0 -1
- package/dist/chunk-G32RCIUI.mjs +0 -645
- package/dist/chunk-G32RCIUI.mjs.map +0 -1
- package/dist/chunk-GR65KM6X.mjs +0 -289
- package/dist/chunk-GR65KM6X.mjs.map +0 -1
- package/dist/chunk-H7LMBTS5.mjs +0 -276
- package/dist/chunk-H7LMBTS5.mjs.map +0 -1
- package/dist/chunk-IK4XIQPC.mjs +0 -242
- package/dist/chunk-IK4XIQPC.mjs.map +0 -1
- package/dist/chunk-J6VNIIYX.mjs +0 -269
- package/dist/chunk-J6VNIIYX.mjs.map +0 -1
- package/dist/chunk-KUO2BVFY.mjs +0 -90
- package/dist/chunk-ML2JX43J.mjs +0 -248
- package/dist/chunk-ML2JX43J.mjs.map +0 -1
- package/dist/chunk-WUMV524J.mjs +0 -379
- package/dist/chunk-WUMV524J.mjs.map +0 -1
- package/dist/chunk-XZ6ZMXXU.mjs +0 -39
- /package/dist/{chunk-BJTO5JO5.mjs.map → chunk-3IIFBJCD.mjs.map} +0 -0
package/dist/chunk-DNQNGDR4.mjs
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MLPACKAGE_FILES
|
|
3
|
-
} from "./chunk-BP7H4NFS.mjs";
|
|
4
|
-
import {
|
|
5
|
-
cropRegion,
|
|
6
|
-
resizeAndNormalize
|
|
7
|
-
} from "./chunk-22BHCDT5.mjs";
|
|
8
|
-
import {
|
|
9
|
-
resolveEngine
|
|
10
|
-
} from "./chunk-6DJZZR64.mjs";
|
|
11
|
-
|
|
12
|
-
// src/catalogs/face-recognition-models.ts
|
|
13
|
-
import { hfModelUrl } from "@camstack/types";
|
|
14
|
-
var HF_REPO = "camstack/camstack-models";
|
|
15
|
-
var FACE_EMBEDDING_LABELS = [
|
|
16
|
-
{ id: "embedding", name: "Face Embedding" }
|
|
17
|
-
];
|
|
18
|
-
var FACE_RECOGNITION_MODELS = [
|
|
19
|
-
{
|
|
20
|
-
id: "arcface-r100",
|
|
21
|
-
name: "ArcFace R100",
|
|
22
|
-
description: "ArcFace ResNet-100 \u2014 high-accuracy face recognition embeddings",
|
|
23
|
-
inputSize: { width: 112, height: 112 },
|
|
24
|
-
inputLayout: "nhwc",
|
|
25
|
-
labels: FACE_EMBEDDING_LABELS,
|
|
26
|
-
formats: {
|
|
27
|
-
onnx: {
|
|
28
|
-
url: hfModelUrl(HF_REPO, "faceRecognition/arcface/onnx/camstack-arcface-arcface.onnx"),
|
|
29
|
-
sizeMB: 130
|
|
30
|
-
},
|
|
31
|
-
coreml: {
|
|
32
|
-
url: hfModelUrl(HF_REPO, "faceRecognition/arcface/coreml/camstack-arcface-r100.mlpackage"),
|
|
33
|
-
sizeMB: 65,
|
|
34
|
-
isDirectory: true,
|
|
35
|
-
files: MLPACKAGE_FILES,
|
|
36
|
-
runtimes: ["python"]
|
|
37
|
-
},
|
|
38
|
-
openvino: {
|
|
39
|
-
url: hfModelUrl(HF_REPO, "faceRecognition/arcface/openvino/camstack-arcface-r100.xml"),
|
|
40
|
-
sizeMB: 65,
|
|
41
|
-
runtimes: ["python"]
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
];
|
|
46
|
-
|
|
47
|
-
// src/shared/postprocess/arcface.ts
|
|
48
|
-
function l2Normalize(vec) {
|
|
49
|
-
let sumSq = 0;
|
|
50
|
-
for (let i = 0; i < vec.length; i++) {
|
|
51
|
-
sumSq += vec[i] * vec[i];
|
|
52
|
-
}
|
|
53
|
-
const norm = Math.sqrt(sumSq);
|
|
54
|
-
if (norm === 0) return new Float32Array(vec.length);
|
|
55
|
-
const out = new Float32Array(vec.length);
|
|
56
|
-
for (let i = 0; i < vec.length; i++) {
|
|
57
|
-
out[i] = vec[i] / norm;
|
|
58
|
-
}
|
|
59
|
-
return out;
|
|
60
|
-
}
|
|
61
|
-
function cosineSimilarity(a, b) {
|
|
62
|
-
if (a.length !== b.length) throw new Error("Embedding length mismatch");
|
|
63
|
-
let dot = 0;
|
|
64
|
-
for (let i = 0; i < a.length; i++) {
|
|
65
|
-
dot += a[i] * b[i];
|
|
66
|
-
}
|
|
67
|
-
return dot;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// src/addons/face-recognition/index.ts
|
|
71
|
-
var IDENTITY_LABEL = { id: "identity", name: "Identity" };
|
|
72
|
-
var IDENTITY_LABELS = [IDENTITY_LABEL];
|
|
73
|
-
var FACE_REC_CLASS_MAP = { mapping: {}, preserveOriginal: true };
|
|
74
|
-
var REQUIRED_STEPS = [
|
|
75
|
-
{ slot: "cropper", outputClasses: ["face"], description: "Requires a face detector" }
|
|
76
|
-
];
|
|
77
|
-
var FaceRecognitionAddon = class {
|
|
78
|
-
id = "face-recognition";
|
|
79
|
-
slot = "classifier";
|
|
80
|
-
inputClasses = ["face"];
|
|
81
|
-
outputClasses = ["identity:*"];
|
|
82
|
-
slotPriority = 0;
|
|
83
|
-
requiredSteps = REQUIRED_STEPS;
|
|
84
|
-
manifest = {
|
|
85
|
-
id: "face-recognition",
|
|
86
|
-
name: "Face Recognition",
|
|
87
|
-
version: "0.1.0",
|
|
88
|
-
description: "ArcFace-based face recognition \u2014 produces 512-d identity embeddings",
|
|
89
|
-
slot: "classifier",
|
|
90
|
-
labelOutputType: "face",
|
|
91
|
-
inputClasses: ["face"],
|
|
92
|
-
outputClasses: ["identity:*"],
|
|
93
|
-
requiredSteps: REQUIRED_STEPS,
|
|
94
|
-
supportsCustomModels: false,
|
|
95
|
-
mayRequirePython: false,
|
|
96
|
-
defaultConfig: {
|
|
97
|
-
modelId: "arcface-r100",
|
|
98
|
-
runtime: "node",
|
|
99
|
-
backend: "cpu"
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
engine = null;
|
|
103
|
-
modelEntry;
|
|
104
|
-
resolvedConfig = null;
|
|
105
|
-
ctx = null;
|
|
106
|
-
getModelRequirements() {
|
|
107
|
-
return FACE_RECOGNITION_MODELS.map((m) => ({
|
|
108
|
-
modelId: m.id,
|
|
109
|
-
name: m.name,
|
|
110
|
-
minRAM_MB: 400,
|
|
111
|
-
accuracyScore: 90,
|
|
112
|
-
formats: Object.keys(m.formats)
|
|
113
|
-
}));
|
|
114
|
-
}
|
|
115
|
-
configure(config) {
|
|
116
|
-
this.resolvedConfig = config;
|
|
117
|
-
}
|
|
118
|
-
async initialize(ctx) {
|
|
119
|
-
this.ctx = ctx;
|
|
120
|
-
const cfg = ctx.addonConfig;
|
|
121
|
-
const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "arcface-r100";
|
|
122
|
-
const entry = FACE_RECOGNITION_MODELS.find((m) => m.id === modelId);
|
|
123
|
-
if (!entry) {
|
|
124
|
-
throw new Error(`FaceRecognitionAddon: unknown modelId "${modelId}"`);
|
|
125
|
-
}
|
|
126
|
-
this.modelEntry = entry;
|
|
127
|
-
}
|
|
128
|
-
async classify(input) {
|
|
129
|
-
if (!this.engine) await this.ensureEngine();
|
|
130
|
-
const start = Date.now();
|
|
131
|
-
const { width: inputW, height: inputH } = this.modelEntry.inputSize;
|
|
132
|
-
const faceCrop = await cropRegion(input.frame.data, input.roi);
|
|
133
|
-
const layout = this.modelEntry.inputLayout ?? "nhwc";
|
|
134
|
-
const normalization = this.modelEntry.inputNormalization ?? "zero-one";
|
|
135
|
-
const normalized = await resizeAndNormalize(faceCrop, inputW, inputH, normalization, layout);
|
|
136
|
-
const rawEmbedding = await this.engine.run(normalized, [1, inputH, inputW, 3]);
|
|
137
|
-
const embedding = l2Normalize(rawEmbedding);
|
|
138
|
-
return {
|
|
139
|
-
classifications: [
|
|
140
|
-
{
|
|
141
|
-
class: "identity",
|
|
142
|
-
score: 1,
|
|
143
|
-
embedding
|
|
144
|
-
}
|
|
145
|
-
],
|
|
146
|
-
inferenceMs: Date.now() - start,
|
|
147
|
-
modelId: this.modelEntry.id
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
async ensureEngine() {
|
|
151
|
-
const config = this.resolvedConfig;
|
|
152
|
-
const modelId = config?.modelId ?? this.modelEntry.id;
|
|
153
|
-
const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
|
|
154
|
-
const backend = config?.backend ?? "cpu";
|
|
155
|
-
const format = config?.format ?? "onnx";
|
|
156
|
-
const entry = FACE_RECOGNITION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
|
|
157
|
-
this.modelEntry = entry;
|
|
158
|
-
const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
|
|
159
|
-
if (this.ctx.models) {
|
|
160
|
-
await this.ctx.models.ensure(modelId, format);
|
|
161
|
-
}
|
|
162
|
-
const resolved = await resolveEngine({
|
|
163
|
-
runtime,
|
|
164
|
-
backend,
|
|
165
|
-
modelEntry: entry,
|
|
166
|
-
modelsDir,
|
|
167
|
-
models: this.ctx.models
|
|
168
|
-
});
|
|
169
|
-
this.engine = resolved.engine;
|
|
170
|
-
}
|
|
171
|
-
async shutdown() {
|
|
172
|
-
await this.engine?.dispose();
|
|
173
|
-
}
|
|
174
|
-
getConfigSchema() {
|
|
175
|
-
return {
|
|
176
|
-
sections: [
|
|
177
|
-
{
|
|
178
|
-
id: "model",
|
|
179
|
-
title: "Model",
|
|
180
|
-
columns: 1,
|
|
181
|
-
fields: [
|
|
182
|
-
{
|
|
183
|
-
key: "modelId",
|
|
184
|
-
label: "Model",
|
|
185
|
-
type: "model-selector",
|
|
186
|
-
catalog: [...FACE_RECOGNITION_MODELS],
|
|
187
|
-
allowCustom: false,
|
|
188
|
-
allowConversion: false,
|
|
189
|
-
acceptFormats: ["onnx", "coreml", "openvino"],
|
|
190
|
-
requiredMetadata: ["inputSize", "labels", "outputFormat"],
|
|
191
|
-
outputFormatHint: "embedding"
|
|
192
|
-
}
|
|
193
|
-
]
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
id: "runtime",
|
|
197
|
-
title: "Runtime",
|
|
198
|
-
columns: 2,
|
|
199
|
-
fields: [
|
|
200
|
-
{
|
|
201
|
-
key: "runtime",
|
|
202
|
-
label: "Runtime",
|
|
203
|
-
type: "select",
|
|
204
|
-
options: [
|
|
205
|
-
{ value: "auto", label: "Auto" },
|
|
206
|
-
{ value: "onnx", label: "ONNX Runtime" },
|
|
207
|
-
{ value: "coreml", label: "CoreML (Apple)" },
|
|
208
|
-
{ value: "openvino", label: "OpenVINO (Intel)" }
|
|
209
|
-
]
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
key: "backend",
|
|
213
|
-
label: "Backend",
|
|
214
|
-
type: "select",
|
|
215
|
-
showWhen: { field: "runtime", equals: "onnx" },
|
|
216
|
-
options: [
|
|
217
|
-
{ value: "auto", label: "Auto" },
|
|
218
|
-
{ value: "cpu", label: "CPU" },
|
|
219
|
-
{ value: "coreml", label: "CoreML" },
|
|
220
|
-
{ value: "cuda", label: "CUDA (NVIDIA)" }
|
|
221
|
-
]
|
|
222
|
-
}
|
|
223
|
-
]
|
|
224
|
-
}
|
|
225
|
-
]
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
getClassMap() {
|
|
229
|
-
return FACE_REC_CLASS_MAP;
|
|
230
|
-
}
|
|
231
|
-
getModelCatalog() {
|
|
232
|
-
return [...FACE_RECOGNITION_MODELS];
|
|
233
|
-
}
|
|
234
|
-
getAvailableModels() {
|
|
235
|
-
return [];
|
|
236
|
-
}
|
|
237
|
-
getActiveLabels() {
|
|
238
|
-
return IDENTITY_LABELS;
|
|
239
|
-
}
|
|
240
|
-
async probe() {
|
|
241
|
-
return {
|
|
242
|
-
available: true,
|
|
243
|
-
runtime: this.engine?.runtime ?? "onnx",
|
|
244
|
-
device: this.engine?.device ?? "cpu",
|
|
245
|
-
capabilities: ["fp32"]
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
export {
|
|
251
|
-
l2Normalize,
|
|
252
|
-
cosineSimilarity,
|
|
253
|
-
FACE_RECOGNITION_MODELS,
|
|
254
|
-
FaceRecognitionAddon
|
|
255
|
-
};
|
|
256
|
-
//# sourceMappingURL=chunk-DNQNGDR4.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/catalogs/face-recognition-models.ts","../src/shared/postprocess/arcface.ts","../src/addons/face-recognition/index.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 FACE_EMBEDDING_LABELS: readonly LabelDefinition[] = [\n { id: 'embedding', name: 'Face Embedding' },\n] as const\n\nexport const FACE_RECOGNITION_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'arcface-r100',\n name: 'ArcFace R100',\n description: 'ArcFace ResNet-100 — high-accuracy face recognition embeddings',\n inputSize: { width: 112, height: 112 },\n inputLayout: 'nhwc',\n labels: FACE_EMBEDDING_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'faceRecognition/arcface/onnx/camstack-arcface-arcface.onnx'),\n sizeMB: 130,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'faceRecognition/arcface/coreml/camstack-arcface-r100.mlpackage'),\n sizeMB: 65,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'faceRecognition/arcface/openvino/camstack-arcface-r100.xml'),\n sizeMB: 65,\n runtimes: ['python'],\n },\n },\n },\n] as const\n","/** L2 normalize a vector in-place, returning a new Float32Array */\nexport function l2Normalize(vec: Float32Array): Float32Array {\n let sumSq = 0\n for (let i = 0; i < vec.length; i++) {\n sumSq += vec[i]! * vec[i]!\n }\n const norm = Math.sqrt(sumSq)\n if (norm === 0) return new Float32Array(vec.length)\n\n const out = new Float32Array(vec.length)\n for (let i = 0; i < vec.length; i++) {\n out[i] = vec[i]! / norm\n }\n return out\n}\n\n/** Cosine similarity between two embeddings (assumes they are already L2-normalized) */\nexport function cosineSimilarity(a: Float32Array, b: Float32Array): number {\n if (a.length !== b.length) throw new Error('Embedding length mismatch')\n let dot = 0\n for (let i = 0; i < a.length; i++) {\n dot += a[i]! * b[i]!\n }\n return dot\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 RequiredStep,\n ModelRequirement,\n ResolvedInferenceConfig,\n} from '@camstack/types'\nimport { FACE_RECOGNITION_MODELS } from '../../catalogs/face-recognition-models.js'\nimport { cropRegion, resizeAndNormalize } from '../../shared/image-utils.js'\nimport { l2Normalize } from '../../shared/postprocess/arcface.js'\nimport { resolveEngine } from '../../shared/engine-resolver.js'\n\nconst IDENTITY_LABEL: LabelDefinition = { id: 'identity', name: 'Identity' }\nconst IDENTITY_LABELS: readonly LabelDefinition[] = [IDENTITY_LABEL]\nconst FACE_REC_CLASS_MAP: ClassMapDefinition = { mapping: {}, preserveOriginal: true }\n\nconst REQUIRED_STEPS: readonly RequiredStep[] = [\n { slot: 'cropper', outputClasses: ['face'], description: 'Requires a face detector' },\n]\n\nexport default class FaceRecognitionAddon implements IClassifierProvider, IDetectionAddon {\n readonly id = 'face-recognition'\n readonly slot = 'classifier' as const\n readonly inputClasses = ['face'] as const\n readonly outputClasses = ['identity:*'] as const\n readonly slotPriority = 0\n readonly requiredSteps = REQUIRED_STEPS\n readonly manifest: AddonManifest = {\n id: 'face-recognition',\n name: 'Face Recognition',\n version: '0.1.0',\n\n description: 'ArcFace-based face recognition — produces 512-d identity embeddings',\n\n slot: 'classifier',\n labelOutputType: 'face',\n inputClasses: ['face'],\n outputClasses: ['identity:*'],\n requiredSteps: REQUIRED_STEPS,\n supportsCustomModels: false,\n mayRequirePython: false,\n defaultConfig: {\n modelId: 'arcface-r100',\n runtime: 'node',\n backend: 'cpu',\n },\n }\n\n private engine: IInferenceEngine | null = null\n private modelEntry!: ModelCatalogEntry\n private resolvedConfig: ResolvedInferenceConfig | null = null\n private ctx: AddonContext | null = null\n\n getModelRequirements(): ModelRequirement[] {\n return FACE_RECOGNITION_MODELS.map((m) => ({\n modelId: m.id,\n name: m.name,\n minRAM_MB: 400,\n accuracyScore: 90,\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 ?? 'arcface-r100'\n\n const entry = FACE_RECOGNITION_MODELS.find((m) => m.id === modelId)\n if (!entry) {\n throw new Error(`FaceRecognitionAddon: unknown modelId \"${modelId}\"`)\n }\n this.modelEntry = entry\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 face region\n const faceCrop = await cropRegion(input.frame.data, input.roi)\n\n // Resize to 112x112, NHWC layout (ArcFace expects NHWC)\n const layout = this.modelEntry.inputLayout ?? 'nhwc'\n const normalization = this.modelEntry.inputNormalization ?? 'zero-one'\n const normalized = await resizeAndNormalize(faceCrop, inputW, inputH, normalization, layout)\n\n // Run inference — output is 512-d embedding\n const rawEmbedding = await this.engine!.run(normalized, [1, inputH, inputW, 3])\n\n // L2 normalize the embedding\n const embedding = l2Normalize(rawEmbedding)\n\n return {\n classifications: [\n {\n class: 'identity',\n score: 1.0,\n embedding,\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 = FACE_RECOGNITION_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: [...FACE_RECOGNITION_MODELS],\n allowCustom: false,\n allowConversion: false,\n acceptFormats: ['onnx', 'coreml', 'openvino'],\n requiredMetadata: ['inputSize', 'labels', 'outputFormat'],\n outputFormatHint: 'embedding',\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 }\n }\n\n getClassMap(): ClassMapDefinition {\n return FACE_REC_CLASS_MAP\n }\n\n getModelCatalog(): ModelCatalogEntry[] {\n return [...FACE_RECOGNITION_MODELS]\n }\n\n getAvailableModels(): DetectionModel[] {\n return []\n }\n\n getActiveLabels(): readonly LabelDefinition[] {\n return IDENTITY_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":[]}
|
package/dist/chunk-DUN6XU3N.mjs
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MLPACKAGE_FILES
|
|
3
|
-
} from "./chunk-BP7H4NFS.mjs";
|
|
4
|
-
|
|
5
|
-
// src/catalogs/animal-classification-models.ts
|
|
6
|
-
import { hfModelUrl } from "@camstack/types";
|
|
7
|
-
var HF_REPO = "camstack/camstack-models";
|
|
8
|
-
var hf = (path) => hfModelUrl(HF_REPO, path);
|
|
9
|
-
var BIRD_LABEL = { id: "species", name: "Bird Species" };
|
|
10
|
-
var ANIMAL_TYPE_LABEL = { id: "animal-type", name: "Animal Type" };
|
|
11
|
-
var BIRD_SPECIES_MODELS = [
|
|
12
|
-
{
|
|
13
|
-
id: "bird-species-525",
|
|
14
|
-
name: "Bird Species (525)",
|
|
15
|
-
description: "EfficientNet bird species classifier \u2014 525 species, MIT license",
|
|
16
|
-
inputSize: { width: 224, height: 224 },
|
|
17
|
-
inputNormalization: "imagenet",
|
|
18
|
-
labels: [BIRD_LABEL],
|
|
19
|
-
formats: {
|
|
20
|
-
onnx: { url: hf("animalClassification/bird-species/onnx/camstack-bird-species-525.onnx"), sizeMB: 32 }
|
|
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
|
-
]
|
|
29
|
-
}
|
|
30
|
-
];
|
|
31
|
-
var BIRD_NABIRDS_MODELS = [
|
|
32
|
-
{
|
|
33
|
-
id: "bird-nabirds-404",
|
|
34
|
-
name: "NABirds (404 species)",
|
|
35
|
-
description: "ResNet50 trained on NABirds \u2014 404 North American species with ONNX, CoreML, OpenVINO",
|
|
36
|
-
inputSize: { width: 224, height: 224 },
|
|
37
|
-
inputNormalization: "imagenet",
|
|
38
|
-
labels: [{ id: "species", name: "Bird Species" }],
|
|
39
|
-
formats: {
|
|
40
|
-
onnx: { url: hf("animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404.onnx"), sizeMB: 93 },
|
|
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
|
-
]
|
|
51
|
-
}
|
|
52
|
-
];
|
|
53
|
-
var ANIMAL_TYPE_MODELS = [
|
|
54
|
-
{
|
|
55
|
-
id: "animals-10",
|
|
56
|
-
name: "Animal Classifier (10)",
|
|
57
|
-
description: "ViT-based animal type classifier \u2014 cat, cow, dog, dolphin, eagle, panda, horse, monkey, sheep, spider",
|
|
58
|
-
inputSize: { width: 224, height: 224 },
|
|
59
|
-
inputNormalization: "imagenet",
|
|
60
|
-
labels: [ANIMAL_TYPE_LABEL],
|
|
61
|
-
formats: {
|
|
62
|
-
onnx: { url: hf("animalClassification/animals-10/onnx/camstack-animals-10.onnx"), sizeMB: 328 }
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
];
|
|
66
|
-
|
|
67
|
-
export {
|
|
68
|
-
BIRD_SPECIES_MODELS,
|
|
69
|
-
BIRD_NABIRDS_MODELS,
|
|
70
|
-
ANIMAL_TYPE_MODELS
|
|
71
|
-
};
|
|
72
|
-
//# sourceMappingURL=chunk-DUN6XU3N.mjs.map
|