@mauriciobenjamin700/ort-vision-sdk-web 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +128 -0
- package/LICENSE +21 -0
- package/README.md +90 -0
- package/dist/core/canvas.d.ts +21 -0
- package/dist/core/canvas.d.ts.map +1 -0
- package/dist/core/canvas.js +58 -0
- package/dist/core/canvas.js.map +1 -0
- package/dist/core/exceptions.d.ts +25 -0
- package/dist/core/exceptions.d.ts.map +1 -0
- package/dist/core/exceptions.js +28 -0
- package/dist/core/exceptions.js.map +1 -0
- package/dist/core/providers.d.ts +21 -0
- package/dist/core/providers.d.ts.map +1 -0
- package/dist/core/providers.js +29 -0
- package/dist/core/providers.js.map +1 -0
- package/dist/core/session.d.ts +47 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +86 -0
- package/dist/core/session.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/io/image.d.ts +17 -0
- package/dist/io/image.d.ts.map +1 -0
- package/dist/io/image.js +104 -0
- package/dist/io/image.js.map +1 -0
- package/dist/labels.d.ts +38 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +71 -0
- package/dist/labels.js.map +1 -0
- package/dist/postprocess/classification.d.ts +16 -0
- package/dist/postprocess/classification.d.ts.map +1 -0
- package/dist/postprocess/classification.js +46 -0
- package/dist/postprocess/classification.js.map +1 -0
- package/dist/postprocess/detection.d.ts +112 -0
- package/dist/postprocess/detection.d.ts.map +1 -0
- package/dist/postprocess/detection.js +283 -0
- package/dist/postprocess/detection.js.map +1 -0
- package/dist/postprocess/segmentation.d.ts +61 -0
- package/dist/postprocess/segmentation.d.ts.map +1 -0
- package/dist/postprocess/segmentation.js +184 -0
- package/dist/postprocess/segmentation.js.map +1 -0
- package/dist/preprocess/image.d.ts +71 -0
- package/dist/preprocess/image.d.ts.map +1 -0
- package/dist/preprocess/image.js +171 -0
- package/dist/preprocess/image.js.map +1 -0
- package/dist/results.d.ts +182 -0
- package/dist/results.d.ts.map +1 -0
- package/dist/results.js +321 -0
- package/dist/results.js.map +1 -0
- package/dist/tasks/base.d.ts +14 -0
- package/dist/tasks/base.d.ts.map +1 -0
- package/dist/tasks/base.js +17 -0
- package/dist/tasks/base.js.map +1 -0
- package/dist/tasks/classifier.d.ts +82 -0
- package/dist/tasks/classifier.d.ts.map +1 -0
- package/dist/tasks/classifier.js +135 -0
- package/dist/tasks/classifier.js.map +1 -0
- package/dist/tasks/detector.d.ts +102 -0
- package/dist/tasks/detector.d.ts.map +1 -0
- package/dist/tasks/detector.js +189 -0
- package/dist/tasks/detector.js.map +1 -0
- package/dist/tasks/segmenter.d.ts +105 -0
- package/dist/tasks/segmenter.d.ts.map +1 -0
- package/dist/tasks/segmenter.js +242 -0
- package/dist/tasks/segmenter.js.map +1 -0
- package/dist/types.d.ts +182 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +147 -0
- package/dist/types.js.map +1 -0
- package/package.json +71 -0
package/dist/results.js
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-image result envelopes — Ultralytics-style `Results` for the SDK.
|
|
3
|
+
*
|
|
4
|
+
* Each `predict()` call returns a 1-element array of these envelopes,
|
|
5
|
+
* mirroring `YOLO("img.jpg")`. Each envelope holds:
|
|
6
|
+
*
|
|
7
|
+
* - A bulk-array view of the predictions (`Boxes`, `Probs`, `Masks`) with
|
|
8
|
+
* the exact attribute names Ultralytics uses (`xyxy`, `xywh`, `xyxyn`,
|
|
9
|
+
* `xywhn`, `cls`, `conf`, `data`, `top1`, `top5`).
|
|
10
|
+
* - Per-instance dataclasses (`DetectionResult`, `SegmentationResult`,
|
|
11
|
+
* `ClassProbability`) for callers who prefer the OO interface.
|
|
12
|
+
* - `names`: `Record<number, string>` matching Ultralytics' `model.names`.
|
|
13
|
+
* - `origImg` / `origShape` / `path`: provenance for the original input.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Bulk numpy-style view of detected boxes for a single image.
|
|
17
|
+
*
|
|
18
|
+
* Mirrors Ultralytics' `Boxes` interface. Coordinates in {@link xyxy} and
|
|
19
|
+
* {@link xywh} are absolute pixels in the original image; the `*n` variants
|
|
20
|
+
* are normalized to `[0, 1]` using `origShape`.
|
|
21
|
+
*/
|
|
22
|
+
export class Boxes {
|
|
23
|
+
xyxy;
|
|
24
|
+
cls;
|
|
25
|
+
conf;
|
|
26
|
+
origShape;
|
|
27
|
+
/**
|
|
28
|
+
* @param xyxy Flat array of length `4 * N` in `[x1, y1, x2, y2, ...]` order.
|
|
29
|
+
* @param cls One class index per box, length `N`.
|
|
30
|
+
* @param conf One confidence per box, length `N`.
|
|
31
|
+
* @param origShape `[height, width]` of the original image.
|
|
32
|
+
*/
|
|
33
|
+
constructor(xyxy, cls, conf, origShape) {
|
|
34
|
+
this.xyxy = xyxy;
|
|
35
|
+
this.cls = cls;
|
|
36
|
+
this.conf = conf;
|
|
37
|
+
this.origShape = origShape;
|
|
38
|
+
}
|
|
39
|
+
/** Number of detected boxes. */
|
|
40
|
+
get length() {
|
|
41
|
+
return this.cls.length;
|
|
42
|
+
}
|
|
43
|
+
/** `[N, 4]` shape of the `xyxy` view. */
|
|
44
|
+
get shape() {
|
|
45
|
+
return [this.length, 4];
|
|
46
|
+
}
|
|
47
|
+
/** Boxes as `[N, 4]` `[cx, cy, w, h]` flat array in absolute pixels. */
|
|
48
|
+
get xywh() {
|
|
49
|
+
const out = new Float32Array(this.xyxy.length);
|
|
50
|
+
for (let i = 0; i < this.length; i++) {
|
|
51
|
+
const x1 = this.xyxy[i * 4];
|
|
52
|
+
const y1 = this.xyxy[i * 4 + 1];
|
|
53
|
+
const x2 = this.xyxy[i * 4 + 2];
|
|
54
|
+
const y2 = this.xyxy[i * 4 + 3];
|
|
55
|
+
out[i * 4] = (x1 + x2) / 2;
|
|
56
|
+
out[i * 4 + 1] = (y1 + y2) / 2;
|
|
57
|
+
out[i * 4 + 2] = x2 - x1;
|
|
58
|
+
out[i * 4 + 3] = y2 - y1;
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
/** Boxes as `[N, 4]` `[x1, y1, x2, y2]` normalized to `[0, 1]`. */
|
|
63
|
+
get xyxyn() {
|
|
64
|
+
const [h, w] = this.origShape;
|
|
65
|
+
const out = new Float32Array(this.xyxy.length);
|
|
66
|
+
if (this.length === 0 || w <= 0 || h <= 0)
|
|
67
|
+
return out;
|
|
68
|
+
for (let i = 0; i < this.length; i++) {
|
|
69
|
+
out[i * 4] = this.xyxy[i * 4] / w;
|
|
70
|
+
out[i * 4 + 1] = this.xyxy[i * 4 + 1] / h;
|
|
71
|
+
out[i * 4 + 2] = this.xyxy[i * 4 + 2] / w;
|
|
72
|
+
out[i * 4 + 3] = this.xyxy[i * 4 + 3] / h;
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
/** Boxes as `[N, 4]` `[cx, cy, w, h]` normalized to `[0, 1]`. */
|
|
77
|
+
get xywhn() {
|
|
78
|
+
const xywh = this.xywh;
|
|
79
|
+
const [h, w] = this.origShape;
|
|
80
|
+
if (this.length === 0 || w <= 0 || h <= 0)
|
|
81
|
+
return xywh;
|
|
82
|
+
for (let i = 0; i < this.length; i++) {
|
|
83
|
+
xywh[i * 4] = xywh[i * 4] / w;
|
|
84
|
+
xywh[i * 4 + 1] = xywh[i * 4 + 1] / h;
|
|
85
|
+
xywh[i * 4 + 2] = xywh[i * 4 + 2] / w;
|
|
86
|
+
xywh[i * 4 + 3] = xywh[i * 4 + 3] / h;
|
|
87
|
+
}
|
|
88
|
+
return xywh;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Concatenated `[N, 6]` array of `[x1, y1, x2, y2, conf, cls]`.
|
|
92
|
+
*
|
|
93
|
+
* Matches Ultralytics' `boxes.data`.
|
|
94
|
+
*/
|
|
95
|
+
get data() {
|
|
96
|
+
const out = new Float32Array(this.length * 6);
|
|
97
|
+
for (let i = 0; i < this.length; i++) {
|
|
98
|
+
out[i * 6] = this.xyxy[i * 4];
|
|
99
|
+
out[i * 6 + 1] = this.xyxy[i * 4 + 1];
|
|
100
|
+
out[i * 6 + 2] = this.xyxy[i * 4 + 2];
|
|
101
|
+
out[i * 6 + 3] = this.xyxy[i * 4 + 3];
|
|
102
|
+
out[i * 6 + 4] = this.conf[i];
|
|
103
|
+
out[i * 6 + 5] = this.cls[i];
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Top-k classification probabilities for a single image.
|
|
110
|
+
*
|
|
111
|
+
* Mirrors Ultralytics' `Probs` interface.
|
|
112
|
+
*/
|
|
113
|
+
export class Probs {
|
|
114
|
+
data;
|
|
115
|
+
/** @param data `[numClasses]` per-class probabilities, indexed by class id. */
|
|
116
|
+
constructor(data) {
|
|
117
|
+
this.data = data;
|
|
118
|
+
}
|
|
119
|
+
/** Number of classes. */
|
|
120
|
+
get length() {
|
|
121
|
+
return this.data.length;
|
|
122
|
+
}
|
|
123
|
+
/** `[numClasses]` shape of the underlying vector. */
|
|
124
|
+
get shape() {
|
|
125
|
+
return [this.length];
|
|
126
|
+
}
|
|
127
|
+
/** Index of the most probable class. */
|
|
128
|
+
get top1() {
|
|
129
|
+
if (this.data.length === 0)
|
|
130
|
+
return 0;
|
|
131
|
+
let best = 0;
|
|
132
|
+
let bestVal = this.data[0];
|
|
133
|
+
for (let i = 1; i < this.data.length; i++) {
|
|
134
|
+
const v = this.data[i];
|
|
135
|
+
if (v > bestVal) {
|
|
136
|
+
best = i;
|
|
137
|
+
bestVal = v;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return best;
|
|
141
|
+
}
|
|
142
|
+
/** Probability of the top-1 class. */
|
|
143
|
+
get top1conf() {
|
|
144
|
+
if (this.data.length === 0)
|
|
145
|
+
return 0;
|
|
146
|
+
return this.data[this.top1];
|
|
147
|
+
}
|
|
148
|
+
/** Indices of the top-5 most probable classes, descending. */
|
|
149
|
+
get top5() {
|
|
150
|
+
return this._topK(5).indices;
|
|
151
|
+
}
|
|
152
|
+
/** Probabilities of the top-5 classes, descending. */
|
|
153
|
+
get top5conf() {
|
|
154
|
+
return this._topK(5).values;
|
|
155
|
+
}
|
|
156
|
+
_topK(k) {
|
|
157
|
+
const n = Math.min(k, this.data.length);
|
|
158
|
+
const order = [];
|
|
159
|
+
for (let i = 0; i < this.data.length; i++)
|
|
160
|
+
order.push(i);
|
|
161
|
+
order.sort((a, b) => this.data[b] - this.data[a]);
|
|
162
|
+
const indices = new Int32Array(n);
|
|
163
|
+
const values = new Float32Array(n);
|
|
164
|
+
for (let i = 0; i < n; i++) {
|
|
165
|
+
indices[i] = order[i];
|
|
166
|
+
values[i] = this.data[order[i]];
|
|
167
|
+
}
|
|
168
|
+
return { indices, values };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Per-instance binary masks for a single image.
|
|
173
|
+
*
|
|
174
|
+
* Each mask is cropped to its instance's bounding box. To paint masks onto
|
|
175
|
+
* a full-image canvas, use `xyxy[i]` as the top-left target.
|
|
176
|
+
*/
|
|
177
|
+
export class Masks {
|
|
178
|
+
data;
|
|
179
|
+
xyxy;
|
|
180
|
+
origShape;
|
|
181
|
+
/**
|
|
182
|
+
* @param data Per-instance binary masks (`Mask` objects from `types.ts`).
|
|
183
|
+
* @param xyxy Flat `[N, 4]` of bounding-box coordinates in original pixels.
|
|
184
|
+
* @param origShape `[height, width]` of the original image.
|
|
185
|
+
*/
|
|
186
|
+
constructor(data, xyxy, origShape) {
|
|
187
|
+
this.data = data;
|
|
188
|
+
this.xyxy = xyxy;
|
|
189
|
+
this.origShape = origShape;
|
|
190
|
+
}
|
|
191
|
+
/** Number of instance masks. */
|
|
192
|
+
get length() {
|
|
193
|
+
return this.data.length;
|
|
194
|
+
}
|
|
195
|
+
/** `[N]` shape of the masks collection. */
|
|
196
|
+
get shape() {
|
|
197
|
+
return [this.length];
|
|
198
|
+
}
|
|
199
|
+
[Symbol.iterator]() {
|
|
200
|
+
return this.data[Symbol.iterator]();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Per-image detection envelope (Ultralytics-style `Results`).
|
|
205
|
+
*
|
|
206
|
+
* Iterating yields per-instance {@link DetectionResult} entries, so legacy
|
|
207
|
+
* code that did `for (const d of detector.predict(img))` only needs an
|
|
208
|
+
* extra `[0]` to bridge:
|
|
209
|
+
*
|
|
210
|
+
* ```typescript
|
|
211
|
+
* for (const d of (await detector.predict(img))[0]) {
|
|
212
|
+
* console.log(d.cls, d.conf, d.box.xyxy);
|
|
213
|
+
* }
|
|
214
|
+
* ```
|
|
215
|
+
*
|
|
216
|
+
* For numpy-style bulk access, use the `boxes` collection.
|
|
217
|
+
*/
|
|
218
|
+
export class DetectionResults {
|
|
219
|
+
boxes;
|
|
220
|
+
detections;
|
|
221
|
+
names;
|
|
222
|
+
origImg;
|
|
223
|
+
origShape;
|
|
224
|
+
path;
|
|
225
|
+
speed;
|
|
226
|
+
constructor(boxes, detections, names, origImg, origShape, path = null, speed = {}) {
|
|
227
|
+
this.boxes = boxes;
|
|
228
|
+
this.detections = detections;
|
|
229
|
+
this.names = names;
|
|
230
|
+
this.origImg = origImg;
|
|
231
|
+
this.origShape = origShape;
|
|
232
|
+
this.path = path;
|
|
233
|
+
this.speed = speed;
|
|
234
|
+
}
|
|
235
|
+
/** Number of surviving detections. */
|
|
236
|
+
get length() {
|
|
237
|
+
return this.detections.length;
|
|
238
|
+
}
|
|
239
|
+
/** Index into the per-instance detections. */
|
|
240
|
+
get(index) {
|
|
241
|
+
return this.detections[index];
|
|
242
|
+
}
|
|
243
|
+
[Symbol.iterator]() {
|
|
244
|
+
return this.detections[Symbol.iterator]();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Per-image classification envelope (Ultralytics-style `Results`).
|
|
249
|
+
*/
|
|
250
|
+
export class ClassificationResults {
|
|
251
|
+
probs;
|
|
252
|
+
result;
|
|
253
|
+
names;
|
|
254
|
+
origImg;
|
|
255
|
+
origShape;
|
|
256
|
+
path;
|
|
257
|
+
speed;
|
|
258
|
+
constructor(probs, result, names, origImg, origShape, path = null, speed = {}) {
|
|
259
|
+
this.probs = probs;
|
|
260
|
+
this.result = result;
|
|
261
|
+
this.names = names;
|
|
262
|
+
this.origImg = origImg;
|
|
263
|
+
this.origShape = origShape;
|
|
264
|
+
this.path = path;
|
|
265
|
+
this.speed = speed;
|
|
266
|
+
}
|
|
267
|
+
/** Top-1 class index (Ultralytics-style alias). */
|
|
268
|
+
get cls() {
|
|
269
|
+
return this.probs.top1;
|
|
270
|
+
}
|
|
271
|
+
/** Top-1 confidence (Ultralytics-style alias). */
|
|
272
|
+
get conf() {
|
|
273
|
+
return this.probs.top1conf;
|
|
274
|
+
}
|
|
275
|
+
/** Top-1 class name. */
|
|
276
|
+
get name() {
|
|
277
|
+
return this.names[this.cls] ?? `class_${this.cls}`;
|
|
278
|
+
}
|
|
279
|
+
/** Per-class probability list, sorted descending (legacy field). */
|
|
280
|
+
get probabilities() {
|
|
281
|
+
return this.result.probabilities;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Per-image instance-segmentation envelope (Ultralytics-style `Results`).
|
|
286
|
+
*
|
|
287
|
+
* Iterating yields per-instance {@link SegmentationResult} entries. `boxes`
|
|
288
|
+
* and `masks` mirror Ultralytics' bulk-array views.
|
|
289
|
+
*/
|
|
290
|
+
export class SegmentationResults {
|
|
291
|
+
boxes;
|
|
292
|
+
masks;
|
|
293
|
+
detections;
|
|
294
|
+
names;
|
|
295
|
+
origImg;
|
|
296
|
+
origShape;
|
|
297
|
+
path;
|
|
298
|
+
speed;
|
|
299
|
+
constructor(boxes, masks, detections, names, origImg, origShape, path = null, speed = {}) {
|
|
300
|
+
this.boxes = boxes;
|
|
301
|
+
this.masks = masks;
|
|
302
|
+
this.detections = detections;
|
|
303
|
+
this.names = names;
|
|
304
|
+
this.origImg = origImg;
|
|
305
|
+
this.origShape = origShape;
|
|
306
|
+
this.path = path;
|
|
307
|
+
this.speed = speed;
|
|
308
|
+
}
|
|
309
|
+
/** Number of surviving instances. */
|
|
310
|
+
get length() {
|
|
311
|
+
return this.detections.length;
|
|
312
|
+
}
|
|
313
|
+
/** Index into the per-instance results. */
|
|
314
|
+
get(index) {
|
|
315
|
+
return this.detections[index];
|
|
316
|
+
}
|
|
317
|
+
[Symbol.iterator]() {
|
|
318
|
+
return this.detections[Symbol.iterator]();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=results.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"results.js","sourceRoot":"","sources":["../src/results.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common foundation for task-oriented vision SDK objects.
|
|
3
|
+
*
|
|
4
|
+
* The base only owns the {@link OrtSession} — label resolution lives in each
|
|
5
|
+
* subclass because how `numClasses` is read from the model differs per task.
|
|
6
|
+
*/
|
|
7
|
+
import { OrtSession } from "../core/session.js";
|
|
8
|
+
export declare abstract class VisionTask {
|
|
9
|
+
protected readonly _session: OrtSession;
|
|
10
|
+
protected constructor(_session: OrtSession);
|
|
11
|
+
/** The underlying {@link OrtSession} used to run inference. */
|
|
12
|
+
get session(): OrtSession;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/tasks/base.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,8BAAsB,UAAU;IACR,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU;IAA7D,SAAS,aAAgC,QAAQ,EAAE,UAAU;IAE7D,+DAA+D;IAC/D,IAAI,OAAO,IAAI,UAAU,CAExB;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common foundation for task-oriented vision SDK objects.
|
|
3
|
+
*
|
|
4
|
+
* The base only owns the {@link OrtSession} — label resolution lives in each
|
|
5
|
+
* subclass because how `numClasses` is read from the model differs per task.
|
|
6
|
+
*/
|
|
7
|
+
export class VisionTask {
|
|
8
|
+
_session;
|
|
9
|
+
constructor(_session) {
|
|
10
|
+
this._session = _session;
|
|
11
|
+
}
|
|
12
|
+
/** The underlying {@link OrtSession} used to run inference. */
|
|
13
|
+
get session() {
|
|
14
|
+
return this._session;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/tasks/base.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,OAAgB,UAAU;IACW;IAAzC,YAAyC,QAAoB;QAApB,aAAQ,GAAR,QAAQ,CAAY;IAAG,CAAC;IAEjE,+DAA+D;IAC/D,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image classification task using ONNX Runtime Web.
|
|
3
|
+
*/
|
|
4
|
+
import { type ModelSource, type OrtSessionOptions } from "../core/session.js";
|
|
5
|
+
import { type ImageInput } from "../io/image.js";
|
|
6
|
+
import { type LabelSpec } from "../labels.js";
|
|
7
|
+
import { ClassificationResults } from "../results.js";
|
|
8
|
+
import { VisionTask } from "./base.js";
|
|
9
|
+
export interface ClassifierOptions extends OrtSessionOptions {
|
|
10
|
+
/** Class label spec — see {@link resolveLabels}. */
|
|
11
|
+
readonly labels: LabelSpec;
|
|
12
|
+
/**
|
|
13
|
+
* Number of classes the model can predict. Required when `labels` is `null`
|
|
14
|
+
* or when you want to validate that the supplied labels match the model.
|
|
15
|
+
*/
|
|
16
|
+
readonly numClasses?: number;
|
|
17
|
+
/** Model input `[width, height]` in pixels. Defaults to `[224, 224]`. */
|
|
18
|
+
readonly inputSize?: readonly [number, number];
|
|
19
|
+
/** Per-channel RGB mean used for normalization. Defaults to ImageNet. */
|
|
20
|
+
readonly mean?: readonly [number, number, number];
|
|
21
|
+
/** Per-channel RGB standard deviation. Defaults to ImageNet. */
|
|
22
|
+
readonly std?: readonly [number, number, number];
|
|
23
|
+
/**
|
|
24
|
+
* If `true` (default), apply softmax to the raw model output. Set to
|
|
25
|
+
* `false` for models whose final layer already produces a probability
|
|
26
|
+
* distribution.
|
|
27
|
+
*/
|
|
28
|
+
readonly applySoftmax?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface ClassifierPredictOptions {
|
|
31
|
+
/**
|
|
32
|
+
* If set, the per-class probability list in `results[0].result.probabilities`
|
|
33
|
+
* is truncated to the top-K entries. The bulk `probs` view always exposes
|
|
34
|
+
* the full vector.
|
|
35
|
+
*/
|
|
36
|
+
readonly topK?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Image classifier wrapping an ONNX model with ImageNet-style preprocessing.
|
|
40
|
+
*
|
|
41
|
+
* `predict()` returns `Promise<ClassificationResults[]>` (length 1 for a
|
|
42
|
+
* single image), mirroring Ultralytics' API. The envelope exposes a `probs`
|
|
43
|
+
* collection (`top1`, `top1conf`, `top5`, `top5conf`, `data`) plus the
|
|
44
|
+
* legacy per-class probability list with names already resolved.
|
|
45
|
+
*
|
|
46
|
+
* Defaults: 224×224 RGB input, `float32` normalized with ImageNet mean/std,
|
|
47
|
+
* NCHW layout, batch size 1, softmax applied to the raw output.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const clf = await Classifier.create("/models/resnet50.onnx", {
|
|
52
|
+
* labels: ["tench", "goldfish", ...] // 1000 ImageNet labels
|
|
53
|
+
* });
|
|
54
|
+
* const r = (await clf.predict("/images/dog.jpg"))[0];
|
|
55
|
+
* console.log(r.cls, r.conf, r.name);
|
|
56
|
+
* console.log(r.probs.top5, r.probs.top5conf);
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare class Classifier extends VisionTask {
|
|
60
|
+
private readonly _labels;
|
|
61
|
+
private readonly _names;
|
|
62
|
+
private readonly _inputSize;
|
|
63
|
+
private readonly _mean;
|
|
64
|
+
private readonly _std;
|
|
65
|
+
private readonly _applySoftmax;
|
|
66
|
+
private constructor();
|
|
67
|
+
/** Load the model and resolve labels. */
|
|
68
|
+
static create(model: ModelSource, options: ClassifierOptions): Promise<Classifier>;
|
|
69
|
+
/** Class labels indexed by class id. */
|
|
70
|
+
get labels(): readonly string[];
|
|
71
|
+
/** Class id → class name dict (matches Ultralytics' `model.names`). */
|
|
72
|
+
get names(): Readonly<Record<number, string>>;
|
|
73
|
+
/** Number of classes the model can predict. */
|
|
74
|
+
get numClasses(): number;
|
|
75
|
+
/** Alias for {@link predict} (parity with PyTorch `nn.Module.__call__`). */
|
|
76
|
+
call(image: ImageInput, options?: ClassifierPredictOptions): Promise<ClassificationResults[]>;
|
|
77
|
+
/** Run classification on a single image. */
|
|
78
|
+
predict(image: ImageInput, options?: ClassifierPredictOptions): Promise<ClassificationResults[]>;
|
|
79
|
+
private _preprocess;
|
|
80
|
+
private _postprocess;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../../src/tasks/classifier.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAc,MAAM,oBAAoB,CAAC;AAC1F,OAAO,EAAE,KAAK,UAAU,EAAa,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,cAAc,CAAC;AAQ7D,OAAO,EAAE,qBAAqB,EAAS,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAUvC,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,yEAAyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,gEAAgE;IAChE,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,UAAW,SAAQ,UAAU;IAGtC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAPhC,OAAO;IAYP,yCAAyC;WAC5B,MAAM,CACjB,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,UAAU,CAAC;IAkBtB,wCAAwC;IACxC,IAAI,MAAM,IAAI,SAAS,MAAM,EAAE,CAE9B;IAED,uEAAuE;IACvE,IAAI,KAAK,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAE5C;IAED,+CAA+C;IAC/C,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,4EAA4E;IACtE,IAAI,CACR,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAInC,4CAA4C;IACtC,OAAO,CACX,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,qBAAqB,EAAE,CAAC;IA0DnC,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,YAAY;CAGrB"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image classification task using ONNX Runtime Web.
|
|
3
|
+
*/
|
|
4
|
+
import { OrtSession } from "../core/session.js";
|
|
5
|
+
import { loadImage } from "../io/image.js";
|
|
6
|
+
import { resolveLabels } from "../labels.js";
|
|
7
|
+
import { softmax, topK } from "../postprocess/classification.js";
|
|
8
|
+
import { normalize, resize, toCHW, toFloat32Tensor, } from "../preprocess/image.js";
|
|
9
|
+
import { ClassificationResults, Probs } from "../results.js";
|
|
10
|
+
import { VisionTask } from "./base.js";
|
|
11
|
+
const IMAGENET_MEAN = [0.485, 0.456, 0.406];
|
|
12
|
+
const IMAGENET_STD = [0.229, 0.224, 0.225];
|
|
13
|
+
/**
|
|
14
|
+
* Image classifier wrapping an ONNX model with ImageNet-style preprocessing.
|
|
15
|
+
*
|
|
16
|
+
* `predict()` returns `Promise<ClassificationResults[]>` (length 1 for a
|
|
17
|
+
* single image), mirroring Ultralytics' API. The envelope exposes a `probs`
|
|
18
|
+
* collection (`top1`, `top1conf`, `top5`, `top5conf`, `data`) plus the
|
|
19
|
+
* legacy per-class probability list with names already resolved.
|
|
20
|
+
*
|
|
21
|
+
* Defaults: 224×224 RGB input, `float32` normalized with ImageNet mean/std,
|
|
22
|
+
* NCHW layout, batch size 1, softmax applied to the raw output.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const clf = await Classifier.create("/models/resnet50.onnx", {
|
|
27
|
+
* labels: ["tench", "goldfish", ...] // 1000 ImageNet labels
|
|
28
|
+
* });
|
|
29
|
+
* const r = (await clf.predict("/images/dog.jpg"))[0];
|
|
30
|
+
* console.log(r.cls, r.conf, r.name);
|
|
31
|
+
* console.log(r.probs.top5, r.probs.top5conf);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export class Classifier extends VisionTask {
|
|
35
|
+
_labels;
|
|
36
|
+
_names;
|
|
37
|
+
_inputSize;
|
|
38
|
+
_mean;
|
|
39
|
+
_std;
|
|
40
|
+
_applySoftmax;
|
|
41
|
+
constructor(session, _labels, _names, _inputSize, _mean, _std, _applySoftmax) {
|
|
42
|
+
super(session);
|
|
43
|
+
this._labels = _labels;
|
|
44
|
+
this._names = _names;
|
|
45
|
+
this._inputSize = _inputSize;
|
|
46
|
+
this._mean = _mean;
|
|
47
|
+
this._std = _std;
|
|
48
|
+
this._applySoftmax = _applySoftmax;
|
|
49
|
+
}
|
|
50
|
+
/** Load the model and resolve labels. */
|
|
51
|
+
static async create(model, options) {
|
|
52
|
+
const session = await OrtSession.create(model, options);
|
|
53
|
+
const labels = resolveLabels(options.labels, { numClasses: options.numClasses });
|
|
54
|
+
const names = {};
|
|
55
|
+
for (let i = 0; i < labels.length; i++) {
|
|
56
|
+
names[i] = labels[i];
|
|
57
|
+
}
|
|
58
|
+
return new Classifier(session, labels, names, options.inputSize ?? [224, 224], options.mean ?? IMAGENET_MEAN, options.std ?? IMAGENET_STD, options.applySoftmax ?? true);
|
|
59
|
+
}
|
|
60
|
+
/** Class labels indexed by class id. */
|
|
61
|
+
get labels() {
|
|
62
|
+
return this._labels;
|
|
63
|
+
}
|
|
64
|
+
/** Class id → class name dict (matches Ultralytics' `model.names`). */
|
|
65
|
+
get names() {
|
|
66
|
+
return this._names;
|
|
67
|
+
}
|
|
68
|
+
/** Number of classes the model can predict. */
|
|
69
|
+
get numClasses() {
|
|
70
|
+
return this._labels.length;
|
|
71
|
+
}
|
|
72
|
+
/** Alias for {@link predict} (parity with PyTorch `nn.Module.__call__`). */
|
|
73
|
+
async call(image, options = {}) {
|
|
74
|
+
return this.predict(image, options);
|
|
75
|
+
}
|
|
76
|
+
/** Run classification on a single image. */
|
|
77
|
+
async predict(image, options = {}) {
|
|
78
|
+
const path = typeof image === "string" ? image : null;
|
|
79
|
+
const original = await loadImage(image);
|
|
80
|
+
const tensor = this._preprocess(original);
|
|
81
|
+
const outputs = await this._session.run({ [this._session.inputName]: tensor });
|
|
82
|
+
const firstOutputName = this._session.outputNames[0];
|
|
83
|
+
if (firstOutputName === undefined) {
|
|
84
|
+
throw new Error("Classifier model has no outputs.");
|
|
85
|
+
}
|
|
86
|
+
const raw = outputs[firstOutputName];
|
|
87
|
+
if (raw === undefined) {
|
|
88
|
+
throw new Error(`Classifier model output ${firstOutputName} missing from run() result.`);
|
|
89
|
+
}
|
|
90
|
+
const fullProbs = this._postprocess(raw.data);
|
|
91
|
+
const { indices, values } = topK(fullProbs, options.topK ?? null);
|
|
92
|
+
const probabilities = [];
|
|
93
|
+
for (let i = 0; i < indices.length; i++) {
|
|
94
|
+
const id = indices[i];
|
|
95
|
+
const className = this._labels[id] ?? `class_${id}`;
|
|
96
|
+
probabilities.push({
|
|
97
|
+
classId: id,
|
|
98
|
+
className,
|
|
99
|
+
probability: values[i],
|
|
100
|
+
cls: id,
|
|
101
|
+
name: className,
|
|
102
|
+
conf: values[i],
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (probabilities.length === 0) {
|
|
106
|
+
throw new Error("Classifier produced no probabilities (empty output).");
|
|
107
|
+
}
|
|
108
|
+
const top = probabilities[0];
|
|
109
|
+
const result = {
|
|
110
|
+
classId: top.classId,
|
|
111
|
+
className: top.className,
|
|
112
|
+
confidence: top.probability,
|
|
113
|
+
cls: top.classId,
|
|
114
|
+
name: top.className,
|
|
115
|
+
conf: top.probability,
|
|
116
|
+
image: original,
|
|
117
|
+
probabilities,
|
|
118
|
+
};
|
|
119
|
+
const orig = [original.height, original.width];
|
|
120
|
+
return [
|
|
121
|
+
new ClassificationResults(new Probs(fullProbs), result, this._names, original, orig, path),
|
|
122
|
+
];
|
|
123
|
+
}
|
|
124
|
+
_preprocess(image) {
|
|
125
|
+
const [tw, th] = this._inputSize;
|
|
126
|
+
const resized = resize(image, tw, th);
|
|
127
|
+
const normalized = normalize(resized, this._mean, this._std);
|
|
128
|
+
const chw = toCHW(normalized, resized.width, resized.height, 3);
|
|
129
|
+
return toFloat32Tensor(chw, [1, 3, resized.height, resized.width]);
|
|
130
|
+
}
|
|
131
|
+
_postprocess(raw) {
|
|
132
|
+
return this._applySoftmax ? softmax(raw) : new Float32Array(raw);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifier.js","sourceRoot":"","sources":["../../src/tasks/classifier.ts"],"names":[],"mappings":"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"}
|