@camstack/addon-pipeline 1.1.53 → 1.1.55
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/audio-analyzer/index.js +1 -1
- package/dist/audio-analyzer/index.mjs +1 -1
- package/dist/detection-pipeline/index.js +289 -1469
- package/dist/detection-pipeline/index.mjs +269 -1449
- package/dist/{dist-DWb62H5U.js → dist-DI57FC8K.js} +167 -8
- package/dist/{dist-BalxNwOt.mjs → dist-RWGGPwVx.mjs} +167 -8
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +772 -21
- package/dist/pipeline-runner/index.mjs +772 -22
- package/dist/recorder/index.js +1 -1
- package/dist/recorder/index.mjs +1 -1
- package/dist/{remote-source-plane-CZpzIVro.js → remote-source-plane-CHgvzzA6.js} +1 -1
- package/dist/{remote-source-plane-BCJW5CvF.mjs → remote-source-plane-DU0aRSPv.mjs} +1 -1
- package/dist/session-decode/decode-worker-child.js +538 -35
- package/dist/session-decode/decode-worker-child.mjs +538 -35
- package/dist/step-definitions-CNBFKjZe.js +1514 -0
- package/dist/step-definitions-CP9kVSml.mjs +1479 -0
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DIN3CcRP.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-mDCPzmT3.mjs} +3 -3
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B3gTdHEh.mjs +26 -0
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-C9fwKMfg.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Dn_pxzP-.mjs} +1 -1
- package/dist/stream-broker/{hostInit-CGUEq--X.mjs → hostInit-GM_CI22k.mjs} +3 -3
- package/dist/stream-broker/index.js +2 -2
- package/dist/stream-broker/index.mjs +2 -2
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-pk7qdYXt.mjs → worker-protocol-CyVJTZEO.mjs} +7 -0
- package/dist/{worker-protocol-BCfO8gUF.js → worker-protocol-PP4jKHHJ.js} +7 -0
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-CqOe8eYa.js → MaskShapeCanvas-DI4BY7W2-BChW0ntM.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-CZyLeUnd.js → MotionZonesSettings-NcxxQN8r-DDzqEbSe.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-Cn0hGZnu.js → PrivacyMaskSettings-APgPLF7p-B879GXaf.js} +1 -1
- package/embed-dist/assets/{index-DRl4XYjA.js → index-CNjQ5rAE.js} +10 -10
- package/embed-dist/index.html +1 -1
- package/package.json +1 -1
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-o4tu_xuc.mjs +0 -26
|
@@ -3,7 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-D6vf50IK.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-DI57FC8K.js");
|
|
7
|
+
const require_step_definitions = require("../step-definitions-CNBFKjZe.js");
|
|
7
8
|
const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
|
|
8
9
|
const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-BLXzxpRB.js");
|
|
9
10
|
let _camstack_shm_ring = require("@camstack/shm-ring");
|
|
@@ -298,1437 +299,6 @@ function projectNodeEngine(store, nodeId) {
|
|
|
298
299
|
return out;
|
|
299
300
|
}
|
|
300
301
|
//#endregion
|
|
301
|
-
//#region src/detection-pipeline/registry/model-catalogs.ts
|
|
302
|
-
var HF_REPO = "camstack/camstack-models";
|
|
303
|
-
var HF_SCRYPTED = "scrypted/plugin-models";
|
|
304
|
-
var hf = (path) => require_dist.hfModelUrl(HF_REPO, path);
|
|
305
|
-
var hfScrypted = (path) => require_dist.hfModelUrl(HF_SCRYPTED, path);
|
|
306
|
-
/**
|
|
307
|
-
* Build an OpenVINO format entry (always python runtime).
|
|
308
|
-
*
|
|
309
|
-
* OpenVINO IR is a two-file bundle: a `.xml` topology + a sibling `.bin`
|
|
310
|
-
* weights file with the same basename. We declare the `.bin` in `files` so
|
|
311
|
-
* the (format-agnostic) downloader fetches it alongside the `.xml` — without
|
|
312
|
-
* the weights, OpenVINO compile fails with "Empty weights data in bin file".
|
|
313
|
-
* A plain `.onnx` run through the OpenVINO runtime (e.g. yamnet) has no
|
|
314
|
-
* sibling, so none is added.
|
|
315
|
-
*/
|
|
316
|
-
var ovFormat = (url, sizeMB) => {
|
|
317
|
-
const base = url.split("/").pop() ?? "";
|
|
318
|
-
const files = base.endsWith(".xml") ? [base.replace(/\.xml$/, ".bin")] : void 0;
|
|
319
|
-
return {
|
|
320
|
-
url,
|
|
321
|
-
sizeMB,
|
|
322
|
-
runtimes: ["python"],
|
|
323
|
-
...files ? { files } : {}
|
|
324
|
-
};
|
|
325
|
-
};
|
|
326
|
-
/**
|
|
327
|
-
* Build a precision-variant catalog entry (OpenVINO-only) derived from a base
|
|
328
|
-
* detection model. fp16 halves the weights (Intel iGPU/NPU sweet spot); int8 is
|
|
329
|
-
* NNCF post-training-quantized (~4× smaller, fastest on CPU/iGPU at a small
|
|
330
|
-
* accuracy cost). The IRs live next to the base `.xml` on HF as
|
|
331
|
-
* `camstack-<id>-<precision>.xml`. Lets an operator scale the model to the node
|
|
332
|
-
* (e.g. yolo26x-int8 on a 265K, yolo26n-int8 on an N100).
|
|
333
|
-
*/
|
|
334
|
-
var ovPrecisionVariant = (baseId, ovDir, baseName, precision, sizeMB, legacy = false) => ({
|
|
335
|
-
id: `${baseId}-${precision}`,
|
|
336
|
-
name: `${baseName} (${precision.toUpperCase()})`,
|
|
337
|
-
description: `${baseName} — OpenVINO ${precision.toUpperCase()} variant for Intel iGPU/NPU; scale by hardware`,
|
|
338
|
-
inputSize: {
|
|
339
|
-
width: 640,
|
|
340
|
-
height: 640
|
|
341
|
-
},
|
|
342
|
-
labels: [],
|
|
343
|
-
preprocessMode: "letterbox",
|
|
344
|
-
formats: { openvino: ovFormat(hf(`${ovDir}/camstack-${baseId}-${precision}.xml`), sizeMB) },
|
|
345
|
-
...legacy ? { legacy: true } : {},
|
|
346
|
-
...precision === "int8" ? { group: {
|
|
347
|
-
family: baseId.slice(0, -1),
|
|
348
|
-
tier: baseId.slice(-1),
|
|
349
|
-
precision: "int8"
|
|
350
|
-
} } : {}
|
|
351
|
-
});
|
|
352
|
-
var MLPACKAGE_FILES = [
|
|
353
|
-
"Manifest.json",
|
|
354
|
-
"Data/com.apple.CoreML/model.mlmodel",
|
|
355
|
-
"Data/com.apple.CoreML/weights/weight.bin"
|
|
356
|
-
];
|
|
357
|
-
var YOLO26_TIER_NAME = {
|
|
358
|
-
n: "Nano",
|
|
359
|
-
s: "Small",
|
|
360
|
-
m: "Medium",
|
|
361
|
-
l: "Large"
|
|
362
|
-
};
|
|
363
|
-
/**
|
|
364
|
-
* Reduced-input YOLO26 variants (2026-07-11). A lower square input (320 / 256)
|
|
365
|
-
* is the biggest, cheapest latency lever measured across every runtime — Mac
|
|
366
|
-
* ANE, Intel Ultra NPU, and especially the N100 — at a small-object accuracy
|
|
367
|
-
* cost. Each resolution ships a base (fp32) entry (onnx + coreml + openvino)
|
|
368
|
-
* grouped under `{family, tier, resolution}`, plus an OpenVINO INT8 entry (best
|
|
369
|
-
* on Intel/N100) grouped with `precision:'int8'`. The grouped selector surfaces
|
|
370
|
-
* `resolution` as a variant axis alongside precision.
|
|
371
|
-
*/
|
|
372
|
-
var yolo26Reduced = (tier, res, sizes) => {
|
|
373
|
-
const name = YOLO26_TIER_NAME[tier] ?? tier.toUpperCase();
|
|
374
|
-
return [{
|
|
375
|
-
id: `yolo26${tier}-${res}`,
|
|
376
|
-
group: {
|
|
377
|
-
family: "yolo26",
|
|
378
|
-
tier,
|
|
379
|
-
resolution: res
|
|
380
|
-
},
|
|
381
|
-
name: `YOLO26 ${name} @${res}`,
|
|
382
|
-
description: `YOLO26 ${name}, reduced ${res}×${res} input — faster on ANE / hub NPU / N100 at a small-object accuracy cost`,
|
|
383
|
-
inputSize: {
|
|
384
|
-
width: res,
|
|
385
|
-
height: res
|
|
386
|
-
},
|
|
387
|
-
labels: [],
|
|
388
|
-
preprocessMode: "letterbox",
|
|
389
|
-
formats: {
|
|
390
|
-
onnx: {
|
|
391
|
-
url: hf(`objectDetection/yolo26/onnx/camstack-yolo26${tier}-${res}.onnx`),
|
|
392
|
-
sizeMB: sizes.onnx
|
|
393
|
-
},
|
|
394
|
-
coreml: {
|
|
395
|
-
url: hf(`objectDetection/yolo26/coreml/camstack-yolo26${tier}-${res}.mlpackage`),
|
|
396
|
-
sizeMB: sizes.coreml,
|
|
397
|
-
isDirectory: true,
|
|
398
|
-
files: [...MLPACKAGE_FILES],
|
|
399
|
-
runtimes: ["python"]
|
|
400
|
-
},
|
|
401
|
-
openvino: ovFormat(hf(`objectDetection/yolo26/openvino/camstack-yolo26${tier}-${res}.xml`), sizes.ovFp32)
|
|
402
|
-
}
|
|
403
|
-
}, {
|
|
404
|
-
id: `yolo26${tier}-${res}-int8`,
|
|
405
|
-
group: {
|
|
406
|
-
family: "yolo26",
|
|
407
|
-
tier,
|
|
408
|
-
precision: "int8",
|
|
409
|
-
resolution: res
|
|
410
|
-
},
|
|
411
|
-
name: `YOLO26 ${name} @${res} (INT8)`,
|
|
412
|
-
description: `YOLO26 ${name} @${res} — OpenVINO INT8 for Intel iGPU/CPU; the N100's fastest config`,
|
|
413
|
-
inputSize: {
|
|
414
|
-
width: res,
|
|
415
|
-
height: res
|
|
416
|
-
},
|
|
417
|
-
labels: [],
|
|
418
|
-
preprocessMode: "letterbox",
|
|
419
|
-
formats: { openvino: ovFormat(hf(`objectDetection/yolo26/openvino/camstack-yolo26${tier}-${res}-int8.xml`), sizes.ovInt8) }
|
|
420
|
-
}];
|
|
421
|
-
};
|
|
422
|
-
var OBJECT_DETECTION_MODELS = [
|
|
423
|
-
{
|
|
424
|
-
id: "yolov9t",
|
|
425
|
-
legacy: true,
|
|
426
|
-
name: "YOLOv9 Tiny",
|
|
427
|
-
description: "YOLOv9 Tiny — ultra-lightweight next-gen detector",
|
|
428
|
-
inputSize: {
|
|
429
|
-
width: 640,
|
|
430
|
-
height: 640
|
|
431
|
-
},
|
|
432
|
-
labels: [],
|
|
433
|
-
preprocessMode: "letterbox",
|
|
434
|
-
formats: {
|
|
435
|
-
onnx: {
|
|
436
|
-
url: hf("objectDetection/yolov9/onnx/camstack-yolov9t.onnx"),
|
|
437
|
-
sizeMB: 8
|
|
438
|
-
},
|
|
439
|
-
coreml: {
|
|
440
|
-
url: hf("objectDetection/yolov9/coreml/camstack-yolov9t.mlpackage"),
|
|
441
|
-
sizeMB: 4,
|
|
442
|
-
isDirectory: true,
|
|
443
|
-
files: [...MLPACKAGE_FILES],
|
|
444
|
-
runtimes: ["python"]
|
|
445
|
-
},
|
|
446
|
-
openvino: ovFormat(hf("objectDetection/yolov9/openvino/camstack-yolov9t.xml"), 6)
|
|
447
|
-
}
|
|
448
|
-
},
|
|
449
|
-
{
|
|
450
|
-
id: "yolov9s",
|
|
451
|
-
legacy: true,
|
|
452
|
-
name: "YOLOv9 Small",
|
|
453
|
-
description: "YOLOv9 Small — improved efficiency over YOLOv8s",
|
|
454
|
-
inputSize: {
|
|
455
|
-
width: 640,
|
|
456
|
-
height: 640
|
|
457
|
-
},
|
|
458
|
-
labels: [],
|
|
459
|
-
preprocessMode: "letterbox",
|
|
460
|
-
formats: {
|
|
461
|
-
onnx: {
|
|
462
|
-
url: hf("objectDetection/yolov9/onnx/camstack-yolov9s.onnx"),
|
|
463
|
-
sizeMB: 28
|
|
464
|
-
},
|
|
465
|
-
coreml: {
|
|
466
|
-
url: hf("objectDetection/yolov9/coreml/camstack-yolov9s.mlpackage"),
|
|
467
|
-
sizeMB: 14,
|
|
468
|
-
isDirectory: true,
|
|
469
|
-
files: [...MLPACKAGE_FILES],
|
|
470
|
-
runtimes: ["python"]
|
|
471
|
-
},
|
|
472
|
-
openvino: ovFormat(hf("objectDetection/yolov9/openvino/camstack-yolov9s.xml"), 16)
|
|
473
|
-
}
|
|
474
|
-
},
|
|
475
|
-
{
|
|
476
|
-
id: "yolov9c",
|
|
477
|
-
legacy: true,
|
|
478
|
-
name: "YOLOv9 C",
|
|
479
|
-
description: "YOLOv9 C — high-accuracy compact model",
|
|
480
|
-
inputSize: {
|
|
481
|
-
width: 640,
|
|
482
|
-
height: 640
|
|
483
|
-
},
|
|
484
|
-
labels: [],
|
|
485
|
-
preprocessMode: "letterbox",
|
|
486
|
-
formats: {
|
|
487
|
-
onnx: {
|
|
488
|
-
url: hf("objectDetection/yolov9/onnx/camstack-yolov9c.onnx"),
|
|
489
|
-
sizeMB: 97
|
|
490
|
-
},
|
|
491
|
-
coreml: {
|
|
492
|
-
url: hf("objectDetection/yolov9/coreml/camstack-yolov9c.mlpackage"),
|
|
493
|
-
sizeMB: 48,
|
|
494
|
-
isDirectory: true,
|
|
495
|
-
files: [...MLPACKAGE_FILES],
|
|
496
|
-
runtimes: ["python"]
|
|
497
|
-
},
|
|
498
|
-
openvino: ovFormat(hf("objectDetection/yolov9/openvino/camstack-yolov9c.xml"), 49)
|
|
499
|
-
}
|
|
500
|
-
},
|
|
501
|
-
{
|
|
502
|
-
id: "yolo26n",
|
|
503
|
-
group: {
|
|
504
|
-
family: "yolo26",
|
|
505
|
-
tier: "n"
|
|
506
|
-
},
|
|
507
|
-
name: "YOLO26 Nano",
|
|
508
|
-
description: "YOLO26 Nano — latest generation ultra-lightweight detector with attention mechanism",
|
|
509
|
-
inputSize: {
|
|
510
|
-
width: 640,
|
|
511
|
-
height: 640
|
|
512
|
-
},
|
|
513
|
-
labels: [],
|
|
514
|
-
preprocessMode: "letterbox",
|
|
515
|
-
formats: {
|
|
516
|
-
onnx: {
|
|
517
|
-
url: hf("objectDetection/yolo26/onnx/camstack-yolo26n.onnx"),
|
|
518
|
-
sizeMB: 10
|
|
519
|
-
},
|
|
520
|
-
coreml: {
|
|
521
|
-
url: hf("objectDetection/yolo26/coreml/camstack-yolo26n.mlpackage"),
|
|
522
|
-
sizeMB: 5,
|
|
523
|
-
isDirectory: true,
|
|
524
|
-
files: [...MLPACKAGE_FILES],
|
|
525
|
-
runtimes: ["python"]
|
|
526
|
-
},
|
|
527
|
-
openvino: ovFormat(hf("objectDetection/yolo26/openvino/camstack-yolo26n.xml"), 9)
|
|
528
|
-
}
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
id: "yolo26s",
|
|
532
|
-
group: {
|
|
533
|
-
family: "yolo26",
|
|
534
|
-
tier: "s"
|
|
535
|
-
},
|
|
536
|
-
name: "YOLO26 Small",
|
|
537
|
-
description: "YOLO26 Small — balanced speed/accuracy with attention-based architecture",
|
|
538
|
-
inputSize: {
|
|
539
|
-
width: 640,
|
|
540
|
-
height: 640
|
|
541
|
-
},
|
|
542
|
-
labels: [],
|
|
543
|
-
preprocessMode: "letterbox",
|
|
544
|
-
formats: {
|
|
545
|
-
onnx: {
|
|
546
|
-
url: hf("objectDetection/yolo26/onnx/camstack-yolo26s.onnx"),
|
|
547
|
-
sizeMB: 37
|
|
548
|
-
},
|
|
549
|
-
coreml: {
|
|
550
|
-
url: hf("objectDetection/yolo26/coreml/camstack-yolo26s.mlpackage"),
|
|
551
|
-
sizeMB: 18,
|
|
552
|
-
isDirectory: true,
|
|
553
|
-
files: [...MLPACKAGE_FILES],
|
|
554
|
-
runtimes: ["python"]
|
|
555
|
-
},
|
|
556
|
-
openvino: ovFormat(hf("objectDetection/yolo26/openvino/camstack-yolo26s.xml"), 36)
|
|
557
|
-
}
|
|
558
|
-
},
|
|
559
|
-
{
|
|
560
|
-
id: "yolo26m",
|
|
561
|
-
group: {
|
|
562
|
-
family: "yolo26",
|
|
563
|
-
tier: "m"
|
|
564
|
-
},
|
|
565
|
-
name: "YOLO26 Medium",
|
|
566
|
-
description: "YOLO26 Medium — high accuracy general-purpose detector",
|
|
567
|
-
inputSize: {
|
|
568
|
-
width: 640,
|
|
569
|
-
height: 640
|
|
570
|
-
},
|
|
571
|
-
labels: [],
|
|
572
|
-
preprocessMode: "letterbox",
|
|
573
|
-
formats: {
|
|
574
|
-
onnx: {
|
|
575
|
-
url: hf("objectDetection/yolo26/onnx/camstack-yolo26m.onnx"),
|
|
576
|
-
sizeMB: 78
|
|
577
|
-
},
|
|
578
|
-
coreml: {
|
|
579
|
-
url: hf("objectDetection/yolo26/coreml/camstack-yolo26m.mlpackage"),
|
|
580
|
-
sizeMB: 39,
|
|
581
|
-
isDirectory: true,
|
|
582
|
-
files: [...MLPACKAGE_FILES],
|
|
583
|
-
runtimes: ["python"]
|
|
584
|
-
},
|
|
585
|
-
openvino: ovFormat(hf("objectDetection/yolo26/openvino/camstack-yolo26m.xml"), 78)
|
|
586
|
-
}
|
|
587
|
-
},
|
|
588
|
-
{
|
|
589
|
-
id: "yolo26l",
|
|
590
|
-
group: {
|
|
591
|
-
family: "yolo26",
|
|
592
|
-
tier: "l"
|
|
593
|
-
},
|
|
594
|
-
name: "YOLO26 Large",
|
|
595
|
-
description: "YOLO26 Large — maximum accuracy for demanding deployments",
|
|
596
|
-
inputSize: {
|
|
597
|
-
width: 640,
|
|
598
|
-
height: 640
|
|
599
|
-
},
|
|
600
|
-
labels: [],
|
|
601
|
-
preprocessMode: "letterbox",
|
|
602
|
-
formats: {
|
|
603
|
-
onnx: {
|
|
604
|
-
url: hf("objectDetection/yolo26/onnx/camstack-yolo26l.onnx"),
|
|
605
|
-
sizeMB: 95
|
|
606
|
-
},
|
|
607
|
-
coreml: {
|
|
608
|
-
url: hf("objectDetection/yolo26/coreml/camstack-yolo26l.mlpackage"),
|
|
609
|
-
sizeMB: 48,
|
|
610
|
-
isDirectory: true,
|
|
611
|
-
files: [...MLPACKAGE_FILES],
|
|
612
|
-
runtimes: ["python"]
|
|
613
|
-
},
|
|
614
|
-
openvino: ovFormat(hf("objectDetection/yolo26/openvino/camstack-yolo26l.xml"), 95)
|
|
615
|
-
}
|
|
616
|
-
},
|
|
617
|
-
{
|
|
618
|
-
id: "yolo26x",
|
|
619
|
-
legacy: true,
|
|
620
|
-
name: "YOLO26 XLarge",
|
|
621
|
-
description: "YOLO26 XLarge — highest accuracy, attention-based architecture",
|
|
622
|
-
inputSize: {
|
|
623
|
-
width: 640,
|
|
624
|
-
height: 640
|
|
625
|
-
},
|
|
626
|
-
labels: [],
|
|
627
|
-
preprocessMode: "letterbox",
|
|
628
|
-
formats: {
|
|
629
|
-
onnx: {
|
|
630
|
-
url: hf("objectDetection/yolo26/onnx/camstack-yolo26x.onnx"),
|
|
631
|
-
sizeMB: 213
|
|
632
|
-
},
|
|
633
|
-
coreml: {
|
|
634
|
-
url: hf("objectDetection/yolo26/coreml/camstack-yolo26x.mlpackage"),
|
|
635
|
-
sizeMB: 107,
|
|
636
|
-
isDirectory: true,
|
|
637
|
-
files: [...MLPACKAGE_FILES],
|
|
638
|
-
runtimes: ["python"]
|
|
639
|
-
},
|
|
640
|
-
openvino: ovFormat(hf("objectDetection/yolo26/openvino/camstack-yolo26x.xml"), 213)
|
|
641
|
-
}
|
|
642
|
-
},
|
|
643
|
-
{
|
|
644
|
-
id: "scrypted-yolov9t-relu",
|
|
645
|
-
legacy: true,
|
|
646
|
-
name: "YOLOv9 Tiny ReLU",
|
|
647
|
-
description: "YOLOv9t ReLU — optimized for int8 quantization",
|
|
648
|
-
inputSize: {
|
|
649
|
-
width: 320,
|
|
650
|
-
height: 320
|
|
651
|
-
},
|
|
652
|
-
labels: [],
|
|
653
|
-
preprocessMode: "letterbox",
|
|
654
|
-
formats: {
|
|
655
|
-
onnx: {
|
|
656
|
-
url: hfScrypted("onnx/scrypted_yolov9t_relu/scrypted_yolov9t_relu.onnx"),
|
|
657
|
-
sizeMB: 8.1
|
|
658
|
-
},
|
|
659
|
-
coreml: {
|
|
660
|
-
url: hfScrypted("coreml/scrypted_yolov9t_relu/scrypted_yolov9t_relu.mlpackage"),
|
|
661
|
-
sizeMB: 4,
|
|
662
|
-
isDirectory: true,
|
|
663
|
-
files: [...MLPACKAGE_FILES],
|
|
664
|
-
runtimes: ["python"]
|
|
665
|
-
},
|
|
666
|
-
openvino: ovFormat(hf("objectDetection/scrypted-yolov9-relu/openvino/scrypted_yolov9t_relu.xml"), 6)
|
|
667
|
-
}
|
|
668
|
-
},
|
|
669
|
-
{
|
|
670
|
-
id: "scrypted-yolov9s-relu",
|
|
671
|
-
legacy: true,
|
|
672
|
-
name: "YOLOv9 Small ReLU",
|
|
673
|
-
description: "YOLOv9s ReLU — improved efficiency, int8 ready",
|
|
674
|
-
inputSize: {
|
|
675
|
-
width: 320,
|
|
676
|
-
height: 320
|
|
677
|
-
},
|
|
678
|
-
labels: [],
|
|
679
|
-
preprocessMode: "letterbox",
|
|
680
|
-
formats: {
|
|
681
|
-
onnx: {
|
|
682
|
-
url: hfScrypted("onnx/scrypted_yolov9s_relu/scrypted_yolov9s_relu.onnx"),
|
|
683
|
-
sizeMB: 27.9
|
|
684
|
-
},
|
|
685
|
-
coreml: {
|
|
686
|
-
url: hfScrypted("coreml/scrypted_yolov9s_relu/scrypted_yolov9s_relu.mlpackage"),
|
|
687
|
-
sizeMB: 14,
|
|
688
|
-
isDirectory: true,
|
|
689
|
-
files: [...MLPACKAGE_FILES],
|
|
690
|
-
runtimes: ["python"]
|
|
691
|
-
},
|
|
692
|
-
openvino: ovFormat(hf("objectDetection/scrypted-yolov9-relu/openvino/scrypted_yolov9s_relu.xml"), 16)
|
|
693
|
-
}
|
|
694
|
-
},
|
|
695
|
-
{
|
|
696
|
-
id: "scrypted-yolov9c-relu",
|
|
697
|
-
legacy: true,
|
|
698
|
-
name: "YOLOv9 C ReLU",
|
|
699
|
-
description: "YOLOv9c ReLU — high-accuracy, int8 ready",
|
|
700
|
-
inputSize: {
|
|
701
|
-
width: 320,
|
|
702
|
-
height: 320
|
|
703
|
-
},
|
|
704
|
-
labels: [],
|
|
705
|
-
preprocessMode: "letterbox",
|
|
706
|
-
formats: {
|
|
707
|
-
onnx: {
|
|
708
|
-
url: hfScrypted("onnx/scrypted_yolov9c_relu/scrypted_yolov9c_relu.onnx"),
|
|
709
|
-
sizeMB: 96.9
|
|
710
|
-
},
|
|
711
|
-
coreml: {
|
|
712
|
-
url: hfScrypted("coreml/scrypted_yolov9c_relu/scrypted_yolov9c_relu.mlpackage"),
|
|
713
|
-
sizeMB: 48,
|
|
714
|
-
isDirectory: true,
|
|
715
|
-
files: [...MLPACKAGE_FILES],
|
|
716
|
-
runtimes: ["python"]
|
|
717
|
-
},
|
|
718
|
-
openvino: ovFormat(hf("objectDetection/scrypted-yolov9-relu/openvino/scrypted_yolov9c_relu.xml"), 49)
|
|
719
|
-
}
|
|
720
|
-
},
|
|
721
|
-
{
|
|
722
|
-
id: "scrypted-yolov9m-relu",
|
|
723
|
-
legacy: true,
|
|
724
|
-
name: "YOLOv9 M ReLU",
|
|
725
|
-
description: "YOLOv9m ReLU — medium, int8 ready",
|
|
726
|
-
inputSize: {
|
|
727
|
-
width: 320,
|
|
728
|
-
height: 320
|
|
729
|
-
},
|
|
730
|
-
labels: [],
|
|
731
|
-
preprocessMode: "letterbox",
|
|
732
|
-
formats: {
|
|
733
|
-
onnx: {
|
|
734
|
-
url: hfScrypted("onnx/scrypted_yolov9m_relu/scrypted_yolov9m_relu.onnx"),
|
|
735
|
-
sizeMB: 76.6
|
|
736
|
-
},
|
|
737
|
-
coreml: {
|
|
738
|
-
url: hfScrypted("coreml/scrypted_yolov9m_relu/scrypted_yolov9m_relu.mlpackage"),
|
|
739
|
-
sizeMB: 38,
|
|
740
|
-
isDirectory: true,
|
|
741
|
-
files: [...MLPACKAGE_FILES],
|
|
742
|
-
runtimes: ["python"]
|
|
743
|
-
},
|
|
744
|
-
openvino: ovFormat(hf("objectDetection/scrypted-yolov9-relu/openvino/scrypted_yolov9m_relu.xml"), 38)
|
|
745
|
-
}
|
|
746
|
-
},
|
|
747
|
-
ovPrecisionVariant("yolov9t", "objectDetection/yolov9/openvino", "YOLOv9 Tiny", "fp16", 5, true),
|
|
748
|
-
ovPrecisionVariant("yolov9t", "objectDetection/yolov9/openvino", "YOLOv9 Tiny", "int8", 3, true),
|
|
749
|
-
ovPrecisionVariant("yolov9s", "objectDetection/yolov9/openvino", "YOLOv9 Small", "fp16", 15, true),
|
|
750
|
-
ovPrecisionVariant("yolov9s", "objectDetection/yolov9/openvino", "YOLOv9 Small", "int8", 8, true),
|
|
751
|
-
ovPrecisionVariant("yolo26n", "objectDetection/yolo26/openvino", "YOLO26 Nano", "fp16", 5, true),
|
|
752
|
-
ovPrecisionVariant("yolo26n", "objectDetection/yolo26/openvino", "YOLO26 Nano", "int8", 3),
|
|
753
|
-
ovPrecisionVariant("yolo26s", "objectDetection/yolo26/openvino", "YOLO26 Small", "fp16", 19, true),
|
|
754
|
-
ovPrecisionVariant("yolo26s", "objectDetection/yolo26/openvino", "YOLO26 Small", "int8", 10),
|
|
755
|
-
ovPrecisionVariant("yolo26m", "objectDetection/yolo26/openvino", "YOLO26 Medium", "fp16", 41, true),
|
|
756
|
-
ovPrecisionVariant("yolo26m", "objectDetection/yolo26/openvino", "YOLO26 Medium", "int8", 21),
|
|
757
|
-
ovPrecisionVariant("yolo26l", "objectDetection/yolo26/openvino", "YOLO26 Large", "fp16", 50, true),
|
|
758
|
-
ovPrecisionVariant("yolo26l", "objectDetection/yolo26/openvino", "YOLO26 Large", "int8", 25),
|
|
759
|
-
...yolo26Reduced("n", 320, {
|
|
760
|
-
onnx: 10.47,
|
|
761
|
-
coreml: 5.05,
|
|
762
|
-
ovFp32: 10.05,
|
|
763
|
-
ovInt8: 3.29
|
|
764
|
-
}),
|
|
765
|
-
...yolo26Reduced("n", 256, {
|
|
766
|
-
onnx: 10.47,
|
|
767
|
-
coreml: 5.05,
|
|
768
|
-
ovFp32: 10.05,
|
|
769
|
-
ovInt8: 3.29
|
|
770
|
-
}),
|
|
771
|
-
...yolo26Reduced("s", 320, {
|
|
772
|
-
onnx: 38.82,
|
|
773
|
-
coreml: 19.23,
|
|
774
|
-
ovFp32: 38.4,
|
|
775
|
-
ovInt8: 10.43
|
|
776
|
-
}),
|
|
777
|
-
...yolo26Reduced("s", 256, {
|
|
778
|
-
onnx: 38.82,
|
|
779
|
-
coreml: 19.23,
|
|
780
|
-
ovFp32: 38.4,
|
|
781
|
-
ovInt8: 10.43
|
|
782
|
-
}),
|
|
783
|
-
...yolo26Reduced("m", 320, {
|
|
784
|
-
onnx: 83.31,
|
|
785
|
-
coreml: 41.07,
|
|
786
|
-
ovFp32: 82.09,
|
|
787
|
-
ovInt8: 21.47
|
|
788
|
-
}),
|
|
789
|
-
...yolo26Reduced("m", 256, {
|
|
790
|
-
onnx: 83.31,
|
|
791
|
-
coreml: 41.07,
|
|
792
|
-
ovFp32: 82.09,
|
|
793
|
-
ovInt8: 21.47
|
|
794
|
-
}),
|
|
795
|
-
...yolo26Reduced("l", 320, {
|
|
796
|
-
onnx: 101.74,
|
|
797
|
-
coreml: 49.97,
|
|
798
|
-
ovFp32: 99.85,
|
|
799
|
-
ovInt8: 26.31
|
|
800
|
-
}),
|
|
801
|
-
...yolo26Reduced("l", 256, {
|
|
802
|
-
onnx: 101.74,
|
|
803
|
-
coreml: 49.97,
|
|
804
|
-
ovFp32: 99.85,
|
|
805
|
-
ovInt8: 26.31
|
|
806
|
-
}),
|
|
807
|
-
ovPrecisionVariant("yolo26x", "objectDetection/yolo26/openvino", "YOLO26 XLarge", "fp16", 112, true),
|
|
808
|
-
ovPrecisionVariant("yolo26x", "objectDetection/yolo26/openvino", "YOLO26 XLarge", "int8", 56, true)
|
|
809
|
-
];
|
|
810
|
-
var FACE_DETECTION_MODELS = [{
|
|
811
|
-
id: "scrfd-2.5g",
|
|
812
|
-
name: "SCRFD 2.5G",
|
|
813
|
-
description: "SCRFD 2.5G — balanced face detection model",
|
|
814
|
-
inputSize: {
|
|
815
|
-
width: 640,
|
|
816
|
-
height: 640
|
|
817
|
-
},
|
|
818
|
-
labels: [{
|
|
819
|
-
id: "face",
|
|
820
|
-
name: "Face"
|
|
821
|
-
}],
|
|
822
|
-
preprocessMode: "letterbox",
|
|
823
|
-
formats: {
|
|
824
|
-
onnx: {
|
|
825
|
-
url: hf("faceDetection/scrfd/onnx/camstack-scrfd-2.5g.onnx"),
|
|
826
|
-
sizeMB: 3.1
|
|
827
|
-
},
|
|
828
|
-
coreml: {
|
|
829
|
-
url: hf("faceDetection/scrfd/coreml/camstack-scrfd-2.5g.mlpackage"),
|
|
830
|
-
sizeMB: 1.7,
|
|
831
|
-
isDirectory: true,
|
|
832
|
-
files: [...MLPACKAGE_FILES],
|
|
833
|
-
runtimes: ["python"]
|
|
834
|
-
},
|
|
835
|
-
openvino: ovFormat(hf("faceDetection/scrfd/openvino/camstack-scrfd-2.5g.xml"), 1.8)
|
|
836
|
-
}
|
|
837
|
-
}, {
|
|
838
|
-
id: "scrypted-yolov9t-face",
|
|
839
|
-
name: "YOLOv9t Face ReLU",
|
|
840
|
-
description: "YOLOv9t face detection — YOLO-based, fast, 320x320 ReLU",
|
|
841
|
-
inputSize: {
|
|
842
|
-
width: 320,
|
|
843
|
-
height: 320
|
|
844
|
-
},
|
|
845
|
-
labels: [{
|
|
846
|
-
id: "face",
|
|
847
|
-
name: "Face"
|
|
848
|
-
}],
|
|
849
|
-
preprocessMode: "letterbox",
|
|
850
|
-
formats: {
|
|
851
|
-
onnx: {
|
|
852
|
-
url: hfScrypted("onnx/scrypted_yolov9t_relu_face/scrypted_yolov9t_relu_face.onnx"),
|
|
853
|
-
sizeMB: 8.1
|
|
854
|
-
},
|
|
855
|
-
coreml: {
|
|
856
|
-
url: hfScrypted("coreml/scrypted_yolov9t_relu_face/scrypted_yolov9t_relu_face.mlpackage"),
|
|
857
|
-
sizeMB: 4,
|
|
858
|
-
isDirectory: true,
|
|
859
|
-
files: [...MLPACKAGE_FILES],
|
|
860
|
-
runtimes: ["python"]
|
|
861
|
-
},
|
|
862
|
-
openvino: ovFormat(hf("faceDetection/scrypted-yolov9-face/openvino/scrypted_yolov9t_relu_face.xml"), 6)
|
|
863
|
-
}
|
|
864
|
-
}];
|
|
865
|
-
var FACE_EMBEDDING_MODELS = [{
|
|
866
|
-
id: "arcface-r100",
|
|
867
|
-
name: "ArcFace R100",
|
|
868
|
-
description: "ArcFace ResNet-100 — high-accuracy face recognition embeddings (512-d)",
|
|
869
|
-
inputSize: {
|
|
870
|
-
width: 112,
|
|
871
|
-
height: 112
|
|
872
|
-
},
|
|
873
|
-
inputLayout: "nhwc",
|
|
874
|
-
labels: [{
|
|
875
|
-
id: "embedding",
|
|
876
|
-
name: "Face Embedding"
|
|
877
|
-
}],
|
|
878
|
-
preprocessMode: "resize",
|
|
879
|
-
faceAlignment: true,
|
|
880
|
-
formats: {
|
|
881
|
-
onnx: {
|
|
882
|
-
url: hf("faceRecognition/arcface/onnx/camstack-arcface-arcface.onnx"),
|
|
883
|
-
sizeMB: 130
|
|
884
|
-
},
|
|
885
|
-
coreml: {
|
|
886
|
-
url: hf("faceRecognition/arcface/coreml/camstack-arcface-r100.mlpackage"),
|
|
887
|
-
sizeMB: 65,
|
|
888
|
-
isDirectory: true,
|
|
889
|
-
files: [...MLPACKAGE_FILES],
|
|
890
|
-
runtimes: ["python"]
|
|
891
|
-
},
|
|
892
|
-
openvino: ovFormat(hf("faceRecognition/arcface/openvino/camstack-arcface-r100.xml"), 65)
|
|
893
|
-
}
|
|
894
|
-
}, {
|
|
895
|
-
id: "inception-resnet-v1",
|
|
896
|
-
name: "Inception ResNet V1",
|
|
897
|
-
description: "FaceNet-style face recognition embeddings (512-d) — hosted on plugin-models HF repo",
|
|
898
|
-
inputSize: {
|
|
899
|
-
width: 160,
|
|
900
|
-
height: 160
|
|
901
|
-
},
|
|
902
|
-
labels: [{
|
|
903
|
-
id: "embedding",
|
|
904
|
-
name: "Face Embedding"
|
|
905
|
-
}],
|
|
906
|
-
preprocessMode: "resize",
|
|
907
|
-
formats: {
|
|
908
|
-
onnx: {
|
|
909
|
-
url: hfScrypted("onnx/inception_resnet_v1/inception_resnet_v1.onnx"),
|
|
910
|
-
sizeMB: 89.6
|
|
911
|
-
},
|
|
912
|
-
coreml: {
|
|
913
|
-
url: hfScrypted("coreml/inception_resnet_v1/inception_resnet_v1.mlpackage"),
|
|
914
|
-
sizeMB: 45,
|
|
915
|
-
isDirectory: true,
|
|
916
|
-
files: [...MLPACKAGE_FILES],
|
|
917
|
-
runtimes: ["python"]
|
|
918
|
-
},
|
|
919
|
-
openvino: ovFormat(hf("faceRecognition/inception-resnet-v1/openvino/camstack-inception-resnet-v1.xml"), 45)
|
|
920
|
-
}
|
|
921
|
-
}];
|
|
922
|
-
var PLATE_DETECTION_MODELS = [{
|
|
923
|
-
id: "yolov8n-plate",
|
|
924
|
-
name: "YOLOv8 Nano — License Plate",
|
|
925
|
-
description: "YOLOv8 Nano fine-tuned for license plate detection",
|
|
926
|
-
inputSize: {
|
|
927
|
-
width: 640,
|
|
928
|
-
height: 640
|
|
929
|
-
},
|
|
930
|
-
labels: [{
|
|
931
|
-
id: "plate",
|
|
932
|
-
name: "License Plate"
|
|
933
|
-
}],
|
|
934
|
-
preprocessMode: "letterbox",
|
|
935
|
-
formats: {
|
|
936
|
-
onnx: {
|
|
937
|
-
url: hf("plateDetection/yolov8-plate/onnx/camstack-yolov8n-plate.onnx"),
|
|
938
|
-
sizeMB: 12
|
|
939
|
-
},
|
|
940
|
-
coreml: {
|
|
941
|
-
url: hf("plateDetection/yolov8-plate/coreml/camstack-yolov8n-plate.mlpackage"),
|
|
942
|
-
sizeMB: 5.9,
|
|
943
|
-
isDirectory: true,
|
|
944
|
-
files: [...MLPACKAGE_FILES],
|
|
945
|
-
runtimes: ["python"]
|
|
946
|
-
},
|
|
947
|
-
openvino: ovFormat(hf("plateDetection/yolov8-plate/openvino/camstack-yolov8n-plate.xml"), 6.1)
|
|
948
|
-
}
|
|
949
|
-
}];
|
|
950
|
-
var PLATE_OCR_MODELS = [{
|
|
951
|
-
id: "vgg-english-g2",
|
|
952
|
-
name: "VGG English G2",
|
|
953
|
-
description: "EasyOCR VGG English G2 — text recognition for license plates and scene text",
|
|
954
|
-
inputSize: {
|
|
955
|
-
width: 384,
|
|
956
|
-
height: 64
|
|
957
|
-
},
|
|
958
|
-
labels: [{
|
|
959
|
-
id: "text",
|
|
960
|
-
name: "Plate Text"
|
|
961
|
-
}],
|
|
962
|
-
preprocessMode: "resize",
|
|
963
|
-
formats: {
|
|
964
|
-
onnx: {
|
|
965
|
-
url: hfScrypted("onnx/vgg_english_g2/vgg_english_g2.onnx"),
|
|
966
|
-
sizeMB: 14.4
|
|
967
|
-
},
|
|
968
|
-
coreml: {
|
|
969
|
-
url: hfScrypted("coreml/vgg_english_g2/vgg_english_g2.mlpackage"),
|
|
970
|
-
sizeMB: 11.2,
|
|
971
|
-
isDirectory: true,
|
|
972
|
-
files: [...MLPACKAGE_FILES],
|
|
973
|
-
runtimes: ["python"]
|
|
974
|
-
},
|
|
975
|
-
openvino: ovFormat(hf("plateRecognition/vgg_english_g2/openvino/vgg_english_g2.xml"), 7.2)
|
|
976
|
-
}
|
|
977
|
-
}];
|
|
978
|
-
var ANIMAL_CLASSIFIER_MODELS = [{
|
|
979
|
-
id: "animals-10",
|
|
980
|
-
name: "Animal Classifier (10)",
|
|
981
|
-
description: "ViT-based animal type classifier — cat, cow, dog, dolphin, eagle, panda, horse, monkey, sheep, spider",
|
|
982
|
-
inputSize: {
|
|
983
|
-
width: 224,
|
|
984
|
-
height: 224
|
|
985
|
-
},
|
|
986
|
-
inputNormalization: "imagenet",
|
|
987
|
-
labels: [{
|
|
988
|
-
id: "animal-type",
|
|
989
|
-
name: "Animal Type"
|
|
990
|
-
}],
|
|
991
|
-
preprocessMode: "resize",
|
|
992
|
-
formats: {
|
|
993
|
-
onnx: {
|
|
994
|
-
url: hf("animalClassification/animals-10/onnx/camstack-animals-10.onnx"),
|
|
995
|
-
sizeMB: 328
|
|
996
|
-
},
|
|
997
|
-
coreml: {
|
|
998
|
-
url: hf("animalClassification/animals-10/coreml/camstack-animals-10.mlpackage"),
|
|
999
|
-
sizeMB: 164,
|
|
1000
|
-
isDirectory: true,
|
|
1001
|
-
files: [...MLPACKAGE_FILES],
|
|
1002
|
-
runtimes: ["python"]
|
|
1003
|
-
},
|
|
1004
|
-
openvino: ovFormat(hf("animalClassification/animals-10/openvino/camstack-animals-10.xml"), 164)
|
|
1005
|
-
}
|
|
1006
|
-
}];
|
|
1007
|
-
var BIRD_CLASSIFIER_MODELS = [{
|
|
1008
|
-
id: "bird-nabirds-404",
|
|
1009
|
-
name: "NABirds (404 species)",
|
|
1010
|
-
description: "ResNet50 trained on NABirds — 404 North American species",
|
|
1011
|
-
inputSize: {
|
|
1012
|
-
width: 224,
|
|
1013
|
-
height: 224
|
|
1014
|
-
},
|
|
1015
|
-
inputNormalization: "imagenet",
|
|
1016
|
-
labels: [{
|
|
1017
|
-
id: "species",
|
|
1018
|
-
name: "Bird Species"
|
|
1019
|
-
}],
|
|
1020
|
-
preprocessMode: "resize",
|
|
1021
|
-
formats: {
|
|
1022
|
-
onnx: {
|
|
1023
|
-
url: hf("animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404.onnx"),
|
|
1024
|
-
sizeMB: 93
|
|
1025
|
-
},
|
|
1026
|
-
coreml: {
|
|
1027
|
-
url: hf("animalClassification/bird-nabirds/coreml/camstack-bird-nabirds-404.mlpackage"),
|
|
1028
|
-
sizeMB: 47,
|
|
1029
|
-
isDirectory: true,
|
|
1030
|
-
files: [...MLPACKAGE_FILES],
|
|
1031
|
-
runtimes: ["python"]
|
|
1032
|
-
},
|
|
1033
|
-
openvino: ovFormat(hf("animalClassification/bird-nabirds/openvino/camstack-bird-nabirds-404.xml"), 47)
|
|
1034
|
-
},
|
|
1035
|
-
extraFiles: [{
|
|
1036
|
-
url: hf("animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404-labels.json"),
|
|
1037
|
-
filename: "camstack-bird-nabirds-404-labels.json",
|
|
1038
|
-
sizeMB: .02
|
|
1039
|
-
}]
|
|
1040
|
-
}];
|
|
1041
|
-
var VEHICLE_CLASSIFIER_MODELS = [{
|
|
1042
|
-
id: "vehicle-type-efficientnet",
|
|
1043
|
-
name: "Vehicle Type (EfficientNet)",
|
|
1044
|
-
description: "EfficientNet-B4 vehicle make/model/year classifier — 8,949 classes from VMMRdb",
|
|
1045
|
-
inputSize: {
|
|
1046
|
-
width: 380,
|
|
1047
|
-
height: 380
|
|
1048
|
-
},
|
|
1049
|
-
inputNormalization: "imagenet",
|
|
1050
|
-
labels: [{
|
|
1051
|
-
id: "vehicle-type",
|
|
1052
|
-
name: "Vehicle Type"
|
|
1053
|
-
}],
|
|
1054
|
-
preprocessMode: "resize",
|
|
1055
|
-
formats: {
|
|
1056
|
-
onnx: {
|
|
1057
|
-
url: hf("vehicleClassification/efficientnet/onnx/camstack-vehicle-type-efficientnet.onnx"),
|
|
1058
|
-
sizeMB: 135
|
|
1059
|
-
},
|
|
1060
|
-
coreml: {
|
|
1061
|
-
url: hf("vehicleClassification/efficientnet/coreml/camstack-vehicle-type-efficientnet.mlpackage"),
|
|
1062
|
-
sizeMB: 10,
|
|
1063
|
-
isDirectory: true,
|
|
1064
|
-
files: [...MLPACKAGE_FILES],
|
|
1065
|
-
runtimes: ["python"]
|
|
1066
|
-
},
|
|
1067
|
-
openvino: ovFormat(hf("vehicleClassification/efficientnet/openvino/camstack-vehicle-type-efficientnet.xml"), 68)
|
|
1068
|
-
},
|
|
1069
|
-
extraFiles: [{
|
|
1070
|
-
url: hf("vehicleClassification/efficientnet/camstack-vehicle-type-labels.json"),
|
|
1071
|
-
filename: "camstack-vehicle-type-labels.json",
|
|
1072
|
-
sizeMB: .2
|
|
1073
|
-
}]
|
|
1074
|
-
}];
|
|
1075
|
-
var SEGMENTATION_REFINER_MODELS = [{
|
|
1076
|
-
id: "u2netp",
|
|
1077
|
-
name: "U2-Net Portable",
|
|
1078
|
-
description: "U2-Net-P — ultra-lightweight salient object segmentation (4.7 MB)",
|
|
1079
|
-
inputSize: {
|
|
1080
|
-
width: 320,
|
|
1081
|
-
height: 320
|
|
1082
|
-
},
|
|
1083
|
-
labels: [{
|
|
1084
|
-
id: "mask",
|
|
1085
|
-
name: "Segmentation Mask"
|
|
1086
|
-
}],
|
|
1087
|
-
preprocessMode: "resize",
|
|
1088
|
-
formats: {
|
|
1089
|
-
onnx: {
|
|
1090
|
-
url: hf("segmentationRefiner/u2netp/onnx/camstack-u2netp.onnx"),
|
|
1091
|
-
sizeMB: 5
|
|
1092
|
-
},
|
|
1093
|
-
coreml: {
|
|
1094
|
-
url: hf("segmentationRefiner/u2netp/coreml/camstack-u2netp.mlpackage"),
|
|
1095
|
-
sizeMB: 3,
|
|
1096
|
-
isDirectory: true,
|
|
1097
|
-
files: [...MLPACKAGE_FILES],
|
|
1098
|
-
runtimes: ["python"]
|
|
1099
|
-
},
|
|
1100
|
-
openvino: ovFormat(hf("segmentationRefiner/u2netp/openvino/camstack-u2netp.xml"), 2.5)
|
|
1101
|
-
}
|
|
1102
|
-
}];
|
|
1103
|
-
var INSTANCE_SEGMENTATION_MODELS = [
|
|
1104
|
-
{
|
|
1105
|
-
id: "yolo26n-seg",
|
|
1106
|
-
name: "YOLO26 Nano Seg",
|
|
1107
|
-
description: "YOLO26 Nano Segmentation — ultra-lightweight instance segmentation with masks",
|
|
1108
|
-
inputSize: {
|
|
1109
|
-
width: 640,
|
|
1110
|
-
height: 640
|
|
1111
|
-
},
|
|
1112
|
-
labels: [],
|
|
1113
|
-
preprocessMode: "letterbox",
|
|
1114
|
-
formats: {
|
|
1115
|
-
onnx: {
|
|
1116
|
-
url: hf("segmentation/yolo26-seg/onnx/camstack-yolo26n-seg.onnx"),
|
|
1117
|
-
sizeMB: 11
|
|
1118
|
-
},
|
|
1119
|
-
coreml: {
|
|
1120
|
-
url: hf("segmentation/yolo26-seg/coreml/camstack-yolo26n-seg.mlpackage"),
|
|
1121
|
-
sizeMB: 6,
|
|
1122
|
-
isDirectory: true,
|
|
1123
|
-
files: [...MLPACKAGE_FILES],
|
|
1124
|
-
runtimes: ["python"]
|
|
1125
|
-
},
|
|
1126
|
-
openvino: ovFormat(hf("segmentation/yolo26-seg/openvino/camstack-yolo26n-seg.xml"), 11)
|
|
1127
|
-
}
|
|
1128
|
-
},
|
|
1129
|
-
{
|
|
1130
|
-
id: "yolo26s-seg",
|
|
1131
|
-
name: "YOLO26 Small Seg",
|
|
1132
|
-
description: "YOLO26 Small Segmentation — balanced instance segmentation",
|
|
1133
|
-
inputSize: {
|
|
1134
|
-
width: 640,
|
|
1135
|
-
height: 640
|
|
1136
|
-
},
|
|
1137
|
-
labels: [],
|
|
1138
|
-
preprocessMode: "letterbox",
|
|
1139
|
-
formats: {
|
|
1140
|
-
onnx: {
|
|
1141
|
-
url: hf("segmentation/yolo26-seg/onnx/camstack-yolo26s-seg.onnx"),
|
|
1142
|
-
sizeMB: 40
|
|
1143
|
-
},
|
|
1144
|
-
coreml: {
|
|
1145
|
-
url: hf("segmentation/yolo26-seg/coreml/camstack-yolo26s-seg.mlpackage"),
|
|
1146
|
-
sizeMB: 20,
|
|
1147
|
-
isDirectory: true,
|
|
1148
|
-
files: [...MLPACKAGE_FILES],
|
|
1149
|
-
runtimes: ["python"]
|
|
1150
|
-
},
|
|
1151
|
-
openvino: ovFormat(hf("segmentation/yolo26-seg/openvino/camstack-yolo26s-seg.xml"), 40)
|
|
1152
|
-
}
|
|
1153
|
-
},
|
|
1154
|
-
{
|
|
1155
|
-
id: "yolo26m-seg",
|
|
1156
|
-
name: "YOLO26 Medium Seg",
|
|
1157
|
-
description: "YOLO26 Medium Segmentation — high-accuracy instance segmentation",
|
|
1158
|
-
inputSize: {
|
|
1159
|
-
width: 640,
|
|
1160
|
-
height: 640
|
|
1161
|
-
},
|
|
1162
|
-
labels: [],
|
|
1163
|
-
preprocessMode: "letterbox",
|
|
1164
|
-
formats: {
|
|
1165
|
-
onnx: {
|
|
1166
|
-
url: hf("segmentation/yolo26-seg/onnx/camstack-yolo26m-seg.onnx"),
|
|
1167
|
-
sizeMB: 90
|
|
1168
|
-
},
|
|
1169
|
-
coreml: {
|
|
1170
|
-
url: hf("segmentation/yolo26-seg/coreml/camstack-yolo26m-seg.mlpackage"),
|
|
1171
|
-
sizeMB: 45,
|
|
1172
|
-
isDirectory: true,
|
|
1173
|
-
files: [...MLPACKAGE_FILES],
|
|
1174
|
-
runtimes: ["python"]
|
|
1175
|
-
},
|
|
1176
|
-
openvino: ovFormat(hf("segmentation/yolo26-seg/openvino/camstack-yolo26m-seg.xml"), 90)
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
];
|
|
1180
|
-
var CLIP_EMBEDDING_MODELS = [
|
|
1181
|
-
{
|
|
1182
|
-
id: "mobileclip-s0",
|
|
1183
|
-
name: "MobileCLIP S0",
|
|
1184
|
-
description: "MobileCLIP S0 — Apple ultra-fast CLIP vision encoder, 512-dim, 256×256 (40 MB ONNX)",
|
|
1185
|
-
inputSize: {
|
|
1186
|
-
width: 256,
|
|
1187
|
-
height: 256
|
|
1188
|
-
},
|
|
1189
|
-
labels: [{
|
|
1190
|
-
id: "embedding",
|
|
1191
|
-
name: "CLIP Embedding"
|
|
1192
|
-
}],
|
|
1193
|
-
preprocessMode: "resize",
|
|
1194
|
-
inputNormalization: "none",
|
|
1195
|
-
formats: {
|
|
1196
|
-
onnx: {
|
|
1197
|
-
url: hf("clip/mobileclip-s0/onnx/camstack-mobileclip-s0-vision.onnx"),
|
|
1198
|
-
sizeMB: 40
|
|
1199
|
-
},
|
|
1200
|
-
openvino: ovFormat(hf("clip/mobileclip-s0/openvino/camstack-mobileclip-s0-vision.xml"), 25),
|
|
1201
|
-
coreml: {
|
|
1202
|
-
url: hf("clip/mobileclip-s0/coreml/camstack-mobileclip-s0-vision.mlpackage"),
|
|
1203
|
-
sizeMB: 30,
|
|
1204
|
-
isDirectory: true,
|
|
1205
|
-
files: [...MLPACKAGE_FILES],
|
|
1206
|
-
runtimes: ["python"]
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
},
|
|
1210
|
-
{
|
|
1211
|
-
id: "mobileclip-s1",
|
|
1212
|
-
name: "MobileCLIP S1",
|
|
1213
|
-
description: "MobileCLIP S1 — Apple balanced CLIP vision encoder, 512-dim, 256×256 (90 MB ONNX)",
|
|
1214
|
-
inputSize: {
|
|
1215
|
-
width: 256,
|
|
1216
|
-
height: 256
|
|
1217
|
-
},
|
|
1218
|
-
labels: [{
|
|
1219
|
-
id: "embedding",
|
|
1220
|
-
name: "CLIP Embedding"
|
|
1221
|
-
}],
|
|
1222
|
-
preprocessMode: "resize",
|
|
1223
|
-
inputNormalization: "none",
|
|
1224
|
-
formats: {
|
|
1225
|
-
onnx: {
|
|
1226
|
-
url: hf("clip/mobileclip-s1/onnx/camstack-mobileclip-s1-vision.onnx"),
|
|
1227
|
-
sizeMB: 90
|
|
1228
|
-
},
|
|
1229
|
-
openvino: ovFormat(hf("clip/mobileclip-s1/openvino/camstack-mobileclip-s1-vision.xml"), 55),
|
|
1230
|
-
coreml: {
|
|
1231
|
-
url: hf("clip/mobileclip-s1/coreml/camstack-mobileclip-s1-vision.mlpackage"),
|
|
1232
|
-
sizeMB: 65,
|
|
1233
|
-
isDirectory: true,
|
|
1234
|
-
files: [...MLPACKAGE_FILES],
|
|
1235
|
-
runtimes: ["python"]
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
},
|
|
1239
|
-
{
|
|
1240
|
-
id: "mobileclip-s2",
|
|
1241
|
-
name: "MobileCLIP S2",
|
|
1242
|
-
description: "MobileCLIP S2 — Apple high-accuracy CLIP vision encoder, 512-dim, 256×256 (150 MB ONNX)",
|
|
1243
|
-
inputSize: {
|
|
1244
|
-
width: 256,
|
|
1245
|
-
height: 256
|
|
1246
|
-
},
|
|
1247
|
-
labels: [{
|
|
1248
|
-
id: "embedding",
|
|
1249
|
-
name: "CLIP Embedding"
|
|
1250
|
-
}],
|
|
1251
|
-
preprocessMode: "resize",
|
|
1252
|
-
inputNormalization: "none",
|
|
1253
|
-
formats: {
|
|
1254
|
-
onnx: {
|
|
1255
|
-
url: hf("clip/mobileclip-s2/onnx/camstack-mobileclip-s2-vision.onnx"),
|
|
1256
|
-
sizeMB: 150
|
|
1257
|
-
},
|
|
1258
|
-
openvino: ovFormat(hf("clip/mobileclip-s2/openvino/camstack-mobileclip-s2-vision.xml"), 90),
|
|
1259
|
-
coreml: {
|
|
1260
|
-
url: hf("clip/mobileclip-s2/coreml/camstack-mobileclip-s2-vision.mlpackage"),
|
|
1261
|
-
sizeMB: 110,
|
|
1262
|
-
isDirectory: true,
|
|
1263
|
-
files: [...MLPACKAGE_FILES],
|
|
1264
|
-
runtimes: ["python"]
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
];
|
|
1269
|
-
var AUDIO_CLASSIFIER_MODELS = [{
|
|
1270
|
-
id: "yamnet-onnx",
|
|
1271
|
-
name: "YAMNet",
|
|
1272
|
-
description: "Google YAMNet — 521-class audio event classifier (3.2 MB ONNX, runs on any platform)",
|
|
1273
|
-
inputSize: {
|
|
1274
|
-
width: 1,
|
|
1275
|
-
height: 16e3
|
|
1276
|
-
},
|
|
1277
|
-
labels: [],
|
|
1278
|
-
preprocessMode: "resize",
|
|
1279
|
-
formats: {
|
|
1280
|
-
onnx: {
|
|
1281
|
-
url: hf("audioClassification/yamnet/onnx/camstack-yamnet.onnx"),
|
|
1282
|
-
sizeMB: 3.2
|
|
1283
|
-
},
|
|
1284
|
-
openvino: ovFormat(hf("audioClassification/yamnet/openvino/camstack-yamnet.xml"), 3.2),
|
|
1285
|
-
coreml: {
|
|
1286
|
-
url: hf("audioClassification/yamnet/onnx/camstack-yamnet.onnx"),
|
|
1287
|
-
sizeMB: 3.2,
|
|
1288
|
-
runtimes: ["python"]
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
}, {
|
|
1292
|
-
id: "apple-soundanalysis",
|
|
1293
|
-
name: "Apple SoundAnalysis",
|
|
1294
|
-
description: "macOS built-in — 303 sound categories, Neural Engine accelerated, zero download",
|
|
1295
|
-
inputSize: {
|
|
1296
|
-
width: 1,
|
|
1297
|
-
height: 16e3
|
|
1298
|
-
},
|
|
1299
|
-
labels: [],
|
|
1300
|
-
preprocessMode: "resize",
|
|
1301
|
-
formats: { coreml: {
|
|
1302
|
-
url: "",
|
|
1303
|
-
sizeMB: 0
|
|
1304
|
-
} }
|
|
1305
|
-
}];
|
|
1306
|
-
//#endregion
|
|
1307
|
-
//#region src/detection-pipeline/registry/step-definitions.ts
|
|
1308
|
-
var ANIMAL_10_LABELS = [
|
|
1309
|
-
"cat",
|
|
1310
|
-
"cow",
|
|
1311
|
-
"dog",
|
|
1312
|
-
"dolphin",
|
|
1313
|
-
"eagle",
|
|
1314
|
-
"giant panda",
|
|
1315
|
-
"horse",
|
|
1316
|
-
"monkey",
|
|
1317
|
-
"sheep",
|
|
1318
|
-
"spider"
|
|
1319
|
-
];
|
|
1320
|
-
var VGG_G2_CHARSET = ["", ..."0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("")];
|
|
1321
|
-
var PipelineStepBase = class {
|
|
1322
|
-
definition;
|
|
1323
|
-
constructor(definition) {
|
|
1324
|
-
this.definition = definition;
|
|
1325
|
-
}
|
|
1326
|
-
getConfigSchema() {
|
|
1327
|
-
return [];
|
|
1328
|
-
}
|
|
1329
|
-
};
|
|
1330
|
-
var ObjectDetectionStep = class {
|
|
1331
|
-
definition = {
|
|
1332
|
-
id: "object-detection",
|
|
1333
|
-
name: "Object Detection",
|
|
1334
|
-
slot: "detector",
|
|
1335
|
-
postprocessor: "yolo",
|
|
1336
|
-
extractMode: "full-frame",
|
|
1337
|
-
inputClasses: null,
|
|
1338
|
-
outputClasses: [
|
|
1339
|
-
"person",
|
|
1340
|
-
"vehicle",
|
|
1341
|
-
"animal"
|
|
1342
|
-
],
|
|
1343
|
-
models: [...OBJECT_DETECTION_MODELS],
|
|
1344
|
-
defaultModelId: "yolo26n",
|
|
1345
|
-
defaultConfidence: .5,
|
|
1346
|
-
labels: require_dist.COCO_80_LABELS.map((l) => l.id),
|
|
1347
|
-
classMap: require_dist.COCO_TO_MACRO
|
|
1348
|
-
};
|
|
1349
|
-
getConfigSchema() {
|
|
1350
|
-
return [
|
|
1351
|
-
{
|
|
1352
|
-
type: "multiselect",
|
|
1353
|
-
key: "enabledMacroClasses",
|
|
1354
|
-
label: "Enabled Classes",
|
|
1355
|
-
description: "Which macro classes to detect (empty = all three).",
|
|
1356
|
-
options: [
|
|
1357
|
-
{
|
|
1358
|
-
value: "person",
|
|
1359
|
-
label: "Person"
|
|
1360
|
-
},
|
|
1361
|
-
{
|
|
1362
|
-
value: "vehicle",
|
|
1363
|
-
label: "Vehicle"
|
|
1364
|
-
},
|
|
1365
|
-
{
|
|
1366
|
-
value: "animal",
|
|
1367
|
-
label: "Animal"
|
|
1368
|
-
}
|
|
1369
|
-
],
|
|
1370
|
-
default: [
|
|
1371
|
-
"person",
|
|
1372
|
-
"vehicle",
|
|
1373
|
-
"animal"
|
|
1374
|
-
]
|
|
1375
|
-
},
|
|
1376
|
-
{
|
|
1377
|
-
type: "slider",
|
|
1378
|
-
key: "minConfidencePerson",
|
|
1379
|
-
label: "Min Confidence — Person",
|
|
1380
|
-
description: "Drop person predictions below this score.",
|
|
1381
|
-
min: 0,
|
|
1382
|
-
max: 1,
|
|
1383
|
-
step: .05,
|
|
1384
|
-
default: .5,
|
|
1385
|
-
showValue: true
|
|
1386
|
-
},
|
|
1387
|
-
{
|
|
1388
|
-
type: "slider",
|
|
1389
|
-
key: "minConfidenceVehicle",
|
|
1390
|
-
label: "Min Confidence — Vehicle",
|
|
1391
|
-
description: "Drop vehicle predictions below this score.",
|
|
1392
|
-
min: 0,
|
|
1393
|
-
max: 1,
|
|
1394
|
-
step: .05,
|
|
1395
|
-
default: .5,
|
|
1396
|
-
showValue: true
|
|
1397
|
-
},
|
|
1398
|
-
{
|
|
1399
|
-
type: "slider",
|
|
1400
|
-
key: "minConfidenceAnimal",
|
|
1401
|
-
label: "Min Confidence — Animal",
|
|
1402
|
-
description: "Drop animal predictions below this score.",
|
|
1403
|
-
min: 0,
|
|
1404
|
-
max: 1,
|
|
1405
|
-
step: .05,
|
|
1406
|
-
default: .5,
|
|
1407
|
-
showValue: true
|
|
1408
|
-
}
|
|
1409
|
-
];
|
|
1410
|
-
}
|
|
1411
|
-
};
|
|
1412
|
-
var AudioClassifierStep = class {
|
|
1413
|
-
definition = {
|
|
1414
|
-
id: "audio-classifier",
|
|
1415
|
-
name: "Audio Classifier",
|
|
1416
|
-
slot: "audio-classifier",
|
|
1417
|
-
postprocessor: "yamnet",
|
|
1418
|
-
extractMode: "full-frame",
|
|
1419
|
-
inputClasses: null,
|
|
1420
|
-
outputClasses: ["audio"],
|
|
1421
|
-
models: [...AUDIO_CLASSIFIER_MODELS],
|
|
1422
|
-
defaultModelId: "yamnet-onnx",
|
|
1423
|
-
defaultModelIdByFormat: { coreml: "apple-soundanalysis" },
|
|
1424
|
-
enabledByDefault: true,
|
|
1425
|
-
defaultConfidence: .3
|
|
1426
|
-
};
|
|
1427
|
-
getConfigSchema() {
|
|
1428
|
-
return [{
|
|
1429
|
-
type: "multiselect",
|
|
1430
|
-
key: "enabledAudioClasses",
|
|
1431
|
-
label: "Audio Classes",
|
|
1432
|
-
description: "Which audio macro classes to surface (empty = all).",
|
|
1433
|
-
options: require_dist.AUDIO_MACRO_LABELS.map((l) => ({
|
|
1434
|
-
value: l.id,
|
|
1435
|
-
label: `${l.icon ?? ""} ${l.name}`.trim()
|
|
1436
|
-
})),
|
|
1437
|
-
default: [
|
|
1438
|
-
"scream",
|
|
1439
|
-
"crying",
|
|
1440
|
-
"dog",
|
|
1441
|
-
"alarm",
|
|
1442
|
-
"doorbell",
|
|
1443
|
-
"glass_breaking",
|
|
1444
|
-
"gunshot",
|
|
1445
|
-
"siren",
|
|
1446
|
-
"footsteps"
|
|
1447
|
-
]
|
|
1448
|
-
}, {
|
|
1449
|
-
type: "slider",
|
|
1450
|
-
key: "minConfidence",
|
|
1451
|
-
label: "Min Confidence",
|
|
1452
|
-
description: "Drop predictions whose score is below this threshold.",
|
|
1453
|
-
default: .3,
|
|
1454
|
-
min: 0,
|
|
1455
|
-
max: 1,
|
|
1456
|
-
step: .05,
|
|
1457
|
-
showValue: true
|
|
1458
|
-
}];
|
|
1459
|
-
}
|
|
1460
|
-
};
|
|
1461
|
-
var AnimalClassifierStep = class {
|
|
1462
|
-
definition = {
|
|
1463
|
-
id: "animal-classifier",
|
|
1464
|
-
name: "Animal Classifier",
|
|
1465
|
-
slot: "classifier",
|
|
1466
|
-
postprocessor: "softmax",
|
|
1467
|
-
extractMode: "crop-roi",
|
|
1468
|
-
inputClasses: ["animal"],
|
|
1469
|
-
outputClasses: ["animal-type"],
|
|
1470
|
-
models: [...ANIMAL_CLASSIFIER_MODELS],
|
|
1471
|
-
defaultModelId: "animals-10",
|
|
1472
|
-
enabledByDefault: false,
|
|
1473
|
-
defaultConfidence: .2,
|
|
1474
|
-
labels: [...ANIMAL_10_LABELS]
|
|
1475
|
-
};
|
|
1476
|
-
getConfigSchema() {
|
|
1477
|
-
return [{
|
|
1478
|
-
type: "multiselect",
|
|
1479
|
-
key: "enabledClasses",
|
|
1480
|
-
label: "Species",
|
|
1481
|
-
description: "Which animal species to keep (empty = all). The classifier still scores every label but only the selected classes are returned on the detection.",
|
|
1482
|
-
options: ANIMAL_10_LABELS.map((l) => ({
|
|
1483
|
-
value: l,
|
|
1484
|
-
label: l
|
|
1485
|
-
})),
|
|
1486
|
-
default: []
|
|
1487
|
-
}, {
|
|
1488
|
-
type: "slider",
|
|
1489
|
-
key: "minConfidence",
|
|
1490
|
-
label: "Min Confidence",
|
|
1491
|
-
description: "Drop classifications whose score is below this threshold.",
|
|
1492
|
-
default: this.definition.defaultConfidence,
|
|
1493
|
-
min: 0,
|
|
1494
|
-
max: 1,
|
|
1495
|
-
step: .05,
|
|
1496
|
-
showValue: true
|
|
1497
|
-
}];
|
|
1498
|
-
}
|
|
1499
|
-
};
|
|
1500
|
-
var ClassifierWithMinConfidence = class extends PipelineStepBase {
|
|
1501
|
-
getConfigSchema() {
|
|
1502
|
-
return [{
|
|
1503
|
-
type: "slider",
|
|
1504
|
-
key: "minConfidence",
|
|
1505
|
-
label: "Min Confidence",
|
|
1506
|
-
description: "Drop classifications whose score is below this threshold.",
|
|
1507
|
-
default: this.definition.defaultConfidence,
|
|
1508
|
-
min: 0,
|
|
1509
|
-
max: 1,
|
|
1510
|
-
step: .05,
|
|
1511
|
-
showValue: true
|
|
1512
|
-
}];
|
|
1513
|
-
}
|
|
1514
|
-
};
|
|
1515
|
-
var STEP_FACE_DETECTION = new PipelineStepBase({
|
|
1516
|
-
id: "face-detection",
|
|
1517
|
-
name: "Face Detection",
|
|
1518
|
-
slot: "cropper",
|
|
1519
|
-
postprocessor: "scrfd",
|
|
1520
|
-
extractMode: "crop-roi",
|
|
1521
|
-
inputClasses: ["person"],
|
|
1522
|
-
outputClasses: ["face"],
|
|
1523
|
-
models: [...FACE_DETECTION_MODELS],
|
|
1524
|
-
defaultModelId: "scrfd-2.5g",
|
|
1525
|
-
defaultConfidence: .5,
|
|
1526
|
-
defaultMinParentScore: .7
|
|
1527
|
-
});
|
|
1528
|
-
var STEP_FACE_EMBEDDING = new PipelineStepBase({
|
|
1529
|
-
id: "face-embedding",
|
|
1530
|
-
name: "Face Embedding",
|
|
1531
|
-
slot: "classifier",
|
|
1532
|
-
postprocessor: "arcface",
|
|
1533
|
-
extractMode: "crop-roi",
|
|
1534
|
-
inputClasses: ["face"],
|
|
1535
|
-
outputClasses: ["identity"],
|
|
1536
|
-
models: [...FACE_EMBEDDING_MODELS],
|
|
1537
|
-
defaultModelId: "arcface-r100",
|
|
1538
|
-
defaultConfidence: 0
|
|
1539
|
-
});
|
|
1540
|
-
var STEP_CLIP_EMBEDDING = new PipelineStepBase({
|
|
1541
|
-
id: "clip-embedding",
|
|
1542
|
-
name: "CLIP Embedding",
|
|
1543
|
-
slot: "classifier",
|
|
1544
|
-
postprocessor: "clip",
|
|
1545
|
-
extractMode: "crop-roi",
|
|
1546
|
-
inputClasses: [
|
|
1547
|
-
"person",
|
|
1548
|
-
"vehicle",
|
|
1549
|
-
"animal"
|
|
1550
|
-
],
|
|
1551
|
-
outputClasses: ["embedding"],
|
|
1552
|
-
models: [...CLIP_EMBEDDING_MODELS],
|
|
1553
|
-
defaultModelId: "mobileclip-s1",
|
|
1554
|
-
enabledByDefault: true,
|
|
1555
|
-
backfillIntoExistingOverrides: true,
|
|
1556
|
-
defaultConfidence: 0,
|
|
1557
|
-
defaultMinParentScore: .4,
|
|
1558
|
-
group: "CLIP"
|
|
1559
|
-
});
|
|
1560
|
-
var STEP_PLATE_DETECTION = new PipelineStepBase({
|
|
1561
|
-
id: "plate-detection",
|
|
1562
|
-
name: "Plate Detection",
|
|
1563
|
-
slot: "cropper",
|
|
1564
|
-
postprocessor: "yolo",
|
|
1565
|
-
extractMode: "crop-roi",
|
|
1566
|
-
inputClasses: ["vehicle"],
|
|
1567
|
-
outputClasses: ["plate"],
|
|
1568
|
-
models: [...PLATE_DETECTION_MODELS],
|
|
1569
|
-
defaultModelId: "yolov8n-plate",
|
|
1570
|
-
defaultConfidence: .5,
|
|
1571
|
-
defaultMinParentScore: .7,
|
|
1572
|
-
labels: ["plate"]
|
|
1573
|
-
});
|
|
1574
|
-
var STEP_PLATE_OCR = new PipelineStepBase({
|
|
1575
|
-
id: "plate-ocr",
|
|
1576
|
-
name: "Plate OCR",
|
|
1577
|
-
slot: "classifier",
|
|
1578
|
-
postprocessor: "ctc",
|
|
1579
|
-
extractMode: "crop-roi",
|
|
1580
|
-
inputClasses: ["plate"],
|
|
1581
|
-
outputClasses: ["plate-text"],
|
|
1582
|
-
models: [...PLATE_OCR_MODELS],
|
|
1583
|
-
defaultModelId: "vgg-english-g2",
|
|
1584
|
-
defaultConfidence: 0,
|
|
1585
|
-
charset: [...VGG_G2_CHARSET]
|
|
1586
|
-
});
|
|
1587
|
-
var STEP_BIRD_CLASSIFIER = new ClassifierWithMinConfidence({
|
|
1588
|
-
id: "bird-classifier",
|
|
1589
|
-
name: "Bird Classifier",
|
|
1590
|
-
slot: "classifier",
|
|
1591
|
-
postprocessor: "softmax",
|
|
1592
|
-
extractMode: "crop-roi",
|
|
1593
|
-
inputClasses: ["animal"],
|
|
1594
|
-
outputClasses: ["species"],
|
|
1595
|
-
models: [...BIRD_CLASSIFIER_MODELS],
|
|
1596
|
-
defaultModelId: "bird-nabirds-404",
|
|
1597
|
-
enabledByDefault: false,
|
|
1598
|
-
defaultConfidence: .2
|
|
1599
|
-
});
|
|
1600
|
-
var STEP_VEHICLE_CLASSIFIER = new ClassifierWithMinConfidence({
|
|
1601
|
-
id: "vehicle-classifier",
|
|
1602
|
-
name: "Vehicle Classifier",
|
|
1603
|
-
slot: "classifier",
|
|
1604
|
-
postprocessor: "softmax",
|
|
1605
|
-
extractMode: "crop-roi",
|
|
1606
|
-
inputClasses: ["vehicle"],
|
|
1607
|
-
outputClasses: ["vehicle-type"],
|
|
1608
|
-
models: [...VEHICLE_CLASSIFIER_MODELS],
|
|
1609
|
-
defaultModelId: "vehicle-type-efficientnet",
|
|
1610
|
-
enabledByDefault: false,
|
|
1611
|
-
defaultConfidence: .3
|
|
1612
|
-
});
|
|
1613
|
-
var STEP_SEGMENTATION = new PipelineStepBase({
|
|
1614
|
-
id: "segmentation",
|
|
1615
|
-
name: "Segmentation",
|
|
1616
|
-
slot: "refiner",
|
|
1617
|
-
postprocessor: "saliency",
|
|
1618
|
-
extractMode: "crop-roi",
|
|
1619
|
-
inputClasses: null,
|
|
1620
|
-
outputClasses: ["mask"],
|
|
1621
|
-
models: [...SEGMENTATION_REFINER_MODELS],
|
|
1622
|
-
defaultModelId: "u2netp",
|
|
1623
|
-
enabledByDefault: false,
|
|
1624
|
-
defaultConfidence: 0,
|
|
1625
|
-
group: "Segmentation"
|
|
1626
|
-
});
|
|
1627
|
-
new PipelineStepBase({
|
|
1628
|
-
id: "instance-segmentation",
|
|
1629
|
-
name: "Instance Segmentation",
|
|
1630
|
-
slot: "refiner",
|
|
1631
|
-
postprocessor: "yolo-seg",
|
|
1632
|
-
extractMode: "full-frame",
|
|
1633
|
-
inputClasses: null,
|
|
1634
|
-
outputClasses: ["mask"],
|
|
1635
|
-
models: [...INSTANCE_SEGMENTATION_MODELS],
|
|
1636
|
-
defaultModelId: "yolo26n-seg",
|
|
1637
|
-
enabledByDefault: false,
|
|
1638
|
-
defaultConfidence: .25,
|
|
1639
|
-
labels: require_dist.COCO_80_LABELS.map((l) => l.id),
|
|
1640
|
-
classMap: require_dist.COCO_TO_MACRO,
|
|
1641
|
-
group: "Segmentation"
|
|
1642
|
-
});
|
|
1643
|
-
var STEP_OBJECT_DETECTION_INSTANCE = new ObjectDetectionStep();
|
|
1644
|
-
var STEP_AUDIO_CLASSIFIER_INSTANCE = new AudioClassifierStep();
|
|
1645
|
-
var ALL_PIPELINE_STEPS = [
|
|
1646
|
-
STEP_OBJECT_DETECTION_INSTANCE,
|
|
1647
|
-
STEP_FACE_DETECTION,
|
|
1648
|
-
STEP_FACE_EMBEDDING,
|
|
1649
|
-
STEP_CLIP_EMBEDDING,
|
|
1650
|
-
STEP_PLATE_DETECTION,
|
|
1651
|
-
STEP_PLATE_OCR,
|
|
1652
|
-
new AnimalClassifierStep(),
|
|
1653
|
-
STEP_BIRD_CLASSIFIER,
|
|
1654
|
-
STEP_VEHICLE_CLASSIFIER,
|
|
1655
|
-
STEP_SEGMENTATION,
|
|
1656
|
-
STEP_AUDIO_CLASSIFIER_INSTANCE
|
|
1657
|
-
];
|
|
1658
|
-
/** Compat: flat array of StepDefinition for existing consumers */
|
|
1659
|
-
var ALL_STEPS = ALL_PIPELINE_STEPS.map((s) => s.definition);
|
|
1660
|
-
var STEP_MAP = new Map(ALL_PIPELINE_STEPS.map((s) => [s.definition.id, s]));
|
|
1661
|
-
/**
|
|
1662
|
-
* Look up a pipeline step by ID (class instance with getConfigSchema).
|
|
1663
|
-
* @throws if the step ID is not registered.
|
|
1664
|
-
*/
|
|
1665
|
-
function getStep(stepId) {
|
|
1666
|
-
const step = STEP_MAP.get(stepId);
|
|
1667
|
-
if (!step) throw new Error(`Unknown pipeline step: "${stepId}". Available: ${ALL_PIPELINE_STEPS.map((s) => s.definition.id).join(", ")}`);
|
|
1668
|
-
return step;
|
|
1669
|
-
}
|
|
1670
|
-
/**
|
|
1671
|
-
* Look up a step definition by ID (compat shortcut).
|
|
1672
|
-
* @throws if the step ID is not registered.
|
|
1673
|
-
*/
|
|
1674
|
-
function getStepDefinition(stepId) {
|
|
1675
|
-
return getStep(stepId).definition;
|
|
1676
|
-
}
|
|
1677
|
-
/**
|
|
1678
|
-
* Get the default model ID for a step given the current model format.
|
|
1679
|
-
*
|
|
1680
|
-
* Resolution order:
|
|
1681
|
-
* 1. `def.defaultModelIdByFormat?.[format]` — the step's declared
|
|
1682
|
-
* per-format preference — if that model exists in `def.models` AND
|
|
1683
|
-
* has a build for `format`.
|
|
1684
|
-
* 2. `def.defaultModelId` — the step's plain declared default — if it
|
|
1685
|
-
* exists in `def.models` AND has a build for `format`.
|
|
1686
|
-
* 3. The smallest-by-size model among those with a `format` build
|
|
1687
|
-
* (legacy fallback, preserved for steps/formats with no declared
|
|
1688
|
-
* preference reachable).
|
|
1689
|
-
* 4. `def.defaultModelId` unchanged, when ZERO models have a `format`
|
|
1690
|
-
* build — an unloadable case flagged elsewhere, not resolved here.
|
|
1691
|
-
*/
|
|
1692
|
-
function getDefaultModelForFormat(stepId, format) {
|
|
1693
|
-
const def = getStepDefinition(stepId);
|
|
1694
|
-
const hasFormatBuild = (modelId) => def.models.find((m) => m.id === modelId)?.formats[format] !== void 0;
|
|
1695
|
-
const declaredForFormat = def.defaultModelIdByFormat?.[format];
|
|
1696
|
-
if (declaredForFormat !== void 0 && hasFormatBuild(declaredForFormat)) return declaredForFormat;
|
|
1697
|
-
if (hasFormatBuild(def.defaultModelId)) return def.defaultModelId;
|
|
1698
|
-
const available = def.models.filter((m) => m.formats[format] && m.legacy !== true);
|
|
1699
|
-
if (available.length === 0) return def.defaultModelId;
|
|
1700
|
-
return [...available].toSorted((a, b) => {
|
|
1701
|
-
return (a.formats[format]?.sizeMB ?? Infinity) - (b.formats[format]?.sizeMB ?? Infinity);
|
|
1702
|
-
})[0].id;
|
|
1703
|
-
}
|
|
1704
|
-
/**
|
|
1705
|
-
* The single node-local authority for turning a CHOSEN model (or none) into a
|
|
1706
|
-
* concrete model that has a build for this node's engine `format`. Fuses the
|
|
1707
|
-
* two previously-duplicated decisions (orchestrator `pickDefaultModelId` +
|
|
1708
|
-
* provider `substituteIncompatibleModels`):
|
|
1709
|
-
*
|
|
1710
|
-
* - chosen === null → the addon's default model for `format`.
|
|
1711
|
-
* - chosen is a catalog model → keep it if it has a `format` build; else
|
|
1712
|
-
* the addon's default model for `format`
|
|
1713
|
-
* (a substitution — the caller surfaces it).
|
|
1714
|
-
* - chosen is NOT in the catalog (custom/unknown) → returned unchanged; the
|
|
1715
|
-
* operator owns a custom model's format compat.
|
|
1716
|
-
* - unknown stepId → chosen returned unchanged (never throws).
|
|
1717
|
-
*/
|
|
1718
|
-
function resolveModelForFormat(stepId, chosenModelId, format) {
|
|
1719
|
-
let def;
|
|
1720
|
-
try {
|
|
1721
|
-
def = getStepDefinition(stepId);
|
|
1722
|
-
} catch {
|
|
1723
|
-
return chosenModelId ?? "";
|
|
1724
|
-
}
|
|
1725
|
-
if (chosenModelId === null) return getDefaultModelForFormat(stepId, format);
|
|
1726
|
-
const entry = def.models.find((m) => m.id === chosenModelId);
|
|
1727
|
-
if (!entry) return chosenModelId;
|
|
1728
|
-
if (entry.formats[format]) return chosenModelId;
|
|
1729
|
-
return getDefaultModelForFormat(stepId, format);
|
|
1730
|
-
}
|
|
1731
|
-
//#endregion
|
|
1732
302
|
//#region src/detection-pipeline/default-detection-model.ts
|
|
1733
303
|
/** The object-detection step id — the only slot this resolver applies to. */
|
|
1734
304
|
var OBJECT_DETECTION_STEP_ID = "object-detection";
|
|
@@ -1788,7 +358,7 @@ function classifyAccelerator(backend, device) {
|
|
|
1788
358
|
* missing-build fallback branch is unit-testable without a live catalog —
|
|
1789
359
|
* mirrors `collectZeroBuildIssues`' injection seam.
|
|
1790
360
|
*/
|
|
1791
|
-
function resolveDefaultDetectionModel(backend, device, format, getStepDef = getStepDefinition) {
|
|
361
|
+
function resolveDefaultDetectionModel(backend, device, format, getStepDef = require_step_definitions.getStepDefinition) {
|
|
1792
362
|
let def;
|
|
1793
363
|
try {
|
|
1794
364
|
def = getStepDef(OBJECT_DETECTION_STEP_ID);
|
|
@@ -2819,7 +1389,7 @@ var EngineFactory = class {
|
|
|
2819
1389
|
await this.poolManager.applyConfig(steps);
|
|
2820
1390
|
}
|
|
2821
1391
|
buildPoolModelConfig(stepId, modelId, poolRuntime) {
|
|
2822
|
-
const def = getStepDefinition(stepId);
|
|
1392
|
+
const def = require_step_definitions.getStepDefinition(stepId);
|
|
2823
1393
|
const modelEntry = def.models.find((m) => m.id === modelId);
|
|
2824
1394
|
if (!modelEntry) throw new Error(`Model "${modelId}" not found in step "${stepId}" catalog`);
|
|
2825
1395
|
const format = RUNTIME_TO_FORMAT[poolRuntime];
|
|
@@ -3723,6 +2293,110 @@ function bboxShortSide(bbox) {
|
|
|
3723
2293
|
return Math.min(bbox[2] - bbox[0], bbox[3] - bbox[1]);
|
|
3724
2294
|
}
|
|
3725
2295
|
/**
|
|
2296
|
+
* Padded region (clamped to the frame) around a face bbox — the area a native
|
|
2297
|
+
* crop must cover so the warp has room around a tilted / edge face. Mirrors the
|
|
2298
|
+
* padding {@link alignFaceCrop} applies internally (`padRatio` default 0.4), so
|
|
2299
|
+
* the native and fallback paths sample the same neighbourhood.
|
|
2300
|
+
*/
|
|
2301
|
+
function paddedFaceRegion(faceBbox, imageWidth, imageHeight, padRatio = .4) {
|
|
2302
|
+
const bw = faceBbox[2] - faceBbox[0];
|
|
2303
|
+
const bh = faceBbox[3] - faceBbox[1];
|
|
2304
|
+
const padX = bw * padRatio;
|
|
2305
|
+
const padY = bh * padRatio;
|
|
2306
|
+
return {
|
|
2307
|
+
left: Math.max(0, Math.floor(faceBbox[0] - padX)),
|
|
2308
|
+
top: Math.max(0, Math.floor(faceBbox[1] - padY)),
|
|
2309
|
+
right: Math.min(imageWidth, Math.ceil(faceBbox[2] + padX)),
|
|
2310
|
+
bottom: Math.min(imageHeight, Math.ceil(faceBbox[3] + padY))
|
|
2311
|
+
};
|
|
2312
|
+
}
|
|
2313
|
+
/**
|
|
2314
|
+
* Warp a raw RGB crop of `region` (native-resolution pixels of exactly that
|
|
2315
|
+
* detection-space region) so `landmarksImageSpace` land on the ArcFace
|
|
2316
|
+
* template. Landmarks are mapped from image space into the crop's local pixel
|
|
2317
|
+
* space by the per-axis region→crop scale (handles `maxWidth` downscale of the
|
|
2318
|
+
* native crop). Channels default to RGB (3) — the format the decode worker's
|
|
2319
|
+
* native surface produces.
|
|
2320
|
+
*/
|
|
2321
|
+
async function alignFaceCropFromRgb(rgb, region, landmarksImageSpace, opts = {}) {
|
|
2322
|
+
const outSize = opts.outSize ?? 112;
|
|
2323
|
+
const quality = opts.quality ?? 95;
|
|
2324
|
+
const channels = opts.channels ?? 3;
|
|
2325
|
+
const regionW = region.right - region.left;
|
|
2326
|
+
const regionH = region.bottom - region.top;
|
|
2327
|
+
if (regionW < 1 || regionH < 1) throw new Error(`alignFaceCropFromRgb: degenerate region ${regionW}x${regionH}`);
|
|
2328
|
+
if (rgb.width < 2 || rgb.height < 2) throw new Error(`alignFaceCropFromRgb: degenerate crop ${rgb.width}x${rgb.height}`);
|
|
2329
|
+
const scaleX = rgb.width / regionW;
|
|
2330
|
+
const scaleY = rgb.height / regionH;
|
|
2331
|
+
const localLandmarks = landmarksImageSpace.map((l) => ({
|
|
2332
|
+
x: (l.x - region.left) * scaleX,
|
|
2333
|
+
y: (l.y - region.top) * scaleY
|
|
2334
|
+
}));
|
|
2335
|
+
const aligned = warpToTemplate({
|
|
2336
|
+
data: rgb.bytes,
|
|
2337
|
+
width: rgb.width,
|
|
2338
|
+
height: rgb.height,
|
|
2339
|
+
channels
|
|
2340
|
+
}, localLandmarks, opts.template ?? ARCFACE_TEMPLATE_112, outSize);
|
|
2341
|
+
return {
|
|
2342
|
+
jpeg: await (0, sharp.default)(Buffer.from(aligned.data), { raw: {
|
|
2343
|
+
width: aligned.width,
|
|
2344
|
+
height: aligned.height,
|
|
2345
|
+
channels: aligned.channels
|
|
2346
|
+
} }).jpeg({ quality }).toBuffer(),
|
|
2347
|
+
width: aligned.width,
|
|
2348
|
+
height: aligned.height
|
|
2349
|
+
};
|
|
2350
|
+
}
|
|
2351
|
+
/**
|
|
2352
|
+
* Produce a landmark-aligned face crop, preferring a NATIVE-resolution crop
|
|
2353
|
+
* (design B — the quality win) and FALLING BACK to today's downscaled
|
|
2354
|
+
* full-frame alignment on any native miss/error (never worse than before).
|
|
2355
|
+
*
|
|
2356
|
+
* The native path requests the padded face region from `nativeCropProvider`
|
|
2357
|
+
* (a best-effort local cap round-trip bound to this frame), warps the native
|
|
2358
|
+
* pixels; the fallback path re-uses {@link alignFaceCrop} on the downscaled
|
|
2359
|
+
* JPEG. ArcFace input is a fixed `outSize`×`outSize` either way — only the crop
|
|
2360
|
+
* SOURCE changes, so model cost is unchanged.
|
|
2361
|
+
*/
|
|
2362
|
+
async function buildAlignedFaceCrop(args) {
|
|
2363
|
+
if (args.nativeCropProvider) try {
|
|
2364
|
+
const region = paddedFaceRegion(args.faceBbox, args.imageWidth, args.imageHeight);
|
|
2365
|
+
const roi = {
|
|
2366
|
+
x: region.left / args.imageWidth,
|
|
2367
|
+
y: region.top / args.imageHeight,
|
|
2368
|
+
w: (region.right - region.left) / args.imageWidth,
|
|
2369
|
+
h: (region.bottom - region.top) / args.imageHeight
|
|
2370
|
+
};
|
|
2371
|
+
const native = await args.nativeCropProvider(roi, args.nativeMaxWidth);
|
|
2372
|
+
if (native && native.width >= 2 && native.height >= 2 && native.bytes.length >= native.width * native.height * 3) return {
|
|
2373
|
+
...await alignFaceCropFromRgb(native, region, args.landmarksImageSpace, { outSize: args.outSize }),
|
|
2374
|
+
source: "native",
|
|
2375
|
+
nativeFaceShortSidePx: nativeFaceShortSide(args.faceBbox, region, native)
|
|
2376
|
+
};
|
|
2377
|
+
} catch {}
|
|
2378
|
+
return {
|
|
2379
|
+
...await alignFaceCrop(args.fullFrameJpeg, args.faceBbox, args.landmarksImageSpace, args.imageWidth, args.imageHeight, { outSize: args.outSize }),
|
|
2380
|
+
source: "fallback"
|
|
2381
|
+
};
|
|
2382
|
+
}
|
|
2383
|
+
/**
|
|
2384
|
+
* Short side (px) of `faceBbox` (in detection space) re-measured in the NATIVE
|
|
2385
|
+
* crop's resolution. The native crop covers `region` (detection-space padded
|
|
2386
|
+
* region) rendered at `native.width × native.height` native pixels, so the
|
|
2387
|
+
* per-axis scale `native / region` maps the detection face size to its native
|
|
2388
|
+
* size. This is the size an embedder actually sees, so the gate uses it.
|
|
2389
|
+
*/
|
|
2390
|
+
function nativeFaceShortSide(faceBbox, region, native) {
|
|
2391
|
+
const regionW = Math.max(1, region.right - region.left);
|
|
2392
|
+
const regionH = Math.max(1, region.bottom - region.top);
|
|
2393
|
+
const scaleX = native.width / regionW;
|
|
2394
|
+
const scaleY = native.height / regionH;
|
|
2395
|
+
const faceW = (faceBbox[2] - faceBbox[0]) * scaleX;
|
|
2396
|
+
const faceH = (faceBbox[3] - faceBbox[1]) * scaleY;
|
|
2397
|
+
return Math.min(faceW, faceH);
|
|
2398
|
+
}
|
|
2399
|
+
/**
|
|
3726
2400
|
* Produce an aligned 112x112 JPEG of a face from the full-frame JPEG and the
|
|
3727
2401
|
* face's 5 landmarks (in absolute image-space coordinates). Decodes a padded
|
|
3728
2402
|
* region around the face bbox to raw RGB, warps to the ArcFace template, and
|
|
@@ -3950,7 +2624,8 @@ function buildFrameResult(input) {
|
|
|
3950
2624
|
...embedding !== void 0 ? {
|
|
3951
2625
|
embedding,
|
|
3952
2626
|
...embeddingModelId !== void 0 ? { embeddingModelId } : {}
|
|
3953
|
-
} : {}
|
|
2627
|
+
} : {},
|
|
2628
|
+
...m.faceAlignedCrop !== void 0 ? { faceAlignedCrop: m.faceAlignedCrop } : {}
|
|
3954
2629
|
};
|
|
3955
2630
|
if (input.debug) {
|
|
3956
2631
|
const cleanDebug = pruneUndefined({
|
|
@@ -4031,7 +2706,8 @@ function toMutableRootDetection(det, rootStep, idGen, rootStepLatencyMs) {
|
|
|
4031
2706
|
mask: det.mask,
|
|
4032
2707
|
maskWidth: det.maskWidth,
|
|
4033
2708
|
maskHeight: det.maskHeight
|
|
4034
|
-
} : {}
|
|
2709
|
+
} : {},
|
|
2710
|
+
...det.landmarks !== void 0 ? { landmarks: det.landmarks } : {}
|
|
4035
2711
|
};
|
|
4036
2712
|
}
|
|
4037
2713
|
//#endregion
|
|
@@ -4149,6 +2825,33 @@ function formatTopResult(output) {
|
|
|
4149
2825
|
* resolution — a deeper change tracked separately.
|
|
4150
2826
|
*/
|
|
4151
2827
|
var DEFAULT_MIN_FACE_SIZE_PX = 28;
|
|
2828
|
+
/**
|
|
2829
|
+
* Cheap pre-native floor (px, detection space): below this a face is treated as
|
|
2830
|
+
* genuinely degenerate — SCRFD landmarks are unreliable and even a large native
|
|
2831
|
+
* upscale can't rescue it — so it is skipped WITHOUT paying a native-crop
|
|
2832
|
+
* round-trip. Above the floor, the real {@link DEFAULT_MIN_FACE_SIZE_PX} gate is
|
|
2833
|
+
* evaluated on the NATIVE face size (see the face branch of `executeChildren`).
|
|
2834
|
+
*/
|
|
2835
|
+
var MIN_FACE_DETECTION_FLOOR_PX = 6;
|
|
2836
|
+
/**
|
|
2837
|
+
* Cap (px) on the width of the NATIVE face crop fetched for embedding (design
|
|
2838
|
+
* B). The arcface input is a fixed 112² warp, so a wider native crop buys no
|
|
2839
|
+
* embedding quality past a modest margin but does inflate the per-face transport
|
|
2840
|
+
* of the best-effort native-crop round-trip. 320px keeps a distant face well
|
|
2841
|
+
* above the downscaled detection resolution while bounding the crop payload.
|
|
2842
|
+
*/
|
|
2843
|
+
var NATIVE_FACE_CROP_MAX_WIDTH = 320;
|
|
2844
|
+
/**
|
|
2845
|
+
* StepOutput kinds that synthesize a full-frame detection when they run at
|
|
2846
|
+
* the tree ROOT (see `synthesizeRootDetection`) — classifier/embedding steps
|
|
2847
|
+
* promoted to root by `pipelineRunner.runDetailSubtree` (task 6b), e.g.
|
|
2848
|
+
* `clip-embedding`, `animal-classifier`. Detector (`'detections'`) roots take
|
|
2849
|
+
* the normal path; `'text'`/`'mask'` roots are out of scope and still
|
|
2850
|
+
* `continue` with no output, matching pre-existing behaviour.
|
|
2851
|
+
*/
|
|
2852
|
+
function isEnrichmentOutput(output) {
|
|
2853
|
+
return output.kind === "classifications" || output.kind === "embedding";
|
|
2854
|
+
}
|
|
4152
2855
|
var PipelineExecutor = class {
|
|
4153
2856
|
opts;
|
|
4154
2857
|
constructor(opts) {
|
|
@@ -4166,6 +2869,23 @@ var PipelineExecutor = class {
|
|
|
4166
2869
|
logger.warn(message, { meta });
|
|
4167
2870
|
}
|
|
4168
2871
|
/**
|
|
2872
|
+
* Surface WHY a face embedding was skipped — a detected face simply too small
|
|
2873
|
+
* (distance / night) is the common silent cause of "faces stopped collecting".
|
|
2874
|
+
* Reports the detection-space short side AND, when the skip was decided on the
|
|
2875
|
+
* native crop, the NATIVE face size so an operator sees the size that actually
|
|
2876
|
+
* gated. Throttled so it isn't per-frame spam.
|
|
2877
|
+
*/
|
|
2878
|
+
warnFaceTooSmall(child, detShortSidePx, minFaceSizePx, nativeFaceShortSidePx) {
|
|
2879
|
+
this.throttledWarn(`face-small:${child.stepId}`, 3e4, "face detected but too small to embed — skipping", {
|
|
2880
|
+
step: child.stepId,
|
|
2881
|
+
model: child.modelId,
|
|
2882
|
+
faceShortSidePx: Math.round(detShortSidePx),
|
|
2883
|
+
minFaceSizePx,
|
|
2884
|
+
gatedOn: nativeFaceShortSidePx === void 0 ? "detection" : "native",
|
|
2885
|
+
...nativeFaceShortSidePx === void 0 ? {} : { nativeFaceShortSidePx: Math.round(nativeFaceShortSidePx) }
|
|
2886
|
+
});
|
|
2887
|
+
}
|
|
2888
|
+
/**
|
|
4169
2889
|
* Execute the full pipeline tree against a frame.
|
|
4170
2890
|
*
|
|
4171
2891
|
* `rootInput` carries the frame in its source representation
|
|
@@ -4178,7 +2898,7 @@ var PipelineExecutor = class {
|
|
|
4178
2898
|
*
|
|
4179
2899
|
* @returns FrameResult + optional trace
|
|
4180
2900
|
*/
|
|
4181
|
-
async run(tree, rootInput, fullFrameJpegProvider, imageWidth, imageHeight, deviceId, runOpts) {
|
|
2901
|
+
async run(tree, rootInput, fullFrameJpegProvider, imageWidth, imageHeight, deviceId, runOpts, nativeFaceCropProvider) {
|
|
4182
2902
|
const startMs = Date.now();
|
|
4183
2903
|
const verbosity = runOpts?.traceVerbosity ?? "off";
|
|
4184
2904
|
const traceBuilder = new ExecutionTraceBuilder(verbosity, deviceId, imageWidth, imageHeight, this.opts.engineRuntime);
|
|
@@ -4201,7 +2921,27 @@ var PipelineExecutor = class {
|
|
|
4201
2921
|
const rootStart = Date.now();
|
|
4202
2922
|
const rootOutput = await this.executeStep(rootStep, rootInput, imageWidth, imageHeight, "full-frame", void 0, void 0, traceBuilder, stepTimings, poolAgg);
|
|
4203
2923
|
const rootMs = Date.now() - rootStart;
|
|
4204
|
-
if (rootOutput.kind !== "detections")
|
|
2924
|
+
if (rootOutput.kind !== "detections") {
|
|
2925
|
+
if (isEnrichmentOutput(rootOutput)) {
|
|
2926
|
+
const mutable = this.synthesizeRootDetection(rootOutput, rootStep, idGen, rootMs, imageWidth, imageHeight);
|
|
2927
|
+
applyChildOutput(mutable, rootStep, rootOutput, rootMs, ctx);
|
|
2928
|
+
try {
|
|
2929
|
+
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, nativeFaceCropProvider);
|
|
2930
|
+
} catch (err) {
|
|
2931
|
+
this.opts.logger?.warn("Pipeline child execution failed — keeping parent detection", {
|
|
2932
|
+
tags: { deviceId },
|
|
2933
|
+
meta: {
|
|
2934
|
+
rootStepId: rootStep.stepId,
|
|
2935
|
+
parentClass: mutable.macroClass,
|
|
2936
|
+
parentScore: mutable.score,
|
|
2937
|
+
error: require_dist.errMsg(err)
|
|
2938
|
+
}
|
|
2939
|
+
});
|
|
2940
|
+
}
|
|
2941
|
+
firstLevel.push(mutable);
|
|
2942
|
+
}
|
|
2943
|
+
continue;
|
|
2944
|
+
}
|
|
4205
2945
|
for (const det of rootOutput.detections) {
|
|
4206
2946
|
const mutable = toMutableRootDetection(det, rootStep, idGen, rootMs);
|
|
4207
2947
|
if (rootStep.definition.classMap) {
|
|
@@ -4216,7 +2956,7 @@ var PipelineExecutor = class {
|
|
|
4216
2956
|
continue;
|
|
4217
2957
|
}
|
|
4218
2958
|
try {
|
|
4219
|
-
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg);
|
|
2959
|
+
await this.executeChildren(rootStep.children, mutable, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, runOpts?.plane, nativeFaceCropProvider);
|
|
4220
2960
|
} catch (err) {
|
|
4221
2961
|
this.opts.logger?.warn("Pipeline child execution failed — keeping parent detection", {
|
|
4222
2962
|
tags: { deviceId },
|
|
@@ -4252,6 +2992,29 @@ var PipelineExecutor = class {
|
|
|
4252
2992
|
trace: traceBuilder.build(firstLevel.length + details.length)
|
|
4253
2993
|
};
|
|
4254
2994
|
}
|
|
2995
|
+
/**
|
|
2996
|
+
* Build a full-frame `MutableObjectDetection` for a ROOT step whose engine
|
|
2997
|
+
* output is a classification/embedding rather than detections — there is
|
|
2998
|
+
* no detector to bound a smaller box, so the synthesized detection covers
|
|
2999
|
+
* the entire input frame (`bbox = [0, 0, imageWidth, imageHeight]`).
|
|
3000
|
+
* `macroClass` is the step's own output semantic (`outputClasses[0]`,
|
|
3001
|
+
* falling back to `inputClasses[0]` when `outputClasses` is empty, then
|
|
3002
|
+
* the step id as a last resort so the field is never empty). `score` is
|
|
3003
|
+
* the output's own confidence when it has one (the classifier's top-1
|
|
3004
|
+
* score) — an embedding carries no confidence, so it defaults to 1.
|
|
3005
|
+
*/
|
|
3006
|
+
synthesizeRootDetection(output, rootStep, idGen, rootStepLatencyMs, imageWidth, imageHeight) {
|
|
3007
|
+
return toMutableRootDetection({
|
|
3008
|
+
class: rootStep.definition.outputClasses[0] ?? rootStep.definition.inputClasses?.[0] ?? rootStep.stepId,
|
|
3009
|
+
score: output.kind === "classifications" ? output.classifications[0]?.score ?? 1 : 1,
|
|
3010
|
+
bbox: [
|
|
3011
|
+
0,
|
|
3012
|
+
0,
|
|
3013
|
+
imageWidth,
|
|
3014
|
+
imageHeight
|
|
3015
|
+
]
|
|
3016
|
+
}, rootStep, idGen, rootStepLatencyMs);
|
|
3017
|
+
}
|
|
4255
3018
|
async executeStep(step, input, inputWidth, inputHeight, inputType, _parentBbox, parentClass, traceBuilder, stepTimings, poolAgg) {
|
|
4256
3019
|
const preprocessStart = Date.now();
|
|
4257
3020
|
const preprocessMs = Date.now() - preprocessStart;
|
|
@@ -4318,8 +3081,9 @@ var PipelineExecutor = class {
|
|
|
4318
3081
|
});
|
|
4319
3082
|
return output;
|
|
4320
3083
|
}
|
|
4321
|
-
async executeChildren(children, parentDetection, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg) {
|
|
3084
|
+
async executeChildren(children, parentDetection, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, plane, nativeFaceCropProvider) {
|
|
4322
3085
|
for (const child of children) {
|
|
3086
|
+
if (plane === "frame" && child.definition.inputClasses !== null) continue;
|
|
4323
3087
|
if (!this.matchesInputClasses(parentDetection.macroClass, child.inputClasses)) continue;
|
|
4324
3088
|
const minParentScore = child.settings?.minParentScore ?? child.definition?.defaultMinParentScore;
|
|
4325
3089
|
if (typeof minParentScore === "number" && parentDetection.score < minParentScore) continue;
|
|
@@ -4333,23 +3097,43 @@ var PipelineExecutor = class {
|
|
|
4333
3097
|
let cropH;
|
|
4334
3098
|
if (modelEntry?.faceAlignment) {
|
|
4335
3099
|
const minFaceSize = typeof child.settings?.["minFaceSize"] === "number" ? child.settings["minFaceSize"] : DEFAULT_MIN_FACE_SIZE_PX;
|
|
4336
|
-
const
|
|
4337
|
-
if (
|
|
4338
|
-
this.
|
|
4339
|
-
step: child.stepId,
|
|
4340
|
-
model: child.modelId,
|
|
4341
|
-
faceShortSidePx: Math.round(faceShortSide),
|
|
4342
|
-
minFaceSizePx: minFaceSize
|
|
4343
|
-
});
|
|
3100
|
+
const detShortSide = bboxShortSide(parentDetection.bbox);
|
|
3101
|
+
if (detShortSide < MIN_FACE_DETECTION_FLOOR_PX) {
|
|
3102
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0);
|
|
4344
3103
|
continue;
|
|
4345
3104
|
}
|
|
4346
3105
|
const lms = parentDetection.landmarks;
|
|
4347
3106
|
if (lms && lms.length >= 5) {
|
|
4348
|
-
|
|
3107
|
+
if (!nativeFaceCropProvider && detShortSide < minFaceSize) {
|
|
3108
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0);
|
|
3109
|
+
continue;
|
|
3110
|
+
}
|
|
3111
|
+
const aligned = await buildAlignedFaceCrop({
|
|
3112
|
+
fullFrameJpeg,
|
|
3113
|
+
faceBbox: parentDetection.bbox,
|
|
3114
|
+
landmarksImageSpace: lms,
|
|
3115
|
+
imageWidth,
|
|
3116
|
+
imageHeight,
|
|
3117
|
+
outSize: modelEntry.inputSize.width,
|
|
3118
|
+
...nativeFaceCropProvider ? {
|
|
3119
|
+
nativeCropProvider: nativeFaceCropProvider,
|
|
3120
|
+
nativeMaxWidth: NATIVE_FACE_CROP_MAX_WIDTH
|
|
3121
|
+
} : {}
|
|
3122
|
+
});
|
|
3123
|
+
const gateShortSide = aligned.nativeFaceShortSidePx ?? detShortSide;
|
|
3124
|
+
if (gateShortSide < minFaceSize) {
|
|
3125
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, aligned.source === "native" ? gateShortSide : void 0);
|
|
3126
|
+
continue;
|
|
3127
|
+
}
|
|
4349
3128
|
cropJpegBuf = aligned.jpeg;
|
|
4350
3129
|
cropW = aligned.width;
|
|
4351
3130
|
cropH = aligned.height;
|
|
3131
|
+
parentDetection.faceAlignedCrop = cropJpegBuf.toString("base64");
|
|
4352
3132
|
} else {
|
|
3133
|
+
if (detShortSide < minFaceSize) {
|
|
3134
|
+
this.warnFaceTooSmall(child, detShortSide, minFaceSize, void 0);
|
|
3135
|
+
continue;
|
|
3136
|
+
}
|
|
4353
3137
|
const crop = await cropJpeg(fullFrameJpeg, parentDetection.bbox, imageWidth, imageHeight);
|
|
4354
3138
|
cropJpegBuf = crop.jpeg;
|
|
4355
3139
|
cropW = crop.width;
|
|
@@ -4379,7 +3163,7 @@ var PipelineExecutor = class {
|
|
|
4379
3163
|
y: l.y + py1
|
|
4380
3164
|
}));
|
|
4381
3165
|
}
|
|
4382
|
-
await this.executeChildren(child.children, detail, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg);
|
|
3166
|
+
await this.executeChildren(child.children, detail, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg, plane, nativeFaceCropProvider);
|
|
4383
3167
|
}
|
|
4384
3168
|
}
|
|
4385
3169
|
} catch (err) {
|
|
@@ -4432,7 +3216,7 @@ function buildExecutableTree(steps, getEngine) {
|
|
|
4432
3216
|
return { roots: steps.filter((s) => s.enabled).filter((s) => s.slot !== "audio-classifier").map((s) => buildNode(s, getEngine)) };
|
|
4433
3217
|
}
|
|
4434
3218
|
function buildNode(step, getEngine) {
|
|
4435
|
-
const definition = getStepDefinition(step.addonId);
|
|
3219
|
+
const definition = require_step_definitions.getStepDefinition(step.addonId);
|
|
4436
3220
|
const engine = getEngine(step.addonId);
|
|
4437
3221
|
const children = (step.children ?? []).filter((c) => c.enabled).map((c) => buildNode(c, getEngine));
|
|
4438
3222
|
const mergedSettings = {
|
|
@@ -4457,7 +3241,7 @@ function buildNode(step, getEngine) {
|
|
|
4457
3241
|
* entered recursively. Fields without a declared default are skipped.
|
|
4458
3242
|
*/
|
|
4459
3243
|
function collectSchemaDefaults(stepId) {
|
|
4460
|
-
const schema = getStep(stepId).getConfigSchema();
|
|
3244
|
+
const schema = require_step_definitions.getStep(stepId).getConfigSchema();
|
|
4461
3245
|
const out = {};
|
|
4462
3246
|
walkFieldsForDefaults(schema, out);
|
|
4463
3247
|
return out;
|
|
@@ -4522,7 +3306,7 @@ function collectSubstitutions(steps, format) {
|
|
|
4522
3306
|
for (const step of steps) {
|
|
4523
3307
|
const chosen = step.modelId;
|
|
4524
3308
|
if (chosen != null) {
|
|
4525
|
-
const running = resolveModelForFormat(step.addonId, chosen, format);
|
|
3309
|
+
const running = require_step_definitions.resolveModelForFormat(step.addonId, chosen, format);
|
|
4526
3310
|
if (running !== chosen) result.push({
|
|
4527
3311
|
addonId: step.addonId,
|
|
4528
3312
|
chosen,
|
|
@@ -4548,7 +3332,7 @@ function collectSubstitutions(steps, format) {
|
|
|
4548
3332
|
* black-box test. Unknown/custom addonIds (no registered `StepDefinition`)
|
|
4549
3333
|
* are skipped, never thrown.
|
|
4550
3334
|
*/
|
|
4551
|
-
function collectZeroBuildIssues(steps, format, getStepDef = getStepDefinition) {
|
|
3335
|
+
function collectZeroBuildIssues(steps, format, getStepDef = require_step_definitions.getStepDefinition) {
|
|
4552
3336
|
const result = [];
|
|
4553
3337
|
for (const step of steps) {
|
|
4554
3338
|
let def;
|
|
@@ -4574,7 +3358,7 @@ function collectZeroBuildIssues(steps, format, getStepDef = getStepDefinition) {
|
|
|
4574
3358
|
* tests can exercise the unknown-addon branch with a fabricated resolver
|
|
4575
3359
|
* without `vi.mock`.
|
|
4576
3360
|
*/
|
|
4577
|
-
function collectUnknownAddonIssues(steps, getStepDef = getStepDefinition) {
|
|
3361
|
+
function collectUnknownAddonIssues(steps, getStepDef = require_step_definitions.getStepDefinition) {
|
|
4578
3362
|
const result = [];
|
|
4579
3363
|
for (const step of steps) {
|
|
4580
3364
|
try {
|
|
@@ -4614,13 +3398,13 @@ function resolveInputSteps(steps, format, engine) {
|
|
|
4614
3398
|
for (const s of steps) {
|
|
4615
3399
|
let def;
|
|
4616
3400
|
try {
|
|
4617
|
-
def = getStepDefinition(s.addonId);
|
|
3401
|
+
def = require_step_definitions.getStepDefinition(s.addonId);
|
|
4618
3402
|
} catch {
|
|
4619
3403
|
unknownAddonIds.push(s.addonId);
|
|
4620
3404
|
continue;
|
|
4621
3405
|
}
|
|
4622
3406
|
const chosenModelId = s.modelId ?? null;
|
|
4623
|
-
const runningModelId = chosenModelId === null && engine !== void 0 && s.addonId === "object-detection" ? resolveDefaultDetectionModel(engine.backend, engine.device, format) : resolveModelForFormat(s.addonId, chosenModelId, format);
|
|
3407
|
+
const runningModelId = chosenModelId === null && engine !== void 0 && s.addonId === "object-detection" ? resolveDefaultDetectionModel(engine.backend, engine.device, format) : require_step_definitions.resolveModelForFormat(s.addonId, chosenModelId, format);
|
|
4624
3408
|
if (chosenModelId !== null && runningModelId !== chosenModelId) substitutions.push({
|
|
4625
3409
|
addonId: s.addonId,
|
|
4626
3410
|
chosen: chosenModelId,
|
|
@@ -5423,7 +4207,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
5423
4207
|
* first, then the custom registry. Returns undefined if neither has it.
|
|
5424
4208
|
*/
|
|
5425
4209
|
async resolveModelEntry(addonId, modelId) {
|
|
5426
|
-
const fromCatalog = getStepDefinition(addonId).models.find((m) => m.id === modelId);
|
|
4210
|
+
const fromCatalog = require_step_definitions.getStepDefinition(addonId).models.find((m) => m.id === modelId);
|
|
5427
4211
|
if (fromCatalog) return fromCatalog;
|
|
5428
4212
|
return (await this.getCustomModels()).get(addonId)?.find((m) => m.id === modelId);
|
|
5429
4213
|
}
|
|
@@ -5519,7 +4303,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
5519
4303
|
/** Pure recursive resolver — builds the resolved step tree without touching `modelSubstitutions`. */
|
|
5520
4304
|
resolveStepModelTree(steps, format) {
|
|
5521
4305
|
return steps.map((step) => {
|
|
5522
|
-
const resolved = resolveModelForFormat(step.addonId, step.modelId ?? null, format);
|
|
4306
|
+
const resolved = require_step_definitions.resolveModelForFormat(step.addonId, step.modelId ?? null, format);
|
|
5523
4307
|
const children = step.children?.length ? this.resolveStepModelTree([...step.children], format) : step.children;
|
|
5524
4308
|
return resolved === step.modelId && children === step.children ? step : {
|
|
5525
4309
|
...step,
|
|
@@ -5667,7 +4451,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
5667
4451
|
for (const step of nodes) {
|
|
5668
4452
|
if (!step.enabled) continue;
|
|
5669
4453
|
try {
|
|
5670
|
-
if (getStepDefinition(step.addonId).slot === "audio-classifier") continue;
|
|
4454
|
+
if (require_step_definitions.getStepDefinition(step.addonId).slot === "audio-classifier") continue;
|
|
5671
4455
|
} catch {
|
|
5672
4456
|
continue;
|
|
5673
4457
|
}
|
|
@@ -5687,7 +4471,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
5687
4471
|
async getCapabilities(_forceRefresh) {
|
|
5688
4472
|
const agentId = (this.addonCtx?.kernel?.cluster?.broker)?.nodeID ?? node_os.hostname();
|
|
5689
4473
|
const agentName = agentId;
|
|
5690
|
-
const addons = ALL_PIPELINE_STEPS.map((s) => ({
|
|
4474
|
+
const addons = require_step_definitions.ALL_PIPELINE_STEPS.map((s) => ({
|
|
5691
4475
|
id: s.definition.id,
|
|
5692
4476
|
name: s.definition.name,
|
|
5693
4477
|
models: s.definition.models.filter((m) => m.legacy !== true).map((m) => {
|
|
@@ -5871,6 +4655,38 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
5871
4655
|
debug: { totalInferenceMs: 0 }
|
|
5872
4656
|
};
|
|
5873
4657
|
}
|
|
4658
|
+
/**
|
|
4659
|
+
* Build the design-B native-face-crop provider for a runtime frame. Present
|
|
4660
|
+
* ONLY when the frame arrived as a retention `frameHandle` (the key the owning
|
|
4661
|
+
* pipeline-runner registered the frame's native surface under) and the sibling
|
|
4662
|
+
* `pipeline-runner` cap is reachable via `ctx.api`. Each call is a best-effort
|
|
4663
|
+
* round-trip pinned to the frame's OWNING node (`nodePin(handle.nodeId)` — the
|
|
4664
|
+
* node that decoded it, i.e. THIS node for a local frame, never a cross-node
|
|
4665
|
+
* hop) that returns the native ROI or `null` on a miss; the executor then
|
|
4666
|
+
* falls back to the downscaled crop, so behaviour is never worse than before.
|
|
4667
|
+
*/
|
|
4668
|
+
buildNativeFaceCropProvider(handle) {
|
|
4669
|
+
if (!handle) return void 0;
|
|
4670
|
+
const api = this.addonCtx?.api;
|
|
4671
|
+
if (!api) return void 0;
|
|
4672
|
+
return async (roi, maxWidth) => {
|
|
4673
|
+
try {
|
|
4674
|
+
const native = await api.pipelineRunner.getNativeCrop.query({
|
|
4675
|
+
handle,
|
|
4676
|
+
bbox: roi,
|
|
4677
|
+
...maxWidth !== void 0 ? { maxWidth } : {}
|
|
4678
|
+
}, require_dist.nodePin(handle.nodeId));
|
|
4679
|
+
if (!native || native.width <= 0 || native.height <= 0) return null;
|
|
4680
|
+
return {
|
|
4681
|
+
bytes: native.bytes,
|
|
4682
|
+
width: native.width,
|
|
4683
|
+
height: native.height
|
|
4684
|
+
};
|
|
4685
|
+
} catch {
|
|
4686
|
+
return null;
|
|
4687
|
+
}
|
|
4688
|
+
};
|
|
4689
|
+
}
|
|
5874
4690
|
async runPipeline(input, onProgress) {
|
|
5875
4691
|
const nodeId = this.addonCtx?.kernel?.localNodeId ?? "hub";
|
|
5876
4692
|
const sessionId = input.sessionId ?? `run-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
@@ -6127,7 +4943,11 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
6127
4943
|
const effectiveDeviceId = input.deviceId ?? 0;
|
|
6128
4944
|
const deviceOverrides = effectiveDeviceId > 0 ? await this.readDeviceStore(effectiveDeviceId) : {};
|
|
6129
4945
|
const effectiveTree = Object.keys(deviceOverrides).length > 0 ? applyDeviceOverridesToTree(tree, "object-detection", deviceOverrides) : tree;
|
|
6130
|
-
const
|
|
4946
|
+
const nativeFaceCropProvider = this.buildNativeFaceCropProvider(input.frameHandle);
|
|
4947
|
+
const { result, trace } = await executor.run(effectiveTree, rootInput, jpegProvider, imageWidth, imageHeight, effectiveDeviceId, {
|
|
4948
|
+
traceVerbosity: isRuntime ? this.eventBus ? "summary" : "off" : "full",
|
|
4949
|
+
plane: input.plane
|
|
4950
|
+
}, nativeFaceCropProvider);
|
|
6131
4951
|
if (isRuntime) {
|
|
6132
4952
|
if (trace && this.eventBus) this.eventBus.emit(require_dist.createEvent(require_dist.EventCategory.PipelineTrace, {
|
|
6133
4953
|
type: "device",
|
|
@@ -7185,7 +6005,7 @@ var DetectionPipelineProvider = class DetectionPipelineProvider {
|
|
|
7185
6005
|
};
|
|
7186
6006
|
function buildSchemaSlots(format, modelsDir, customByStep) {
|
|
7187
6007
|
const slotMap = /* @__PURE__ */ new Map();
|
|
7188
|
-
for (const pipelineStep of ALL_PIPELINE_STEPS) {
|
|
6008
|
+
for (const pipelineStep of require_step_definitions.ALL_PIPELINE_STEPS) {
|
|
7189
6009
|
const step = pipelineStep.definition;
|
|
7190
6010
|
const availableModels = mergeCustomModels(step.models, customByStep?.get(step.id) ?? []).filter((m) => m.formats[format] && m.legacy !== true);
|
|
7191
6011
|
if (availableModels.length === 0) continue;
|
|
@@ -7272,7 +6092,7 @@ function resolveChildSlots(slot) {
|
|
|
7272
6092
|
*/
|
|
7273
6093
|
function buildDefaultStepTree(format, objectDetectionModelId) {
|
|
7274
6094
|
const makeStep = (stepId, children, opts) => {
|
|
7275
|
-
const def = getStepDefinition(stepId);
|
|
6095
|
+
const def = require_step_definitions.getStepDefinition(stepId);
|
|
7276
6096
|
if (!def.models.some((m) => m.formats[format])) return null;
|
|
7277
6097
|
return {
|
|
7278
6098
|
addonId: def.id,
|
|
@@ -7281,7 +6101,7 @@ function buildDefaultStepTree(format, objectDetectionModelId) {
|
|
|
7281
6101
|
inputClasses: def.inputClasses ?? [],
|
|
7282
6102
|
outputClasses: def.outputClasses,
|
|
7283
6103
|
enabled: opts?.enabled ?? true,
|
|
7284
|
-
modelId: opts?.modelId ?? getDefaultModelForFormat(stepId, format),
|
|
6104
|
+
modelId: opts?.modelId ?? require_step_definitions.getDefaultModelForFormat(stepId, format),
|
|
7285
6105
|
children,
|
|
7286
6106
|
...def.group ? { group: def.group } : {}
|
|
7287
6107
|
};
|
|
@@ -8028,7 +6848,7 @@ var DetectionPipelineAddon = class DetectionPipelineAddon extends require_dist.B
|
|
|
8028
6848
|
}).catch(() => {});
|
|
8029
6849
|
}
|
|
8030
6850
|
getModelCatalog() {
|
|
8031
|
-
return ALL_STEPS.flatMap((s) => s.models.filter((m) => m.legacy !== true));
|
|
6851
|
+
return require_step_definitions.ALL_STEPS.flatMap((s) => s.models.filter((m) => m.legacy !== true));
|
|
8032
6852
|
}
|
|
8033
6853
|
/**
|
|
8034
6854
|
* Proactively install the OpenVINO Python package when Intel hardware
|
|
@@ -8136,10 +6956,10 @@ var DetectionPipelineAddon = class DetectionPipelineAddon extends require_dist.B
|
|
|
8136
6956
|
}
|
|
8137
6957
|
};
|
|
8138
6958
|
//#endregion
|
|
8139
|
-
exports.ALL_STEPS = ALL_STEPS;
|
|
6959
|
+
exports.ALL_STEPS = require_step_definitions.ALL_STEPS;
|
|
8140
6960
|
exports.DetectionPipelineProvider = DetectionPipelineProvider;
|
|
8141
6961
|
exports.backendToFormat = backendToFormat;
|
|
8142
6962
|
exports.default = DetectionPipelineAddon;
|
|
8143
|
-
exports.getDefaultModelForFormat = getDefaultModelForFormat;
|
|
8144
|
-
exports.getStepDefinition = getStepDefinition;
|
|
6963
|
+
exports.getDefaultModelForFormat = require_step_definitions.getDefaultModelForFormat;
|
|
6964
|
+
exports.getStepDefinition = require_step_definitions.getStepDefinition;
|
|
8145
6965
|
exports.shouldInstallOpenvino = shouldInstallOpenvino;
|