@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.
- package/dist/addons/animal-classifier/index.d.mts +6 -1
- package/dist/addons/animal-classifier/index.d.ts +6 -1
- package/dist/addons/animal-classifier/index.js +514 -49
- package/dist/addons/animal-classifier/index.js.map +1 -1
- package/dist/addons/animal-classifier/index.mjs +6 -4
- package/dist/addons/audio-classification/index.d.mts +6 -1
- package/dist/addons/audio-classification/index.d.ts +6 -1
- package/dist/addons/audio-classification/index.js +87 -26
- package/dist/addons/audio-classification/index.js.map +1 -1
- package/dist/addons/audio-classification/index.mjs +3 -2
- package/dist/addons/bird-global-classifier/index.d.mts +6 -1
- package/dist/addons/bird-global-classifier/index.d.ts +6 -1
- package/dist/addons/bird-global-classifier/index.js +515 -50
- package/dist/addons/bird-global-classifier/index.js.map +1 -1
- package/dist/addons/bird-global-classifier/index.mjs +6 -4
- package/dist/addons/bird-nabirds-classifier/index.d.mts +6 -1
- package/dist/addons/bird-nabirds-classifier/index.d.ts +6 -1
- package/dist/addons/bird-nabirds-classifier/index.js +524 -60
- package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
- package/dist/addons/bird-nabirds-classifier/index.mjs +6 -4
- package/dist/addons/face-detection/index.d.mts +6 -1
- package/dist/addons/face-detection/index.d.ts +6 -1
- package/dist/addons/face-detection/index.js +539 -39
- package/dist/addons/face-detection/index.js.map +1 -1
- package/dist/addons/face-detection/index.mjs +5 -3
- package/dist/addons/face-recognition/index.d.mts +6 -1
- package/dist/addons/face-recognition/index.d.ts +6 -1
- package/dist/addons/face-recognition/index.js +488 -33
- package/dist/addons/face-recognition/index.js.map +1 -1
- package/dist/addons/face-recognition/index.mjs +5 -3
- package/dist/addons/motion-detection/index.d.mts +3 -1
- package/dist/addons/motion-detection/index.d.ts +3 -1
- package/dist/addons/motion-detection/index.js +11 -3
- package/dist/addons/motion-detection/index.js.map +1 -1
- package/dist/addons/motion-detection/index.mjs +140 -3
- package/dist/addons/motion-detection/index.mjs.map +1 -1
- package/dist/addons/object-detection/index.d.mts +6 -1
- package/dist/addons/object-detection/index.d.ts +6 -1
- package/dist/addons/object-detection/index.js +370 -72
- package/dist/addons/object-detection/index.js.map +1 -1
- package/dist/addons/object-detection/index.mjs +5 -3
- package/dist/addons/plate-detection/index.d.mts +6 -1
- package/dist/addons/plate-detection/index.d.ts +6 -1
- package/dist/addons/plate-detection/index.js +532 -31
- package/dist/addons/plate-detection/index.js.map +1 -1
- package/dist/addons/plate-detection/index.mjs +5 -3
- package/dist/addons/plate-recognition/index.d.mts +7 -1
- package/dist/addons/plate-recognition/index.d.ts +7 -1
- package/dist/addons/plate-recognition/index.js +177 -44
- package/dist/addons/plate-recognition/index.js.map +1 -1
- package/dist/addons/plate-recognition/index.mjs +4 -3
- package/dist/addons/segmentation-refiner/index.d.mts +30 -0
- package/dist/addons/segmentation-refiner/index.d.ts +30 -0
- package/dist/addons/segmentation-refiner/index.js +1049 -0
- package/dist/addons/segmentation-refiner/index.js.map +1 -0
- package/dist/addons/segmentation-refiner/index.mjs +209 -0
- package/dist/addons/segmentation-refiner/index.mjs.map +1 -0
- package/dist/addons/vehicle-classifier/index.d.mts +31 -0
- package/dist/addons/vehicle-classifier/index.d.ts +31 -0
- package/dist/addons/vehicle-classifier/index.js +689 -0
- package/dist/addons/vehicle-classifier/index.js.map +1 -0
- package/dist/addons/vehicle-classifier/index.mjs +250 -0
- package/dist/addons/vehicle-classifier/index.mjs.map +1 -0
- package/dist/{chunk-6OR5TE7A.mjs → chunk-22BHCDT5.mjs} +2 -2
- package/dist/chunk-22BHCDT5.mjs.map +1 -0
- package/dist/{chunk-LPI42WL6.mjs → chunk-6DJZZR64.mjs} +24 -12
- package/dist/chunk-6DJZZR64.mjs.map +1 -0
- package/dist/chunk-7DYHXUPZ.mjs +36 -0
- package/dist/chunk-7DYHXUPZ.mjs.map +1 -0
- package/dist/chunk-BJTO5JO5.mjs +11 -0
- package/dist/chunk-BP7H4NFS.mjs +412 -0
- package/dist/chunk-BP7H4NFS.mjs.map +1 -0
- package/dist/chunk-BR2FPGOX.mjs +98 -0
- package/dist/chunk-BR2FPGOX.mjs.map +1 -0
- package/dist/{chunk-B3R66MPF.mjs → chunk-DNQNGDR4.mjs} +58 -21
- package/dist/chunk-DNQNGDR4.mjs.map +1 -0
- package/dist/{chunk-ISOIDU4U.mjs → chunk-DUN6XU3N.mjs} +23 -5
- package/dist/chunk-DUN6XU3N.mjs.map +1 -0
- package/dist/{chunk-MEVASN3P.mjs → chunk-EPNWLSCG.mjs} +104 -22
- package/dist/chunk-EPNWLSCG.mjs.map +1 -0
- package/dist/{chunk-AYBFB7ID.mjs → chunk-G32RCIUI.mjs} +200 -318
- package/dist/chunk-G32RCIUI.mjs.map +1 -0
- package/dist/{chunk-3MQFUDRU.mjs → chunk-GR65KM6X.mjs} +76 -47
- package/dist/chunk-GR65KM6X.mjs.map +1 -0
- package/dist/{chunk-5AIQSN32.mjs → chunk-H7LMBTS5.mjs} +66 -17
- package/dist/chunk-H7LMBTS5.mjs.map +1 -0
- package/dist/{chunk-J4WRYHHY.mjs → chunk-IK4XIQPC.mjs} +66 -36
- package/dist/chunk-IK4XIQPC.mjs.map +1 -0
- package/dist/{chunk-5JJZGKL7.mjs → chunk-J6VNIIYX.mjs} +102 -19
- package/dist/chunk-J6VNIIYX.mjs.map +1 -0
- package/dist/{chunk-Q3SQOYG6.mjs → chunk-ML2JX43J.mjs} +67 -37
- package/dist/chunk-ML2JX43J.mjs.map +1 -0
- package/dist/{chunk-PDSHDDPV.mjs → chunk-WUMV524J.mjs} +159 -35
- package/dist/chunk-WUMV524J.mjs.map +1 -0
- package/dist/chunk-XZ6ZMXXU.mjs +39 -0
- package/dist/chunk-XZ6ZMXXU.mjs.map +1 -0
- package/dist/index.d.mts +17 -5
- package/dist/index.d.ts +17 -5
- package/dist/index.js +1344 -550
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +191 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +95 -18
- package/python/coreml_inference.py +61 -18
- package/python/openvino_inference.py +12 -4
- package/python/pytorch_inference.py +12 -4
- package/dist/addons/camera-native-detection/index.d.mts +0 -32
- package/dist/addons/camera-native-detection/index.d.ts +0 -32
- package/dist/addons/camera-native-detection/index.js +0 -99
- package/dist/addons/camera-native-detection/index.js.map +0 -1
- package/dist/addons/camera-native-detection/index.mjs +0 -7
- package/dist/chunk-3MQFUDRU.mjs.map +0 -1
- package/dist/chunk-5AIQSN32.mjs.map +0 -1
- package/dist/chunk-5JJZGKL7.mjs.map +0 -1
- package/dist/chunk-6OR5TE7A.mjs.map +0 -1
- package/dist/chunk-AYBFB7ID.mjs.map +0 -1
- package/dist/chunk-B3R66MPF.mjs.map +0 -1
- package/dist/chunk-DTOAB2CE.mjs +0 -79
- package/dist/chunk-DTOAB2CE.mjs.map +0 -1
- package/dist/chunk-ISOIDU4U.mjs.map +0 -1
- package/dist/chunk-J4WRYHHY.mjs.map +0 -1
- package/dist/chunk-LPI42WL6.mjs.map +0 -1
- package/dist/chunk-MEVASN3P.mjs.map +0 -1
- package/dist/chunk-PDSHDDPV.mjs.map +0 -1
- package/dist/chunk-Q3SQOYG6.mjs.map +0 -1
- package/dist/chunk-QIMDG34B.mjs +0 -229
- package/dist/chunk-QIMDG34B.mjs.map +0 -1
- package/python/__pycache__/coreml_inference.cpython-313.pyc +0 -0
- package/python/__pycache__/openvino_inference.cpython-313.pyc +0 -0
- package/python/__pycache__/pytorch_inference.cpython-313.pyc +0 -0
- /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
|
-
|
|
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: "
|
|
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,
|
|
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
|
|
663
|
-
if (
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
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
|
|
672
|
+
`resolveEngine: model file not found at ${modelPath} and no model service provided`
|
|
670
673
|
);
|
|
671
674
|
}
|
|
672
675
|
}
|
|
673
|
-
if (selectedFormat === "onnx"
|
|
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
|
|
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
|
|
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
|
|
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/
|
|
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,
|
|
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,
|
|
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
|
|
1289
|
-
var
|
|
1692
|
+
var import_types8 = require("@camstack/types");
|
|
1693
|
+
var HF_REPO8 = "camstack/camstack-models";
|
|
1290
1694
|
var SEGMENTATION_MODELS = [
|
|
1291
|
-
// YOLO11-seg
|
|
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:
|
|
1701
|
+
labels: import_types8.COCO_80_LABELS,
|
|
1298
1702
|
formats: {
|
|
1299
1703
|
onnx: {
|
|
1300
|
-
url: (0,
|
|
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,
|
|
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:
|
|
1726
|
+
labels: import_types8.COCO_80_LABELS,
|
|
1315
1727
|
formats: {
|
|
1316
1728
|
onnx: {
|
|
1317
|
-
url: (0,
|
|
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,
|
|
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:
|
|
1751
|
+
labels: import_types8.COCO_80_LABELS,
|
|
1332
1752
|
formats: {
|
|
1333
1753
|
onnx: {
|
|
1334
|
-
url: (0,
|
|
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,
|
|
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
|
|
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:
|
|
1777
|
+
labels: import_types8.COCO_80_LABELS,
|
|
1350
1778
|
formats: {
|
|
1351
1779
|
onnx: {
|
|
1352
|
-
url: (0,
|
|
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,
|
|
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,
|
|
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:
|
|
1802
|
+
labels: import_types8.COCO_80_LABELS,
|
|
1371
1803
|
formats: {
|
|
1372
1804
|
onnx: {
|
|
1373
|
-
url: (0,
|
|
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,
|
|
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,
|
|
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:
|
|
1827
|
+
labels: import_types8.COCO_80_LABELS,
|
|
1392
1828
|
formats: {
|
|
1393
1829
|
onnx: {
|
|
1394
|
-
url: (0,
|
|
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,
|
|
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,
|
|
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
|
|
1411
|
-
var
|
|
1412
|
-
var hf = (path6) => (0,
|
|
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
|
|
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: "
|
|
1610
|
-
runtime: "
|
|
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"] ?? "
|
|
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,
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
|
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" ?
|
|
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/
|
|
1820
|
-
var
|
|
1821
|
-
var
|
|
1822
|
-
var
|
|
1823
|
-
var
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
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: "
|
|
1832
|
-
name: "
|
|
2462
|
+
id: "face-detection",
|
|
2463
|
+
name: "Face Detection",
|
|
1833
2464
|
version: "0.1.0",
|
|
1834
|
-
description: "
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
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
|
-
|
|
1843
|
-
|
|
2472
|
+
modelId: "scrfd-500m",
|
|
2473
|
+
runtime: "node",
|
|
2474
|
+
backend: "cpu",
|
|
2475
|
+
confidence: 0.5
|
|
1844
2476
|
}
|
|
1845
2477
|
};
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
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
|
-
|
|
1854
|
-
this.
|
|
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
|
|
1857
|
-
|
|
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: "
|
|
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
|
|
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
|
-
|
|
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: "
|
|
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: "
|
|
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 =
|
|
3138
|
+
const numChars = this.charset.length;
|
|
2453
3139
|
const seqLen = output.length / numChars;
|
|
2454
|
-
const { text, confidence } = ctcDecode(output, seqLen, numChars,
|
|
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: "
|
|
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
|
|
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
|
-
|
|
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: "
|
|
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
|
|
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
|
-
|
|
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: "
|
|
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: "
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|