@camstack/addon-vision 0.1.2 → 0.1.4
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.js +999 -822
- package/dist/addons/animal-classifier/index.js.map +1 -1
- package/dist/addons/animal-classifier/index.mjs +242 -7
- package/dist/addons/animal-classifier/index.mjs.map +1 -1
- package/dist/addons/audio-classification/index.js +501 -378
- package/dist/addons/audio-classification/index.js.map +1 -1
- package/dist/addons/audio-classification/index.mjs +224 -4
- package/dist/addons/audio-classification/index.mjs.map +1 -1
- package/dist/addons/bird-global-classifier/index.js +1002 -825
- package/dist/addons/bird-global-classifier/index.js.map +1 -1
- package/dist/addons/bird-global-classifier/index.mjs +248 -7
- package/dist/addons/bird-global-classifier/index.mjs.map +1 -1
- package/dist/addons/bird-nabirds-classifier/index.js +1002 -825
- package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
- package/dist/addons/bird-nabirds-classifier/index.mjs +289 -7
- package/dist/addons/bird-nabirds-classifier/index.mjs.map +1 -1
- package/dist/addons/face-detection/index.js +1196 -934
- package/dist/addons/face-detection/index.js.map +1 -1
- package/dist/addons/face-detection/index.mjs +227 -7
- package/dist/addons/face-detection/index.mjs.map +1 -1
- package/dist/addons/face-recognition/index.js +1003 -807
- package/dist/addons/face-recognition/index.js.map +1 -1
- package/dist/addons/face-recognition/index.mjs +197 -6
- package/dist/addons/face-recognition/index.mjs.map +1 -1
- package/dist/addons/motion-detection/index.js +214 -111
- package/dist/addons/motion-detection/index.js.map +1 -1
- package/dist/addons/motion-detection/index.mjs +12 -9
- package/dist/addons/motion-detection/index.mjs.map +1 -1
- package/dist/addons/object-detection/index.js +1287 -1082
- package/dist/addons/object-detection/index.js.map +1 -1
- package/dist/addons/object-detection/index.mjs +373 -7
- package/dist/addons/object-detection/index.mjs.map +1 -1
- package/dist/addons/plate-detection/index.js +1075 -868
- package/dist/addons/plate-detection/index.js.map +1 -1
- package/dist/addons/plate-detection/index.mjs +230 -7
- package/dist/addons/plate-detection/index.mjs.map +1 -1
- package/dist/addons/plate-recognition/index.js +684 -505
- package/dist/addons/plate-recognition/index.js.map +1 -1
- package/dist/addons/plate-recognition/index.mjs +244 -5
- package/dist/addons/plate-recognition/index.mjs.map +1 -1
- package/dist/addons/segmentation-refiner/index.js +967 -790
- package/dist/addons/segmentation-refiner/index.js.map +1 -1
- package/dist/addons/segmentation-refiner/index.mjs +21 -17
- package/dist/addons/segmentation-refiner/index.mjs.map +1 -1
- package/dist/addons/vehicle-classifier/index.js +581 -410
- package/dist/addons/vehicle-classifier/index.js.map +1 -1
- package/dist/addons/vehicle-classifier/index.mjs +20 -16
- package/dist/addons/vehicle-classifier/index.mjs.map +1 -1
- package/dist/chunk-2YMA6QOV.mjs +193 -0
- package/dist/chunk-2YMA6QOV.mjs.map +1 -0
- package/dist/chunk-3IIFBJCD.mjs +45 -0
- package/dist/chunk-BS4DKYGN.mjs +48 -0
- package/dist/{chunk-7DYHXUPZ.mjs.map → chunk-BS4DKYGN.mjs.map} +1 -1
- package/dist/chunk-DE7I3VHO.mjs +106 -0
- package/dist/{chunk-KUO2BVFY.mjs.map → chunk-DE7I3VHO.mjs.map} +1 -1
- package/dist/chunk-F6D2OZ36.mjs +89 -0
- package/dist/chunk-F6D2OZ36.mjs.map +1 -0
- package/dist/chunk-GAOIFQDX.mjs +59 -0
- package/dist/chunk-GAOIFQDX.mjs.map +1 -0
- package/dist/chunk-HUIX2XVR.mjs +159 -0
- package/dist/chunk-HUIX2XVR.mjs.map +1 -0
- package/dist/chunk-K36R6HWY.mjs +51 -0
- package/dist/{chunk-XZ6ZMXXU.mjs.map → chunk-K36R6HWY.mjs.map} +1 -1
- package/dist/chunk-MBTAI3WE.mjs +78 -0
- package/dist/chunk-MBTAI3WE.mjs.map +1 -0
- package/dist/chunk-MGT6RUVX.mjs +423 -0
- package/dist/{chunk-BP7H4NFS.mjs.map → chunk-MGT6RUVX.mjs.map} +1 -1
- package/dist/chunk-PIFS7AIT.mjs +446 -0
- package/dist/{chunk-2IOKI4ES.mjs.map → chunk-PIFS7AIT.mjs.map} +1 -1
- package/dist/chunk-WG66JYYW.mjs +116 -0
- package/dist/{chunk-22BHCDT5.mjs.map → chunk-WG66JYYW.mjs.map} +1 -1
- package/dist/chunk-XD7WGXHZ.mjs +82 -0
- package/dist/{chunk-DUN6XU3N.mjs.map → chunk-XD7WGXHZ.mjs.map} +1 -1
- package/dist/chunk-YYDM6V2F.mjs +113 -0
- package/dist/{chunk-BR2FPGOX.mjs.map → chunk-YYDM6V2F.mjs.map} +1 -1
- package/dist/chunk-ZK7P3TZN.mjs +286 -0
- package/dist/chunk-ZK7P3TZN.mjs.map +1 -0
- package/dist/index.js +4443 -3924
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2698 -250
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-22BHCDT5.mjs +0 -101
- package/dist/chunk-2IOKI4ES.mjs +0 -335
- package/dist/chunk-7DYHXUPZ.mjs +0 -36
- package/dist/chunk-BJTO5JO5.mjs +0 -11
- package/dist/chunk-BP7H4NFS.mjs +0 -412
- package/dist/chunk-BR2FPGOX.mjs +0 -98
- package/dist/chunk-D6WEHN33.mjs +0 -276
- package/dist/chunk-D6WEHN33.mjs.map +0 -1
- package/dist/chunk-DRYFGARD.mjs +0 -289
- package/dist/chunk-DRYFGARD.mjs.map +0 -1
- package/dist/chunk-DUN6XU3N.mjs +0 -72
- package/dist/chunk-ESLHNWWE.mjs +0 -387
- package/dist/chunk-ESLHNWWE.mjs.map +0 -1
- package/dist/chunk-JUQEW6ON.mjs +0 -256
- package/dist/chunk-JUQEW6ON.mjs.map +0 -1
- package/dist/chunk-KUO2BVFY.mjs +0 -90
- package/dist/chunk-R5J3WAUI.mjs +0 -645
- package/dist/chunk-R5J3WAUI.mjs.map +0 -1
- package/dist/chunk-XZ6ZMXXU.mjs +0 -39
- package/dist/chunk-YPU4WTXZ.mjs +0 -269
- package/dist/chunk-YPU4WTXZ.mjs.map +0 -1
- package/dist/chunk-YUCD2TFH.mjs +0 -242
- package/dist/chunk-YUCD2TFH.mjs.map +0 -1
- package/dist/chunk-ZTJENCFC.mjs +0 -379
- package/dist/chunk-ZTJENCFC.mjs.map +0 -1
- package/dist/chunk-ZWYXXCXP.mjs +0 -248
- package/dist/chunk-ZWYXXCXP.mjs.map +0 -1
- /package/dist/{chunk-BJTO5JO5.mjs.map → chunk-3IIFBJCD.mjs.map} +0 -0
|
@@ -5,6 +5,9 @@ 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
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,535 +30,711 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
30
|
-
// src/
|
|
31
|
-
var
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
var
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
var PLATE_RECOGNITION_MODELS = [
|
|
44
|
-
// ── PaddleOCR PP-OCRv5 ────────────────────────────────────────
|
|
45
|
-
{
|
|
46
|
-
id: "paddleocr-latin",
|
|
47
|
-
name: "PaddleOCR Latin",
|
|
48
|
-
description: "PaddleOCR PP-OCRv5 recognition model for Latin-script license plates",
|
|
49
|
-
inputSize: { width: 320, height: 48 },
|
|
50
|
-
labels: PLATE_TEXT_LABELS,
|
|
51
|
-
formats: {
|
|
52
|
-
// ONNX only — PaddleOCR has dynamic dimensions incompatible with CoreML native conversion.
|
|
53
|
-
// On Apple Silicon, ONNX Runtime uses CoreML EP automatically for acceleration.
|
|
54
|
-
onnx: {
|
|
55
|
-
url: (0, import_types.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/onnx/camstack-paddleocr-latin-rec.onnx"),
|
|
56
|
-
sizeMB: 7.5
|
|
57
|
-
},
|
|
58
|
-
openvino: {
|
|
59
|
-
url: (0, import_types.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/openvino/camstack-paddleocr-latin.xml"),
|
|
60
|
-
sizeMB: 4,
|
|
61
|
-
runtimes: ["python"]
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
extraFiles: [
|
|
33
|
+
// src/catalogs/plate-recognition-models.js
|
|
34
|
+
var require_plate_recognition_models = __commonJS({
|
|
35
|
+
"src/catalogs/plate-recognition-models.js"(exports2) {
|
|
36
|
+
"use strict";
|
|
37
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
38
|
+
exports2.PLATE_RECOGNITION_MODELS = void 0;
|
|
39
|
+
var types_1 = require("@camstack/types");
|
|
40
|
+
var HF_REPO = "camstack/camstack-models";
|
|
41
|
+
var PLATE_TEXT_LABELS2 = [
|
|
42
|
+
{ id: "text", name: "Plate Text" }
|
|
43
|
+
];
|
|
44
|
+
exports2.PLATE_RECOGNITION_MODELS = [
|
|
45
|
+
// ── PaddleOCR PP-OCRv5 ────────────────────────────────────────
|
|
65
46
|
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
47
|
+
id: "paddleocr-latin",
|
|
48
|
+
name: "PaddleOCR Latin",
|
|
49
|
+
description: "PaddleOCR PP-OCRv5 recognition model for Latin-script license plates",
|
|
50
|
+
inputSize: { width: 320, height: 48 },
|
|
51
|
+
labels: PLATE_TEXT_LABELS2,
|
|
52
|
+
formats: {
|
|
53
|
+
// ONNX only — PaddleOCR has dynamic dimensions incompatible with CoreML native conversion.
|
|
54
|
+
// On Apple Silicon, ONNX Runtime uses CoreML EP automatically for acceleration.
|
|
55
|
+
onnx: {
|
|
56
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/onnx/camstack-paddleocr-latin-rec.onnx"),
|
|
57
|
+
sizeMB: 7.5
|
|
58
|
+
},
|
|
59
|
+
openvino: {
|
|
60
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/openvino/camstack-paddleocr-latin.xml"),
|
|
61
|
+
sizeMB: 4,
|
|
62
|
+
runtimes: ["python"]
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
extraFiles: [
|
|
66
|
+
{
|
|
67
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/onnx/camstack-paddleocr-latin-dict.txt"),
|
|
68
|
+
filename: "camstack-paddleocr-latin-dict.txt",
|
|
69
|
+
sizeMB: 0.01
|
|
70
|
+
}
|
|
71
|
+
]
|
|
82
72
|
},
|
|
83
|
-
openvino: {
|
|
84
|
-
url: (0, import_types.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/openvino/camstack-paddleocr-en.xml"),
|
|
85
|
-
sizeMB: 4,
|
|
86
|
-
runtimes: ["python"]
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
extraFiles: [
|
|
90
73
|
{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
74
|
+
id: "paddleocr-en",
|
|
75
|
+
name: "PaddleOCR English",
|
|
76
|
+
description: "PaddleOCR PP-OCRv5 recognition model optimized for English license plates",
|
|
77
|
+
inputSize: { width: 320, height: 48 },
|
|
78
|
+
labels: PLATE_TEXT_LABELS2,
|
|
79
|
+
formats: {
|
|
80
|
+
onnx: {
|
|
81
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/onnx/camstack-paddleocr-en-rec.onnx"),
|
|
82
|
+
sizeMB: 7.5
|
|
83
|
+
},
|
|
84
|
+
openvino: {
|
|
85
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/openvino/camstack-paddleocr-en.xml"),
|
|
86
|
+
sizeMB: 4,
|
|
87
|
+
runtimes: ["python"]
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
extraFiles: [
|
|
91
|
+
{
|
|
92
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/onnx/camstack-paddleocr-en-dict.txt"),
|
|
93
|
+
filename: "camstack-paddleocr-en-dict.txt",
|
|
94
|
+
sizeMB: 0.01
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
// ── CRNN-MobileNetV3 (via OnnxTR/docTR) ─────────────────────────
|
|
99
|
+
// Simple CNN+LSTM+CTC architecture — good CoreML compatibility (no dynamic ops)
|
|
112
100
|
{
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
101
|
+
id: "crnn-mobilenet-v3-small",
|
|
102
|
+
name: "CRNN MobileNet V3 Small",
|
|
103
|
+
description: "CRNN MobileNetV3-Small \u2014 lightweight text recognition, CoreML compatible via OnnxTR",
|
|
104
|
+
inputSize: { width: 128, height: 32 },
|
|
105
|
+
labels: PLATE_TEXT_LABELS2,
|
|
106
|
+
formats: {
|
|
107
|
+
onnx: {
|
|
108
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/crnn-mobilenet/onnx/camstack-crnn-mobilenet-v3-small.onnx"),
|
|
109
|
+
sizeMB: 8
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
extraFiles: [
|
|
113
|
+
{
|
|
114
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/crnn-mobilenet/camstack-crnn-mobilenet-charset.txt"),
|
|
115
|
+
filename: "camstack-crnn-mobilenet-charset.txt",
|
|
116
|
+
sizeMB: 0.01
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
},
|
|
132
120
|
{
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
121
|
+
id: "crnn-mobilenet-v3-large",
|
|
122
|
+
name: "CRNN MobileNet V3 Large",
|
|
123
|
+
description: "CRNN MobileNetV3-Large \u2014 higher accuracy text recognition, CoreML compatible",
|
|
124
|
+
inputSize: { width: 128, height: 32 },
|
|
125
|
+
labels: PLATE_TEXT_LABELS2,
|
|
126
|
+
formats: {
|
|
127
|
+
onnx: {
|
|
128
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/crnn-mobilenet/onnx/camstack-crnn-mobilenet-v3-large.onnx"),
|
|
129
|
+
sizeMB: 17
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
extraFiles: [
|
|
133
|
+
{
|
|
134
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/crnn-mobilenet/camstack-crnn-mobilenet-charset.txt"),
|
|
135
|
+
filename: "camstack-crnn-mobilenet-charset.txt",
|
|
136
|
+
sizeMB: 0.01
|
|
137
|
+
}
|
|
138
|
+
]
|
|
136
139
|
}
|
|
137
|
-
]
|
|
140
|
+
];
|
|
138
141
|
}
|
|
139
|
-
|
|
142
|
+
});
|
|
140
143
|
|
|
141
|
-
// src/shared/image-utils.
|
|
142
|
-
var
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
144
|
+
// src/shared/image-utils.js
|
|
145
|
+
var require_image_utils = __commonJS({
|
|
146
|
+
"src/shared/image-utils.js"(exports2) {
|
|
147
|
+
"use strict";
|
|
148
|
+
var __importDefault = exports2 && exports2.__importDefault || function(mod) {
|
|
149
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
150
|
+
};
|
|
151
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
152
|
+
exports2.jpegToRgb = jpegToRgb;
|
|
153
|
+
exports2.cropRegion = cropRegion2;
|
|
154
|
+
exports2.letterbox = letterbox;
|
|
155
|
+
exports2.resizeAndNormalize = resizeAndNormalize2;
|
|
156
|
+
exports2.rgbToGrayscale = rgbToGrayscale;
|
|
157
|
+
var sharp_1 = __importDefault(require("sharp"));
|
|
158
|
+
async function jpegToRgb(jpeg) {
|
|
159
|
+
const { data, info } = await (0, sharp_1.default)(jpeg).removeAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
160
|
+
return { data, width: info.width, height: info.height };
|
|
161
|
+
}
|
|
162
|
+
async function cropRegion2(jpeg, roi) {
|
|
163
|
+
return (0, sharp_1.default)(jpeg).extract({
|
|
164
|
+
left: Math.round(roi.x),
|
|
165
|
+
top: Math.round(roi.y),
|
|
166
|
+
width: Math.round(roi.w),
|
|
167
|
+
height: Math.round(roi.h)
|
|
168
|
+
}).jpeg().toBuffer();
|
|
169
|
+
}
|
|
170
|
+
async function letterbox(jpeg, targetSize) {
|
|
171
|
+
const meta = await (0, sharp_1.default)(jpeg).metadata();
|
|
172
|
+
const originalWidth = meta.width ?? 0;
|
|
173
|
+
const originalHeight = meta.height ?? 0;
|
|
174
|
+
const scale = Math.min(targetSize / originalWidth, targetSize / originalHeight);
|
|
175
|
+
const scaledWidth = Math.round(originalWidth * scale);
|
|
176
|
+
const scaledHeight = Math.round(originalHeight * scale);
|
|
177
|
+
const padX = Math.floor((targetSize - scaledWidth) / 2);
|
|
178
|
+
const padY = Math.floor((targetSize - scaledHeight) / 2);
|
|
179
|
+
const { data } = await (0, sharp_1.default)(jpeg).resize(scaledWidth, scaledHeight).extend({
|
|
180
|
+
top: padY,
|
|
181
|
+
bottom: targetSize - scaledHeight - padY,
|
|
182
|
+
left: padX,
|
|
183
|
+
right: targetSize - scaledWidth - padX,
|
|
184
|
+
background: { r: 114, g: 114, b: 114 }
|
|
185
|
+
}).removeAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
186
|
+
const numPixels = targetSize * targetSize;
|
|
187
|
+
const float32 = new Float32Array(3 * numPixels);
|
|
188
|
+
for (let i = 0; i < numPixels; i++) {
|
|
189
|
+
const srcBase = i * 3;
|
|
190
|
+
float32[0 * numPixels + i] = data[srcBase] / 255;
|
|
191
|
+
float32[1 * numPixels + i] = data[srcBase + 1] / 255;
|
|
192
|
+
float32[2 * numPixels + i] = data[srcBase + 2] / 255;
|
|
171
193
|
}
|
|
194
|
+
return { data: float32, scale, padX, padY, originalWidth, originalHeight };
|
|
172
195
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
196
|
+
async function resizeAndNormalize2(jpeg, targetWidth, targetHeight, normalization, layout) {
|
|
197
|
+
const { data } = await (0, sharp_1.default)(jpeg).resize(targetWidth, targetHeight, { fit: "fill" }).removeAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
198
|
+
const numPixels = targetWidth * targetHeight;
|
|
199
|
+
const float32 = new Float32Array(3 * numPixels);
|
|
200
|
+
const mean = [0.485, 0.456, 0.406];
|
|
201
|
+
const std = [0.229, 0.224, 0.225];
|
|
202
|
+
if (layout === "nchw") {
|
|
203
|
+
for (let i = 0; i < numPixels; i++) {
|
|
204
|
+
const srcBase = i * 3;
|
|
205
|
+
for (let c = 0; c < 3; c++) {
|
|
206
|
+
const raw = data[srcBase + c] / 255;
|
|
207
|
+
let val;
|
|
208
|
+
if (normalization === "zero-one") {
|
|
209
|
+
val = raw;
|
|
210
|
+
} else if (normalization === "imagenet") {
|
|
211
|
+
val = (raw - mean[c]) / std[c];
|
|
212
|
+
} else {
|
|
213
|
+
val = data[srcBase + c];
|
|
214
|
+
}
|
|
215
|
+
float32[c * numPixels + i] = val;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
for (let i = 0; i < numPixels; i++) {
|
|
220
|
+
const srcBase = i * 3;
|
|
221
|
+
for (let c = 0; c < 3; c++) {
|
|
222
|
+
const raw = data[srcBase + c] / 255;
|
|
223
|
+
let val;
|
|
224
|
+
if (normalization === "zero-one") {
|
|
225
|
+
val = raw;
|
|
226
|
+
} else if (normalization === "imagenet") {
|
|
227
|
+
val = (raw - mean[c]) / std[c];
|
|
228
|
+
} else {
|
|
229
|
+
val = data[srcBase + c];
|
|
230
|
+
}
|
|
231
|
+
float32[i * 3 + c] = val;
|
|
232
|
+
}
|
|
185
233
|
}
|
|
186
|
-
float32[i * 3 + c] = val;
|
|
187
234
|
}
|
|
235
|
+
return float32;
|
|
188
236
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
for (let t = 0; t < seqLen; t++) {
|
|
198
|
-
const offset = t * numChars;
|
|
199
|
-
let bestIdx = 0;
|
|
200
|
-
let bestVal = output[offset];
|
|
201
|
-
for (let c = 1; c < numChars; c++) {
|
|
202
|
-
const val = output[offset + c];
|
|
203
|
-
if (val > bestVal) {
|
|
204
|
-
bestVal = val;
|
|
205
|
-
bestIdx = c;
|
|
237
|
+
function rgbToGrayscale(rgb, width, height) {
|
|
238
|
+
const numPixels = width * height;
|
|
239
|
+
const gray = new Uint8Array(numPixels);
|
|
240
|
+
for (let i = 0; i < numPixels; i++) {
|
|
241
|
+
const r = rgb[i * 3];
|
|
242
|
+
const g = rgb[i * 3 + 1];
|
|
243
|
+
const b = rgb[i * 3 + 2];
|
|
244
|
+
gray[i] = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
|
|
206
245
|
}
|
|
207
|
-
|
|
208
|
-
rawIndices.push(bestIdx);
|
|
209
|
-
totalLogScore += bestVal;
|
|
210
|
-
}
|
|
211
|
-
const collapsed = [];
|
|
212
|
-
for (let i = 0; i < rawIndices.length; i++) {
|
|
213
|
-
const cur = rawIndices[i];
|
|
214
|
-
if (i === 0 || cur !== rawIndices[i - 1]) {
|
|
215
|
-
collapsed.push(cur);
|
|
246
|
+
return gray;
|
|
216
247
|
}
|
|
217
248
|
}
|
|
218
|
-
|
|
219
|
-
const text = filtered.map((idx) => charset[idx] ?? "").join("");
|
|
220
|
-
const confidence = seqLen > 0 ? totalLogScore / seqLen : 0;
|
|
221
|
-
return { text, confidence };
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// src/shared/engine-resolver.ts
|
|
225
|
-
var fs = __toESM(require("fs"));
|
|
226
|
-
var path2 = __toESM(require("path"));
|
|
249
|
+
});
|
|
227
250
|
|
|
228
|
-
// src/shared/
|
|
229
|
-
var
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (!this.session) {
|
|
263
|
-
throw new Error("NodeInferenceEngine: not initialized \u2014 call initialize() first");
|
|
264
|
-
}
|
|
265
|
-
const ort = await import("onnxruntime-node");
|
|
266
|
-
const sess = this.session;
|
|
267
|
-
const inputName = sess.inputNames[0];
|
|
268
|
-
const tensor = new ort.Tensor("float32", input, [...inputShape]);
|
|
269
|
-
const feeds = { [inputName]: tensor };
|
|
270
|
-
const results = await sess.run(feeds);
|
|
271
|
-
const outputName = sess.outputNames[0];
|
|
272
|
-
const outputTensor = results[outputName];
|
|
273
|
-
return outputTensor.data;
|
|
274
|
-
}
|
|
275
|
-
async runMultiOutput(input, inputShape) {
|
|
276
|
-
if (!this.session) {
|
|
277
|
-
throw new Error("NodeInferenceEngine: not initialized \u2014 call initialize() first");
|
|
278
|
-
}
|
|
279
|
-
const ort = await import("onnxruntime-node");
|
|
280
|
-
const sess = this.session;
|
|
281
|
-
const inputName = sess.inputNames[0];
|
|
282
|
-
const tensor = new ort.Tensor("float32", input, [...inputShape]);
|
|
283
|
-
const feeds = { [inputName]: tensor };
|
|
284
|
-
const results = await sess.run(feeds);
|
|
285
|
-
const out = {};
|
|
286
|
-
for (const name of sess.outputNames) {
|
|
287
|
-
out[name] = results[name].data;
|
|
251
|
+
// src/shared/postprocess/paddleocr.js
|
|
252
|
+
var require_paddleocr = __commonJS({
|
|
253
|
+
"src/shared/postprocess/paddleocr.js"(exports2) {
|
|
254
|
+
"use strict";
|
|
255
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
256
|
+
exports2.ctcDecode = ctcDecode2;
|
|
257
|
+
function ctcDecode2(output, seqLen, numChars, charset) {
|
|
258
|
+
let totalLogScore = 0;
|
|
259
|
+
const rawIndices = [];
|
|
260
|
+
for (let t = 0; t < seqLen; t++) {
|
|
261
|
+
const offset = t * numChars;
|
|
262
|
+
let bestIdx = 0;
|
|
263
|
+
let bestVal = output[offset];
|
|
264
|
+
for (let c = 1; c < numChars; c++) {
|
|
265
|
+
const val = output[offset + c];
|
|
266
|
+
if (val > bestVal) {
|
|
267
|
+
bestVal = val;
|
|
268
|
+
bestIdx = c;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
rawIndices.push(bestIdx);
|
|
272
|
+
totalLogScore += bestVal;
|
|
273
|
+
}
|
|
274
|
+
const collapsed = [];
|
|
275
|
+
for (let i = 0; i < rawIndices.length; i++) {
|
|
276
|
+
const cur = rawIndices[i];
|
|
277
|
+
if (i === 0 || cur !== rawIndices[i - 1]) {
|
|
278
|
+
collapsed.push(cur);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const filtered = collapsed.filter((idx) => idx !== 0);
|
|
282
|
+
const text = filtered.map((idx) => charset[idx] ?? "").join("");
|
|
283
|
+
const confidence = seqLen > 0 ? totalLogScore / seqLen : 0;
|
|
284
|
+
return { text, confidence };
|
|
288
285
|
}
|
|
289
|
-
return out;
|
|
290
286
|
}
|
|
291
|
-
|
|
292
|
-
this.session = null;
|
|
293
|
-
}
|
|
294
|
-
};
|
|
287
|
+
});
|
|
295
288
|
|
|
296
|
-
// src/shared/
|
|
297
|
-
var
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
289
|
+
// src/shared/node-engine.js
|
|
290
|
+
var require_node_engine = __commonJS({
|
|
291
|
+
"src/shared/node-engine.js"(exports2) {
|
|
292
|
+
"use strict";
|
|
293
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
294
|
+
if (k2 === void 0) k2 = k;
|
|
295
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
296
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
297
|
+
desc = { enumerable: true, get: function() {
|
|
298
|
+
return m[k];
|
|
299
|
+
} };
|
|
300
|
+
}
|
|
301
|
+
Object.defineProperty(o, k2, desc);
|
|
302
|
+
}) : (function(o, m, k, k2) {
|
|
303
|
+
if (k2 === void 0) k2 = k;
|
|
304
|
+
o[k2] = m[k];
|
|
305
|
+
}));
|
|
306
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
307
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
308
|
+
}) : function(o, v) {
|
|
309
|
+
o["default"] = v;
|
|
310
|
+
});
|
|
311
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
312
|
+
var ownKeys = function(o) {
|
|
313
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
314
|
+
var ar = [];
|
|
315
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
316
|
+
return ar;
|
|
317
|
+
};
|
|
318
|
+
return ownKeys(o);
|
|
319
|
+
};
|
|
320
|
+
return function(mod) {
|
|
321
|
+
if (mod && mod.__esModule) return mod;
|
|
322
|
+
var result = {};
|
|
323
|
+
if (mod != null) {
|
|
324
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
325
|
+
}
|
|
326
|
+
__setModuleDefault(result, mod);
|
|
327
|
+
return result;
|
|
328
|
+
};
|
|
329
|
+
})();
|
|
330
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
331
|
+
exports2.NodeInferenceEngine = void 0;
|
|
332
|
+
var path2 = __importStar(require("path"));
|
|
333
|
+
var BACKEND_TO_PROVIDER = {
|
|
334
|
+
cpu: "cpu",
|
|
335
|
+
coreml: "coreml",
|
|
336
|
+
cuda: "cuda",
|
|
337
|
+
tensorrt: "tensorrt",
|
|
338
|
+
dml: "dml"
|
|
339
|
+
};
|
|
340
|
+
var BACKEND_TO_DEVICE = {
|
|
341
|
+
cpu: "cpu",
|
|
307
342
|
coreml: "gpu-mps",
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
tflite: "cpu"
|
|
343
|
+
cuda: "gpu-cuda",
|
|
344
|
+
tensorrt: "tensorrt"
|
|
311
345
|
};
|
|
312
|
-
|
|
346
|
+
var NodeInferenceEngine = class {
|
|
347
|
+
modelPath;
|
|
348
|
+
backend;
|
|
349
|
+
runtime = "onnx";
|
|
350
|
+
device;
|
|
351
|
+
session = null;
|
|
352
|
+
constructor(modelPath, backend) {
|
|
353
|
+
this.modelPath = modelPath;
|
|
354
|
+
this.backend = backend;
|
|
355
|
+
this.device = BACKEND_TO_DEVICE[backend] ?? "cpu";
|
|
356
|
+
}
|
|
357
|
+
async initialize() {
|
|
358
|
+
const ort = await Promise.resolve().then(() => __importStar(require("onnxruntime-node")));
|
|
359
|
+
const provider = BACKEND_TO_PROVIDER[this.backend] ?? "cpu";
|
|
360
|
+
const absModelPath = path2.isAbsolute(this.modelPath) ? this.modelPath : path2.resolve(process.cwd(), this.modelPath);
|
|
361
|
+
const sessionOptions = {
|
|
362
|
+
executionProviders: [provider]
|
|
363
|
+
};
|
|
364
|
+
this.session = await ort.InferenceSession.create(absModelPath, sessionOptions);
|
|
365
|
+
}
|
|
366
|
+
async run(input, inputShape) {
|
|
367
|
+
if (!this.session) {
|
|
368
|
+
throw new Error("NodeInferenceEngine: not initialized \u2014 call initialize() first");
|
|
369
|
+
}
|
|
370
|
+
const ort = await Promise.resolve().then(() => __importStar(require("onnxruntime-node")));
|
|
371
|
+
const sess = this.session;
|
|
372
|
+
const inputName = sess.inputNames[0];
|
|
373
|
+
const tensor = new ort.Tensor("float32", input, [...inputShape]);
|
|
374
|
+
const feeds = { [inputName]: tensor };
|
|
375
|
+
const results = await sess.run(feeds);
|
|
376
|
+
const outputName = sess.outputNames[0];
|
|
377
|
+
const outputTensor = results[outputName];
|
|
378
|
+
return outputTensor.data;
|
|
379
|
+
}
|
|
380
|
+
async runMultiOutput(input, inputShape) {
|
|
381
|
+
if (!this.session) {
|
|
382
|
+
throw new Error("NodeInferenceEngine: not initialized \u2014 call initialize() first");
|
|
383
|
+
}
|
|
384
|
+
const ort = await Promise.resolve().then(() => __importStar(require("onnxruntime-node")));
|
|
385
|
+
const sess = this.session;
|
|
386
|
+
const inputName = sess.inputNames[0];
|
|
387
|
+
const tensor = new ort.Tensor("float32", input, [...inputShape]);
|
|
388
|
+
const feeds = { [inputName]: tensor };
|
|
389
|
+
const results = await sess.run(feeds);
|
|
390
|
+
const out = {};
|
|
391
|
+
for (const name of sess.outputNames) {
|
|
392
|
+
out[name] = results[name].data;
|
|
393
|
+
}
|
|
394
|
+
return out;
|
|
395
|
+
}
|
|
396
|
+
async dispose() {
|
|
397
|
+
this.session = null;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
exports2.NodeInferenceEngine = NodeInferenceEngine;
|
|
313
401
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
this.
|
|
340
|
-
this.
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// src/shared/python-engine.js
|
|
405
|
+
var require_python_engine = __commonJS({
|
|
406
|
+
"src/shared/python-engine.js"(exports2) {
|
|
407
|
+
"use strict";
|
|
408
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
409
|
+
exports2.PythonInferenceEngine = void 0;
|
|
410
|
+
exports2.resolvePythonBinary = resolvePythonBinary;
|
|
411
|
+
var node_child_process_1 = require("child_process");
|
|
412
|
+
var PythonInferenceEngine = class {
|
|
413
|
+
pythonPath;
|
|
414
|
+
scriptPath;
|
|
415
|
+
modelPath;
|
|
416
|
+
extraArgs;
|
|
417
|
+
runtime;
|
|
418
|
+
device;
|
|
419
|
+
process = null;
|
|
420
|
+
receiveBuffer = Buffer.alloc(0);
|
|
421
|
+
pendingResolve = null;
|
|
422
|
+
pendingReject = null;
|
|
423
|
+
constructor(pythonPath, scriptPath, runtime, modelPath, extraArgs = []) {
|
|
424
|
+
this.pythonPath = pythonPath;
|
|
425
|
+
this.scriptPath = scriptPath;
|
|
426
|
+
this.modelPath = modelPath;
|
|
427
|
+
this.extraArgs = extraArgs;
|
|
428
|
+
this.runtime = runtime;
|
|
429
|
+
const runtimeDeviceMap = {
|
|
430
|
+
onnx: "cpu",
|
|
431
|
+
coreml: "gpu-mps",
|
|
432
|
+
pytorch: "cpu",
|
|
433
|
+
openvino: "cpu",
|
|
434
|
+
tflite: "cpu"
|
|
435
|
+
};
|
|
436
|
+
this.device = runtimeDeviceMap[runtime];
|
|
437
|
+
}
|
|
438
|
+
async initialize() {
|
|
439
|
+
const args = [this.scriptPath, this.modelPath, ...this.extraArgs];
|
|
440
|
+
this.process = (0, node_child_process_1.spawn)(this.pythonPath, args, {
|
|
441
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
442
|
+
});
|
|
443
|
+
if (!this.process.stdout || !this.process.stdin) {
|
|
444
|
+
throw new Error("PythonInferenceEngine: failed to create process pipes");
|
|
445
|
+
}
|
|
446
|
+
this.process.stderr?.on("data", (chunk) => {
|
|
447
|
+
process.stderr.write(`[python-engine] ${chunk.toString()}`);
|
|
448
|
+
});
|
|
449
|
+
this.process.on("error", (err) => {
|
|
450
|
+
this.pendingReject?.(err);
|
|
451
|
+
this.pendingReject = null;
|
|
452
|
+
this.pendingResolve = null;
|
|
453
|
+
});
|
|
454
|
+
this.process.on("exit", (code) => {
|
|
455
|
+
if (code !== 0) {
|
|
456
|
+
const err = new Error(`PythonInferenceEngine: process exited with code ${code}`);
|
|
457
|
+
this.pendingReject?.(err);
|
|
458
|
+
this.pendingReject = null;
|
|
459
|
+
this.pendingResolve = null;
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
this.process.stdout.on("data", (chunk) => {
|
|
463
|
+
this.receiveBuffer = Buffer.concat([this.receiveBuffer, chunk]);
|
|
464
|
+
this._tryReceive();
|
|
465
|
+
});
|
|
466
|
+
await new Promise((resolve, reject) => {
|
|
467
|
+
const timeout = setTimeout(() => resolve(), 2e3);
|
|
468
|
+
this.process?.on("error", (err) => {
|
|
469
|
+
clearTimeout(timeout);
|
|
470
|
+
reject(err);
|
|
471
|
+
});
|
|
472
|
+
this.process?.on("exit", (code) => {
|
|
473
|
+
clearTimeout(timeout);
|
|
474
|
+
if (code !== 0) {
|
|
475
|
+
reject(new Error(`PythonInferenceEngine: process exited early with code ${code}`));
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
_tryReceive() {
|
|
481
|
+
if (this.receiveBuffer.length < 4)
|
|
482
|
+
return;
|
|
483
|
+
const length = this.receiveBuffer.readUInt32LE(0);
|
|
484
|
+
if (this.receiveBuffer.length < 4 + length)
|
|
485
|
+
return;
|
|
486
|
+
const jsonBytes = this.receiveBuffer.subarray(4, 4 + length);
|
|
487
|
+
this.receiveBuffer = this.receiveBuffer.subarray(4 + length);
|
|
488
|
+
const resolve = this.pendingResolve;
|
|
489
|
+
const reject = this.pendingReject;
|
|
341
490
|
this.pendingResolve = null;
|
|
491
|
+
this.pendingReject = null;
|
|
492
|
+
if (!resolve)
|
|
493
|
+
return;
|
|
494
|
+
try {
|
|
495
|
+
const parsed = JSON.parse(jsonBytes.toString("utf8"));
|
|
496
|
+
resolve(parsed);
|
|
497
|
+
} catch (err) {
|
|
498
|
+
reject?.(err instanceof Error ? err : new Error(String(err)));
|
|
499
|
+
}
|
|
342
500
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
});
|
|
348
|
-
await new Promise((resolve2, reject) => {
|
|
349
|
-
const timeout = setTimeout(() => resolve2(), 2e3);
|
|
350
|
-
this.process?.on("error", (err) => {
|
|
351
|
-
clearTimeout(timeout);
|
|
352
|
-
reject(err);
|
|
353
|
-
});
|
|
354
|
-
this.process?.on("exit", (code) => {
|
|
355
|
-
clearTimeout(timeout);
|
|
356
|
-
if (code !== 0) {
|
|
357
|
-
reject(new Error(`PythonInferenceEngine: process exited early with code ${code}`));
|
|
501
|
+
/** Send JPEG buffer, receive JSON detection results */
|
|
502
|
+
async runJpeg(jpeg) {
|
|
503
|
+
if (!this.process?.stdin) {
|
|
504
|
+
throw new Error("PythonInferenceEngine: process not initialized");
|
|
358
505
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
const lengthBuf = Buffer.allocUnsafe(4);
|
|
389
|
-
lengthBuf.writeUInt32LE(jpeg.length, 0);
|
|
390
|
-
this.process.stdin.write(Buffer.concat([lengthBuf, jpeg]));
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
/** IInferenceEngine.run — wraps runJpeg for compatibility */
|
|
394
|
-
async run(_input, _inputShape) {
|
|
395
|
-
throw new Error(
|
|
396
|
-
"PythonInferenceEngine: use runJpeg() directly \u2014 this engine operates on JPEG input"
|
|
397
|
-
);
|
|
398
|
-
}
|
|
399
|
-
/** IInferenceEngine.runMultiOutput — not supported by Python engine (operates on JPEG input) */
|
|
400
|
-
async runMultiOutput(_input, _inputShape) {
|
|
401
|
-
throw new Error(
|
|
402
|
-
"PythonInferenceEngine: runMultiOutput() is not supported \u2014 this engine operates on JPEG input"
|
|
403
|
-
);
|
|
404
|
-
}
|
|
405
|
-
async dispose() {
|
|
406
|
-
if (this.process) {
|
|
407
|
-
this.process.stdin?.end();
|
|
408
|
-
this.process.kill("SIGTERM");
|
|
409
|
-
this.process = null;
|
|
506
|
+
return new Promise((resolve, reject) => {
|
|
507
|
+
this.pendingResolve = resolve;
|
|
508
|
+
this.pendingReject = reject;
|
|
509
|
+
const lengthBuf = Buffer.allocUnsafe(4);
|
|
510
|
+
lengthBuf.writeUInt32LE(jpeg.length, 0);
|
|
511
|
+
this.process.stdin.write(Buffer.concat([lengthBuf, jpeg]));
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
/** IInferenceEngine.run — wraps runJpeg for compatibility */
|
|
515
|
+
async run(_input, _inputShape) {
|
|
516
|
+
throw new Error("PythonInferenceEngine: use runJpeg() directly \u2014 this engine operates on JPEG input");
|
|
517
|
+
}
|
|
518
|
+
/** IInferenceEngine.runMultiOutput — not supported by Python engine (operates on JPEG input) */
|
|
519
|
+
async runMultiOutput(_input, _inputShape) {
|
|
520
|
+
throw new Error("PythonInferenceEngine: runMultiOutput() is not supported \u2014 this engine operates on JPEG input");
|
|
521
|
+
}
|
|
522
|
+
async dispose() {
|
|
523
|
+
if (this.process) {
|
|
524
|
+
this.process.stdin?.end();
|
|
525
|
+
this.process.kill("SIGTERM");
|
|
526
|
+
this.process = null;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
exports2.PythonInferenceEngine = PythonInferenceEngine;
|
|
531
|
+
async function resolvePythonBinary(configPath, deps) {
|
|
532
|
+
if (configPath)
|
|
533
|
+
return configPath;
|
|
534
|
+
return deps.ensurePython();
|
|
410
535
|
}
|
|
411
536
|
}
|
|
412
|
-
};
|
|
537
|
+
});
|
|
413
538
|
|
|
414
|
-
// src/shared/engine-resolver.
|
|
415
|
-
var
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
function
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
-
|
|
474
|
-
|
|
475
|
-
|
|
539
|
+
// src/shared/engine-resolver.js
|
|
540
|
+
var require_engine_resolver = __commonJS({
|
|
541
|
+
"src/shared/engine-resolver.js"(exports2) {
|
|
542
|
+
"use strict";
|
|
543
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
544
|
+
if (k2 === void 0) k2 = k;
|
|
545
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
546
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
547
|
+
desc = { enumerable: true, get: function() {
|
|
548
|
+
return m[k];
|
|
549
|
+
} };
|
|
550
|
+
}
|
|
551
|
+
Object.defineProperty(o, k2, desc);
|
|
552
|
+
}) : (function(o, m, k, k2) {
|
|
553
|
+
if (k2 === void 0) k2 = k;
|
|
554
|
+
o[k2] = m[k];
|
|
555
|
+
}));
|
|
556
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
557
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
558
|
+
}) : function(o, v) {
|
|
559
|
+
o["default"] = v;
|
|
560
|
+
});
|
|
561
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
562
|
+
var ownKeys = function(o) {
|
|
563
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
564
|
+
var ar = [];
|
|
565
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
566
|
+
return ar;
|
|
567
|
+
};
|
|
568
|
+
return ownKeys(o);
|
|
569
|
+
};
|
|
570
|
+
return function(mod) {
|
|
571
|
+
if (mod && mod.__esModule) return mod;
|
|
572
|
+
var result = {};
|
|
573
|
+
if (mod != null) {
|
|
574
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
575
|
+
}
|
|
576
|
+
__setModuleDefault(result, mod);
|
|
577
|
+
return result;
|
|
578
|
+
};
|
|
579
|
+
})();
|
|
580
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
581
|
+
exports2.resolveEngine = resolveEngine2;
|
|
582
|
+
exports2.probeOnnxBackends = probeOnnxBackends;
|
|
583
|
+
var fs2 = __importStar(require("fs"));
|
|
584
|
+
var path2 = __importStar(require("path"));
|
|
585
|
+
var node_engine_js_1 = require_node_engine();
|
|
586
|
+
var python_engine_js_1 = require_python_engine();
|
|
587
|
+
var AUTO_BACKEND_PRIORITY = ["coreml", "cuda", "tensorrt", "cpu"];
|
|
588
|
+
var BACKEND_TO_FORMAT = {
|
|
589
|
+
cpu: "onnx",
|
|
590
|
+
coreml: "onnx",
|
|
591
|
+
cuda: "onnx",
|
|
592
|
+
tensorrt: "onnx"
|
|
593
|
+
};
|
|
594
|
+
var RUNTIME_TO_FORMAT = {
|
|
595
|
+
onnx: "onnx",
|
|
596
|
+
coreml: "coreml",
|
|
597
|
+
openvino: "openvino",
|
|
598
|
+
tflite: "tflite",
|
|
599
|
+
pytorch: "pt"
|
|
600
|
+
};
|
|
601
|
+
function modelFilePath(modelsDir, modelEntry, format) {
|
|
602
|
+
const formatEntry = modelEntry.formats[format];
|
|
603
|
+
if (!formatEntry) {
|
|
604
|
+
throw new Error(`Model ${modelEntry.id} has no ${format} format`);
|
|
605
|
+
}
|
|
606
|
+
const urlParts = formatEntry.url.split("/");
|
|
607
|
+
const filename = urlParts[urlParts.length - 1] ?? `${modelEntry.id}.${format}`;
|
|
608
|
+
return path2.join(modelsDir, filename);
|
|
476
609
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
} else {
|
|
484
|
-
modelPath = modelFilePath(modelsDir, modelEntry, selectedFormat);
|
|
485
|
-
if (!modelExists(modelPath)) {
|
|
486
|
-
throw new Error(
|
|
487
|
-
`resolveEngine: model file not found at ${modelPath} and no model service provided`
|
|
488
|
-
);
|
|
610
|
+
function modelExists(filePath) {
|
|
611
|
+
try {
|
|
612
|
+
return fs2.existsSync(filePath);
|
|
613
|
+
} catch {
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
489
616
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
617
|
+
async function resolveEngine2(options) {
|
|
618
|
+
const { runtime, backend, modelEntry, modelsDir, models } = options;
|
|
619
|
+
let selectedFormat;
|
|
620
|
+
let selectedBackend;
|
|
621
|
+
if (runtime === "auto") {
|
|
622
|
+
const available = await probeOnnxBackends();
|
|
623
|
+
let chosen = null;
|
|
624
|
+
for (const b of AUTO_BACKEND_PRIORITY) {
|
|
625
|
+
if (!available.includes(b))
|
|
626
|
+
continue;
|
|
627
|
+
const fmt = BACKEND_TO_FORMAT[b];
|
|
628
|
+
if (!fmt)
|
|
629
|
+
continue;
|
|
630
|
+
if (!modelEntry.formats[fmt])
|
|
631
|
+
continue;
|
|
632
|
+
chosen = { backend: b, format: fmt };
|
|
633
|
+
break;
|
|
634
|
+
}
|
|
635
|
+
if (!chosen) {
|
|
636
|
+
throw new Error(`resolveEngine: no compatible backend found for model ${modelEntry.id}. Available backends: ${available.join(", ")}`);
|
|
637
|
+
}
|
|
638
|
+
selectedFormat = chosen.format;
|
|
639
|
+
selectedBackend = chosen.backend;
|
|
640
|
+
} else {
|
|
641
|
+
const fmt = RUNTIME_TO_FORMAT[runtime];
|
|
642
|
+
if (!fmt) {
|
|
643
|
+
throw new Error(`resolveEngine: unsupported runtime "${runtime}"`);
|
|
644
|
+
}
|
|
645
|
+
if (!modelEntry.formats[fmt]) {
|
|
646
|
+
throw new Error(`resolveEngine: model ${modelEntry.id} has no ${fmt} format for runtime ${runtime}`);
|
|
647
|
+
}
|
|
648
|
+
selectedFormat = fmt;
|
|
649
|
+
selectedBackend = runtime === "onnx" ? backend || "cpu" : runtime;
|
|
650
|
+
}
|
|
651
|
+
let modelPath;
|
|
652
|
+
if (models) {
|
|
653
|
+
modelPath = await models.ensure(modelEntry.id, selectedFormat);
|
|
654
|
+
} else {
|
|
655
|
+
modelPath = modelFilePath(modelsDir, modelEntry, selectedFormat);
|
|
656
|
+
if (!modelExists(modelPath)) {
|
|
657
|
+
throw new Error(`resolveEngine: model file not found at ${modelPath} and no model service provided`);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
if (selectedFormat === "onnx") {
|
|
661
|
+
const engine = new node_engine_js_1.NodeInferenceEngine(modelPath, selectedBackend);
|
|
662
|
+
await engine.initialize();
|
|
663
|
+
return { engine, format: selectedFormat, modelPath };
|
|
664
|
+
}
|
|
665
|
+
const { pythonPath } = options;
|
|
666
|
+
const PYTHON_SCRIPT_MAP = {
|
|
667
|
+
coreml: "coreml_inference.py",
|
|
668
|
+
pytorch: "pytorch_inference.py",
|
|
669
|
+
openvino: "openvino_inference.py"
|
|
670
|
+
};
|
|
671
|
+
const effectiveRuntime = runtime === "auto" ? selectedBackend : runtime;
|
|
672
|
+
const scriptName = PYTHON_SCRIPT_MAP[effectiveRuntime];
|
|
673
|
+
if (scriptName && pythonPath) {
|
|
674
|
+
const candidates = [
|
|
675
|
+
path2.join(__dirname, "../../python", scriptName),
|
|
676
|
+
path2.join(__dirname, "../python", scriptName),
|
|
677
|
+
path2.join(__dirname, "../../../python", scriptName)
|
|
678
|
+
];
|
|
679
|
+
const scriptPath = candidates.find((p) => fs2.existsSync(p));
|
|
680
|
+
if (!scriptPath) {
|
|
681
|
+
throw new Error(`resolveEngine: Python script "${scriptName}" not found. Searched:
|
|
682
|
+
${candidates.join("\n")}`);
|
|
683
|
+
}
|
|
684
|
+
const inputSize = Math.max(modelEntry.inputSize.width, modelEntry.inputSize.height);
|
|
685
|
+
const engine = new python_engine_js_1.PythonInferenceEngine(pythonPath, scriptPath, effectiveRuntime, modelPath, [
|
|
686
|
+
`--input-size=${inputSize}`,
|
|
687
|
+
`--confidence=0.25`
|
|
688
|
+
]);
|
|
689
|
+
await engine.initialize();
|
|
690
|
+
return { engine, format: selectedFormat, modelPath };
|
|
691
|
+
}
|
|
692
|
+
const fallbackPath = modelFilePath(modelsDir, modelEntry, "onnx");
|
|
693
|
+
if (modelEntry.formats["onnx"] && modelExists(fallbackPath)) {
|
|
694
|
+
const engine = new node_engine_js_1.NodeInferenceEngine(fallbackPath, "cpu");
|
|
695
|
+
await engine.initialize();
|
|
696
|
+
return { engine, format: "onnx", modelPath: fallbackPath };
|
|
697
|
+
}
|
|
698
|
+
throw new Error(`resolveEngine: format ${selectedFormat} is not yet supported by NodeInferenceEngine, no Python runtime is available, and no ONNX fallback exists`);
|
|
516
699
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
try {
|
|
538
|
-
const ort = await import("onnxruntime-node");
|
|
539
|
-
const providers = ort.env?.webgl?.disabled !== void 0 ? ort.InferenceSession?.getAvailableProviders?.() ?? [] : [];
|
|
540
|
-
for (const p of providers) {
|
|
541
|
-
const normalized = p.toLowerCase().replace("executionprovider", "");
|
|
542
|
-
if (normalized === "coreml") available.push("coreml");
|
|
543
|
-
else if (normalized === "cuda") available.push("cuda");
|
|
544
|
-
else if (normalized === "tensorrt") available.push("tensorrt");
|
|
700
|
+
async function probeOnnxBackends() {
|
|
701
|
+
const available = ["cpu"];
|
|
702
|
+
try {
|
|
703
|
+
const ort = await Promise.resolve().then(() => __importStar(require("onnxruntime-node")));
|
|
704
|
+
const providers = ort.env?.webgl?.disabled !== void 0 ? ort.InferenceSession?.getAvailableProviders?.() ?? [] : [];
|
|
705
|
+
for (const p of providers) {
|
|
706
|
+
const normalized = p.toLowerCase().replace("executionprovider", "");
|
|
707
|
+
if (normalized === "coreml")
|
|
708
|
+
available.push("coreml");
|
|
709
|
+
else if (normalized === "cuda")
|
|
710
|
+
available.push("cuda");
|
|
711
|
+
else if (normalized === "tensorrt")
|
|
712
|
+
available.push("tensorrt");
|
|
713
|
+
}
|
|
714
|
+
} catch {
|
|
715
|
+
}
|
|
716
|
+
if (process.platform === "darwin" && !available.includes("coreml")) {
|
|
717
|
+
available.push("coreml");
|
|
718
|
+
}
|
|
719
|
+
return [...new Set(available)];
|
|
545
720
|
}
|
|
546
|
-
} catch {
|
|
547
|
-
}
|
|
548
|
-
if (process.platform === "darwin" && !available.includes("coreml")) {
|
|
549
|
-
available.push("coreml");
|
|
550
721
|
}
|
|
551
|
-
|
|
552
|
-
}
|
|
722
|
+
});
|
|
553
723
|
|
|
554
724
|
// src/addons/plate-recognition/index.ts
|
|
555
|
-
var
|
|
556
|
-
|
|
725
|
+
var plate_recognition_exports = {};
|
|
726
|
+
__export(plate_recognition_exports, {
|
|
727
|
+
default: () => PlateRecognitionAddon
|
|
728
|
+
});
|
|
729
|
+
module.exports = __toCommonJS(plate_recognition_exports);
|
|
730
|
+
var import_plate_recognition_models = __toESM(require_plate_recognition_models());
|
|
731
|
+
var import_image_utils = __toESM(require_image_utils());
|
|
732
|
+
var import_paddleocr = __toESM(require_paddleocr());
|
|
733
|
+
var import_engine_resolver = __toESM(require_engine_resolver());
|
|
734
|
+
var fs = __toESM(require("fs"));
|
|
735
|
+
var path = __toESM(require("path"));
|
|
557
736
|
var PLATE_TEXT_LABEL = { id: "plate-text", name: "Plate Text" };
|
|
558
|
-
var
|
|
737
|
+
var PLATE_TEXT_LABELS = [PLATE_TEXT_LABEL];
|
|
559
738
|
var PLATE_REC_CLASS_MAP = { mapping: {}, preserveOriginal: true };
|
|
560
739
|
function loadCharset(modelsDir, modelId) {
|
|
561
740
|
const dictNames = [
|
|
@@ -565,9 +744,9 @@ function loadCharset(modelsDir, modelId) {
|
|
|
565
744
|
`camstack-crnn-mobilenet-charset.txt`
|
|
566
745
|
];
|
|
567
746
|
for (const name of dictNames) {
|
|
568
|
-
const dictPath =
|
|
569
|
-
if (
|
|
570
|
-
const lines =
|
|
747
|
+
const dictPath = path.join(modelsDir, name);
|
|
748
|
+
if (fs.existsSync(dictPath)) {
|
|
749
|
+
const lines = fs.readFileSync(dictPath, "utf-8").split("\n").filter((l) => l.length > 0);
|
|
571
750
|
return ["", ...lines, " "];
|
|
572
751
|
}
|
|
573
752
|
}
|
|
@@ -613,7 +792,7 @@ var PlateRecognitionAddon = class {
|
|
|
613
792
|
"paddleocr-latin": { ram: 100, accuracy: 80 },
|
|
614
793
|
"paddleocr-en": { ram: 100, accuracy: 80 }
|
|
615
794
|
};
|
|
616
|
-
return PLATE_RECOGNITION_MODELS.map((m) => ({
|
|
795
|
+
return import_plate_recognition_models.PLATE_RECOGNITION_MODELS.map((m) => ({
|
|
617
796
|
modelId: m.id,
|
|
618
797
|
name: m.name,
|
|
619
798
|
minRAM_MB: scores[m.id]?.ram ?? 100,
|
|
@@ -629,7 +808,7 @@ var PlateRecognitionAddon = class {
|
|
|
629
808
|
const cfg = ctx.addonConfig;
|
|
630
809
|
const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "paddleocr-latin";
|
|
631
810
|
this.minConfidence = cfg["minConfidence"] ?? 0.5;
|
|
632
|
-
const entry = PLATE_RECOGNITION_MODELS.find((m) => m.id === modelId);
|
|
811
|
+
const entry = import_plate_recognition_models.PLATE_RECOGNITION_MODELS.find((m) => m.id === modelId);
|
|
633
812
|
if (!entry) {
|
|
634
813
|
throw new Error(`PlateRecognitionAddon: unknown modelId "${modelId}"`);
|
|
635
814
|
}
|
|
@@ -640,17 +819,17 @@ var PlateRecognitionAddon = class {
|
|
|
640
819
|
const start = Date.now();
|
|
641
820
|
const { width: inputW, height: inputH } = this.modelEntry.inputSize;
|
|
642
821
|
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}`);
|
|
643
|
-
const plateCrop = await cropRegion(input.frame.data, input.roi);
|
|
822
|
+
const plateCrop = await (0, import_image_utils.cropRegion)(input.frame.data, input.roi);
|
|
644
823
|
console.log(`[plate-recognition] Crop size: ${plateCrop.length} bytes`);
|
|
645
824
|
try {
|
|
646
825
|
require("fs").writeFileSync("/tmp/plate-recognition-crop.jpg", plateCrop);
|
|
647
826
|
} catch {
|
|
648
827
|
}
|
|
649
|
-
const normalized = await resizeAndNormalize(plateCrop, inputW, inputH, "zero-one", "nchw");
|
|
828
|
+
const normalized = await (0, import_image_utils.resizeAndNormalize)(plateCrop, inputW, inputH, "zero-one", "nchw");
|
|
650
829
|
const output = await this.engine.run(normalized, [1, 3, inputH, inputW]);
|
|
651
830
|
const numChars = this.charset.length;
|
|
652
831
|
const seqLen = output.length / numChars;
|
|
653
|
-
const { text, confidence } = ctcDecode(output, seqLen, numChars, this.charset);
|
|
832
|
+
const { text, confidence } = (0, import_paddleocr.ctcDecode)(output, seqLen, numChars, this.charset);
|
|
654
833
|
return {
|
|
655
834
|
classifications: [
|
|
656
835
|
{
|
|
@@ -669,14 +848,14 @@ var PlateRecognitionAddon = class {
|
|
|
669
848
|
const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
|
|
670
849
|
const backend = config?.backend ?? "cpu";
|
|
671
850
|
const format = config?.format ?? "onnx";
|
|
672
|
-
const entry = PLATE_RECOGNITION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
|
|
851
|
+
const entry = import_plate_recognition_models.PLATE_RECOGNITION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
|
|
673
852
|
this.modelEntry = entry;
|
|
674
853
|
const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
|
|
675
854
|
if (this.ctx.models) {
|
|
676
855
|
await this.ctx.models.ensure(modelId, format);
|
|
677
856
|
}
|
|
678
857
|
this.charset = loadCharset(modelsDir, modelId);
|
|
679
|
-
const resolved = await resolveEngine({
|
|
858
|
+
const resolved = await (0, import_engine_resolver.resolveEngine)({
|
|
680
859
|
runtime,
|
|
681
860
|
backend,
|
|
682
861
|
modelEntry: entry,
|
|
@@ -700,7 +879,7 @@ var PlateRecognitionAddon = class {
|
|
|
700
879
|
key: "modelId",
|
|
701
880
|
label: "Model",
|
|
702
881
|
type: "model-selector",
|
|
703
|
-
catalog: [...PLATE_RECOGNITION_MODELS],
|
|
882
|
+
catalog: [...import_plate_recognition_models.PLATE_RECOGNITION_MODELS],
|
|
704
883
|
allowCustom: false,
|
|
705
884
|
allowConversion: false,
|
|
706
885
|
acceptFormats: ["onnx", "openvino"],
|
|
@@ -760,13 +939,13 @@ var PlateRecognitionAddon = class {
|
|
|
760
939
|
return PLATE_REC_CLASS_MAP;
|
|
761
940
|
}
|
|
762
941
|
getModelCatalog() {
|
|
763
|
-
return [...PLATE_RECOGNITION_MODELS];
|
|
942
|
+
return [...import_plate_recognition_models.PLATE_RECOGNITION_MODELS];
|
|
764
943
|
}
|
|
765
944
|
getAvailableModels() {
|
|
766
945
|
return [];
|
|
767
946
|
}
|
|
768
947
|
getActiveLabels() {
|
|
769
|
-
return
|
|
948
|
+
return PLATE_TEXT_LABELS;
|
|
770
949
|
}
|
|
771
950
|
async probe() {
|
|
772
951
|
return {
|