tempest-react-sdk 0.34.0 → 0.36.0
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/README.md +72 -68
- package/dist/audio/audio-output.cjs +2 -0
- package/dist/audio/audio-output.cjs.map +1 -0
- package/dist/audio/audio-output.js +17 -0
- package/dist/audio/audio-output.js.map +1 -0
- package/dist/audio/audio-player.cjs +1 -1
- package/dist/audio/audio-player.cjs.map +1 -1
- package/dist/audio/audio-player.js +21 -20
- package/dist/audio/audio-player.js.map +1 -1
- package/dist/audio/audio-recorder.cjs +2 -0
- package/dist/audio/audio-recorder.cjs.map +1 -0
- package/dist/audio/audio-recorder.js +30 -0
- package/dist/audio/audio-recorder.js.map +1 -0
- package/dist/audio/duration.cjs +2 -0
- package/dist/audio/duration.cjs.map +1 -0
- package/dist/audio/duration.js +10 -0
- package/dist/audio/duration.js.map +1 -0
- package/dist/audio/level-meter.cjs +2 -0
- package/dist/audio/level-meter.cjs.map +1 -0
- package/dist/audio/level-meter.js +34 -0
- package/dist/audio/level-meter.js.map +1 -0
- package/dist/audio/media-access.cjs +2 -0
- package/dist/audio/media-access.cjs.map +1 -0
- package/dist/audio/media-access.js +51 -0
- package/dist/audio/media-access.js.map +1 -0
- package/dist/audio/use-audio-recorder.cjs +2 -0
- package/dist/audio/use-audio-recorder.cjs.map +1 -0
- package/dist/audio/use-audio-recorder.js +94 -0
- package/dist/audio/use-audio-recorder.js.map +1 -0
- package/dist/audio/use-audio.cjs.map +1 -1
- package/dist/audio/use-audio.js.map +1 -1
- package/dist/audio/use-microphone.cjs +2 -0
- package/dist/audio/use-microphone.cjs.map +1 -0
- package/dist/audio/use-microphone.js +54 -0
- package/dist/audio/use-microphone.js.map +1 -0
- package/dist/audio/wav.cjs +2 -0
- package/dist/audio/wav.cjs.map +1 -0
- package/dist/audio/wav.js +49 -0
- package/dist/audio/wav.js.map +1 -0
- package/dist/auth/passkey.cjs +2 -0
- package/dist/auth/passkey.cjs.map +1 -0
- package/dist/auth/passkey.js +171 -0
- package/dist/auth/passkey.js.map +1 -0
- package/dist/auth/use-passkey.cjs +2 -0
- package/dist/auth/use-passkey.cjs.map +1 -0
- package/dist/auth/use-passkey.js +120 -0
- package/dist/auth/use-passkey.js.map +1 -0
- package/dist/br/PixQRCode.cjs +2 -0
- package/dist/br/PixQRCode.cjs.map +1 -0
- package/dist/br/PixQRCode.js +70 -0
- package/dist/br/PixQRCode.js.map +1 -0
- package/dist/br/PixQRCode.module.cjs +2 -0
- package/dist/br/PixQRCode.module.cjs.map +1 -0
- package/dist/br/PixQRCode.module.js +15 -0
- package/dist/br/PixQRCode.module.js.map +1 -0
- package/dist/br/boleto.cjs +2 -0
- package/dist/br/boleto.cjs.map +1 -0
- package/dist/br/boleto.js +225 -0
- package/dist/br/boleto.js.map +1 -0
- package/dist/br/holidays.cjs +2 -0
- package/dist/br/holidays.cjs.map +1 -0
- package/dist/br/holidays.js +148 -0
- package/dist/br/holidays.js.map +1 -0
- package/dist/br/nfe.cjs +2 -0
- package/dist/br/nfe.cjs.map +1 -0
- package/dist/br/nfe.js +104 -0
- package/dist/br/nfe.js.map +1 -0
- package/dist/br/pix.cjs +2 -0
- package/dist/br/pix.cjs.map +1 -0
- package/dist/br/pix.js +148 -0
- package/dist/br/pix.js.map +1 -0
- package/dist/br.cjs +1 -1
- package/dist/br.cjs.map +1 -1
- package/dist/br.d.ts +878 -0
- package/dist/br.js +7 -2
- package/dist/br.js.map +1 -1
- package/dist/capture/barcode.cjs +2 -0
- package/dist/capture/barcode.cjs.map +1 -0
- package/dist/capture/barcode.js +59 -0
- package/dist/capture/barcode.js.map +1 -0
- package/dist/capture/media-recorder.cjs +2 -0
- package/dist/capture/media-recorder.cjs.map +1 -0
- package/dist/capture/media-recorder.js +64 -0
- package/dist/capture/media-recorder.js.map +1 -0
- package/dist/capture/use-barcode-scanner.cjs +2 -0
- package/dist/capture/use-barcode-scanner.cjs.map +1 -0
- package/dist/capture/use-barcode-scanner.js +86 -0
- package/dist/capture/use-barcode-scanner.js.map +1 -0
- package/dist/capture/use-screen-capture.cjs +2 -0
- package/dist/capture/use-screen-capture.cjs.map +1 -0
- package/dist/capture/use-screen-capture.js +79 -0
- package/dist/capture/use-screen-capture.js.map +1 -0
- package/dist/capture/use-speech-recognition.cjs +2 -0
- package/dist/capture/use-speech-recognition.cjs.map +1 -0
- package/dist/capture/use-speech-recognition.js +118 -0
- package/dist/capture/use-speech-recognition.js.map +1 -0
- package/dist/capture/use-torch.cjs +2 -0
- package/dist/capture/use-torch.cjs.map +1 -0
- package/dist/capture/use-torch.js +33 -0
- package/dist/capture/use-torch.js.map +1 -0
- package/dist/capture/use-video-recorder.cjs +2 -0
- package/dist/capture/use-video-recorder.cjs.map +1 -0
- package/dist/capture/use-video-recorder.js +90 -0
- package/dist/capture/use-video-recorder.js.map +1 -0
- package/dist/capture/video-recorder.cjs +2 -0
- package/dist/capture/video-recorder.cjs.map +1 -0
- package/dist/capture/video-recorder.js +31 -0
- package/dist/capture/video-recorder.js.map +1 -0
- package/dist/components/AIChat/AIChat.cjs +1 -1
- package/dist/components/AIChat/AIChat.cjs.map +1 -1
- package/dist/components/AIChat/AIChat.js +93 -97
- package/dist/components/AIChat/AIChat.js.map +1 -1
- package/dist/components/AIChat/AIChatComposer.cjs +1 -1
- package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
- package/dist/components/AIChat/AIChatComposer.js +2 -1
- package/dist/components/AIChat/AIChatComposer.js.map +1 -1
- package/dist/components/AIChat/AIChatTurn.cjs +2 -2
- package/dist/components/AIChat/AIChatTurn.js +6 -6
- package/dist/components/AIChat/AIChatTurn.js.map +1 -1
- package/dist/components/Alert/Alert.module.cjs.map +1 -1
- package/dist/components/Alert/Alert.module.js.map +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.cjs +2 -0
- package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -0
- package/dist/components/AudioPlayer/AudioPlayer.js +123 -0
- package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -0
- package/dist/components/AudioPlayer/AudioPlayer.module.cjs +2 -0
- package/dist/components/AudioPlayer/AudioPlayer.module.cjs.map +1 -0
- package/dist/components/AudioPlayer/AudioPlayer.module.js +12 -0
- package/dist/components/AudioPlayer/AudioPlayer.module.js.map +1 -0
- package/dist/components/AudioRecorder/AudioRecorder.cjs +2 -0
- package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -0
- package/dist/components/AudioRecorder/AudioRecorder.js +179 -0
- package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -0
- package/dist/components/AudioRecorder/AudioRecorder.module.cjs +2 -0
- package/dist/components/AudioRecorder/AudioRecorder.module.cjs.map +1 -0
- package/dist/components/AudioRecorder/AudioRecorder.module.js +19 -0
- package/dist/components/AudioRecorder/AudioRecorder.module.js.map +1 -0
- package/dist/components/Badge/Badge.module.cjs.map +1 -1
- package/dist/components/Badge/Badge.module.js.map +1 -1
- package/dist/components/BarcodeScanner/BarcodeScanner.cjs +2 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.js +123 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs +2 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs.map +1 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.module.js +22 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.module.js.map +1 -0
- package/dist/components/BottomNavigation/BottomNavigation.module.cjs.map +1 -1
- package/dist/components/BottomNavigation/BottomNavigation.module.js.map +1 -1
- package/dist/components/Button/Button.module.cjs.map +1 -1
- package/dist/components/Button/Button.module.js.map +1 -1
- package/dist/components/Combobox/Combobox.module.cjs.map +1 -1
- package/dist/components/Combobox/Combobox.module.js.map +1 -1
- package/dist/components/DataTable/DataTable.cjs +1 -1
- package/dist/components/DataTable/DataTable.cjs.map +1 -1
- package/dist/components/DataTable/DataTable.js +203 -66
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/DataTable.module.cjs +1 -1
- package/dist/components/DataTable/DataTable.module.cjs.map +1 -1
- package/dist/components/DataTable/DataTable.module.js +9 -3
- package/dist/components/DataTable/DataTable.module.js.map +1 -1
- package/dist/components/DataTable/EditableCell.cjs +2 -0
- package/dist/components/DataTable/EditableCell.cjs.map +1 -0
- package/dist/components/DataTable/EditableCell.js +77 -0
- package/dist/components/DataTable/EditableCell.js.map +1 -0
- package/dist/components/DataTable/edit-labels.cjs +2 -0
- package/dist/components/DataTable/edit-labels.cjs.map +1 -0
- package/dist/components/DataTable/edit-labels.js +11 -0
- package/dist/components/DataTable/edit-labels.js.map +1 -0
- package/dist/components/DateRangePicker/DateRangePicker.module.cjs.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.module.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.module.cjs.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.module.js.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.module.cjs.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.module.js.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.js +33 -32
- package/dist/components/SyncStatusBadge/SyncStatusBadge.js.map +1 -1
- package/dist/components/Toast/ToastProvider.cjs +1 -1
- package/dist/components/Toast/ToastProvider.cjs.map +1 -1
- package/dist/components/Toast/ToastProvider.js +1 -2
- package/dist/components/Toast/ToastProvider.js.map +1 -1
- package/dist/hooks/use-announce.cjs +2 -0
- package/dist/hooks/use-announce.cjs.map +1 -0
- package/dist/hooks/use-announce.js +50 -0
- package/dist/hooks/use-announce.js.map +1 -0
- package/dist/hooks/use-media-devices.cjs +2 -0
- package/dist/hooks/use-media-devices.cjs.map +1 -0
- package/dist/hooks/use-media-devices.js +46 -0
- package/dist/hooks/use-media-devices.js.map +1 -0
- package/dist/hooks/use-media-permission.cjs +2 -0
- package/dist/hooks/use-media-permission.cjs.map +1 -0
- package/dist/hooks/use-media-permission.js +33 -0
- package/dist/hooks/use-media-permission.js.map +1 -0
- package/dist/http/resumable-upload.cjs +2 -0
- package/dist/http/resumable-upload.cjs.map +1 -0
- package/dist/http/resumable-upload.js +249 -0
- package/dist/http/resumable-upload.js.map +1 -0
- package/dist/perf/cache-size.cjs +2 -0
- package/dist/perf/cache-size.cjs.map +1 -0
- package/dist/perf/cache-size.js +16 -0
- package/dist/perf/cache-size.js.map +1 -0
- package/dist/perf/device.cjs +2 -0
- package/dist/perf/device.cjs.map +1 -0
- package/dist/perf/device.js +22 -0
- package/dist/perf/device.js.map +1 -0
- package/dist/perf/format.cjs +2 -0
- package/dist/perf/format.cjs.map +1 -0
- package/dist/perf/format.js +8 -0
- package/dist/perf/format.js.map +1 -0
- package/dist/perf/profiler.cjs +2 -0
- package/dist/perf/profiler.cjs.map +1 -0
- package/dist/perf/profiler.js +46 -0
- package/dist/perf/profiler.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +2705 -38
- package/dist/tempest-react-sdk.js +268 -240
- package/dist/vision/core/timing.cjs +2 -0
- package/dist/vision/core/timing.cjs.map +1 -0
- package/dist/vision/core/timing.js +24 -0
- package/dist/vision/core/timing.js.map +1 -0
- package/dist/vision/index.cjs +1 -1
- package/dist/vision/index.cjs.map +1 -1
- package/dist/vision/index.js +16 -15
- package/dist/vision/index.js.map +1 -1
- package/dist/vision/postprocess/detection.cjs +1 -1
- package/dist/vision/postprocess/detection.cjs.map +1 -1
- package/dist/vision/postprocess/detection.js +2 -2
- package/dist/vision/postprocess/detection.js.map +1 -1
- package/dist/vision/postprocess/segmentation.cjs +1 -1
- package/dist/vision/postprocess/segmentation.cjs.map +1 -1
- package/dist/vision/postprocess/segmentation.js +1 -1
- package/dist/vision/postprocess/segmentation.js.map +1 -1
- package/dist/vision/results.cjs +1 -1
- package/dist/vision/results.cjs.map +1 -1
- package/dist/vision/results.js +18 -13
- package/dist/vision/results.js.map +1 -1
- package/dist/vision/tasks/classifier.cjs +1 -1
- package/dist/vision/tasks/classifier.cjs.map +1 -1
- package/dist/vision/tasks/classifier.js +46 -39
- package/dist/vision/tasks/classifier.js.map +1 -1
- package/dist/vision/tasks/detector.cjs +1 -1
- package/dist/vision/tasks/detector.cjs.map +1 -1
- package/dist/vision/tasks/detector.js +40 -33
- package/dist/vision/tasks/detector.js.map +1 -1
- package/dist/vision/tasks/segmenter.cjs +1 -1
- package/dist/vision/tasks/segmenter.cjs.map +1 -1
- package/dist/vision/tasks/segmenter.js +35 -28
- package/dist/vision/tasks/segmenter.js.map +1 -1
- package/dist/vision/use-camera-stream.cjs +1 -1
- package/dist/vision/use-camera-stream.cjs.map +1 -1
- package/dist/vision/use-camera-stream.js +40 -57
- package/dist/vision/use-camera-stream.js.map +1 -1
- package/dist/vision.cjs +1 -1
- package/dist/vision.d.ts +93 -13
- package/dist/vision.js +21 -20
- package/package.json +1 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=class{_last;_speed={load:0,preprocess:0,inference:0,postprocess:0};constructor(){this._last=performance.now()}stage(e){let t=performance.now();this._speed[e]+=t-this._last,this._last=t}speed(){return{...this._speed}}};exports.SpeedTimer=e;
|
|
2
|
+
//# sourceMappingURL=timing.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timing.cjs","names":[],"sources":["../../../src/vision/core/timing.ts"],"sourcesContent":["/**\n * Per-stage timing for a single `predict()` call.\n *\n * Populates the `speed` field every `Results` envelope carries, mirroring\n * Ultralytics' `results[0].speed`. All values are milliseconds measured with\n * `performance.now()`.\n */\n\n/**\n * Stage durations of one inference, in milliseconds.\n *\n * `preprocess`, `inference` and `postprocess` are the three keys Ultralytics\n * reports, measured over the same boundaries. `load` is specific to this SDK:\n * `predict()` accepts a URL, `Blob` or DOM element and decodes it internally,\n * so the fetch/decode cost would otherwise be invisible — and on a cold cache\n * it dominates everything else.\n */\nexport interface Speed {\n /** Fetching and decoding the input into an `RGBImage`. */\n load: number;\n /** Letterbox/resize, normalization and tensor packing. */\n preprocess: number;\n /** The ONNX Runtime forward pass. */\n inference: number;\n /** Decoding raw outputs into results (NMS, mask assembly, top-k). */\n postprocess: number;\n}\n\n/**\n * Accumulate stage durations while a `predict()` call runs.\n *\n * Each `stage()` call closes the previous stage: the elapsed time since the\n * last boundary is attributed to the name given. This keeps the call sites\n * free of paired start/stop bookkeeping and guarantees the four stages tile\n * the whole call without gaps.\n */\nexport class SpeedTimer {\n private _last: number;\n private readonly _speed: Speed = {\n load: 0,\n preprocess: 0,\n inference: 0,\n postprocess: 0,\n };\n\n constructor() {\n this._last = performance.now();\n }\n\n /**\n * Attribute the time elapsed since the previous boundary to `stage`.\n *\n * @param stage Which stage just finished.\n */\n stage(stage: keyof Speed): void {\n const now = performance.now();\n this._speed[stage] += now - this._last;\n this._last = now;\n }\n\n /**\n * The accumulated durations.\n *\n * @returns The `speed` object to hand to the `Results` envelope.\n */\n speed(): Speed {\n return { ...this._speed };\n }\n}\n"],"mappings":"AAoCA,IAAa,EAAb,KAAwB,CACpB,MACA,OAAiC,CAC7B,KAAM,EACN,WAAY,EACZ,UAAW,EACX,YAAa,CACjB,EAEA,aAAc,CACV,KAAK,MAAQ,YAAY,IAAI,CACjC,CAOA,MAAM,EAA0B,CAC5B,IAAM,EAAM,YAAY,IAAI,EAC5B,KAAK,OAAO,IAAU,EAAM,KAAK,MACjC,KAAK,MAAQ,CACjB,CAOA,OAAe,CACX,MAAO,CAAE,GAAG,KAAK,MAAO,CAC5B,CACJ"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/vision/core/timing.ts
|
|
2
|
+
var e = class {
|
|
3
|
+
_last;
|
|
4
|
+
_speed = {
|
|
5
|
+
load: 0,
|
|
6
|
+
preprocess: 0,
|
|
7
|
+
inference: 0,
|
|
8
|
+
postprocess: 0
|
|
9
|
+
};
|
|
10
|
+
constructor() {
|
|
11
|
+
this._last = performance.now();
|
|
12
|
+
}
|
|
13
|
+
stage(e) {
|
|
14
|
+
let t = performance.now();
|
|
15
|
+
this._speed[e] += t - this._last, this._last = t;
|
|
16
|
+
}
|
|
17
|
+
speed() {
|
|
18
|
+
return { ...this._speed };
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { e as SpeedTimer };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=timing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timing.js","names":[],"sources":["../../../src/vision/core/timing.ts"],"sourcesContent":["/**\n * Per-stage timing for a single `predict()` call.\n *\n * Populates the `speed` field every `Results` envelope carries, mirroring\n * Ultralytics' `results[0].speed`. All values are milliseconds measured with\n * `performance.now()`.\n */\n\n/**\n * Stage durations of one inference, in milliseconds.\n *\n * `preprocess`, `inference` and `postprocess` are the three keys Ultralytics\n * reports, measured over the same boundaries. `load` is specific to this SDK:\n * `predict()` accepts a URL, `Blob` or DOM element and decodes it internally,\n * so the fetch/decode cost would otherwise be invisible — and on a cold cache\n * it dominates everything else.\n */\nexport interface Speed {\n /** Fetching and decoding the input into an `RGBImage`. */\n load: number;\n /** Letterbox/resize, normalization and tensor packing. */\n preprocess: number;\n /** The ONNX Runtime forward pass. */\n inference: number;\n /** Decoding raw outputs into results (NMS, mask assembly, top-k). */\n postprocess: number;\n}\n\n/**\n * Accumulate stage durations while a `predict()` call runs.\n *\n * Each `stage()` call closes the previous stage: the elapsed time since the\n * last boundary is attributed to the name given. This keeps the call sites\n * free of paired start/stop bookkeeping and guarantees the four stages tile\n * the whole call without gaps.\n */\nexport class SpeedTimer {\n private _last: number;\n private readonly _speed: Speed = {\n load: 0,\n preprocess: 0,\n inference: 0,\n postprocess: 0,\n };\n\n constructor() {\n this._last = performance.now();\n }\n\n /**\n * Attribute the time elapsed since the previous boundary to `stage`.\n *\n * @param stage Which stage just finished.\n */\n stage(stage: keyof Speed): void {\n const now = performance.now();\n this._speed[stage] += now - this._last;\n this._last = now;\n }\n\n /**\n * The accumulated durations.\n *\n * @returns The `speed` object to hand to the `Results` envelope.\n */\n speed(): Speed {\n return { ...this._speed };\n }\n}\n"],"mappings":";AAoCA,IAAa,IAAb,MAAwB;CACpB;CACA,SAAiC;EAC7B,MAAM;EACN,YAAY;EACZ,WAAW;EACX,aAAa;CACjB;CAEA,cAAc;EACV,KAAK,QAAQ,YAAY,IAAI;CACjC;CAOA,MAAM,GAA0B;EAC5B,IAAM,IAAM,YAAY,IAAI;EAE5B,AADA,KAAK,OAAO,MAAU,IAAM,KAAK,OACjC,KAAK,QAAQ;CACjB;CAOA,QAAe;EACX,OAAO,EAAE,GAAG,KAAK,OAAO;CAC5B;AACJ"}
|
package/dist/vision/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./core/exceptions.cjs"),t=require("./types.cjs"),n=require("./
|
|
1
|
+
const e=require("./core/exceptions.cjs"),t=require("./types.cjs"),n=require("./core/timing.cjs"),r=require("./results.cjs"),i=require("./labels.cjs"),a=require("./core/providers.cjs"),o=require("./core/session.cjs"),s=require("./io/image.cjs"),c=require("./preprocess/image.cjs"),l=require("./postprocess/classification.cjs"),u=require("./postprocess/detection.cjs"),d=require("./postprocess/segmentation.cjs"),f=require("./tasks/base.cjs"),p=require("./tasks/classifier.cjs"),m=require("./tasks/detector.cjs"),h=require("./tasks/segmenter.cjs");var g=`0.3.0`;exports.BoundingBox=t.BoundingBox,exports.Boxes=r.Boxes,exports.COCO_CLASSES=i.COCO_CLASSES,exports.ClassificationResults=r.ClassificationResults,exports.Classifier=p.Classifier,exports.DEFAULT_PROVIDERS=a.DEFAULT_PROVIDERS,exports.DetectionResults=r.DetectionResults,exports.Detector=m.Detector,exports.ImageLoadError=e.ImageLoadError,exports.InferenceError=e.InferenceError,exports.LabelMapError=e.LabelMapError,exports.Mask=t.Mask,exports.Masks=r.Masks,exports.ModelLoadError=e.ModelLoadError,exports.OrtSession=o.OrtSession,exports.OrtVisionError=e.OrtVisionError,exports.Probs=r.Probs,exports.ProviderNotAvailableError=e.ProviderNotAvailableError,exports.RGBImage=t.RGBImage,exports.SegmentationResults=r.SegmentationResults,exports.Segmenter=h.Segmenter,exports.SpeedTimer=n.SpeedTimer,exports.VERSION=g,exports.VisionTask=f.VisionTask,exports.batchedNms=u.batchedNms,exports.decodeYolo=u.decodeYolo,exports.decodeYoloAnchors=u.decodeYoloAnchors,exports.decodeYoloSeg=d.decodeYoloSeg,exports.decodeYoloV8=u.decodeYoloV8,exports.decodeYoloV8Anchors=u.decodeYoloV8Anchors,exports.decodeYoloV8Seg=d.decodeYoloV8Seg,exports.fromCv2=c.fromCv2,exports.letterbox=c.letterbox,exports.loadImage=s.loadImage,exports.nms=u.nms,exports.normalize=c.normalize,exports.resize=c.resize,exports.resolveLabels=i.resolveLabels,exports.resolveProviders=a.resolveProviders,exports.softmax=l.softmax,exports.toCHW=c.toCHW,exports.toCv2=c.toCv2,exports.toFloat32=c.toFloat32,exports.toFloat32Tensor=c.toFloat32Tensor,exports.toTensor=c.toTensor,exports.topK=l.topK;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/vision/index.ts"],"sourcesContent":["/**\n * `tempest-react-sdk/vision` — browser computer-vision inference with ONNX\n * Runtime Web (classification, detection, segmentation).\n *\n * Vendored from `@mauriciobenjamin700/ort-vision-sdk-web@0.
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/vision/index.ts"],"sourcesContent":["/**\n * `tempest-react-sdk/vision` — browser computer-vision inference with ONNX\n * Runtime Web (classification, detection, segmentation).\n *\n * Vendored from `@mauriciobenjamin700/ort-vision-sdk-web@0.3.0` (MIT, same\n * author) so it ships inside this SDK without an extra package install.\n * `onnxruntime-web` stays an optional peer dependency — install it (and ship\n * the matching `.wasm` files) only when you use this subpath.\n *\n * Do not hand-edit — regenerate with `npm run vendor:vision`.\n */\n\nexport {\n BoundingBox,\n Mask,\n RGBImage,\n type ClassProbability,\n type ClassificationResult,\n type DetectionResult,\n type SegmentationResult,\n} from \"./types\";\n\nexport {\n Boxes,\n ClassificationResults,\n DetectionResults,\n Masks,\n Probs,\n SegmentationResults,\n} from \"./results\";\n\nexport { COCO_CLASSES, type LabelSpec, type ResolveLabelsOptions, resolveLabels } from \"./labels\";\n\nexport {\n ImageLoadError,\n InferenceError,\n LabelMapError,\n ModelLoadError,\n OrtVisionError,\n ProviderNotAvailableError,\n} from \"./core/exceptions\";\n\nexport { type ModelSource, type OrtSessionOptions, OrtSession } from \"./core/session\";\nexport { DEFAULT_PROVIDERS, resolveProviders } from \"./core/providers\";\nexport { type Speed, SpeedTimer } from \"./core/timing\";\n\nexport { type ImageInput, loadImage } from \"./io/image\";\n\nexport {\n type LetterboxResult,\n fromCv2,\n letterbox,\n normalize,\n resize,\n toCHW,\n toCv2,\n toFloat32,\n toFloat32Tensor,\n toTensor,\n} from \"./preprocess/image\";\n\nexport { type TopKResult, softmax, topK } from \"./postprocess/classification\";\n\nexport {\n type DecodeYoloAnchorsOptions,\n type DecodeYoloOptions,\n type DecodeYoloV8AnchorsOptions,\n type DecodeYoloV8Options,\n type DecodedAnchors,\n type DecodedDetection,\n batchedNms,\n decodeYolo,\n decodeYoloAnchors,\n decodeYoloV8,\n decodeYoloV8Anchors,\n nms,\n} from \"./postprocess/detection\";\n\nexport {\n type DecodeYoloSegOptions,\n type DecodeYoloV8SegOptions,\n type DecodedSegmentation,\n decodeYoloSeg,\n decodeYoloV8Seg,\n} from \"./postprocess/segmentation\";\n\nexport { VisionTask } from \"./tasks/base\";\nexport {\n type ClassifierOptions,\n type ClassifierPredictOptions,\n Classifier,\n} from \"./tasks/classifier\";\nexport {\n type DetectorHead,\n type DetectorOptions,\n type DetectorPredictOptions,\n Detector,\n} from \"./tasks/detector\";\nexport {\n type SegmenterHead,\n type SegmenterOptions,\n type SegmenterPredictOptions,\n Segmenter,\n} from \"./tasks/segmenter\";\n\nexport const VERSION: string = \"0.3.0\";\n"],"mappings":"kiBAyGA,IAAa,EAAkB"}
|
package/dist/vision/index.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import { ImageLoadError as e, InferenceError as t, LabelMapError as n, ModelLoadError as r, OrtVisionError as i, ProviderNotAvailableError as a } from "./core/exceptions.js";
|
|
2
2
|
import { BoundingBox as o, Mask as s, RGBImage as c } from "./types.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
3
|
+
import { SpeedTimer as l } from "./core/timing.js";
|
|
4
|
+
import { Boxes as u, ClassificationResults as d, DetectionResults as f, Masks as p, Probs as m, SegmentationResults as h } from "./results.js";
|
|
5
|
+
import { COCO_CLASSES as g, resolveLabels as _ } from "./labels.js";
|
|
6
|
+
import { DEFAULT_PROVIDERS as v, resolveProviders as y } from "./core/providers.js";
|
|
7
|
+
import { OrtSession as b } from "./core/session.js";
|
|
8
|
+
import { loadImage as x } from "./io/image.js";
|
|
9
|
+
import { fromCv2 as S, letterbox as C, normalize as w, resize as T, toCHW as E, toCv2 as D, toFloat32 as O, toFloat32Tensor as k, toTensor as A } from "./preprocess/image.js";
|
|
10
|
+
import { softmax as j, topK as M } from "./postprocess/classification.js";
|
|
11
|
+
import { batchedNms as N, decodeYolo as P, decodeYoloAnchors as F, decodeYoloV8 as I, decodeYoloV8Anchors as L, nms as R } from "./postprocess/detection.js";
|
|
12
|
+
import { decodeYoloSeg as z, decodeYoloV8Seg as B } from "./postprocess/segmentation.js";
|
|
13
|
+
import { VisionTask as V } from "./tasks/base.js";
|
|
14
|
+
import { Classifier as H } from "./tasks/classifier.js";
|
|
15
|
+
import { Detector as U } from "./tasks/detector.js";
|
|
16
|
+
import { Segmenter as W } from "./tasks/segmenter.js";
|
|
16
17
|
//#region src/vision/index.ts
|
|
17
|
-
var
|
|
18
|
+
var G = "0.3.0";
|
|
18
19
|
//#endregion
|
|
19
|
-
export { o as BoundingBox,
|
|
20
|
+
export { o as BoundingBox, u as Boxes, g as COCO_CLASSES, d as ClassificationResults, H as Classifier, v as DEFAULT_PROVIDERS, f as DetectionResults, U as Detector, e as ImageLoadError, t as InferenceError, n as LabelMapError, s as Mask, p as Masks, r as ModelLoadError, b as OrtSession, i as OrtVisionError, m as Probs, a as ProviderNotAvailableError, c as RGBImage, h as SegmentationResults, W as Segmenter, l as SpeedTimer, G as VERSION, V as VisionTask, N as batchedNms, P as decodeYolo, F as decodeYoloAnchors, z as decodeYoloSeg, I as decodeYoloV8, L as decodeYoloV8Anchors, B as decodeYoloV8Seg, S as fromCv2, C as letterbox, x as loadImage, R as nms, w as normalize, T as resize, _ as resolveLabels, y as resolveProviders, j as softmax, E as toCHW, D as toCv2, O as toFloat32, k as toFloat32Tensor, A as toTensor, M as topK };
|
|
20
21
|
|
|
21
22
|
//# sourceMappingURL=index.js.map
|
package/dist/vision/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/vision/index.ts"],"sourcesContent":["/**\n * `tempest-react-sdk/vision` — browser computer-vision inference with ONNX\n * Runtime Web (classification, detection, segmentation).\n *\n * Vendored from `@mauriciobenjamin700/ort-vision-sdk-web@0.
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/vision/index.ts"],"sourcesContent":["/**\n * `tempest-react-sdk/vision` — browser computer-vision inference with ONNX\n * Runtime Web (classification, detection, segmentation).\n *\n * Vendored from `@mauriciobenjamin700/ort-vision-sdk-web@0.3.0` (MIT, same\n * author) so it ships inside this SDK without an extra package install.\n * `onnxruntime-web` stays an optional peer dependency — install it (and ship\n * the matching `.wasm` files) only when you use this subpath.\n *\n * Do not hand-edit — regenerate with `npm run vendor:vision`.\n */\n\nexport {\n BoundingBox,\n Mask,\n RGBImage,\n type ClassProbability,\n type ClassificationResult,\n type DetectionResult,\n type SegmentationResult,\n} from \"./types\";\n\nexport {\n Boxes,\n ClassificationResults,\n DetectionResults,\n Masks,\n Probs,\n SegmentationResults,\n} from \"./results\";\n\nexport { COCO_CLASSES, type LabelSpec, type ResolveLabelsOptions, resolveLabels } from \"./labels\";\n\nexport {\n ImageLoadError,\n InferenceError,\n LabelMapError,\n ModelLoadError,\n OrtVisionError,\n ProviderNotAvailableError,\n} from \"./core/exceptions\";\n\nexport { type ModelSource, type OrtSessionOptions, OrtSession } from \"./core/session\";\nexport { DEFAULT_PROVIDERS, resolveProviders } from \"./core/providers\";\nexport { type Speed, SpeedTimer } from \"./core/timing\";\n\nexport { type ImageInput, loadImage } from \"./io/image\";\n\nexport {\n type LetterboxResult,\n fromCv2,\n letterbox,\n normalize,\n resize,\n toCHW,\n toCv2,\n toFloat32,\n toFloat32Tensor,\n toTensor,\n} from \"./preprocess/image\";\n\nexport { type TopKResult, softmax, topK } from \"./postprocess/classification\";\n\nexport {\n type DecodeYoloAnchorsOptions,\n type DecodeYoloOptions,\n type DecodeYoloV8AnchorsOptions,\n type DecodeYoloV8Options,\n type DecodedAnchors,\n type DecodedDetection,\n batchedNms,\n decodeYolo,\n decodeYoloAnchors,\n decodeYoloV8,\n decodeYoloV8Anchors,\n nms,\n} from \"./postprocess/detection\";\n\nexport {\n type DecodeYoloSegOptions,\n type DecodeYoloV8SegOptions,\n type DecodedSegmentation,\n decodeYoloSeg,\n decodeYoloV8Seg,\n} from \"./postprocess/segmentation\";\n\nexport { VisionTask } from \"./tasks/base\";\nexport {\n type ClassifierOptions,\n type ClassifierPredictOptions,\n Classifier,\n} from \"./tasks/classifier\";\nexport {\n type DetectorHead,\n type DetectorOptions,\n type DetectorPredictOptions,\n Detector,\n} from \"./tasks/detector\";\nexport {\n type SegmenterHead,\n type SegmenterOptions,\n type SegmenterPredictOptions,\n Segmenter,\n} from \"./tasks/segmenter\";\n\nexport const VERSION: string = \"0.3.0\";\n"],"mappings":";;;;;;;;;;;;;;;;;AAyGA,IAAa,IAAkB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../types.cjs");function t(e,t,n){let r=t.length;if(r===0)return new Int32Array;let i=new Float32Array(r);for(let t=0;t<r;t++){let n=e[t*4],r=e[t*4+1],a=e[t*4+2],o=e[t*4+3];i[t]=Math.max(0,a-n)*Math.max(0,o-r)}let a=Array(r);for(let e=0;e<r;e++)a[e]=e;a.sort((e,n)=>t[n]-t[e]);let o=new Uint8Array(r),s=[];for(let t=0;t<a.length;t++){let r=a[t];if(o[r])continue;s.push(r);let c=e[r*4],l=e[r*4+1],u=e[r*4+2],d=e[r*4+3],f=i[r];for(let r=t+1;r<a.length;r++){let t=a[r];if(o[t])continue;let s=e[t*4],p=e[t*4+1],m=e[t*4+2],h=e[t*4+3],g=Math.max(c,s),_=Math.max(l,p),v=Math.min(u,m),y=Math.min(d,h),b=Math.max(0,v-g)*Math.max(0,y-_),x=f+i[t]-b;(x>0?b/x:0)>n&&(o[t]=1)}}return Int32Array.from(s)}function n(e,n,r,i){if(n.length===0)return new Int32Array;let a=new Map;for(let e=0;e<r.length;e++){let t=r[e],n=a.get(t);n===void 0?a.set(t,[e]):n.push(e)}let o=[];for(let r of a.values()){let a=r.length,s=new Float32Array(a*4),c=new Float32Array(a);for(let t=0;t<a;t++){let i=r[t];s[t*4]=e[i*4],s[t*4+1]=e[i*4+1],s[t*4+2]=e[i*4+2],s[t*4+3]=e[i*4+3],c[t]=n[i]}let l=t(s,c,i);for(let e=0;e<l.length;e++)o.push(r[l[e]])}return o.sort((e,t)=>n[t]-n[e]),Int32Array.from(o)}function r(e,t,r){let a=t;if(a.length===3){if(a[0]!==1)throw Error(`decodeYoloAnchors: expected batch size 1, got ${a[0]}.`);a=[a[1],a[2]]}if(a.length!==2)throw Error(`decodeYoloAnchors: expected 2-D output after batch removal, got dims=${JSON.stringify(t)}.`);let o=a[0],s=a[1],{numClasses:c,originalWidth:l,originalHeight:u,padLeft:d,padTop:f,scale:p,confThreshold:m,iouThreshold:h,maxDetections:g}=r;if(c<1||c+4>o)throw Error(`decodeYoloAnchors: invalid numClasses=${c} for channels=${o}.`);if(e.length!==o*s)throw Error(`decodeYoloAnchors: data length ${e.length} does not match channels*numAnchors=${o*s}.`);let _=[];for(let t=0;t<s;t++){let n=0,r=-1/0;for(let i=0;i<c;i++){let a=e[(4+i)*s+t];a!==void 0&&a>r&&(r=a,n=i)}if(r<m)continue;let i=e[t],a=e[s+t],o=e[2*s+t],h=e[3*s+t],g=i-o/2,v=a-h/2,y=i+o/2,b=a+h/2;g=(g-d)/p,v=(v-f)/p,y=(y-d)/p,b=(b-f)/p,g=Math.max(0,Math.min(l,g)),v=Math.max(0,Math.min(u,v)),y=Math.max(0,Math.min(l,y)),b=Math.max(0,Math.min(u,b)),_.push({anchorIdx:t,x1:g,y1:v,x2:y,y2:b,classId:n,confidence:r})}if(_.length===0)return i();let v=new Float32Array(_.length*4),y=new Float32Array(_.length),b=new Int32Array(_.length);for(let e=0;e<_.length;e++){let t=_[e];v[e*4]=t.x1,v[e*4+1]=t.y1,v[e*4+2]=t.x2,v[e*4+3]=t.y2,y[e]=t.confidence,b[e]=t.classId}let x=n(v,y,b,h);if(x.length===0)return i();let S=Array.from(x).slice(0,g),C=S.length,w=new Int32Array(C),T=new Float32Array(C*4),E=new Int32Array(C),D=new Float32Array(C);for(let e=0;e<C;e++){let t=_[S[e]];w[e]=t.anchorIdx,T[e*4]=t.x1,T[e*4+1]=t.y1,T[e*4+2]=t.x2,T[e*4+3]=t.y2,E[e]=t.classId,D[e]=t.confidence}return{anchorIndices:w,boxesXyxy:T,classIds:E,confidences:D}}function i(){return{anchorIndices:new Int32Array,boxesXyxy:new Float32Array,classIds:new Int32Array,confidences:new Float32Array}}function a(t,n,i){let a=n.length===3?n[1]:n[0];if(a===void 0||a<5)throw Error(`decodeYolo: invalid output channel count ${a} (expected >= 5).`);let o=r(t,n,{numClasses:a-4,...i}),s=[];for(let t=0;t<o.classIds.length;t++)s.push({bbox:new e.BoundingBox(o.boxesXyxy[t*4],o.boxesXyxy[t*4+1],o.boxesXyxy[t*4+2],o.boxesXyxy[t*4+3]),classId:o.classIds[t],confidence:o.confidences[t]});return s}var o=!1,s=!1;function c(e,t,n){return o||(o=!0,console.warn(`[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. The alias will be removed in 0.
|
|
1
|
+
const e=require("../types.cjs");function t(e,t,n){let r=t.length;if(r===0)return new Int32Array;let i=new Float32Array(r);for(let t=0;t<r;t++){let n=e[t*4],r=e[t*4+1],a=e[t*4+2],o=e[t*4+3];i[t]=Math.max(0,a-n)*Math.max(0,o-r)}let a=Array(r);for(let e=0;e<r;e++)a[e]=e;a.sort((e,n)=>t[n]-t[e]);let o=new Uint8Array(r),s=[];for(let t=0;t<a.length;t++){let r=a[t];if(o[r])continue;s.push(r);let c=e[r*4],l=e[r*4+1],u=e[r*4+2],d=e[r*4+3],f=i[r];for(let r=t+1;r<a.length;r++){let t=a[r];if(o[t])continue;let s=e[t*4],p=e[t*4+1],m=e[t*4+2],h=e[t*4+3],g=Math.max(c,s),_=Math.max(l,p),v=Math.min(u,m),y=Math.min(d,h),b=Math.max(0,v-g)*Math.max(0,y-_),x=f+i[t]-b;(x>0?b/x:0)>n&&(o[t]=1)}}return Int32Array.from(s)}function n(e,n,r,i){if(n.length===0)return new Int32Array;let a=new Map;for(let e=0;e<r.length;e++){let t=r[e],n=a.get(t);n===void 0?a.set(t,[e]):n.push(e)}let o=[];for(let r of a.values()){let a=r.length,s=new Float32Array(a*4),c=new Float32Array(a);for(let t=0;t<a;t++){let i=r[t];s[t*4]=e[i*4],s[t*4+1]=e[i*4+1],s[t*4+2]=e[i*4+2],s[t*4+3]=e[i*4+3],c[t]=n[i]}let l=t(s,c,i);for(let e=0;e<l.length;e++)o.push(r[l[e]])}return o.sort((e,t)=>n[t]-n[e]),Int32Array.from(o)}function r(e,t,r){let a=t;if(a.length===3){if(a[0]!==1)throw Error(`decodeYoloAnchors: expected batch size 1, got ${a[0]}.`);a=[a[1],a[2]]}if(a.length!==2)throw Error(`decodeYoloAnchors: expected 2-D output after batch removal, got dims=${JSON.stringify(t)}.`);let o=a[0],s=a[1],{numClasses:c,originalWidth:l,originalHeight:u,padLeft:d,padTop:f,scale:p,confThreshold:m,iouThreshold:h,maxDetections:g}=r;if(c<1||c+4>o)throw Error(`decodeYoloAnchors: invalid numClasses=${c} for channels=${o}.`);if(e.length!==o*s)throw Error(`decodeYoloAnchors: data length ${e.length} does not match channels*numAnchors=${o*s}.`);let _=[];for(let t=0;t<s;t++){let n=0,r=-1/0;for(let i=0;i<c;i++){let a=e[(4+i)*s+t];a!==void 0&&a>r&&(r=a,n=i)}if(r<m)continue;let i=e[t],a=e[s+t],o=e[2*s+t],h=e[3*s+t],g=i-o/2,v=a-h/2,y=i+o/2,b=a+h/2;g=(g-d)/p,v=(v-f)/p,y=(y-d)/p,b=(b-f)/p,g=Math.max(0,Math.min(l,g)),v=Math.max(0,Math.min(u,v)),y=Math.max(0,Math.min(l,y)),b=Math.max(0,Math.min(u,b)),_.push({anchorIdx:t,x1:g,y1:v,x2:y,y2:b,classId:n,confidence:r})}if(_.length===0)return i();let v=new Float32Array(_.length*4),y=new Float32Array(_.length),b=new Int32Array(_.length);for(let e=0;e<_.length;e++){let t=_[e];v[e*4]=t.x1,v[e*4+1]=t.y1,v[e*4+2]=t.x2,v[e*4+3]=t.y2,y[e]=t.confidence,b[e]=t.classId}let x=n(v,y,b,h);if(x.length===0)return i();let S=Array.from(x).slice(0,g),C=S.length,w=new Int32Array(C),T=new Float32Array(C*4),E=new Int32Array(C),D=new Float32Array(C);for(let e=0;e<C;e++){let t=_[S[e]];w[e]=t.anchorIdx,T[e*4]=t.x1,T[e*4+1]=t.y1,T[e*4+2]=t.x2,T[e*4+3]=t.y2,E[e]=t.classId,D[e]=t.confidence}return{anchorIndices:w,boxesXyxy:T,classIds:E,confidences:D}}function i(){return{anchorIndices:new Int32Array,boxesXyxy:new Float32Array,classIds:new Int32Array,confidences:new Float32Array}}function a(t,n,i){let a=n.length===3?n[1]:n[0];if(a===void 0||a<5)throw Error(`decodeYolo: invalid output channel count ${a} (expected >= 5).`);let o=r(t,n,{numClasses:a-4,...i}),s=[];for(let t=0;t<o.classIds.length;t++)s.push({bbox:new e.BoundingBox(o.boxesXyxy[t*4],o.boxesXyxy[t*4+1],o.boxesXyxy[t*4+2],o.boxesXyxy[t*4+3]),classId:o.classIds[t],confidence:o.confidences[t]});return s}var o=!1,s=!1;function c(e,t,n){return o||(o=!0,console.warn(`[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. The alias will be removed in 0.4.0.`)),a(e,t,n)}function l(e,t,n){return s||(s=!0,console.warn(`[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. The alias will be removed in 0.4.0.`)),r(e,t,n)}exports.batchedNms=n,exports.decodeYolo=a,exports.decodeYoloAnchors=r,exports.decodeYoloV8=c,exports.decodeYoloV8Anchors=l,exports.nms=t;
|
|
2
2
|
//# sourceMappingURL=detection.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detection.cjs","names":[],"sources":["../../../src/vision/postprocess/detection.ts"],"sourcesContent":["/**\n * Detection head postprocessing: anchor-free YOLO decoding + non-maximum suppression.\n *\n * The shared {@link decodeYoloAnchors} helper does the per-anchor work that\n * is identical for plain detection and segmentation (transpose, xywh→xyxy,\n * letterbox unmap, per-class NMS, sort & cap). {@link decodeYolo} is a thin\n * wrapper around it; the segmentation module ({@link ./segmentation.js})\n * calls the helper directly so it can also recover the per-anchor mask\n * coefficients.\n *\n * Works for any YOLO export with the post-v8 anchor-free head:\n * **YOLOv8 / v9 / v10 / v11 / v12** detect heads, all of which share the\n * `[1, 4 + nc, N]` output layout.\n */\n\nimport { BoundingBox } from \"../types\";\n\n/**\n * Greedy non-maximum suppression on axis-aligned bounding boxes.\n *\n * Mirrors `torchvision.ops.nms` (keeps boxes with the highest score, drops\n * any subsequent box whose IoU exceeds the threshold).\n *\n * @param boxes Flat array of length `4 * N` in xyxy order: `[x1,y1,x2,y2, ...]`.\n * @param scores Detection score per box, length `N`.\n * @param iouThreshold Boxes with IoU above this threshold relative to a kept box are suppressed.\n * @returns Indices of kept boxes, in descending score order.\n */\nexport function nms(boxes: Float32Array, scores: Float32Array, iouThreshold: number): Int32Array {\n const n = scores.length;\n if (n === 0) return new Int32Array(0);\n\n const areas = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const x1 = boxes[i * 4] as number;\n const y1 = boxes[i * 4 + 1] as number;\n const x2 = boxes[i * 4 + 2] as number;\n const y2 = boxes[i * 4 + 3] as number;\n areas[i] = Math.max(0, x2 - x1) * Math.max(0, y2 - y1);\n }\n\n const order = new Array<number>(n);\n for (let i = 0; i < n; i++) order[i] = i;\n order.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n\n const suppressed = new Uint8Array(n);\n const keep: number[] = [];\n\n for (let oi = 0; oi < order.length; oi++) {\n const i = order[oi] as number;\n if (suppressed[i]) continue;\n keep.push(i);\n\n const ax1 = boxes[i * 4] as number;\n const ay1 = boxes[i * 4 + 1] as number;\n const ax2 = boxes[i * 4 + 2] as number;\n const ay2 = boxes[i * 4 + 3] as number;\n const ai = areas[i] as number;\n\n for (let oj = oi + 1; oj < order.length; oj++) {\n const j = order[oj] as number;\n if (suppressed[j]) continue;\n\n const bx1 = boxes[j * 4] as number;\n const by1 = boxes[j * 4 + 1] as number;\n const bx2 = boxes[j * 4 + 2] as number;\n const by2 = boxes[j * 4 + 3] as number;\n\n const ix1 = Math.max(ax1, bx1);\n const iy1 = Math.max(ay1, by1);\n const ix2 = Math.min(ax2, bx2);\n const iy2 = Math.min(ay2, by2);\n const iw = Math.max(0, ix2 - ix1);\n const ih = Math.max(0, iy2 - iy1);\n const inter = iw * ih;\n const union = ai + (areas[j] as number) - inter;\n const iou = union > 0 ? inter / union : 0;\n if (iou > iouThreshold) suppressed[j] = 1;\n }\n }\n\n return Int32Array.from(keep);\n}\n\n/**\n * Per-class NMS — boxes are suppressed only by other boxes of the same class.\n *\n * Mirrors `torchvision.ops.batched_nms`.\n *\n * @param boxes Flat array of length `4 * N` in xyxy order.\n * @param scores Detection score per box, length `N`.\n * @param idxs Class index per box, length `N`. Boxes with different `idxs`\n * never suppress each other.\n * @param iouThreshold IoU threshold for suppression within a class.\n */\nexport function batchedNms(\n boxes: Float32Array,\n scores: Float32Array,\n idxs: Int32Array,\n iouThreshold: number,\n): Int32Array {\n if (scores.length === 0) return new Int32Array(0);\n\n const byClass = new Map<number, number[]>();\n for (let i = 0; i < idxs.length; i++) {\n const c = idxs[i] as number;\n const list = byClass.get(c);\n if (list === undefined) byClass.set(c, [i]);\n else list.push(i);\n }\n\n const keep: number[] = [];\n for (const indices of byClass.values()) {\n const m = indices.length;\n const subBoxes = new Float32Array(m * 4);\n const subScores = new Float32Array(m);\n for (let k = 0; k < m; k++) {\n const i = indices[k] as number;\n subBoxes[k * 4] = boxes[i * 4] as number;\n subBoxes[k * 4 + 1] = boxes[i * 4 + 1] as number;\n subBoxes[k * 4 + 2] = boxes[i * 4 + 2] as number;\n subBoxes[k * 4 + 3] = boxes[i * 4 + 3] as number;\n subScores[k] = scores[i] as number;\n }\n const subKeep = nms(subBoxes, subScores, iouThreshold);\n for (let k = 0; k < subKeep.length; k++) {\n keep.push(indices[subKeep[k] as number] as number);\n }\n }\n\n keep.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n return Int32Array.from(keep);\n}\n\nexport interface DecodeYoloAnchorsOptions {\n /** Number of class-score channels following the 4 box channels. */\n readonly numClasses: number;\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedAnchors {\n /** Indices into the original `numAnchors` axis, in descending confidence order. */\n readonly anchorIndices: Int32Array;\n /** `[k, 4]` boxes in original-image pixel coords, flat row-major xyxy. */\n readonly boxesXyxy: Float32Array;\n /** Predicted class id per survivor. */\n readonly classIds: Int32Array;\n /** Confidence per survivor. */\n readonly confidences: Float32Array;\n}\n\n/**\n * Shared YOLO per-anchor decode used by both detection and segmentation\n * (v8 / v9 / v10 / v11 / v12).\n *\n * Only the first `4 + numClasses` channels are read; later channels (e.g.\n * mask coefficients) are ignored — callers can fetch them via the returned\n * {@link DecodedAnchors.anchorIndices}.\n *\n * @param data Flat per-anchor output, length `channels * numAnchors`.\n * @param dims Dims as reported by ORT, e.g. `[1, 84, 8400]` (det) or\n * `[1, 116, 8400]` (seg). The leading batch dim must be 1.\n */\nexport function decodeYoloAnchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n let normalized = dims;\n if (normalized.length === 3) {\n if (normalized[0] !== 1) {\n throw new Error(`decodeYoloAnchors: expected batch size 1, got ${normalized[0]}.`);\n }\n normalized = [normalized[1] as number, normalized[2] as number];\n }\n if (normalized.length !== 2) {\n throw new Error(\n `decodeYoloAnchors: expected 2-D output after batch removal, got dims=${JSON.stringify(dims)}.`,\n );\n }\n const channels = normalized[0] as number;\n const numAnchors = normalized[1] as number;\n\n const {\n numClasses,\n originalWidth,\n originalHeight,\n padLeft,\n padTop,\n scale,\n confThreshold,\n iouThreshold,\n maxDetections,\n } = options;\n\n if (numClasses < 1 || numClasses + 4 > channels) {\n throw new Error(\n `decodeYoloAnchors: invalid numClasses=${numClasses} for channels=${channels}.`,\n );\n }\n if (data.length !== channels * numAnchors) {\n throw new Error(\n `decodeYoloAnchors: data length ${data.length} does not match channels*numAnchors=${channels * numAnchors}.`,\n );\n }\n\n type Candidate = {\n anchorIdx: number;\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n classId: number;\n confidence: number;\n };\n const candidates: Candidate[] = [];\n\n for (let a = 0; a < numAnchors; a++) {\n let bestCls = 0;\n let bestScore = -Infinity;\n for (let c = 0; c < numClasses; c++) {\n const s = data[(4 + c) * numAnchors + a];\n if (s !== undefined && s > bestScore) {\n bestScore = s;\n bestCls = c;\n }\n }\n if (bestScore < confThreshold) continue;\n\n const cx = data[a] as number;\n const cy = data[numAnchors + a] as number;\n const w = data[2 * numAnchors + a] as number;\n const h = data[3 * numAnchors + a] as number;\n\n let x1 = cx - w / 2;\n let y1 = cy - h / 2;\n let x2 = cx + w / 2;\n let y2 = cy + h / 2;\n\n x1 = (x1 - padLeft) / scale;\n y1 = (y1 - padTop) / scale;\n x2 = (x2 - padLeft) / scale;\n y2 = (y2 - padTop) / scale;\n\n x1 = Math.max(0, Math.min(originalWidth, x1));\n y1 = Math.max(0, Math.min(originalHeight, y1));\n x2 = Math.max(0, Math.min(originalWidth, x2));\n y2 = Math.max(0, Math.min(originalHeight, y2));\n\n candidates.push({ anchorIdx: a, x1, y1, x2, y2, classId: bestCls, confidence: bestScore });\n }\n\n if (candidates.length === 0) return emptyDecoded();\n\n // Build flat arrays then delegate to batchedNms — same algorithm as before\n // but funnelled through the public per-class NMS helper.\n const flatBoxes = new Float32Array(candidates.length * 4);\n const scoresArr = new Float32Array(candidates.length);\n const idxsArr = new Int32Array(candidates.length);\n for (let i = 0; i < candidates.length; i++) {\n const c = candidates[i] as Candidate;\n flatBoxes[i * 4] = c.x1;\n flatBoxes[i * 4 + 1] = c.y1;\n flatBoxes[i * 4 + 2] = c.x2;\n flatBoxes[i * 4 + 3] = c.y2;\n scoresArr[i] = c.confidence;\n idxsArr[i] = c.classId;\n }\n const kept = batchedNms(flatBoxes, scoresArr, idxsArr, iouThreshold);\n if (kept.length === 0) return emptyDecoded();\n\n const limited = Array.from(kept).slice(0, maxDetections);\n const k = limited.length;\n const anchorIndices = new Int32Array(k);\n const boxesXyxy = new Float32Array(k * 4);\n const classIds = new Int32Array(k);\n const confidences = new Float32Array(k);\n for (let i = 0; i < k; i++) {\n const c = candidates[limited[i] as number] as Candidate;\n anchorIndices[i] = c.anchorIdx;\n boxesXyxy[i * 4] = c.x1;\n boxesXyxy[i * 4 + 1] = c.y1;\n boxesXyxy[i * 4 + 2] = c.x2;\n boxesXyxy[i * 4 + 3] = c.y2;\n classIds[i] = c.classId;\n confidences[i] = c.confidence;\n }\n return { anchorIndices, boxesXyxy, classIds, confidences };\n}\n\nfunction emptyDecoded(): DecodedAnchors {\n return {\n anchorIndices: new Int32Array(0),\n boxesXyxy: new Float32Array(0),\n classIds: new Int32Array(0),\n confidences: new Float32Array(0),\n };\n}\n\nexport interface DecodeYoloOptions {\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedDetection {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n}\n\n/**\n * Decode an anchor-free YOLO detection output into a list of detections.\n *\n * Works for **YOLOv8 / v9 / v10 / v11 / v12** detect heads.\n *\n * Expected raw shape: `[1, 4 + numClasses, N]`. `numClasses` is inferred\n * from the channel count.\n */\nexport function decodeYolo(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n const channels = outputDims.length === 3 ? outputDims[1] : outputDims[0];\n if (channels === undefined || channels < 5) {\n throw new Error(`decodeYolo: invalid output channel count ${channels} (expected >= 5).`);\n }\n const numClasses = channels - 4;\n\n const decoded = decodeYoloAnchors(output, outputDims, {\n numClasses,\n ...options,\n });\n\n const results: DecodedDetection[] = [];\n for (let i = 0; i < decoded.classIds.length; i++) {\n results.push({\n bbox: new BoundingBox(\n decoded.boxesXyxy[i * 4] as number,\n decoded.boxesXyxy[i * 4 + 1] as number,\n decoded.boxesXyxy[i * 4 + 2] as number,\n decoded.boxesXyxy[i * 4 + 3] as number,\n ),\n classId: decoded.classIds[i] as number,\n confidence: decoded.confidences[i] as number,\n });\n }\n return results;\n}\n\nlet _warnedDecodeYoloV8 = false;\nlet _warnedDecodeYoloV8Anchors = false;\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYolo}. Same behavior; the\n * decoder covers v8/v9/v10/v11/v12 detect heads. Will be removed in 0.3.0.\n */\nexport function decodeYoloV8(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n if (!_warnedDecodeYoloV8) {\n _warnedDecodeYoloV8 = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. \" +\n \"The alias will be removed in 0.3.0.\",\n );\n }\n return decodeYolo(output, outputDims, options);\n}\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYoloAnchors}. Will be removed in 0.3.0.\n */\nexport function decodeYoloV8Anchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n if (!_warnedDecodeYoloV8Anchors) {\n _warnedDecodeYoloV8Anchors = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. \" +\n \"The alias will be removed in 0.3.0.\",\n );\n }\n return decodeYoloAnchors(data, dims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloAnchorsOptions}. */\nexport type DecodeYoloV8AnchorsOptions = DecodeYoloAnchorsOptions;\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloOptions}. */\nexport type DecodeYoloV8Options = DecodeYoloOptions;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"detection.cjs","names":[],"sources":["../../../src/vision/postprocess/detection.ts"],"sourcesContent":["/**\n * Detection head postprocessing: anchor-free YOLO decoding + non-maximum suppression.\n *\n * The shared {@link decodeYoloAnchors} helper does the per-anchor work that\n * is identical for plain detection and segmentation (transpose, xywh→xyxy,\n * letterbox unmap, per-class NMS, sort & cap). {@link decodeYolo} is a thin\n * wrapper around it; the segmentation module ({@link ./segmentation.js})\n * calls the helper directly so it can also recover the per-anchor mask\n * coefficients.\n *\n * Works for any YOLO export with the post-v8 anchor-free head:\n * **YOLOv8 / v9 / v10 / v11 / v12** detect heads, all of which share the\n * `[1, 4 + nc, N]` output layout.\n */\n\nimport { BoundingBox } from \"../types\";\n\n/**\n * Greedy non-maximum suppression on axis-aligned bounding boxes.\n *\n * Mirrors `torchvision.ops.nms` (keeps boxes with the highest score, drops\n * any subsequent box whose IoU exceeds the threshold).\n *\n * @param boxes Flat array of length `4 * N` in xyxy order: `[x1,y1,x2,y2, ...]`.\n * @param scores Detection score per box, length `N`.\n * @param iouThreshold Boxes with IoU above this threshold relative to a kept box are suppressed.\n * @returns Indices of kept boxes, in descending score order.\n */\nexport function nms(boxes: Float32Array, scores: Float32Array, iouThreshold: number): Int32Array {\n const n = scores.length;\n if (n === 0) return new Int32Array(0);\n\n const areas = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const x1 = boxes[i * 4] as number;\n const y1 = boxes[i * 4 + 1] as number;\n const x2 = boxes[i * 4 + 2] as number;\n const y2 = boxes[i * 4 + 3] as number;\n areas[i] = Math.max(0, x2 - x1) * Math.max(0, y2 - y1);\n }\n\n const order = new Array<number>(n);\n for (let i = 0; i < n; i++) order[i] = i;\n order.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n\n const suppressed = new Uint8Array(n);\n const keep: number[] = [];\n\n for (let oi = 0; oi < order.length; oi++) {\n const i = order[oi] as number;\n if (suppressed[i]) continue;\n keep.push(i);\n\n const ax1 = boxes[i * 4] as number;\n const ay1 = boxes[i * 4 + 1] as number;\n const ax2 = boxes[i * 4 + 2] as number;\n const ay2 = boxes[i * 4 + 3] as number;\n const ai = areas[i] as number;\n\n for (let oj = oi + 1; oj < order.length; oj++) {\n const j = order[oj] as number;\n if (suppressed[j]) continue;\n\n const bx1 = boxes[j * 4] as number;\n const by1 = boxes[j * 4 + 1] as number;\n const bx2 = boxes[j * 4 + 2] as number;\n const by2 = boxes[j * 4 + 3] as number;\n\n const ix1 = Math.max(ax1, bx1);\n const iy1 = Math.max(ay1, by1);\n const ix2 = Math.min(ax2, bx2);\n const iy2 = Math.min(ay2, by2);\n const iw = Math.max(0, ix2 - ix1);\n const ih = Math.max(0, iy2 - iy1);\n const inter = iw * ih;\n const union = ai + (areas[j] as number) - inter;\n const iou = union > 0 ? inter / union : 0;\n if (iou > iouThreshold) suppressed[j] = 1;\n }\n }\n\n return Int32Array.from(keep);\n}\n\n/**\n * Per-class NMS — boxes are suppressed only by other boxes of the same class.\n *\n * Mirrors `torchvision.ops.batched_nms`.\n *\n * @param boxes Flat array of length `4 * N` in xyxy order.\n * @param scores Detection score per box, length `N`.\n * @param idxs Class index per box, length `N`. Boxes with different `idxs`\n * never suppress each other.\n * @param iouThreshold IoU threshold for suppression within a class.\n */\nexport function batchedNms(\n boxes: Float32Array,\n scores: Float32Array,\n idxs: Int32Array,\n iouThreshold: number,\n): Int32Array {\n if (scores.length === 0) return new Int32Array(0);\n\n const byClass = new Map<number, number[]>();\n for (let i = 0; i < idxs.length; i++) {\n const c = idxs[i] as number;\n const list = byClass.get(c);\n if (list === undefined) byClass.set(c, [i]);\n else list.push(i);\n }\n\n const keep: number[] = [];\n for (const indices of byClass.values()) {\n const m = indices.length;\n const subBoxes = new Float32Array(m * 4);\n const subScores = new Float32Array(m);\n for (let k = 0; k < m; k++) {\n const i = indices[k] as number;\n subBoxes[k * 4] = boxes[i * 4] as number;\n subBoxes[k * 4 + 1] = boxes[i * 4 + 1] as number;\n subBoxes[k * 4 + 2] = boxes[i * 4 + 2] as number;\n subBoxes[k * 4 + 3] = boxes[i * 4 + 3] as number;\n subScores[k] = scores[i] as number;\n }\n const subKeep = nms(subBoxes, subScores, iouThreshold);\n for (let k = 0; k < subKeep.length; k++) {\n keep.push(indices[subKeep[k] as number] as number);\n }\n }\n\n keep.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n return Int32Array.from(keep);\n}\n\nexport interface DecodeYoloAnchorsOptions {\n /** Number of class-score channels following the 4 box channels. */\n readonly numClasses: number;\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedAnchors {\n /** Indices into the original `numAnchors` axis, in descending confidence order. */\n readonly anchorIndices: Int32Array;\n /** `[k, 4]` boxes in original-image pixel coords, flat row-major xyxy. */\n readonly boxesXyxy: Float32Array;\n /** Predicted class id per survivor. */\n readonly classIds: Int32Array;\n /** Confidence per survivor. */\n readonly confidences: Float32Array;\n}\n\n/**\n * Shared YOLO per-anchor decode used by both detection and segmentation\n * (v8 / v9 / v10 / v11 / v12).\n *\n * Only the first `4 + numClasses` channels are read; later channels (e.g.\n * mask coefficients) are ignored — callers can fetch them via the returned\n * {@link DecodedAnchors.anchorIndices}.\n *\n * @param data Flat per-anchor output, length `channels * numAnchors`.\n * @param dims Dims as reported by ORT, e.g. `[1, 84, 8400]` (det) or\n * `[1, 116, 8400]` (seg). The leading batch dim must be 1.\n */\nexport function decodeYoloAnchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n let normalized = dims;\n if (normalized.length === 3) {\n if (normalized[0] !== 1) {\n throw new Error(`decodeYoloAnchors: expected batch size 1, got ${normalized[0]}.`);\n }\n normalized = [normalized[1] as number, normalized[2] as number];\n }\n if (normalized.length !== 2) {\n throw new Error(\n `decodeYoloAnchors: expected 2-D output after batch removal, got dims=${JSON.stringify(dims)}.`,\n );\n }\n const channels = normalized[0] as number;\n const numAnchors = normalized[1] as number;\n\n const {\n numClasses,\n originalWidth,\n originalHeight,\n padLeft,\n padTop,\n scale,\n confThreshold,\n iouThreshold,\n maxDetections,\n } = options;\n\n if (numClasses < 1 || numClasses + 4 > channels) {\n throw new Error(\n `decodeYoloAnchors: invalid numClasses=${numClasses} for channels=${channels}.`,\n );\n }\n if (data.length !== channels * numAnchors) {\n throw new Error(\n `decodeYoloAnchors: data length ${data.length} does not match channels*numAnchors=${channels * numAnchors}.`,\n );\n }\n\n type Candidate = {\n anchorIdx: number;\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n classId: number;\n confidence: number;\n };\n const candidates: Candidate[] = [];\n\n for (let a = 0; a < numAnchors; a++) {\n let bestCls = 0;\n let bestScore = -Infinity;\n for (let c = 0; c < numClasses; c++) {\n const s = data[(4 + c) * numAnchors + a];\n if (s !== undefined && s > bestScore) {\n bestScore = s;\n bestCls = c;\n }\n }\n if (bestScore < confThreshold) continue;\n\n const cx = data[a] as number;\n const cy = data[numAnchors + a] as number;\n const w = data[2 * numAnchors + a] as number;\n const h = data[3 * numAnchors + a] as number;\n\n let x1 = cx - w / 2;\n let y1 = cy - h / 2;\n let x2 = cx + w / 2;\n let y2 = cy + h / 2;\n\n x1 = (x1 - padLeft) / scale;\n y1 = (y1 - padTop) / scale;\n x2 = (x2 - padLeft) / scale;\n y2 = (y2 - padTop) / scale;\n\n x1 = Math.max(0, Math.min(originalWidth, x1));\n y1 = Math.max(0, Math.min(originalHeight, y1));\n x2 = Math.max(0, Math.min(originalWidth, x2));\n y2 = Math.max(0, Math.min(originalHeight, y2));\n\n candidates.push({ anchorIdx: a, x1, y1, x2, y2, classId: bestCls, confidence: bestScore });\n }\n\n if (candidates.length === 0) return emptyDecoded();\n\n // Build flat arrays then delegate to batchedNms — same algorithm as before\n // but funnelled through the public per-class NMS helper.\n const flatBoxes = new Float32Array(candidates.length * 4);\n const scoresArr = new Float32Array(candidates.length);\n const idxsArr = new Int32Array(candidates.length);\n for (let i = 0; i < candidates.length; i++) {\n const c = candidates[i] as Candidate;\n flatBoxes[i * 4] = c.x1;\n flatBoxes[i * 4 + 1] = c.y1;\n flatBoxes[i * 4 + 2] = c.x2;\n flatBoxes[i * 4 + 3] = c.y2;\n scoresArr[i] = c.confidence;\n idxsArr[i] = c.classId;\n }\n const kept = batchedNms(flatBoxes, scoresArr, idxsArr, iouThreshold);\n if (kept.length === 0) return emptyDecoded();\n\n const limited = Array.from(kept).slice(0, maxDetections);\n const k = limited.length;\n const anchorIndices = new Int32Array(k);\n const boxesXyxy = new Float32Array(k * 4);\n const classIds = new Int32Array(k);\n const confidences = new Float32Array(k);\n for (let i = 0; i < k; i++) {\n const c = candidates[limited[i] as number] as Candidate;\n anchorIndices[i] = c.anchorIdx;\n boxesXyxy[i * 4] = c.x1;\n boxesXyxy[i * 4 + 1] = c.y1;\n boxesXyxy[i * 4 + 2] = c.x2;\n boxesXyxy[i * 4 + 3] = c.y2;\n classIds[i] = c.classId;\n confidences[i] = c.confidence;\n }\n return { anchorIndices, boxesXyxy, classIds, confidences };\n}\n\nfunction emptyDecoded(): DecodedAnchors {\n return {\n anchorIndices: new Int32Array(0),\n boxesXyxy: new Float32Array(0),\n classIds: new Int32Array(0),\n confidences: new Float32Array(0),\n };\n}\n\nexport interface DecodeYoloOptions {\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedDetection {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n}\n\n/**\n * Decode an anchor-free YOLO detection output into a list of detections.\n *\n * Works for **YOLOv8 / v9 / v10 / v11 / v12** detect heads.\n *\n * Expected raw shape: `[1, 4 + numClasses, N]`. `numClasses` is inferred\n * from the channel count.\n */\nexport function decodeYolo(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n const channels = outputDims.length === 3 ? outputDims[1] : outputDims[0];\n if (channels === undefined || channels < 5) {\n throw new Error(`decodeYolo: invalid output channel count ${channels} (expected >= 5).`);\n }\n const numClasses = channels - 4;\n\n const decoded = decodeYoloAnchors(output, outputDims, {\n numClasses,\n ...options,\n });\n\n const results: DecodedDetection[] = [];\n for (let i = 0; i < decoded.classIds.length; i++) {\n results.push({\n bbox: new BoundingBox(\n decoded.boxesXyxy[i * 4] as number,\n decoded.boxesXyxy[i * 4 + 1] as number,\n decoded.boxesXyxy[i * 4 + 2] as number,\n decoded.boxesXyxy[i * 4 + 3] as number,\n ),\n classId: decoded.classIds[i] as number,\n confidence: decoded.confidences[i] as number,\n });\n }\n return results;\n}\n\nlet _warnedDecodeYoloV8 = false;\nlet _warnedDecodeYoloV8Anchors = false;\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYolo}. Same behavior; the\n * decoder covers v8/v9/v10/v11/v12 detect heads. Will be removed in 0.4.0.\n */\nexport function decodeYoloV8(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n if (!_warnedDecodeYoloV8) {\n _warnedDecodeYoloV8 = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. \" +\n \"The alias will be removed in 0.4.0.\",\n );\n }\n return decodeYolo(output, outputDims, options);\n}\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYoloAnchors}. Will be removed in 0.4.0.\n */\nexport function decodeYoloV8Anchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n if (!_warnedDecodeYoloV8Anchors) {\n _warnedDecodeYoloV8Anchors = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. \" +\n \"The alias will be removed in 0.4.0.\",\n );\n }\n return decodeYoloAnchors(data, dims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloAnchorsOptions}. */\nexport type DecodeYoloV8AnchorsOptions = DecodeYoloAnchorsOptions;\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloOptions}. */\nexport type DecodeYoloV8Options = DecodeYoloOptions;\n"],"mappings":"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"}
|
|
@@ -118,10 +118,10 @@ function a(t, n, i) {
|
|
|
118
118
|
}
|
|
119
119
|
var o = !1, s = !1;
|
|
120
120
|
function c(e, t, n) {
|
|
121
|
-
return o || (o = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. The alias will be removed in 0.
|
|
121
|
+
return o || (o = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. The alias will be removed in 0.4.0.")), a(e, t, n);
|
|
122
122
|
}
|
|
123
123
|
function l(e, t, n) {
|
|
124
|
-
return s || (s = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. The alias will be removed in 0.
|
|
124
|
+
return s || (s = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. The alias will be removed in 0.4.0.")), r(e, t, n);
|
|
125
125
|
}
|
|
126
126
|
//#endregion
|
|
127
127
|
export { n as batchedNms, a as decodeYolo, r as decodeYoloAnchors, c as decodeYoloV8, l as decodeYoloV8Anchors, t as nms };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detection.js","names":[],"sources":["../../../src/vision/postprocess/detection.ts"],"sourcesContent":["/**\n * Detection head postprocessing: anchor-free YOLO decoding + non-maximum suppression.\n *\n * The shared {@link decodeYoloAnchors} helper does the per-anchor work that\n * is identical for plain detection and segmentation (transpose, xywh→xyxy,\n * letterbox unmap, per-class NMS, sort & cap). {@link decodeYolo} is a thin\n * wrapper around it; the segmentation module ({@link ./segmentation.js})\n * calls the helper directly so it can also recover the per-anchor mask\n * coefficients.\n *\n * Works for any YOLO export with the post-v8 anchor-free head:\n * **YOLOv8 / v9 / v10 / v11 / v12** detect heads, all of which share the\n * `[1, 4 + nc, N]` output layout.\n */\n\nimport { BoundingBox } from \"../types\";\n\n/**\n * Greedy non-maximum suppression on axis-aligned bounding boxes.\n *\n * Mirrors `torchvision.ops.nms` (keeps boxes with the highest score, drops\n * any subsequent box whose IoU exceeds the threshold).\n *\n * @param boxes Flat array of length `4 * N` in xyxy order: `[x1,y1,x2,y2, ...]`.\n * @param scores Detection score per box, length `N`.\n * @param iouThreshold Boxes with IoU above this threshold relative to a kept box are suppressed.\n * @returns Indices of kept boxes, in descending score order.\n */\nexport function nms(boxes: Float32Array, scores: Float32Array, iouThreshold: number): Int32Array {\n const n = scores.length;\n if (n === 0) return new Int32Array(0);\n\n const areas = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const x1 = boxes[i * 4] as number;\n const y1 = boxes[i * 4 + 1] as number;\n const x2 = boxes[i * 4 + 2] as number;\n const y2 = boxes[i * 4 + 3] as number;\n areas[i] = Math.max(0, x2 - x1) * Math.max(0, y2 - y1);\n }\n\n const order = new Array<number>(n);\n for (let i = 0; i < n; i++) order[i] = i;\n order.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n\n const suppressed = new Uint8Array(n);\n const keep: number[] = [];\n\n for (let oi = 0; oi < order.length; oi++) {\n const i = order[oi] as number;\n if (suppressed[i]) continue;\n keep.push(i);\n\n const ax1 = boxes[i * 4] as number;\n const ay1 = boxes[i * 4 + 1] as number;\n const ax2 = boxes[i * 4 + 2] as number;\n const ay2 = boxes[i * 4 + 3] as number;\n const ai = areas[i] as number;\n\n for (let oj = oi + 1; oj < order.length; oj++) {\n const j = order[oj] as number;\n if (suppressed[j]) continue;\n\n const bx1 = boxes[j * 4] as number;\n const by1 = boxes[j * 4 + 1] as number;\n const bx2 = boxes[j * 4 + 2] as number;\n const by2 = boxes[j * 4 + 3] as number;\n\n const ix1 = Math.max(ax1, bx1);\n const iy1 = Math.max(ay1, by1);\n const ix2 = Math.min(ax2, bx2);\n const iy2 = Math.min(ay2, by2);\n const iw = Math.max(0, ix2 - ix1);\n const ih = Math.max(0, iy2 - iy1);\n const inter = iw * ih;\n const union = ai + (areas[j] as number) - inter;\n const iou = union > 0 ? inter / union : 0;\n if (iou > iouThreshold) suppressed[j] = 1;\n }\n }\n\n return Int32Array.from(keep);\n}\n\n/**\n * Per-class NMS — boxes are suppressed only by other boxes of the same class.\n *\n * Mirrors `torchvision.ops.batched_nms`.\n *\n * @param boxes Flat array of length `4 * N` in xyxy order.\n * @param scores Detection score per box, length `N`.\n * @param idxs Class index per box, length `N`. Boxes with different `idxs`\n * never suppress each other.\n * @param iouThreshold IoU threshold for suppression within a class.\n */\nexport function batchedNms(\n boxes: Float32Array,\n scores: Float32Array,\n idxs: Int32Array,\n iouThreshold: number,\n): Int32Array {\n if (scores.length === 0) return new Int32Array(0);\n\n const byClass = new Map<number, number[]>();\n for (let i = 0; i < idxs.length; i++) {\n const c = idxs[i] as number;\n const list = byClass.get(c);\n if (list === undefined) byClass.set(c, [i]);\n else list.push(i);\n }\n\n const keep: number[] = [];\n for (const indices of byClass.values()) {\n const m = indices.length;\n const subBoxes = new Float32Array(m * 4);\n const subScores = new Float32Array(m);\n for (let k = 0; k < m; k++) {\n const i = indices[k] as number;\n subBoxes[k * 4] = boxes[i * 4] as number;\n subBoxes[k * 4 + 1] = boxes[i * 4 + 1] as number;\n subBoxes[k * 4 + 2] = boxes[i * 4 + 2] as number;\n subBoxes[k * 4 + 3] = boxes[i * 4 + 3] as number;\n subScores[k] = scores[i] as number;\n }\n const subKeep = nms(subBoxes, subScores, iouThreshold);\n for (let k = 0; k < subKeep.length; k++) {\n keep.push(indices[subKeep[k] as number] as number);\n }\n }\n\n keep.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n return Int32Array.from(keep);\n}\n\nexport interface DecodeYoloAnchorsOptions {\n /** Number of class-score channels following the 4 box channels. */\n readonly numClasses: number;\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedAnchors {\n /** Indices into the original `numAnchors` axis, in descending confidence order. */\n readonly anchorIndices: Int32Array;\n /** `[k, 4]` boxes in original-image pixel coords, flat row-major xyxy. */\n readonly boxesXyxy: Float32Array;\n /** Predicted class id per survivor. */\n readonly classIds: Int32Array;\n /** Confidence per survivor. */\n readonly confidences: Float32Array;\n}\n\n/**\n * Shared YOLO per-anchor decode used by both detection and segmentation\n * (v8 / v9 / v10 / v11 / v12).\n *\n * Only the first `4 + numClasses` channels are read; later channels (e.g.\n * mask coefficients) are ignored — callers can fetch them via the returned\n * {@link DecodedAnchors.anchorIndices}.\n *\n * @param data Flat per-anchor output, length `channels * numAnchors`.\n * @param dims Dims as reported by ORT, e.g. `[1, 84, 8400]` (det) or\n * `[1, 116, 8400]` (seg). The leading batch dim must be 1.\n */\nexport function decodeYoloAnchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n let normalized = dims;\n if (normalized.length === 3) {\n if (normalized[0] !== 1) {\n throw new Error(`decodeYoloAnchors: expected batch size 1, got ${normalized[0]}.`);\n }\n normalized = [normalized[1] as number, normalized[2] as number];\n }\n if (normalized.length !== 2) {\n throw new Error(\n `decodeYoloAnchors: expected 2-D output after batch removal, got dims=${JSON.stringify(dims)}.`,\n );\n }\n const channels = normalized[0] as number;\n const numAnchors = normalized[1] as number;\n\n const {\n numClasses,\n originalWidth,\n originalHeight,\n padLeft,\n padTop,\n scale,\n confThreshold,\n iouThreshold,\n maxDetections,\n } = options;\n\n if (numClasses < 1 || numClasses + 4 > channels) {\n throw new Error(\n `decodeYoloAnchors: invalid numClasses=${numClasses} for channels=${channels}.`,\n );\n }\n if (data.length !== channels * numAnchors) {\n throw new Error(\n `decodeYoloAnchors: data length ${data.length} does not match channels*numAnchors=${channels * numAnchors}.`,\n );\n }\n\n type Candidate = {\n anchorIdx: number;\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n classId: number;\n confidence: number;\n };\n const candidates: Candidate[] = [];\n\n for (let a = 0; a < numAnchors; a++) {\n let bestCls = 0;\n let bestScore = -Infinity;\n for (let c = 0; c < numClasses; c++) {\n const s = data[(4 + c) * numAnchors + a];\n if (s !== undefined && s > bestScore) {\n bestScore = s;\n bestCls = c;\n }\n }\n if (bestScore < confThreshold) continue;\n\n const cx = data[a] as number;\n const cy = data[numAnchors + a] as number;\n const w = data[2 * numAnchors + a] as number;\n const h = data[3 * numAnchors + a] as number;\n\n let x1 = cx - w / 2;\n let y1 = cy - h / 2;\n let x2 = cx + w / 2;\n let y2 = cy + h / 2;\n\n x1 = (x1 - padLeft) / scale;\n y1 = (y1 - padTop) / scale;\n x2 = (x2 - padLeft) / scale;\n y2 = (y2 - padTop) / scale;\n\n x1 = Math.max(0, Math.min(originalWidth, x1));\n y1 = Math.max(0, Math.min(originalHeight, y1));\n x2 = Math.max(0, Math.min(originalWidth, x2));\n y2 = Math.max(0, Math.min(originalHeight, y2));\n\n candidates.push({ anchorIdx: a, x1, y1, x2, y2, classId: bestCls, confidence: bestScore });\n }\n\n if (candidates.length === 0) return emptyDecoded();\n\n // Build flat arrays then delegate to batchedNms — same algorithm as before\n // but funnelled through the public per-class NMS helper.\n const flatBoxes = new Float32Array(candidates.length * 4);\n const scoresArr = new Float32Array(candidates.length);\n const idxsArr = new Int32Array(candidates.length);\n for (let i = 0; i < candidates.length; i++) {\n const c = candidates[i] as Candidate;\n flatBoxes[i * 4] = c.x1;\n flatBoxes[i * 4 + 1] = c.y1;\n flatBoxes[i * 4 + 2] = c.x2;\n flatBoxes[i * 4 + 3] = c.y2;\n scoresArr[i] = c.confidence;\n idxsArr[i] = c.classId;\n }\n const kept = batchedNms(flatBoxes, scoresArr, idxsArr, iouThreshold);\n if (kept.length === 0) return emptyDecoded();\n\n const limited = Array.from(kept).slice(0, maxDetections);\n const k = limited.length;\n const anchorIndices = new Int32Array(k);\n const boxesXyxy = new Float32Array(k * 4);\n const classIds = new Int32Array(k);\n const confidences = new Float32Array(k);\n for (let i = 0; i < k; i++) {\n const c = candidates[limited[i] as number] as Candidate;\n anchorIndices[i] = c.anchorIdx;\n boxesXyxy[i * 4] = c.x1;\n boxesXyxy[i * 4 + 1] = c.y1;\n boxesXyxy[i * 4 + 2] = c.x2;\n boxesXyxy[i * 4 + 3] = c.y2;\n classIds[i] = c.classId;\n confidences[i] = c.confidence;\n }\n return { anchorIndices, boxesXyxy, classIds, confidences };\n}\n\nfunction emptyDecoded(): DecodedAnchors {\n return {\n anchorIndices: new Int32Array(0),\n boxesXyxy: new Float32Array(0),\n classIds: new Int32Array(0),\n confidences: new Float32Array(0),\n };\n}\n\nexport interface DecodeYoloOptions {\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedDetection {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n}\n\n/**\n * Decode an anchor-free YOLO detection output into a list of detections.\n *\n * Works for **YOLOv8 / v9 / v10 / v11 / v12** detect heads.\n *\n * Expected raw shape: `[1, 4 + numClasses, N]`. `numClasses` is inferred\n * from the channel count.\n */\nexport function decodeYolo(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n const channels = outputDims.length === 3 ? outputDims[1] : outputDims[0];\n if (channels === undefined || channels < 5) {\n throw new Error(`decodeYolo: invalid output channel count ${channels} (expected >= 5).`);\n }\n const numClasses = channels - 4;\n\n const decoded = decodeYoloAnchors(output, outputDims, {\n numClasses,\n ...options,\n });\n\n const results: DecodedDetection[] = [];\n for (let i = 0; i < decoded.classIds.length; i++) {\n results.push({\n bbox: new BoundingBox(\n decoded.boxesXyxy[i * 4] as number,\n decoded.boxesXyxy[i * 4 + 1] as number,\n decoded.boxesXyxy[i * 4 + 2] as number,\n decoded.boxesXyxy[i * 4 + 3] as number,\n ),\n classId: decoded.classIds[i] as number,\n confidence: decoded.confidences[i] as number,\n });\n }\n return results;\n}\n\nlet _warnedDecodeYoloV8 = false;\nlet _warnedDecodeYoloV8Anchors = false;\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYolo}. Same behavior; the\n * decoder covers v8/v9/v10/v11/v12 detect heads. Will be removed in 0.3.0.\n */\nexport function decodeYoloV8(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n if (!_warnedDecodeYoloV8) {\n _warnedDecodeYoloV8 = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. \" +\n \"The alias will be removed in 0.3.0.\",\n );\n }\n return decodeYolo(output, outputDims, options);\n}\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYoloAnchors}. Will be removed in 0.3.0.\n */\nexport function decodeYoloV8Anchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n if (!_warnedDecodeYoloV8Anchors) {\n _warnedDecodeYoloV8Anchors = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. \" +\n \"The alias will be removed in 0.3.0.\",\n );\n }\n return decodeYoloAnchors(data, dims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloAnchorsOptions}. */\nexport type DecodeYoloV8AnchorsOptions = DecodeYoloAnchorsOptions;\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloOptions}. */\nexport type DecodeYoloV8Options = DecodeYoloOptions;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"detection.js","names":[],"sources":["../../../src/vision/postprocess/detection.ts"],"sourcesContent":["/**\n * Detection head postprocessing: anchor-free YOLO decoding + non-maximum suppression.\n *\n * The shared {@link decodeYoloAnchors} helper does the per-anchor work that\n * is identical for plain detection and segmentation (transpose, xywh→xyxy,\n * letterbox unmap, per-class NMS, sort & cap). {@link decodeYolo} is a thin\n * wrapper around it; the segmentation module ({@link ./segmentation.js})\n * calls the helper directly so it can also recover the per-anchor mask\n * coefficients.\n *\n * Works for any YOLO export with the post-v8 anchor-free head:\n * **YOLOv8 / v9 / v10 / v11 / v12** detect heads, all of which share the\n * `[1, 4 + nc, N]` output layout.\n */\n\nimport { BoundingBox } from \"../types\";\n\n/**\n * Greedy non-maximum suppression on axis-aligned bounding boxes.\n *\n * Mirrors `torchvision.ops.nms` (keeps boxes with the highest score, drops\n * any subsequent box whose IoU exceeds the threshold).\n *\n * @param boxes Flat array of length `4 * N` in xyxy order: `[x1,y1,x2,y2, ...]`.\n * @param scores Detection score per box, length `N`.\n * @param iouThreshold Boxes with IoU above this threshold relative to a kept box are suppressed.\n * @returns Indices of kept boxes, in descending score order.\n */\nexport function nms(boxes: Float32Array, scores: Float32Array, iouThreshold: number): Int32Array {\n const n = scores.length;\n if (n === 0) return new Int32Array(0);\n\n const areas = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const x1 = boxes[i * 4] as number;\n const y1 = boxes[i * 4 + 1] as number;\n const x2 = boxes[i * 4 + 2] as number;\n const y2 = boxes[i * 4 + 3] as number;\n areas[i] = Math.max(0, x2 - x1) * Math.max(0, y2 - y1);\n }\n\n const order = new Array<number>(n);\n for (let i = 0; i < n; i++) order[i] = i;\n order.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n\n const suppressed = new Uint8Array(n);\n const keep: number[] = [];\n\n for (let oi = 0; oi < order.length; oi++) {\n const i = order[oi] as number;\n if (suppressed[i]) continue;\n keep.push(i);\n\n const ax1 = boxes[i * 4] as number;\n const ay1 = boxes[i * 4 + 1] as number;\n const ax2 = boxes[i * 4 + 2] as number;\n const ay2 = boxes[i * 4 + 3] as number;\n const ai = areas[i] as number;\n\n for (let oj = oi + 1; oj < order.length; oj++) {\n const j = order[oj] as number;\n if (suppressed[j]) continue;\n\n const bx1 = boxes[j * 4] as number;\n const by1 = boxes[j * 4 + 1] as number;\n const bx2 = boxes[j * 4 + 2] as number;\n const by2 = boxes[j * 4 + 3] as number;\n\n const ix1 = Math.max(ax1, bx1);\n const iy1 = Math.max(ay1, by1);\n const ix2 = Math.min(ax2, bx2);\n const iy2 = Math.min(ay2, by2);\n const iw = Math.max(0, ix2 - ix1);\n const ih = Math.max(0, iy2 - iy1);\n const inter = iw * ih;\n const union = ai + (areas[j] as number) - inter;\n const iou = union > 0 ? inter / union : 0;\n if (iou > iouThreshold) suppressed[j] = 1;\n }\n }\n\n return Int32Array.from(keep);\n}\n\n/**\n * Per-class NMS — boxes are suppressed only by other boxes of the same class.\n *\n * Mirrors `torchvision.ops.batched_nms`.\n *\n * @param boxes Flat array of length `4 * N` in xyxy order.\n * @param scores Detection score per box, length `N`.\n * @param idxs Class index per box, length `N`. Boxes with different `idxs`\n * never suppress each other.\n * @param iouThreshold IoU threshold for suppression within a class.\n */\nexport function batchedNms(\n boxes: Float32Array,\n scores: Float32Array,\n idxs: Int32Array,\n iouThreshold: number,\n): Int32Array {\n if (scores.length === 0) return new Int32Array(0);\n\n const byClass = new Map<number, number[]>();\n for (let i = 0; i < idxs.length; i++) {\n const c = idxs[i] as number;\n const list = byClass.get(c);\n if (list === undefined) byClass.set(c, [i]);\n else list.push(i);\n }\n\n const keep: number[] = [];\n for (const indices of byClass.values()) {\n const m = indices.length;\n const subBoxes = new Float32Array(m * 4);\n const subScores = new Float32Array(m);\n for (let k = 0; k < m; k++) {\n const i = indices[k] as number;\n subBoxes[k * 4] = boxes[i * 4] as number;\n subBoxes[k * 4 + 1] = boxes[i * 4 + 1] as number;\n subBoxes[k * 4 + 2] = boxes[i * 4 + 2] as number;\n subBoxes[k * 4 + 3] = boxes[i * 4 + 3] as number;\n subScores[k] = scores[i] as number;\n }\n const subKeep = nms(subBoxes, subScores, iouThreshold);\n for (let k = 0; k < subKeep.length; k++) {\n keep.push(indices[subKeep[k] as number] as number);\n }\n }\n\n keep.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n return Int32Array.from(keep);\n}\n\nexport interface DecodeYoloAnchorsOptions {\n /** Number of class-score channels following the 4 box channels. */\n readonly numClasses: number;\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedAnchors {\n /** Indices into the original `numAnchors` axis, in descending confidence order. */\n readonly anchorIndices: Int32Array;\n /** `[k, 4]` boxes in original-image pixel coords, flat row-major xyxy. */\n readonly boxesXyxy: Float32Array;\n /** Predicted class id per survivor. */\n readonly classIds: Int32Array;\n /** Confidence per survivor. */\n readonly confidences: Float32Array;\n}\n\n/**\n * Shared YOLO per-anchor decode used by both detection and segmentation\n * (v8 / v9 / v10 / v11 / v12).\n *\n * Only the first `4 + numClasses` channels are read; later channels (e.g.\n * mask coefficients) are ignored — callers can fetch them via the returned\n * {@link DecodedAnchors.anchorIndices}.\n *\n * @param data Flat per-anchor output, length `channels * numAnchors`.\n * @param dims Dims as reported by ORT, e.g. `[1, 84, 8400]` (det) or\n * `[1, 116, 8400]` (seg). The leading batch dim must be 1.\n */\nexport function decodeYoloAnchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n let normalized = dims;\n if (normalized.length === 3) {\n if (normalized[0] !== 1) {\n throw new Error(`decodeYoloAnchors: expected batch size 1, got ${normalized[0]}.`);\n }\n normalized = [normalized[1] as number, normalized[2] as number];\n }\n if (normalized.length !== 2) {\n throw new Error(\n `decodeYoloAnchors: expected 2-D output after batch removal, got dims=${JSON.stringify(dims)}.`,\n );\n }\n const channels = normalized[0] as number;\n const numAnchors = normalized[1] as number;\n\n const {\n numClasses,\n originalWidth,\n originalHeight,\n padLeft,\n padTop,\n scale,\n confThreshold,\n iouThreshold,\n maxDetections,\n } = options;\n\n if (numClasses < 1 || numClasses + 4 > channels) {\n throw new Error(\n `decodeYoloAnchors: invalid numClasses=${numClasses} for channels=${channels}.`,\n );\n }\n if (data.length !== channels * numAnchors) {\n throw new Error(\n `decodeYoloAnchors: data length ${data.length} does not match channels*numAnchors=${channels * numAnchors}.`,\n );\n }\n\n type Candidate = {\n anchorIdx: number;\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n classId: number;\n confidence: number;\n };\n const candidates: Candidate[] = [];\n\n for (let a = 0; a < numAnchors; a++) {\n let bestCls = 0;\n let bestScore = -Infinity;\n for (let c = 0; c < numClasses; c++) {\n const s = data[(4 + c) * numAnchors + a];\n if (s !== undefined && s > bestScore) {\n bestScore = s;\n bestCls = c;\n }\n }\n if (bestScore < confThreshold) continue;\n\n const cx = data[a] as number;\n const cy = data[numAnchors + a] as number;\n const w = data[2 * numAnchors + a] as number;\n const h = data[3 * numAnchors + a] as number;\n\n let x1 = cx - w / 2;\n let y1 = cy - h / 2;\n let x2 = cx + w / 2;\n let y2 = cy + h / 2;\n\n x1 = (x1 - padLeft) / scale;\n y1 = (y1 - padTop) / scale;\n x2 = (x2 - padLeft) / scale;\n y2 = (y2 - padTop) / scale;\n\n x1 = Math.max(0, Math.min(originalWidth, x1));\n y1 = Math.max(0, Math.min(originalHeight, y1));\n x2 = Math.max(0, Math.min(originalWidth, x2));\n y2 = Math.max(0, Math.min(originalHeight, y2));\n\n candidates.push({ anchorIdx: a, x1, y1, x2, y2, classId: bestCls, confidence: bestScore });\n }\n\n if (candidates.length === 0) return emptyDecoded();\n\n // Build flat arrays then delegate to batchedNms — same algorithm as before\n // but funnelled through the public per-class NMS helper.\n const flatBoxes = new Float32Array(candidates.length * 4);\n const scoresArr = new Float32Array(candidates.length);\n const idxsArr = new Int32Array(candidates.length);\n for (let i = 0; i < candidates.length; i++) {\n const c = candidates[i] as Candidate;\n flatBoxes[i * 4] = c.x1;\n flatBoxes[i * 4 + 1] = c.y1;\n flatBoxes[i * 4 + 2] = c.x2;\n flatBoxes[i * 4 + 3] = c.y2;\n scoresArr[i] = c.confidence;\n idxsArr[i] = c.classId;\n }\n const kept = batchedNms(flatBoxes, scoresArr, idxsArr, iouThreshold);\n if (kept.length === 0) return emptyDecoded();\n\n const limited = Array.from(kept).slice(0, maxDetections);\n const k = limited.length;\n const anchorIndices = new Int32Array(k);\n const boxesXyxy = new Float32Array(k * 4);\n const classIds = new Int32Array(k);\n const confidences = new Float32Array(k);\n for (let i = 0; i < k; i++) {\n const c = candidates[limited[i] as number] as Candidate;\n anchorIndices[i] = c.anchorIdx;\n boxesXyxy[i * 4] = c.x1;\n boxesXyxy[i * 4 + 1] = c.y1;\n boxesXyxy[i * 4 + 2] = c.x2;\n boxesXyxy[i * 4 + 3] = c.y2;\n classIds[i] = c.classId;\n confidences[i] = c.confidence;\n }\n return { anchorIndices, boxesXyxy, classIds, confidences };\n}\n\nfunction emptyDecoded(): DecodedAnchors {\n return {\n anchorIndices: new Int32Array(0),\n boxesXyxy: new Float32Array(0),\n classIds: new Int32Array(0),\n confidences: new Float32Array(0),\n };\n}\n\nexport interface DecodeYoloOptions {\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedDetection {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n}\n\n/**\n * Decode an anchor-free YOLO detection output into a list of detections.\n *\n * Works for **YOLOv8 / v9 / v10 / v11 / v12** detect heads.\n *\n * Expected raw shape: `[1, 4 + numClasses, N]`. `numClasses` is inferred\n * from the channel count.\n */\nexport function decodeYolo(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n const channels = outputDims.length === 3 ? outputDims[1] : outputDims[0];\n if (channels === undefined || channels < 5) {\n throw new Error(`decodeYolo: invalid output channel count ${channels} (expected >= 5).`);\n }\n const numClasses = channels - 4;\n\n const decoded = decodeYoloAnchors(output, outputDims, {\n numClasses,\n ...options,\n });\n\n const results: DecodedDetection[] = [];\n for (let i = 0; i < decoded.classIds.length; i++) {\n results.push({\n bbox: new BoundingBox(\n decoded.boxesXyxy[i * 4] as number,\n decoded.boxesXyxy[i * 4 + 1] as number,\n decoded.boxesXyxy[i * 4 + 2] as number,\n decoded.boxesXyxy[i * 4 + 3] as number,\n ),\n classId: decoded.classIds[i] as number,\n confidence: decoded.confidences[i] as number,\n });\n }\n return results;\n}\n\nlet _warnedDecodeYoloV8 = false;\nlet _warnedDecodeYoloV8Anchors = false;\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYolo}. Same behavior; the\n * decoder covers v8/v9/v10/v11/v12 detect heads. Will be removed in 0.4.0.\n */\nexport function decodeYoloV8(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n if (!_warnedDecodeYoloV8) {\n _warnedDecodeYoloV8 = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. \" +\n \"The alias will be removed in 0.4.0.\",\n );\n }\n return decodeYolo(output, outputDims, options);\n}\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYoloAnchors}. Will be removed in 0.4.0.\n */\nexport function decodeYoloV8Anchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n if (!_warnedDecodeYoloV8Anchors) {\n _warnedDecodeYoloV8Anchors = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. \" +\n \"The alias will be removed in 0.4.0.\",\n );\n }\n return decodeYoloAnchors(data, dims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloAnchorsOptions}. */\nexport type DecodeYoloV8AnchorsOptions = DecodeYoloAnchorsOptions;\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloOptions}. */\nexport type DecodeYoloV8Options = DecodeYoloOptions;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../types.cjs"),t=require("./detection.cjs");function n(n,i,a,s,c){let l=s;if(l.length===4){if(l[0]!==1)throw Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${l[0]}.`);l=[l[1],l[2],l[3]]}if(l.length!==3)throw Error(`decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(s)}.`);let u=l[0],d=l[1],f=l[2],p=i.length===3?i[1]:i[0],m=i.length===3?i[2]:i[1];if(p===void 0||m===void 0)throw Error(`decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(i)}.`);let h=4+c.numClasses+u;if(p!==h)throw Error(`decodeYoloSeg: channels=${p} does not match 4 + numClasses(${c.numClasses}) + numMaskCoefs(${u}) = ${h}.`);if(a.length!==u*d*f)throw Error(`decodeYoloSeg: prototype length ${a.length} does not match dims=${JSON.stringify(s)}.`);let g=t.decodeYoloAnchors(n,i,{numClasses:c.numClasses,originalWidth:c.originalWidth,originalHeight:c.originalHeight,padLeft:c.padLeft,padTop:c.padTop,scale:c.scale,confThreshold:c.confThreshold,iouThreshold:c.iouThreshold,maxDetections:c.maxDetections});if(g.anchorIndices.length===0)return[];let _=c.maskThreshold??.5,v=f/c.inputWidth,y=d/c.inputHeight,b=d*f,x=(4+c.numClasses)*m,S=[];for(let t=0;t<g.anchorIndices.length;t++){let i=g.anchorIndices[t],s=g.boxesXyxy[t*4],l=g.boxesXyxy[t*4+1],p=g.boxesXyxy[t*4+2],h=g.boxesXyxy[t*4+3],C=new e.BoundingBox(s,l,p,h),w=g.classIds[t],T=g.confidences[t],E=Math.max(0,Math.trunc(p)-Math.trunc(s)),D=Math.max(0,Math.trunc(h)-Math.trunc(l));if(E===0||D===0){S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(new Uint8Array,0,0)});continue}let O=s*c.scale+c.padLeft,k=l*c.scale+c.padTop,A=p*c.scale+c.padLeft,j=h*c.scale+c.padTop,M=Math.max(0,Math.floor(O*v)),N=Math.max(0,Math.floor(k*y)),P=Math.min(f,Math.ceil(A*v)),F=Math.min(d,Math.ceil(j*y));if(P<=M||F<=N){S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(new Uint8Array(E*D),E,D)});continue}let I=P-M,L=F-N,R=new Float32Array(I*L);for(let e=0;e<L;e++){let t=N+e;for(let o=0;o<I;o++){let s=M+o,c=0;for(let e=0;e<u;e++){let r=n[x+e*m+i],o=a[e*b+t*f+s];c+=r*o}R[e*I+o]=r(c)}}let z=o(R,I,L,E,D),B=new Uint8Array(E*D);for(let e=0;e<B.length;e++)B[e]=z[e]>=_?255:0;S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(B,E,D)})}return S}function r(e){if(e>=0)return 1/(1+Math.exp(-e));let t=Math.exp(e);return t/(1+t)}var i=!1;function a(e,t,r,a,o){return i||(i=!0,console.warn(`[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. The alias will be removed in 0.
|
|
1
|
+
const e=require("../types.cjs"),t=require("./detection.cjs");function n(n,i,a,s,c){let l=s;if(l.length===4){if(l[0]!==1)throw Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${l[0]}.`);l=[l[1],l[2],l[3]]}if(l.length!==3)throw Error(`decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(s)}.`);let u=l[0],d=l[1],f=l[2],p=i.length===3?i[1]:i[0],m=i.length===3?i[2]:i[1];if(p===void 0||m===void 0)throw Error(`decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(i)}.`);let h=4+c.numClasses+u;if(p!==h)throw Error(`decodeYoloSeg: channels=${p} does not match 4 + numClasses(${c.numClasses}) + numMaskCoefs(${u}) = ${h}.`);if(a.length!==u*d*f)throw Error(`decodeYoloSeg: prototype length ${a.length} does not match dims=${JSON.stringify(s)}.`);let g=t.decodeYoloAnchors(n,i,{numClasses:c.numClasses,originalWidth:c.originalWidth,originalHeight:c.originalHeight,padLeft:c.padLeft,padTop:c.padTop,scale:c.scale,confThreshold:c.confThreshold,iouThreshold:c.iouThreshold,maxDetections:c.maxDetections});if(g.anchorIndices.length===0)return[];let _=c.maskThreshold??.5,v=f/c.inputWidth,y=d/c.inputHeight,b=d*f,x=(4+c.numClasses)*m,S=[];for(let t=0;t<g.anchorIndices.length;t++){let i=g.anchorIndices[t],s=g.boxesXyxy[t*4],l=g.boxesXyxy[t*4+1],p=g.boxesXyxy[t*4+2],h=g.boxesXyxy[t*4+3],C=new e.BoundingBox(s,l,p,h),w=g.classIds[t],T=g.confidences[t],E=Math.max(0,Math.trunc(p)-Math.trunc(s)),D=Math.max(0,Math.trunc(h)-Math.trunc(l));if(E===0||D===0){S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(new Uint8Array,0,0)});continue}let O=s*c.scale+c.padLeft,k=l*c.scale+c.padTop,A=p*c.scale+c.padLeft,j=h*c.scale+c.padTop,M=Math.max(0,Math.floor(O*v)),N=Math.max(0,Math.floor(k*y)),P=Math.min(f,Math.ceil(A*v)),F=Math.min(d,Math.ceil(j*y));if(P<=M||F<=N){S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(new Uint8Array(E*D),E,D)});continue}let I=P-M,L=F-N,R=new Float32Array(I*L);for(let e=0;e<L;e++){let t=N+e;for(let o=0;o<I;o++){let s=M+o,c=0;for(let e=0;e<u;e++){let r=n[x+e*m+i],o=a[e*b+t*f+s];c+=r*o}R[e*I+o]=r(c)}}let z=o(R,I,L,E,D),B=new Uint8Array(E*D);for(let e=0;e<B.length;e++)B[e]=z[e]>=_?255:0;S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(B,E,D)})}return S}function r(e){if(e>=0)return 1/(1+Math.exp(-e));let t=Math.exp(e);return t/(1+t)}var i=!1;function a(e,t,r,a,o){return i||(i=!0,console.warn(`[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. The alias will be removed in 0.4.0.`)),n(e,t,r,a,o)}function o(e,t,n,r,i){let a=new Float32Array(r*i);if(r===0||i===0||t===0||n===0)return a;if(r===t&&i===n)return a.set(e),a;let o=t/r,s=n/i;for(let c=0;c<i;c++){let i=(c+.5)*s-.5,l=Math.max(0,Math.floor(i)),u=Math.min(n-1,l+1),d=Math.max(0,Math.min(1,i-l));for(let n=0;n<r;n++){let i=(n+.5)*o-.5,s=Math.max(0,Math.floor(i)),f=Math.min(t-1,s+1),p=Math.max(0,Math.min(1,i-s)),m=e[l*t+s],h=e[l*t+f],g=e[u*t+s],_=e[u*t+f],v=m*(1-p)+h*p,y=g*(1-p)+_*p;a[c*r+n]=v*(1-d)+y*d}}return a}exports.decodeYoloSeg=n,exports.decodeYoloV8Seg=a;
|
|
2
2
|
//# sourceMappingURL=segmentation.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segmentation.cjs","names":[],"sources":["../../../src/vision/postprocess/segmentation.ts"],"sourcesContent":["/**\n * Segmentation head postprocessing: YOLO instance-segmentation decoding.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg exports (and any later seg head\n * sharing the layout). The model produces two output tensors:\n *\n * - `output0` of shape `(1, 4 + numClasses + numMaskCoefs, numAnchors)` — the\n * same per-anchor predictions as plain YOLO detection plus an extra\n * `numMaskCoefs` (typically 32) channels of mask coefficients.\n * - `output1` of shape `(1, numMaskCoefs, maskH, maskW)` — a set of \"prototype\"\n * masks shared across all anchors.\n *\n * The per-anchor decode (xywh→xyxy, undo letterbox, per-class NMS, sort & cap)\n * is delegated to {@link decodeYoloAnchors}; this module only handles the\n * mask-specific work: matmul against prototypes, sigmoid, bilinear resize and\n * thresholding.\n */\n\nimport { decodeYoloAnchors } from \"./detection\";\nimport { BoundingBox, Mask } from \"../types\";\n\nexport interface DecodeYoloSegOptions {\n readonly numClasses: number;\n /** Model input `[width, height]` (post-letterbox). */\n readonly inputWidth: number;\n readonly inputHeight: number;\n /** Original image `[width, height]`. */\n readonly originalWidth: number;\n readonly originalHeight: number;\n /** Letterbox horizontal padding in input-tensor pixels. */\n readonly padLeft: number;\n /** Letterbox vertical padding in input-tensor pixels. */\n readonly padTop: number;\n /** Letterbox scale factor. */\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n /** Probability cutoff applied to the soft mask. Defaults to `0.5`. */\n readonly maskThreshold?: number;\n}\n\nexport interface DecodedSegmentation {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n /** Binary mask cropped to `bbox`. Width/height match `bbox.asIntXyxy()` extents. */\n readonly mask: Mask;\n}\n\n/**\n * Decode YOLO segmentation raw outputs into a list of segmented instances.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg.\n *\n * @param perAnchorData Flat `output0`, length `(4 + numClasses + numMaskCoefs) * numAnchors`.\n * @param perAnchorDims Dims as reported by ORT, e.g. `[1, 116, 8400]`.\n * @param prototypeData Flat `output1`, length `numMaskCoefs * maskH * maskW`.\n * @param prototypeDims Dims as reported by ORT, e.g. `[1, 32, 160, 160]`.\n */\nexport function decodeYoloSeg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n // Strip batch dim from prototypes; perAnchor batch is validated by the helper.\n let pDims = prototypeDims;\n if (pDims.length === 4) {\n if (pDims[0] !== 1) {\n throw new Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${pDims[0]}.`);\n }\n pDims = [pDims[1] as number, pDims[2] as number, pDims[3] as number];\n }\n if (pDims.length !== 3) {\n throw new Error(\n `decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n const numMaskCoefs = pDims[0] as number;\n const maskH = pDims[1] as number;\n const maskW = pDims[2] as number;\n\n const channels = perAnchorDims.length === 3 ? perAnchorDims[1] : perAnchorDims[0];\n const numAnchors = perAnchorDims.length === 3 ? perAnchorDims[2] : perAnchorDims[1];\n if (channels === undefined || numAnchors === undefined) {\n throw new Error(\n `decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(perAnchorDims)}.`,\n );\n }\n\n const expectedChannels = 4 + options.numClasses + numMaskCoefs;\n if (channels !== expectedChannels) {\n throw new Error(\n `decodeYoloSeg: channels=${channels} does not match 4 + numClasses(${options.numClasses}) + numMaskCoefs(${numMaskCoefs}) = ${expectedChannels}.`,\n );\n }\n if (prototypeData.length !== numMaskCoefs * maskH * maskW) {\n throw new Error(\n `decodeYoloSeg: prototype length ${prototypeData.length} does not match dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n\n const decoded = decodeYoloAnchors(perAnchorData, perAnchorDims, {\n numClasses: options.numClasses,\n originalWidth: options.originalWidth,\n originalHeight: options.originalHeight,\n padLeft: options.padLeft,\n padTop: options.padTop,\n scale: options.scale,\n confThreshold: options.confThreshold,\n iouThreshold: options.iouThreshold,\n maxDetections: options.maxDetections,\n });\n\n if (decoded.anchorIndices.length === 0) return [];\n\n const maskThreshold = options.maskThreshold ?? 0.5;\n const scaleX = maskW / options.inputWidth;\n const scaleY = maskH / options.inputHeight;\n const protoPlane = maskH * maskW;\n const coefBase = (4 + options.numClasses) * numAnchors;\n\n const results: DecodedSegmentation[] = [];\n\n for (let i = 0; i < decoded.anchorIndices.length; i++) {\n const a = decoded.anchorIndices[i] as number;\n const x1 = decoded.boxesXyxy[i * 4] as number;\n const y1 = decoded.boxesXyxy[i * 4 + 1] as number;\n const x2 = decoded.boxesXyxy[i * 4 + 2] as number;\n const y2 = decoded.boxesXyxy[i * 4 + 3] as number;\n const bbox = new BoundingBox(x1, y1, x2, y2);\n const classId = decoded.classIds[i] as number;\n const confidence = decoded.confidences[i] as number;\n\n const bboxW = Math.max(0, Math.trunc(x2) - Math.trunc(x1));\n const bboxH = Math.max(0, Math.trunc(y2) - Math.trunc(y1));\n\n if (bboxW === 0 || bboxH === 0) {\n results.push({ bbox, classId, confidence, mask: new Mask(new Uint8Array(0), 0, 0) });\n continue;\n }\n\n // Bbox in input-tensor coords, then in low-res mask coords.\n const ibx1 = x1 * options.scale + options.padLeft;\n const iby1 = y1 * options.scale + options.padTop;\n const ibx2 = x2 * options.scale + options.padLeft;\n const iby2 = y2 * options.scale + options.padTop;\n\n const mbx1 = Math.max(0, Math.floor(ibx1 * scaleX));\n const mby1 = Math.max(0, Math.floor(iby1 * scaleY));\n const mbx2 = Math.min(maskW, Math.ceil(ibx2 * scaleX));\n const mby2 = Math.min(maskH, Math.ceil(iby2 * scaleY));\n\n if (mbx2 <= mbx1 || mby2 <= mby1) {\n results.push({\n bbox,\n classId,\n confidence,\n mask: new Mask(new Uint8Array(bboxW * bboxH), bboxW, bboxH),\n });\n continue;\n }\n\n // Compute soft mask only within the prototype region under this bbox.\n const cropW = mbx2 - mbx1;\n const cropH = mby2 - mby1;\n const softCrop = new Float32Array(cropW * cropH);\n for (let y = 0; y < cropH; y++) {\n const py = mby1 + y;\n for (let x = 0; x < cropW; x++) {\n const px = mbx1 + x;\n let sum = 0;\n for (let kk = 0; kk < numMaskCoefs; kk++) {\n const coef = perAnchorData[coefBase + kk * numAnchors + a];\n const proto = prototypeData[kk * protoPlane + py * maskW + px];\n sum += coef * proto;\n }\n softCrop[y * cropW + x] = sigmoid(sum);\n }\n }\n\n const resized = resizeBilinear(softCrop, cropW, cropH, bboxW, bboxH);\n const binary = new Uint8Array(bboxW * bboxH);\n for (let j = 0; j < binary.length; j++) {\n binary[j] = resized[j] >= maskThreshold ? 255 : 0;\n }\n\n results.push({ bbox, classId, confidence, mask: new Mask(binary, bboxW, bboxH) });\n }\n\n return results;\n}\n\nfunction sigmoid(x: number): number {\n if (x >= 0) {\n return 1 / (1 + Math.exp(-x));\n }\n const e = Math.exp(x);\n return e / (1 + e);\n}\n\nlet _warnedDecodeYoloV8Seg = false;\n\n/** @deprecated since 0.2.0 — use {@link decodeYoloSeg}. Will be removed in 0.3.0. */\nexport function decodeYoloV8Seg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n if (!_warnedDecodeYoloV8Seg) {\n _warnedDecodeYoloV8Seg = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. \" +\n \"The alias will be removed in 0.3.0.\",\n );\n }\n return decodeYoloSeg(perAnchorData, perAnchorDims, prototypeData, prototypeDims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloSegOptions}. */\nexport type DecodeYoloV8SegOptions = DecodeYoloSegOptions;\n\nfunction resizeBilinear(\n src: Float32Array,\n srcWidth: number,\n srcHeight: number,\n targetWidth: number,\n targetHeight: number,\n): Float32Array {\n const out = new Float32Array(targetWidth * targetHeight);\n if (targetWidth === 0 || targetHeight === 0 || srcWidth === 0 || srcHeight === 0) {\n return out;\n }\n if (targetWidth === srcWidth && targetHeight === srcHeight) {\n out.set(src);\n return out;\n }\n const sx = srcWidth / targetWidth;\n const sy = srcHeight / targetHeight;\n for (let y = 0; y < targetHeight; y++) {\n const yy = (y + 0.5) * sy - 0.5;\n const y0 = Math.max(0, Math.floor(yy));\n const y1 = Math.min(srcHeight - 1, y0 + 1);\n const wy = Math.max(0, Math.min(1, yy - y0));\n for (let x = 0; x < targetWidth; x++) {\n const xx = (x + 0.5) * sx - 0.5;\n const x0 = Math.max(0, Math.floor(xx));\n const x1 = Math.min(srcWidth - 1, x0 + 1);\n const wx = Math.max(0, Math.min(1, xx - x0));\n const v00 = src[y0 * srcWidth + x0];\n const v01 = src[y0 * srcWidth + x1];\n const v10 = src[y1 * srcWidth + x0];\n const v11 = src[y1 * srcWidth + x1];\n const top = v00 * (1 - wx) + v01 * wx;\n const bot = v10 * (1 - wx) + v11 * wx;\n out[y * targetWidth + x] = top * (1 - wy) + bot * wy;\n }\n }\n return out;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"segmentation.cjs","names":[],"sources":["../../../src/vision/postprocess/segmentation.ts"],"sourcesContent":["/**\n * Segmentation head postprocessing: YOLO instance-segmentation decoding.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg exports (and any later seg head\n * sharing the layout). The model produces two output tensors:\n *\n * - `output0` of shape `(1, 4 + numClasses + numMaskCoefs, numAnchors)` — the\n * same per-anchor predictions as plain YOLO detection plus an extra\n * `numMaskCoefs` (typically 32) channels of mask coefficients.\n * - `output1` of shape `(1, numMaskCoefs, maskH, maskW)` — a set of \"prototype\"\n * masks shared across all anchors.\n *\n * The per-anchor decode (xywh→xyxy, undo letterbox, per-class NMS, sort & cap)\n * is delegated to {@link decodeYoloAnchors}; this module only handles the\n * mask-specific work: matmul against prototypes, sigmoid, bilinear resize and\n * thresholding.\n */\n\nimport { decodeYoloAnchors } from \"./detection\";\nimport { BoundingBox, Mask } from \"../types\";\n\nexport interface DecodeYoloSegOptions {\n readonly numClasses: number;\n /** Model input `[width, height]` (post-letterbox). */\n readonly inputWidth: number;\n readonly inputHeight: number;\n /** Original image `[width, height]`. */\n readonly originalWidth: number;\n readonly originalHeight: number;\n /** Letterbox horizontal padding in input-tensor pixels. */\n readonly padLeft: number;\n /** Letterbox vertical padding in input-tensor pixels. */\n readonly padTop: number;\n /** Letterbox scale factor. */\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n /** Probability cutoff applied to the soft mask. Defaults to `0.5`. */\n readonly maskThreshold?: number;\n}\n\nexport interface DecodedSegmentation {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n /** Binary mask cropped to `bbox`. Width/height match `bbox.asIntXyxy()` extents. */\n readonly mask: Mask;\n}\n\n/**\n * Decode YOLO segmentation raw outputs into a list of segmented instances.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg.\n *\n * @param perAnchorData Flat `output0`, length `(4 + numClasses + numMaskCoefs) * numAnchors`.\n * @param perAnchorDims Dims as reported by ORT, e.g. `[1, 116, 8400]`.\n * @param prototypeData Flat `output1`, length `numMaskCoefs * maskH * maskW`.\n * @param prototypeDims Dims as reported by ORT, e.g. `[1, 32, 160, 160]`.\n */\nexport function decodeYoloSeg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n // Strip batch dim from prototypes; perAnchor batch is validated by the helper.\n let pDims = prototypeDims;\n if (pDims.length === 4) {\n if (pDims[0] !== 1) {\n throw new Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${pDims[0]}.`);\n }\n pDims = [pDims[1] as number, pDims[2] as number, pDims[3] as number];\n }\n if (pDims.length !== 3) {\n throw new Error(\n `decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n const numMaskCoefs = pDims[0] as number;\n const maskH = pDims[1] as number;\n const maskW = pDims[2] as number;\n\n const channels = perAnchorDims.length === 3 ? perAnchorDims[1] : perAnchorDims[0];\n const numAnchors = perAnchorDims.length === 3 ? perAnchorDims[2] : perAnchorDims[1];\n if (channels === undefined || numAnchors === undefined) {\n throw new Error(\n `decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(perAnchorDims)}.`,\n );\n }\n\n const expectedChannels = 4 + options.numClasses + numMaskCoefs;\n if (channels !== expectedChannels) {\n throw new Error(\n `decodeYoloSeg: channels=${channels} does not match 4 + numClasses(${options.numClasses}) + numMaskCoefs(${numMaskCoefs}) = ${expectedChannels}.`,\n );\n }\n if (prototypeData.length !== numMaskCoefs * maskH * maskW) {\n throw new Error(\n `decodeYoloSeg: prototype length ${prototypeData.length} does not match dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n\n const decoded = decodeYoloAnchors(perAnchorData, perAnchorDims, {\n numClasses: options.numClasses,\n originalWidth: options.originalWidth,\n originalHeight: options.originalHeight,\n padLeft: options.padLeft,\n padTop: options.padTop,\n scale: options.scale,\n confThreshold: options.confThreshold,\n iouThreshold: options.iouThreshold,\n maxDetections: options.maxDetections,\n });\n\n if (decoded.anchorIndices.length === 0) return [];\n\n const maskThreshold = options.maskThreshold ?? 0.5;\n const scaleX = maskW / options.inputWidth;\n const scaleY = maskH / options.inputHeight;\n const protoPlane = maskH * maskW;\n const coefBase = (4 + options.numClasses) * numAnchors;\n\n const results: DecodedSegmentation[] = [];\n\n for (let i = 0; i < decoded.anchorIndices.length; i++) {\n const a = decoded.anchorIndices[i] as number;\n const x1 = decoded.boxesXyxy[i * 4] as number;\n const y1 = decoded.boxesXyxy[i * 4 + 1] as number;\n const x2 = decoded.boxesXyxy[i * 4 + 2] as number;\n const y2 = decoded.boxesXyxy[i * 4 + 3] as number;\n const bbox = new BoundingBox(x1, y1, x2, y2);\n const classId = decoded.classIds[i] as number;\n const confidence = decoded.confidences[i] as number;\n\n const bboxW = Math.max(0, Math.trunc(x2) - Math.trunc(x1));\n const bboxH = Math.max(0, Math.trunc(y2) - Math.trunc(y1));\n\n if (bboxW === 0 || bboxH === 0) {\n results.push({ bbox, classId, confidence, mask: new Mask(new Uint8Array(0), 0, 0) });\n continue;\n }\n\n // Bbox in input-tensor coords, then in low-res mask coords.\n const ibx1 = x1 * options.scale + options.padLeft;\n const iby1 = y1 * options.scale + options.padTop;\n const ibx2 = x2 * options.scale + options.padLeft;\n const iby2 = y2 * options.scale + options.padTop;\n\n const mbx1 = Math.max(0, Math.floor(ibx1 * scaleX));\n const mby1 = Math.max(0, Math.floor(iby1 * scaleY));\n const mbx2 = Math.min(maskW, Math.ceil(ibx2 * scaleX));\n const mby2 = Math.min(maskH, Math.ceil(iby2 * scaleY));\n\n if (mbx2 <= mbx1 || mby2 <= mby1) {\n results.push({\n bbox,\n classId,\n confidence,\n mask: new Mask(new Uint8Array(bboxW * bboxH), bboxW, bboxH),\n });\n continue;\n }\n\n // Compute soft mask only within the prototype region under this bbox.\n const cropW = mbx2 - mbx1;\n const cropH = mby2 - mby1;\n const softCrop = new Float32Array(cropW * cropH);\n for (let y = 0; y < cropH; y++) {\n const py = mby1 + y;\n for (let x = 0; x < cropW; x++) {\n const px = mbx1 + x;\n let sum = 0;\n for (let kk = 0; kk < numMaskCoefs; kk++) {\n const coef = perAnchorData[coefBase + kk * numAnchors + a];\n const proto = prototypeData[kk * protoPlane + py * maskW + px];\n sum += coef * proto;\n }\n softCrop[y * cropW + x] = sigmoid(sum);\n }\n }\n\n const resized = resizeBilinear(softCrop, cropW, cropH, bboxW, bboxH);\n const binary = new Uint8Array(bboxW * bboxH);\n for (let j = 0; j < binary.length; j++) {\n binary[j] = resized[j] >= maskThreshold ? 255 : 0;\n }\n\n results.push({ bbox, classId, confidence, mask: new Mask(binary, bboxW, bboxH) });\n }\n\n return results;\n}\n\nfunction sigmoid(x: number): number {\n if (x >= 0) {\n return 1 / (1 + Math.exp(-x));\n }\n const e = Math.exp(x);\n return e / (1 + e);\n}\n\nlet _warnedDecodeYoloV8Seg = false;\n\n/** @deprecated since 0.2.0 — use {@link decodeYoloSeg}. Will be removed in 0.4.0. */\nexport function decodeYoloV8Seg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n if (!_warnedDecodeYoloV8Seg) {\n _warnedDecodeYoloV8Seg = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. \" +\n \"The alias will be removed in 0.4.0.\",\n );\n }\n return decodeYoloSeg(perAnchorData, perAnchorDims, prototypeData, prototypeDims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloSegOptions}. */\nexport type DecodeYoloV8SegOptions = DecodeYoloSegOptions;\n\nfunction resizeBilinear(\n src: Float32Array,\n srcWidth: number,\n srcHeight: number,\n targetWidth: number,\n targetHeight: number,\n): Float32Array {\n const out = new Float32Array(targetWidth * targetHeight);\n if (targetWidth === 0 || targetHeight === 0 || srcWidth === 0 || srcHeight === 0) {\n return out;\n }\n if (targetWidth === srcWidth && targetHeight === srcHeight) {\n out.set(src);\n return out;\n }\n const sx = srcWidth / targetWidth;\n const sy = srcHeight / targetHeight;\n for (let y = 0; y < targetHeight; y++) {\n const yy = (y + 0.5) * sy - 0.5;\n const y0 = Math.max(0, Math.floor(yy));\n const y1 = Math.min(srcHeight - 1, y0 + 1);\n const wy = Math.max(0, Math.min(1, yy - y0));\n for (let x = 0; x < targetWidth; x++) {\n const xx = (x + 0.5) * sx - 0.5;\n const x0 = Math.max(0, Math.floor(xx));\n const x1 = Math.min(srcWidth - 1, x0 + 1);\n const wx = Math.max(0, Math.min(1, xx - x0));\n const v00 = src[y0 * srcWidth + x0];\n const v01 = src[y0 * srcWidth + x1];\n const v10 = src[y1 * srcWidth + x0];\n const v11 = src[y1 * srcWidth + x1];\n const top = v00 * (1 - wx) + v01 * wx;\n const bot = v10 * (1 - wx) + v11 * wx;\n out[y * targetWidth + x] = top * (1 - wy) + bot * wy;\n }\n }\n return out;\n}\n"],"mappings":"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"}
|
|
@@ -81,7 +81,7 @@ function i(e) {
|
|
|
81
81
|
}
|
|
82
82
|
var a = !1;
|
|
83
83
|
function o(e, t, n, i, o) {
|
|
84
|
-
return a || (a = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. The alias will be removed in 0.
|
|
84
|
+
return a || (a = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. The alias will be removed in 0.4.0.")), r(e, t, n, i, o);
|
|
85
85
|
}
|
|
86
86
|
function s(e, t, n, r, i) {
|
|
87
87
|
let a = new Float32Array(r * i);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segmentation.js","names":[],"sources":["../../../src/vision/postprocess/segmentation.ts"],"sourcesContent":["/**\n * Segmentation head postprocessing: YOLO instance-segmentation decoding.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg exports (and any later seg head\n * sharing the layout). The model produces two output tensors:\n *\n * - `output0` of shape `(1, 4 + numClasses + numMaskCoefs, numAnchors)` — the\n * same per-anchor predictions as plain YOLO detection plus an extra\n * `numMaskCoefs` (typically 32) channels of mask coefficients.\n * - `output1` of shape `(1, numMaskCoefs, maskH, maskW)` — a set of \"prototype\"\n * masks shared across all anchors.\n *\n * The per-anchor decode (xywh→xyxy, undo letterbox, per-class NMS, sort & cap)\n * is delegated to {@link decodeYoloAnchors}; this module only handles the\n * mask-specific work: matmul against prototypes, sigmoid, bilinear resize and\n * thresholding.\n */\n\nimport { decodeYoloAnchors } from \"./detection\";\nimport { BoundingBox, Mask } from \"../types\";\n\nexport interface DecodeYoloSegOptions {\n readonly numClasses: number;\n /** Model input `[width, height]` (post-letterbox). */\n readonly inputWidth: number;\n readonly inputHeight: number;\n /** Original image `[width, height]`. */\n readonly originalWidth: number;\n readonly originalHeight: number;\n /** Letterbox horizontal padding in input-tensor pixels. */\n readonly padLeft: number;\n /** Letterbox vertical padding in input-tensor pixels. */\n readonly padTop: number;\n /** Letterbox scale factor. */\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n /** Probability cutoff applied to the soft mask. Defaults to `0.5`. */\n readonly maskThreshold?: number;\n}\n\nexport interface DecodedSegmentation {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n /** Binary mask cropped to `bbox`. Width/height match `bbox.asIntXyxy()` extents. */\n readonly mask: Mask;\n}\n\n/**\n * Decode YOLO segmentation raw outputs into a list of segmented instances.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg.\n *\n * @param perAnchorData Flat `output0`, length `(4 + numClasses + numMaskCoefs) * numAnchors`.\n * @param perAnchorDims Dims as reported by ORT, e.g. `[1, 116, 8400]`.\n * @param prototypeData Flat `output1`, length `numMaskCoefs * maskH * maskW`.\n * @param prototypeDims Dims as reported by ORT, e.g. `[1, 32, 160, 160]`.\n */\nexport function decodeYoloSeg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n // Strip batch dim from prototypes; perAnchor batch is validated by the helper.\n let pDims = prototypeDims;\n if (pDims.length === 4) {\n if (pDims[0] !== 1) {\n throw new Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${pDims[0]}.`);\n }\n pDims = [pDims[1] as number, pDims[2] as number, pDims[3] as number];\n }\n if (pDims.length !== 3) {\n throw new Error(\n `decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n const numMaskCoefs = pDims[0] as number;\n const maskH = pDims[1] as number;\n const maskW = pDims[2] as number;\n\n const channels = perAnchorDims.length === 3 ? perAnchorDims[1] : perAnchorDims[0];\n const numAnchors = perAnchorDims.length === 3 ? perAnchorDims[2] : perAnchorDims[1];\n if (channels === undefined || numAnchors === undefined) {\n throw new Error(\n `decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(perAnchorDims)}.`,\n );\n }\n\n const expectedChannels = 4 + options.numClasses + numMaskCoefs;\n if (channels !== expectedChannels) {\n throw new Error(\n `decodeYoloSeg: channels=${channels} does not match 4 + numClasses(${options.numClasses}) + numMaskCoefs(${numMaskCoefs}) = ${expectedChannels}.`,\n );\n }\n if (prototypeData.length !== numMaskCoefs * maskH * maskW) {\n throw new Error(\n `decodeYoloSeg: prototype length ${prototypeData.length} does not match dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n\n const decoded = decodeYoloAnchors(perAnchorData, perAnchorDims, {\n numClasses: options.numClasses,\n originalWidth: options.originalWidth,\n originalHeight: options.originalHeight,\n padLeft: options.padLeft,\n padTop: options.padTop,\n scale: options.scale,\n confThreshold: options.confThreshold,\n iouThreshold: options.iouThreshold,\n maxDetections: options.maxDetections,\n });\n\n if (decoded.anchorIndices.length === 0) return [];\n\n const maskThreshold = options.maskThreshold ?? 0.5;\n const scaleX = maskW / options.inputWidth;\n const scaleY = maskH / options.inputHeight;\n const protoPlane = maskH * maskW;\n const coefBase = (4 + options.numClasses) * numAnchors;\n\n const results: DecodedSegmentation[] = [];\n\n for (let i = 0; i < decoded.anchorIndices.length; i++) {\n const a = decoded.anchorIndices[i] as number;\n const x1 = decoded.boxesXyxy[i * 4] as number;\n const y1 = decoded.boxesXyxy[i * 4 + 1] as number;\n const x2 = decoded.boxesXyxy[i * 4 + 2] as number;\n const y2 = decoded.boxesXyxy[i * 4 + 3] as number;\n const bbox = new BoundingBox(x1, y1, x2, y2);\n const classId = decoded.classIds[i] as number;\n const confidence = decoded.confidences[i] as number;\n\n const bboxW = Math.max(0, Math.trunc(x2) - Math.trunc(x1));\n const bboxH = Math.max(0, Math.trunc(y2) - Math.trunc(y1));\n\n if (bboxW === 0 || bboxH === 0) {\n results.push({ bbox, classId, confidence, mask: new Mask(new Uint8Array(0), 0, 0) });\n continue;\n }\n\n // Bbox in input-tensor coords, then in low-res mask coords.\n const ibx1 = x1 * options.scale + options.padLeft;\n const iby1 = y1 * options.scale + options.padTop;\n const ibx2 = x2 * options.scale + options.padLeft;\n const iby2 = y2 * options.scale + options.padTop;\n\n const mbx1 = Math.max(0, Math.floor(ibx1 * scaleX));\n const mby1 = Math.max(0, Math.floor(iby1 * scaleY));\n const mbx2 = Math.min(maskW, Math.ceil(ibx2 * scaleX));\n const mby2 = Math.min(maskH, Math.ceil(iby2 * scaleY));\n\n if (mbx2 <= mbx1 || mby2 <= mby1) {\n results.push({\n bbox,\n classId,\n confidence,\n mask: new Mask(new Uint8Array(bboxW * bboxH), bboxW, bboxH),\n });\n continue;\n }\n\n // Compute soft mask only within the prototype region under this bbox.\n const cropW = mbx2 - mbx1;\n const cropH = mby2 - mby1;\n const softCrop = new Float32Array(cropW * cropH);\n for (let y = 0; y < cropH; y++) {\n const py = mby1 + y;\n for (let x = 0; x < cropW; x++) {\n const px = mbx1 + x;\n let sum = 0;\n for (let kk = 0; kk < numMaskCoefs; kk++) {\n const coef = perAnchorData[coefBase + kk * numAnchors + a];\n const proto = prototypeData[kk * protoPlane + py * maskW + px];\n sum += coef * proto;\n }\n softCrop[y * cropW + x] = sigmoid(sum);\n }\n }\n\n const resized = resizeBilinear(softCrop, cropW, cropH, bboxW, bboxH);\n const binary = new Uint8Array(bboxW * bboxH);\n for (let j = 0; j < binary.length; j++) {\n binary[j] = resized[j] >= maskThreshold ? 255 : 0;\n }\n\n results.push({ bbox, classId, confidence, mask: new Mask(binary, bboxW, bboxH) });\n }\n\n return results;\n}\n\nfunction sigmoid(x: number): number {\n if (x >= 0) {\n return 1 / (1 + Math.exp(-x));\n }\n const e = Math.exp(x);\n return e / (1 + e);\n}\n\nlet _warnedDecodeYoloV8Seg = false;\n\n/** @deprecated since 0.2.0 — use {@link decodeYoloSeg}. Will be removed in 0.3.0. */\nexport function decodeYoloV8Seg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n if (!_warnedDecodeYoloV8Seg) {\n _warnedDecodeYoloV8Seg = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. \" +\n \"The alias will be removed in 0.3.0.\",\n );\n }\n return decodeYoloSeg(perAnchorData, perAnchorDims, prototypeData, prototypeDims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloSegOptions}. */\nexport type DecodeYoloV8SegOptions = DecodeYoloSegOptions;\n\nfunction resizeBilinear(\n src: Float32Array,\n srcWidth: number,\n srcHeight: number,\n targetWidth: number,\n targetHeight: number,\n): Float32Array {\n const out = new Float32Array(targetWidth * targetHeight);\n if (targetWidth === 0 || targetHeight === 0 || srcWidth === 0 || srcHeight === 0) {\n return out;\n }\n if (targetWidth === srcWidth && targetHeight === srcHeight) {\n out.set(src);\n return out;\n }\n const sx = srcWidth / targetWidth;\n const sy = srcHeight / targetHeight;\n for (let y = 0; y < targetHeight; y++) {\n const yy = (y + 0.5) * sy - 0.5;\n const y0 = Math.max(0, Math.floor(yy));\n const y1 = Math.min(srcHeight - 1, y0 + 1);\n const wy = Math.max(0, Math.min(1, yy - y0));\n for (let x = 0; x < targetWidth; x++) {\n const xx = (x + 0.5) * sx - 0.5;\n const x0 = Math.max(0, Math.floor(xx));\n const x1 = Math.min(srcWidth - 1, x0 + 1);\n const wx = Math.max(0, Math.min(1, xx - x0));\n const v00 = src[y0 * srcWidth + x0];\n const v01 = src[y0 * srcWidth + x1];\n const v10 = src[y1 * srcWidth + x0];\n const v11 = src[y1 * srcWidth + x1];\n const top = v00 * (1 - wx) + v01 * wx;\n const bot = v10 * (1 - wx) + v11 * wx;\n out[y * targetWidth + x] = top * (1 - wy) + bot * wy;\n }\n }\n return out;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"segmentation.js","names":[],"sources":["../../../src/vision/postprocess/segmentation.ts"],"sourcesContent":["/**\n * Segmentation head postprocessing: YOLO instance-segmentation decoding.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg exports (and any later seg head\n * sharing the layout). The model produces two output tensors:\n *\n * - `output0` of shape `(1, 4 + numClasses + numMaskCoefs, numAnchors)` — the\n * same per-anchor predictions as plain YOLO detection plus an extra\n * `numMaskCoefs` (typically 32) channels of mask coefficients.\n * - `output1` of shape `(1, numMaskCoefs, maskH, maskW)` — a set of \"prototype\"\n * masks shared across all anchors.\n *\n * The per-anchor decode (xywh→xyxy, undo letterbox, per-class NMS, sort & cap)\n * is delegated to {@link decodeYoloAnchors}; this module only handles the\n * mask-specific work: matmul against prototypes, sigmoid, bilinear resize and\n * thresholding.\n */\n\nimport { decodeYoloAnchors } from \"./detection\";\nimport { BoundingBox, Mask } from \"../types\";\n\nexport interface DecodeYoloSegOptions {\n readonly numClasses: number;\n /** Model input `[width, height]` (post-letterbox). */\n readonly inputWidth: number;\n readonly inputHeight: number;\n /** Original image `[width, height]`. */\n readonly originalWidth: number;\n readonly originalHeight: number;\n /** Letterbox horizontal padding in input-tensor pixels. */\n readonly padLeft: number;\n /** Letterbox vertical padding in input-tensor pixels. */\n readonly padTop: number;\n /** Letterbox scale factor. */\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n /** Probability cutoff applied to the soft mask. Defaults to `0.5`. */\n readonly maskThreshold?: number;\n}\n\nexport interface DecodedSegmentation {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n /** Binary mask cropped to `bbox`. Width/height match `bbox.asIntXyxy()` extents. */\n readonly mask: Mask;\n}\n\n/**\n * Decode YOLO segmentation raw outputs into a list of segmented instances.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg.\n *\n * @param perAnchorData Flat `output0`, length `(4 + numClasses + numMaskCoefs) * numAnchors`.\n * @param perAnchorDims Dims as reported by ORT, e.g. `[1, 116, 8400]`.\n * @param prototypeData Flat `output1`, length `numMaskCoefs * maskH * maskW`.\n * @param prototypeDims Dims as reported by ORT, e.g. `[1, 32, 160, 160]`.\n */\nexport function decodeYoloSeg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n // Strip batch dim from prototypes; perAnchor batch is validated by the helper.\n let pDims = prototypeDims;\n if (pDims.length === 4) {\n if (pDims[0] !== 1) {\n throw new Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${pDims[0]}.`);\n }\n pDims = [pDims[1] as number, pDims[2] as number, pDims[3] as number];\n }\n if (pDims.length !== 3) {\n throw new Error(\n `decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n const numMaskCoefs = pDims[0] as number;\n const maskH = pDims[1] as number;\n const maskW = pDims[2] as number;\n\n const channels = perAnchorDims.length === 3 ? perAnchorDims[1] : perAnchorDims[0];\n const numAnchors = perAnchorDims.length === 3 ? perAnchorDims[2] : perAnchorDims[1];\n if (channels === undefined || numAnchors === undefined) {\n throw new Error(\n `decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(perAnchorDims)}.`,\n );\n }\n\n const expectedChannels = 4 + options.numClasses + numMaskCoefs;\n if (channels !== expectedChannels) {\n throw new Error(\n `decodeYoloSeg: channels=${channels} does not match 4 + numClasses(${options.numClasses}) + numMaskCoefs(${numMaskCoefs}) = ${expectedChannels}.`,\n );\n }\n if (prototypeData.length !== numMaskCoefs * maskH * maskW) {\n throw new Error(\n `decodeYoloSeg: prototype length ${prototypeData.length} does not match dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n\n const decoded = decodeYoloAnchors(perAnchorData, perAnchorDims, {\n numClasses: options.numClasses,\n originalWidth: options.originalWidth,\n originalHeight: options.originalHeight,\n padLeft: options.padLeft,\n padTop: options.padTop,\n scale: options.scale,\n confThreshold: options.confThreshold,\n iouThreshold: options.iouThreshold,\n maxDetections: options.maxDetections,\n });\n\n if (decoded.anchorIndices.length === 0) return [];\n\n const maskThreshold = options.maskThreshold ?? 0.5;\n const scaleX = maskW / options.inputWidth;\n const scaleY = maskH / options.inputHeight;\n const protoPlane = maskH * maskW;\n const coefBase = (4 + options.numClasses) * numAnchors;\n\n const results: DecodedSegmentation[] = [];\n\n for (let i = 0; i < decoded.anchorIndices.length; i++) {\n const a = decoded.anchorIndices[i] as number;\n const x1 = decoded.boxesXyxy[i * 4] as number;\n const y1 = decoded.boxesXyxy[i * 4 + 1] as number;\n const x2 = decoded.boxesXyxy[i * 4 + 2] as number;\n const y2 = decoded.boxesXyxy[i * 4 + 3] as number;\n const bbox = new BoundingBox(x1, y1, x2, y2);\n const classId = decoded.classIds[i] as number;\n const confidence = decoded.confidences[i] as number;\n\n const bboxW = Math.max(0, Math.trunc(x2) - Math.trunc(x1));\n const bboxH = Math.max(0, Math.trunc(y2) - Math.trunc(y1));\n\n if (bboxW === 0 || bboxH === 0) {\n results.push({ bbox, classId, confidence, mask: new Mask(new Uint8Array(0), 0, 0) });\n continue;\n }\n\n // Bbox in input-tensor coords, then in low-res mask coords.\n const ibx1 = x1 * options.scale + options.padLeft;\n const iby1 = y1 * options.scale + options.padTop;\n const ibx2 = x2 * options.scale + options.padLeft;\n const iby2 = y2 * options.scale + options.padTop;\n\n const mbx1 = Math.max(0, Math.floor(ibx1 * scaleX));\n const mby1 = Math.max(0, Math.floor(iby1 * scaleY));\n const mbx2 = Math.min(maskW, Math.ceil(ibx2 * scaleX));\n const mby2 = Math.min(maskH, Math.ceil(iby2 * scaleY));\n\n if (mbx2 <= mbx1 || mby2 <= mby1) {\n results.push({\n bbox,\n classId,\n confidence,\n mask: new Mask(new Uint8Array(bboxW * bboxH), bboxW, bboxH),\n });\n continue;\n }\n\n // Compute soft mask only within the prototype region under this bbox.\n const cropW = mbx2 - mbx1;\n const cropH = mby2 - mby1;\n const softCrop = new Float32Array(cropW * cropH);\n for (let y = 0; y < cropH; y++) {\n const py = mby1 + y;\n for (let x = 0; x < cropW; x++) {\n const px = mbx1 + x;\n let sum = 0;\n for (let kk = 0; kk < numMaskCoefs; kk++) {\n const coef = perAnchorData[coefBase + kk * numAnchors + a];\n const proto = prototypeData[kk * protoPlane + py * maskW + px];\n sum += coef * proto;\n }\n softCrop[y * cropW + x] = sigmoid(sum);\n }\n }\n\n const resized = resizeBilinear(softCrop, cropW, cropH, bboxW, bboxH);\n const binary = new Uint8Array(bboxW * bboxH);\n for (let j = 0; j < binary.length; j++) {\n binary[j] = resized[j] >= maskThreshold ? 255 : 0;\n }\n\n results.push({ bbox, classId, confidence, mask: new Mask(binary, bboxW, bboxH) });\n }\n\n return results;\n}\n\nfunction sigmoid(x: number): number {\n if (x >= 0) {\n return 1 / (1 + Math.exp(-x));\n }\n const e = Math.exp(x);\n return e / (1 + e);\n}\n\nlet _warnedDecodeYoloV8Seg = false;\n\n/** @deprecated since 0.2.0 — use {@link decodeYoloSeg}. Will be removed in 0.4.0. */\nexport function decodeYoloV8Seg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n if (!_warnedDecodeYoloV8Seg) {\n _warnedDecodeYoloV8Seg = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. \" +\n \"The alias will be removed in 0.4.0.\",\n );\n }\n return decodeYoloSeg(perAnchorData, perAnchorDims, prototypeData, prototypeDims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloSegOptions}. */\nexport type DecodeYoloV8SegOptions = DecodeYoloSegOptions;\n\nfunction resizeBilinear(\n src: Float32Array,\n srcWidth: number,\n srcHeight: number,\n targetWidth: number,\n targetHeight: number,\n): Float32Array {\n const out = new Float32Array(targetWidth * targetHeight);\n if (targetWidth === 0 || targetHeight === 0 || srcWidth === 0 || srcHeight === 0) {\n return out;\n }\n if (targetWidth === srcWidth && targetHeight === srcHeight) {\n out.set(src);\n return out;\n }\n const sx = srcWidth / targetWidth;\n const sy = srcHeight / targetHeight;\n for (let y = 0; y < targetHeight; y++) {\n const yy = (y + 0.5) * sy - 0.5;\n const y0 = Math.max(0, Math.floor(yy));\n const y1 = Math.min(srcHeight - 1, y0 + 1);\n const wy = Math.max(0, Math.min(1, yy - y0));\n for (let x = 0; x < targetWidth; x++) {\n const xx = (x + 0.5) * sx - 0.5;\n const x0 = Math.max(0, Math.floor(xx));\n const x1 = Math.min(srcWidth - 1, x0 + 1);\n const wx = Math.max(0, Math.min(1, xx - x0));\n const v00 = src[y0 * srcWidth + x0];\n const v01 = src[y0 * srcWidth + x1];\n const v10 = src[y1 * srcWidth + x0];\n const v11 = src[y1 * srcWidth + x1];\n const top = v00 * (1 - wx) + v01 * wx;\n const bot = v10 * (1 - wx) + v11 * wx;\n out[y * targetWidth + x] = top * (1 - wy) + bot * wy;\n }\n }\n return out;\n}\n"],"mappings":"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"}
|
package/dist/vision/results.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=class{xyxy;cls;conf;origShape;constructor(e,t,n,r){this.xyxy=e,this.cls=t,this.conf=n,this.origShape=r}get length(){return this.cls.length}get shape(){return[this.length,4]}get xywh(){let e=new Float32Array(this.xyxy.length);for(let t=0;t<this.length;t++){let n=this.xyxy[t*4],r=this.xyxy[t*4+1],i=this.xyxy[t*4+2],a=this.xyxy[t*4+3];e[t*4]=(n+i)/2,e[t*4+1]=(r+a)/2,e[t*4+2]=i-n,e[t*4+3]=a-r}return e}get xyxyn(){let[e,t]=this.origShape,n=new Float32Array(this.xyxy.length);if(this.length===0||t<=0||e<=0)return n;for(let r=0;r<this.length;r++)n[r*4]=this.xyxy[r*4]/t,n[r*4+1]=this.xyxy[r*4+1]/e,n[r*4+2]=this.xyxy[r*4+2]/t,n[r*4+3]=this.xyxy[r*4+3]/e;return n}get xywhn(){let e=this.xywh,[t,n]=this.origShape;if(this.length===0||n<=0||t<=0)return e;for(let r=0;r<this.length;r++)e[r*4]=e[r*4]/n,e[r*4+1]=e[r*4+1]/t,e[r*4+2]=e[r*4+2]/n,e[r*4+3]=e[r*4+3]/t;return e}get data(){let e=new Float32Array(this.length*6);for(let t=0;t<this.length;t++)e[t*6]=this.xyxy[t*4],e[t*6+1]=this.xyxy[t*4+1],e[t*6+2]=this.xyxy[t*4+2],e[t*6+3]=this.xyxy[t*4+3],e[t*6+4]=this.conf[t],e[t*6+5]=this.cls[t];return e}},
|
|
1
|
+
var e={load:0,preprocess:0,inference:0,postprocess:0},t=class{xyxy;cls;conf;origShape;constructor(e,t,n,r){this.xyxy=e,this.cls=t,this.conf=n,this.origShape=r}get length(){return this.cls.length}get shape(){return[this.length,4]}get xywh(){let e=new Float32Array(this.xyxy.length);for(let t=0;t<this.length;t++){let n=this.xyxy[t*4],r=this.xyxy[t*4+1],i=this.xyxy[t*4+2],a=this.xyxy[t*4+3];e[t*4]=(n+i)/2,e[t*4+1]=(r+a)/2,e[t*4+2]=i-n,e[t*4+3]=a-r}return e}get xyxyn(){let[e,t]=this.origShape,n=new Float32Array(this.xyxy.length);if(this.length===0||t<=0||e<=0)return n;for(let r=0;r<this.length;r++)n[r*4]=this.xyxy[r*4]/t,n[r*4+1]=this.xyxy[r*4+1]/e,n[r*4+2]=this.xyxy[r*4+2]/t,n[r*4+3]=this.xyxy[r*4+3]/e;return n}get xywhn(){let e=this.xywh,[t,n]=this.origShape;if(this.length===0||n<=0||t<=0)return e;for(let r=0;r<this.length;r++)e[r*4]=e[r*4]/n,e[r*4+1]=e[r*4+1]/t,e[r*4+2]=e[r*4+2]/n,e[r*4+3]=e[r*4+3]/t;return e}get data(){let e=new Float32Array(this.length*6);for(let t=0;t<this.length;t++)e[t*6]=this.xyxy[t*4],e[t*6+1]=this.xyxy[t*4+1],e[t*6+2]=this.xyxy[t*4+2],e[t*6+3]=this.xyxy[t*4+3],e[t*6+4]=this.conf[t],e[t*6+5]=this.cls[t];return e}},n=class{data;constructor(e){this.data=e}get length(){return this.data.length}get shape(){return[this.length]}get top1(){if(this.data.length===0)return 0;let e=0,t=this.data[0];for(let n=1;n<this.data.length;n++){let r=this.data[n];r>t&&(e=n,t=r)}return e}get top1conf(){return this.data.length===0?0:this.data[this.top1]}get top5(){return this._topK(5).indices}get top5conf(){return this._topK(5).values}_topK(e){let t=Math.min(e,this.data.length),n=[];for(let e=0;e<this.data.length;e++)n.push(e);n.sort((e,t)=>this.data[t]-this.data[e]);let r=new Int32Array(t),i=new Float32Array(t);for(let e=0;e<t;e++)r[e]=n[e],i[e]=this.data[n[e]];return{indices:r,values:i}}},r=class{data;xyxy;origShape;constructor(e,t,n){this.data=e,this.xyxy=t,this.origShape=n}get length(){return this.data.length}get shape(){return[this.length]}[Symbol.iterator](){return this.data[Symbol.iterator]()}},i=class{boxes;detections;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o=null,s=e){this.boxes=t,this.detections=n,this.names=r,this.origImg=i,this.origShape=a,this.path=o,this.speed=s}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}},a=class{probs;result;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o=null,s=e){this.probs=t,this.result=n,this.names=r,this.origImg=i,this.origShape=a,this.path=o,this.speed=s}get cls(){return this.probs.top1}get conf(){return this.probs.top1conf}get name(){return this.names[this.cls]??`class_${this.cls}`}get probabilities(){return this.result.probabilities}},o=class{boxes;masks;detections;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o,s=null,c=e){this.boxes=t,this.masks=n,this.detections=r,this.names=i,this.origImg=a,this.origShape=o,this.path=s,this.speed=c}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}};exports.Boxes=t,exports.ClassificationResults=a,exports.DetectionResults=i,exports.Masks=r,exports.Probs=n,exports.SegmentationResults=o;
|
|
2
2
|
//# sourceMappingURL=results.cjs.map
|