@camstack/addon-vision 0.1.0 → 0.1.1

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 (131) hide show
  1. package/dist/addons/animal-classifier/index.d.mts +6 -1
  2. package/dist/addons/animal-classifier/index.d.ts +6 -1
  3. package/dist/addons/animal-classifier/index.js +514 -49
  4. package/dist/addons/animal-classifier/index.js.map +1 -1
  5. package/dist/addons/animal-classifier/index.mjs +6 -4
  6. package/dist/addons/audio-classification/index.d.mts +6 -1
  7. package/dist/addons/audio-classification/index.d.ts +6 -1
  8. package/dist/addons/audio-classification/index.js +87 -26
  9. package/dist/addons/audio-classification/index.js.map +1 -1
  10. package/dist/addons/audio-classification/index.mjs +3 -2
  11. package/dist/addons/bird-global-classifier/index.d.mts +6 -1
  12. package/dist/addons/bird-global-classifier/index.d.ts +6 -1
  13. package/dist/addons/bird-global-classifier/index.js +515 -50
  14. package/dist/addons/bird-global-classifier/index.js.map +1 -1
  15. package/dist/addons/bird-global-classifier/index.mjs +6 -4
  16. package/dist/addons/bird-nabirds-classifier/index.d.mts +6 -1
  17. package/dist/addons/bird-nabirds-classifier/index.d.ts +6 -1
  18. package/dist/addons/bird-nabirds-classifier/index.js +524 -60
  19. package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
  20. package/dist/addons/bird-nabirds-classifier/index.mjs +6 -4
  21. package/dist/addons/face-detection/index.d.mts +6 -1
  22. package/dist/addons/face-detection/index.d.ts +6 -1
  23. package/dist/addons/face-detection/index.js +539 -39
  24. package/dist/addons/face-detection/index.js.map +1 -1
  25. package/dist/addons/face-detection/index.mjs +5 -3
  26. package/dist/addons/face-recognition/index.d.mts +6 -1
  27. package/dist/addons/face-recognition/index.d.ts +6 -1
  28. package/dist/addons/face-recognition/index.js +488 -33
  29. package/dist/addons/face-recognition/index.js.map +1 -1
  30. package/dist/addons/face-recognition/index.mjs +5 -3
  31. package/dist/addons/motion-detection/index.d.mts +3 -1
  32. package/dist/addons/motion-detection/index.d.ts +3 -1
  33. package/dist/addons/motion-detection/index.js +11 -3
  34. package/dist/addons/motion-detection/index.js.map +1 -1
  35. package/dist/addons/motion-detection/index.mjs +140 -3
  36. package/dist/addons/motion-detection/index.mjs.map +1 -1
  37. package/dist/addons/object-detection/index.d.mts +6 -1
  38. package/dist/addons/object-detection/index.d.ts +6 -1
  39. package/dist/addons/object-detection/index.js +370 -72
  40. package/dist/addons/object-detection/index.js.map +1 -1
  41. package/dist/addons/object-detection/index.mjs +5 -3
  42. package/dist/addons/plate-detection/index.d.mts +6 -1
  43. package/dist/addons/plate-detection/index.d.ts +6 -1
  44. package/dist/addons/plate-detection/index.js +532 -31
  45. package/dist/addons/plate-detection/index.js.map +1 -1
  46. package/dist/addons/plate-detection/index.mjs +5 -3
  47. package/dist/addons/plate-recognition/index.d.mts +7 -1
  48. package/dist/addons/plate-recognition/index.d.ts +7 -1
  49. package/dist/addons/plate-recognition/index.js +177 -44
  50. package/dist/addons/plate-recognition/index.js.map +1 -1
  51. package/dist/addons/plate-recognition/index.mjs +4 -3
  52. package/dist/addons/segmentation-refiner/index.d.mts +30 -0
  53. package/dist/addons/segmentation-refiner/index.d.ts +30 -0
  54. package/dist/addons/segmentation-refiner/index.js +1049 -0
  55. package/dist/addons/segmentation-refiner/index.js.map +1 -0
  56. package/dist/addons/segmentation-refiner/index.mjs +209 -0
  57. package/dist/addons/segmentation-refiner/index.mjs.map +1 -0
  58. package/dist/addons/vehicle-classifier/index.d.mts +31 -0
  59. package/dist/addons/vehicle-classifier/index.d.ts +31 -0
  60. package/dist/addons/vehicle-classifier/index.js +689 -0
  61. package/dist/addons/vehicle-classifier/index.js.map +1 -0
  62. package/dist/addons/vehicle-classifier/index.mjs +250 -0
  63. package/dist/addons/vehicle-classifier/index.mjs.map +1 -0
  64. package/dist/{chunk-6OR5TE7A.mjs → chunk-22BHCDT5.mjs} +2 -2
  65. package/dist/chunk-22BHCDT5.mjs.map +1 -0
  66. package/dist/{chunk-LPI42WL6.mjs → chunk-6DJZZR64.mjs} +24 -12
  67. package/dist/chunk-6DJZZR64.mjs.map +1 -0
  68. package/dist/chunk-7DYHXUPZ.mjs +36 -0
  69. package/dist/chunk-7DYHXUPZ.mjs.map +1 -0
  70. package/dist/chunk-BJTO5JO5.mjs +11 -0
  71. package/dist/chunk-BP7H4NFS.mjs +412 -0
  72. package/dist/chunk-BP7H4NFS.mjs.map +1 -0
  73. package/dist/chunk-BR2FPGOX.mjs +98 -0
  74. package/dist/chunk-BR2FPGOX.mjs.map +1 -0
  75. package/dist/{chunk-B3R66MPF.mjs → chunk-DNQNGDR4.mjs} +58 -21
  76. package/dist/chunk-DNQNGDR4.mjs.map +1 -0
  77. package/dist/{chunk-ISOIDU4U.mjs → chunk-DUN6XU3N.mjs} +23 -5
  78. package/dist/chunk-DUN6XU3N.mjs.map +1 -0
  79. package/dist/{chunk-MEVASN3P.mjs → chunk-EPNWLSCG.mjs} +104 -22
  80. package/dist/chunk-EPNWLSCG.mjs.map +1 -0
  81. package/dist/{chunk-AYBFB7ID.mjs → chunk-G32RCIUI.mjs} +200 -318
  82. package/dist/chunk-G32RCIUI.mjs.map +1 -0
  83. package/dist/{chunk-3MQFUDRU.mjs → chunk-GR65KM6X.mjs} +76 -47
  84. package/dist/chunk-GR65KM6X.mjs.map +1 -0
  85. package/dist/{chunk-5AIQSN32.mjs → chunk-H7LMBTS5.mjs} +66 -17
  86. package/dist/chunk-H7LMBTS5.mjs.map +1 -0
  87. package/dist/{chunk-J4WRYHHY.mjs → chunk-IK4XIQPC.mjs} +66 -36
  88. package/dist/chunk-IK4XIQPC.mjs.map +1 -0
  89. package/dist/{chunk-5JJZGKL7.mjs → chunk-J6VNIIYX.mjs} +102 -19
  90. package/dist/chunk-J6VNIIYX.mjs.map +1 -0
  91. package/dist/{chunk-Q3SQOYG6.mjs → chunk-ML2JX43J.mjs} +67 -37
  92. package/dist/chunk-ML2JX43J.mjs.map +1 -0
  93. package/dist/{chunk-PDSHDDPV.mjs → chunk-WUMV524J.mjs} +159 -35
  94. package/dist/chunk-WUMV524J.mjs.map +1 -0
  95. package/dist/chunk-XZ6ZMXXU.mjs +39 -0
  96. package/dist/chunk-XZ6ZMXXU.mjs.map +1 -0
  97. package/dist/index.d.mts +17 -5
  98. package/dist/index.d.ts +17 -5
  99. package/dist/index.js +1344 -550
  100. package/dist/index.js.map +1 -1
  101. package/dist/index.mjs +191 -20
  102. package/dist/index.mjs.map +1 -1
  103. package/package.json +95 -18
  104. package/python/coreml_inference.py +61 -18
  105. package/python/openvino_inference.py +12 -4
  106. package/python/pytorch_inference.py +12 -4
  107. package/dist/addons/camera-native-detection/index.d.mts +0 -32
  108. package/dist/addons/camera-native-detection/index.d.ts +0 -32
  109. package/dist/addons/camera-native-detection/index.js +0 -99
  110. package/dist/addons/camera-native-detection/index.js.map +0 -1
  111. package/dist/addons/camera-native-detection/index.mjs +0 -7
  112. package/dist/chunk-3MQFUDRU.mjs.map +0 -1
  113. package/dist/chunk-5AIQSN32.mjs.map +0 -1
  114. package/dist/chunk-5JJZGKL7.mjs.map +0 -1
  115. package/dist/chunk-6OR5TE7A.mjs.map +0 -1
  116. package/dist/chunk-AYBFB7ID.mjs.map +0 -1
  117. package/dist/chunk-B3R66MPF.mjs.map +0 -1
  118. package/dist/chunk-DTOAB2CE.mjs +0 -79
  119. package/dist/chunk-DTOAB2CE.mjs.map +0 -1
  120. package/dist/chunk-ISOIDU4U.mjs.map +0 -1
  121. package/dist/chunk-J4WRYHHY.mjs.map +0 -1
  122. package/dist/chunk-LPI42WL6.mjs.map +0 -1
  123. package/dist/chunk-MEVASN3P.mjs.map +0 -1
  124. package/dist/chunk-PDSHDDPV.mjs.map +0 -1
  125. package/dist/chunk-Q3SQOYG6.mjs.map +0 -1
  126. package/dist/chunk-QIMDG34B.mjs +0 -229
  127. package/dist/chunk-QIMDG34B.mjs.map +0 -1
  128. package/python/__pycache__/coreml_inference.cpython-313.pyc +0 -0
  129. package/python/__pycache__/openvino_inference.cpython-313.pyc +0 -0
  130. package/python/__pycache__/pytorch_inference.cpython-313.pyc +0 -0
  131. /package/dist/{addons/camera-native-detection/index.mjs.map → chunk-BJTO5JO5.mjs.map} +0 -0
package/dist/index.js CHANGED
@@ -38,12 +38,12 @@ __export(src_exports, {
38
38
  BIRD_SPECIES_MODELS: () => BIRD_SPECIES_MODELS,
39
39
  BirdGlobalClassifierAddon: () => BirdGlobalClassifierAddon,
40
40
  BirdNABirdsClassifierAddon: () => BirdNABirdsClassifierAddon,
41
- CameraNativeDetectionAddon: () => CameraNativeDetectionAddon,
42
41
  FACE_DETECTION_MODELS: () => FACE_DETECTION_MODELS,
43
42
  FACE_RECOGNITION_MODELS: () => FACE_RECOGNITION_MODELS,
44
43
  FaceDetectionAddon: () => FaceDetectionAddon,
45
44
  FaceRecognitionAddon: () => FaceRecognitionAddon,
46
- MotionDetectionAddon: () => MotionDetectionAddon,
45
+ GENERAL_OCR_MODELS: () => GENERAL_OCR_MODELS,
46
+ MLPACKAGE_FILES: () => MLPACKAGE_FILES,
47
47
  NodeInferenceEngine: () => NodeInferenceEngine,
48
48
  OBJECT_DETECTION_MODELS: () => OBJECT_DETECTION_MODELS,
49
49
  ObjectDetectionAddon: () => ObjectDetectionAddon,
@@ -53,6 +53,8 @@ __export(src_exports, {
53
53
  PlateRecognitionAddon: () => PlateRecognitionAddon,
54
54
  PythonInferenceEngine: () => PythonInferenceEngine,
55
55
  SEGMENTATION_MODELS: () => SEGMENTATION_MODELS,
56
+ SEGMENTATION_REFINER_MODELS: () => SEGMENTATION_REFINER_MODELS,
57
+ VEHICLE_TYPE_MODELS: () => VEHICLE_TYPE_MODELS,
56
58
  cosineSimilarity: () => cosineSimilarity,
57
59
  cropRegion: () => cropRegion,
58
60
  ctcDecode: () => ctcDecode,
@@ -113,7 +115,7 @@ async function letterbox(jpeg, targetSize) {
113
115
  return { data: float32, scale, padX, padY, originalWidth, originalHeight };
114
116
  }
115
117
  async function resizeAndNormalize(jpeg, targetWidth, targetHeight, normalization, layout) {
116
- const { data } = await (0, import_sharp.default)(jpeg).resize(targetWidth, targetHeight).removeAlpha().raw().toBuffer({ resolveWithObject: true });
118
+ const { data } = await (0, import_sharp.default)(jpeg).resize(targetWidth, targetHeight, { fit: "fill" }).removeAlpha().raw().toBuffer({ resolveWithObject: true });
117
119
  const numPixels = targetWidth * targetHeight;
118
120
  const float32 = new Float32Array(3 * numPixels);
119
121
  const mean = [0.485, 0.456, 0.406];
@@ -475,6 +477,7 @@ var NodeInferenceEngine = class {
475
477
 
476
478
  // src/shared/python-engine.ts
477
479
  var import_node_child_process = require("child_process");
480
+ var import_core = require("@camstack/core");
478
481
  var PythonInferenceEngine = class {
479
482
  constructor(pythonPath, scriptPath, runtime, modelPath, extraArgs = []) {
480
483
  this.pythonPath = pythonPath;
@@ -597,7 +600,7 @@ var path2 = __toESM(require("path"));
597
600
  var AUTO_BACKEND_PRIORITY = ["coreml", "cuda", "tensorrt", "cpu"];
598
601
  var BACKEND_TO_FORMAT = {
599
602
  cpu: "onnx",
600
- coreml: "coreml",
603
+ coreml: "onnx",
601
604
  cuda: "onnx",
602
605
  tensorrt: "onnx"
603
606
  };
@@ -625,7 +628,7 @@ function modelExists(filePath) {
625
628
  }
626
629
  }
627
630
  async function resolveEngine(options) {
628
- const { runtime, backend, modelEntry, modelsDir, downloadModel } = options;
631
+ const { runtime, backend, modelEntry, modelsDir, models } = options;
629
632
  let selectedFormat;
630
633
  let selectedBackend;
631
634
  if (runtime === "auto") {
@@ -659,18 +662,18 @@ async function resolveEngine(options) {
659
662
  selectedFormat = fmt;
660
663
  selectedBackend = runtime === "onnx" ? backend || "cpu" : runtime;
661
664
  }
662
- let modelPath = modelFilePath(modelsDir, modelEntry, selectedFormat);
663
- if (!modelExists(modelPath)) {
664
- if (downloadModel) {
665
- const formatEntry = modelEntry.formats[selectedFormat];
666
- modelPath = await downloadModel(formatEntry.url, modelsDir);
667
- } else {
665
+ let modelPath;
666
+ if (models) {
667
+ modelPath = await models.ensure(modelEntry.id, selectedFormat);
668
+ } else {
669
+ modelPath = modelFilePath(modelsDir, modelEntry, selectedFormat);
670
+ if (!modelExists(modelPath)) {
668
671
  throw new Error(
669
- `resolveEngine: model file not found at ${modelPath} and no downloadModel function provided`
672
+ `resolveEngine: model file not found at ${modelPath} and no model service provided`
670
673
  );
671
674
  }
672
675
  }
673
- if (selectedFormat === "onnx" || selectedFormat === "coreml") {
676
+ if (selectedFormat === "onnx") {
674
677
  const engine = new NodeInferenceEngine(modelPath, selectedBackend);
675
678
  await engine.initialize();
676
679
  return { engine, format: selectedFormat, modelPath };
@@ -684,7 +687,18 @@ async function resolveEngine(options) {
684
687
  const effectiveRuntime = runtime === "auto" ? selectedBackend : runtime;
685
688
  const scriptName = PYTHON_SCRIPT_MAP[effectiveRuntime];
686
689
  if (scriptName && pythonPath) {
687
- const scriptPath = path2.join(__dirname, "../../python", scriptName);
690
+ const candidates = [
691
+ path2.join(__dirname, "../../python", scriptName),
692
+ path2.join(__dirname, "../python", scriptName),
693
+ path2.join(__dirname, "../../../python", scriptName)
694
+ ];
695
+ const scriptPath = candidates.find((p) => fs.existsSync(p));
696
+ if (!scriptPath) {
697
+ throw new Error(
698
+ `resolveEngine: Python script "${scriptName}" not found. Searched:
699
+ ${candidates.join("\n")}`
700
+ );
701
+ }
688
702
  const inputSize = Math.max(modelEntry.inputSize.width, modelEntry.inputSize.height);
689
703
  const engine = new PythonInferenceEngine(pythonPath, scriptPath, effectiveRuntime, modelPath, [
690
704
  `--input-size=${inputSize}`,
@@ -819,7 +833,13 @@ function detectMotion(current, previous, width, height, threshold, minArea) {
819
833
  // src/catalogs/object-detection-models.ts
820
834
  var import_types = require("@camstack/types");
821
835
  var HF_REPO = "camstack/camstack-models";
836
+ var MLPACKAGE_FILES = [
837
+ "Manifest.json",
838
+ "Data/com.apple.CoreML/model.mlmodel",
839
+ "Data/com.apple.CoreML/weights/weight.bin"
840
+ ];
822
841
  var OBJECT_DETECTION_MODELS = [
842
+ // ── YOLOv8 ──────────────────────────────────────────────────────
823
843
  {
824
844
  id: "yolov8n",
825
845
  name: "YOLOv8 Nano",
@@ -833,15 +853,20 @@ var OBJECT_DETECTION_MODELS = [
833
853
  },
834
854
  coreml: {
835
855
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8n.mlpackage"),
836
- sizeMB: 6
856
+ sizeMB: 6,
857
+ isDirectory: true,
858
+ files: MLPACKAGE_FILES,
859
+ runtimes: ["python"]
837
860
  },
838
861
  openvino: {
839
862
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8n.xml"),
840
- sizeMB: 7
863
+ sizeMB: 7,
864
+ runtimes: ["python"]
841
865
  },
842
866
  tflite: {
843
867
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/tflite/camstack-yolov8n_float32.tflite"),
844
- sizeMB: 12
868
+ sizeMB: 12,
869
+ runtimes: ["python"]
845
870
  }
846
871
  }
847
872
  },
@@ -858,14 +883,32 @@ var OBJECT_DETECTION_MODELS = [
858
883
  },
859
884
  coreml: {
860
885
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8s.mlpackage"),
861
- sizeMB: 21
886
+ sizeMB: 21,
887
+ isDirectory: true,
888
+ files: MLPACKAGE_FILES,
889
+ runtimes: ["python"]
862
890
  },
863
891
  openvino: {
864
892
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8s.xml"),
865
- sizeMB: 22
893
+ sizeMB: 22,
894
+ runtimes: ["python"]
866
895
  },
867
896
  tflite: {
868
897
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/tflite/camstack-yolov8s_float32.tflite"),
898
+ sizeMB: 43,
899
+ runtimes: ["python"]
900
+ }
901
+ }
902
+ },
903
+ {
904
+ id: "yolov8s-relu",
905
+ name: "YOLOv8 Small ReLU",
906
+ description: "YOLOv8 Small with ReLU activation \u2014 better hardware compatibility",
907
+ inputSize: { width: 640, height: 640 },
908
+ labels: import_types.COCO_80_LABELS,
909
+ formats: {
910
+ onnx: {
911
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8s-relu.onnx"),
869
912
  sizeMB: 43
870
913
  }
871
914
  }
@@ -883,18 +926,74 @@ var OBJECT_DETECTION_MODELS = [
883
926
  },
884
927
  coreml: {
885
928
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8m.mlpackage"),
886
- sizeMB: 49
929
+ sizeMB: 49,
930
+ isDirectory: true,
931
+ files: MLPACKAGE_FILES,
932
+ runtimes: ["python"]
887
933
  },
888
934
  openvino: {
889
935
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8m.xml"),
890
- sizeMB: 50
936
+ sizeMB: 50,
937
+ runtimes: ["python"]
891
938
  },
892
939
  tflite: {
893
940
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/tflite/camstack-yolov8m_float32.tflite"),
894
- sizeMB: 99
941
+ sizeMB: 99,
942
+ runtimes: ["python"]
943
+ }
944
+ }
945
+ },
946
+ {
947
+ id: "yolov8l",
948
+ name: "YOLOv8 Large",
949
+ description: "YOLOv8 Large \u2014 high-accuracy large model",
950
+ inputSize: { width: 640, height: 640 },
951
+ labels: import_types.COCO_80_LABELS,
952
+ formats: {
953
+ onnx: {
954
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8l.onnx"),
955
+ sizeMB: 167
956
+ },
957
+ coreml: {
958
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8l.mlpackage"),
959
+ sizeMB: 83,
960
+ isDirectory: true,
961
+ files: MLPACKAGE_FILES,
962
+ runtimes: ["python"]
963
+ },
964
+ openvino: {
965
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8l.xml"),
966
+ sizeMB: 84,
967
+ runtimes: ["python"]
968
+ }
969
+ }
970
+ },
971
+ {
972
+ id: "yolov8x",
973
+ name: "YOLOv8 Extra-Large",
974
+ description: "YOLOv8 Extra-Large \u2014 maximum accuracy",
975
+ inputSize: { width: 640, height: 640 },
976
+ labels: import_types.COCO_80_LABELS,
977
+ formats: {
978
+ onnx: {
979
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8x.onnx"),
980
+ sizeMB: 260
981
+ },
982
+ coreml: {
983
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8x.mlpackage"),
984
+ sizeMB: 130,
985
+ isDirectory: true,
986
+ files: MLPACKAGE_FILES,
987
+ runtimes: ["python"]
988
+ },
989
+ openvino: {
990
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8x.xml"),
991
+ sizeMB: 131,
992
+ runtimes: ["python"]
895
993
  }
896
994
  }
897
995
  },
996
+ // ── YOLOv9 ──────────────────────────────────────────────────────
898
997
  {
899
998
  id: "yolov9t",
900
999
  name: "YOLOv9 Tiny",
@@ -908,15 +1007,20 @@ var OBJECT_DETECTION_MODELS = [
908
1007
  },
909
1008
  coreml: {
910
1009
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/coreml/camstack-yolov9t.mlpackage"),
911
- sizeMB: 4
1010
+ sizeMB: 4,
1011
+ isDirectory: true,
1012
+ files: MLPACKAGE_FILES,
1013
+ runtimes: ["python"]
912
1014
  },
913
1015
  openvino: {
914
1016
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/openvino/camstack-yolov9t.xml"),
915
- sizeMB: 6
1017
+ sizeMB: 6,
1018
+ runtimes: ["python"]
916
1019
  },
917
1020
  tflite: {
918
1021
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/tflite/camstack-yolov9t_float32.tflite"),
919
- sizeMB: 8
1022
+ sizeMB: 8,
1023
+ runtimes: ["python"]
920
1024
  }
921
1025
  }
922
1026
  },
@@ -933,15 +1037,20 @@ var OBJECT_DETECTION_MODELS = [
933
1037
  },
934
1038
  coreml: {
935
1039
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/coreml/camstack-yolov9s.mlpackage"),
936
- sizeMB: 14
1040
+ sizeMB: 14,
1041
+ isDirectory: true,
1042
+ files: MLPACKAGE_FILES,
1043
+ runtimes: ["python"]
937
1044
  },
938
1045
  openvino: {
939
1046
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/openvino/camstack-yolov9s.xml"),
940
- sizeMB: 16
1047
+ sizeMB: 16,
1048
+ runtimes: ["python"]
941
1049
  },
942
1050
  tflite: {
943
1051
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/tflite/camstack-yolov9s_float32.tflite"),
944
- sizeMB: 28
1052
+ sizeMB: 28,
1053
+ runtimes: ["python"]
945
1054
  }
946
1055
  }
947
1056
  },
@@ -958,23 +1067,28 @@ var OBJECT_DETECTION_MODELS = [
958
1067
  },
959
1068
  coreml: {
960
1069
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/coreml/camstack-yolov9c.mlpackage"),
961
- sizeMB: 48
1070
+ sizeMB: 48,
1071
+ isDirectory: true,
1072
+ files: MLPACKAGE_FILES,
1073
+ runtimes: ["python"]
962
1074
  },
963
1075
  openvino: {
964
1076
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/openvino/camstack-yolov9c.xml"),
965
- sizeMB: 49
1077
+ sizeMB: 49,
1078
+ runtimes: ["python"]
966
1079
  },
967
1080
  tflite: {
968
1081
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/tflite/camstack-yolov9c_float32.tflite"),
969
- sizeMB: 97
1082
+ sizeMB: 97,
1083
+ runtimes: ["python"]
970
1084
  }
971
1085
  }
972
1086
  },
973
- // YOLO11 — no CoreML (coremltools incompatible)
1087
+ // ── YOLO11 ────────────────────────────────────────────────────
974
1088
  {
975
1089
  id: "yolo11n",
976
1090
  name: "YOLO11 Nano",
977
- description: "YOLO11 Nano \u2014 fastest, smallest YOLO11 detection model",
1091
+ description: "YOLO11 Nano \u2014 fastest, smallest YOLO11 detection model (mAP 39.5)",
978
1092
  inputSize: { width: 640, height: 640 },
979
1093
  labels: import_types.COCO_80_LABELS,
980
1094
  formats: {
@@ -982,20 +1096,29 @@ var OBJECT_DETECTION_MODELS = [
982
1096
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11n.onnx"),
983
1097
  sizeMB: 10
984
1098
  },
1099
+ coreml: {
1100
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11n.mlpackage"),
1101
+ sizeMB: 5,
1102
+ isDirectory: true,
1103
+ files: MLPACKAGE_FILES,
1104
+ runtimes: ["python"]
1105
+ },
985
1106
  openvino: {
986
1107
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11n.xml"),
987
- sizeMB: 5.4
1108
+ sizeMB: 5,
1109
+ runtimes: ["python"]
988
1110
  },
989
1111
  tflite: {
990
1112
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11n_float32.tflite"),
991
- sizeMB: 10
1113
+ sizeMB: 10,
1114
+ runtimes: ["python"]
992
1115
  }
993
1116
  }
994
1117
  },
995
1118
  {
996
1119
  id: "yolo11s",
997
1120
  name: "YOLO11 Small",
998
- description: "YOLO11 Small \u2014 balanced speed and accuracy",
1121
+ description: "YOLO11 Small \u2014 balanced speed and accuracy (mAP 47.0)",
999
1122
  inputSize: { width: 640, height: 640 },
1000
1123
  labels: import_types.COCO_80_LABELS,
1001
1124
  formats: {
@@ -1003,20 +1126,29 @@ var OBJECT_DETECTION_MODELS = [
1003
1126
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11s.onnx"),
1004
1127
  sizeMB: 36
1005
1128
  },
1129
+ coreml: {
1130
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11s.mlpackage"),
1131
+ sizeMB: 18,
1132
+ isDirectory: true,
1133
+ files: MLPACKAGE_FILES,
1134
+ runtimes: ["python"]
1135
+ },
1006
1136
  openvino: {
1007
1137
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11s.xml"),
1008
- sizeMB: 18
1138
+ sizeMB: 18,
1139
+ runtimes: ["python"]
1009
1140
  },
1010
1141
  tflite: {
1011
1142
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11s_float32.tflite"),
1012
- sizeMB: 36
1143
+ sizeMB: 36,
1144
+ runtimes: ["python"]
1013
1145
  }
1014
1146
  }
1015
1147
  },
1016
1148
  {
1017
1149
  id: "yolo11m",
1018
1150
  name: "YOLO11 Medium",
1019
- description: "YOLO11 Medium \u2014 higher accuracy, moderate size",
1151
+ description: "YOLO11 Medium \u2014 higher accuracy, moderate size (mAP 51.5)",
1020
1152
  inputSize: { width: 640, height: 640 },
1021
1153
  labels: import_types.COCO_80_LABELS,
1022
1154
  formats: {
@@ -1024,20 +1156,29 @@ var OBJECT_DETECTION_MODELS = [
1024
1156
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11m.onnx"),
1025
1157
  sizeMB: 77
1026
1158
  },
1159
+ coreml: {
1160
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11m.mlpackage"),
1161
+ sizeMB: 39,
1162
+ isDirectory: true,
1163
+ files: MLPACKAGE_FILES,
1164
+ runtimes: ["python"]
1165
+ },
1027
1166
  openvino: {
1028
1167
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11m.xml"),
1029
- sizeMB: 39
1168
+ sizeMB: 39,
1169
+ runtimes: ["python"]
1030
1170
  },
1031
1171
  tflite: {
1032
1172
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11m_float32.tflite"),
1033
- sizeMB: 77
1173
+ sizeMB: 77,
1174
+ runtimes: ["python"]
1034
1175
  }
1035
1176
  }
1036
1177
  },
1037
1178
  {
1038
1179
  id: "yolo11l",
1039
1180
  name: "YOLO11 Large",
1040
- description: "YOLO11 Large \u2014 high-accuracy large model",
1181
+ description: "YOLO11 Large \u2014 high-accuracy large model (mAP 53.4)",
1041
1182
  inputSize: { width: 640, height: 640 },
1042
1183
  labels: import_types.COCO_80_LABELS,
1043
1184
  formats: {
@@ -1045,20 +1186,29 @@ var OBJECT_DETECTION_MODELS = [
1045
1186
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11l.onnx"),
1046
1187
  sizeMB: 97
1047
1188
  },
1189
+ coreml: {
1190
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11l.mlpackage"),
1191
+ sizeMB: 49,
1192
+ isDirectory: true,
1193
+ files: MLPACKAGE_FILES,
1194
+ runtimes: ["python"]
1195
+ },
1048
1196
  openvino: {
1049
1197
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11l.xml"),
1050
- sizeMB: 49
1198
+ sizeMB: 49,
1199
+ runtimes: ["python"]
1051
1200
  },
1052
1201
  tflite: {
1053
1202
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11l_float32.tflite"),
1054
- sizeMB: 97
1203
+ sizeMB: 97,
1204
+ runtimes: ["python"]
1055
1205
  }
1056
1206
  }
1057
1207
  },
1058
1208
  {
1059
1209
  id: "yolo11x",
1060
1210
  name: "YOLO11 Extra-Large",
1061
- description: "YOLO11 Extra-Large \u2014 maximum accuracy",
1211
+ description: "YOLO11 Extra-Large \u2014 maximum accuracy (mAP 54.7)",
1062
1212
  inputSize: { width: 640, height: 640 },
1063
1213
  labels: import_types.COCO_80_LABELS,
1064
1214
  formats: {
@@ -1066,13 +1216,22 @@ var OBJECT_DETECTION_MODELS = [
1066
1216
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11x.onnx"),
1067
1217
  sizeMB: 218
1068
1218
  },
1219
+ coreml: {
1220
+ url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11x.mlpackage"),
1221
+ sizeMB: 109,
1222
+ isDirectory: true,
1223
+ files: MLPACKAGE_FILES,
1224
+ runtimes: ["python"]
1225
+ },
1069
1226
  openvino: {
1070
1227
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11x.xml"),
1071
- sizeMB: 109
1228
+ sizeMB: 109,
1229
+ runtimes: ["python"]
1072
1230
  },
1073
1231
  tflite: {
1074
1232
  url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11x_float32.tflite"),
1075
- sizeMB: 218
1233
+ sizeMB: 218,
1234
+ runtimes: ["python"]
1076
1235
  }
1077
1236
  }
1078
1237
  }
@@ -1098,11 +1257,15 @@ var FACE_DETECTION_MODELS = [
1098
1257
  },
1099
1258
  coreml: {
1100
1259
  url: (0, import_types2.hfModelUrl)(HF_REPO2, "faceDetection/scrfd/coreml/camstack-scrfd-500m.mlpackage"),
1101
- sizeMB: 1.2
1260
+ sizeMB: 1.2,
1261
+ isDirectory: true,
1262
+ files: MLPACKAGE_FILES,
1263
+ runtimes: ["python"]
1102
1264
  },
1103
1265
  openvino: {
1104
1266
  url: (0, import_types2.hfModelUrl)(HF_REPO2, "faceDetection/scrfd/openvino/camstack-scrfd-500m.xml"),
1105
- sizeMB: 1.3
1267
+ sizeMB: 1.3,
1268
+ runtimes: ["python"]
1106
1269
  }
1107
1270
  }
1108
1271
  },
@@ -1119,11 +1282,15 @@ var FACE_DETECTION_MODELS = [
1119
1282
  },
1120
1283
  coreml: {
1121
1284
  url: (0, import_types2.hfModelUrl)(HF_REPO2, "faceDetection/scrfd/coreml/camstack-scrfd-2.5g.mlpackage"),
1122
- sizeMB: 1.7
1285
+ sizeMB: 1.7,
1286
+ isDirectory: true,
1287
+ files: MLPACKAGE_FILES,
1288
+ runtimes: ["python"]
1123
1289
  },
1124
1290
  openvino: {
1125
1291
  url: (0, import_types2.hfModelUrl)(HF_REPO2, "faceDetection/scrfd/openvino/camstack-scrfd-2.5g.xml"),
1126
- sizeMB: 1.8
1292
+ sizeMB: 1.8,
1293
+ runtimes: ["python"]
1127
1294
  }
1128
1295
  }
1129
1296
  },
@@ -1140,11 +1307,15 @@ var FACE_DETECTION_MODELS = [
1140
1307
  },
1141
1308
  coreml: {
1142
1309
  url: (0, import_types2.hfModelUrl)(HF_REPO2, "faceDetection/scrfd/coreml/camstack-scrfd-10g.mlpackage"),
1143
- sizeMB: 8.2
1310
+ sizeMB: 8.2,
1311
+ isDirectory: true,
1312
+ files: MLPACKAGE_FILES,
1313
+ runtimes: ["python"]
1144
1314
  },
1145
1315
  openvino: {
1146
1316
  url: (0, import_types2.hfModelUrl)(HF_REPO2, "faceDetection/scrfd/openvino/camstack-scrfd-10g.xml"),
1147
- sizeMB: 8.3
1317
+ sizeMB: 8.3,
1318
+ runtimes: ["python"]
1148
1319
  }
1149
1320
  }
1150
1321
  }
@@ -1171,11 +1342,15 @@ var FACE_RECOGNITION_MODELS = [
1171
1342
  },
1172
1343
  coreml: {
1173
1344
  url: (0, import_types3.hfModelUrl)(HF_REPO3, "faceRecognition/arcface/coreml/camstack-arcface-r100.mlpackage"),
1174
- sizeMB: 65
1345
+ sizeMB: 65,
1346
+ isDirectory: true,
1347
+ files: MLPACKAGE_FILES,
1348
+ runtimes: ["python"]
1175
1349
  },
1176
1350
  openvino: {
1177
1351
  url: (0, import_types3.hfModelUrl)(HF_REPO3, "faceRecognition/arcface/openvino/camstack-arcface-r100.xml"),
1178
- sizeMB: 65
1352
+ sizeMB: 65,
1353
+ runtimes: ["python"]
1179
1354
  }
1180
1355
  }
1181
1356
  }
@@ -1201,15 +1376,20 @@ var PLATE_DETECTION_MODELS = [
1201
1376
  },
1202
1377
  coreml: {
1203
1378
  url: (0, import_types4.hfModelUrl)(HF_REPO4, "plateDetection/yolov8-plate/coreml/camstack-yolov8n-plate.mlpackage"),
1204
- sizeMB: 5.9
1379
+ sizeMB: 5.9,
1380
+ isDirectory: true,
1381
+ files: MLPACKAGE_FILES,
1382
+ runtimes: ["python"]
1205
1383
  },
1206
1384
  openvino: {
1207
1385
  url: (0, import_types4.hfModelUrl)(HF_REPO4, "plateDetection/yolov8-plate/openvino/camstack-yolov8n-plate.xml"),
1208
- sizeMB: 6.1
1386
+ sizeMB: 6.1,
1387
+ runtimes: ["python"]
1209
1388
  },
1210
1389
  tflite: {
1211
1390
  url: (0, import_types4.hfModelUrl)(HF_REPO4, "plateDetection/yolov8-plate/tflite/camstack-yolov8n-plate_float32.tflite"),
1212
- sizeMB: 12
1391
+ sizeMB: 12,
1392
+ runtimes: ["python"]
1213
1393
  }
1214
1394
  }
1215
1395
  }
@@ -1222,27 +1402,38 @@ var PLATE_TEXT_LABELS = [
1222
1402
  { id: "text", name: "Plate Text" }
1223
1403
  ];
1224
1404
  var PLATE_RECOGNITION_MODELS = [
1405
+ // ── PaddleOCR PP-OCRv5 ────────────────────────────────────────
1225
1406
  {
1226
1407
  id: "paddleocr-latin",
1227
1408
  name: "PaddleOCR Latin",
1228
- description: "PaddleOCR recognition model for Latin-script license plates",
1409
+ description: "PaddleOCR PP-OCRv5 recognition model for Latin-script license plates",
1229
1410
  inputSize: { width: 320, height: 48 },
1230
1411
  labels: PLATE_TEXT_LABELS,
1231
1412
  formats: {
1413
+ // ONNX only — PaddleOCR has dynamic dimensions incompatible with CoreML native conversion.
1414
+ // On Apple Silicon, ONNX Runtime uses CoreML EP automatically for acceleration.
1232
1415
  onnx: {
1233
1416
  url: (0, import_types5.hfModelUrl)(HF_REPO5, "plateRecognition/paddleocr/onnx/camstack-paddleocr-latin-rec.onnx"),
1234
1417
  sizeMB: 7.5
1235
1418
  },
1236
1419
  openvino: {
1237
1420
  url: (0, import_types5.hfModelUrl)(HF_REPO5, "plateRecognition/paddleocr/openvino/camstack-paddleocr-latin.xml"),
1238
- sizeMB: 4
1421
+ sizeMB: 4,
1422
+ runtimes: ["python"]
1239
1423
  }
1240
- }
1424
+ },
1425
+ extraFiles: [
1426
+ {
1427
+ url: (0, import_types5.hfModelUrl)(HF_REPO5, "plateRecognition/paddleocr/onnx/camstack-paddleocr-latin-dict.txt"),
1428
+ filename: "camstack-paddleocr-latin-dict.txt",
1429
+ sizeMB: 0.01
1430
+ }
1431
+ ]
1241
1432
  },
1242
1433
  {
1243
1434
  id: "paddleocr-en",
1244
1435
  name: "PaddleOCR English",
1245
- description: "PaddleOCR recognition model optimized for English license plates",
1436
+ description: "PaddleOCR PP-OCRv5 recognition model optimized for English license plates",
1246
1437
  inputSize: { width: 320, height: 48 },
1247
1438
  labels: PLATE_TEXT_LABELS,
1248
1439
  formats: {
@@ -1252,15 +1443,228 @@ var PLATE_RECOGNITION_MODELS = [
1252
1443
  },
1253
1444
  openvino: {
1254
1445
  url: (0, import_types5.hfModelUrl)(HF_REPO5, "plateRecognition/paddleocr/openvino/camstack-paddleocr-en.xml"),
1255
- sizeMB: 4
1446
+ sizeMB: 4,
1447
+ runtimes: ["python"]
1256
1448
  }
1257
- }
1449
+ },
1450
+ extraFiles: [
1451
+ {
1452
+ url: (0, import_types5.hfModelUrl)(HF_REPO5, "plateRecognition/paddleocr/onnx/camstack-paddleocr-en-dict.txt"),
1453
+ filename: "camstack-paddleocr-en-dict.txt",
1454
+ sizeMB: 0.01
1455
+ }
1456
+ ]
1457
+ },
1458
+ // ── CRNN-MobileNetV3 (via OnnxTR/docTR) ─────────────────────────
1459
+ // Simple CNN+LSTM+CTC architecture — good CoreML compatibility (no dynamic ops)
1460
+ {
1461
+ id: "crnn-mobilenet-v3-small",
1462
+ name: "CRNN MobileNet V3 Small",
1463
+ description: "CRNN MobileNetV3-Small \u2014 lightweight text recognition, CoreML compatible via OnnxTR",
1464
+ inputSize: { width: 128, height: 32 },
1465
+ labels: PLATE_TEXT_LABELS,
1466
+ formats: {
1467
+ onnx: {
1468
+ url: (0, import_types5.hfModelUrl)(HF_REPO5, "plateRecognition/crnn-mobilenet/onnx/camstack-crnn-mobilenet-v3-small.onnx"),
1469
+ sizeMB: 8
1470
+ }
1471
+ },
1472
+ extraFiles: [
1473
+ {
1474
+ url: (0, import_types5.hfModelUrl)(HF_REPO5, "plateRecognition/crnn-mobilenet/camstack-crnn-mobilenet-charset.txt"),
1475
+ filename: "camstack-crnn-mobilenet-charset.txt",
1476
+ sizeMB: 0.01
1477
+ }
1478
+ ]
1479
+ },
1480
+ {
1481
+ id: "crnn-mobilenet-v3-large",
1482
+ name: "CRNN MobileNet V3 Large",
1483
+ description: "CRNN MobileNetV3-Large \u2014 higher accuracy text recognition, CoreML compatible",
1484
+ inputSize: { width: 128, height: 32 },
1485
+ labels: PLATE_TEXT_LABELS,
1486
+ formats: {
1487
+ onnx: {
1488
+ url: (0, import_types5.hfModelUrl)(HF_REPO5, "plateRecognition/crnn-mobilenet/onnx/camstack-crnn-mobilenet-v3-large.onnx"),
1489
+ sizeMB: 17
1490
+ }
1491
+ },
1492
+ extraFiles: [
1493
+ {
1494
+ url: (0, import_types5.hfModelUrl)(HF_REPO5, "plateRecognition/crnn-mobilenet/camstack-crnn-mobilenet-charset.txt"),
1495
+ filename: "camstack-crnn-mobilenet-charset.txt",
1496
+ sizeMB: 0.01
1497
+ }
1498
+ ]
1258
1499
  }
1259
1500
  ];
1260
1501
 
1261
- // src/catalogs/audio-classification-models.ts
1502
+ // src/catalogs/general-ocr-models.ts
1262
1503
  var import_types6 = require("@camstack/types");
1263
1504
  var HF_REPO6 = "camstack/camstack-models";
1505
+ var OCR_TEXT_LABELS = [
1506
+ { id: "text", name: "Scene Text" }
1507
+ ];
1508
+ var GENERAL_OCR_MODELS = [
1509
+ // ── OnnxTR / docTR — lightweight general scene text recognition ──
1510
+ {
1511
+ id: "doctr-det-db-mobilenet",
1512
+ name: "docTR Detection MobileNet",
1513
+ description: "docTR DBNet MobileNet V3 \u2014 lightweight text region detection for scene text",
1514
+ inputSize: { width: 1024, height: 1024 },
1515
+ labels: OCR_TEXT_LABELS,
1516
+ formats: {
1517
+ onnx: {
1518
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/doctr/onnx/camstack-doctr-det-db-mobilenet-v3.onnx"),
1519
+ sizeMB: 15
1520
+ },
1521
+ coreml: {
1522
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/doctr/coreml/camstack-doctr-det-db-mobilenet-v3.mlpackage"),
1523
+ sizeMB: 8,
1524
+ isDirectory: true,
1525
+ files: [
1526
+ "Manifest.json",
1527
+ "Data/com.apple.CoreML/model.mlmodel",
1528
+ "Data/com.apple.CoreML/weights/weight.bin"
1529
+ ],
1530
+ runtimes: ["python"]
1531
+ },
1532
+ openvino: {
1533
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/doctr/openvino/camstack-doctr-det-db-mobilenet-v3.xml"),
1534
+ sizeMB: 8,
1535
+ runtimes: ["python"]
1536
+ }
1537
+ }
1538
+ },
1539
+ {
1540
+ id: "doctr-rec-crnn-mobilenet",
1541
+ name: "docTR Recognition CRNN MobileNet",
1542
+ description: "docTR CRNN MobileNet V3 \u2014 lightweight text recognition for detected regions",
1543
+ inputSize: { width: 128, height: 32 },
1544
+ labels: OCR_TEXT_LABELS,
1545
+ formats: {
1546
+ onnx: {
1547
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/doctr/onnx/camstack-doctr-rec-crnn-mobilenet-v3.onnx"),
1548
+ sizeMB: 5
1549
+ },
1550
+ coreml: {
1551
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/doctr/coreml/camstack-doctr-rec-crnn-mobilenet-v3.mlpackage"),
1552
+ sizeMB: 3,
1553
+ isDirectory: true,
1554
+ files: [
1555
+ "Manifest.json",
1556
+ "Data/com.apple.CoreML/model.mlmodel",
1557
+ "Data/com.apple.CoreML/weights/weight.bin"
1558
+ ],
1559
+ runtimes: ["python"]
1560
+ },
1561
+ openvino: {
1562
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/doctr/openvino/camstack-doctr-rec-crnn-mobilenet-v3.xml"),
1563
+ sizeMB: 3,
1564
+ runtimes: ["python"]
1565
+ }
1566
+ }
1567
+ },
1568
+ {
1569
+ id: "doctr-rec-parseq",
1570
+ name: "docTR Recognition PARSeq",
1571
+ description: "docTR PARSeq \u2014 high-accuracy scene text recognition (top ICDAR scores)",
1572
+ inputSize: { width: 128, height: 32 },
1573
+ labels: OCR_TEXT_LABELS,
1574
+ formats: {
1575
+ onnx: {
1576
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/doctr/onnx/camstack-doctr-rec-parseq.onnx"),
1577
+ sizeMB: 25
1578
+ },
1579
+ coreml: {
1580
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/doctr/coreml/camstack-doctr-rec-parseq.mlpackage"),
1581
+ sizeMB: 13,
1582
+ isDirectory: true,
1583
+ files: [
1584
+ "Manifest.json",
1585
+ "Data/com.apple.CoreML/model.mlmodel",
1586
+ "Data/com.apple.CoreML/weights/weight.bin"
1587
+ ],
1588
+ runtimes: ["python"]
1589
+ },
1590
+ openvino: {
1591
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/doctr/openvino/camstack-doctr-rec-parseq.xml"),
1592
+ sizeMB: 13,
1593
+ runtimes: ["python"]
1594
+ }
1595
+ }
1596
+ },
1597
+ // ── PaddleOCR PP-OCRv5 Mobile — general-purpose text detection + recognition ──
1598
+ {
1599
+ id: "ppocr-v5-det-mobile",
1600
+ name: "PP-OCRv5 Detection Mobile",
1601
+ description: "PP-OCRv5 mobile text detection \u2014 optimized for edge, 100+ languages",
1602
+ inputSize: { width: 640, height: 640 },
1603
+ labels: OCR_TEXT_LABELS,
1604
+ formats: {
1605
+ onnx: {
1606
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/ppocr-v5/onnx/camstack-ppocr-v5-det-mobile.onnx"),
1607
+ sizeMB: 6
1608
+ },
1609
+ coreml: {
1610
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/ppocr-v5/coreml/camstack-ppocr-v5-det-mobile.mlpackage"),
1611
+ sizeMB: 3,
1612
+ isDirectory: true,
1613
+ files: [
1614
+ "Manifest.json",
1615
+ "Data/com.apple.CoreML/model.mlmodel",
1616
+ "Data/com.apple.CoreML/weights/weight.bin"
1617
+ ],
1618
+ runtimes: ["python"]
1619
+ },
1620
+ openvino: {
1621
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/ppocr-v5/openvino/camstack-ppocr-v5-det-mobile.xml"),
1622
+ sizeMB: 3,
1623
+ runtimes: ["python"]
1624
+ }
1625
+ }
1626
+ },
1627
+ {
1628
+ id: "ppocr-v5-rec-mobile",
1629
+ name: "PP-OCRv5 Recognition Mobile",
1630
+ description: "PP-OCRv5 mobile text recognition \u2014 100+ languages, CTC decoding",
1631
+ inputSize: { width: 320, height: 48 },
1632
+ labels: OCR_TEXT_LABELS,
1633
+ formats: {
1634
+ onnx: {
1635
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/ppocr-v5/onnx/camstack-ppocr-v5-rec-mobile.onnx"),
1636
+ sizeMB: 8
1637
+ },
1638
+ coreml: {
1639
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/ppocr-v5/coreml/camstack-ppocr-v5-rec-mobile.mlpackage"),
1640
+ sizeMB: 4,
1641
+ isDirectory: true,
1642
+ files: [
1643
+ "Manifest.json",
1644
+ "Data/com.apple.CoreML/model.mlmodel",
1645
+ "Data/com.apple.CoreML/weights/weight.bin"
1646
+ ],
1647
+ runtimes: ["python"]
1648
+ },
1649
+ openvino: {
1650
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/ppocr-v5/openvino/camstack-ppocr-v5-rec-mobile.xml"),
1651
+ sizeMB: 4,
1652
+ runtimes: ["python"]
1653
+ }
1654
+ },
1655
+ extraFiles: [
1656
+ {
1657
+ url: (0, import_types6.hfModelUrl)(HF_REPO6, "generalOcr/ppocr-v5/camstack-ppocr-v5-keys.txt"),
1658
+ filename: "camstack-ppocr-v5-keys.txt",
1659
+ sizeMB: 0.1
1660
+ }
1661
+ ]
1662
+ }
1663
+ ];
1664
+
1665
+ // src/catalogs/audio-classification-models.ts
1666
+ var import_types7 = require("@camstack/types");
1667
+ var HF_REPO7 = "camstack/camstack-models";
1264
1668
  var AUDIO_LABELS = [
1265
1669
  { id: "audio", name: "Audio Event" }
1266
1670
  ];
@@ -1273,11 +1677,11 @@ var AUDIO_CLASSIFICATION_MODELS = [
1273
1677
  labels: AUDIO_LABELS,
1274
1678
  formats: {
1275
1679
  onnx: {
1276
- url: (0, import_types6.hfModelUrl)(HF_REPO6, "audioClassification/yamnet/onnx/camstack-yamnet.onnx"),
1680
+ url: (0, import_types7.hfModelUrl)(HF_REPO7, "audioClassification/yamnet/onnx/camstack-yamnet.onnx"),
1277
1681
  sizeMB: 15
1278
1682
  },
1279
1683
  openvino: {
1280
- url: (0, import_types6.hfModelUrl)(HF_REPO6, "audioClassification/yamnet/openvino/camstack-yamnet.xml"),
1684
+ url: (0, import_types7.hfModelUrl)(HF_REPO7, "audioClassification/yamnet/openvino/camstack-yamnet.xml"),
1281
1685
  sizeMB: 8
1282
1686
  }
1283
1687
  }
@@ -1285,24 +1689,32 @@ var AUDIO_CLASSIFICATION_MODELS = [
1285
1689
  ];
1286
1690
 
1287
1691
  // src/catalogs/segmentation-models.ts
1288
- var import_types7 = require("@camstack/types");
1289
- var HF_REPO7 = "camstack/camstack-models";
1692
+ var import_types8 = require("@camstack/types");
1693
+ var HF_REPO8 = "camstack/camstack-models";
1290
1694
  var SEGMENTATION_MODELS = [
1291
- // YOLO11-seg — no CoreML (coremltools incompatible)
1695
+ // ── YOLO11-seg ───────────────────────────────────────────────
1292
1696
  {
1293
1697
  id: "yolo11n-seg",
1294
1698
  name: "YOLO11 Nano Segmentation",
1295
1699
  description: "YOLO11 Nano \u2014 fastest, smallest YOLO11 instance segmentation model",
1296
1700
  inputSize: { width: 640, height: 640 },
1297
- labels: import_types7.COCO_80_LABELS,
1701
+ labels: import_types8.COCO_80_LABELS,
1298
1702
  formats: {
1299
1703
  onnx: {
1300
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolo11-seg/onnx/camstack-yolo11n-seg.onnx"),
1704
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolo11-seg/onnx/camstack-yolo11n-seg.onnx"),
1301
1705
  sizeMB: 11
1302
1706
  },
1707
+ coreml: {
1708
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolo11-seg/coreml/camstack-yolo11n-seg.mlpackage"),
1709
+ sizeMB: 6,
1710
+ isDirectory: true,
1711
+ files: MLPACKAGE_FILES,
1712
+ runtimes: ["python"]
1713
+ },
1303
1714
  openvino: {
1304
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolo11-seg/openvino/camstack-yolo11n-seg.xml"),
1305
- sizeMB: 6
1715
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolo11-seg/openvino/camstack-yolo11n-seg.xml"),
1716
+ sizeMB: 6,
1717
+ runtimes: ["python"]
1306
1718
  }
1307
1719
  }
1308
1720
  },
@@ -1311,15 +1723,23 @@ var SEGMENTATION_MODELS = [
1311
1723
  name: "YOLO11 Small Segmentation",
1312
1724
  description: "YOLO11 Small \u2014 balanced speed and accuracy for instance segmentation",
1313
1725
  inputSize: { width: 640, height: 640 },
1314
- labels: import_types7.COCO_80_LABELS,
1726
+ labels: import_types8.COCO_80_LABELS,
1315
1727
  formats: {
1316
1728
  onnx: {
1317
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolo11-seg/onnx/camstack-yolo11s-seg.onnx"),
1729
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolo11-seg/onnx/camstack-yolo11s-seg.onnx"),
1318
1730
  sizeMB: 39
1319
1731
  },
1732
+ coreml: {
1733
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolo11-seg/coreml/camstack-yolo11s-seg.mlpackage"),
1734
+ sizeMB: 20,
1735
+ isDirectory: true,
1736
+ files: MLPACKAGE_FILES,
1737
+ runtimes: ["python"]
1738
+ },
1320
1739
  openvino: {
1321
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolo11-seg/openvino/camstack-yolo11s-seg.xml"),
1322
- sizeMB: 20
1740
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolo11-seg/openvino/camstack-yolo11s-seg.xml"),
1741
+ sizeMB: 20,
1742
+ runtimes: ["python"]
1323
1743
  }
1324
1744
  }
1325
1745
  },
@@ -1328,37 +1748,49 @@ var SEGMENTATION_MODELS = [
1328
1748
  name: "YOLO11 Medium Segmentation",
1329
1749
  description: "YOLO11 Medium \u2014 higher accuracy instance segmentation",
1330
1750
  inputSize: { width: 640, height: 640 },
1331
- labels: import_types7.COCO_80_LABELS,
1751
+ labels: import_types8.COCO_80_LABELS,
1332
1752
  formats: {
1333
1753
  onnx: {
1334
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolo11-seg/onnx/camstack-yolo11m-seg.onnx"),
1754
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolo11-seg/onnx/camstack-yolo11m-seg.onnx"),
1335
1755
  sizeMB: 86
1336
1756
  },
1757
+ coreml: {
1758
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolo11-seg/coreml/camstack-yolo11m-seg.mlpackage"),
1759
+ sizeMB: 43,
1760
+ isDirectory: true,
1761
+ files: MLPACKAGE_FILES,
1762
+ runtimes: ["python"]
1763
+ },
1337
1764
  openvino: {
1338
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolo11-seg/openvino/camstack-yolo11m-seg.xml"),
1339
- sizeMB: 43
1765
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolo11-seg/openvino/camstack-yolo11m-seg.xml"),
1766
+ sizeMB: 43,
1767
+ runtimes: ["python"]
1340
1768
  }
1341
1769
  }
1342
1770
  },
1343
- // YOLOv8-seg — CoreML available
1771
+ // ── YOLOv8-seg — CoreML supported ─────────────────────────────
1344
1772
  {
1345
1773
  id: "yolov8n-seg",
1346
1774
  name: "YOLOv8 Nano Segmentation",
1347
1775
  description: "YOLOv8 Nano \u2014 fastest, smallest YOLOv8 instance segmentation model",
1348
1776
  inputSize: { width: 640, height: 640 },
1349
- labels: import_types7.COCO_80_LABELS,
1777
+ labels: import_types8.COCO_80_LABELS,
1350
1778
  formats: {
1351
1779
  onnx: {
1352
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolov8-seg/onnx/camstack-yolov8n-seg.onnx"),
1780
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolov8-seg/onnx/camstack-yolov8n-seg.onnx"),
1353
1781
  sizeMB: 13
1354
1782
  },
1355
1783
  coreml: {
1356
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolov8-seg/coreml/camstack-yolov8n-seg.mlpackage"),
1357
- sizeMB: 7
1784
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolov8-seg/coreml/camstack-yolov8n-seg.mlpackage"),
1785
+ sizeMB: 7,
1786
+ isDirectory: true,
1787
+ files: MLPACKAGE_FILES,
1788
+ runtimes: ["python"]
1358
1789
  },
1359
1790
  openvino: {
1360
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolov8-seg/openvino/camstack-yolov8n-seg.xml"),
1361
- sizeMB: 7
1791
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolov8-seg/openvino/camstack-yolov8n-seg.xml"),
1792
+ sizeMB: 7,
1793
+ runtimes: ["python"]
1362
1794
  }
1363
1795
  }
1364
1796
  },
@@ -1367,19 +1799,23 @@ var SEGMENTATION_MODELS = [
1367
1799
  name: "YOLOv8 Small Segmentation",
1368
1800
  description: "YOLOv8 Small \u2014 balanced speed and accuracy for instance segmentation",
1369
1801
  inputSize: { width: 640, height: 640 },
1370
- labels: import_types7.COCO_80_LABELS,
1802
+ labels: import_types8.COCO_80_LABELS,
1371
1803
  formats: {
1372
1804
  onnx: {
1373
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolov8-seg/onnx/camstack-yolov8s-seg.onnx"),
1805
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolov8-seg/onnx/camstack-yolov8s-seg.onnx"),
1374
1806
  sizeMB: 45
1375
1807
  },
1376
1808
  coreml: {
1377
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolov8-seg/coreml/camstack-yolov8s-seg.mlpackage"),
1378
- sizeMB: 23
1809
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolov8-seg/coreml/camstack-yolov8s-seg.mlpackage"),
1810
+ sizeMB: 23,
1811
+ isDirectory: true,
1812
+ files: MLPACKAGE_FILES,
1813
+ runtimes: ["python"]
1379
1814
  },
1380
1815
  openvino: {
1381
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolov8-seg/openvino/camstack-yolov8s-seg.xml"),
1382
- sizeMB: 23
1816
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolov8-seg/openvino/camstack-yolov8s-seg.xml"),
1817
+ sizeMB: 23,
1818
+ runtimes: ["python"]
1383
1819
  }
1384
1820
  }
1385
1821
  },
@@ -1388,28 +1824,32 @@ var SEGMENTATION_MODELS = [
1388
1824
  name: "YOLOv8 Medium Segmentation",
1389
1825
  description: "YOLOv8 Medium \u2014 higher accuracy instance segmentation",
1390
1826
  inputSize: { width: 640, height: 640 },
1391
- labels: import_types7.COCO_80_LABELS,
1827
+ labels: import_types8.COCO_80_LABELS,
1392
1828
  formats: {
1393
1829
  onnx: {
1394
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolov8-seg/onnx/camstack-yolov8m-seg.onnx"),
1830
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolov8-seg/onnx/camstack-yolov8m-seg.onnx"),
1395
1831
  sizeMB: 104
1396
1832
  },
1397
1833
  coreml: {
1398
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolov8-seg/coreml/camstack-yolov8m-seg.mlpackage"),
1399
- sizeMB: 52
1834
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolov8-seg/coreml/camstack-yolov8m-seg.mlpackage"),
1835
+ sizeMB: 52,
1836
+ isDirectory: true,
1837
+ files: MLPACKAGE_FILES,
1838
+ runtimes: ["python"]
1400
1839
  },
1401
1840
  openvino: {
1402
- url: (0, import_types7.hfModelUrl)(HF_REPO7, "segmentation/yolov8-seg/openvino/camstack-yolov8m-seg.xml"),
1403
- sizeMB: 53
1841
+ url: (0, import_types8.hfModelUrl)(HF_REPO8, "segmentation/yolov8-seg/openvino/camstack-yolov8m-seg.xml"),
1842
+ sizeMB: 53,
1843
+ runtimes: ["python"]
1404
1844
  }
1405
1845
  }
1406
1846
  }
1407
1847
  ];
1408
1848
 
1409
1849
  // src/catalogs/animal-classification-models.ts
1410
- var import_types8 = require("@camstack/types");
1411
- var HF_REPO8 = "camstack/camstack-models";
1412
- var hf = (path6) => (0, import_types8.hfModelUrl)(HF_REPO8, path6);
1850
+ var import_types9 = require("@camstack/types");
1851
+ var HF_REPO9 = "camstack/camstack-models";
1852
+ var hf = (path6) => (0, import_types9.hfModelUrl)(HF_REPO9, path6);
1413
1853
  var BIRD_LABEL = { id: "species", name: "Bird Species" };
1414
1854
  var ANIMAL_TYPE_LABEL = { id: "animal-type", name: "Animal Type" };
1415
1855
  var BIRD_SPECIES_MODELS = [
@@ -1422,7 +1862,14 @@ var BIRD_SPECIES_MODELS = [
1422
1862
  labels: [BIRD_LABEL],
1423
1863
  formats: {
1424
1864
  onnx: { url: hf("animalClassification/bird-species/onnx/camstack-bird-species-525.onnx"), sizeMB: 32 }
1425
- }
1865
+ },
1866
+ extraFiles: [
1867
+ {
1868
+ url: hf("animalClassification/bird-species/onnx/camstack-bird-species-525-labels.json"),
1869
+ filename: "camstack-bird-species-525-labels.json",
1870
+ sizeMB: 0.02
1871
+ }
1872
+ ]
1426
1873
  }
1427
1874
  ];
1428
1875
  var BIRD_NABIRDS_MODELS = [
@@ -1435,9 +1882,16 @@ var BIRD_NABIRDS_MODELS = [
1435
1882
  labels: [{ id: "species", name: "Bird Species" }],
1436
1883
  formats: {
1437
1884
  onnx: { url: hf("animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404.onnx"), sizeMB: 93 },
1438
- coreml: { url: hf("animalClassification/bird-nabirds/coreml/camstack-bird-nabirds-404.mlpackage"), sizeMB: 47 },
1439
- openvino: { url: hf("animalClassification/bird-nabirds/openvino/camstack-bird-nabirds-404.xml"), sizeMB: 47 }
1440
- }
1885
+ coreml: { url: hf("animalClassification/bird-nabirds/coreml/camstack-bird-nabirds-404.mlpackage"), sizeMB: 47, isDirectory: true, files: MLPACKAGE_FILES, runtimes: ["python"] },
1886
+ openvino: { url: hf("animalClassification/bird-nabirds/openvino/camstack-bird-nabirds-404.xml"), sizeMB: 47, runtimes: ["python"] }
1887
+ },
1888
+ extraFiles: [
1889
+ {
1890
+ url: hf("animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404-labels.json"),
1891
+ filename: "camstack-bird-nabirds-404-labels.json",
1892
+ sizeMB: 0.02
1893
+ }
1894
+ ]
1441
1895
  }
1442
1896
  ];
1443
1897
  var ANIMAL_TYPE_MODELS = [
@@ -1454,8 +1908,71 @@ var ANIMAL_TYPE_MODELS = [
1454
1908
  }
1455
1909
  ];
1456
1910
 
1911
+ // src/catalogs/vehicle-classification-models.ts
1912
+ var import_types10 = require("@camstack/types");
1913
+ var HF_REPO10 = "camstack/camstack-models";
1914
+ var hf2 = (path6) => (0, import_types10.hfModelUrl)(HF_REPO10, path6);
1915
+ var VEHICLE_LABELS = [
1916
+ { id: "vehicle-type", name: "Vehicle Type" }
1917
+ ];
1918
+ var VEHICLE_TYPE_MODELS = [
1919
+ {
1920
+ id: "vehicle-type-efficientnet",
1921
+ name: "Vehicle Type (EfficientNet)",
1922
+ description: "EfficientNet-B4 vehicle make/model/year classifier \u2014 8,949 classes from VMMRdb",
1923
+ inputSize: { width: 380, height: 380 },
1924
+ inputNormalization: "imagenet",
1925
+ labels: VEHICLE_LABELS,
1926
+ formats: {
1927
+ onnx: { url: hf2("vehicleClassification/efficientnet/onnx/camstack-vehicle-type-efficientnet.onnx"), sizeMB: 135 },
1928
+ coreml: {
1929
+ url: hf2("vehicleClassification/efficientnet/coreml/camstack-vehicle-type-efficientnet.mlpackage"),
1930
+ sizeMB: 10,
1931
+ isDirectory: true,
1932
+ files: ["Manifest.json", "Data/com.apple.CoreML/model.mlmodel", "Data/com.apple.CoreML/weights/weight.bin"],
1933
+ runtimes: ["python"]
1934
+ }
1935
+ },
1936
+ extraFiles: [
1937
+ {
1938
+ url: hf2("vehicleClassification/efficientnet/camstack-vehicle-type-labels.json"),
1939
+ filename: "camstack-vehicle-type-labels.json",
1940
+ sizeMB: 0.2
1941
+ }
1942
+ ]
1943
+ }
1944
+ ];
1945
+
1946
+ // src/catalogs/segmentation-refiner-models.ts
1947
+ var import_types11 = require("@camstack/types");
1948
+ var HF_REPO11 = "camstack/camstack-models";
1949
+ var hf3 = (path6) => (0, import_types11.hfModelUrl)(HF_REPO11, path6);
1950
+ var MASK_LABELS = [
1951
+ { id: "mask", name: "Segmentation Mask" }
1952
+ ];
1953
+ var SEGMENTATION_REFINER_MODELS = [
1954
+ {
1955
+ id: "u2netp",
1956
+ name: "U2-Net Portable",
1957
+ description: "U2-Net-P \u2014 ultra-lightweight salient object segmentation (4.7 MB), no prompt needed",
1958
+ inputSize: { width: 320, height: 320 },
1959
+ labels: MASK_LABELS,
1960
+ formats: {
1961
+ onnx: { url: hf3("segmentationRefiner/u2netp/onnx/camstack-u2netp.onnx"), sizeMB: 5 },
1962
+ coreml: {
1963
+ url: hf3("segmentationRefiner/u2netp/coreml/camstack-u2netp.mlpackage"),
1964
+ sizeMB: 3,
1965
+ isDirectory: true,
1966
+ files: MLPACKAGE_FILES,
1967
+ runtimes: ["python"]
1968
+ }
1969
+ // OpenVINO: not yet converted
1970
+ }
1971
+ }
1972
+ ];
1973
+
1457
1974
  // src/addons/object-detection/index.ts
1458
- var import_types9 = require("@camstack/types");
1975
+ var import_types12 = require("@camstack/types");
1459
1976
 
1460
1977
  // src/shared/postprocess/yolo-seg.ts
1461
1978
  function sigmoid(x) {
@@ -1588,6 +2105,50 @@ function applyClassMap(detections, classMap) {
1588
2105
  class: classMap.mapping[d.class]
1589
2106
  }));
1590
2107
  }
2108
+ var RAM_ESTIMATES = {
2109
+ "yolov8n": 80,
2110
+ "yolov8s": 150,
2111
+ "yolov8s-relu": 150,
2112
+ "yolov8m": 300,
2113
+ "yolov8l": 500,
2114
+ "yolov8x": 800,
2115
+ "yolov9t": 60,
2116
+ "yolov9s": 120,
2117
+ "yolov9c": 300,
2118
+ "yolo11n": 70,
2119
+ "yolo11s": 130,
2120
+ "yolo11m": 280,
2121
+ "yolo11l": 450,
2122
+ "yolo11x": 750,
2123
+ "yolo11n-seg": 84,
2124
+ "yolo11s-seg": 156,
2125
+ "yolo11m-seg": 336,
2126
+ "yolov8n-seg": 96,
2127
+ "yolov8s-seg": 180,
2128
+ "yolov8m-seg": 360
2129
+ };
2130
+ var ACCURACY_SCORES = {
2131
+ "yolov8n": 55,
2132
+ "yolov8s": 70,
2133
+ "yolov8s-relu": 68,
2134
+ "yolov8m": 82,
2135
+ "yolov8l": 88,
2136
+ "yolov8x": 92,
2137
+ "yolov9t": 58,
2138
+ "yolov9s": 73,
2139
+ "yolov9c": 86,
2140
+ "yolo11n": 62,
2141
+ "yolo11s": 78,
2142
+ "yolo11m": 88,
2143
+ "yolo11l": 93,
2144
+ "yolo11x": 97,
2145
+ "yolo11n-seg": 62,
2146
+ "yolo11s-seg": 78,
2147
+ "yolo11m-seg": 88,
2148
+ "yolov8n-seg": 55,
2149
+ "yolov8s-seg": 70,
2150
+ "yolov8m-seg": 82
2151
+ };
1591
2152
  var ObjectDetectionAddon = class {
1592
2153
  id = "object-detection";
1593
2154
  slot = "detector";
@@ -1599,31 +2160,43 @@ var ObjectDetectionAddon = class {
1599
2160
  name: "Object Detection",
1600
2161
  version: "0.1.0",
1601
2162
  description: "YOLO-based object detection \u2014 detects persons, vehicles, and animals",
1602
- packageName: "@camstack/addon-vision",
1603
2163
  slot: "detector",
1604
2164
  inputClasses: void 0,
1605
2165
  outputClasses: ["person", "vehicle", "animal"],
1606
2166
  supportsCustomModels: true,
1607
2167
  mayRequirePython: false,
1608
2168
  defaultConfig: {
1609
- modelId: "yolov8n",
1610
- runtime: "auto",
2169
+ modelId: "yolo11n",
2170
+ runtime: "node",
1611
2171
  backend: "cpu",
1612
2172
  confidence: 0.5,
1613
2173
  iouThreshold: 0.45,
1614
2174
  classMapMode: "macro"
1615
2175
  }
1616
2176
  };
1617
- engine;
2177
+ engine = null;
1618
2178
  modelEntry;
1619
2179
  confidence = 0.5;
1620
2180
  iouThreshold = 0.45;
1621
2181
  classMapMode = "macro";
2182
+ resolvedConfig = null;
2183
+ ctx = null;
2184
+ getModelRequirements() {
2185
+ return ALL_DETECTION_MODELS.map((m) => ({
2186
+ modelId: m.id,
2187
+ name: m.name,
2188
+ minRAM_MB: RAM_ESTIMATES[m.id] ?? 100,
2189
+ accuracyScore: ACCURACY_SCORES[m.id] ?? 60,
2190
+ formats: Object.keys(m.formats)
2191
+ }));
2192
+ }
2193
+ configure(config) {
2194
+ this.resolvedConfig = config;
2195
+ }
1622
2196
  async initialize(ctx) {
2197
+ this.ctx = ctx;
1623
2198
  const cfg = ctx.addonConfig;
1624
- const modelId = cfg["modelId"] ?? "yolov8n";
1625
- const runtime = cfg["runtime"] ?? "auto";
1626
- const backend = cfg["backend"] ?? "cpu";
2199
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "yolo11n";
1627
2200
  this.confidence = cfg["confidence"] ?? 0.5;
1628
2201
  this.iouThreshold = cfg["iouThreshold"] ?? 0.45;
1629
2202
  this.classMapMode = cfg["classMapMode"] ?? "macro";
@@ -1632,16 +2205,30 @@ var ObjectDetectionAddon = class {
1632
2205
  throw new Error(`ObjectDetectionAddon: unknown modelId "${modelId}"`);
1633
2206
  }
1634
2207
  this.modelEntry = entry;
1635
- const resolved = await resolveEngine({
1636
- runtime,
1637
- backend,
1638
- modelEntry: entry,
1639
- modelsDir: ctx.locationPaths.models
1640
- });
1641
- this.engine = resolved.engine;
1642
2208
  }
1643
2209
  async detect(frame) {
2210
+ if (!this.engine) await this.ensureEngine();
1644
2211
  const start = Date.now();
2212
+ if ("runJpeg" in this.engine && typeof this.engine.runJpeg === "function") {
2213
+ const result = await this.engine.runJpeg(frame.data);
2214
+ const rawDets = result.detections ?? [];
2215
+ const detections2 = rawDets.map((d) => ({
2216
+ class: this.classMapMode === "all" ? d.className : import_types12.COCO_TO_MACRO.mapping[d.className] ?? d.className,
2217
+ originalClass: d.className,
2218
+ score: d.score,
2219
+ bbox: {
2220
+ x: d.bbox[0] * frame.width,
2221
+ y: d.bbox[1] * frame.height,
2222
+ w: (d.bbox[2] - d.bbox[0]) * frame.width,
2223
+ h: (d.bbox[3] - d.bbox[1]) * frame.height
2224
+ }
2225
+ })).filter((d) => this.classMapMode === "all" || import_types12.COCO_TO_MACRO.mapping[d.originalClass] !== void 0);
2226
+ return {
2227
+ detections: detections2,
2228
+ inferenceMs: result.inferenceMs ?? Date.now() - start,
2229
+ modelId: this.modelEntry.id
2230
+ };
2231
+ }
1645
2232
  const { width: inputW, height: inputH } = this.modelEntry.inputSize;
1646
2233
  const targetSize = Math.max(inputW, inputH);
1647
2234
  const lb = await letterbox(frame.data, targetSize);
@@ -1689,13 +2276,47 @@ var ObjectDetectionAddon = class {
1689
2276
  const numBoxes = output.length / (4 + numClasses);
1690
2277
  rawDetections = yoloPostprocess(output, numClasses, numBoxes, postprocessOpts);
1691
2278
  }
1692
- const detections = this.classMapMode === "all" ? rawDetections : applyClassMap(rawDetections, import_types9.COCO_TO_MACRO);
2279
+ const detections = this.classMapMode === "all" ? rawDetections : applyClassMap(rawDetections, import_types12.COCO_TO_MACRO);
1693
2280
  return {
1694
2281
  detections,
1695
2282
  inferenceMs: Date.now() - start,
1696
2283
  modelId: this.modelEntry.id
1697
2284
  };
1698
2285
  }
2286
+ async ensureEngine() {
2287
+ const config = this.resolvedConfig;
2288
+ const modelId = config?.modelId ?? this.modelEntry.id;
2289
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
2290
+ const backend = config?.backend ?? "cpu";
2291
+ const format = config?.format ?? "onnx";
2292
+ const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
2293
+ this.modelEntry = entry;
2294
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
2295
+ if (this.ctx.models) {
2296
+ await this.ctx.models.ensure(modelId, format);
2297
+ }
2298
+ let pythonPath;
2299
+ if (config?.runtime === "python") {
2300
+ for (const cmd of ["python3", "python"]) {
2301
+ try {
2302
+ const { execSync } = await import("child_process");
2303
+ execSync(`${cmd} --version`, { timeout: 3e3, stdio: "ignore" });
2304
+ pythonPath = cmd;
2305
+ break;
2306
+ } catch {
2307
+ }
2308
+ }
2309
+ }
2310
+ const resolved = await resolveEngine({
2311
+ runtime,
2312
+ backend,
2313
+ modelEntry: entry,
2314
+ modelsDir,
2315
+ pythonPath,
2316
+ models: this.ctx.models
2317
+ });
2318
+ this.engine = resolved.engine;
2319
+ }
1699
2320
  async shutdown() {
1700
2321
  await this.engine?.dispose();
1701
2322
  }
@@ -1705,7 +2326,7 @@ var ObjectDetectionAddon = class {
1705
2326
  {
1706
2327
  id: "model",
1707
2328
  title: "Model",
1708
- columns: 2,
2329
+ columns: 1,
1709
2330
  fields: [
1710
2331
  {
1711
2332
  key: "modelId",
@@ -1730,7 +2351,7 @@ var ObjectDetectionAddon = class {
1730
2351
  label: "Runtime",
1731
2352
  type: "select",
1732
2353
  options: [
1733
- { value: "auto", label: "Auto (recommended)" },
2354
+ { value: "auto", label: "Auto" },
1734
2355
  { value: "onnx", label: "ONNX Runtime" },
1735
2356
  { value: "coreml", label: "CoreML (Apple)" },
1736
2357
  { value: "openvino", label: "OpenVINO (Intel)" }
@@ -1740,8 +2361,9 @@ var ObjectDetectionAddon = class {
1740
2361
  key: "backend",
1741
2362
  label: "Backend",
1742
2363
  type: "select",
1743
- dependsOn: { runtime: "onnx" },
2364
+ showWhen: { field: "runtime", equals: "onnx" },
1744
2365
  options: [
2366
+ { value: "auto", label: "Auto" },
1745
2367
  { value: "cpu", label: "CPU" },
1746
2368
  { value: "coreml", label: "CoreML" },
1747
2369
  { value: "cuda", label: "CUDA (NVIDIA)" },
@@ -1795,7 +2417,7 @@ var ObjectDetectionAddon = class {
1795
2417
  };
1796
2418
  }
1797
2419
  getClassMap() {
1798
- return import_types9.COCO_TO_MACRO;
2420
+ return import_types12.COCO_TO_MACRO;
1799
2421
  }
1800
2422
  getModelCatalog() {
1801
2423
  return [...ALL_DETECTION_MODELS];
@@ -1804,7 +2426,7 @@ var ObjectDetectionAddon = class {
1804
2426
  return [];
1805
2427
  }
1806
2428
  getActiveLabels() {
1807
- return this.classMapMode === "all" ? import_types9.COCO_80_LABELS : import_types9.MACRO_LABELS;
2429
+ return this.classMapMode === "all" ? import_types12.COCO_80_LABELS : import_types12.MACRO_LABELS;
1808
2430
  }
1809
2431
  async probe() {
1810
2432
  return {
@@ -1816,182 +2438,73 @@ var ObjectDetectionAddon = class {
1816
2438
  }
1817
2439
  };
1818
2440
 
1819
- // src/addons/motion-detection/index.ts
1820
- var MOTION_LABEL = { id: "motion", name: "Motion" };
1821
- var MOTION_LABELS = [MOTION_LABEL];
1822
- var EMPTY_CLASS_MAP = { mapping: {}, preserveOriginal: true };
1823
- var MotionDetectionAddon = class {
1824
- id = "motion-detection";
1825
- slot = "detector";
1826
- inputClasses = null;
1827
- outputClasses = ["motion"];
1828
- slotPriority = 10;
1829
- // runs first — feeds other detectors
2441
+ // src/addons/face-detection/index.ts
2442
+ var FACE_LABEL = { id: "face", name: "Face" };
2443
+ var FACE_LABELS2 = [FACE_LABEL];
2444
+ var FACE_CLASS_MAP = { mapping: {}, preserveOriginal: true };
2445
+ var RAM_ESTIMATES2 = {
2446
+ "scrfd-500m": 50,
2447
+ "scrfd-2.5g": 80,
2448
+ "scrfd-10g": 200
2449
+ };
2450
+ var ACCURACY_SCORES2 = {
2451
+ "scrfd-500m": 70,
2452
+ "scrfd-2.5g": 82,
2453
+ "scrfd-10g": 92
2454
+ };
2455
+ var FaceDetectionAddon = class {
2456
+ id = "face-detection";
2457
+ slot = "cropper";
2458
+ inputClasses = ["person"];
2459
+ outputClasses = ["face"];
2460
+ slotPriority = 0;
1830
2461
  manifest = {
1831
- id: "motion-detection",
1832
- name: "Motion Detection",
2462
+ id: "face-detection",
2463
+ name: "Face Detection",
1833
2464
  version: "0.1.0",
1834
- description: "Frame-differencing motion detector \u2014 no inference engine required",
1835
- packageName: "@camstack/addon-vision",
1836
- slot: "detector",
1837
- inputClasses: void 0,
1838
- outputClasses: ["motion"],
2465
+ description: "SCRFD-based face detector \u2014 crops face regions from person detections",
2466
+ slot: "cropper",
2467
+ inputClasses: ["person"],
2468
+ outputClasses: ["face"],
1839
2469
  supportsCustomModels: false,
1840
2470
  mayRequirePython: false,
1841
2471
  defaultConfig: {
1842
- threshold: 25,
1843
- minArea: 500
2472
+ modelId: "scrfd-500m",
2473
+ runtime: "node",
2474
+ backend: "cpu",
2475
+ confidence: 0.5
1844
2476
  }
1845
2477
  };
1846
- previousGray = null;
1847
- previousWidth = 0;
1848
- previousHeight = 0;
1849
- threshold = 25;
1850
- minArea = 500;
2478
+ engine = null;
2479
+ modelEntry;
2480
+ confidence = 0.5;
2481
+ resolvedConfig = null;
2482
+ ctx = null;
2483
+ getModelRequirements() {
2484
+ return FACE_DETECTION_MODELS.map((m) => ({
2485
+ modelId: m.id,
2486
+ name: m.name,
2487
+ minRAM_MB: RAM_ESTIMATES2[m.id] ?? 50,
2488
+ accuracyScore: ACCURACY_SCORES2[m.id] ?? 70,
2489
+ formats: Object.keys(m.formats)
2490
+ }));
2491
+ }
2492
+ configure(config) {
2493
+ this.resolvedConfig = config;
2494
+ }
1851
2495
  async initialize(ctx) {
2496
+ this.ctx = ctx;
1852
2497
  const cfg = ctx.addonConfig;
1853
- this.threshold = cfg["threshold"] ?? 25;
1854
- this.minArea = cfg["minArea"] ?? 500;
2498
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "scrfd-500m";
2499
+ this.confidence = cfg["confidence"] ?? 0.5;
2500
+ const entry = FACE_DETECTION_MODELS.find((m) => m.id === modelId);
2501
+ if (!entry) {
2502
+ throw new Error(`FaceDetectionAddon: unknown modelId "${modelId}"`);
2503
+ }
2504
+ this.modelEntry = entry;
1855
2505
  }
1856
- async detect(frame) {
1857
- const start = Date.now();
1858
- const { data, width, height } = await jpegToRgb(frame.data);
1859
- const currentGray = rgbToGrayscale(data, width, height);
1860
- if (!this.previousGray || this.previousWidth !== width || this.previousHeight !== height) {
1861
- this.previousGray = currentGray;
1862
- this.previousWidth = width;
1863
- this.previousHeight = height;
1864
- return { detections: [], inferenceMs: Date.now() - start, modelId: "frame-diff" };
1865
- }
1866
- const regions = detectMotion(
1867
- currentGray,
1868
- this.previousGray,
1869
- width,
1870
- height,
1871
- this.threshold,
1872
- this.minArea
1873
- );
1874
- this.previousGray = currentGray;
1875
- const detections = regions.map((r) => ({
1876
- class: "motion",
1877
- originalClass: "motion",
1878
- score: Math.min(1, r.intensity / 255),
1879
- bbox: r.bbox
1880
- }));
1881
- return {
1882
- detections,
1883
- inferenceMs: Date.now() - start,
1884
- modelId: "frame-diff"
1885
- };
1886
- }
1887
- async shutdown() {
1888
- this.previousGray = null;
1889
- }
1890
- getConfigSchema() {
1891
- return {
1892
- sections: [
1893
- {
1894
- id: "motion",
1895
- title: "Motion Detection",
1896
- columns: 2,
1897
- fields: [
1898
- {
1899
- key: "threshold",
1900
- label: "Pixel Difference Threshold",
1901
- description: "Minimum per-pixel intensity change to count as motion (0-255)",
1902
- type: "slider",
1903
- min: 5,
1904
- max: 100,
1905
- step: 5,
1906
- default: 25
1907
- },
1908
- {
1909
- key: "minArea",
1910
- label: "Minimum Region Area (px)",
1911
- description: "Minimum number of changed pixels to report a motion region",
1912
- type: "number",
1913
- min: 50,
1914
- max: 1e4
1915
- }
1916
- ]
1917
- }
1918
- ]
1919
- };
1920
- }
1921
- getClassMap() {
1922
- return EMPTY_CLASS_MAP;
1923
- }
1924
- getModelCatalog() {
1925
- return [];
1926
- }
1927
- getAvailableModels() {
1928
- return [];
1929
- }
1930
- getActiveLabels() {
1931
- return MOTION_LABELS;
1932
- }
1933
- async probe() {
1934
- return {
1935
- available: true,
1936
- runtime: "onnx",
1937
- // no inference; satisfies the type (any runtime works)
1938
- device: "cpu",
1939
- capabilities: ["fp32"]
1940
- };
1941
- }
1942
- };
1943
-
1944
- // src/addons/face-detection/index.ts
1945
- var FACE_LABEL = { id: "face", name: "Face" };
1946
- var FACE_LABELS2 = [FACE_LABEL];
1947
- var FACE_CLASS_MAP = { mapping: {}, preserveOriginal: true };
1948
- var FaceDetectionAddon = class {
1949
- id = "face-detection";
1950
- slot = "cropper";
1951
- inputClasses = ["person"];
1952
- outputClasses = ["face"];
1953
- slotPriority = 0;
1954
- manifest = {
1955
- id: "face-detection",
1956
- name: "Face Detection",
1957
- version: "0.1.0",
1958
- description: "SCRFD-based face detector \u2014 crops face regions from person detections",
1959
- packageName: "@camstack/addon-vision",
1960
- slot: "cropper",
1961
- inputClasses: ["person"],
1962
- outputClasses: ["face"],
1963
- supportsCustomModels: false,
1964
- mayRequirePython: false,
1965
- defaultConfig: {
1966
- modelId: "scrfd-500m",
1967
- runtime: "auto",
1968
- backend: "cpu",
1969
- confidence: 0.5
1970
- }
1971
- };
1972
- engine;
1973
- modelEntry;
1974
- confidence = 0.5;
1975
- async initialize(ctx) {
1976
- const cfg = ctx.addonConfig;
1977
- const modelId = cfg["modelId"] ?? "scrfd-500m";
1978
- const runtime = cfg["runtime"] ?? "auto";
1979
- const backend = cfg["backend"] ?? "cpu";
1980
- this.confidence = cfg["confidence"] ?? 0.5;
1981
- const entry = FACE_DETECTION_MODELS.find((m) => m.id === modelId);
1982
- if (!entry) {
1983
- throw new Error(`FaceDetectionAddon: unknown modelId "${modelId}"`);
1984
- }
1985
- this.modelEntry = entry;
1986
- const resolved = await resolveEngine({
1987
- runtime,
1988
- backend,
1989
- modelEntry: entry,
1990
- modelsDir: ctx.locationPaths.models
1991
- });
1992
- this.engine = resolved.engine;
1993
- }
1994
- async crop(input) {
2506
+ async crop(input) {
2507
+ if (!this.engine) await this.ensureEngine();
1995
2508
  const start = Date.now();
1996
2509
  const { width: inputW, height: inputH } = this.modelEntry.inputSize;
1997
2510
  const targetSize = Math.max(inputW, inputH);
@@ -2018,6 +2531,27 @@ var FaceDetectionAddon = class {
2018
2531
  modelId: this.modelEntry.id
2019
2532
  };
2020
2533
  }
2534
+ async ensureEngine() {
2535
+ const config = this.resolvedConfig;
2536
+ const modelId = config?.modelId ?? this.modelEntry.id;
2537
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
2538
+ const backend = config?.backend ?? "cpu";
2539
+ const format = config?.format ?? "onnx";
2540
+ const entry = FACE_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
2541
+ this.modelEntry = entry;
2542
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
2543
+ if (this.ctx.models) {
2544
+ await this.ctx.models.ensure(modelId, format);
2545
+ }
2546
+ const resolved = await resolveEngine({
2547
+ runtime,
2548
+ backend,
2549
+ modelEntry: entry,
2550
+ modelsDir,
2551
+ models: this.ctx.models
2552
+ });
2553
+ this.engine = resolved.engine;
2554
+ }
2021
2555
  async shutdown() {
2022
2556
  await this.engine?.dispose();
2023
2557
  }
@@ -2042,6 +2576,36 @@ var FaceDetectionAddon = class {
2042
2576
  }
2043
2577
  ]
2044
2578
  },
2579
+ {
2580
+ id: "runtime",
2581
+ title: "Runtime",
2582
+ columns: 2,
2583
+ fields: [
2584
+ {
2585
+ key: "runtime",
2586
+ label: "Runtime",
2587
+ type: "select",
2588
+ options: [
2589
+ { value: "auto", label: "Auto" },
2590
+ { value: "onnx", label: "ONNX Runtime" },
2591
+ { value: "coreml", label: "CoreML (Apple)" },
2592
+ { value: "openvino", label: "OpenVINO (Intel)" }
2593
+ ]
2594
+ },
2595
+ {
2596
+ key: "backend",
2597
+ label: "Backend",
2598
+ type: "select",
2599
+ showWhen: { field: "runtime", equals: "onnx" },
2600
+ options: [
2601
+ { value: "auto", label: "Auto" },
2602
+ { value: "cpu", label: "CPU" },
2603
+ { value: "coreml", label: "CoreML" },
2604
+ { value: "cuda", label: "CUDA (NVIDIA)" }
2605
+ ]
2606
+ }
2607
+ ]
2608
+ },
2045
2609
  {
2046
2610
  id: "thresholds",
2047
2611
  title: "Detection Thresholds",
@@ -2102,8 +2666,8 @@ var FaceRecognitionAddon = class {
2102
2666
  name: "Face Recognition",
2103
2667
  version: "0.1.0",
2104
2668
  description: "ArcFace-based face recognition \u2014 produces 512-d identity embeddings",
2105
- packageName: "@camstack/addon-vision",
2106
2669
  slot: "classifier",
2670
+ labelOutputType: "face",
2107
2671
  inputClasses: ["face"],
2108
2672
  outputClasses: ["identity:*"],
2109
2673
  requiredSteps: REQUIRED_STEPS,
@@ -2111,31 +2675,38 @@ var FaceRecognitionAddon = class {
2111
2675
  mayRequirePython: false,
2112
2676
  defaultConfig: {
2113
2677
  modelId: "arcface-r100",
2114
- runtime: "auto",
2678
+ runtime: "node",
2115
2679
  backend: "cpu"
2116
2680
  }
2117
2681
  };
2118
- engine;
2682
+ engine = null;
2119
2683
  modelEntry;
2684
+ resolvedConfig = null;
2685
+ ctx = null;
2686
+ getModelRequirements() {
2687
+ return FACE_RECOGNITION_MODELS.map((m) => ({
2688
+ modelId: m.id,
2689
+ name: m.name,
2690
+ minRAM_MB: 400,
2691
+ accuracyScore: 90,
2692
+ formats: Object.keys(m.formats)
2693
+ }));
2694
+ }
2695
+ configure(config) {
2696
+ this.resolvedConfig = config;
2697
+ }
2120
2698
  async initialize(ctx) {
2699
+ this.ctx = ctx;
2121
2700
  const cfg = ctx.addonConfig;
2122
- const modelId = cfg["modelId"] ?? "arcface-r100";
2123
- const runtime = cfg["runtime"] ?? "auto";
2124
- const backend = cfg["backend"] ?? "cpu";
2701
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "arcface-r100";
2125
2702
  const entry = FACE_RECOGNITION_MODELS.find((m) => m.id === modelId);
2126
2703
  if (!entry) {
2127
2704
  throw new Error(`FaceRecognitionAddon: unknown modelId "${modelId}"`);
2128
2705
  }
2129
2706
  this.modelEntry = entry;
2130
- const resolved = await resolveEngine({
2131
- runtime,
2132
- backend,
2133
- modelEntry: entry,
2134
- modelsDir: ctx.locationPaths.models
2135
- });
2136
- this.engine = resolved.engine;
2137
2707
  }
2138
2708
  async classify(input) {
2709
+ if (!this.engine) await this.ensureEngine();
2139
2710
  const start = Date.now();
2140
2711
  const { width: inputW, height: inputH } = this.modelEntry.inputSize;
2141
2712
  const faceCrop = await cropRegion(input.frame.data, input.roi);
@@ -2156,6 +2727,27 @@ var FaceRecognitionAddon = class {
2156
2727
  modelId: this.modelEntry.id
2157
2728
  };
2158
2729
  }
2730
+ async ensureEngine() {
2731
+ const config = this.resolvedConfig;
2732
+ const modelId = config?.modelId ?? this.modelEntry.id;
2733
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
2734
+ const backend = config?.backend ?? "cpu";
2735
+ const format = config?.format ?? "onnx";
2736
+ const entry = FACE_RECOGNITION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
2737
+ this.modelEntry = entry;
2738
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
2739
+ if (this.ctx.models) {
2740
+ await this.ctx.models.ensure(modelId, format);
2741
+ }
2742
+ const resolved = await resolveEngine({
2743
+ runtime,
2744
+ backend,
2745
+ modelEntry: entry,
2746
+ modelsDir,
2747
+ models: this.ctx.models
2748
+ });
2749
+ this.engine = resolved.engine;
2750
+ }
2159
2751
  async shutdown() {
2160
2752
  await this.engine?.dispose();
2161
2753
  }
@@ -2190,17 +2782,19 @@ var FaceRecognitionAddon = class {
2190
2782
  label: "Runtime",
2191
2783
  type: "select",
2192
2784
  options: [
2193
- { value: "auto", label: "Auto (recommended)" },
2785
+ { value: "auto", label: "Auto" },
2194
2786
  { value: "onnx", label: "ONNX Runtime" },
2195
- { value: "coreml", label: "CoreML (Apple)" }
2787
+ { value: "coreml", label: "CoreML (Apple)" },
2788
+ { value: "openvino", label: "OpenVINO (Intel)" }
2196
2789
  ]
2197
2790
  },
2198
2791
  {
2199
2792
  key: "backend",
2200
2793
  label: "Backend",
2201
2794
  type: "select",
2202
- dependsOn: { runtime: "onnx" },
2795
+ showWhen: { field: "runtime", equals: "onnx" },
2203
2796
  options: [
2797
+ { value: "auto", label: "Auto" },
2204
2798
  { value: "cpu", label: "CPU" },
2205
2799
  { value: "coreml", label: "CoreML" },
2206
2800
  { value: "cuda", label: "CUDA (NVIDIA)" }
@@ -2248,7 +2842,6 @@ var PlateDetectionAddon = class {
2248
2842
  name: "License Plate Detection",
2249
2843
  version: "0.1.0",
2250
2844
  description: "YOLO-based license plate detector \u2014 crops plate regions from vehicle detections",
2251
- packageName: "@camstack/addon-vision",
2252
2845
  slot: "cropper",
2253
2846
  inputClasses: ["vehicle"],
2254
2847
  outputClasses: ["plate"],
@@ -2256,21 +2849,34 @@ var PlateDetectionAddon = class {
2256
2849
  mayRequirePython: false,
2257
2850
  defaultConfig: {
2258
2851
  modelId: "yolov8n-plate",
2259
- runtime: "auto",
2852
+ runtime: "node",
2260
2853
  backend: "cpu",
2261
2854
  confidence: 0.5,
2262
2855
  iouThreshold: 0.45
2263
2856
  }
2264
2857
  };
2265
- engine;
2858
+ engine = null;
2266
2859
  modelEntry;
2267
2860
  confidence = 0.5;
2268
2861
  iouThreshold = 0.45;
2862
+ resolvedConfig = null;
2863
+ ctx = null;
2864
+ getModelRequirements() {
2865
+ return PLATE_DETECTION_MODELS.map((m) => ({
2866
+ modelId: m.id,
2867
+ name: m.name,
2868
+ minRAM_MB: 80,
2869
+ accuracyScore: 60,
2870
+ formats: Object.keys(m.formats)
2871
+ }));
2872
+ }
2873
+ configure(config) {
2874
+ this.resolvedConfig = config;
2875
+ }
2269
2876
  async initialize(ctx) {
2877
+ this.ctx = ctx;
2270
2878
  const cfg = ctx.addonConfig;
2271
- const modelId = cfg["modelId"] ?? "yolov8n-plate";
2272
- const runtime = cfg["runtime"] ?? "auto";
2273
- const backend = cfg["backend"] ?? "cpu";
2879
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "yolov8n-plate";
2274
2880
  this.confidence = cfg["confidence"] ?? 0.5;
2275
2881
  this.iouThreshold = cfg["iouThreshold"] ?? 0.45;
2276
2882
  const entry = PLATE_DETECTION_MODELS.find((m) => m.id === modelId);
@@ -2278,15 +2884,9 @@ var PlateDetectionAddon = class {
2278
2884
  throw new Error(`PlateDetectionAddon: unknown modelId "${modelId}"`);
2279
2885
  }
2280
2886
  this.modelEntry = entry;
2281
- const resolved = await resolveEngine({
2282
- runtime,
2283
- backend,
2284
- modelEntry: entry,
2285
- modelsDir: ctx.locationPaths.models
2286
- });
2287
- this.engine = resolved.engine;
2288
2887
  }
2289
2888
  async crop(input) {
2889
+ if (!this.engine) await this.ensureEngine();
2290
2890
  const start = Date.now();
2291
2891
  const { width: inputW, height: inputH } = this.modelEntry.inputSize;
2292
2892
  const targetSize = Math.max(inputW, inputH);
@@ -2313,12 +2913,81 @@ var PlateDetectionAddon = class {
2313
2913
  modelId: this.modelEntry.id
2314
2914
  };
2315
2915
  }
2916
+ async ensureEngine() {
2917
+ const config = this.resolvedConfig;
2918
+ const modelId = config?.modelId ?? this.modelEntry.id;
2919
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
2920
+ const backend = config?.backend ?? "cpu";
2921
+ const format = config?.format ?? "onnx";
2922
+ const entry = PLATE_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
2923
+ this.modelEntry = entry;
2924
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
2925
+ if (this.ctx.models) {
2926
+ await this.ctx.models.ensure(modelId, format);
2927
+ }
2928
+ const resolved = await resolveEngine({
2929
+ runtime,
2930
+ backend,
2931
+ modelEntry: entry,
2932
+ modelsDir,
2933
+ models: this.ctx.models
2934
+ });
2935
+ this.engine = resolved.engine;
2936
+ }
2316
2937
  async shutdown() {
2317
2938
  await this.engine?.dispose();
2318
2939
  }
2319
2940
  getConfigSchema() {
2320
2941
  return {
2321
2942
  sections: [
2943
+ {
2944
+ id: "model",
2945
+ title: "Model",
2946
+ columns: 1,
2947
+ fields: [
2948
+ {
2949
+ key: "modelId",
2950
+ label: "Model",
2951
+ type: "model-selector",
2952
+ catalog: [...PLATE_DETECTION_MODELS],
2953
+ allowCustom: false,
2954
+ allowConversion: false,
2955
+ acceptFormats: ["onnx", "coreml", "openvino"],
2956
+ requiredMetadata: ["inputSize", "labels", "outputFormat"],
2957
+ outputFormatHint: "yolo"
2958
+ }
2959
+ ]
2960
+ },
2961
+ {
2962
+ id: "runtime",
2963
+ title: "Runtime",
2964
+ columns: 2,
2965
+ fields: [
2966
+ {
2967
+ key: "runtime",
2968
+ label: "Runtime",
2969
+ type: "select",
2970
+ options: [
2971
+ { value: "auto", label: "Auto" },
2972
+ { value: "onnx", label: "ONNX Runtime" },
2973
+ { value: "coreml", label: "CoreML (Apple)" },
2974
+ { value: "openvino", label: "OpenVINO (Intel)" }
2975
+ ]
2976
+ },
2977
+ {
2978
+ key: "backend",
2979
+ label: "Backend",
2980
+ type: "select",
2981
+ showWhen: { field: "runtime", equals: "onnx" },
2982
+ options: [
2983
+ { value: "auto", label: "Auto" },
2984
+ { value: "cpu", label: "CPU" },
2985
+ { value: "coreml", label: "CoreML" },
2986
+ { value: "cuda", label: "CUDA (NVIDIA)" }
2987
+ ]
2988
+ }
2989
+ ]
2990
+ },
2322
2991
  {
2323
2992
  id: "thresholds",
2324
2993
  title: "Detection Thresholds",
@@ -2379,7 +3048,8 @@ function loadCharset(modelsDir, modelId) {
2379
3048
  const dictNames = [
2380
3049
  `camstack-${modelId}-dict.txt`,
2381
3050
  `camstack-paddleocr-latin-dict.txt`,
2382
- `camstack-paddleocr-en-dict.txt`
3051
+ `camstack-paddleocr-en-dict.txt`,
3052
+ `camstack-crnn-mobilenet-charset.txt`
2383
3053
  ];
2384
3054
  for (const name of dictNames) {
2385
3055
  const dictPath = path3.join(modelsDir, name);
@@ -2390,7 +3060,6 @@ function loadCharset(modelsDir, modelId) {
2390
3060
  }
2391
3061
  throw new Error(`PlateRecognitionAddon: dict.txt not found in ${modelsDir}`);
2392
3062
  }
2393
- var CHARSET = [];
2394
3063
  var REQUIRED_STEPS2 = [
2395
3064
  { slot: "cropper", outputClasses: ["plate"], description: "Requires a plate detector" }
2396
3065
  ];
@@ -2406,8 +3075,8 @@ var PlateRecognitionAddon = class {
2406
3075
  name: "License Plate Recognition (OCR)",
2407
3076
  version: "0.1.0",
2408
3077
  description: "PaddleOCR-based license plate text recognition",
2409
- packageName: "@camstack/addon-vision",
2410
3078
  slot: "classifier",
3079
+ labelOutputType: "plate",
2411
3080
  inputClasses: ["plate"],
2412
3081
  outputClasses: ["plate-text:*"],
2413
3082
  requiredSteps: REQUIRED_STEPS2,
@@ -2415,62 +3084,94 @@ var PlateRecognitionAddon = class {
2415
3084
  mayRequirePython: false,
2416
3085
  defaultConfig: {
2417
3086
  modelId: "paddleocr-latin",
2418
- runtime: "auto",
3087
+ runtime: "node",
2419
3088
  backend: "cpu",
2420
3089
  minConfidence: 0.5
2421
3090
  }
2422
3091
  };
2423
- engine;
3092
+ engine = null;
2424
3093
  modelEntry;
2425
3094
  minConfidence = 0.5;
3095
+ charset = [];
3096
+ resolvedConfig = null;
3097
+ ctx = null;
3098
+ getModelRequirements() {
3099
+ const scores = {
3100
+ "paddleocr-latin": { ram: 100, accuracy: 80 },
3101
+ "paddleocr-en": { ram: 100, accuracy: 80 }
3102
+ };
3103
+ return PLATE_RECOGNITION_MODELS.map((m) => ({
3104
+ modelId: m.id,
3105
+ name: m.name,
3106
+ minRAM_MB: scores[m.id]?.ram ?? 100,
3107
+ accuracyScore: scores[m.id]?.accuracy ?? 75,
3108
+ formats: Object.keys(m.formats)
3109
+ }));
3110
+ }
3111
+ configure(config) {
3112
+ this.resolvedConfig = config;
3113
+ }
2426
3114
  async initialize(ctx) {
3115
+ this.ctx = ctx;
2427
3116
  const cfg = ctx.addonConfig;
2428
- const modelId = cfg["modelId"] ?? "paddleocr-latin";
2429
- const runtime = cfg["runtime"] ?? "auto";
2430
- const backend = cfg["backend"] ?? "cpu";
3117
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "paddleocr-latin";
2431
3118
  this.minConfidence = cfg["minConfidence"] ?? 0.5;
2432
3119
  const entry = PLATE_RECOGNITION_MODELS.find((m) => m.id === modelId);
2433
3120
  if (!entry) {
2434
3121
  throw new Error(`PlateRecognitionAddon: unknown modelId "${modelId}"`);
2435
3122
  }
2436
3123
  this.modelEntry = entry;
2437
- CHARSET = loadCharset(ctx.locationPaths.models, modelId);
2438
- const resolved = await resolveEngine({
2439
- runtime,
2440
- backend,
2441
- modelEntry: entry,
2442
- modelsDir: ctx.locationPaths.models
2443
- });
2444
- this.engine = resolved.engine;
2445
3124
  }
2446
3125
  async classify(input) {
3126
+ if (!this.engine) await this.ensureEngine();
2447
3127
  const start = Date.now();
2448
3128
  const { width: inputW, height: inputH } = this.modelEntry.inputSize;
3129
+ console.log(`[plate-recognition] ROI: x=${input.roi?.x}, y=${input.roi?.y}, w=${input.roi?.w}, h=${input.roi?.h}, frameSize=${input.frame?.data?.length}`);
2449
3130
  const plateCrop = await cropRegion(input.frame.data, input.roi);
3131
+ console.log(`[plate-recognition] Crop size: ${plateCrop.length} bytes`);
3132
+ try {
3133
+ require("fs").writeFileSync("/tmp/plate-recognition-crop.jpg", plateCrop);
3134
+ } catch {
3135
+ }
2450
3136
  const normalized = await resizeAndNormalize(plateCrop, inputW, inputH, "zero-one", "nchw");
2451
3137
  const output = await this.engine.run(normalized, [1, 3, inputH, inputW]);
2452
- const numChars = CHARSET.length;
3138
+ const numChars = this.charset.length;
2453
3139
  const seqLen = output.length / numChars;
2454
- const { text, confidence } = ctcDecode(output, seqLen, numChars, CHARSET);
2455
- if (confidence < this.minConfidence || text.trim().length === 0) {
2456
- return {
2457
- classifications: [],
2458
- inferenceMs: Date.now() - start,
2459
- modelId: this.modelEntry.id
2460
- };
2461
- }
3140
+ const { text, confidence } = ctcDecode(output, seqLen, numChars, this.charset);
2462
3141
  return {
2463
3142
  classifications: [
2464
3143
  {
2465
3144
  class: "plate-text",
2466
3145
  score: confidence,
2467
- text
3146
+ text: text.trim() || "(unreadable)"
2468
3147
  }
2469
3148
  ],
2470
3149
  inferenceMs: Date.now() - start,
2471
3150
  modelId: this.modelEntry.id
2472
3151
  };
2473
3152
  }
3153
+ async ensureEngine() {
3154
+ const config = this.resolvedConfig;
3155
+ const modelId = config?.modelId ?? this.modelEntry.id;
3156
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
3157
+ const backend = config?.backend ?? "cpu";
3158
+ const format = config?.format ?? "onnx";
3159
+ const entry = PLATE_RECOGNITION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
3160
+ this.modelEntry = entry;
3161
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
3162
+ if (this.ctx.models) {
3163
+ await this.ctx.models.ensure(modelId, format);
3164
+ }
3165
+ this.charset = loadCharset(modelsDir, modelId);
3166
+ const resolved = await resolveEngine({
3167
+ runtime,
3168
+ backend,
3169
+ modelEntry: entry,
3170
+ modelsDir,
3171
+ models: this.ctx.models
3172
+ });
3173
+ this.engine = resolved.engine;
3174
+ }
2474
3175
  async shutdown() {
2475
3176
  await this.engine?.dispose();
2476
3177
  }
@@ -2495,6 +3196,34 @@ var PlateRecognitionAddon = class {
2495
3196
  }
2496
3197
  ]
2497
3198
  },
3199
+ {
3200
+ id: "runtime",
3201
+ title: "Runtime",
3202
+ columns: 2,
3203
+ fields: [
3204
+ {
3205
+ key: "runtime",
3206
+ label: "Runtime",
3207
+ type: "select",
3208
+ options: [
3209
+ { value: "auto", label: "Auto" },
3210
+ { value: "onnx", label: "ONNX Runtime" },
3211
+ { value: "openvino", label: "OpenVINO (Intel)" }
3212
+ ]
3213
+ },
3214
+ {
3215
+ key: "backend",
3216
+ label: "Backend",
3217
+ type: "select",
3218
+ showWhen: { field: "runtime", equals: "onnx" },
3219
+ options: [
3220
+ { value: "auto", label: "Auto" },
3221
+ { value: "cpu", label: "CPU" },
3222
+ { value: "cuda", label: "CUDA (NVIDIA)" }
3223
+ ]
3224
+ }
3225
+ ]
3226
+ },
2498
3227
  {
2499
3228
  id: "thresholds",
2500
3229
  title: "Recognition Settings",
@@ -2552,40 +3281,46 @@ var AudioClassificationAddon = class {
2552
3281
  name: "Audio Classification",
2553
3282
  version: "0.1.0",
2554
3283
  description: "YAMNet-based audio event classification from audio waveform",
2555
- packageName: "@camstack/addon-vision",
2556
3284
  slot: "classifier",
3285
+ labelOutputType: "classification",
2557
3286
  inputClasses: void 0,
2558
3287
  outputClasses: ["audio-event:*"],
2559
3288
  supportsCustomModels: false,
2560
3289
  mayRequirePython: false,
2561
3290
  defaultConfig: {
2562
3291
  modelId: "yamnet",
2563
- runtime: "auto",
3292
+ runtime: "node",
2564
3293
  backend: "cpu",
2565
3294
  minScore: 0.3
2566
3295
  }
2567
3296
  };
2568
- engine;
3297
+ engine = null;
2569
3298
  modelEntry;
2570
3299
  minScore = 0.3;
3300
+ resolvedConfig = null;
3301
+ ctx = null;
3302
+ getModelRequirements() {
3303
+ return AUDIO_CLASSIFICATION_MODELS.map((m) => ({
3304
+ modelId: m.id,
3305
+ name: m.name,
3306
+ minRAM_MB: 100,
3307
+ accuracyScore: 80,
3308
+ formats: Object.keys(m.formats)
3309
+ }));
3310
+ }
3311
+ configure(config) {
3312
+ this.resolvedConfig = config;
3313
+ }
2571
3314
  async initialize(ctx) {
3315
+ this.ctx = ctx;
2572
3316
  const cfg = ctx.addonConfig;
2573
- const modelId = cfg["modelId"] ?? "yamnet";
2574
- const runtime = cfg["runtime"] ?? "auto";
2575
- const backend = cfg["backend"] ?? "cpu";
3317
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "yamnet";
2576
3318
  this.minScore = cfg["minScore"] ?? 0.3;
2577
3319
  const entry = AUDIO_CLASSIFICATION_MODELS.find((m) => m.id === modelId);
2578
3320
  if (!entry) {
2579
3321
  throw new Error(`AudioClassificationAddon: unknown modelId "${modelId}"`);
2580
3322
  }
2581
3323
  this.modelEntry = entry;
2582
- const resolved = await resolveEngine({
2583
- runtime,
2584
- backend,
2585
- modelEntry: entry,
2586
- modelsDir: ctx.locationPaths.models
2587
- });
2588
- this.engine = resolved.engine;
2589
3324
  }
2590
3325
  /**
2591
3326
  * classify() receives a CropInput but internally treats input.frame.data as raw audio context.
@@ -2595,6 +3330,7 @@ var AudioClassificationAddon = class {
2595
3330
  * The CropInput.roi is not used for audio — it is ignored.
2596
3331
  */
2597
3332
  async classify(input) {
3333
+ if (!this.engine) await this.ensureEngine();
2598
3334
  const start = Date.now();
2599
3335
  const buf = input.frame.data;
2600
3336
  const numSamples = Math.floor(buf.length / 4);
@@ -2625,12 +3361,51 @@ var AudioClassificationAddon = class {
2625
3361
  modelId: this.modelEntry.id
2626
3362
  };
2627
3363
  }
3364
+ async ensureEngine() {
3365
+ const config = this.resolvedConfig;
3366
+ const modelId = config?.modelId ?? this.modelEntry.id;
3367
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
3368
+ const backend = config?.backend ?? "cpu";
3369
+ const format = config?.format ?? "onnx";
3370
+ const entry = AUDIO_CLASSIFICATION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
3371
+ this.modelEntry = entry;
3372
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
3373
+ if (this.ctx.models) {
3374
+ await this.ctx.models.ensure(modelId, format);
3375
+ }
3376
+ const resolved = await resolveEngine({
3377
+ runtime,
3378
+ backend,
3379
+ modelEntry: entry,
3380
+ modelsDir,
3381
+ models: this.ctx.models
3382
+ });
3383
+ this.engine = resolved.engine;
3384
+ }
2628
3385
  async shutdown() {
2629
3386
  await this.engine?.dispose();
2630
3387
  }
2631
3388
  getConfigSchema() {
2632
3389
  return {
2633
3390
  sections: [
3391
+ {
3392
+ id: "model",
3393
+ title: "Model",
3394
+ columns: 1,
3395
+ fields: [
3396
+ {
3397
+ key: "modelId",
3398
+ label: "Model",
3399
+ type: "model-selector",
3400
+ catalog: [...AUDIO_CLASSIFICATION_MODELS],
3401
+ allowCustom: false,
3402
+ allowConversion: false,
3403
+ acceptFormats: ["onnx", "openvino"],
3404
+ requiredMetadata: ["inputSize", "labels", "outputFormat"],
3405
+ outputFormatHint: "classification"
3406
+ }
3407
+ ]
3408
+ },
2634
3409
  {
2635
3410
  id: "runtime",
2636
3411
  title: "Runtime",
@@ -2641,8 +3416,9 @@ var AudioClassificationAddon = class {
2641
3416
  label: "Runtime",
2642
3417
  type: "select",
2643
3418
  options: [
2644
- { value: "auto", label: "Auto (recommended)" },
3419
+ { value: "auto", label: "Auto" },
2645
3420
  { value: "onnx", label: "ONNX Runtime" },
3421
+ { value: "coreml", label: "CoreML (Apple)" },
2646
3422
  { value: "openvino", label: "OpenVINO (Intel)" }
2647
3423
  ]
2648
3424
  },
@@ -2650,9 +3426,11 @@ var AudioClassificationAddon = class {
2650
3426
  key: "backend",
2651
3427
  label: "Backend",
2652
3428
  type: "select",
2653
- dependsOn: { runtime: "onnx" },
3429
+ showWhen: { field: "runtime", equals: "onnx" },
2654
3430
  options: [
3431
+ { value: "auto", label: "Auto" },
2655
3432
  { value: "cpu", label: "CPU" },
3433
+ { value: "coreml", label: "CoreML" },
2656
3434
  { value: "cuda", label: "CUDA (NVIDIA)" }
2657
3435
  ]
2658
3436
  }
@@ -2699,81 +3477,6 @@ var AudioClassificationAddon = class {
2699
3477
  }
2700
3478
  };
2701
3479
 
2702
- // src/addons/camera-native-detection/index.ts
2703
- var NATIVE_LABELS = [
2704
- { id: "person", name: "Person" },
2705
- { id: "vehicle", name: "Vehicle" },
2706
- { id: "motion", name: "Motion" },
2707
- { id: "face", name: "Face" }
2708
- ];
2709
- var NATIVE_CLASS_MAP = { mapping: {}, preserveOriginal: true };
2710
- var CameraNativeDetectionAddon = class {
2711
- id = "camera-native-detection";
2712
- slot = "detector";
2713
- inputClasses = null;
2714
- outputClasses = ["person", "vehicle", "motion", "face"];
2715
- slotPriority = 5;
2716
- manifest = {
2717
- id: "camera-native-detection",
2718
- name: "Camera Native Detection",
2719
- version: "0.1.0",
2720
- description: "Passthrough adapter for camera-native events (Frigate, Scrypted, ONVIF) \u2014 no inference engine",
2721
- packageName: "@camstack/addon-vision",
2722
- slot: "detector",
2723
- inputClasses: void 0,
2724
- outputClasses: ["person", "vehicle", "motion", "face"],
2725
- supportsCustomModels: false,
2726
- mayRequirePython: false,
2727
- defaultConfig: {}
2728
- };
2729
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2730
- async initialize(_ctx) {
2731
- }
2732
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2733
- async detect(_frame) {
2734
- return {
2735
- detections: [],
2736
- inferenceMs: 0,
2737
- modelId: "camera-native"
2738
- };
2739
- }
2740
- async shutdown() {
2741
- }
2742
- getConfigSchema() {
2743
- return {
2744
- sections: [
2745
- {
2746
- id: "info",
2747
- title: "Camera Native Detection",
2748
- description: "This addon forwards detections from native camera events (Frigate webhooks, Scrypted push notifications, ONVIF events). No configuration required.",
2749
- fields: []
2750
- }
2751
- ]
2752
- };
2753
- }
2754
- getClassMap() {
2755
- return NATIVE_CLASS_MAP;
2756
- }
2757
- getModelCatalog() {
2758
- return [];
2759
- }
2760
- getAvailableModels() {
2761
- return [];
2762
- }
2763
- getActiveLabels() {
2764
- return NATIVE_LABELS;
2765
- }
2766
- async probe() {
2767
- return {
2768
- available: true,
2769
- runtime: "onnx",
2770
- // no runtime used; satisfies the type
2771
- device: "cpu",
2772
- capabilities: ["fp32"]
2773
- };
2774
- }
2775
- };
2776
-
2777
3480
  // src/addons/bird-global-classifier/index.ts
2778
3481
  var fs3 = __toESM(require("fs"));
2779
3482
  var path4 = __toESM(require("path"));
@@ -2812,44 +3515,50 @@ var BirdGlobalClassifierAddon = class {
2812
3515
  name: "Bird Classifier (Global, 525 species)",
2813
3516
  version: "0.1.0",
2814
3517
  description: "EfficientNet \u2014 525 worldwide bird species (MIT license, ONNX only)",
2815
- packageName: "@camstack/addon-vision",
2816
3518
  slot: "classifier",
3519
+ labelOutputType: "classification",
2817
3520
  inputClasses: ["animal"],
2818
3521
  outputClasses: ["species:*"],
2819
3522
  supportsCustomModels: false,
2820
3523
  mayRequirePython: false,
2821
3524
  defaultConfig: {
2822
3525
  modelId: "bird-species-525",
2823
- runtime: "auto",
3526
+ runtime: "node",
2824
3527
  backend: "cpu",
2825
3528
  minConfidence: 0.3
2826
3529
  }
2827
3530
  };
2828
- engine;
3531
+ engine = null;
2829
3532
  modelEntry;
2830
3533
  labels = [];
2831
3534
  minConfidence = 0.3;
3535
+ resolvedConfig = null;
3536
+ ctx = null;
3537
+ getModelRequirements() {
3538
+ return BIRD_SPECIES_MODELS.map((m) => ({
3539
+ modelId: m.id,
3540
+ name: m.name,
3541
+ minRAM_MB: 120,
3542
+ accuracyScore: 80,
3543
+ formats: Object.keys(m.formats)
3544
+ }));
3545
+ }
3546
+ configure(config) {
3547
+ this.resolvedConfig = config;
3548
+ }
2832
3549
  async initialize(ctx) {
3550
+ this.ctx = ctx;
2833
3551
  const cfg = ctx.addonConfig;
2834
- const modelId = cfg["modelId"] ?? "bird-species-525";
2835
- const runtime = cfg["runtime"] ?? "auto";
2836
- const backend = cfg["backend"] ?? "cpu";
3552
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "bird-species-525";
2837
3553
  this.minConfidence = cfg["minConfidence"] ?? 0.3;
2838
3554
  const entry = BIRD_SPECIES_MODELS.find((m) => m.id === modelId);
2839
3555
  if (!entry) {
2840
3556
  throw new Error(`BirdGlobalClassifierAddon: unknown modelId "${modelId}"`);
2841
3557
  }
2842
3558
  this.modelEntry = entry;
2843
- this.labels = loadLabels(ctx.locationPaths.models, modelId);
2844
- const resolved = await resolveEngine({
2845
- runtime,
2846
- backend,
2847
- modelEntry: entry,
2848
- modelsDir: ctx.locationPaths.models
2849
- });
2850
- this.engine = resolved.engine;
2851
3559
  }
2852
3560
  async classify(input) {
3561
+ if (!this.engine) await this.ensureEngine();
2853
3562
  const start = Date.now();
2854
3563
  const { width: inputW, height: inputH } = this.modelEntry.inputSize;
2855
3564
  const animalCrop = await cropRegion(input.frame.data, input.roi);
@@ -2884,6 +3593,28 @@ var BirdGlobalClassifierAddon = class {
2884
3593
  modelId: this.modelEntry.id
2885
3594
  };
2886
3595
  }
3596
+ async ensureEngine() {
3597
+ const config = this.resolvedConfig;
3598
+ const modelId = config?.modelId ?? this.modelEntry.id;
3599
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
3600
+ const backend = config?.backend ?? "cpu";
3601
+ const format = config?.format ?? "onnx";
3602
+ const entry = BIRD_SPECIES_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
3603
+ this.modelEntry = entry;
3604
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
3605
+ if (this.ctx.models) {
3606
+ await this.ctx.models.ensure(modelId, format);
3607
+ }
3608
+ this.labels = loadLabels(modelsDir, modelId);
3609
+ const resolved = await resolveEngine({
3610
+ runtime,
3611
+ backend,
3612
+ modelEntry: entry,
3613
+ modelsDir,
3614
+ models: this.ctx.models
3615
+ });
3616
+ this.engine = resolved.engine;
3617
+ }
2887
3618
  async shutdown() {
2888
3619
  await this.engine?.dispose();
2889
3620
  }
@@ -2908,22 +3639,6 @@ var BirdGlobalClassifierAddon = class {
2908
3639
  }
2909
3640
  ]
2910
3641
  },
2911
- {
2912
- id: "thresholds",
2913
- title: "Classification Settings",
2914
- columns: 1,
2915
- fields: [
2916
- {
2917
- key: "minConfidence",
2918
- label: "Minimum Confidence",
2919
- type: "slider",
2920
- min: 0.05,
2921
- max: 1,
2922
- step: 0.05,
2923
- default: 0.3
2924
- }
2925
- ]
2926
- },
2927
3642
  {
2928
3643
  id: "runtime",
2929
3644
  title: "Runtime",
@@ -2934,23 +3649,41 @@ var BirdGlobalClassifierAddon = class {
2934
3649
  label: "Runtime",
2935
3650
  type: "select",
2936
3651
  options: [
2937
- { value: "auto", label: "Auto (recommended)" },
3652
+ { value: "auto", label: "Auto" },
2938
3653
  { value: "onnx", label: "ONNX Runtime" },
2939
- { value: "coreml", label: "CoreML (Apple)" }
3654
+ { value: "coreml", label: "CoreML (Apple)" },
3655
+ { value: "openvino", label: "OpenVINO (Intel)" }
2940
3656
  ]
2941
3657
  },
2942
3658
  {
2943
3659
  key: "backend",
2944
3660
  label: "Backend",
2945
3661
  type: "select",
2946
- dependsOn: { runtime: "onnx" },
3662
+ showWhen: { field: "runtime", equals: "onnx" },
2947
3663
  options: [
3664
+ { value: "auto", label: "Auto" },
2948
3665
  { value: "cpu", label: "CPU" },
2949
3666
  { value: "coreml", label: "CoreML" },
2950
3667
  { value: "cuda", label: "CUDA (NVIDIA)" }
2951
3668
  ]
2952
3669
  }
2953
3670
  ]
3671
+ },
3672
+ {
3673
+ id: "thresholds",
3674
+ title: "Classification Settings",
3675
+ columns: 1,
3676
+ fields: [
3677
+ {
3678
+ key: "minConfidence",
3679
+ label: "Minimum Confidence",
3680
+ type: "slider",
3681
+ min: 0.05,
3682
+ max: 1,
3683
+ step: 0.05,
3684
+ default: 0.3
3685
+ }
3686
+ ]
2954
3687
  }
2955
3688
  ]
2956
3689
  };
@@ -3015,29 +3748,42 @@ var BirdNABirdsClassifierAddon = class {
3015
3748
  name: "Bird Classifier (NABirds, 404 species)",
3016
3749
  version: "0.1.0",
3017
3750
  description: "ResNet50 \u2014 404 North American bird species (NABirds dataset, ONNX + CoreML + OpenVINO)",
3018
- packageName: "@camstack/addon-vision",
3019
3751
  slot: "classifier",
3752
+ labelOutputType: "classification",
3020
3753
  inputClasses: ["animal"],
3021
3754
  outputClasses: ["species:*"],
3022
3755
  supportsCustomModels: false,
3023
3756
  mayRequirePython: false,
3024
3757
  defaultConfig: {
3025
3758
  modelId: "bird-nabirds-404",
3026
- runtime: "auto",
3759
+ runtime: "node",
3027
3760
  backend: "cpu",
3028
3761
  minConfidence: 0.3
3029
3762
  }
3030
3763
  };
3031
- engine;
3764
+ engine = null;
3032
3765
  modelEntry;
3033
3766
  labels = [];
3034
3767
  minConfidence = 0.3;
3035
3768
  allowedSpecies;
3769
+ resolvedConfig = null;
3770
+ ctx = null;
3771
+ getModelRequirements() {
3772
+ return BIRD_NABIRDS_MODELS.map((m) => ({
3773
+ modelId: m.id,
3774
+ name: m.name,
3775
+ minRAM_MB: 300,
3776
+ accuracyScore: 80,
3777
+ formats: Object.keys(m.formats)
3778
+ }));
3779
+ }
3780
+ configure(config) {
3781
+ this.resolvedConfig = config;
3782
+ }
3036
3783
  async initialize(ctx) {
3784
+ this.ctx = ctx;
3037
3785
  const cfg = ctx.addonConfig;
3038
- const modelId = cfg["modelId"] ?? "bird-nabirds-404";
3039
- const runtime = cfg["runtime"] ?? "auto";
3040
- const backend = cfg["backend"] ?? "cpu";
3786
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "bird-nabirds-404";
3041
3787
  this.minConfidence = cfg["minConfidence"] ?? 0.3;
3042
3788
  this.allowedSpecies = cfg["allowedSpecies"];
3043
3789
  const entry = BIRD_NABIRDS_MODELS.find((m) => m.id === modelId);
@@ -3045,14 +3791,6 @@ var BirdNABirdsClassifierAddon = class {
3045
3791
  throw new Error(`BirdNABirdsClassifierAddon: unknown modelId "${modelId}"`);
3046
3792
  }
3047
3793
  this.modelEntry = entry;
3048
- this.labels = loadLabels2(ctx.locationPaths.models, modelId);
3049
- const resolved = await resolveEngine({
3050
- runtime,
3051
- backend,
3052
- modelEntry: entry,
3053
- modelsDir: ctx.locationPaths.models
3054
- });
3055
- this.engine = resolved.engine;
3056
3794
  }
3057
3795
  applyRegionFilter(scores, labels) {
3058
3796
  if (!this.allowedSpecies || this.allowedSpecies.length === 0) return;
@@ -3064,6 +3802,7 @@ var BirdNABirdsClassifierAddon = class {
3064
3802
  }
3065
3803
  }
3066
3804
  async classify(input) {
3805
+ if (!this.engine) await this.ensureEngine();
3067
3806
  const start = Date.now();
3068
3807
  const { width: inputW, height: inputH } = this.modelEntry.inputSize;
3069
3808
  const animalCrop = await cropRegion(input.frame.data, input.roi);
@@ -3105,6 +3844,28 @@ var BirdNABirdsClassifierAddon = class {
3105
3844
  modelId: this.modelEntry.id
3106
3845
  };
3107
3846
  }
3847
+ async ensureEngine() {
3848
+ const config = this.resolvedConfig;
3849
+ const modelId = config?.modelId ?? this.modelEntry.id;
3850
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
3851
+ const backend = config?.backend ?? "cpu";
3852
+ const format = config?.format ?? "onnx";
3853
+ const entry = BIRD_NABIRDS_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
3854
+ this.modelEntry = entry;
3855
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
3856
+ if (this.ctx.models) {
3857
+ await this.ctx.models.ensure(modelId, format);
3858
+ }
3859
+ this.labels = loadLabels2(modelsDir, modelId);
3860
+ const resolved = await resolveEngine({
3861
+ runtime,
3862
+ backend,
3863
+ modelEntry: entry,
3864
+ modelsDir,
3865
+ models: this.ctx.models
3866
+ });
3867
+ this.engine = resolved.engine;
3868
+ }
3108
3869
  async shutdown() {
3109
3870
  await this.engine?.dispose();
3110
3871
  }
@@ -3129,6 +3890,36 @@ var BirdNABirdsClassifierAddon = class {
3129
3890
  }
3130
3891
  ]
3131
3892
  },
3893
+ {
3894
+ id: "runtime",
3895
+ title: "Runtime",
3896
+ columns: 2,
3897
+ fields: [
3898
+ {
3899
+ key: "runtime",
3900
+ label: "Runtime",
3901
+ type: "select",
3902
+ options: [
3903
+ { value: "auto", label: "Auto" },
3904
+ { value: "onnx", label: "ONNX Runtime" },
3905
+ { value: "coreml", label: "CoreML (Apple)" },
3906
+ { value: "openvino", label: "OpenVINO (Intel)" }
3907
+ ]
3908
+ },
3909
+ {
3910
+ key: "backend",
3911
+ label: "Backend",
3912
+ type: "select",
3913
+ showWhen: { field: "runtime", equals: "onnx" },
3914
+ options: [
3915
+ { value: "auto", label: "Auto" },
3916
+ { value: "cpu", label: "CPU" },
3917
+ { value: "coreml", label: "CoreML" },
3918
+ { value: "cuda", label: "CUDA (NVIDIA)" }
3919
+ ]
3920
+ }
3921
+ ]
3922
+ },
3132
3923
  {
3133
3924
  id: "thresholds",
3134
3925
  title: "Classification Settings",
@@ -3167,35 +3958,6 @@ var BirdNABirdsClassifierAddon = class {
3167
3958
  type: "text"
3168
3959
  }
3169
3960
  ]
3170
- },
3171
- {
3172
- id: "runtime",
3173
- title: "Runtime",
3174
- columns: 2,
3175
- fields: [
3176
- {
3177
- key: "runtime",
3178
- label: "Runtime",
3179
- type: "select",
3180
- options: [
3181
- { value: "auto", label: "Auto (recommended)" },
3182
- { value: "onnx", label: "ONNX Runtime" },
3183
- { value: "coreml", label: "CoreML (Apple)" },
3184
- { value: "openvino", label: "OpenVINO (Intel)" }
3185
- ]
3186
- },
3187
- {
3188
- key: "backend",
3189
- label: "Backend",
3190
- type: "select",
3191
- dependsOn: { runtime: "onnx" },
3192
- options: [
3193
- { value: "cpu", label: "CPU" },
3194
- { value: "coreml", label: "CoreML" },
3195
- { value: "cuda", label: "CUDA (NVIDIA)" }
3196
- ]
3197
- }
3198
- ]
3199
3961
  }
3200
3962
  ]
3201
3963
  };
@@ -3256,42 +4018,49 @@ var AnimalClassifierAddon = class {
3256
4018
  name: "Animal Classifier",
3257
4019
  version: "0.1.0",
3258
4020
  description: "ViT-based animal type classifier \u2014 10 common species",
3259
- packageName: "@camstack/addon-vision",
3260
4021
  slot: "classifier",
4022
+ labelOutputType: "classification",
3261
4023
  inputClasses: ["animal"],
3262
4024
  outputClasses: ["animal-type:*"],
3263
4025
  supportsCustomModels: false,
3264
4026
  mayRequirePython: false,
3265
4027
  defaultConfig: {
3266
4028
  modelId: "animals-10",
3267
- runtime: "auto",
4029
+ runtime: "node",
3268
4030
  backend: "cpu",
3269
4031
  minConfidence: 0.3
3270
4032
  }
3271
4033
  };
3272
- engine;
4034
+ engine = null;
3273
4035
  modelEntry;
3274
4036
  minConfidence = 0.3;
4037
+ resolvedConfig = null;
4038
+ ctx = null;
4039
+ getModelRequirements() {
4040
+ return ANIMAL_TYPE_MODELS.map((m) => ({
4041
+ modelId: m.id,
4042
+ name: m.name,
4043
+ minRAM_MB: 800,
4044
+ accuracyScore: 75,
4045
+ formats: Object.keys(m.formats)
4046
+ }));
4047
+ }
4048
+ configure(config) {
4049
+ this.resolvedConfig = config;
4050
+ }
3275
4051
  async initialize(ctx) {
4052
+ this.ctx = ctx;
3276
4053
  const cfg = ctx.addonConfig;
3277
- const modelId = cfg["modelId"] ?? "animals-10";
3278
- const runtime = cfg["runtime"] ?? "auto";
3279
- const backend = cfg["backend"] ?? "cpu";
4054
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "animals-10";
3280
4055
  this.minConfidence = cfg["minConfidence"] ?? 0.3;
3281
4056
  const entry = ANIMAL_TYPE_MODELS.find((m) => m.id === modelId);
3282
4057
  if (!entry) {
3283
4058
  throw new Error(`AnimalClassifierAddon: unknown modelId "${modelId}"`);
3284
4059
  }
3285
4060
  this.modelEntry = entry;
3286
- const resolved = await resolveEngine({
3287
- runtime,
3288
- backend,
3289
- modelEntry: entry,
3290
- modelsDir: ctx.locationPaths.models
3291
- });
3292
- this.engine = resolved.engine;
3293
4061
  }
3294
4062
  async classify(input) {
4063
+ if (!this.engine) await this.ensureEngine();
3295
4064
  const start = Date.now();
3296
4065
  const { width: inputW, height: inputH } = this.modelEntry.inputSize;
3297
4066
  const animalCrop = await cropRegion(input.frame.data, input.roi);
@@ -3326,6 +4095,27 @@ var AnimalClassifierAddon = class {
3326
4095
  modelId: this.modelEntry.id
3327
4096
  };
3328
4097
  }
4098
+ async ensureEngine() {
4099
+ const config = this.resolvedConfig;
4100
+ const modelId = config?.modelId ?? this.modelEntry.id;
4101
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
4102
+ const backend = config?.backend ?? "cpu";
4103
+ const format = config?.format ?? "onnx";
4104
+ const entry = ANIMAL_TYPE_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
4105
+ this.modelEntry = entry;
4106
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
4107
+ if (this.ctx.models) {
4108
+ await this.ctx.models.ensure(modelId, format);
4109
+ }
4110
+ const resolved = await resolveEngine({
4111
+ runtime,
4112
+ backend,
4113
+ modelEntry: entry,
4114
+ modelsDir,
4115
+ models: this.ctx.models
4116
+ });
4117
+ this.engine = resolved.engine;
4118
+ }
3329
4119
  async shutdown() {
3330
4120
  await this.engine?.dispose();
3331
4121
  }
@@ -3350,22 +4140,6 @@ var AnimalClassifierAddon = class {
3350
4140
  }
3351
4141
  ]
3352
4142
  },
3353
- {
3354
- id: "thresholds",
3355
- title: "Classification Settings",
3356
- columns: 1,
3357
- fields: [
3358
- {
3359
- key: "minConfidence",
3360
- label: "Minimum Confidence",
3361
- type: "slider",
3362
- min: 0.05,
3363
- max: 1,
3364
- step: 0.05,
3365
- default: 0.3
3366
- }
3367
- ]
3368
- },
3369
4143
  {
3370
4144
  id: "runtime",
3371
4145
  title: "Runtime",
@@ -3376,23 +4150,41 @@ var AnimalClassifierAddon = class {
3376
4150
  label: "Runtime",
3377
4151
  type: "select",
3378
4152
  options: [
3379
- { value: "auto", label: "Auto (recommended)" },
4153
+ { value: "auto", label: "Auto" },
3380
4154
  { value: "onnx", label: "ONNX Runtime" },
3381
- { value: "coreml", label: "CoreML (Apple)" }
4155
+ { value: "coreml", label: "CoreML (Apple)" },
4156
+ { value: "openvino", label: "OpenVINO (Intel)" }
3382
4157
  ]
3383
4158
  },
3384
4159
  {
3385
4160
  key: "backend",
3386
4161
  label: "Backend",
3387
4162
  type: "select",
3388
- dependsOn: { runtime: "onnx" },
4163
+ showWhen: { field: "runtime", equals: "onnx" },
3389
4164
  options: [
4165
+ { value: "auto", label: "Auto" },
3390
4166
  { value: "cpu", label: "CPU" },
3391
4167
  { value: "coreml", label: "CoreML" },
3392
4168
  { value: "cuda", label: "CUDA (NVIDIA)" }
3393
4169
  ]
3394
4170
  }
3395
4171
  ]
4172
+ },
4173
+ {
4174
+ id: "thresholds",
4175
+ title: "Classification Settings",
4176
+ columns: 1,
4177
+ fields: [
4178
+ {
4179
+ key: "minConfidence",
4180
+ label: "Minimum Confidence",
4181
+ type: "slider",
4182
+ min: 0.05,
4183
+ max: 1,
4184
+ step: 0.05,
4185
+ default: 0.3
4186
+ }
4187
+ ]
3396
4188
  }
3397
4189
  ]
3398
4190
  };
@@ -3428,12 +4220,12 @@ var AnimalClassifierAddon = class {
3428
4220
  BIRD_SPECIES_MODELS,
3429
4221
  BirdGlobalClassifierAddon,
3430
4222
  BirdNABirdsClassifierAddon,
3431
- CameraNativeDetectionAddon,
3432
4223
  FACE_DETECTION_MODELS,
3433
4224
  FACE_RECOGNITION_MODELS,
3434
4225
  FaceDetectionAddon,
3435
4226
  FaceRecognitionAddon,
3436
- MotionDetectionAddon,
4227
+ GENERAL_OCR_MODELS,
4228
+ MLPACKAGE_FILES,
3437
4229
  NodeInferenceEngine,
3438
4230
  OBJECT_DETECTION_MODELS,
3439
4231
  ObjectDetectionAddon,
@@ -3443,6 +4235,8 @@ var AnimalClassifierAddon = class {
3443
4235
  PlateRecognitionAddon,
3444
4236
  PythonInferenceEngine,
3445
4237
  SEGMENTATION_MODELS,
4238
+ SEGMENTATION_REFINER_MODELS,
4239
+ VEHICLE_TYPE_MODELS,
3446
4240
  cosineSimilarity,
3447
4241
  cropRegion,
3448
4242
  ctcDecode,