@camstack/addon-pipeline 1.2.328 → 1.2.330

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/THIRD_PARTY_MODELS.md +2 -2
  2. package/dist/audio-analyzer/index.js +2 -2
  3. package/dist/audio-analyzer/index.mjs +2 -2
  4. package/dist/{default-detection-model-1SadEKsW.js → default-detection-model-B6gKGnfx.js} +53 -71
  5. package/dist/{default-detection-model-CMeVTcPZ.mjs → default-detection-model-CPDT_eFT.mjs} +53 -71
  6. package/dist/detection-pipeline/index.js +607 -39
  7. package/dist/detection-pipeline/index.mjs +607 -39
  8. package/dist/{dist-wJO7mXeO.js → dist-CMeICL07.js} +781 -465
  9. package/dist/{dist-Bpub2VcJ.mjs → dist-CuPEyZY2.mjs} +736 -438
  10. package/dist/motion-wasm/index.js +1 -1
  11. package/dist/motion-wasm/index.mjs +1 -1
  12. package/dist/{node-BjCSgD4M.mjs → node-USq5jYwq.mjs} +1 -1
  13. package/dist/{node-BCrqaejt.js → node-X_0Tka7-.js} +1 -1
  14. package/dist/pipeline-runner/index.js +355 -104
  15. package/dist/pipeline-runner/index.mjs +355 -104
  16. package/dist/{process-memory-BaKQ8u2G.mjs → process-memory-07XYts8V.mjs} +1 -1
  17. package/dist/{process-memory-iUJuTpXs.js → process-memory-o4LFWbBN.js} +1 -1
  18. package/dist/recorder/index.js +7 -7
  19. package/dist/recorder/index.mjs +7 -7
  20. package/dist/{segment-demux-js-C5ez9LYG.mjs → segment-demux-js-Bq8DrH0b.mjs} +2 -2
  21. package/dist/{segment-demux-js-Opx6Hv9G.js → segment-demux-js-FqaQjG7n.js} +2 -2
  22. package/dist/stream-broker/_stub.js +2 -2
  23. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B94LgsV0.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-EYRUYv_r.mjs} +3 -3
  24. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BnP7C_HO.mjs +26 -0
  25. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CR0--kRv.mjs +26 -0
  26. package/dist/stream-broker/demux-worker-child.js +1 -1
  27. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  28. package/dist/stream-broker/{hostInit-xOx7AvgW.mjs → hostInit-iGdBpvGc.mjs} +3 -3
  29. package/dist/stream-broker/index.js +4 -4
  30. package/dist/stream-broker/index.mjs +4 -4
  31. package/dist/stream-broker/remoteEntry.js +1 -1
  32. package/package.json +1 -1
  33. package/python/edgetpu_dequant.py +38 -1
  34. package/python/inference_pool.py +31 -17
  35. package/python/postprocessors/test_yolox_plate_edgetpu.py +126 -0
  36. package/python/postprocessors/test_yunet_edgetpu.py +149 -0
  37. package/python/postprocessors/testdata/yolox_plate_int8_outputs.json +1 -0
  38. package/python/postprocessors/testdata/yunet_int8_outputs.json +1 -0
  39. package/python/postprocessors/yolo.py +44 -0
  40. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BPWYf4_O.mjs +0 -26
  41. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BpXPNINd.mjs +0 -26
@@ -134,7 +134,7 @@ entry kept resolvable for a saved selection but no longer offered.
134
134
 
135
135
  | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
136
136
  | --- | --- | --- | --- | --- | --- |
137
- | `yunet-2023mar` (default) | [OpenCV Zoo YuNet](https://github.com/opencv/opencv_zoo/tree/main/models/face_detection_yunet) | BSD-3-Clause (`BSD-3-Clause.txt`) / MIT (`MIT-yunet-reference.txt`) | WIDER FACE: research-oriented terms; images CC BY-NC-ND | input contract baked into the graph (the pool RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather); internal tensor names cleared in the OpenVINO IR; ONNX fp32, OpenVINO IR fp32, CoreML fp16 (scripts/build-yunet-model.py) | mirror `faceDetection/yunet` |
137
+ | `yunet-2023mar` (default) | [OpenCV Zoo YuNet](https://github.com/opencv/opencv_zoo/tree/main/models/face_detection_yunet) | BSD-3-Clause (`BSD-3-Clause.txt`) / MIT (`MIT-yunet-reference.txt`) | WIDER FACE: research-oriented terms; images CC BY-NC-ND | input contract baked into the graph (the pool RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather); internal tensor names cleared in the OpenVINO IR; ONNX fp32, OpenVINO IR fp32, CoreML fp16 (scripts/build-yunet-model.py); Edge TPU build: the bake folded into the first Conv, full-integer int8 post-training quantisation calibrated on CamStack person crops, compiled with edgetpu_compiler 14 (scripts/build-yunet-edgetpu.py) | mirror `faceDetection/yunet` |
138
138
 
139
139
  ### Face recognition
140
140
 
@@ -146,7 +146,7 @@ entry kept resolvable for a saved selection but no longer offered.
146
146
 
147
147
  | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
148
148
  | --- | --- | --- | --- | --- | --- |
149
- | `yolox-tiny-plate` (default) | [open-lpr models (faisalthaheem/open-lpr-models), YOLOX-tiny](https://huggingface.co/faisalthaheem/open-lpr-models) | Apache-2.0 / Apache-2.0 (`Apache-2.0.txt`) | Simanno annotated plate corpus plus community-contributed photographs, pseudo-labelled by a teacher model (not published; the upstream NOTICE says the photographs were uploaded without consent obtained): UNKNOWN | input contract baked into the graph (static 1x3x640x640 RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather) and the output reshaped to the YOLOv8 layout (cx, cy, w, h, obj*cls); ONNX fp32, OpenVINO IR fp16, CoreML fp16 (scripts/build-yolox-plate-model.py) | mirror `plateDetection/yolox-tiny-plate` |
149
+ | `yolox-tiny-plate` (default) | [open-lpr models (faisalthaheem/open-lpr-models), YOLOX-tiny](https://huggingface.co/faisalthaheem/open-lpr-models) | Apache-2.0 / Apache-2.0 (`Apache-2.0.txt`) | Simanno annotated plate corpus plus community-contributed photographs, pseudo-labelled by a teacher model (not published; the upstream NOTICE says the photographs were uploaded without consent obtained): UNKNOWN | input contract baked into the graph (static 1x3x640x640 RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather) and the output reshaped to the YOLOv8 layout (cx, cy, w, h, obj*cls); ONNX fp32, OpenVINO IR fp16, CoreML fp16 (scripts/build-yolox-plate-model.py); Edge TPU build: the Focus stem rewritten as the equivalent 6x6 stride-2 Conv with the input bake folded into it, the graph cut before the grid decode (raw per-stride head), full-integer int8 post-training quantisation calibrated on CamStack vehicle crops, compiled with edgetpu_compiler 14 (scripts/build-yolox-plate-edgetpu.py) | mirror `plateDetection/yolox-tiny-plate` |
150
150
 
151
151
  ### Licence plate reading
152
152
 
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../chunk-emK7D4bc.js");
6
- const require_dist = require("../dist-wJO7mXeO.js");
7
- const require_process_memory = require("../process-memory-iUJuTpXs.js");
6
+ const require_dist = require("../dist-CMeICL07.js");
7
+ const require_process_memory = require("../process-memory-o4LFWbBN.js");
8
8
  let node_fs = require("node:fs");
9
9
  node_fs = require_chunk.__toESM(node_fs);
10
10
  let node_path = require("node:path");
@@ -1,6 +1,6 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { An as hydrateSchema, F as PoolMemoryWatchdog, J as audioAnalysisCapability, Pn as nodePin, Sn as BaseAddon, Tn as audioChunkBytesPerSample, Y as audioAnalyzerCapability, Zn as EventCategory, bn as errMsg, en as resolvePoolMemoryPolicy, k as HF_BASE_URL, kn as expandAudioChunkToF32le, kt as mapAudioLabelToMacro, m as DEFAULT_AUDIO_ANALYZER_CONFIG, r as AUDIO_BACKEND_CHOICES } from "../dist-Bpub2VcJ.mjs";
3
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-BaKQ8u2G.mjs";
2
+ import { Cn as errMsg, D as HF_BASE_URL, J as audioAnalysisCapability, Ln as nodePin, Mn as expandAudioChunkToF32le, N as PoolMemoryWatchdog, Nn as hydrateSchema, On as audioChunkBytesPerSample, Tn as BaseAddon, Y as audioAnalyzerCapability, er as EventCategory, h as DEFAULT_AUDIO_ANALYZER_CONFIG, jt as mapAudioLabelToMacro, r as AUDIO_BACKEND_CHOICES, tn as resolvePoolMemoryPolicy } from "../dist-CuPEyZY2.mjs";
3
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-07XYts8V.mjs";
4
4
  import * as fs from "node:fs";
5
5
  import * as path$1 from "node:path";
6
6
  import { downloadFile } from "@camstack/system/addon-utils";
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-wJO7mXeO.js");
1
+ const require_dist = require("./dist-CMeICL07.js");
2
2
  const require_worker_protocol = require("./worker-protocol-C-G8qmye.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  //#region src/detection-pipeline/registry/effective-confidence.ts
@@ -90,7 +90,7 @@ var YUNET_MIT = {
90
90
  },
91
91
  url: "https://github.com/opencv/opencv_zoo/blob/main/models/face_detection_yunet/LICENSE",
92
92
  attribution: "YuNet weights Copyright (c) 2020 Shiqi Yu, MIT. Training code: ShiqiYu/libfacedetection.train, BSD-3-Clause.",
93
- modifications: "input contract baked into the graph (the pool RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather); internal tensor names cleared in the OpenVINO IR; ONNX fp32, OpenVINO IR fp32, CoreML fp16 (scripts/build-yunet-model.py)",
93
+ modifications: "input contract baked into the graph (the pool RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather); internal tensor names cleared in the OpenVINO IR; ONNX fp32, OpenVINO IR fp32, CoreML fp16 (scripts/build-yunet-model.py); Edge TPU build: the bake folded into the first Conv, full-integer int8 post-training quantisation calibrated on CamStack person crops, compiled with edgetpu_compiler 14 (scripts/build-yunet-edgetpu.py)",
94
94
  hosting: "camstack-hf"
95
95
  };
96
96
  var AURAFACE_APACHE = {
@@ -125,7 +125,7 @@ var OPEN_LPR_YOLOX_APACHE = {
125
125
  },
126
126
  url: "https://huggingface.co/faisalthaheem/open-lpr-models/blob/aed0df35ec2891c5a90437041ebeadb592cc516b/LICENSE",
127
127
  attribution: "open-lpr models, Copyright the open-lpr contributors, Apache-2.0 (https://huggingface.co/faisalthaheem/open-lpr-models, tag detector-2026.10.1). YOLOX architecture and COCO pretraining by Megvii (https://github.com/Megvii-BaseDetection/YOLOX), Apache-2.0. The upstream NOTICE is reproduced verbatim (`NOTICE-open-lpr.txt`).",
128
- modifications: "input contract baked into the graph (static 1x3x640x640 RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather) and the output reshaped to the YOLOv8 layout (cx, cy, w, h, obj*cls); ONNX fp32, OpenVINO IR fp16, CoreML fp16 (scripts/build-yolox-plate-model.py)",
128
+ modifications: "input contract baked into the graph (static 1x3x640x640 RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather) and the output reshaped to the YOLOv8 layout (cx, cy, w, h, obj*cls); ONNX fp32, OpenVINO IR fp16, CoreML fp16 (scripts/build-yolox-plate-model.py); Edge TPU build: the Focus stem rewritten as the equivalent 6x6 stride-2 Conv with the input bake folded into it, the graph cut before the grid decode (raw per-stride head), full-integer int8 post-training quantisation calibrated on CamStack vehicle crops, compiled with edgetpu_compiler 14 (scripts/build-yolox-plate-edgetpu.py)",
129
129
  hosting: "camstack-hf"
130
130
  };
131
131
  var FAST_PLATE_OCR_MIT = {
@@ -752,7 +752,12 @@ var FACE_DETECTION_MODELS = [{
752
752
  files: [...MLPACKAGE_FILES],
753
753
  runtimes: ["python"]
754
754
  },
755
- openvino: ovFormat(hf("faceDetection/yunet/openvino/camstack-yunet-2023mar.xml"), .36)
755
+ openvino: ovFormat(hf("faceDetection/yunet/openvino/camstack-yunet-2023mar.xml"), .36),
756
+ tflite: {
757
+ url: hf("faceDetection/yunet/tflite/camstack-yunet-2023mar_edgetpu.tflite"),
758
+ sizeMB: .7,
759
+ runtimes: ["python"]
760
+ }
756
761
  }
757
762
  }];
758
763
  var FACE_EMBEDDING_MODELS = [{
@@ -812,7 +817,12 @@ var PLATE_DETECTION_MODELS = [{
812
817
  files: [...MLPACKAGE_FILES],
813
818
  runtimes: ["python"]
814
819
  },
815
- openvino: ovFormat(hf("plateDetection/yolox-tiny-plate/openvino/camstack-yolox-tiny-plate.xml"), 10)
820
+ openvino: ovFormat(hf("plateDetection/yolox-tiny-plate/openvino/camstack-yolox-tiny-plate.xml"), 10),
821
+ tflite: {
822
+ url: hf("plateDetection/yolox-tiny-plate/tflite/camstack-yolox-tiny-plate_edgetpu.tflite"),
823
+ sizeMB: 6.9,
824
+ runtimes: ["python"]
825
+ }
816
826
  }
817
827
  }];
818
828
  var PACKAGE_DETECTION_MODELS = [{
@@ -1174,27 +1184,8 @@ var ANIMAL_10_LABELS = [
1174
1184
  "sheep",
1175
1185
  "spider"
1176
1186
  ];
1177
- var ANIMAL_CLASSIFIER_LABELS = require_dist.FILLABLE_STEP_VOCABULARIES["animal-classifier"];
1178
- var VEHICLE_CLASSIFIER_LABELS = require_dist.FILLABLE_STEP_VOCABULARIES["vehicle-classifier"];
1179
- /**
1180
- * The `labelLink` policy field (D715) — offered on every step a root detector
1181
- * can fill. Stored in the step's own settings (`DeviceStepConfig.settings` /
1182
- * `CameraStepOverridePatch.settings`), so it has ONE authority. It changes
1183
- * nothing unless the camera's root model declares it fills this step.
1184
- */
1185
- function labelLinkField(stepName) {
1186
- return {
1187
- type: "select",
1188
- key: require_dist.LABEL_LINK_SETTING_KEY,
1189
- label: "When the detector already fills this step",
1190
- description: `Only matters when the root detection model declares it fills ${stepName} (e.g. a Frigate+ model). "Skip" does not run ${stepName} for a subject the detector already named, and makes the detector's label the one answer — but only once every class the detector cannot produce is switched off in this step's class list. "Run" always runs ${stepName}; the detector's label is then a fallback any answer of the step outranks.`,
1191
- options: require_dist.LABEL_LINK_POLICIES.map((p) => ({
1192
- value: p,
1193
- label: p === "run" ? "Run anyway" : "Skip when filled"
1194
- })),
1195
- default: require_dist.DEFAULT_LABEL_LINK_POLICY
1196
- };
1197
- }
1187
+ var ANIMAL_CLASSIFIER_LABELS = require_dist.LABEL_SUPPLY_VOCABULARIES["animal-classifier"];
1188
+ var VEHICLE_CLASSIFIER_LABELS = require_dist.LABEL_SUPPLY_VOCABULARIES["vehicle-classifier"];
1198
1189
  var VGG_G2_CHARSET = [
1199
1190
  "",
1200
1191
  ..."0123456789".split(""),
@@ -1410,31 +1401,27 @@ var AnimalClassifierStep = class {
1410
1401
  }
1411
1402
  };
1412
1403
  getConfigSchema(model) {
1413
- return [
1414
- {
1415
- type: "multiselect",
1416
- key: "enabledClasses",
1417
- label: "Species",
1418
- description: "Which animal species to keep (empty = all). The classifier still scores every label but only the selected classes are returned on the detection.",
1419
- options: ANIMAL_CLASSIFIER_LABELS.map((l) => ({
1420
- value: l,
1421
- label: l
1422
- })),
1423
- default: []
1424
- },
1425
- labelLinkField("the animal classifier"),
1426
- {
1427
- type: "slider",
1428
- key: "minConfidence",
1429
- label: "Min Confidence",
1430
- description: "Drop classifications whose score is below this threshold.",
1431
- default: resolveModelDefaultConfidence(this.definition, model),
1432
- min: 0,
1433
- max: 1,
1434
- step: .05,
1435
- showValue: true
1436
- }
1437
- ];
1404
+ return [{
1405
+ type: "multiselect",
1406
+ key: "enabledClasses",
1407
+ label: "Species",
1408
+ description: "Which animal species to keep (empty = all). The classifier still scores every label but only the selected classes are returned on the detection. When the root model is the source, the same list decides which of its labels become the species; a switched-off species stays \"animal\".",
1409
+ options: ANIMAL_CLASSIFIER_LABELS.map((l) => ({
1410
+ value: l,
1411
+ label: l
1412
+ })),
1413
+ default: []
1414
+ }, {
1415
+ type: "slider",
1416
+ key: "minConfidence",
1417
+ label: "Min Confidence",
1418
+ description: "Drop classifications whose score is below this threshold.",
1419
+ default: resolveModelDefaultConfidence(this.definition, model),
1420
+ min: 0,
1421
+ max: 1,
1422
+ step: .05,
1423
+ showValue: true
1424
+ }];
1438
1425
  }
1439
1426
  };
1440
1427
  /**
@@ -1472,7 +1459,7 @@ var PackageDetectionStep = class extends PipelineStepBase {
1472
1459
  step: .05,
1473
1460
  default: resolveModelDefaultConfidence(this.definition, model),
1474
1461
  showValue: true
1475
- }, labelLinkField("package detection")];
1462
+ }];
1476
1463
  }
1477
1464
  };
1478
1465
  var ClassifierWithMinConfidence = class extends PipelineStepBase {
@@ -1688,28 +1675,23 @@ var STEP_BIRD_CLASSIFIER = new ClassifierWithMinConfidence({
1688
1675
  }
1689
1676
  });
1690
1677
  /**
1691
- * `vehicle-classifier` — the `minConfidence` slider plus the two fields a
1692
- * root-detector fill needs (D715): the class allow-list (a coverage gap the
1693
- * detector cannot produce, e.g. `Van` for Frigate+, is switched off HERE before
1694
- * the skip applies) and the `labelLink` policy.
1678
+ * `vehicle-classifier` — the `minConfidence` slider plus the class allow-list.
1679
+ * When the step takes the root model's labels (`useRootModel`, D730) the same
1680
+ * allow-list filters which root labels become the vehicle type.
1695
1681
  */
1696
1682
  var VehicleClassifierStep = class extends ClassifierWithMinConfidence {
1697
1683
  getConfigSchema(model) {
1698
- return [
1699
- {
1700
- type: "multiselect",
1701
- key: "enabledClasses",
1702
- label: "Vehicle types",
1703
- description: "Which vehicle types to keep (empty = all). The classifier still scores every type but only the selected ones are returned on the detection.",
1704
- options: VEHICLE_CLASSIFIER_LABELS.map((l) => ({
1705
- value: l,
1706
- label: l
1707
- })),
1708
- default: []
1709
- },
1710
- ...super.getConfigSchema(model),
1711
- labelLinkField("the vehicle classifier")
1712
- ];
1684
+ return [{
1685
+ type: "multiselect",
1686
+ key: "enabledClasses",
1687
+ label: "Vehicle types",
1688
+ description: "Which vehicle types to keep (empty = all). The classifier still scores every type but only the selected ones are returned on the detection. When the root model is the source, the same list decides which of its labels become the type; a switched-off type stays \"vehicle\".",
1689
+ options: VEHICLE_CLASSIFIER_LABELS.map((l) => ({
1690
+ value: l,
1691
+ label: l
1692
+ })),
1693
+ default: []
1694
+ }, ...super.getConfigSchema(model)];
1713
1695
  }
1714
1696
  };
1715
1697
  var STEP_VEHICLE_CLASSIFIER = new VehicleClassifierStep({
@@ -1,4 +1,4 @@
1
- import { A as LABEL_LINK_POLICIES, Ct as inferModelProvider, E as FILLABLE_STEP_VOCABULARIES, St as hfModelUrl, X as audioKindId, b as DEVICE_BACKEND_TO_FORMAT, f as COCO_80_LABELS, i as AUDIO_MACRO_LABELS, j as LABEL_LINK_SETTING_KEY, p as COCO_TO_MACRO, rn as stepModelRunsOnFormat, v as DEFAULT_LABEL_LINK_POLICY } from "./dist-Bpub2VcJ.mjs";
1
+ import { Tt as inferModelProvider, X as audioKindId, b as DEVICE_BACKEND_TO_FORMAT, f as COCO_80_LABELS, i as AUDIO_MACRO_LABELS, k as LABEL_SUPPLY_VOCABULARIES, on as stepModelRunsOnFormat, p as COCO_TO_MACRO, wt as hfModelUrl } from "./dist-CuPEyZY2.mjs";
2
2
  import { t as isWorkerReply } from "./worker-protocol-D_NzPcnh.mjs";
3
3
  import { randomUUID } from "node:crypto";
4
4
  //#region src/detection-pipeline/registry/effective-confidence.ts
@@ -90,7 +90,7 @@ var YUNET_MIT = {
90
90
  },
91
91
  url: "https://github.com/opencv/opencv_zoo/blob/main/models/face_detection_yunet/LICENSE",
92
92
  attribution: "YuNet weights Copyright (c) 2020 Shiqi Yu, MIT. Training code: ShiqiYu/libfacedetection.train, BSD-3-Clause.",
93
- modifications: "input contract baked into the graph (the pool RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather); internal tensor names cleared in the OpenVINO IR; ONNX fp32, OpenVINO IR fp32, CoreML fp16 (scripts/build-yunet-model.py)",
93
+ modifications: "input contract baked into the graph (the pool RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather); internal tensor names cleared in the OpenVINO IR; ONNX fp32, OpenVINO IR fp32, CoreML fp16 (scripts/build-yunet-model.py); Edge TPU build: the bake folded into the first Conv, full-integer int8 post-training quantisation calibrated on CamStack person crops, compiled with edgetpu_compiler 14 (scripts/build-yunet-edgetpu.py)",
94
94
  hosting: "camstack-hf"
95
95
  };
96
96
  var AURAFACE_APACHE = {
@@ -125,7 +125,7 @@ var OPEN_LPR_YOLOX_APACHE = {
125
125
  },
126
126
  url: "https://huggingface.co/faisalthaheem/open-lpr-models/blob/aed0df35ec2891c5a90437041ebeadb592cc516b/LICENSE",
127
127
  attribution: "open-lpr models, Copyright the open-lpr contributors, Apache-2.0 (https://huggingface.co/faisalthaheem/open-lpr-models, tag detector-2026.10.1). YOLOX architecture and COCO pretraining by Megvii (https://github.com/Megvii-BaseDetection/YOLOX), Apache-2.0. The upstream NOTICE is reproduced verbatim (`NOTICE-open-lpr.txt`).",
128
- modifications: "input contract baked into the graph (static 1x3x640x640 RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather) and the output reshaped to the YOLOv8 layout (cx, cy, w, h, obj*cls); ONNX fp32, OpenVINO IR fp16, CoreML fp16 (scripts/build-yolox-plate-model.py)",
128
+ modifications: "input contract baked into the graph (static 1x3x640x640 RGB /255 becomes the upstream BGR 0..255: Mul(255) plus a channel Gather) and the output reshaped to the YOLOv8 layout (cx, cy, w, h, obj*cls); ONNX fp32, OpenVINO IR fp16, CoreML fp16 (scripts/build-yolox-plate-model.py); Edge TPU build: the Focus stem rewritten as the equivalent 6x6 stride-2 Conv with the input bake folded into it, the graph cut before the grid decode (raw per-stride head), full-integer int8 post-training quantisation calibrated on CamStack vehicle crops, compiled with edgetpu_compiler 14 (scripts/build-yolox-plate-edgetpu.py)",
129
129
  hosting: "camstack-hf"
130
130
  };
131
131
  var FAST_PLATE_OCR_MIT = {
@@ -752,7 +752,12 @@ var FACE_DETECTION_MODELS = [{
752
752
  files: [...MLPACKAGE_FILES],
753
753
  runtimes: ["python"]
754
754
  },
755
- openvino: ovFormat(hf("faceDetection/yunet/openvino/camstack-yunet-2023mar.xml"), .36)
755
+ openvino: ovFormat(hf("faceDetection/yunet/openvino/camstack-yunet-2023mar.xml"), .36),
756
+ tflite: {
757
+ url: hf("faceDetection/yunet/tflite/camstack-yunet-2023mar_edgetpu.tflite"),
758
+ sizeMB: .7,
759
+ runtimes: ["python"]
760
+ }
756
761
  }
757
762
  }];
758
763
  var FACE_EMBEDDING_MODELS = [{
@@ -812,7 +817,12 @@ var PLATE_DETECTION_MODELS = [{
812
817
  files: [...MLPACKAGE_FILES],
813
818
  runtimes: ["python"]
814
819
  },
815
- openvino: ovFormat(hf("plateDetection/yolox-tiny-plate/openvino/camstack-yolox-tiny-plate.xml"), 10)
820
+ openvino: ovFormat(hf("plateDetection/yolox-tiny-plate/openvino/camstack-yolox-tiny-plate.xml"), 10),
821
+ tflite: {
822
+ url: hf("plateDetection/yolox-tiny-plate/tflite/camstack-yolox-tiny-plate_edgetpu.tflite"),
823
+ sizeMB: 6.9,
824
+ runtimes: ["python"]
825
+ }
816
826
  }
817
827
  }];
818
828
  var PACKAGE_DETECTION_MODELS = [{
@@ -1174,27 +1184,8 @@ var ANIMAL_10_LABELS = [
1174
1184
  "sheep",
1175
1185
  "spider"
1176
1186
  ];
1177
- var ANIMAL_CLASSIFIER_LABELS = FILLABLE_STEP_VOCABULARIES["animal-classifier"];
1178
- var VEHICLE_CLASSIFIER_LABELS = FILLABLE_STEP_VOCABULARIES["vehicle-classifier"];
1179
- /**
1180
- * The `labelLink` policy field (D715) — offered on every step a root detector
1181
- * can fill. Stored in the step's own settings (`DeviceStepConfig.settings` /
1182
- * `CameraStepOverridePatch.settings`), so it has ONE authority. It changes
1183
- * nothing unless the camera's root model declares it fills this step.
1184
- */
1185
- function labelLinkField(stepName) {
1186
- return {
1187
- type: "select",
1188
- key: LABEL_LINK_SETTING_KEY,
1189
- label: "When the detector already fills this step",
1190
- description: `Only matters when the root detection model declares it fills ${stepName} (e.g. a Frigate+ model). "Skip" does not run ${stepName} for a subject the detector already named, and makes the detector's label the one answer — but only once every class the detector cannot produce is switched off in this step's class list. "Run" always runs ${stepName}; the detector's label is then a fallback any answer of the step outranks.`,
1191
- options: LABEL_LINK_POLICIES.map((p) => ({
1192
- value: p,
1193
- label: p === "run" ? "Run anyway" : "Skip when filled"
1194
- })),
1195
- default: DEFAULT_LABEL_LINK_POLICY
1196
- };
1197
- }
1187
+ var ANIMAL_CLASSIFIER_LABELS = LABEL_SUPPLY_VOCABULARIES["animal-classifier"];
1188
+ var VEHICLE_CLASSIFIER_LABELS = LABEL_SUPPLY_VOCABULARIES["vehicle-classifier"];
1198
1189
  var VGG_G2_CHARSET = [
1199
1190
  "",
1200
1191
  ..."0123456789".split(""),
@@ -1410,31 +1401,27 @@ var AnimalClassifierStep = class {
1410
1401
  }
1411
1402
  };
1412
1403
  getConfigSchema(model) {
1413
- return [
1414
- {
1415
- type: "multiselect",
1416
- key: "enabledClasses",
1417
- label: "Species",
1418
- description: "Which animal species to keep (empty = all). The classifier still scores every label but only the selected classes are returned on the detection.",
1419
- options: ANIMAL_CLASSIFIER_LABELS.map((l) => ({
1420
- value: l,
1421
- label: l
1422
- })),
1423
- default: []
1424
- },
1425
- labelLinkField("the animal classifier"),
1426
- {
1427
- type: "slider",
1428
- key: "minConfidence",
1429
- label: "Min Confidence",
1430
- description: "Drop classifications whose score is below this threshold.",
1431
- default: resolveModelDefaultConfidence(this.definition, model),
1432
- min: 0,
1433
- max: 1,
1434
- step: .05,
1435
- showValue: true
1436
- }
1437
- ];
1404
+ return [{
1405
+ type: "multiselect",
1406
+ key: "enabledClasses",
1407
+ label: "Species",
1408
+ description: "Which animal species to keep (empty = all). The classifier still scores every label but only the selected classes are returned on the detection. When the root model is the source, the same list decides which of its labels become the species; a switched-off species stays \"animal\".",
1409
+ options: ANIMAL_CLASSIFIER_LABELS.map((l) => ({
1410
+ value: l,
1411
+ label: l
1412
+ })),
1413
+ default: []
1414
+ }, {
1415
+ type: "slider",
1416
+ key: "minConfidence",
1417
+ label: "Min Confidence",
1418
+ description: "Drop classifications whose score is below this threshold.",
1419
+ default: resolveModelDefaultConfidence(this.definition, model),
1420
+ min: 0,
1421
+ max: 1,
1422
+ step: .05,
1423
+ showValue: true
1424
+ }];
1438
1425
  }
1439
1426
  };
1440
1427
  /**
@@ -1472,7 +1459,7 @@ var PackageDetectionStep = class extends PipelineStepBase {
1472
1459
  step: .05,
1473
1460
  default: resolveModelDefaultConfidence(this.definition, model),
1474
1461
  showValue: true
1475
- }, labelLinkField("package detection")];
1462
+ }];
1476
1463
  }
1477
1464
  };
1478
1465
  var ClassifierWithMinConfidence = class extends PipelineStepBase {
@@ -1688,28 +1675,23 @@ var STEP_BIRD_CLASSIFIER = new ClassifierWithMinConfidence({
1688
1675
  }
1689
1676
  });
1690
1677
  /**
1691
- * `vehicle-classifier` — the `minConfidence` slider plus the two fields a
1692
- * root-detector fill needs (D715): the class allow-list (a coverage gap the
1693
- * detector cannot produce, e.g. `Van` for Frigate+, is switched off HERE before
1694
- * the skip applies) and the `labelLink` policy.
1678
+ * `vehicle-classifier` — the `minConfidence` slider plus the class allow-list.
1679
+ * When the step takes the root model's labels (`useRootModel`, D730) the same
1680
+ * allow-list filters which root labels become the vehicle type.
1695
1681
  */
1696
1682
  var VehicleClassifierStep = class extends ClassifierWithMinConfidence {
1697
1683
  getConfigSchema(model) {
1698
- return [
1699
- {
1700
- type: "multiselect",
1701
- key: "enabledClasses",
1702
- label: "Vehicle types",
1703
- description: "Which vehicle types to keep (empty = all). The classifier still scores every type but only the selected ones are returned on the detection.",
1704
- options: VEHICLE_CLASSIFIER_LABELS.map((l) => ({
1705
- value: l,
1706
- label: l
1707
- })),
1708
- default: []
1709
- },
1710
- ...super.getConfigSchema(model),
1711
- labelLinkField("the vehicle classifier")
1712
- ];
1684
+ return [{
1685
+ type: "multiselect",
1686
+ key: "enabledClasses",
1687
+ label: "Vehicle types",
1688
+ description: "Which vehicle types to keep (empty = all). The classifier still scores every type but only the selected ones are returned on the detection. When the root model is the source, the same list decides which of its labels become the type; a switched-off type stays \"vehicle\".",
1689
+ options: VEHICLE_CLASSIFIER_LABELS.map((l) => ({
1690
+ value: l,
1691
+ label: l
1692
+ })),
1693
+ default: []
1694
+ }, ...super.getConfigSchema(model)];
1713
1695
  }
1714
1696
  };
1715
1697
  var STEP_VEHICLE_CLASSIFIER = new VehicleClassifierStep({