@camstack/addon-vision 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/addons/animal-classifier/index.js +999 -822
  2. package/dist/addons/animal-classifier/index.js.map +1 -1
  3. package/dist/addons/animal-classifier/index.mjs +242 -7
  4. package/dist/addons/animal-classifier/index.mjs.map +1 -1
  5. package/dist/addons/audio-classification/index.js +501 -378
  6. package/dist/addons/audio-classification/index.js.map +1 -1
  7. package/dist/addons/audio-classification/index.mjs +224 -4
  8. package/dist/addons/audio-classification/index.mjs.map +1 -1
  9. package/dist/addons/bird-global-classifier/index.js +1002 -825
  10. package/dist/addons/bird-global-classifier/index.js.map +1 -1
  11. package/dist/addons/bird-global-classifier/index.mjs +248 -7
  12. package/dist/addons/bird-global-classifier/index.mjs.map +1 -1
  13. package/dist/addons/bird-nabirds-classifier/index.js +1002 -825
  14. package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
  15. package/dist/addons/bird-nabirds-classifier/index.mjs +289 -7
  16. package/dist/addons/bird-nabirds-classifier/index.mjs.map +1 -1
  17. package/dist/addons/face-detection/index.js +1196 -934
  18. package/dist/addons/face-detection/index.js.map +1 -1
  19. package/dist/addons/face-detection/index.mjs +227 -7
  20. package/dist/addons/face-detection/index.mjs.map +1 -1
  21. package/dist/addons/face-recognition/index.js +1003 -807
  22. package/dist/addons/face-recognition/index.js.map +1 -1
  23. package/dist/addons/face-recognition/index.mjs +197 -6
  24. package/dist/addons/face-recognition/index.mjs.map +1 -1
  25. package/dist/addons/motion-detection/index.js +214 -111
  26. package/dist/addons/motion-detection/index.js.map +1 -1
  27. package/dist/addons/motion-detection/index.mjs +12 -9
  28. package/dist/addons/motion-detection/index.mjs.map +1 -1
  29. package/dist/addons/object-detection/index.js +1287 -1082
  30. package/dist/addons/object-detection/index.js.map +1 -1
  31. package/dist/addons/object-detection/index.mjs +373 -7
  32. package/dist/addons/object-detection/index.mjs.map +1 -1
  33. package/dist/addons/plate-detection/index.js +1075 -868
  34. package/dist/addons/plate-detection/index.js.map +1 -1
  35. package/dist/addons/plate-detection/index.mjs +230 -7
  36. package/dist/addons/plate-detection/index.mjs.map +1 -1
  37. package/dist/addons/plate-recognition/index.js +684 -505
  38. package/dist/addons/plate-recognition/index.js.map +1 -1
  39. package/dist/addons/plate-recognition/index.mjs +244 -5
  40. package/dist/addons/plate-recognition/index.mjs.map +1 -1
  41. package/dist/addons/segmentation-refiner/index.js +967 -790
  42. package/dist/addons/segmentation-refiner/index.js.map +1 -1
  43. package/dist/addons/segmentation-refiner/index.mjs +21 -17
  44. package/dist/addons/segmentation-refiner/index.mjs.map +1 -1
  45. package/dist/addons/vehicle-classifier/index.js +581 -410
  46. package/dist/addons/vehicle-classifier/index.js.map +1 -1
  47. package/dist/addons/vehicle-classifier/index.mjs +20 -16
  48. package/dist/addons/vehicle-classifier/index.mjs.map +1 -1
  49. package/dist/chunk-2YMA6QOV.mjs +193 -0
  50. package/dist/chunk-2YMA6QOV.mjs.map +1 -0
  51. package/dist/chunk-3IIFBJCD.mjs +45 -0
  52. package/dist/chunk-BS4DKYGN.mjs +48 -0
  53. package/dist/{chunk-7DYHXUPZ.mjs.map → chunk-BS4DKYGN.mjs.map} +1 -1
  54. package/dist/chunk-DE7I3VHO.mjs +106 -0
  55. package/dist/{chunk-KUO2BVFY.mjs.map → chunk-DE7I3VHO.mjs.map} +1 -1
  56. package/dist/chunk-F6D2OZ36.mjs +89 -0
  57. package/dist/chunk-F6D2OZ36.mjs.map +1 -0
  58. package/dist/chunk-GAOIFQDX.mjs +59 -0
  59. package/dist/chunk-GAOIFQDX.mjs.map +1 -0
  60. package/dist/chunk-HUIX2XVR.mjs +159 -0
  61. package/dist/chunk-HUIX2XVR.mjs.map +1 -0
  62. package/dist/chunk-K36R6HWY.mjs +51 -0
  63. package/dist/{chunk-XZ6ZMXXU.mjs.map → chunk-K36R6HWY.mjs.map} +1 -1
  64. package/dist/chunk-MBTAI3WE.mjs +78 -0
  65. package/dist/chunk-MBTAI3WE.mjs.map +1 -0
  66. package/dist/chunk-MGT6RUVX.mjs +423 -0
  67. package/dist/{chunk-BP7H4NFS.mjs.map → chunk-MGT6RUVX.mjs.map} +1 -1
  68. package/dist/chunk-PIFS7AIT.mjs +446 -0
  69. package/dist/{chunk-2IOKI4ES.mjs.map → chunk-PIFS7AIT.mjs.map} +1 -1
  70. package/dist/chunk-WG66JYYW.mjs +116 -0
  71. package/dist/{chunk-22BHCDT5.mjs.map → chunk-WG66JYYW.mjs.map} +1 -1
  72. package/dist/chunk-XD7WGXHZ.mjs +82 -0
  73. package/dist/{chunk-DUN6XU3N.mjs.map → chunk-XD7WGXHZ.mjs.map} +1 -1
  74. package/dist/chunk-YYDM6V2F.mjs +113 -0
  75. package/dist/{chunk-BR2FPGOX.mjs.map → chunk-YYDM6V2F.mjs.map} +1 -1
  76. package/dist/chunk-ZK7P3TZN.mjs +286 -0
  77. package/dist/chunk-ZK7P3TZN.mjs.map +1 -0
  78. package/dist/index.js +4443 -3924
  79. package/dist/index.js.map +1 -1
  80. package/dist/index.mjs +2698 -250
  81. package/dist/index.mjs.map +1 -1
  82. package/package.json +1 -1
  83. package/dist/chunk-22BHCDT5.mjs +0 -101
  84. package/dist/chunk-2IOKI4ES.mjs +0 -335
  85. package/dist/chunk-7DYHXUPZ.mjs +0 -36
  86. package/dist/chunk-BJTO5JO5.mjs +0 -11
  87. package/dist/chunk-BP7H4NFS.mjs +0 -412
  88. package/dist/chunk-BR2FPGOX.mjs +0 -98
  89. package/dist/chunk-D6WEHN33.mjs +0 -276
  90. package/dist/chunk-D6WEHN33.mjs.map +0 -1
  91. package/dist/chunk-DRYFGARD.mjs +0 -289
  92. package/dist/chunk-DRYFGARD.mjs.map +0 -1
  93. package/dist/chunk-DUN6XU3N.mjs +0 -72
  94. package/dist/chunk-ESLHNWWE.mjs +0 -387
  95. package/dist/chunk-ESLHNWWE.mjs.map +0 -1
  96. package/dist/chunk-JUQEW6ON.mjs +0 -256
  97. package/dist/chunk-JUQEW6ON.mjs.map +0 -1
  98. package/dist/chunk-KUO2BVFY.mjs +0 -90
  99. package/dist/chunk-R5J3WAUI.mjs +0 -645
  100. package/dist/chunk-R5J3WAUI.mjs.map +0 -1
  101. package/dist/chunk-XZ6ZMXXU.mjs +0 -39
  102. package/dist/chunk-YPU4WTXZ.mjs +0 -269
  103. package/dist/chunk-YPU4WTXZ.mjs.map +0 -1
  104. package/dist/chunk-YUCD2TFH.mjs +0 -242
  105. package/dist/chunk-YUCD2TFH.mjs.map +0 -1
  106. package/dist/chunk-ZTJENCFC.mjs +0 -379
  107. package/dist/chunk-ZTJENCFC.mjs.map +0 -1
  108. package/dist/chunk-ZWYXXCXP.mjs +0 -248
  109. package/dist/chunk-ZWYXXCXP.mjs.map +0 -1
  110. /package/dist/{chunk-BJTO5JO5.mjs.map → chunk-3IIFBJCD.mjs.map} +0 -0
@@ -1,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-2IOKI4ES.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-JUQEW6ON.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":[]}
@@ -1,90 +0,0 @@
1
- // src/shared/postprocess/yolo.ts
2
- function iou(a, b) {
3
- const ax1 = a.x;
4
- const ay1 = a.y;
5
- const ax2 = a.x + a.w;
6
- const ay2 = a.y + a.h;
7
- const bx1 = b.x;
8
- const by1 = b.y;
9
- const bx2 = b.x + b.w;
10
- const by2 = b.y + b.h;
11
- const interX1 = Math.max(ax1, bx1);
12
- const interY1 = Math.max(ay1, by1);
13
- const interX2 = Math.min(ax2, bx2);
14
- const interY2 = Math.min(ay2, by2);
15
- const interW = Math.max(0, interX2 - interX1);
16
- const interH = Math.max(0, interY2 - interY1);
17
- const interArea = interW * interH;
18
- if (interArea === 0) return 0;
19
- const areaA = a.w * a.h;
20
- const areaB = b.w * b.h;
21
- const unionArea = areaA + areaB - interArea;
22
- return unionArea === 0 ? 0 : interArea / unionArea;
23
- }
24
- function nms(boxes, iouThreshold) {
25
- const indices = boxes.map((_, i) => i).sort((a, b) => boxes[b].score - boxes[a].score);
26
- const kept = [];
27
- const suppressed = /* @__PURE__ */ new Set();
28
- for (const idx of indices) {
29
- if (suppressed.has(idx)) continue;
30
- kept.push(idx);
31
- for (const other of indices) {
32
- if (other === idx || suppressed.has(other)) continue;
33
- if (iou(boxes[idx].bbox, boxes[other].bbox) > iouThreshold) {
34
- suppressed.add(other);
35
- }
36
- }
37
- }
38
- return kept;
39
- }
40
- function yoloPostprocess(output, numClasses, numBoxes, options) {
41
- const { confidence, iouThreshold, labels, scale, padX, padY, originalWidth, originalHeight } = options;
42
- const candidates = [];
43
- for (let i = 0; i < numBoxes; i++) {
44
- const cx = output[0 * numBoxes + i];
45
- const cy = output[1 * numBoxes + i];
46
- const w = output[2 * numBoxes + i];
47
- const h = output[3 * numBoxes + i];
48
- let bestScore = -Infinity;
49
- let bestClass = 0;
50
- for (let j = 0; j < numClasses; j++) {
51
- const score = output[(4 + j) * numBoxes + i];
52
- if (score > bestScore) {
53
- bestScore = score;
54
- bestClass = j;
55
- }
56
- }
57
- if (bestScore < confidence) continue;
58
- const bbox = {
59
- x: cx - w / 2,
60
- y: cy - h / 2,
61
- w,
62
- h
63
- };
64
- candidates.push({ bbox, score: bestScore, classIdx: bestClass });
65
- }
66
- if (candidates.length === 0) return [];
67
- const keptIndices = nms(candidates, iouThreshold);
68
- return keptIndices.map((idx) => {
69
- const { bbox, score, classIdx } = candidates[idx];
70
- const label = labels[classIdx] ?? String(classIdx);
71
- const x = Math.max(0, Math.min(originalWidth, (bbox.x - padX) / scale));
72
- const y = Math.max(0, Math.min(originalHeight, (bbox.y - padY) / scale));
73
- const x2 = Math.max(0, Math.min(originalWidth, (bbox.x + bbox.w - padX) / scale));
74
- const y2 = Math.max(0, Math.min(originalHeight, (bbox.y + bbox.h - padY) / scale));
75
- const finalBbox = { x, y, w: x2 - x, h: y2 - y };
76
- return {
77
- class: label,
78
- originalClass: label,
79
- score,
80
- bbox: finalBbox
81
- };
82
- });
83
- }
84
-
85
- export {
86
- iou,
87
- nms,
88
- yoloPostprocess
89
- };
90
- //# sourceMappingURL=chunk-KUO2BVFY.mjs.map