@camstack/addon-vision 0.1.7 → 0.1.9
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 +30 -0
- package/dist/addons/animal-classifier/index.d.ts +30 -0
- package/dist/addons/animal-classifier/index.js +822 -999
- package/dist/addons/animal-classifier/index.js.map +1 -1
- package/dist/addons/animal-classifier/index.mjs +7 -242
- package/dist/addons/animal-classifier/index.mjs.map +1 -1
- package/dist/addons/audio-classification/index.d.mts +36 -0
- package/dist/addons/audio-classification/index.d.ts +36 -0
- package/dist/addons/audio-classification/index.js +378 -501
- package/dist/addons/audio-classification/index.js.map +1 -1
- package/dist/addons/audio-classification/index.mjs +4 -224
- package/dist/addons/audio-classification/index.mjs.map +1 -1
- package/dist/addons/bird-global-classifier/index.d.mts +31 -0
- package/dist/addons/bird-global-classifier/index.d.ts +31 -0
- package/dist/addons/bird-global-classifier/index.js +825 -1002
- package/dist/addons/bird-global-classifier/index.js.map +1 -1
- package/dist/addons/bird-global-classifier/index.mjs +7 -248
- package/dist/addons/bird-global-classifier/index.mjs.map +1 -1
- package/dist/addons/bird-nabirds-classifier/index.d.mts +33 -0
- package/dist/addons/bird-nabirds-classifier/index.d.ts +33 -0
- package/dist/addons/bird-nabirds-classifier/index.js +825 -1002
- package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
- package/dist/addons/bird-nabirds-classifier/index.mjs +7 -289
- package/dist/addons/bird-nabirds-classifier/index.mjs.map +1 -1
- package/dist/addons/face-detection/index.d.mts +29 -0
- package/dist/addons/face-detection/index.d.ts +29 -0
- package/dist/addons/face-detection/index.js +934 -1196
- package/dist/addons/face-detection/index.js.map +1 -1
- package/dist/addons/face-detection/index.mjs +7 -227
- package/dist/addons/face-detection/index.mjs.map +1 -1
- package/dist/addons/face-recognition/index.d.mts +29 -0
- package/dist/addons/face-recognition/index.d.ts +29 -0
- package/dist/addons/face-recognition/index.js +807 -1003
- package/dist/addons/face-recognition/index.js.map +1 -1
- package/dist/addons/face-recognition/index.mjs +6 -197
- package/dist/addons/face-recognition/index.mjs.map +1 -1
- package/dist/addons/motion-detection/index.d.mts +28 -0
- package/dist/addons/motion-detection/index.d.ts +28 -0
- package/dist/addons/motion-detection/index.js +111 -214
- package/dist/addons/motion-detection/index.js.map +1 -1
- package/dist/addons/motion-detection/index.mjs +9 -12
- package/dist/addons/motion-detection/index.mjs.map +1 -1
- package/dist/addons/object-detection/index.d.mts +31 -0
- package/dist/addons/object-detection/index.d.ts +31 -0
- package/dist/addons/object-detection/index.js +1082 -1287
- package/dist/addons/object-detection/index.js.map +1 -1
- package/dist/addons/object-detection/index.mjs +7 -373
- package/dist/addons/object-detection/index.mjs.map +1 -1
- package/dist/addons/plate-detection/index.d.mts +30 -0
- package/dist/addons/plate-detection/index.d.ts +30 -0
- package/dist/addons/plate-detection/index.js +868 -1075
- package/dist/addons/plate-detection/index.js.map +1 -1
- package/dist/addons/plate-detection/index.mjs +7 -230
- package/dist/addons/plate-detection/index.mjs.map +1 -1
- package/dist/addons/plate-recognition/index.d.mts +31 -0
- package/dist/addons/plate-recognition/index.d.ts +31 -0
- package/dist/addons/plate-recognition/index.js +505 -684
- package/dist/addons/plate-recognition/index.js.map +1 -1
- package/dist/addons/plate-recognition/index.mjs +5 -244
- package/dist/addons/plate-recognition/index.mjs.map +1 -1
- 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 +790 -967
- package/dist/addons/segmentation-refiner/index.js.map +1 -1
- package/dist/addons/segmentation-refiner/index.mjs +17 -21
- package/dist/addons/segmentation-refiner/index.mjs.map +1 -1
- 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 +410 -581
- package/dist/addons/vehicle-classifier/index.js.map +1 -1
- package/dist/addons/vehicle-classifier/index.mjs +16 -20
- package/dist/addons/vehicle-classifier/index.mjs.map +1 -1
- package/dist/chunk-22BHCDT5.mjs +101 -0
- package/dist/{chunk-WG66JYYW.mjs.map → chunk-22BHCDT5.mjs.map} +1 -1
- package/dist/chunk-2IOKI4ES.mjs +335 -0
- package/dist/{chunk-PIFS7AIT.mjs.map → chunk-2IOKI4ES.mjs.map} +1 -1
- package/dist/chunk-7DYHXUPZ.mjs +36 -0
- package/dist/{chunk-BS4DKYGN.mjs.map → chunk-7DYHXUPZ.mjs.map} +1 -1
- package/dist/chunk-BJTO5JO5.mjs +11 -0
- package/dist/chunk-BP7H4NFS.mjs +412 -0
- package/dist/{chunk-MGT6RUVX.mjs.map → chunk-BP7H4NFS.mjs.map} +1 -1
- package/dist/chunk-BR2FPGOX.mjs +98 -0
- package/dist/{chunk-YYDM6V2F.mjs.map → chunk-BR2FPGOX.mjs.map} +1 -1
- package/dist/chunk-D6WEHN33.mjs +276 -0
- package/dist/chunk-D6WEHN33.mjs.map +1 -0
- package/dist/chunk-DRYFGARD.mjs +289 -0
- package/dist/chunk-DRYFGARD.mjs.map +1 -0
- package/dist/chunk-DUN6XU3N.mjs +72 -0
- package/dist/{chunk-XD7WGXHZ.mjs.map → chunk-DUN6XU3N.mjs.map} +1 -1
- package/dist/chunk-ESLHNWWE.mjs +387 -0
- package/dist/chunk-ESLHNWWE.mjs.map +1 -0
- package/dist/chunk-JUQEW6ON.mjs +256 -0
- package/dist/chunk-JUQEW6ON.mjs.map +1 -0
- package/dist/chunk-KUO2BVFY.mjs +90 -0
- package/dist/{chunk-DE7I3VHO.mjs.map → chunk-KUO2BVFY.mjs.map} +1 -1
- package/dist/chunk-R5J3WAUI.mjs +645 -0
- package/dist/chunk-R5J3WAUI.mjs.map +1 -0
- package/dist/chunk-XZ6ZMXXU.mjs +39 -0
- package/dist/{chunk-K36R6HWY.mjs.map → chunk-XZ6ZMXXU.mjs.map} +1 -1
- package/dist/chunk-YPU4WTXZ.mjs +269 -0
- package/dist/chunk-YPU4WTXZ.mjs.map +1 -0
- package/dist/chunk-YUCD2TFH.mjs +242 -0
- package/dist/chunk-YUCD2TFH.mjs.map +1 -0
- package/dist/chunk-ZTJENCFC.mjs +379 -0
- package/dist/chunk-ZTJENCFC.mjs.map +1 -0
- package/dist/chunk-ZWYXXCXP.mjs +248 -0
- package/dist/chunk-ZWYXXCXP.mjs.map +1 -0
- package/dist/index.d.mts +183 -0
- package/dist/index.d.ts +183 -0
- package/dist/index.js +3930 -4449
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +250 -2698
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-2YMA6QOV.mjs +0 -193
- package/dist/chunk-2YMA6QOV.mjs.map +0 -1
- package/dist/chunk-3IIFBJCD.mjs +0 -45
- package/dist/chunk-BS4DKYGN.mjs +0 -48
- package/dist/chunk-DE7I3VHO.mjs +0 -106
- package/dist/chunk-F6D2OZ36.mjs +0 -89
- package/dist/chunk-F6D2OZ36.mjs.map +0 -1
- package/dist/chunk-GAOIFQDX.mjs +0 -59
- package/dist/chunk-GAOIFQDX.mjs.map +0 -1
- package/dist/chunk-HUIX2XVR.mjs +0 -159
- package/dist/chunk-HUIX2XVR.mjs.map +0 -1
- package/dist/chunk-K36R6HWY.mjs +0 -51
- package/dist/chunk-MBTAI3WE.mjs +0 -78
- package/dist/chunk-MBTAI3WE.mjs.map +0 -1
- package/dist/chunk-MGT6RUVX.mjs +0 -423
- package/dist/chunk-PIFS7AIT.mjs +0 -446
- package/dist/chunk-WG66JYYW.mjs +0 -116
- package/dist/chunk-XD7WGXHZ.mjs +0 -82
- package/dist/chunk-YYDM6V2F.mjs +0 -113
- package/dist/chunk-ZK7P3TZN.mjs +0 -286
- package/dist/chunk-ZK7P3TZN.mjs.map +0 -1
- /package/dist/{chunk-3IIFBJCD.mjs.map → chunk-BJTO5JO5.mjs.map} +0 -0
|
@@ -5,9 +5,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
-
};
|
|
11
8
|
var __export = (target, all) => {
|
|
12
9
|
for (var name in all)
|
|
13
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -30,1043 +27,869 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
27
|
));
|
|
31
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
29
|
|
|
33
|
-
// src/
|
|
34
|
-
var
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
files: exports2.MLPACKAGE_FILES,
|
|
64
|
-
runtimes: ["python"]
|
|
65
|
-
},
|
|
66
|
-
openvino: {
|
|
67
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8n.xml"),
|
|
68
|
-
sizeMB: 7,
|
|
69
|
-
runtimes: ["python"]
|
|
70
|
-
},
|
|
71
|
-
tflite: {
|
|
72
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/tflite/camstack-yolov8n_float32.tflite"),
|
|
73
|
-
sizeMB: 12,
|
|
74
|
-
runtimes: ["python"]
|
|
75
|
-
}
|
|
76
|
-
}
|
|
30
|
+
// src/addons/bird-global-classifier/index.ts
|
|
31
|
+
var bird_global_classifier_exports = {};
|
|
32
|
+
__export(bird_global_classifier_exports, {
|
|
33
|
+
default: () => BirdGlobalClassifierAddon
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(bird_global_classifier_exports);
|
|
36
|
+
|
|
37
|
+
// src/catalogs/animal-classification-models.ts
|
|
38
|
+
var import_types2 = require("@camstack/types");
|
|
39
|
+
|
|
40
|
+
// src/catalogs/object-detection-models.ts
|
|
41
|
+
var import_types = require("@camstack/types");
|
|
42
|
+
var HF_REPO = "camstack/camstack-models";
|
|
43
|
+
var MLPACKAGE_FILES = [
|
|
44
|
+
"Manifest.json",
|
|
45
|
+
"Data/com.apple.CoreML/model.mlmodel",
|
|
46
|
+
"Data/com.apple.CoreML/weights/weight.bin"
|
|
47
|
+
];
|
|
48
|
+
var OBJECT_DETECTION_MODELS = [
|
|
49
|
+
// ── YOLOv8 ──────────────────────────────────────────────────────
|
|
50
|
+
{
|
|
51
|
+
id: "yolov8n",
|
|
52
|
+
name: "YOLOv8 Nano",
|
|
53
|
+
description: "YOLOv8 Nano \u2014 fastest, smallest object detection model",
|
|
54
|
+
inputSize: { width: 640, height: 640 },
|
|
55
|
+
labels: import_types.COCO_80_LABELS,
|
|
56
|
+
formats: {
|
|
57
|
+
onnx: {
|
|
58
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8n.onnx"),
|
|
59
|
+
sizeMB: 12
|
|
77
60
|
},
|
|
78
|
-
{
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
formats: {
|
|
85
|
-
onnx: {
|
|
86
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8s.onnx"),
|
|
87
|
-
sizeMB: 43
|
|
88
|
-
},
|
|
89
|
-
coreml: {
|
|
90
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8s.mlpackage"),
|
|
91
|
-
sizeMB: 21,
|
|
92
|
-
isDirectory: true,
|
|
93
|
-
files: exports2.MLPACKAGE_FILES,
|
|
94
|
-
runtimes: ["python"]
|
|
95
|
-
},
|
|
96
|
-
openvino: {
|
|
97
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8s.xml"),
|
|
98
|
-
sizeMB: 22,
|
|
99
|
-
runtimes: ["python"]
|
|
100
|
-
},
|
|
101
|
-
tflite: {
|
|
102
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/tflite/camstack-yolov8s_float32.tflite"),
|
|
103
|
-
sizeMB: 43,
|
|
104
|
-
runtimes: ["python"]
|
|
105
|
-
}
|
|
106
|
-
}
|
|
61
|
+
coreml: {
|
|
62
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8n.mlpackage"),
|
|
63
|
+
sizeMB: 6,
|
|
64
|
+
isDirectory: true,
|
|
65
|
+
files: MLPACKAGE_FILES,
|
|
66
|
+
runtimes: ["python"]
|
|
107
67
|
},
|
|
108
|
-
{
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
inputSize: { width: 640, height: 640 },
|
|
113
|
-
labels: types_1.COCO_80_LABELS,
|
|
114
|
-
formats: {
|
|
115
|
-
onnx: {
|
|
116
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8s-relu.onnx"),
|
|
117
|
-
sizeMB: 43
|
|
118
|
-
}
|
|
119
|
-
}
|
|
68
|
+
openvino: {
|
|
69
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8n.xml"),
|
|
70
|
+
sizeMB: 7,
|
|
71
|
+
runtimes: ["python"]
|
|
120
72
|
},
|
|
121
|
-
{
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
},
|
|
139
|
-
openvino: {
|
|
140
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8m.xml"),
|
|
141
|
-
sizeMB: 50,
|
|
142
|
-
runtimes: ["python"]
|
|
143
|
-
},
|
|
144
|
-
tflite: {
|
|
145
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/tflite/camstack-yolov8m_float32.tflite"),
|
|
146
|
-
sizeMB: 99,
|
|
147
|
-
runtimes: ["python"]
|
|
148
|
-
}
|
|
149
|
-
}
|
|
73
|
+
tflite: {
|
|
74
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/tflite/camstack-yolov8n_float32.tflite"),
|
|
75
|
+
sizeMB: 12,
|
|
76
|
+
runtimes: ["python"]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "yolov8s",
|
|
82
|
+
name: "YOLOv8 Small",
|
|
83
|
+
description: "YOLOv8 Small \u2014 balanced speed and accuracy",
|
|
84
|
+
inputSize: { width: 640, height: 640 },
|
|
85
|
+
labels: import_types.COCO_80_LABELS,
|
|
86
|
+
formats: {
|
|
87
|
+
onnx: {
|
|
88
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8s.onnx"),
|
|
89
|
+
sizeMB: 43
|
|
150
90
|
},
|
|
151
|
-
{
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
formats: {
|
|
158
|
-
onnx: {
|
|
159
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8l.onnx"),
|
|
160
|
-
sizeMB: 167
|
|
161
|
-
},
|
|
162
|
-
coreml: {
|
|
163
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8l.mlpackage"),
|
|
164
|
-
sizeMB: 83,
|
|
165
|
-
isDirectory: true,
|
|
166
|
-
files: exports2.MLPACKAGE_FILES,
|
|
167
|
-
runtimes: ["python"]
|
|
168
|
-
},
|
|
169
|
-
openvino: {
|
|
170
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8l.xml"),
|
|
171
|
-
sizeMB: 84,
|
|
172
|
-
runtimes: ["python"]
|
|
173
|
-
}
|
|
174
|
-
}
|
|
91
|
+
coreml: {
|
|
92
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8s.mlpackage"),
|
|
93
|
+
sizeMB: 21,
|
|
94
|
+
isDirectory: true,
|
|
95
|
+
files: MLPACKAGE_FILES,
|
|
96
|
+
runtimes: ["python"]
|
|
175
97
|
},
|
|
176
|
-
{
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
inputSize: { width: 640, height: 640 },
|
|
181
|
-
labels: types_1.COCO_80_LABELS,
|
|
182
|
-
formats: {
|
|
183
|
-
onnx: {
|
|
184
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8x.onnx"),
|
|
185
|
-
sizeMB: 260
|
|
186
|
-
},
|
|
187
|
-
coreml: {
|
|
188
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8x.mlpackage"),
|
|
189
|
-
sizeMB: 130,
|
|
190
|
-
isDirectory: true,
|
|
191
|
-
files: exports2.MLPACKAGE_FILES,
|
|
192
|
-
runtimes: ["python"]
|
|
193
|
-
},
|
|
194
|
-
openvino: {
|
|
195
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8x.xml"),
|
|
196
|
-
sizeMB: 131,
|
|
197
|
-
runtimes: ["python"]
|
|
198
|
-
}
|
|
199
|
-
}
|
|
98
|
+
openvino: {
|
|
99
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8s.xml"),
|
|
100
|
+
sizeMB: 22,
|
|
101
|
+
runtimes: ["python"]
|
|
200
102
|
},
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
103
|
+
tflite: {
|
|
104
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/tflite/camstack-yolov8s_float32.tflite"),
|
|
105
|
+
sizeMB: 43,
|
|
106
|
+
runtimes: ["python"]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: "yolov8s-relu",
|
|
112
|
+
name: "YOLOv8 Small ReLU",
|
|
113
|
+
description: "YOLOv8 Small with ReLU activation \u2014 better hardware compatibility",
|
|
114
|
+
inputSize: { width: 640, height: 640 },
|
|
115
|
+
labels: import_types.COCO_80_LABELS,
|
|
116
|
+
formats: {
|
|
117
|
+
onnx: {
|
|
118
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8s-relu.onnx"),
|
|
119
|
+
sizeMB: 43
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: "yolov8m",
|
|
125
|
+
name: "YOLOv8 Medium",
|
|
126
|
+
description: "YOLOv8 Medium \u2014 higher accuracy, moderate size",
|
|
127
|
+
inputSize: { width: 640, height: 640 },
|
|
128
|
+
labels: import_types.COCO_80_LABELS,
|
|
129
|
+
formats: {
|
|
130
|
+
onnx: {
|
|
131
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8m.onnx"),
|
|
132
|
+
sizeMB: 99
|
|
231
133
|
},
|
|
232
|
-
{
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
formats: {
|
|
239
|
-
onnx: {
|
|
240
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov9/onnx/camstack-yolov9s.onnx"),
|
|
241
|
-
sizeMB: 28
|
|
242
|
-
},
|
|
243
|
-
coreml: {
|
|
244
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov9/coreml/camstack-yolov9s.mlpackage"),
|
|
245
|
-
sizeMB: 14,
|
|
246
|
-
isDirectory: true,
|
|
247
|
-
files: exports2.MLPACKAGE_FILES,
|
|
248
|
-
runtimes: ["python"]
|
|
249
|
-
},
|
|
250
|
-
openvino: {
|
|
251
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov9/openvino/camstack-yolov9s.xml"),
|
|
252
|
-
sizeMB: 16,
|
|
253
|
-
runtimes: ["python"]
|
|
254
|
-
},
|
|
255
|
-
tflite: {
|
|
256
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov9/tflite/camstack-yolov9s_float32.tflite"),
|
|
257
|
-
sizeMB: 28,
|
|
258
|
-
runtimes: ["python"]
|
|
259
|
-
}
|
|
260
|
-
}
|
|
134
|
+
coreml: {
|
|
135
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8m.mlpackage"),
|
|
136
|
+
sizeMB: 49,
|
|
137
|
+
isDirectory: true,
|
|
138
|
+
files: MLPACKAGE_FILES,
|
|
139
|
+
runtimes: ["python"]
|
|
261
140
|
},
|
|
262
|
-
{
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
inputSize: { width: 640, height: 640 },
|
|
267
|
-
labels: types_1.COCO_80_LABELS,
|
|
268
|
-
formats: {
|
|
269
|
-
onnx: {
|
|
270
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov9/onnx/camstack-yolov9c.onnx"),
|
|
271
|
-
sizeMB: 97
|
|
272
|
-
},
|
|
273
|
-
coreml: {
|
|
274
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov9/coreml/camstack-yolov9c.mlpackage"),
|
|
275
|
-
sizeMB: 48,
|
|
276
|
-
isDirectory: true,
|
|
277
|
-
files: exports2.MLPACKAGE_FILES,
|
|
278
|
-
runtimes: ["python"]
|
|
279
|
-
},
|
|
280
|
-
openvino: {
|
|
281
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov9/openvino/camstack-yolov9c.xml"),
|
|
282
|
-
sizeMB: 49,
|
|
283
|
-
runtimes: ["python"]
|
|
284
|
-
},
|
|
285
|
-
tflite: {
|
|
286
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolov9/tflite/camstack-yolov9c_float32.tflite"),
|
|
287
|
-
sizeMB: 97,
|
|
288
|
-
runtimes: ["python"]
|
|
289
|
-
}
|
|
290
|
-
}
|
|
141
|
+
openvino: {
|
|
142
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8m.xml"),
|
|
143
|
+
sizeMB: 50,
|
|
144
|
+
runtimes: ["python"]
|
|
291
145
|
},
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
runtimes: ["python"]
|
|
310
|
-
},
|
|
311
|
-
openvino: {
|
|
312
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11n.xml"),
|
|
313
|
-
sizeMB: 5,
|
|
314
|
-
runtimes: ["python"]
|
|
315
|
-
},
|
|
316
|
-
tflite: {
|
|
317
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11n_float32.tflite"),
|
|
318
|
-
sizeMB: 10,
|
|
319
|
-
runtimes: ["python"]
|
|
320
|
-
}
|
|
321
|
-
}
|
|
146
|
+
tflite: {
|
|
147
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/tflite/camstack-yolov8m_float32.tflite"),
|
|
148
|
+
sizeMB: 99,
|
|
149
|
+
runtimes: ["python"]
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: "yolov8l",
|
|
155
|
+
name: "YOLOv8 Large",
|
|
156
|
+
description: "YOLOv8 Large \u2014 high-accuracy large model",
|
|
157
|
+
inputSize: { width: 640, height: 640 },
|
|
158
|
+
labels: import_types.COCO_80_LABELS,
|
|
159
|
+
formats: {
|
|
160
|
+
onnx: {
|
|
161
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8l.onnx"),
|
|
162
|
+
sizeMB: 167
|
|
322
163
|
},
|
|
323
|
-
{
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
formats: {
|
|
330
|
-
onnx: {
|
|
331
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11s.onnx"),
|
|
332
|
-
sizeMB: 36
|
|
333
|
-
},
|
|
334
|
-
coreml: {
|
|
335
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11s.mlpackage"),
|
|
336
|
-
sizeMB: 18,
|
|
337
|
-
isDirectory: true,
|
|
338
|
-
files: exports2.MLPACKAGE_FILES,
|
|
339
|
-
runtimes: ["python"]
|
|
340
|
-
},
|
|
341
|
-
openvino: {
|
|
342
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11s.xml"),
|
|
343
|
-
sizeMB: 18,
|
|
344
|
-
runtimes: ["python"]
|
|
345
|
-
},
|
|
346
|
-
tflite: {
|
|
347
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11s_float32.tflite"),
|
|
348
|
-
sizeMB: 36,
|
|
349
|
-
runtimes: ["python"]
|
|
350
|
-
}
|
|
351
|
-
}
|
|
164
|
+
coreml: {
|
|
165
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8l.mlpackage"),
|
|
166
|
+
sizeMB: 83,
|
|
167
|
+
isDirectory: true,
|
|
168
|
+
files: MLPACKAGE_FILES,
|
|
169
|
+
runtimes: ["python"]
|
|
352
170
|
},
|
|
353
|
-
{
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
},
|
|
371
|
-
openvino: {
|
|
372
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11m.xml"),
|
|
373
|
-
sizeMB: 39,
|
|
374
|
-
runtimes: ["python"]
|
|
375
|
-
},
|
|
376
|
-
tflite: {
|
|
377
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11m_float32.tflite"),
|
|
378
|
-
sizeMB: 77,
|
|
379
|
-
runtimes: ["python"]
|
|
380
|
-
}
|
|
381
|
-
}
|
|
171
|
+
openvino: {
|
|
172
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8l.xml"),
|
|
173
|
+
sizeMB: 84,
|
|
174
|
+
runtimes: ["python"]
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
id: "yolov8x",
|
|
180
|
+
name: "YOLOv8 Extra-Large",
|
|
181
|
+
description: "YOLOv8 Extra-Large \u2014 maximum accuracy",
|
|
182
|
+
inputSize: { width: 640, height: 640 },
|
|
183
|
+
labels: import_types.COCO_80_LABELS,
|
|
184
|
+
formats: {
|
|
185
|
+
onnx: {
|
|
186
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/onnx/camstack-yolov8x.onnx"),
|
|
187
|
+
sizeMB: 260
|
|
382
188
|
},
|
|
383
|
-
{
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
formats: {
|
|
390
|
-
onnx: {
|
|
391
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11l.onnx"),
|
|
392
|
-
sizeMB: 97
|
|
393
|
-
},
|
|
394
|
-
coreml: {
|
|
395
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11l.mlpackage"),
|
|
396
|
-
sizeMB: 49,
|
|
397
|
-
isDirectory: true,
|
|
398
|
-
files: exports2.MLPACKAGE_FILES,
|
|
399
|
-
runtimes: ["python"]
|
|
400
|
-
},
|
|
401
|
-
openvino: {
|
|
402
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11l.xml"),
|
|
403
|
-
sizeMB: 49,
|
|
404
|
-
runtimes: ["python"]
|
|
405
|
-
},
|
|
406
|
-
tflite: {
|
|
407
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11l_float32.tflite"),
|
|
408
|
-
sizeMB: 97,
|
|
409
|
-
runtimes: ["python"]
|
|
410
|
-
}
|
|
411
|
-
}
|
|
189
|
+
coreml: {
|
|
190
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/coreml/camstack-yolov8x.mlpackage"),
|
|
191
|
+
sizeMB: 130,
|
|
192
|
+
isDirectory: true,
|
|
193
|
+
files: MLPACKAGE_FILES,
|
|
194
|
+
runtimes: ["python"]
|
|
412
195
|
},
|
|
413
|
-
{
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
inputSize: { width: 640, height: 640 },
|
|
418
|
-
labels: types_1.COCO_80_LABELS,
|
|
419
|
-
formats: {
|
|
420
|
-
onnx: {
|
|
421
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11x.onnx"),
|
|
422
|
-
sizeMB: 218
|
|
423
|
-
},
|
|
424
|
-
coreml: {
|
|
425
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11x.mlpackage"),
|
|
426
|
-
sizeMB: 109,
|
|
427
|
-
isDirectory: true,
|
|
428
|
-
files: exports2.MLPACKAGE_FILES,
|
|
429
|
-
runtimes: ["python"]
|
|
430
|
-
},
|
|
431
|
-
openvino: {
|
|
432
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11x.xml"),
|
|
433
|
-
sizeMB: 109,
|
|
434
|
-
runtimes: ["python"]
|
|
435
|
-
},
|
|
436
|
-
tflite: {
|
|
437
|
-
url: (0, types_1.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11x_float32.tflite"),
|
|
438
|
-
sizeMB: 218,
|
|
439
|
-
runtimes: ["python"]
|
|
440
|
-
}
|
|
441
|
-
}
|
|
196
|
+
openvino: {
|
|
197
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov8/openvino/camstack-yolov8x.xml"),
|
|
198
|
+
sizeMB: 131,
|
|
199
|
+
runtimes: ["python"]
|
|
442
200
|
}
|
|
443
|
-
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
filename: "camstack-bird-species-525-labels.json",
|
|
474
|
-
sizeMB: 0.02
|
|
475
|
-
}
|
|
476
|
-
]
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
// ── YOLOv9 ──────────────────────────────────────────────────────
|
|
204
|
+
{
|
|
205
|
+
id: "yolov9t",
|
|
206
|
+
name: "YOLOv9 Tiny",
|
|
207
|
+
description: "YOLOv9 Tiny \u2014 ultra-lightweight next-gen detector",
|
|
208
|
+
inputSize: { width: 640, height: 640 },
|
|
209
|
+
labels: import_types.COCO_80_LABELS,
|
|
210
|
+
formats: {
|
|
211
|
+
onnx: {
|
|
212
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/onnx/camstack-yolov9t.onnx"),
|
|
213
|
+
sizeMB: 8
|
|
214
|
+
},
|
|
215
|
+
coreml: {
|
|
216
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/coreml/camstack-yolov9t.mlpackage"),
|
|
217
|
+
sizeMB: 4,
|
|
218
|
+
isDirectory: true,
|
|
219
|
+
files: MLPACKAGE_FILES,
|
|
220
|
+
runtimes: ["python"]
|
|
221
|
+
},
|
|
222
|
+
openvino: {
|
|
223
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/openvino/camstack-yolov9t.xml"),
|
|
224
|
+
sizeMB: 6,
|
|
225
|
+
runtimes: ["python"]
|
|
226
|
+
},
|
|
227
|
+
tflite: {
|
|
228
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/tflite/camstack-yolov9t_float32.tflite"),
|
|
229
|
+
sizeMB: 8,
|
|
230
|
+
runtimes: ["python"]
|
|
477
231
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
id: "yolov9s",
|
|
236
|
+
name: "YOLOv9 Small",
|
|
237
|
+
description: "YOLOv9 Small \u2014 improved efficiency over YOLOv8s",
|
|
238
|
+
inputSize: { width: 640, height: 640 },
|
|
239
|
+
labels: import_types.COCO_80_LABELS,
|
|
240
|
+
formats: {
|
|
241
|
+
onnx: {
|
|
242
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/onnx/camstack-yolov9s.onnx"),
|
|
243
|
+
sizeMB: 28
|
|
244
|
+
},
|
|
245
|
+
coreml: {
|
|
246
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/coreml/camstack-yolov9s.mlpackage"),
|
|
247
|
+
sizeMB: 14,
|
|
248
|
+
isDirectory: true,
|
|
249
|
+
files: MLPACKAGE_FILES,
|
|
250
|
+
runtimes: ["python"]
|
|
251
|
+
},
|
|
252
|
+
openvino: {
|
|
253
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/openvino/camstack-yolov9s.xml"),
|
|
254
|
+
sizeMB: 16,
|
|
255
|
+
runtimes: ["python"]
|
|
256
|
+
},
|
|
257
|
+
tflite: {
|
|
258
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/tflite/camstack-yolov9s_float32.tflite"),
|
|
259
|
+
sizeMB: 28,
|
|
260
|
+
runtimes: ["python"]
|
|
499
261
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
id: "yolov9c",
|
|
266
|
+
name: "YOLOv9 C",
|
|
267
|
+
description: "YOLOv9 C \u2014 high-accuracy compact model",
|
|
268
|
+
inputSize: { width: 640, height: 640 },
|
|
269
|
+
labels: import_types.COCO_80_LABELS,
|
|
270
|
+
formats: {
|
|
271
|
+
onnx: {
|
|
272
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/onnx/camstack-yolov9c.onnx"),
|
|
273
|
+
sizeMB: 97
|
|
274
|
+
},
|
|
275
|
+
coreml: {
|
|
276
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/coreml/camstack-yolov9c.mlpackage"),
|
|
277
|
+
sizeMB: 48,
|
|
278
|
+
isDirectory: true,
|
|
279
|
+
files: MLPACKAGE_FILES,
|
|
280
|
+
runtimes: ["python"]
|
|
281
|
+
},
|
|
282
|
+
openvino: {
|
|
283
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/openvino/camstack-yolov9c.xml"),
|
|
284
|
+
sizeMB: 49,
|
|
285
|
+
runtimes: ["python"]
|
|
286
|
+
},
|
|
287
|
+
tflite: {
|
|
288
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolov9/tflite/camstack-yolov9c_float32.tflite"),
|
|
289
|
+
sizeMB: 97,
|
|
290
|
+
runtimes: ["python"]
|
|
512
291
|
}
|
|
513
|
-
];
|
|
514
|
-
}
|
|
515
|
-
});
|
|
516
|
-
|
|
517
|
-
// src/shared/image-utils.js
|
|
518
|
-
var require_image_utils = __commonJS({
|
|
519
|
-
"src/shared/image-utils.js"(exports2) {
|
|
520
|
-
"use strict";
|
|
521
|
-
var __importDefault = exports2 && exports2.__importDefault || function(mod) {
|
|
522
|
-
return mod && mod.__esModule ? mod : { "default": mod };
|
|
523
|
-
};
|
|
524
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
525
|
-
exports2.jpegToRgb = jpegToRgb;
|
|
526
|
-
exports2.cropRegion = cropRegion2;
|
|
527
|
-
exports2.letterbox = letterbox;
|
|
528
|
-
exports2.resizeAndNormalize = resizeAndNormalize2;
|
|
529
|
-
exports2.rgbToGrayscale = rgbToGrayscale;
|
|
530
|
-
var sharp_1 = __importDefault(require("sharp"));
|
|
531
|
-
async function jpegToRgb(jpeg) {
|
|
532
|
-
const { data, info } = await (0, sharp_1.default)(jpeg).removeAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
533
|
-
return { data, width: info.width, height: info.height };
|
|
534
292
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
293
|
+
},
|
|
294
|
+
// ── YOLO11 ────────────────────────────────────────────────────
|
|
295
|
+
{
|
|
296
|
+
id: "yolo11n",
|
|
297
|
+
name: "YOLO11 Nano",
|
|
298
|
+
description: "YOLO11 Nano \u2014 fastest, smallest YOLO11 detection model (mAP 39.5)",
|
|
299
|
+
inputSize: { width: 640, height: 640 },
|
|
300
|
+
labels: import_types.COCO_80_LABELS,
|
|
301
|
+
formats: {
|
|
302
|
+
onnx: {
|
|
303
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11n.onnx"),
|
|
304
|
+
sizeMB: 10
|
|
305
|
+
},
|
|
306
|
+
coreml: {
|
|
307
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11n.mlpackage"),
|
|
308
|
+
sizeMB: 5,
|
|
309
|
+
isDirectory: true,
|
|
310
|
+
files: MLPACKAGE_FILES,
|
|
311
|
+
runtimes: ["python"]
|
|
312
|
+
},
|
|
313
|
+
openvino: {
|
|
314
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11n.xml"),
|
|
315
|
+
sizeMB: 5,
|
|
316
|
+
runtimes: ["python"]
|
|
317
|
+
},
|
|
318
|
+
tflite: {
|
|
319
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11n_float32.tflite"),
|
|
320
|
+
sizeMB: 10,
|
|
321
|
+
runtimes: ["python"]
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
id: "yolo11s",
|
|
327
|
+
name: "YOLO11 Small",
|
|
328
|
+
description: "YOLO11 Small \u2014 balanced speed and accuracy (mAP 47.0)",
|
|
329
|
+
inputSize: { width: 640, height: 640 },
|
|
330
|
+
labels: import_types.COCO_80_LABELS,
|
|
331
|
+
formats: {
|
|
332
|
+
onnx: {
|
|
333
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11s.onnx"),
|
|
334
|
+
sizeMB: 36
|
|
335
|
+
},
|
|
336
|
+
coreml: {
|
|
337
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11s.mlpackage"),
|
|
338
|
+
sizeMB: 18,
|
|
339
|
+
isDirectory: true,
|
|
340
|
+
files: MLPACKAGE_FILES,
|
|
341
|
+
runtimes: ["python"]
|
|
342
|
+
},
|
|
343
|
+
openvino: {
|
|
344
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11s.xml"),
|
|
345
|
+
sizeMB: 18,
|
|
346
|
+
runtimes: ["python"]
|
|
347
|
+
},
|
|
348
|
+
tflite: {
|
|
349
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11s_float32.tflite"),
|
|
350
|
+
sizeMB: 36,
|
|
351
|
+
runtimes: ["python"]
|
|
352
|
+
}
|
|
542
353
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
id: "yolo11m",
|
|
357
|
+
name: "YOLO11 Medium",
|
|
358
|
+
description: "YOLO11 Medium \u2014 higher accuracy, moderate size (mAP 51.5)",
|
|
359
|
+
inputSize: { width: 640, height: 640 },
|
|
360
|
+
labels: import_types.COCO_80_LABELS,
|
|
361
|
+
formats: {
|
|
362
|
+
onnx: {
|
|
363
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11m.onnx"),
|
|
364
|
+
sizeMB: 77
|
|
365
|
+
},
|
|
366
|
+
coreml: {
|
|
367
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11m.mlpackage"),
|
|
368
|
+
sizeMB: 39,
|
|
369
|
+
isDirectory: true,
|
|
370
|
+
files: MLPACKAGE_FILES,
|
|
371
|
+
runtimes: ["python"]
|
|
372
|
+
},
|
|
373
|
+
openvino: {
|
|
374
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11m.xml"),
|
|
375
|
+
sizeMB: 39,
|
|
376
|
+
runtimes: ["python"]
|
|
377
|
+
},
|
|
378
|
+
tflite: {
|
|
379
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11m_float32.tflite"),
|
|
380
|
+
sizeMB: 77,
|
|
381
|
+
runtimes: ["python"]
|
|
566
382
|
}
|
|
567
|
-
return { data: float32, scale, padX, padY, originalWidth, originalHeight };
|
|
568
383
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
if (normalization === "zero-one") {
|
|
598
|
-
val = raw;
|
|
599
|
-
} else if (normalization === "imagenet") {
|
|
600
|
-
val = (raw - mean[c]) / std[c];
|
|
601
|
-
} else {
|
|
602
|
-
val = data[srcBase + c];
|
|
603
|
-
}
|
|
604
|
-
float32[i * 3 + c] = val;
|
|
605
|
-
}
|
|
606
|
-
}
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
id: "yolo11l",
|
|
387
|
+
name: "YOLO11 Large",
|
|
388
|
+
description: "YOLO11 Large \u2014 high-accuracy large model (mAP 53.4)",
|
|
389
|
+
inputSize: { width: 640, height: 640 },
|
|
390
|
+
labels: import_types.COCO_80_LABELS,
|
|
391
|
+
formats: {
|
|
392
|
+
onnx: {
|
|
393
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11l.onnx"),
|
|
394
|
+
sizeMB: 97
|
|
395
|
+
},
|
|
396
|
+
coreml: {
|
|
397
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11l.mlpackage"),
|
|
398
|
+
sizeMB: 49,
|
|
399
|
+
isDirectory: true,
|
|
400
|
+
files: MLPACKAGE_FILES,
|
|
401
|
+
runtimes: ["python"]
|
|
402
|
+
},
|
|
403
|
+
openvino: {
|
|
404
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11l.xml"),
|
|
405
|
+
sizeMB: 49,
|
|
406
|
+
runtimes: ["python"]
|
|
407
|
+
},
|
|
408
|
+
tflite: {
|
|
409
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11l_float32.tflite"),
|
|
410
|
+
sizeMB: 97,
|
|
411
|
+
runtimes: ["python"]
|
|
607
412
|
}
|
|
608
|
-
return float32;
|
|
609
413
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
id: "yolo11x",
|
|
417
|
+
name: "YOLO11 Extra-Large",
|
|
418
|
+
description: "YOLO11 Extra-Large \u2014 maximum accuracy (mAP 54.7)",
|
|
419
|
+
inputSize: { width: 640, height: 640 },
|
|
420
|
+
labels: import_types.COCO_80_LABELS,
|
|
421
|
+
formats: {
|
|
422
|
+
onnx: {
|
|
423
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/onnx/camstack-yolo11x.onnx"),
|
|
424
|
+
sizeMB: 218
|
|
425
|
+
},
|
|
426
|
+
coreml: {
|
|
427
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/coreml/camstack-yolo11x.mlpackage"),
|
|
428
|
+
sizeMB: 109,
|
|
429
|
+
isDirectory: true,
|
|
430
|
+
files: MLPACKAGE_FILES,
|
|
431
|
+
runtimes: ["python"]
|
|
432
|
+
},
|
|
433
|
+
openvino: {
|
|
434
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/openvino/camstack-yolo11x.xml"),
|
|
435
|
+
sizeMB: 109,
|
|
436
|
+
runtimes: ["python"]
|
|
437
|
+
},
|
|
438
|
+
tflite: {
|
|
439
|
+
url: (0, import_types.hfModelUrl)(HF_REPO, "objectDetection/yolo11/tflite/camstack-yolo11x_float32.tflite"),
|
|
440
|
+
sizeMB: 218,
|
|
441
|
+
runtimes: ["python"]
|
|
618
442
|
}
|
|
619
|
-
return gray;
|
|
620
443
|
}
|
|
621
444
|
}
|
|
622
|
-
|
|
445
|
+
];
|
|
623
446
|
|
|
624
|
-
// src/
|
|
625
|
-
var
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
});
|
|
646
|
-
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
647
|
-
var ownKeys = function(o) {
|
|
648
|
-
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
649
|
-
var ar = [];
|
|
650
|
-
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
651
|
-
return ar;
|
|
652
|
-
};
|
|
653
|
-
return ownKeys(o);
|
|
654
|
-
};
|
|
655
|
-
return function(mod) {
|
|
656
|
-
if (mod && mod.__esModule) return mod;
|
|
657
|
-
var result = {};
|
|
658
|
-
if (mod != null) {
|
|
659
|
-
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
660
|
-
}
|
|
661
|
-
__setModuleDefault(result, mod);
|
|
662
|
-
return result;
|
|
663
|
-
};
|
|
664
|
-
})();
|
|
665
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
666
|
-
exports2.NodeInferenceEngine = void 0;
|
|
667
|
-
var path2 = __importStar(require("path"));
|
|
668
|
-
var BACKEND_TO_PROVIDER = {
|
|
669
|
-
cpu: "cpu",
|
|
670
|
-
coreml: "coreml",
|
|
671
|
-
cuda: "cuda",
|
|
672
|
-
tensorrt: "tensorrt",
|
|
673
|
-
dml: "dml"
|
|
674
|
-
};
|
|
675
|
-
var BACKEND_TO_DEVICE = {
|
|
676
|
-
cpu: "cpu",
|
|
677
|
-
coreml: "gpu-mps",
|
|
678
|
-
cuda: "gpu-cuda",
|
|
679
|
-
tensorrt: "tensorrt"
|
|
680
|
-
};
|
|
681
|
-
var NodeInferenceEngine = class {
|
|
682
|
-
modelPath;
|
|
683
|
-
backend;
|
|
684
|
-
runtime = "onnx";
|
|
685
|
-
device;
|
|
686
|
-
session = null;
|
|
687
|
-
constructor(modelPath, backend) {
|
|
688
|
-
this.modelPath = modelPath;
|
|
689
|
-
this.backend = backend;
|
|
690
|
-
this.device = BACKEND_TO_DEVICE[backend] ?? "cpu";
|
|
691
|
-
}
|
|
692
|
-
async initialize() {
|
|
693
|
-
const ort = await Promise.resolve().then(() => __importStar(require("onnxruntime-node")));
|
|
694
|
-
const provider = BACKEND_TO_PROVIDER[this.backend] ?? "cpu";
|
|
695
|
-
const absModelPath = path2.isAbsolute(this.modelPath) ? this.modelPath : path2.resolve(process.cwd(), this.modelPath);
|
|
696
|
-
const sessionOptions = {
|
|
697
|
-
executionProviders: [provider]
|
|
698
|
-
};
|
|
699
|
-
this.session = await ort.InferenceSession.create(absModelPath, sessionOptions);
|
|
700
|
-
}
|
|
701
|
-
async run(input, inputShape) {
|
|
702
|
-
if (!this.session) {
|
|
703
|
-
throw new Error("NodeInferenceEngine: not initialized \u2014 call initialize() first");
|
|
704
|
-
}
|
|
705
|
-
const ort = await Promise.resolve().then(() => __importStar(require("onnxruntime-node")));
|
|
706
|
-
const sess = this.session;
|
|
707
|
-
const inputName = sess.inputNames[0];
|
|
708
|
-
const tensor = new ort.Tensor("float32", input, [...inputShape]);
|
|
709
|
-
const feeds = { [inputName]: tensor };
|
|
710
|
-
const results = await sess.run(feeds);
|
|
711
|
-
const outputName = sess.outputNames[0];
|
|
712
|
-
const outputTensor = results[outputName];
|
|
713
|
-
return outputTensor.data;
|
|
714
|
-
}
|
|
715
|
-
async runMultiOutput(input, inputShape) {
|
|
716
|
-
if (!this.session) {
|
|
717
|
-
throw new Error("NodeInferenceEngine: not initialized \u2014 call initialize() first");
|
|
718
|
-
}
|
|
719
|
-
const ort = await Promise.resolve().then(() => __importStar(require("onnxruntime-node")));
|
|
720
|
-
const sess = this.session;
|
|
721
|
-
const inputName = sess.inputNames[0];
|
|
722
|
-
const tensor = new ort.Tensor("float32", input, [...inputShape]);
|
|
723
|
-
const feeds = { [inputName]: tensor };
|
|
724
|
-
const results = await sess.run(feeds);
|
|
725
|
-
const out = {};
|
|
726
|
-
for (const name of sess.outputNames) {
|
|
727
|
-
out[name] = results[name].data;
|
|
728
|
-
}
|
|
729
|
-
return out;
|
|
447
|
+
// src/catalogs/animal-classification-models.ts
|
|
448
|
+
var HF_REPO2 = "camstack/camstack-models";
|
|
449
|
+
var hf = (path4) => (0, import_types2.hfModelUrl)(HF_REPO2, path4);
|
|
450
|
+
var BIRD_LABEL = { id: "species", name: "Bird Species" };
|
|
451
|
+
var ANIMAL_TYPE_LABEL = { id: "animal-type", name: "Animal Type" };
|
|
452
|
+
var BIRD_SPECIES_MODELS = [
|
|
453
|
+
{
|
|
454
|
+
id: "bird-species-525",
|
|
455
|
+
name: "Bird Species (525)",
|
|
456
|
+
description: "EfficientNet bird species classifier \u2014 525 species, MIT license",
|
|
457
|
+
inputSize: { width: 224, height: 224 },
|
|
458
|
+
inputNormalization: "imagenet",
|
|
459
|
+
labels: [BIRD_LABEL],
|
|
460
|
+
formats: {
|
|
461
|
+
onnx: { url: hf("animalClassification/bird-species/onnx/camstack-bird-species-525.onnx"), sizeMB: 32 }
|
|
462
|
+
},
|
|
463
|
+
extraFiles: [
|
|
464
|
+
{
|
|
465
|
+
url: hf("animalClassification/bird-species/onnx/camstack-bird-species-525-labels.json"),
|
|
466
|
+
filename: "camstack-bird-species-525-labels.json",
|
|
467
|
+
sizeMB: 0.02
|
|
730
468
|
}
|
|
731
|
-
|
|
732
|
-
|
|
469
|
+
]
|
|
470
|
+
}
|
|
471
|
+
];
|
|
472
|
+
var BIRD_NABIRDS_MODELS = [
|
|
473
|
+
{
|
|
474
|
+
id: "bird-nabirds-404",
|
|
475
|
+
name: "NABirds (404 species)",
|
|
476
|
+
description: "ResNet50 trained on NABirds \u2014 404 North American species with ONNX, CoreML, OpenVINO",
|
|
477
|
+
inputSize: { width: 224, height: 224 },
|
|
478
|
+
inputNormalization: "imagenet",
|
|
479
|
+
labels: [{ id: "species", name: "Bird Species" }],
|
|
480
|
+
formats: {
|
|
481
|
+
onnx: { url: hf("animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404.onnx"), sizeMB: 93 },
|
|
482
|
+
coreml: { url: hf("animalClassification/bird-nabirds/coreml/camstack-bird-nabirds-404.mlpackage"), sizeMB: 47, isDirectory: true, files: MLPACKAGE_FILES, runtimes: ["python"] },
|
|
483
|
+
openvino: { url: hf("animalClassification/bird-nabirds/openvino/camstack-bird-nabirds-404.xml"), sizeMB: 47, runtimes: ["python"] }
|
|
484
|
+
},
|
|
485
|
+
extraFiles: [
|
|
486
|
+
{
|
|
487
|
+
url: hf("animalClassification/bird-nabirds/onnx/camstack-bird-nabirds-404-labels.json"),
|
|
488
|
+
filename: "camstack-bird-nabirds-404-labels.json",
|
|
489
|
+
sizeMB: 0.02
|
|
733
490
|
}
|
|
734
|
-
|
|
735
|
-
exports2.NodeInferenceEngine = NodeInferenceEngine;
|
|
491
|
+
]
|
|
736
492
|
}
|
|
737
|
-
|
|
493
|
+
];
|
|
494
|
+
var ANIMAL_TYPE_MODELS = [
|
|
495
|
+
{
|
|
496
|
+
id: "animals-10",
|
|
497
|
+
name: "Animal Classifier (10)",
|
|
498
|
+
description: "ViT-based animal type classifier \u2014 cat, cow, dog, dolphin, eagle, panda, horse, monkey, sheep, spider",
|
|
499
|
+
inputSize: { width: 224, height: 224 },
|
|
500
|
+
inputNormalization: "imagenet",
|
|
501
|
+
labels: [ANIMAL_TYPE_LABEL],
|
|
502
|
+
formats: {
|
|
503
|
+
onnx: { url: hf("animalClassification/animals-10/onnx/camstack-animals-10.onnx"), sizeMB: 328 }
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
];
|
|
738
507
|
|
|
739
|
-
// src/shared/
|
|
740
|
-
var
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
pytorch: "cpu",
|
|
768
|
-
openvino: "cpu",
|
|
769
|
-
tflite: "cpu"
|
|
770
|
-
};
|
|
771
|
-
this.device = runtimeDeviceMap[runtime];
|
|
772
|
-
}
|
|
773
|
-
async initialize() {
|
|
774
|
-
const args = [this.scriptPath, this.modelPath, ...this.extraArgs];
|
|
775
|
-
this.process = (0, node_child_process_1.spawn)(this.pythonPath, args, {
|
|
776
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
777
|
-
});
|
|
778
|
-
if (!this.process.stdout || !this.process.stdin) {
|
|
779
|
-
throw new Error("PythonInferenceEngine: failed to create process pipes");
|
|
780
|
-
}
|
|
781
|
-
this.process.stderr?.on("data", (chunk) => {
|
|
782
|
-
process.stderr.write(`[python-engine] ${chunk.toString()}`);
|
|
783
|
-
});
|
|
784
|
-
this.process.on("error", (err) => {
|
|
785
|
-
this.pendingReject?.(err);
|
|
786
|
-
this.pendingReject = null;
|
|
787
|
-
this.pendingResolve = null;
|
|
788
|
-
});
|
|
789
|
-
this.process.on("exit", (code) => {
|
|
790
|
-
if (code !== 0) {
|
|
791
|
-
const err = new Error(`PythonInferenceEngine: process exited with code ${code}`);
|
|
792
|
-
this.pendingReject?.(err);
|
|
793
|
-
this.pendingReject = null;
|
|
794
|
-
this.pendingResolve = null;
|
|
795
|
-
}
|
|
796
|
-
});
|
|
797
|
-
this.process.stdout.on("data", (chunk) => {
|
|
798
|
-
this.receiveBuffer = Buffer.concat([this.receiveBuffer, chunk]);
|
|
799
|
-
this._tryReceive();
|
|
800
|
-
});
|
|
801
|
-
await new Promise((resolve, reject) => {
|
|
802
|
-
const timeout = setTimeout(() => resolve(), 2e3);
|
|
803
|
-
this.process?.on("error", (err) => {
|
|
804
|
-
clearTimeout(timeout);
|
|
805
|
-
reject(err);
|
|
806
|
-
});
|
|
807
|
-
this.process?.on("exit", (code) => {
|
|
808
|
-
clearTimeout(timeout);
|
|
809
|
-
if (code !== 0) {
|
|
810
|
-
reject(new Error(`PythonInferenceEngine: process exited early with code ${code}`));
|
|
811
|
-
}
|
|
812
|
-
});
|
|
813
|
-
});
|
|
814
|
-
}
|
|
815
|
-
_tryReceive() {
|
|
816
|
-
if (this.receiveBuffer.length < 4)
|
|
817
|
-
return;
|
|
818
|
-
const length = this.receiveBuffer.readUInt32LE(0);
|
|
819
|
-
if (this.receiveBuffer.length < 4 + length)
|
|
820
|
-
return;
|
|
821
|
-
const jsonBytes = this.receiveBuffer.subarray(4, 4 + length);
|
|
822
|
-
this.receiveBuffer = this.receiveBuffer.subarray(4 + length);
|
|
823
|
-
const resolve = this.pendingResolve;
|
|
824
|
-
const reject = this.pendingReject;
|
|
825
|
-
this.pendingResolve = null;
|
|
826
|
-
this.pendingReject = null;
|
|
827
|
-
if (!resolve)
|
|
828
|
-
return;
|
|
829
|
-
try {
|
|
830
|
-
const parsed = JSON.parse(jsonBytes.toString("utf8"));
|
|
831
|
-
resolve(parsed);
|
|
832
|
-
} catch (err) {
|
|
833
|
-
reject?.(err instanceof Error ? err : new Error(String(err)));
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
/** Send JPEG buffer, receive JSON detection results */
|
|
837
|
-
async runJpeg(jpeg) {
|
|
838
|
-
if (!this.process?.stdin) {
|
|
839
|
-
throw new Error("PythonInferenceEngine: process not initialized");
|
|
508
|
+
// src/shared/image-utils.ts
|
|
509
|
+
var import_sharp = __toESM(require("sharp"));
|
|
510
|
+
async function cropRegion(jpeg, roi) {
|
|
511
|
+
return (0, import_sharp.default)(jpeg).extract({
|
|
512
|
+
left: Math.round(roi.x),
|
|
513
|
+
top: Math.round(roi.y),
|
|
514
|
+
width: Math.round(roi.w),
|
|
515
|
+
height: Math.round(roi.h)
|
|
516
|
+
}).jpeg().toBuffer();
|
|
517
|
+
}
|
|
518
|
+
async function resizeAndNormalize(jpeg, targetWidth, targetHeight, normalization, layout) {
|
|
519
|
+
const { data } = await (0, import_sharp.default)(jpeg).resize(targetWidth, targetHeight, { fit: "fill" }).removeAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
520
|
+
const numPixels = targetWidth * targetHeight;
|
|
521
|
+
const float32 = new Float32Array(3 * numPixels);
|
|
522
|
+
const mean = [0.485, 0.456, 0.406];
|
|
523
|
+
const std = [0.229, 0.224, 0.225];
|
|
524
|
+
if (layout === "nchw") {
|
|
525
|
+
for (let i = 0; i < numPixels; i++) {
|
|
526
|
+
const srcBase = i * 3;
|
|
527
|
+
for (let c = 0; c < 3; c++) {
|
|
528
|
+
const raw = data[srcBase + c] / 255;
|
|
529
|
+
let val;
|
|
530
|
+
if (normalization === "zero-one") {
|
|
531
|
+
val = raw;
|
|
532
|
+
} else if (normalization === "imagenet") {
|
|
533
|
+
val = (raw - mean[c]) / std[c];
|
|
534
|
+
} else {
|
|
535
|
+
val = data[srcBase + c];
|
|
840
536
|
}
|
|
841
|
-
|
|
842
|
-
this.pendingResolve = resolve;
|
|
843
|
-
this.pendingReject = reject;
|
|
844
|
-
const lengthBuf = Buffer.allocUnsafe(4);
|
|
845
|
-
lengthBuf.writeUInt32LE(jpeg.length, 0);
|
|
846
|
-
this.process.stdin.write(Buffer.concat([lengthBuf, jpeg]));
|
|
847
|
-
});
|
|
848
|
-
}
|
|
849
|
-
/** IInferenceEngine.run — wraps runJpeg for compatibility */
|
|
850
|
-
async run(_input, _inputShape) {
|
|
851
|
-
throw new Error("PythonInferenceEngine: use runJpeg() directly \u2014 this engine operates on JPEG input");
|
|
852
|
-
}
|
|
853
|
-
/** IInferenceEngine.runMultiOutput — not supported by Python engine (operates on JPEG input) */
|
|
854
|
-
async runMultiOutput(_input, _inputShape) {
|
|
855
|
-
throw new Error("PythonInferenceEngine: runMultiOutput() is not supported \u2014 this engine operates on JPEG input");
|
|
537
|
+
float32[c * numPixels + i] = val;
|
|
856
538
|
}
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
539
|
+
}
|
|
540
|
+
} else {
|
|
541
|
+
for (let i = 0; i < numPixels; i++) {
|
|
542
|
+
const srcBase = i * 3;
|
|
543
|
+
for (let c = 0; c < 3; c++) {
|
|
544
|
+
const raw = data[srcBase + c] / 255;
|
|
545
|
+
let val;
|
|
546
|
+
if (normalization === "zero-one") {
|
|
547
|
+
val = raw;
|
|
548
|
+
} else if (normalization === "imagenet") {
|
|
549
|
+
val = (raw - mean[c]) / std[c];
|
|
550
|
+
} else {
|
|
551
|
+
val = data[srcBase + c];
|
|
862
552
|
}
|
|
553
|
+
float32[i * 3 + c] = val;
|
|
863
554
|
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return float32;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// src/shared/engine-resolver.ts
|
|
561
|
+
var fs = __toESM(require("fs"));
|
|
562
|
+
var path2 = __toESM(require("path"));
|
|
563
|
+
|
|
564
|
+
// src/shared/node-engine.ts
|
|
565
|
+
var path = __toESM(require("path"));
|
|
566
|
+
var BACKEND_TO_PROVIDER = {
|
|
567
|
+
cpu: "cpu",
|
|
568
|
+
coreml: "coreml",
|
|
569
|
+
cuda: "cuda",
|
|
570
|
+
tensorrt: "tensorrt",
|
|
571
|
+
dml: "dml"
|
|
572
|
+
};
|
|
573
|
+
var BACKEND_TO_DEVICE = {
|
|
574
|
+
cpu: "cpu",
|
|
575
|
+
coreml: "gpu-mps",
|
|
576
|
+
cuda: "gpu-cuda",
|
|
577
|
+
tensorrt: "tensorrt"
|
|
578
|
+
};
|
|
579
|
+
var NodeInferenceEngine = class {
|
|
580
|
+
constructor(modelPath, backend) {
|
|
581
|
+
this.modelPath = modelPath;
|
|
582
|
+
this.backend = backend;
|
|
583
|
+
this.device = BACKEND_TO_DEVICE[backend] ?? "cpu";
|
|
584
|
+
}
|
|
585
|
+
runtime = "onnx";
|
|
586
|
+
device;
|
|
587
|
+
session = null;
|
|
588
|
+
async initialize() {
|
|
589
|
+
const ort = await import("onnxruntime-node");
|
|
590
|
+
const provider = BACKEND_TO_PROVIDER[this.backend] ?? "cpu";
|
|
591
|
+
const absModelPath = path.isAbsolute(this.modelPath) ? this.modelPath : path.resolve(process.cwd(), this.modelPath);
|
|
592
|
+
const sessionOptions = {
|
|
593
|
+
executionProviders: [provider]
|
|
864
594
|
};
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
595
|
+
this.session = await ort.InferenceSession.create(absModelPath, sessionOptions);
|
|
596
|
+
}
|
|
597
|
+
async run(input, inputShape) {
|
|
598
|
+
if (!this.session) {
|
|
599
|
+
throw new Error("NodeInferenceEngine: not initialized \u2014 call initialize() first");
|
|
870
600
|
}
|
|
601
|
+
const ort = await import("onnxruntime-node");
|
|
602
|
+
const sess = this.session;
|
|
603
|
+
const inputName = sess.inputNames[0];
|
|
604
|
+
const tensor = new ort.Tensor("float32", input, [...inputShape]);
|
|
605
|
+
const feeds = { [inputName]: tensor };
|
|
606
|
+
const results = await sess.run(feeds);
|
|
607
|
+
const outputName = sess.outputNames[0];
|
|
608
|
+
const outputTensor = results[outputName];
|
|
609
|
+
return outputTensor.data;
|
|
871
610
|
}
|
|
872
|
-
|
|
611
|
+
async runMultiOutput(input, inputShape) {
|
|
612
|
+
if (!this.session) {
|
|
613
|
+
throw new Error("NodeInferenceEngine: not initialized \u2014 call initialize() first");
|
|
614
|
+
}
|
|
615
|
+
const ort = await import("onnxruntime-node");
|
|
616
|
+
const sess = this.session;
|
|
617
|
+
const inputName = sess.inputNames[0];
|
|
618
|
+
const tensor = new ort.Tensor("float32", input, [...inputShape]);
|
|
619
|
+
const feeds = { [inputName]: tensor };
|
|
620
|
+
const results = await sess.run(feeds);
|
|
621
|
+
const out = {};
|
|
622
|
+
for (const name of sess.outputNames) {
|
|
623
|
+
out[name] = results[name].data;
|
|
624
|
+
}
|
|
625
|
+
return out;
|
|
626
|
+
}
|
|
627
|
+
async dispose() {
|
|
628
|
+
this.session = null;
|
|
629
|
+
}
|
|
630
|
+
};
|
|
873
631
|
|
|
874
|
-
// src/shared/engine
|
|
875
|
-
var
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
632
|
+
// src/shared/python-engine.ts
|
|
633
|
+
var import_node_child_process = require("child_process");
|
|
634
|
+
var PythonInferenceEngine = class {
|
|
635
|
+
constructor(pythonPath, scriptPath, runtime, modelPath, extraArgs = []) {
|
|
636
|
+
this.pythonPath = pythonPath;
|
|
637
|
+
this.scriptPath = scriptPath;
|
|
638
|
+
this.modelPath = modelPath;
|
|
639
|
+
this.extraArgs = extraArgs;
|
|
640
|
+
this.runtime = runtime;
|
|
641
|
+
const runtimeDeviceMap = {
|
|
642
|
+
onnx: "cpu",
|
|
643
|
+
coreml: "gpu-mps",
|
|
644
|
+
pytorch: "cpu",
|
|
645
|
+
openvino: "cpu",
|
|
646
|
+
tflite: "cpu"
|
|
647
|
+
};
|
|
648
|
+
this.device = runtimeDeviceMap[runtime];
|
|
649
|
+
}
|
|
650
|
+
runtime;
|
|
651
|
+
device;
|
|
652
|
+
process = null;
|
|
653
|
+
receiveBuffer = Buffer.alloc(0);
|
|
654
|
+
pendingResolve = null;
|
|
655
|
+
pendingReject = null;
|
|
656
|
+
async initialize() {
|
|
657
|
+
const args = [this.scriptPath, this.modelPath, ...this.extraArgs];
|
|
658
|
+
this.process = (0, import_node_child_process.spawn)(this.pythonPath, args, {
|
|
659
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
660
|
+
});
|
|
661
|
+
if (!this.process.stdout || !this.process.stdin) {
|
|
662
|
+
throw new Error("PythonInferenceEngine: failed to create process pipes");
|
|
663
|
+
}
|
|
664
|
+
this.process.stderr?.on("data", (chunk) => {
|
|
665
|
+
process.stderr.write(`[python-engine] ${chunk.toString()}`);
|
|
666
|
+
});
|
|
667
|
+
this.process.on("error", (err) => {
|
|
668
|
+
this.pendingReject?.(err);
|
|
669
|
+
this.pendingReject = null;
|
|
670
|
+
this.pendingResolve = null;
|
|
671
|
+
});
|
|
672
|
+
this.process.on("exit", (code) => {
|
|
673
|
+
if (code !== 0) {
|
|
674
|
+
const err = new Error(`PythonInferenceEngine: process exited with code ${code}`);
|
|
675
|
+
this.pendingReject?.(err);
|
|
676
|
+
this.pendingReject = null;
|
|
677
|
+
this.pendingResolve = null;
|
|
885
678
|
}
|
|
886
|
-
Object.defineProperty(o, k2, desc);
|
|
887
|
-
}) : (function(o, m, k, k2) {
|
|
888
|
-
if (k2 === void 0) k2 = k;
|
|
889
|
-
o[k2] = m[k];
|
|
890
|
-
}));
|
|
891
|
-
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
892
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
893
|
-
}) : function(o, v) {
|
|
894
|
-
o["default"] = v;
|
|
895
679
|
});
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
if (
|
|
909
|
-
|
|
680
|
+
this.process.stdout.on("data", (chunk) => {
|
|
681
|
+
this.receiveBuffer = Buffer.concat([this.receiveBuffer, chunk]);
|
|
682
|
+
this._tryReceive();
|
|
683
|
+
});
|
|
684
|
+
await new Promise((resolve2, reject) => {
|
|
685
|
+
const timeout = setTimeout(() => resolve2(), 2e3);
|
|
686
|
+
this.process?.on("error", (err) => {
|
|
687
|
+
clearTimeout(timeout);
|
|
688
|
+
reject(err);
|
|
689
|
+
});
|
|
690
|
+
this.process?.on("exit", (code) => {
|
|
691
|
+
clearTimeout(timeout);
|
|
692
|
+
if (code !== 0) {
|
|
693
|
+
reject(new Error(`PythonInferenceEngine: process exited early with code ${code}`));
|
|
910
694
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
onnx: "onnx",
|
|
931
|
-
coreml: "coreml",
|
|
932
|
-
openvino: "openvino",
|
|
933
|
-
tflite: "tflite",
|
|
934
|
-
pytorch: "pt"
|
|
935
|
-
};
|
|
936
|
-
function modelFilePath(modelsDir, modelEntry, format) {
|
|
937
|
-
const formatEntry = modelEntry.formats[format];
|
|
938
|
-
if (!formatEntry) {
|
|
939
|
-
throw new Error(`Model ${modelEntry.id} has no ${format} format`);
|
|
940
|
-
}
|
|
941
|
-
const urlParts = formatEntry.url.split("/");
|
|
942
|
-
const filename = urlParts[urlParts.length - 1] ?? `${modelEntry.id}.${format}`;
|
|
943
|
-
return path2.join(modelsDir, filename);
|
|
695
|
+
});
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
_tryReceive() {
|
|
699
|
+
if (this.receiveBuffer.length < 4) return;
|
|
700
|
+
const length = this.receiveBuffer.readUInt32LE(0);
|
|
701
|
+
if (this.receiveBuffer.length < 4 + length) return;
|
|
702
|
+
const jsonBytes = this.receiveBuffer.subarray(4, 4 + length);
|
|
703
|
+
this.receiveBuffer = this.receiveBuffer.subarray(4 + length);
|
|
704
|
+
const resolve2 = this.pendingResolve;
|
|
705
|
+
const reject = this.pendingReject;
|
|
706
|
+
this.pendingResolve = null;
|
|
707
|
+
this.pendingReject = null;
|
|
708
|
+
if (!resolve2) return;
|
|
709
|
+
try {
|
|
710
|
+
const parsed = JSON.parse(jsonBytes.toString("utf8"));
|
|
711
|
+
resolve2(parsed);
|
|
712
|
+
} catch (err) {
|
|
713
|
+
reject?.(err instanceof Error ? err : new Error(String(err)));
|
|
944
714
|
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
}
|
|
715
|
+
}
|
|
716
|
+
/** Send JPEG buffer, receive JSON detection results */
|
|
717
|
+
async runJpeg(jpeg) {
|
|
718
|
+
if (!this.process?.stdin) {
|
|
719
|
+
throw new Error("PythonInferenceEngine: process not initialized");
|
|
951
720
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
if (!fmt) {
|
|
978
|
-
throw new Error(`resolveEngine: unsupported runtime "${runtime}"`);
|
|
979
|
-
}
|
|
980
|
-
if (!modelEntry.formats[fmt]) {
|
|
981
|
-
throw new Error(`resolveEngine: model ${modelEntry.id} has no ${fmt} format for runtime ${runtime}`);
|
|
982
|
-
}
|
|
983
|
-
selectedFormat = fmt;
|
|
984
|
-
selectedBackend = runtime === "onnx" ? backend || "cpu" : runtime;
|
|
985
|
-
}
|
|
986
|
-
let modelPath;
|
|
987
|
-
if (models) {
|
|
988
|
-
modelPath = await models.ensure(modelEntry.id, selectedFormat);
|
|
989
|
-
} else {
|
|
990
|
-
modelPath = modelFilePath(modelsDir, modelEntry, selectedFormat);
|
|
991
|
-
if (!modelExists(modelPath)) {
|
|
992
|
-
throw new Error(`resolveEngine: model file not found at ${modelPath} and no model service provided`);
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
if (selectedFormat === "onnx") {
|
|
996
|
-
const engine = new node_engine_js_1.NodeInferenceEngine(modelPath, selectedBackend);
|
|
997
|
-
await engine.initialize();
|
|
998
|
-
return { engine, format: selectedFormat, modelPath };
|
|
999
|
-
}
|
|
1000
|
-
const { pythonPath } = options;
|
|
1001
|
-
const PYTHON_SCRIPT_MAP = {
|
|
1002
|
-
coreml: "coreml_inference.py",
|
|
1003
|
-
pytorch: "pytorch_inference.py",
|
|
1004
|
-
openvino: "openvino_inference.py"
|
|
1005
|
-
};
|
|
1006
|
-
const effectiveRuntime = runtime === "auto" ? selectedBackend : runtime;
|
|
1007
|
-
const scriptName = PYTHON_SCRIPT_MAP[effectiveRuntime];
|
|
1008
|
-
if (scriptName && pythonPath) {
|
|
1009
|
-
const candidates = [
|
|
1010
|
-
path2.join(__dirname, "../../python", scriptName),
|
|
1011
|
-
path2.join(__dirname, "../python", scriptName),
|
|
1012
|
-
path2.join(__dirname, "../../../python", scriptName)
|
|
1013
|
-
];
|
|
1014
|
-
const scriptPath = candidates.find((p) => fs2.existsSync(p));
|
|
1015
|
-
if (!scriptPath) {
|
|
1016
|
-
throw new Error(`resolveEngine: Python script "${scriptName}" not found. Searched:
|
|
1017
|
-
${candidates.join("\n")}`);
|
|
1018
|
-
}
|
|
1019
|
-
const inputSize = Math.max(modelEntry.inputSize.width, modelEntry.inputSize.height);
|
|
1020
|
-
const engine = new python_engine_js_1.PythonInferenceEngine(pythonPath, scriptPath, effectiveRuntime, modelPath, [
|
|
1021
|
-
`--input-size=${inputSize}`,
|
|
1022
|
-
`--confidence=0.25`
|
|
1023
|
-
]);
|
|
1024
|
-
await engine.initialize();
|
|
1025
|
-
return { engine, format: selectedFormat, modelPath };
|
|
1026
|
-
}
|
|
1027
|
-
const fallbackPath = modelFilePath(modelsDir, modelEntry, "onnx");
|
|
1028
|
-
if (modelEntry.formats["onnx"] && modelExists(fallbackPath)) {
|
|
1029
|
-
const engine = new node_engine_js_1.NodeInferenceEngine(fallbackPath, "cpu");
|
|
1030
|
-
await engine.initialize();
|
|
1031
|
-
return { engine, format: "onnx", modelPath: fallbackPath };
|
|
1032
|
-
}
|
|
1033
|
-
throw new Error(`resolveEngine: format ${selectedFormat} is not yet supported by NodeInferenceEngine, no Python runtime is available, and no ONNX fallback exists`);
|
|
721
|
+
return new Promise((resolve2, reject) => {
|
|
722
|
+
this.pendingResolve = resolve2;
|
|
723
|
+
this.pendingReject = reject;
|
|
724
|
+
const lengthBuf = Buffer.allocUnsafe(4);
|
|
725
|
+
lengthBuf.writeUInt32LE(jpeg.length, 0);
|
|
726
|
+
this.process.stdin.write(Buffer.concat([lengthBuf, jpeg]));
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
/** IInferenceEngine.run — wraps runJpeg for compatibility */
|
|
730
|
+
async run(_input, _inputShape) {
|
|
731
|
+
throw new Error(
|
|
732
|
+
"PythonInferenceEngine: use runJpeg() directly \u2014 this engine operates on JPEG input"
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
/** IInferenceEngine.runMultiOutput — not supported by Python engine (operates on JPEG input) */
|
|
736
|
+
async runMultiOutput(_input, _inputShape) {
|
|
737
|
+
throw new Error(
|
|
738
|
+
"PythonInferenceEngine: runMultiOutput() is not supported \u2014 this engine operates on JPEG input"
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
async dispose() {
|
|
742
|
+
if (this.process) {
|
|
743
|
+
this.process.stdin?.end();
|
|
744
|
+
this.process.kill("SIGTERM");
|
|
745
|
+
this.process = null;
|
|
1034
746
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
// src/shared/engine-resolver.ts
|
|
751
|
+
var AUTO_BACKEND_PRIORITY = ["coreml", "cuda", "tensorrt", "cpu"];
|
|
752
|
+
var BACKEND_TO_FORMAT = {
|
|
753
|
+
cpu: "onnx",
|
|
754
|
+
coreml: "onnx",
|
|
755
|
+
cuda: "onnx",
|
|
756
|
+
tensorrt: "onnx"
|
|
757
|
+
};
|
|
758
|
+
var RUNTIME_TO_FORMAT = {
|
|
759
|
+
onnx: "onnx",
|
|
760
|
+
coreml: "coreml",
|
|
761
|
+
openvino: "openvino",
|
|
762
|
+
tflite: "tflite",
|
|
763
|
+
pytorch: "pt"
|
|
764
|
+
};
|
|
765
|
+
function modelFilePath(modelsDir, modelEntry, format) {
|
|
766
|
+
const formatEntry = modelEntry.formats[format];
|
|
767
|
+
if (!formatEntry) {
|
|
768
|
+
throw new Error(`Model ${modelEntry.id} has no ${format} format`);
|
|
769
|
+
}
|
|
770
|
+
const urlParts = formatEntry.url.split("/");
|
|
771
|
+
const filename = urlParts[urlParts.length - 1] ?? `${modelEntry.id}.${format}`;
|
|
772
|
+
return path2.join(modelsDir, filename);
|
|
773
|
+
}
|
|
774
|
+
function modelExists(filePath) {
|
|
775
|
+
try {
|
|
776
|
+
return fs.existsSync(filePath);
|
|
777
|
+
} catch {
|
|
778
|
+
return false;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
async function resolveEngine(options) {
|
|
782
|
+
const { runtime, backend, modelEntry, modelsDir, models } = options;
|
|
783
|
+
let selectedFormat;
|
|
784
|
+
let selectedBackend;
|
|
785
|
+
if (runtime === "auto") {
|
|
786
|
+
const available = await probeOnnxBackends();
|
|
787
|
+
let chosen = null;
|
|
788
|
+
for (const b of AUTO_BACKEND_PRIORITY) {
|
|
789
|
+
if (!available.includes(b)) continue;
|
|
790
|
+
const fmt = BACKEND_TO_FORMAT[b];
|
|
791
|
+
if (!fmt) continue;
|
|
792
|
+
if (!modelEntry.formats[fmt]) continue;
|
|
793
|
+
chosen = { backend: b, format: fmt };
|
|
794
|
+
break;
|
|
795
|
+
}
|
|
796
|
+
if (!chosen) {
|
|
797
|
+
throw new Error(
|
|
798
|
+
`resolveEngine: no compatible backend found for model ${modelEntry.id}. Available backends: ${available.join(", ")}`
|
|
799
|
+
);
|
|
1055
800
|
}
|
|
801
|
+
selectedFormat = chosen.format;
|
|
802
|
+
selectedBackend = chosen.backend;
|
|
803
|
+
} else {
|
|
804
|
+
const fmt = RUNTIME_TO_FORMAT[runtime];
|
|
805
|
+
if (!fmt) {
|
|
806
|
+
throw new Error(`resolveEngine: unsupported runtime "${runtime}"`);
|
|
807
|
+
}
|
|
808
|
+
if (!modelEntry.formats[fmt]) {
|
|
809
|
+
throw new Error(
|
|
810
|
+
`resolveEngine: model ${modelEntry.id} has no ${fmt} format for runtime ${runtime}`
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
selectedFormat = fmt;
|
|
814
|
+
selectedBackend = runtime === "onnx" ? backend || "cpu" : runtime;
|
|
1056
815
|
}
|
|
1057
|
-
|
|
816
|
+
let modelPath;
|
|
817
|
+
if (models) {
|
|
818
|
+
modelPath = await models.ensure(modelEntry.id, selectedFormat);
|
|
819
|
+
} else {
|
|
820
|
+
modelPath = modelFilePath(modelsDir, modelEntry, selectedFormat);
|
|
821
|
+
if (!modelExists(modelPath)) {
|
|
822
|
+
throw new Error(
|
|
823
|
+
`resolveEngine: model file not found at ${modelPath} and no model service provided`
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
if (selectedFormat === "onnx") {
|
|
828
|
+
const engine = new NodeInferenceEngine(modelPath, selectedBackend);
|
|
829
|
+
await engine.initialize();
|
|
830
|
+
return { engine, format: selectedFormat, modelPath };
|
|
831
|
+
}
|
|
832
|
+
const { pythonPath } = options;
|
|
833
|
+
const PYTHON_SCRIPT_MAP = {
|
|
834
|
+
coreml: "coreml_inference.py",
|
|
835
|
+
pytorch: "pytorch_inference.py",
|
|
836
|
+
openvino: "openvino_inference.py"
|
|
837
|
+
};
|
|
838
|
+
const effectiveRuntime = runtime === "auto" ? selectedBackend : runtime;
|
|
839
|
+
const scriptName = PYTHON_SCRIPT_MAP[effectiveRuntime];
|
|
840
|
+
if (scriptName && pythonPath) {
|
|
841
|
+
const candidates = [
|
|
842
|
+
path2.join(__dirname, "../../python", scriptName),
|
|
843
|
+
path2.join(__dirname, "../python", scriptName),
|
|
844
|
+
path2.join(__dirname, "../../../python", scriptName)
|
|
845
|
+
];
|
|
846
|
+
const scriptPath = candidates.find((p) => fs.existsSync(p));
|
|
847
|
+
if (!scriptPath) {
|
|
848
|
+
throw new Error(
|
|
849
|
+
`resolveEngine: Python script "${scriptName}" not found. Searched:
|
|
850
|
+
${candidates.join("\n")}`
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
const inputSize = Math.max(modelEntry.inputSize.width, modelEntry.inputSize.height);
|
|
854
|
+
const engine = new PythonInferenceEngine(pythonPath, scriptPath, effectiveRuntime, modelPath, [
|
|
855
|
+
`--input-size=${inputSize}`,
|
|
856
|
+
`--confidence=0.25`
|
|
857
|
+
]);
|
|
858
|
+
await engine.initialize();
|
|
859
|
+
return { engine, format: selectedFormat, modelPath };
|
|
860
|
+
}
|
|
861
|
+
const fallbackPath = modelFilePath(modelsDir, modelEntry, "onnx");
|
|
862
|
+
if (modelEntry.formats["onnx"] && modelExists(fallbackPath)) {
|
|
863
|
+
const engine = new NodeInferenceEngine(fallbackPath, "cpu");
|
|
864
|
+
await engine.initialize();
|
|
865
|
+
return { engine, format: "onnx", modelPath: fallbackPath };
|
|
866
|
+
}
|
|
867
|
+
throw new Error(
|
|
868
|
+
`resolveEngine: format ${selectedFormat} is not yet supported by NodeInferenceEngine, no Python runtime is available, and no ONNX fallback exists`
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
async function probeOnnxBackends() {
|
|
872
|
+
const available = ["cpu"];
|
|
873
|
+
try {
|
|
874
|
+
const ort = await import("onnxruntime-node");
|
|
875
|
+
const providers = ort.env?.webgl?.disabled !== void 0 ? ort.InferenceSession?.getAvailableProviders?.() ?? [] : [];
|
|
876
|
+
for (const p of providers) {
|
|
877
|
+
const normalized = p.toLowerCase().replace("executionprovider", "");
|
|
878
|
+
if (normalized === "coreml") available.push("coreml");
|
|
879
|
+
else if (normalized === "cuda") available.push("cuda");
|
|
880
|
+
else if (normalized === "tensorrt") available.push("tensorrt");
|
|
881
|
+
}
|
|
882
|
+
} catch {
|
|
883
|
+
}
|
|
884
|
+
if (process.platform === "darwin" && !available.includes("coreml")) {
|
|
885
|
+
available.push("coreml");
|
|
886
|
+
}
|
|
887
|
+
return [...new Set(available)];
|
|
888
|
+
}
|
|
1058
889
|
|
|
1059
890
|
// src/addons/bird-global-classifier/index.ts
|
|
1060
|
-
var
|
|
1061
|
-
|
|
1062
|
-
default: () => BirdGlobalClassifierAddon
|
|
1063
|
-
});
|
|
1064
|
-
module.exports = __toCommonJS(bird_global_classifier_exports);
|
|
1065
|
-
var import_animal_classification_models = __toESM(require_animal_classification_models());
|
|
1066
|
-
var import_image_utils = __toESM(require_image_utils());
|
|
1067
|
-
var import_engine_resolver = __toESM(require_engine_resolver());
|
|
1068
|
-
var fs = __toESM(require("fs"));
|
|
1069
|
-
var path = __toESM(require("path"));
|
|
891
|
+
var fs2 = __toESM(require("fs"));
|
|
892
|
+
var path3 = __toESM(require("path"));
|
|
1070
893
|
var SPECIES_LABEL = { id: "species", name: "Bird Species" };
|
|
1071
894
|
var SPECIES_LABELS = [SPECIES_LABEL];
|
|
1072
895
|
var BIRD_CLASS_MAP = { mapping: {}, preserveOriginal: true };
|
|
@@ -1076,9 +899,9 @@ function loadLabels(modelsDir, modelId) {
|
|
|
1076
899
|
`camstack-bird-species-525-labels.json`
|
|
1077
900
|
];
|
|
1078
901
|
for (const name of labelNames) {
|
|
1079
|
-
const labelPath =
|
|
1080
|
-
if (
|
|
1081
|
-
const raw =
|
|
902
|
+
const labelPath = path3.join(modelsDir, name);
|
|
903
|
+
if (fs2.existsSync(labelPath)) {
|
|
904
|
+
const raw = fs2.readFileSync(labelPath, "utf-8");
|
|
1082
905
|
return JSON.parse(raw);
|
|
1083
906
|
}
|
|
1084
907
|
}
|
|
@@ -1122,7 +945,7 @@ var BirdGlobalClassifierAddon = class {
|
|
|
1122
945
|
resolvedConfig = null;
|
|
1123
946
|
ctx = null;
|
|
1124
947
|
getModelRequirements() {
|
|
1125
|
-
return
|
|
948
|
+
return BIRD_SPECIES_MODELS.map((m) => ({
|
|
1126
949
|
modelId: m.id,
|
|
1127
950
|
name: m.name,
|
|
1128
951
|
minRAM_MB: 120,
|
|
@@ -1138,7 +961,7 @@ var BirdGlobalClassifierAddon = class {
|
|
|
1138
961
|
const cfg = ctx.addonConfig;
|
|
1139
962
|
const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "bird-species-525";
|
|
1140
963
|
this.minConfidence = cfg["minConfidence"] ?? 0.3;
|
|
1141
|
-
const entry =
|
|
964
|
+
const entry = BIRD_SPECIES_MODELS.find((m) => m.id === modelId);
|
|
1142
965
|
if (!entry) {
|
|
1143
966
|
throw new Error(`BirdGlobalClassifierAddon: unknown modelId "${modelId}"`);
|
|
1144
967
|
}
|
|
@@ -1148,8 +971,8 @@ var BirdGlobalClassifierAddon = class {
|
|
|
1148
971
|
if (!this.engine) await this.ensureEngine();
|
|
1149
972
|
const start = Date.now();
|
|
1150
973
|
const { width: inputW, height: inputH } = this.modelEntry.inputSize;
|
|
1151
|
-
const animalCrop = await
|
|
1152
|
-
const normalized = await
|
|
974
|
+
const animalCrop = await cropRegion(input.frame.data, input.roi);
|
|
975
|
+
const normalized = await resizeAndNormalize(animalCrop, inputW, inputH, "imagenet", "nchw");
|
|
1153
976
|
const rawOutput = await this.engine.run(normalized, [1, 3, inputH, inputW]);
|
|
1154
977
|
const probs = softmax(rawOutput);
|
|
1155
978
|
let maxIdx = 0;
|
|
@@ -1186,14 +1009,14 @@ var BirdGlobalClassifierAddon = class {
|
|
|
1186
1009
|
const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
|
|
1187
1010
|
const backend = config?.backend ?? "cpu";
|
|
1188
1011
|
const format = config?.format ?? "onnx";
|
|
1189
|
-
const entry =
|
|
1012
|
+
const entry = BIRD_SPECIES_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
|
|
1190
1013
|
this.modelEntry = entry;
|
|
1191
1014
|
const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
|
|
1192
1015
|
if (this.ctx.models) {
|
|
1193
1016
|
await this.ctx.models.ensure(modelId, format);
|
|
1194
1017
|
}
|
|
1195
1018
|
this.labels = loadLabels(modelsDir, modelId);
|
|
1196
|
-
const resolved = await
|
|
1019
|
+
const resolved = await resolveEngine({
|
|
1197
1020
|
runtime,
|
|
1198
1021
|
backend,
|
|
1199
1022
|
modelEntry: entry,
|
|
@@ -1217,7 +1040,7 @@ var BirdGlobalClassifierAddon = class {
|
|
|
1217
1040
|
key: "modelId",
|
|
1218
1041
|
label: "Model",
|
|
1219
1042
|
type: "model-selector",
|
|
1220
|
-
catalog: [...
|
|
1043
|
+
catalog: [...BIRD_SPECIES_MODELS],
|
|
1221
1044
|
allowCustom: false,
|
|
1222
1045
|
allowConversion: false,
|
|
1223
1046
|
acceptFormats: ["onnx", "coreml", "openvino"],
|
|
@@ -1279,7 +1102,7 @@ var BirdGlobalClassifierAddon = class {
|
|
|
1279
1102
|
return BIRD_CLASS_MAP;
|
|
1280
1103
|
}
|
|
1281
1104
|
getModelCatalog() {
|
|
1282
|
-
return [...
|
|
1105
|
+
return [...BIRD_SPECIES_MODELS];
|
|
1283
1106
|
}
|
|
1284
1107
|
getAvailableModels() {
|
|
1285
1108
|
return [];
|