@camstack/addon-vision 0.1.2 → 0.1.4
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 -822
- 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 -378
- 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 -825
- 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 -825
- 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 -934
- 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 -807
- 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 -1082
- 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 -868
- 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 -505
- 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 -790
- 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 -410
- 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-2IOKI4ES.mjs.map → chunk-PIFS7AIT.mjs.map} +1 -1
- 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 -3924
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2698 -250
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-22BHCDT5.mjs +0 -101
- package/dist/chunk-2IOKI4ES.mjs +0 -335
- 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-D6WEHN33.mjs +0 -276
- package/dist/chunk-D6WEHN33.mjs.map +0 -1
- package/dist/chunk-DRYFGARD.mjs +0 -289
- package/dist/chunk-DRYFGARD.mjs.map +0 -1
- package/dist/chunk-DUN6XU3N.mjs +0 -72
- package/dist/chunk-ESLHNWWE.mjs +0 -387
- package/dist/chunk-ESLHNWWE.mjs.map +0 -1
- package/dist/chunk-JUQEW6ON.mjs +0 -256
- package/dist/chunk-JUQEW6ON.mjs.map +0 -1
- package/dist/chunk-KUO2BVFY.mjs +0 -90
- package/dist/chunk-R5J3WAUI.mjs +0 -645
- package/dist/chunk-R5J3WAUI.mjs.map +0 -1
- package/dist/chunk-XZ6ZMXXU.mjs +0 -39
- package/dist/chunk-YPU4WTXZ.mjs +0 -269
- package/dist/chunk-YPU4WTXZ.mjs.map +0 -1
- package/dist/chunk-YUCD2TFH.mjs +0 -242
- package/dist/chunk-YUCD2TFH.mjs.map +0 -1
- package/dist/chunk-ZTJENCFC.mjs +0 -379
- package/dist/chunk-ZTJENCFC.mjs.map +0 -1
- package/dist/chunk-ZWYXXCXP.mjs +0 -248
- package/dist/chunk-ZWYXXCXP.mjs.map +0 -1
- /package/dist/{chunk-BJTO5JO5.mjs.map → chunk-3IIFBJCD.mjs.map} +0 -0
|
@@ -1,11 +1,231 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
7
|
-
import
|
|
8
|
-
|
|
2
|
+
require_face_detection_models,
|
|
3
|
+
require_scrfd
|
|
4
|
+
} from "../../chunk-2YMA6QOV.mjs";
|
|
5
|
+
import "../../chunk-DE7I3VHO.mjs";
|
|
6
|
+
import "../../chunk-MGT6RUVX.mjs";
|
|
7
|
+
import {
|
|
8
|
+
require_image_utils
|
|
9
|
+
} from "../../chunk-WG66JYYW.mjs";
|
|
10
|
+
import {
|
|
11
|
+
require_engine_resolver
|
|
12
|
+
} from "../../chunk-PIFS7AIT.mjs";
|
|
13
|
+
import {
|
|
14
|
+
__toESM
|
|
15
|
+
} from "../../chunk-3IIFBJCD.mjs";
|
|
16
|
+
|
|
17
|
+
// src/addons/face-detection/index.ts
|
|
18
|
+
var import_face_detection_models = __toESM(require_face_detection_models());
|
|
19
|
+
var import_image_utils = __toESM(require_image_utils());
|
|
20
|
+
var import_scrfd = __toESM(require_scrfd());
|
|
21
|
+
var import_engine_resolver = __toESM(require_engine_resolver());
|
|
22
|
+
var FACE_LABEL = { id: "face", name: "Face" };
|
|
23
|
+
var FACE_LABELS = [FACE_LABEL];
|
|
24
|
+
var FACE_CLASS_MAP = { mapping: {}, preserveOriginal: true };
|
|
25
|
+
var RAM_ESTIMATES = {
|
|
26
|
+
"scrfd-500m": 50,
|
|
27
|
+
"scrfd-2.5g": 80,
|
|
28
|
+
"scrfd-10g": 200
|
|
29
|
+
};
|
|
30
|
+
var ACCURACY_SCORES = {
|
|
31
|
+
"scrfd-500m": 70,
|
|
32
|
+
"scrfd-2.5g": 82,
|
|
33
|
+
"scrfd-10g": 92
|
|
34
|
+
};
|
|
35
|
+
var FaceDetectionAddon = class {
|
|
36
|
+
id = "face-detection";
|
|
37
|
+
slot = "cropper";
|
|
38
|
+
inputClasses = ["person"];
|
|
39
|
+
outputClasses = ["face"];
|
|
40
|
+
slotPriority = 0;
|
|
41
|
+
manifest = {
|
|
42
|
+
id: "face-detection",
|
|
43
|
+
name: "Face Detection",
|
|
44
|
+
version: "0.1.0",
|
|
45
|
+
description: "SCRFD-based face detector \u2014 crops face regions from person detections",
|
|
46
|
+
slot: "cropper",
|
|
47
|
+
inputClasses: ["person"],
|
|
48
|
+
outputClasses: ["face"],
|
|
49
|
+
supportsCustomModels: false,
|
|
50
|
+
mayRequirePython: false,
|
|
51
|
+
defaultConfig: {
|
|
52
|
+
modelId: "scrfd-500m",
|
|
53
|
+
runtime: "node",
|
|
54
|
+
backend: "cpu",
|
|
55
|
+
confidence: 0.5
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
engine = null;
|
|
59
|
+
modelEntry;
|
|
60
|
+
confidence = 0.5;
|
|
61
|
+
resolvedConfig = null;
|
|
62
|
+
ctx = null;
|
|
63
|
+
getModelRequirements() {
|
|
64
|
+
return import_face_detection_models.FACE_DETECTION_MODELS.map((m) => ({
|
|
65
|
+
modelId: m.id,
|
|
66
|
+
name: m.name,
|
|
67
|
+
minRAM_MB: RAM_ESTIMATES[m.id] ?? 50,
|
|
68
|
+
accuracyScore: ACCURACY_SCORES[m.id] ?? 70,
|
|
69
|
+
formats: Object.keys(m.formats)
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
configure(config) {
|
|
73
|
+
this.resolvedConfig = config;
|
|
74
|
+
}
|
|
75
|
+
async initialize(ctx) {
|
|
76
|
+
this.ctx = ctx;
|
|
77
|
+
const cfg = ctx.addonConfig;
|
|
78
|
+
const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "scrfd-500m";
|
|
79
|
+
this.confidence = cfg["confidence"] ?? 0.5;
|
|
80
|
+
const entry = import_face_detection_models.FACE_DETECTION_MODELS.find((m) => m.id === modelId);
|
|
81
|
+
if (!entry) {
|
|
82
|
+
throw new Error(`FaceDetectionAddon: unknown modelId "${modelId}"`);
|
|
83
|
+
}
|
|
84
|
+
this.modelEntry = entry;
|
|
85
|
+
}
|
|
86
|
+
async crop(input) {
|
|
87
|
+
if (!this.engine) await this.ensureEngine();
|
|
88
|
+
const start = Date.now();
|
|
89
|
+
const { width: inputW, height: inputH } = this.modelEntry.inputSize;
|
|
90
|
+
const targetSize = Math.max(inputW, inputH);
|
|
91
|
+
const personCrop = await (0, import_image_utils.cropRegion)(input.frame.data, input.roi);
|
|
92
|
+
const lb = await (0, import_image_utils.letterbox)(personCrop, targetSize);
|
|
93
|
+
const engineWithMulti = this.engine;
|
|
94
|
+
let outputs;
|
|
95
|
+
if (typeof engineWithMulti.runMultiOutput === "function") {
|
|
96
|
+
outputs = await engineWithMulti.runMultiOutput(lb.data, [1, 3, targetSize, targetSize]);
|
|
97
|
+
} else {
|
|
98
|
+
const single = await this.engine.run(lb.data, [1, 3, targetSize, targetSize]);
|
|
99
|
+
outputs = { output0: single };
|
|
100
|
+
}
|
|
101
|
+
const crops = (0, import_scrfd.scrfdPostprocess)(
|
|
102
|
+
outputs,
|
|
103
|
+
this.confidence,
|
|
104
|
+
targetSize,
|
|
105
|
+
lb.originalWidth,
|
|
106
|
+
lb.originalHeight
|
|
107
|
+
);
|
|
108
|
+
return {
|
|
109
|
+
crops,
|
|
110
|
+
inferenceMs: Date.now() - start,
|
|
111
|
+
modelId: this.modelEntry.id
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async ensureEngine() {
|
|
115
|
+
const config = this.resolvedConfig;
|
|
116
|
+
const modelId = config?.modelId ?? this.modelEntry.id;
|
|
117
|
+
const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
|
|
118
|
+
const backend = config?.backend ?? "cpu";
|
|
119
|
+
const format = config?.format ?? "onnx";
|
|
120
|
+
const entry = import_face_detection_models.FACE_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
|
|
121
|
+
this.modelEntry = entry;
|
|
122
|
+
const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
|
|
123
|
+
if (this.ctx.models) {
|
|
124
|
+
await this.ctx.models.ensure(modelId, format);
|
|
125
|
+
}
|
|
126
|
+
const resolved = await (0, import_engine_resolver.resolveEngine)({
|
|
127
|
+
runtime,
|
|
128
|
+
backend,
|
|
129
|
+
modelEntry: entry,
|
|
130
|
+
modelsDir,
|
|
131
|
+
models: this.ctx.models
|
|
132
|
+
});
|
|
133
|
+
this.engine = resolved.engine;
|
|
134
|
+
}
|
|
135
|
+
async shutdown() {
|
|
136
|
+
await this.engine?.dispose();
|
|
137
|
+
}
|
|
138
|
+
getConfigSchema() {
|
|
139
|
+
return {
|
|
140
|
+
sections: [
|
|
141
|
+
{
|
|
142
|
+
id: "model",
|
|
143
|
+
title: "Model",
|
|
144
|
+
columns: 1,
|
|
145
|
+
fields: [
|
|
146
|
+
{
|
|
147
|
+
key: "modelId",
|
|
148
|
+
label: "Model",
|
|
149
|
+
type: "model-selector",
|
|
150
|
+
catalog: [...import_face_detection_models.FACE_DETECTION_MODELS],
|
|
151
|
+
allowCustom: false,
|
|
152
|
+
allowConversion: false,
|
|
153
|
+
acceptFormats: ["onnx", "coreml", "openvino"],
|
|
154
|
+
requiredMetadata: ["inputSize", "labels", "outputFormat"],
|
|
155
|
+
outputFormatHint: "ssd"
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: "runtime",
|
|
161
|
+
title: "Runtime",
|
|
162
|
+
columns: 2,
|
|
163
|
+
fields: [
|
|
164
|
+
{
|
|
165
|
+
key: "runtime",
|
|
166
|
+
label: "Runtime",
|
|
167
|
+
type: "select",
|
|
168
|
+
options: [
|
|
169
|
+
{ value: "auto", label: "Auto" },
|
|
170
|
+
{ value: "onnx", label: "ONNX Runtime" },
|
|
171
|
+
{ value: "coreml", label: "CoreML (Apple)" },
|
|
172
|
+
{ value: "openvino", label: "OpenVINO (Intel)" }
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
key: "backend",
|
|
177
|
+
label: "Backend",
|
|
178
|
+
type: "select",
|
|
179
|
+
showWhen: { field: "runtime", equals: "onnx" },
|
|
180
|
+
options: [
|
|
181
|
+
{ value: "auto", label: "Auto" },
|
|
182
|
+
{ value: "cpu", label: "CPU" },
|
|
183
|
+
{ value: "coreml", label: "CoreML" },
|
|
184
|
+
{ value: "cuda", label: "CUDA (NVIDIA)" }
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: "thresholds",
|
|
191
|
+
title: "Detection Thresholds",
|
|
192
|
+
columns: 1,
|
|
193
|
+
fields: [
|
|
194
|
+
{
|
|
195
|
+
key: "confidence",
|
|
196
|
+
label: "Confidence Threshold",
|
|
197
|
+
type: "slider",
|
|
198
|
+
min: 0.1,
|
|
199
|
+
max: 1,
|
|
200
|
+
step: 0.05,
|
|
201
|
+
default: 0.5
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
getClassMap() {
|
|
209
|
+
return FACE_CLASS_MAP;
|
|
210
|
+
}
|
|
211
|
+
getModelCatalog() {
|
|
212
|
+
return [...import_face_detection_models.FACE_DETECTION_MODELS];
|
|
213
|
+
}
|
|
214
|
+
getAvailableModels() {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
getActiveLabels() {
|
|
218
|
+
return FACE_LABELS;
|
|
219
|
+
}
|
|
220
|
+
async probe() {
|
|
221
|
+
return {
|
|
222
|
+
available: true,
|
|
223
|
+
runtime: this.engine?.runtime ?? "onnx",
|
|
224
|
+
device: this.engine?.device ?? "cpu",
|
|
225
|
+
capabilities: ["fp32"]
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
};
|
|
9
229
|
export {
|
|
10
230
|
FaceDetectionAddon as default
|
|
11
231
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/addons/face-detection/index.ts"],"sourcesContent":["import type {\n ICropperProvider,\n IDetectionAddon,\n AddonManifest,\n AddonContext,\n CropInput,\n CropperOutput,\n ConfigUISchema,\n ClassMapDefinition,\n ProbeResult,\n ModelCatalogEntry,\n DetectionModel,\n LabelDefinition,\n IInferenceEngine,\n ModelRequirement,\n ResolvedInferenceConfig,\n} from '@camstack/types'\nimport { FACE_DETECTION_MODELS } from '../../catalogs/face-detection-models.js'\nimport { cropRegion, letterbox } from '../../shared/image-utils.js'\nimport { scrfdPostprocess } from '../../shared/postprocess/scrfd.js'\nimport { resolveEngine } from '../../shared/engine-resolver.js'\n\nconst FACE_LABEL: LabelDefinition = { id: 'face', name: 'Face' }\nconst FACE_LABELS: readonly LabelDefinition[] = [FACE_LABEL]\nconst FACE_CLASS_MAP: ClassMapDefinition = { mapping: {}, preserveOriginal: true }\n\n/** RAM estimates per model (MB) */\nconst RAM_ESTIMATES: Record<string, number> = {\n 'scrfd-500m': 50,\n 'scrfd-2.5g': 80,\n 'scrfd-10g': 200,\n}\n\n/** Accuracy scores per model (0-100) */\nconst ACCURACY_SCORES: Record<string, number> = {\n 'scrfd-500m': 70,\n 'scrfd-2.5g': 82,\n 'scrfd-10g': 92,\n}\n\nexport default class FaceDetectionAddon implements ICropperProvider, IDetectionAddon {\n readonly id = 'face-detection'\n readonly slot = 'cropper' as const\n readonly inputClasses = ['person'] as const\n readonly outputClasses = ['face'] as const\n readonly slotPriority = 0\n readonly manifest: AddonManifest = {\n id: 'face-detection',\n name: 'Face Detection',\n version: '0.1.0',\n\n description: 'SCRFD-based face detector — crops face regions from person detections',\n\n slot: 'cropper',\n inputClasses: ['person'],\n outputClasses: ['face'],\n supportsCustomModels: false,\n mayRequirePython: false,\n defaultConfig: {\n modelId: 'scrfd-500m',\n runtime: 'node',\n backend: 'cpu',\n confidence: 0.5,\n },\n }\n\n private engine: IInferenceEngine | null = null\n private modelEntry!: ModelCatalogEntry\n private confidence = 0.5\n private resolvedConfig: ResolvedInferenceConfig | null = null\n private ctx: AddonContext | null = null\n\n getModelRequirements(): ModelRequirement[] {\n return FACE_DETECTION_MODELS.map((m) => ({\n modelId: m.id,\n name: m.name,\n minRAM_MB: RAM_ESTIMATES[m.id] ?? 50,\n accuracyScore: ACCURACY_SCORES[m.id] ?? 70,\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 ?? 'scrfd-500m'\n this.confidence = (cfg['confidence'] as number | undefined) ?? 0.5\n\n const entry = FACE_DETECTION_MODELS.find((m) => m.id === modelId)\n if (!entry) {\n throw new Error(`FaceDetectionAddon: unknown modelId \"${modelId}\"`)\n }\n this.modelEntry = entry\n }\n\n async crop(input: CropInput): Promise<CropperOutput> {\n if (!this.engine) await this.ensureEngine()\n const start = Date.now()\n const { width: inputW, height: inputH } = this.modelEntry.inputSize\n const targetSize = Math.max(inputW, inputH)\n\n // Crop the person region from the full frame\n const personCrop = await cropRegion(input.frame.data, input.roi)\n\n // Letterbox resize to model input size\n const lb = await letterbox(personCrop, targetSize)\n\n // SCRFD has multiple output tensors\n const engineWithMulti = this.engine as IInferenceEngine & {\n runMultiOutput?: (input: Float32Array, shape: readonly number[]) => Promise<Record<string, Float32Array>>\n }\n\n let outputs: Record<string, Float32Array>\n if (typeof engineWithMulti.runMultiOutput === 'function') {\n outputs = await engineWithMulti.runMultiOutput(lb.data, [1, 3, targetSize, targetSize])\n } else {\n // Fallback: wrap single output\n const single = await this.engine!.run(lb.data, [1, 3, targetSize, targetSize])\n outputs = { output0: single }\n }\n\n const crops = scrfdPostprocess(\n outputs,\n this.confidence,\n targetSize,\n lb.originalWidth,\n lb.originalHeight,\n )\n\n return {\n crops,\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_DETECTION_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_DETECTION_MODELS],\n allowCustom: false,\n allowConversion: false,\n acceptFormats: ['onnx', 'coreml', 'openvino'],\n requiredMetadata: ['inputSize', 'labels', 'outputFormat'],\n outputFormatHint: 'ssd',\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: 'Detection Thresholds',\n columns: 1,\n fields: [\n {\n key: 'confidence',\n label: 'Confidence Threshold',\n type: 'slider',\n min: 0.1,\n max: 1.0,\n step: 0.05,\n default: 0.5,\n },\n ],\n },\n ],\n }\n }\n\n getClassMap(): ClassMapDefinition {\n return FACE_CLASS_MAP\n }\n\n getModelCatalog(): ModelCatalogEntry[] {\n return [...FACE_DETECTION_MODELS]\n }\n\n getAvailableModels(): DetectionModel[] {\n return []\n }\n\n getActiveLabels(): readonly LabelDefinition[] {\n return FACE_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":[]}
|