tempest-react-sdk 0.69.0 → 0.71.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 +3 -3
- package/dist/telemetry/app-error-adapter.cjs +2 -0
- package/dist/telemetry/app-error-adapter.cjs.map +1 -0
- package/dist/telemetry/app-error-adapter.js +18 -0
- package/dist/telemetry/app-error-adapter.js.map +1 -0
- package/dist/telemetry/app-error-queue.cjs +2 -0
- package/dist/telemetry/app-error-queue.cjs.map +1 -0
- package/dist/telemetry/app-error-queue.js +42 -0
- package/dist/telemetry/app-error-queue.js.map +1 -0
- package/dist/telemetry/app-error-reporter.cjs +2 -0
- package/dist/telemetry/app-error-reporter.cjs.map +1 -0
- package/dist/telemetry/app-error-reporter.js +64 -0
- package/dist/telemetry/app-error-reporter.js.map +1 -0
- package/dist/telemetry/app-error-schema.cjs +2 -0
- package/dist/telemetry/app-error-schema.cjs.map +1 -0
- package/dist/telemetry/app-error-schema.js +28 -0
- package/dist/telemetry/app-error-schema.js.map +1 -0
- package/dist/telemetry/app-error-transport.cjs +2 -0
- package/dist/telemetry/app-error-transport.cjs.map +1 -0
- package/dist/telemetry/app-error-transport.js +44 -0
- package/dist/telemetry/app-error-transport.js.map +1 -0
- package/dist/telemetry/describe-app-error.cjs +3 -0
- package/dist/telemetry/describe-app-error.cjs.map +1 -0
- package/dist/telemetry/describe-app-error.js +54 -0
- package/dist/telemetry/describe-app-error.js.map +1 -0
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +214 -0
- package/dist/tempest-react-sdk.js +13 -10
- package/dist/vision/core/canvas.cjs +1 -1
- package/dist/vision/core/canvas.cjs.map +1 -1
- package/dist/vision/core/canvas.js +37 -13
- package/dist/vision/core/canvas.js.map +1 -1
- package/dist/vision/core/dtypes.cjs +2 -0
- package/dist/vision/core/dtypes.cjs.map +1 -0
- package/dist/vision/core/dtypes.js +33 -0
- package/dist/vision/core/dtypes.js.map +1 -0
- package/dist/vision/core/graph.cjs +1 -1
- package/dist/vision/core/graph.cjs.map +1 -1
- package/dist/vision/core/graph.js +10 -2
- package/dist/vision/core/graph.js.map +1 -1
- package/dist/vision/core/metadata.cjs +2 -2
- package/dist/vision/core/metadata.cjs.map +1 -1
- package/dist/vision/core/metadata.js +103 -13
- package/dist/vision/core/metadata.js.map +1 -1
- package/dist/vision/core/providers.cjs +1 -1
- package/dist/vision/core/providers.cjs.map +1 -1
- package/dist/vision/core/providers.js +9 -6
- package/dist/vision/core/providers.js.map +1 -1
- package/dist/vision/core/session.cjs +1 -1
- package/dist/vision/core/session.cjs.map +1 -1
- package/dist/vision/core/session.js +115 -27
- package/dist/vision/core/session.js.map +1 -1
- package/dist/vision/fusion.cjs +1 -1
- package/dist/vision/fusion.cjs.map +1 -1
- package/dist/vision/fusion.js +28 -23
- package/dist/vision/fusion.js.map +1 -1
- package/dist/vision/index.cjs +1 -1
- package/dist/vision/index.cjs.map +1 -1
- package/dist/vision/index.js +20 -19
- package/dist/vision/index.js.map +1 -1
- package/dist/vision/io/image.cjs +1 -1
- package/dist/vision/io/image.cjs.map +1 -1
- package/dist/vision/io/image.js +55 -20
- package/dist/vision/io/image.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 +42 -51
- 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 +45 -31
- package/dist/vision/postprocess/segmentation.js.map +1 -1
- package/dist/vision/preprocess/pipeline.cjs +1 -1
- package/dist/vision/preprocess/pipeline.cjs.map +1 -1
- package/dist/vision/preprocess/pipeline.js +24 -25
- package/dist/vision/preprocess/pipeline.js.map +1 -1
- package/dist/vision/tasks/base.cjs +1 -1
- package/dist/vision/tasks/base.cjs.map +1 -1
- package/dist/vision/tasks/base.js +22 -7
- package/dist/vision/tasks/base.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 +64 -55
- package/dist/vision/tasks/classifier.js.map +1 -1
- package/dist/vision/tasks/detectClassify.cjs +1 -1
- package/dist/vision/tasks/detectClassify.cjs.map +1 -1
- package/dist/vision/tasks/detectClassify.js +80 -69
- package/dist/vision/tasks/detectClassify.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 +74 -68
- 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 +85 -62
- package/dist/vision/tasks/segmenter.js.map +1 -1
- package/dist/vision/types.cjs +1 -1
- package/dist/vision/types.cjs.map +1 -1
- package/dist/vision/types.js +24 -4
- package/dist/vision/types.js.map +1 -1
- package/dist/vision.cjs +1 -1
- package/dist/vision.d.ts +1153 -777
- package/dist/vision.js +22 -21
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fusion.cjs","names":[],"sources":["../../src/vision/fusion.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * The contract a fused pipeline carries inside its own `.onnx` file.\n *\n * A pipeline built by the Python SDK's `ort_vision_sdk.compose` is a single\n * graph that already contains the detector, the crop-and-resize bridge and the\n * classifier. Everything the runtime needs to drive it — the letterbox\n * resolution, the crop resolution, where the crops come from, how many\n * detections the graph emits, the class names of both stages — was decided at\n * fusion time and written into the model's metadata.\n *\n * This module reads it back. It is the browser half of a contract whose other\n * half lives in `ort_vision_sdk/fusion.py`: the same keys, the same encodings,\n * the same fallbacks. A pipeline fused once therefore runs identically in\n * Python and in a browser tab, off the same file.\n *\n * Building a pipeline stays a Python-side build step — there is no ONNX\n * protobuf writer here, and there is no reason for one: fusing is something you\n * do once next to your export pipeline, not in a page load.\n */\n\nimport { parseNames } from \"./core/metadata\";\n\n/**\n * Which tensor the bridge crops the detected boxes out of.\n *\n * - `\"detector_input\"`: the letterboxed tensor already fed to the detector.\n * The fused graph then has a **single** image input, but a small object is\n * cropped out of its downscaled copy.\n * - `\"original\"`: a second, full-resolution image input. The bridge undoes the\n * letterbox transform in-graph and crops at native resolution. Two tensors to\n * feed, still one session and one model load.\n */\nexport type CropSource = \"detector_input\" | \"original\";\n\n/** Value of the `ovs.kind` metadata key for a detector→classifier pipeline. */\nexport const FUSION_KIND_DETECT_CLASSIFY = \"detect_classify\";\n\n/**\n * Namespace for every metadata key the fusion writes.\n *\n * Namespaced on purpose: the detector's own Ultralytics metadata (`names`,\n * `task`, `imgsz`) is carried over into the fused model, and an un-prefixed key\n * would either collide with it or be mistaken for it.\n */\nexport const METADATA_PREFIX = \"ovs.\";\n\n/** Name of the fused graph's letterboxed detector input, `[1, 3, H, W]` float32 in `[0, 1]`. */\nexport const INPUT_IMAGE = \"images\";\n\n/** Name of the full-resolution input. Present only when `cropSource === \"original\"`. */\nexport const INPUT_SOURCE = \"source_image\";\n\n/** Name of the `[1]` float32 letterbox scale factor. Only with `cropSource === \"original\"`. */\nexport const INPUT_SCALE = \"letterbox_scale\";\n\n/** Name of the `[2]` float32 `[padLeft, padTop]`. Only with `cropSource === \"original\"`. */\nexport const INPUT_PAD = \"letterbox_pad\";\n\n/**\n * Name of the `[K, 4]` float32 xyxy output, in **letterboxed** input pixels.\n *\n * A file fused by `ort-vision-sdk` 0.9.0 or later reports the box that was\n * actually classified: clamped to the image the crop came from, exactly as\n * RoiAlign received it. Older files report the raw box, so one that ran off the\n * frame draws a rectangle wider than the region the classifier saw.\n */\nexport const OUTPUT_BOXES = \"boxes\";\n\n/** Name of the `[K]` float32 detection-confidence output. */\nexport const OUTPUT_SCORES = \"scores\";\n\n/** Name of the `[K]` int64 detector-class output. */\nexport const OUTPUT_CLASSES = \"classes\";\n\n/** Name of the `[1]` int64 output holding how many of the `K` rows are real. */\nexport const OUTPUT_NUM_DETECTIONS = \"num_detections\";\n\n/** Name of the `[K, numClassifierClasses]` float32 classifier output, one row per box. */\nexport const OUTPUT_PROBS = \"probs\";\n\n/** Everything a fused pipeline declares about how it must be driven. */\nexport interface FusionSpec {\n /** Pipeline family. Only `\"detect_classify\"` exists today. */\n readonly kind: string;\n /** `[width, height]` the detector stage expects — the resolution to letterbox to. */\n readonly inputSize: readonly [number, number];\n /** `[width, height]` every crop is resampled to inside the graph. */\n readonly cropSize: readonly [number, number];\n /** Which tensor the crops are taken from. */\n readonly cropSource: CropSource;\n /**\n * Fixed number of rows `K` every output carries, surplus zero-padded and\n * counted by {@link OUTPUT_NUM_DETECTIONS}. `null` means the graph emits\n * exactly as many rows as survived NMS.\n */\n readonly maxDetections: number | null;\n /** Score threshold baked into the graph's NMS node. */\n readonly confThreshold: number;\n /** IoU threshold baked into the graph's NMS node. */\n readonly iouThreshold: number;\n /** Whether the classifier stage emits logits that still need a softmax. */\n readonly applySoftmax: boolean;\n /** Detector class names in class-id order, or `null` when the fusion recorded none. */\n readonly detectorNames: readonly string[] | null;\n /** Classifier class names in class-id order, or `null`. */\n readonly classifierNames: readonly string[] | null;\n /** Version of `ort-vision-sdk` that produced the file. */\n readonly sdkVersion: string;\n /** Whether driving this pipeline requires feeding the full-resolution input. */\n readonly needsSourceImage: boolean;\n}\n\nconst KEY_KIND = \"kind\";\nconst KEY_SDK_VERSION = \"sdk_version\";\nconst KEY_INPUT_SIZE = \"input_size\";\nconst KEY_CROP_SIZE = \"crop_size\";\nconst KEY_CROP_SOURCE = \"crop_source\";\nconst KEY_MAX_DETECTIONS = \"max_detections\";\nconst KEY_CONF_THRESHOLD = \"conf_threshold\";\nconst KEY_IOU_THRESHOLD = \"iou_threshold\";\nconst KEY_APPLY_SOFTMAX = \"apply_softmax\";\nconst KEY_DETECTOR_NAMES = \"detector_names\";\nconst KEY_CLASSIFIER_NAMES = \"classifier_names\";\n\nconst DYNAMIC = \"dynamic\";\n\n/**\n * Decode a `\"640,640\"` pair.\n *\n * @param raw The encoded pair.\n * @returns `[width, height]`, or `null` when the value is missing or malformed.\n */\nfunction decodeSize(raw: string | undefined): readonly [number, number] | null {\n if (!raw) return null;\n const parts = raw.split(\",\");\n if (parts.length !== 2) return null;\n const width = Number(parts[0]);\n const height = Number(parts[1]);\n if (!Number.isInteger(width) || !Number.isInteger(height)) return null;\n if (width < 1 || height < 1) return null;\n return [width, height];\n}\n\n/**\n * Decode a float, falling back when the value is missing or malformed.\n *\n * @param raw The encoded value.\n * @param fallback Value to use when `raw` cannot be read.\n * @returns The parsed number, or `fallback`.\n */\nfunction decodeFloat(raw: string | undefined, fallback: number): number {\n if (!raw) return fallback;\n const value = Number(raw);\n return Number.isFinite(value) ? value : fallback;\n}\n\n/**\n * Read a pipeline spec out of a model's custom metadata.\n *\n * Individual malformed entries fall back to the value a fusion would have used\n * by default — a single bad float is not a reason to reject an otherwise\n * loadable pipeline. A malformed resolution is fatal, because there is no safe\n * default for one.\n *\n * @param metadata A model's custom metadata map, as read by\n * {@link readModelMetadata}.\n * @returns The decoded spec, or `null` when the model is not a fused pipeline —\n * it carries no `ovs.kind` entry, or one naming a pipeline kind this version\n * does not know how to drive.\n */\nexport function readFusionSpec(\n metadata: Readonly<Record<string, string>> | undefined,\n): FusionSpec | null {\n if (!metadata) return null;\n\n const read: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata)) {\n if (key.startsWith(METADATA_PREFIX)) read[key.slice(METADATA_PREFIX.length)] = value;\n }\n if (read[KEY_KIND] !== FUSION_KIND_DETECT_CLASSIFY) return null;\n\n const inputSize = decodeSize(read[KEY_INPUT_SIZE]);\n const cropSize = decodeSize(read[KEY_CROP_SIZE]);\n if (inputSize === null || cropSize === null) return null;\n\n const rawMax = read[KEY_MAX_DETECTIONS] ?? DYNAMIC;\n const parsedMax = Number(rawMax);\n const maxDetections =\n rawMax === DYNAMIC || !Number.isInteger(parsedMax) || parsedMax < 1 ? null : parsedMax;\n\n const cropSource: CropSource =\n read[KEY_CROP_SOURCE] === \"original\" ? \"original\" : \"detector_input\";\n\n return {\n kind: FUSION_KIND_DETECT_CLASSIFY,\n inputSize,\n cropSize,\n cropSource,\n maxDetections,\n confThreshold: decodeFloat(read[KEY_CONF_THRESHOLD], 0.25),\n iouThreshold: decodeFloat(read[KEY_IOU_THRESHOLD], 0.45),\n applySoftmax: (read[KEY_APPLY_SOFTMAX] ?? \"1\") !== \"0\",\n detectorNames: parseNames(read[KEY_DETECTOR_NAMES]),\n classifierNames: parseNames(read[KEY_CLASSIFIER_NAMES]),\n sdkVersion: read[KEY_SDK_VERSION] ?? \"\",\n needsSourceImage: cropSource === \"original\",\n };\n}\n"],"mappings":"uCAoCA,IAAa,EAA8B,kBAS9B,EAAkB,OAGlB,EAAc,SAGd,EAAe,eAGf,EAAc,kBAGd,EAAY,gBAUZ,EAAe,QAGf,EAAgB,SAGhB,EAAiB,UAGjB,EAAwB,iBAGxB,EAAe,QAkCtB,EAAW,OACX,EAAkB,cAClB,EAAiB,aACjB,EAAgB,YAChB,EAAkB,cAClB,EAAqB,iBACrB,EAAqB,iBACrB,EAAoB,gBACpB,EAAoB,gBACpB,EAAqB,iBACrB,EAAuB,mBAEvB,EAAU,UAQhB,SAAS,EAAW,EAA2D,CAC3E,GAAI,CAAC,EAAK,OAAO,KACjB,IAAM,EAAQ,EAAI,MAAM,GAAG,EAC3B,GAAI,EAAM,SAAW,EAAG,OAAO,KAC/B,IAAM,EAAQ,OAAO,EAAM,EAAE,EACvB,EAAS,OAAO,EAAM,EAAE,EAG9B,MAFI,CAAC,OAAO,UAAU,CAAK,GAAK,CAAC,OAAO,UAAU,CAAM,GACpD,EAAQ,GAAK,EAAS,EAAU,KAC7B,CAAC,EAAO,CAAM,CACzB,CASA,SAAS,EAAY,EAAyB,EAA0B,CACpE,GAAI,CAAC,EAAK,OAAO,EACjB,IAAM,EAAQ,OAAO,CAAG,EACxB,OAAO,OAAO,SAAS,CAAK,EAAI,EAAQ,CAC5C,CAgBA,SAAgB,EACZ,EACiB,CACjB,GAAI,CAAC,EAAU,OAAO,KAEtB,IAAM,EAA+B,CAAC,EACtC,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAQ,EAC1C,EAAI,WAAA,MAA0B,IAAG,EAAK,EAAI,MAAM,CAAsB,GAAK,GAEnF,GAAI,EAAK,KAAA,kBAA2C,OAAO,KAE3D,IAAM,EAAY,EAAW,EAAK,EAAe,EAC3C,EAAW,EAAW,EAAK,EAAc,EAC/C,GAAI,IAAc,MAAQ,IAAa,KAAM,OAAO,KAEpD,IAAM,EAAS,EAAK,IAAuB,EACrC,EAAY,OAAO,CAAM,EACzB,EACF,IAAW,GAAW,CAAC,OAAO,UAAU,CAAS,GAAK,EAAY,EAAI,KAAO,EAE3E,EACF,EAAK,KAAqB,WAAa,WAAa,iBAExD,MAAO,CACH,KAAM,EACN,YACA,WACA,aACA,gBACA,cAAe,EAAY,EAAK,GAAqB,GAAI,EACzD,aAAc,EAAY,EAAK,GAAoB,GAAI,EACvD,cAAe,EAAK,IAAsB,OAAS,IACnD,cAAe,EAAA,WAAW,EAAK,EAAmB,EAClD,gBAAiB,EAAA,WAAW,EAAK,EAAqB,EACtD,WAAY,EAAK,IAAoB,GACrC,iBAAkB,IAAe,UACrC,CACJ"}
|
|
1
|
+
{"version":3,"file":"fusion.cjs","names":[],"sources":["../../src/vision/fusion.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * The contract a fused pipeline carries inside its own `.onnx` file.\n *\n * A pipeline built by the Python SDK's `ort_vision_sdk.compose` is a single\n * graph that already contains the detector, the crop-and-resize bridge and the\n * classifier. Everything the runtime needs to drive it — the letterbox\n * resolution, the crop resolution, where the crops come from, how many\n * detections the graph emits, the class names of both stages — was decided at\n * fusion time and written into the model's metadata.\n *\n * This module reads it back. It is the browser half of a contract whose other\n * half lives in `ort_vision_sdk/fusion.py`: the same keys, the same encodings,\n * the same fallbacks. A pipeline fused once therefore runs identically in\n * Python and in a browser tab, off the same file.\n *\n * Building a pipeline stays a Python-side build step — there is no ONNX\n * protobuf writer here, and there is no reason for one: fusing is something you\n * do once next to your export pipeline, not in a page load.\n */\n\nimport { parseNames } from \"./core/metadata\";\n\n/**\n * Which tensor the bridge crops the detected boxes out of.\n *\n * - `\"detector_input\"`: the letterboxed tensor already fed to the detector.\n * The fused graph then has a **single** image input, but a small object is\n * cropped out of its downscaled copy.\n * - `\"original\"`: a second, full-resolution image input. The bridge undoes the\n * letterbox transform in-graph and crops at native resolution. Two tensors to\n * feed, still one session and one model load.\n */\nexport type CropSource = \"detector_input\" | \"original\";\n\n/** Value of the `ovs.kind` metadata key for a detector→classifier pipeline. */\nexport const FUSION_KIND_DETECT_CLASSIFY = \"detect_classify\";\n\n/**\n * Value of `ovs.kind` for a detector→segmenter→classifier pipeline.\n *\n * The segmenter runs inside each crop rather than over the whole frame: the\n * detector finds the boxes, the bridge cuts them out, and the segmenter turns\n * each crop into a foreground mask that gates the pixels the classifier sees.\n * Fusing one is a build step on the Python side; the browser only loads the\n * result.\n */\nexport const FUSION_KIND_DETECT_SEGMENT_CLASSIFY = \"detect_segment_classify\";\n\n/**\n * Namespace for every metadata key the fusion writes.\n *\n * Namespaced on purpose: the detector's own Ultralytics metadata (`names`,\n * `task`, `imgsz`) is carried over into the fused model, and an un-prefixed key\n * would either collide with it or be mistaken for it.\n */\nexport const METADATA_PREFIX = \"ovs.\";\n\n/** Name of the fused graph's letterboxed detector input, `[1, 3, H, W]` float32 in `[0, 1]`. */\nexport const INPUT_IMAGE = \"images\";\n\n/** Name of the full-resolution input. Present only when `cropSource === \"original\"`. */\nexport const INPUT_SOURCE = \"source_image\";\n\n/** Name of the `[1]` float32 letterbox scale factor. Only with `cropSource === \"original\"`. */\nexport const INPUT_SCALE = \"letterbox_scale\";\n\n/** Name of the `[2]` float32 `[padLeft, padTop]`. Only with `cropSource === \"original\"`. */\nexport const INPUT_PAD = \"letterbox_pad\";\n\n/**\n * Name of the `[K, 4]` float32 xyxy output, in **letterboxed** input pixels.\n *\n * A file fused by `ort-vision-sdk` 0.9.0 or later reports the box that was\n * actually classified: clamped to the image the crop came from, exactly as\n * RoiAlign received it. Older files report the raw box, so one that ran off the\n * frame draws a rectangle wider than the region the classifier saw.\n */\nexport const OUTPUT_BOXES = \"boxes\";\n\n/** Name of the `[K]` float32 detection-confidence output. */\nexport const OUTPUT_SCORES = \"scores\";\n\n/** Name of the `[K]` int64 detector-class output. */\nexport const OUTPUT_CLASSES = \"classes\";\n\n/** Name of the `[1]` int64 output holding how many of the `K` rows are real. */\nexport const OUTPUT_NUM_DETECTIONS = \"num_detections\";\n\n/** Name of the `[K, numClassifierClasses]` float32 classifier output, one row per box. */\n/**\n * Name of the `(K, 1, cropH, cropW)` float32 mask output. Only on a\n * `detect_segment_classify` pipeline.\n *\n * The mask lives in the **crop's** coordinate space, not the original image's,\n * because that is where the segmenter computed it. Values are 0 or 1 after\n * thresholding; padded rows are all-zero, like every other output.\n */\nexport const OUTPUT_MASKS = \"masks\";\n\nexport const OUTPUT_PROBS = \"probs\";\n\n/** Everything a fused pipeline declares about how it must be driven. */\nexport interface FusionSpec {\n /** Pipeline family — {@link FUSION_KIND_DETECT_CLASSIFY} or {@link FUSION_KIND_DETECT_SEGMENT_CLASSIFY}. */\n readonly kind: string;\n /** `[width, height]` the detector stage expects — the resolution to letterbox to. */\n readonly inputSize: readonly [number, number];\n /** `[width, height]` every crop is resampled to inside the graph. */\n readonly cropSize: readonly [number, number];\n /** Which tensor the crops are taken from. */\n readonly cropSource: CropSource;\n /**\n * Fixed number of rows `K` every output carries, surplus zero-padded and\n * counted by {@link OUTPUT_NUM_DETECTIONS}. `null` means the graph emits\n * exactly as many rows as survived NMS.\n */\n readonly maxDetections: number | null;\n /** Score threshold baked into the graph's NMS node. */\n readonly confThreshold: number;\n /** IoU threshold baked into the graph's NMS node. */\n readonly iouThreshold: number;\n /** Whether the classifier stage emits logits that still need a softmax. */\n readonly applySoftmax: boolean;\n /** Detector class names in class-id order, or `null` when the fusion recorded none. */\n readonly detectorNames: readonly string[] | null;\n /** Classifier class names in class-id order, or `null`. */\n readonly classifierNames: readonly string[] | null;\n /** Version of `ort-vision-sdk` that produced the file. */\n readonly sdkVersion: string;\n /** Whether driving this pipeline requires feeding the full-resolution input. */\n readonly needsSourceImage: boolean;\n /** Whether this pipeline emits a {@link OUTPUT_MASKS} tensor. */\n readonly hasMasks: boolean;\n /** Class id → name for the segmenter's channels, or `null`. */\n readonly segmenterNames: readonly string[] | null;\n /**\n * Probability above which a segmenter pixel counted as foreground.\n *\n * Baked into the graph at fusion time; reported so a caller can say what the\n * masks mean.\n */\n readonly maskThreshold: number;\n /** Whether the mask gated the crop before the classifier saw it. */\n readonly maskApplied: boolean;\n}\n\nconst KEY_KIND = \"kind\";\nconst KEY_SDK_VERSION = \"sdk_version\";\nconst KEY_INPUT_SIZE = \"input_size\";\nconst KEY_CROP_SIZE = \"crop_size\";\nconst KEY_CROP_SOURCE = \"crop_source\";\nconst KEY_MAX_DETECTIONS = \"max_detections\";\nconst KEY_CONF_THRESHOLD = \"conf_threshold\";\nconst KEY_IOU_THRESHOLD = \"iou_threshold\";\nconst KEY_APPLY_SOFTMAX = \"apply_softmax\";\nconst KEY_DETECTOR_NAMES = \"detector_names\";\nconst KEY_CLASSIFIER_NAMES = \"classifier_names\";\nconst KEY_SEGMENTER_NAMES = \"segmenter_names\";\nconst KEY_MASK_THRESHOLD = \"mask_threshold\";\nconst KEY_MASK_APPLIED = \"mask_applied\";\n\nconst DYNAMIC = \"dynamic\";\n\n/**\n * Decode a `\"640,640\"` pair.\n *\n * @param raw The encoded pair.\n * @returns `[width, height]`, or `null` when the value is missing or malformed.\n */\nfunction decodeSize(raw: string | undefined): readonly [number, number] | null {\n if (!raw) return null;\n const parts = raw.split(\",\");\n if (parts.length !== 2) return null;\n const width = Number(parts[0]);\n const height = Number(parts[1]);\n if (!Number.isInteger(width) || !Number.isInteger(height)) return null;\n if (width < 1 || height < 1) return null;\n return [width, height];\n}\n\n/**\n * Decode a float, falling back when the value is missing or malformed.\n *\n * @param raw The encoded value.\n * @param fallback Value to use when `raw` cannot be read.\n * @returns The parsed number, or `fallback`.\n */\nfunction decodeFloat(raw: string | undefined, fallback: number): number {\n if (!raw) return fallback;\n const value = Number(raw);\n return Number.isFinite(value) ? value : fallback;\n}\n\n/**\n * Read a pipeline spec out of a model's custom metadata.\n *\n * Individual malformed entries fall back to the value a fusion would have used\n * by default — a single bad float is not a reason to reject an otherwise\n * loadable pipeline. A malformed resolution is fatal, because there is no safe\n * default for one.\n *\n * @param metadata A model's custom metadata map, as read by\n * {@link readModelMetadata}.\n * @returns The decoded spec, or `null` when the model is not a fused pipeline —\n * it carries no `ovs.kind` entry, or one naming a pipeline kind this version\n * does not know how to drive.\n */\nexport function readFusionSpec(\n metadata: Readonly<Record<string, string>> | undefined,\n): FusionSpec | null {\n if (!metadata) return null;\n\n const read: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata)) {\n if (key.startsWith(METADATA_PREFIX)) read[key.slice(METADATA_PREFIX.length)] = value;\n }\n const kind = read[KEY_KIND];\n if (kind !== FUSION_KIND_DETECT_CLASSIFY && kind !== FUSION_KIND_DETECT_SEGMENT_CLASSIFY) {\n return null;\n }\n\n const inputSize = decodeSize(read[KEY_INPUT_SIZE]);\n const cropSize = decodeSize(read[KEY_CROP_SIZE]);\n if (inputSize === null || cropSize === null) return null;\n\n const rawMax = read[KEY_MAX_DETECTIONS] ?? DYNAMIC;\n const parsedMax = Number(rawMax);\n const maxDetections =\n rawMax === DYNAMIC || !Number.isInteger(parsedMax) || parsedMax < 1 ? null : parsedMax;\n\n const cropSource: CropSource =\n read[KEY_CROP_SOURCE] === \"original\" ? \"original\" : \"detector_input\";\n\n return {\n kind,\n inputSize,\n cropSize,\n cropSource,\n maxDetections,\n confThreshold: decodeFloat(read[KEY_CONF_THRESHOLD], 0.25),\n iouThreshold: decodeFloat(read[KEY_IOU_THRESHOLD], 0.45),\n applySoftmax: (read[KEY_APPLY_SOFTMAX] ?? \"1\") !== \"0\",\n detectorNames: parseNames(read[KEY_DETECTOR_NAMES]),\n classifierNames: parseNames(read[KEY_CLASSIFIER_NAMES]),\n sdkVersion: read[KEY_SDK_VERSION] ?? \"\",\n needsSourceImage: cropSource === \"original\",\n hasMasks: kind === FUSION_KIND_DETECT_SEGMENT_CLASSIFY,\n segmenterNames: parseNames(read[KEY_SEGMENTER_NAMES]),\n maskThreshold: decodeFloat(read[KEY_MASK_THRESHOLD], 0.5),\n maskApplied: (read[KEY_MASK_APPLIED] ?? \"1\") !== \"0\",\n };\n}\n"],"mappings":"uCAoCA,IAAa,EAA8B,kBAW9B,EAAsC,0BAStC,EAAkB,OAGlB,EAAc,SAGd,EAAe,eAGf,EAAc,kBAGd,EAAY,gBAUZ,EAAe,QAGf,EAAgB,SAGhB,EAAiB,UAGjB,EAAwB,iBAWxB,EAAe,QAEf,EAAe,QA+CtB,EAAW,OACX,EAAkB,cAClB,EAAiB,aACjB,EAAgB,YAChB,EAAkB,cAClB,EAAqB,iBACrB,EAAqB,iBACrB,EAAoB,gBACpB,EAAoB,gBACpB,EAAqB,iBACrB,EAAuB,mBACvB,EAAsB,kBACtB,EAAqB,iBACrB,EAAmB,eAEnB,EAAU,UAQhB,SAAS,EAAW,EAA2D,CAC3E,GAAI,CAAC,EAAK,OAAO,KACjB,IAAM,EAAQ,EAAI,MAAM,GAAG,EAC3B,GAAI,EAAM,SAAW,EAAG,OAAO,KAC/B,IAAM,EAAQ,OAAO,EAAM,EAAE,EACvB,EAAS,OAAO,EAAM,EAAE,EAG9B,MAFI,CAAC,OAAO,UAAU,CAAK,GAAK,CAAC,OAAO,UAAU,CAAM,GACpD,EAAQ,GAAK,EAAS,EAAU,KAC7B,CAAC,EAAO,CAAM,CACzB,CASA,SAAS,EAAY,EAAyB,EAA0B,CACpE,GAAI,CAAC,EAAK,OAAO,EACjB,IAAM,EAAQ,OAAO,CAAG,EACxB,OAAO,OAAO,SAAS,CAAK,EAAI,EAAQ,CAC5C,CAgBA,SAAgB,EACZ,EACiB,CACjB,GAAI,CAAC,EAAU,OAAO,KAEtB,IAAM,EAA+B,CAAC,EACtC,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAQ,EAC1C,EAAI,WAAA,MAA0B,IAAG,EAAK,EAAI,MAAM,CAAsB,GAAK,GAEnF,IAAM,EAAO,EAAK,GAClB,GAAI,IAAA,mBAAwC,IAAA,0BACxC,OAAO,KAGX,IAAM,EAAY,EAAW,EAAK,EAAe,EAC3C,EAAW,EAAW,EAAK,EAAc,EAC/C,GAAI,IAAc,MAAQ,IAAa,KAAM,OAAO,KAEpD,IAAM,EAAS,EAAK,IAAuB,EACrC,EAAY,OAAO,CAAM,EACzB,EACF,IAAW,GAAW,CAAC,OAAO,UAAU,CAAS,GAAK,EAAY,EAAI,KAAO,EAE3E,EACF,EAAK,KAAqB,WAAa,WAAa,iBAExD,MAAO,CACH,OACA,YACA,WACA,aACA,gBACA,cAAe,EAAY,EAAK,GAAqB,GAAI,EACzD,aAAc,EAAY,EAAK,GAAoB,GAAI,EACvD,cAAe,EAAK,IAAsB,OAAS,IACnD,cAAe,EAAA,WAAW,EAAK,EAAmB,EAClD,gBAAiB,EAAA,WAAW,EAAK,EAAqB,EACtD,WAAY,EAAK,IAAoB,GACrC,iBAAkB,IAAe,WACjC,SAAU,IAAS,EACnB,eAAgB,EAAA,WAAW,EAAK,EAAoB,EACpD,cAAe,EAAY,EAAK,GAAqB,EAAG,EACxD,aAAc,EAAK,IAAqB,OAAS,GACrD,CACJ"}
|
package/dist/vision/fusion.js
CHANGED
|
@@ -1,42 +1,47 @@
|
|
|
1
1
|
import { parseNames as e } from "./core/metadata.js";
|
|
2
2
|
//#region src/vision/fusion.ts
|
|
3
|
-
var t = "detect_classify", n = "ovs.",
|
|
4
|
-
function
|
|
3
|
+
var t = "detect_classify", n = "detect_segment_classify", r = "ovs.", i = "images", a = "source_image", o = "letterbox_scale", s = "letterbox_pad", c = "boxes", l = "scores", u = "classes", d = "num_detections", f = "masks", p = "probs", m = "kind", h = "sdk_version", g = "input_size", _ = "crop_size", v = "crop_source", y = "max_detections", b = "conf_threshold", x = "iou_threshold", S = "apply_softmax", C = "detector_names", w = "classifier_names", T = "segmenter_names", E = "mask_threshold", D = "mask_applied", O = "dynamic";
|
|
4
|
+
function k(e) {
|
|
5
5
|
if (!e) return null;
|
|
6
6
|
let t = e.split(",");
|
|
7
7
|
if (t.length !== 2) return null;
|
|
8
8
|
let n = Number(t[0]), r = Number(t[1]);
|
|
9
9
|
return !Number.isInteger(n) || !Number.isInteger(r) || n < 1 || r < 1 ? null : [n, r];
|
|
10
10
|
}
|
|
11
|
-
function
|
|
11
|
+
function A(e, t) {
|
|
12
12
|
if (!e) return t;
|
|
13
13
|
let n = Number(e);
|
|
14
14
|
return Number.isFinite(n) ? n : t;
|
|
15
15
|
}
|
|
16
|
-
function
|
|
17
|
-
if (!
|
|
16
|
+
function j(t) {
|
|
17
|
+
if (!t) return null;
|
|
18
18
|
let r = {};
|
|
19
|
-
for (let [e,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
for (let [e, n] of Object.entries(t)) e.startsWith("ovs.") && (r[e.slice(4)] = n);
|
|
20
|
+
let i = r[m];
|
|
21
|
+
if (i !== "detect_classify" && i !== "detect_segment_classify") return null;
|
|
22
|
+
let a = k(r[g]), o = k(r[_]);
|
|
23
|
+
if (a === null || o === null) return null;
|
|
24
|
+
let s = r[y] ?? O, c = Number(s), l = s === O || !Number.isInteger(c) || c < 1 ? null : c, u = r[v] === "original" ? "original" : "detector_input";
|
|
24
25
|
return {
|
|
25
|
-
kind:
|
|
26
|
-
inputSize:
|
|
27
|
-
cropSize:
|
|
28
|
-
cropSource:
|
|
29
|
-
maxDetections:
|
|
30
|
-
confThreshold:
|
|
31
|
-
iouThreshold:
|
|
32
|
-
applySoftmax: (r[
|
|
33
|
-
detectorNames: e(r[
|
|
34
|
-
classifierNames: e(r[
|
|
35
|
-
sdkVersion: r[
|
|
36
|
-
needsSourceImage:
|
|
26
|
+
kind: i,
|
|
27
|
+
inputSize: a,
|
|
28
|
+
cropSize: o,
|
|
29
|
+
cropSource: u,
|
|
30
|
+
maxDetections: l,
|
|
31
|
+
confThreshold: A(r[b], .25),
|
|
32
|
+
iouThreshold: A(r[x], .45),
|
|
33
|
+
applySoftmax: (r[S] ?? "1") !== "0",
|
|
34
|
+
detectorNames: e(r[C]),
|
|
35
|
+
classifierNames: e(r[w]),
|
|
36
|
+
sdkVersion: r[h] ?? "",
|
|
37
|
+
needsSourceImage: u === "original",
|
|
38
|
+
hasMasks: i === n,
|
|
39
|
+
segmenterNames: e(r[T]),
|
|
40
|
+
maskThreshold: A(r[E], .5),
|
|
41
|
+
maskApplied: (r[D] ?? "1") !== "0"
|
|
37
42
|
};
|
|
38
43
|
}
|
|
39
44
|
//#endregion
|
|
40
|
-
export { t as FUSION_KIND_DETECT_CLASSIFY,
|
|
45
|
+
export { t as FUSION_KIND_DETECT_CLASSIFY, n as FUSION_KIND_DETECT_SEGMENT_CLASSIFY, i as INPUT_IMAGE, s as INPUT_PAD, o as INPUT_SCALE, a as INPUT_SOURCE, r as METADATA_PREFIX, c as OUTPUT_BOXES, u as OUTPUT_CLASSES, f as OUTPUT_MASKS, d as OUTPUT_NUM_DETECTIONS, p as OUTPUT_PROBS, l as OUTPUT_SCORES, j as readFusionSpec };
|
|
41
46
|
|
|
42
47
|
//# sourceMappingURL=fusion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fusion.js","names":[],"sources":["../../src/vision/fusion.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * The contract a fused pipeline carries inside its own `.onnx` file.\n *\n * A pipeline built by the Python SDK's `ort_vision_sdk.compose` is a single\n * graph that already contains the detector, the crop-and-resize bridge and the\n * classifier. Everything the runtime needs to drive it — the letterbox\n * resolution, the crop resolution, where the crops come from, how many\n * detections the graph emits, the class names of both stages — was decided at\n * fusion time and written into the model's metadata.\n *\n * This module reads it back. It is the browser half of a contract whose other\n * half lives in `ort_vision_sdk/fusion.py`: the same keys, the same encodings,\n * the same fallbacks. A pipeline fused once therefore runs identically in\n * Python and in a browser tab, off the same file.\n *\n * Building a pipeline stays a Python-side build step — there is no ONNX\n * protobuf writer here, and there is no reason for one: fusing is something you\n * do once next to your export pipeline, not in a page load.\n */\n\nimport { parseNames } from \"./core/metadata\";\n\n/**\n * Which tensor the bridge crops the detected boxes out of.\n *\n * - `\"detector_input\"`: the letterboxed tensor already fed to the detector.\n * The fused graph then has a **single** image input, but a small object is\n * cropped out of its downscaled copy.\n * - `\"original\"`: a second, full-resolution image input. The bridge undoes the\n * letterbox transform in-graph and crops at native resolution. Two tensors to\n * feed, still one session and one model load.\n */\nexport type CropSource = \"detector_input\" | \"original\";\n\n/** Value of the `ovs.kind` metadata key for a detector→classifier pipeline. */\nexport const FUSION_KIND_DETECT_CLASSIFY = \"detect_classify\";\n\n/**\n * Namespace for every metadata key the fusion writes.\n *\n * Namespaced on purpose: the detector's own Ultralytics metadata (`names`,\n * `task`, `imgsz`) is carried over into the fused model, and an un-prefixed key\n * would either collide with it or be mistaken for it.\n */\nexport const METADATA_PREFIX = \"ovs.\";\n\n/** Name of the fused graph's letterboxed detector input, `[1, 3, H, W]` float32 in `[0, 1]`. */\nexport const INPUT_IMAGE = \"images\";\n\n/** Name of the full-resolution input. Present only when `cropSource === \"original\"`. */\nexport const INPUT_SOURCE = \"source_image\";\n\n/** Name of the `[1]` float32 letterbox scale factor. Only with `cropSource === \"original\"`. */\nexport const INPUT_SCALE = \"letterbox_scale\";\n\n/** Name of the `[2]` float32 `[padLeft, padTop]`. Only with `cropSource === \"original\"`. */\nexport const INPUT_PAD = \"letterbox_pad\";\n\n/**\n * Name of the `[K, 4]` float32 xyxy output, in **letterboxed** input pixels.\n *\n * A file fused by `ort-vision-sdk` 0.9.0 or later reports the box that was\n * actually classified: clamped to the image the crop came from, exactly as\n * RoiAlign received it. Older files report the raw box, so one that ran off the\n * frame draws a rectangle wider than the region the classifier saw.\n */\nexport const OUTPUT_BOXES = \"boxes\";\n\n/** Name of the `[K]` float32 detection-confidence output. */\nexport const OUTPUT_SCORES = \"scores\";\n\n/** Name of the `[K]` int64 detector-class output. */\nexport const OUTPUT_CLASSES = \"classes\";\n\n/** Name of the `[1]` int64 output holding how many of the `K` rows are real. */\nexport const OUTPUT_NUM_DETECTIONS = \"num_detections\";\n\n/** Name of the `[K, numClassifierClasses]` float32 classifier output, one row per box. */\nexport const OUTPUT_PROBS = \"probs\";\n\n/** Everything a fused pipeline declares about how it must be driven. */\nexport interface FusionSpec {\n /** Pipeline family. Only `\"detect_classify\"` exists today. */\n readonly kind: string;\n /** `[width, height]` the detector stage expects — the resolution to letterbox to. */\n readonly inputSize: readonly [number, number];\n /** `[width, height]` every crop is resampled to inside the graph. */\n readonly cropSize: readonly [number, number];\n /** Which tensor the crops are taken from. */\n readonly cropSource: CropSource;\n /**\n * Fixed number of rows `K` every output carries, surplus zero-padded and\n * counted by {@link OUTPUT_NUM_DETECTIONS}. `null` means the graph emits\n * exactly as many rows as survived NMS.\n */\n readonly maxDetections: number | null;\n /** Score threshold baked into the graph's NMS node. */\n readonly confThreshold: number;\n /** IoU threshold baked into the graph's NMS node. */\n readonly iouThreshold: number;\n /** Whether the classifier stage emits logits that still need a softmax. */\n readonly applySoftmax: boolean;\n /** Detector class names in class-id order, or `null` when the fusion recorded none. */\n readonly detectorNames: readonly string[] | null;\n /** Classifier class names in class-id order, or `null`. */\n readonly classifierNames: readonly string[] | null;\n /** Version of `ort-vision-sdk` that produced the file. */\n readonly sdkVersion: string;\n /** Whether driving this pipeline requires feeding the full-resolution input. */\n readonly needsSourceImage: boolean;\n}\n\nconst KEY_KIND = \"kind\";\nconst KEY_SDK_VERSION = \"sdk_version\";\nconst KEY_INPUT_SIZE = \"input_size\";\nconst KEY_CROP_SIZE = \"crop_size\";\nconst KEY_CROP_SOURCE = \"crop_source\";\nconst KEY_MAX_DETECTIONS = \"max_detections\";\nconst KEY_CONF_THRESHOLD = \"conf_threshold\";\nconst KEY_IOU_THRESHOLD = \"iou_threshold\";\nconst KEY_APPLY_SOFTMAX = \"apply_softmax\";\nconst KEY_DETECTOR_NAMES = \"detector_names\";\nconst KEY_CLASSIFIER_NAMES = \"classifier_names\";\n\nconst DYNAMIC = \"dynamic\";\n\n/**\n * Decode a `\"640,640\"` pair.\n *\n * @param raw The encoded pair.\n * @returns `[width, height]`, or `null` when the value is missing or malformed.\n */\nfunction decodeSize(raw: string | undefined): readonly [number, number] | null {\n if (!raw) return null;\n const parts = raw.split(\",\");\n if (parts.length !== 2) return null;\n const width = Number(parts[0]);\n const height = Number(parts[1]);\n if (!Number.isInteger(width) || !Number.isInteger(height)) return null;\n if (width < 1 || height < 1) return null;\n return [width, height];\n}\n\n/**\n * Decode a float, falling back when the value is missing or malformed.\n *\n * @param raw The encoded value.\n * @param fallback Value to use when `raw` cannot be read.\n * @returns The parsed number, or `fallback`.\n */\nfunction decodeFloat(raw: string | undefined, fallback: number): number {\n if (!raw) return fallback;\n const value = Number(raw);\n return Number.isFinite(value) ? value : fallback;\n}\n\n/**\n * Read a pipeline spec out of a model's custom metadata.\n *\n * Individual malformed entries fall back to the value a fusion would have used\n * by default — a single bad float is not a reason to reject an otherwise\n * loadable pipeline. A malformed resolution is fatal, because there is no safe\n * default for one.\n *\n * @param metadata A model's custom metadata map, as read by\n * {@link readModelMetadata}.\n * @returns The decoded spec, or `null` when the model is not a fused pipeline —\n * it carries no `ovs.kind` entry, or one naming a pipeline kind this version\n * does not know how to drive.\n */\nexport function readFusionSpec(\n metadata: Readonly<Record<string, string>> | undefined,\n): FusionSpec | null {\n if (!metadata) return null;\n\n const read: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata)) {\n if (key.startsWith(METADATA_PREFIX)) read[key.slice(METADATA_PREFIX.length)] = value;\n }\n if (read[KEY_KIND] !== FUSION_KIND_DETECT_CLASSIFY) return null;\n\n const inputSize = decodeSize(read[KEY_INPUT_SIZE]);\n const cropSize = decodeSize(read[KEY_CROP_SIZE]);\n if (inputSize === null || cropSize === null) return null;\n\n const rawMax = read[KEY_MAX_DETECTIONS] ?? DYNAMIC;\n const parsedMax = Number(rawMax);\n const maxDetections =\n rawMax === DYNAMIC || !Number.isInteger(parsedMax) || parsedMax < 1 ? null : parsedMax;\n\n const cropSource: CropSource =\n read[KEY_CROP_SOURCE] === \"original\" ? \"original\" : \"detector_input\";\n\n return {\n kind: FUSION_KIND_DETECT_CLASSIFY,\n inputSize,\n cropSize,\n cropSource,\n maxDetections,\n confThreshold: decodeFloat(read[KEY_CONF_THRESHOLD], 0.25),\n iouThreshold: decodeFloat(read[KEY_IOU_THRESHOLD], 0.45),\n applySoftmax: (read[KEY_APPLY_SOFTMAX] ?? \"1\") !== \"0\",\n detectorNames: parseNames(read[KEY_DETECTOR_NAMES]),\n classifierNames: parseNames(read[KEY_CLASSIFIER_NAMES]),\n sdkVersion: read[KEY_SDK_VERSION] ?? \"\",\n needsSourceImage: cropSource === \"original\",\n };\n}\n"],"mappings":";;AAoCA,IAAa,IAA8B,mBAS9B,IAAkB,QAGlB,IAAc,UAGd,IAAe,gBAGf,IAAc,mBAGd,IAAY,iBAUZ,IAAe,SAGf,IAAgB,UAGhB,IAAiB,WAGjB,IAAwB,kBAGxB,IAAe,SAkCtB,IAAW,QACX,IAAkB,eAClB,IAAiB,cACjB,IAAgB,aAChB,IAAkB,eAClB,IAAqB,kBACrB,IAAqB,kBACrB,IAAoB,iBACpB,IAAoB,iBACpB,IAAqB,kBACrB,IAAuB,oBAEvB,IAAU;AAQhB,SAAS,EAAW,GAA2D;CAC3E,IAAI,CAAC,GAAK,OAAO;CACjB,IAAM,IAAQ,EAAI,MAAM,GAAG;CAC3B,IAAI,EAAM,WAAW,GAAG,OAAO;CAC/B,IAAM,IAAQ,OAAO,EAAM,EAAE,GACvB,IAAS,OAAO,EAAM,EAAE;CAG9B,OAFI,CAAC,OAAO,UAAU,CAAK,KAAK,CAAC,OAAO,UAAU,CAAM,KACpD,IAAQ,KAAK,IAAS,IAAU,OAC7B,CAAC,GAAO,CAAM;AACzB;AASA,SAAS,EAAY,GAAyB,GAA0B;CACpE,IAAI,CAAC,GAAK,OAAO;CACjB,IAAM,IAAQ,OAAO,CAAG;CACxB,OAAO,OAAO,SAAS,CAAK,IAAI,IAAQ;AAC5C;AAgBA,SAAgB,EACZ,GACiB;CACjB,IAAI,CAAC,GAAU,OAAO;CAEtB,IAAM,IAA+B,CAAC;CACtC,KAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,CAAQ,GAC9C,AAAI,EAAI,WAAA,MAA0B,MAAG,EAAK,EAAI,MAAM,CAAsB,KAAK;CAEnF,IAAI,EAAK,OAAA,mBAA2C,OAAO;CAE3D,IAAM,IAAY,EAAW,EAAK,EAAe,GAC3C,IAAW,EAAW,EAAK,EAAc;CAC/C,IAAI,MAAc,QAAQ,MAAa,MAAM,OAAO;CAEpD,IAAM,IAAS,EAAK,MAAuB,GACrC,IAAY,OAAO,CAAM,GACzB,IACF,MAAW,KAAW,CAAC,OAAO,UAAU,CAAS,KAAK,IAAY,IAAI,OAAO,GAE3E,IACF,EAAK,OAAqB,aAAa,aAAa;CAExD,OAAO;EACH,MAAM;EACN;EACA;EACA;EACA;EACA,eAAe,EAAY,EAAK,IAAqB,GAAI;EACzD,cAAc,EAAY,EAAK,IAAoB,GAAI;EACvD,eAAe,EAAK,MAAsB,SAAS;EACnD,eAAe,EAAW,EAAK,EAAmB;EAClD,iBAAiB,EAAW,EAAK,EAAqB;EACtD,YAAY,EAAK,MAAoB;EACrC,kBAAkB,MAAe;CACrC;AACJ"}
|
|
1
|
+
{"version":3,"file":"fusion.js","names":[],"sources":["../../src/vision/fusion.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * The contract a fused pipeline carries inside its own `.onnx` file.\n *\n * A pipeline built by the Python SDK's `ort_vision_sdk.compose` is a single\n * graph that already contains the detector, the crop-and-resize bridge and the\n * classifier. Everything the runtime needs to drive it — the letterbox\n * resolution, the crop resolution, where the crops come from, how many\n * detections the graph emits, the class names of both stages — was decided at\n * fusion time and written into the model's metadata.\n *\n * This module reads it back. It is the browser half of a contract whose other\n * half lives in `ort_vision_sdk/fusion.py`: the same keys, the same encodings,\n * the same fallbacks. A pipeline fused once therefore runs identically in\n * Python and in a browser tab, off the same file.\n *\n * Building a pipeline stays a Python-side build step — there is no ONNX\n * protobuf writer here, and there is no reason for one: fusing is something you\n * do once next to your export pipeline, not in a page load.\n */\n\nimport { parseNames } from \"./core/metadata\";\n\n/**\n * Which tensor the bridge crops the detected boxes out of.\n *\n * - `\"detector_input\"`: the letterboxed tensor already fed to the detector.\n * The fused graph then has a **single** image input, but a small object is\n * cropped out of its downscaled copy.\n * - `\"original\"`: a second, full-resolution image input. The bridge undoes the\n * letterbox transform in-graph and crops at native resolution. Two tensors to\n * feed, still one session and one model load.\n */\nexport type CropSource = \"detector_input\" | \"original\";\n\n/** Value of the `ovs.kind` metadata key for a detector→classifier pipeline. */\nexport const FUSION_KIND_DETECT_CLASSIFY = \"detect_classify\";\n\n/**\n * Value of `ovs.kind` for a detector→segmenter→classifier pipeline.\n *\n * The segmenter runs inside each crop rather than over the whole frame: the\n * detector finds the boxes, the bridge cuts them out, and the segmenter turns\n * each crop into a foreground mask that gates the pixels the classifier sees.\n * Fusing one is a build step on the Python side; the browser only loads the\n * result.\n */\nexport const FUSION_KIND_DETECT_SEGMENT_CLASSIFY = \"detect_segment_classify\";\n\n/**\n * Namespace for every metadata key the fusion writes.\n *\n * Namespaced on purpose: the detector's own Ultralytics metadata (`names`,\n * `task`, `imgsz`) is carried over into the fused model, and an un-prefixed key\n * would either collide with it or be mistaken for it.\n */\nexport const METADATA_PREFIX = \"ovs.\";\n\n/** Name of the fused graph's letterboxed detector input, `[1, 3, H, W]` float32 in `[0, 1]`. */\nexport const INPUT_IMAGE = \"images\";\n\n/** Name of the full-resolution input. Present only when `cropSource === \"original\"`. */\nexport const INPUT_SOURCE = \"source_image\";\n\n/** Name of the `[1]` float32 letterbox scale factor. Only with `cropSource === \"original\"`. */\nexport const INPUT_SCALE = \"letterbox_scale\";\n\n/** Name of the `[2]` float32 `[padLeft, padTop]`. Only with `cropSource === \"original\"`. */\nexport const INPUT_PAD = \"letterbox_pad\";\n\n/**\n * Name of the `[K, 4]` float32 xyxy output, in **letterboxed** input pixels.\n *\n * A file fused by `ort-vision-sdk` 0.9.0 or later reports the box that was\n * actually classified: clamped to the image the crop came from, exactly as\n * RoiAlign received it. Older files report the raw box, so one that ran off the\n * frame draws a rectangle wider than the region the classifier saw.\n */\nexport const OUTPUT_BOXES = \"boxes\";\n\n/** Name of the `[K]` float32 detection-confidence output. */\nexport const OUTPUT_SCORES = \"scores\";\n\n/** Name of the `[K]` int64 detector-class output. */\nexport const OUTPUT_CLASSES = \"classes\";\n\n/** Name of the `[1]` int64 output holding how many of the `K` rows are real. */\nexport const OUTPUT_NUM_DETECTIONS = \"num_detections\";\n\n/** Name of the `[K, numClassifierClasses]` float32 classifier output, one row per box. */\n/**\n * Name of the `(K, 1, cropH, cropW)` float32 mask output. Only on a\n * `detect_segment_classify` pipeline.\n *\n * The mask lives in the **crop's** coordinate space, not the original image's,\n * because that is where the segmenter computed it. Values are 0 or 1 after\n * thresholding; padded rows are all-zero, like every other output.\n */\nexport const OUTPUT_MASKS = \"masks\";\n\nexport const OUTPUT_PROBS = \"probs\";\n\n/** Everything a fused pipeline declares about how it must be driven. */\nexport interface FusionSpec {\n /** Pipeline family — {@link FUSION_KIND_DETECT_CLASSIFY} or {@link FUSION_KIND_DETECT_SEGMENT_CLASSIFY}. */\n readonly kind: string;\n /** `[width, height]` the detector stage expects — the resolution to letterbox to. */\n readonly inputSize: readonly [number, number];\n /** `[width, height]` every crop is resampled to inside the graph. */\n readonly cropSize: readonly [number, number];\n /** Which tensor the crops are taken from. */\n readonly cropSource: CropSource;\n /**\n * Fixed number of rows `K` every output carries, surplus zero-padded and\n * counted by {@link OUTPUT_NUM_DETECTIONS}. `null` means the graph emits\n * exactly as many rows as survived NMS.\n */\n readonly maxDetections: number | null;\n /** Score threshold baked into the graph's NMS node. */\n readonly confThreshold: number;\n /** IoU threshold baked into the graph's NMS node. */\n readonly iouThreshold: number;\n /** Whether the classifier stage emits logits that still need a softmax. */\n readonly applySoftmax: boolean;\n /** Detector class names in class-id order, or `null` when the fusion recorded none. */\n readonly detectorNames: readonly string[] | null;\n /** Classifier class names in class-id order, or `null`. */\n readonly classifierNames: readonly string[] | null;\n /** Version of `ort-vision-sdk` that produced the file. */\n readonly sdkVersion: string;\n /** Whether driving this pipeline requires feeding the full-resolution input. */\n readonly needsSourceImage: boolean;\n /** Whether this pipeline emits a {@link OUTPUT_MASKS} tensor. */\n readonly hasMasks: boolean;\n /** Class id → name for the segmenter's channels, or `null`. */\n readonly segmenterNames: readonly string[] | null;\n /**\n * Probability above which a segmenter pixel counted as foreground.\n *\n * Baked into the graph at fusion time; reported so a caller can say what the\n * masks mean.\n */\n readonly maskThreshold: number;\n /** Whether the mask gated the crop before the classifier saw it. */\n readonly maskApplied: boolean;\n}\n\nconst KEY_KIND = \"kind\";\nconst KEY_SDK_VERSION = \"sdk_version\";\nconst KEY_INPUT_SIZE = \"input_size\";\nconst KEY_CROP_SIZE = \"crop_size\";\nconst KEY_CROP_SOURCE = \"crop_source\";\nconst KEY_MAX_DETECTIONS = \"max_detections\";\nconst KEY_CONF_THRESHOLD = \"conf_threshold\";\nconst KEY_IOU_THRESHOLD = \"iou_threshold\";\nconst KEY_APPLY_SOFTMAX = \"apply_softmax\";\nconst KEY_DETECTOR_NAMES = \"detector_names\";\nconst KEY_CLASSIFIER_NAMES = \"classifier_names\";\nconst KEY_SEGMENTER_NAMES = \"segmenter_names\";\nconst KEY_MASK_THRESHOLD = \"mask_threshold\";\nconst KEY_MASK_APPLIED = \"mask_applied\";\n\nconst DYNAMIC = \"dynamic\";\n\n/**\n * Decode a `\"640,640\"` pair.\n *\n * @param raw The encoded pair.\n * @returns `[width, height]`, or `null` when the value is missing or malformed.\n */\nfunction decodeSize(raw: string | undefined): readonly [number, number] | null {\n if (!raw) return null;\n const parts = raw.split(\",\");\n if (parts.length !== 2) return null;\n const width = Number(parts[0]);\n const height = Number(parts[1]);\n if (!Number.isInteger(width) || !Number.isInteger(height)) return null;\n if (width < 1 || height < 1) return null;\n return [width, height];\n}\n\n/**\n * Decode a float, falling back when the value is missing or malformed.\n *\n * @param raw The encoded value.\n * @param fallback Value to use when `raw` cannot be read.\n * @returns The parsed number, or `fallback`.\n */\nfunction decodeFloat(raw: string | undefined, fallback: number): number {\n if (!raw) return fallback;\n const value = Number(raw);\n return Number.isFinite(value) ? value : fallback;\n}\n\n/**\n * Read a pipeline spec out of a model's custom metadata.\n *\n * Individual malformed entries fall back to the value a fusion would have used\n * by default — a single bad float is not a reason to reject an otherwise\n * loadable pipeline. A malformed resolution is fatal, because there is no safe\n * default for one.\n *\n * @param metadata A model's custom metadata map, as read by\n * {@link readModelMetadata}.\n * @returns The decoded spec, or `null` when the model is not a fused pipeline —\n * it carries no `ovs.kind` entry, or one naming a pipeline kind this version\n * does not know how to drive.\n */\nexport function readFusionSpec(\n metadata: Readonly<Record<string, string>> | undefined,\n): FusionSpec | null {\n if (!metadata) return null;\n\n const read: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata)) {\n if (key.startsWith(METADATA_PREFIX)) read[key.slice(METADATA_PREFIX.length)] = value;\n }\n const kind = read[KEY_KIND];\n if (kind !== FUSION_KIND_DETECT_CLASSIFY && kind !== FUSION_KIND_DETECT_SEGMENT_CLASSIFY) {\n return null;\n }\n\n const inputSize = decodeSize(read[KEY_INPUT_SIZE]);\n const cropSize = decodeSize(read[KEY_CROP_SIZE]);\n if (inputSize === null || cropSize === null) return null;\n\n const rawMax = read[KEY_MAX_DETECTIONS] ?? DYNAMIC;\n const parsedMax = Number(rawMax);\n const maxDetections =\n rawMax === DYNAMIC || !Number.isInteger(parsedMax) || parsedMax < 1 ? null : parsedMax;\n\n const cropSource: CropSource =\n read[KEY_CROP_SOURCE] === \"original\" ? \"original\" : \"detector_input\";\n\n return {\n kind,\n inputSize,\n cropSize,\n cropSource,\n maxDetections,\n confThreshold: decodeFloat(read[KEY_CONF_THRESHOLD], 0.25),\n iouThreshold: decodeFloat(read[KEY_IOU_THRESHOLD], 0.45),\n applySoftmax: (read[KEY_APPLY_SOFTMAX] ?? \"1\") !== \"0\",\n detectorNames: parseNames(read[KEY_DETECTOR_NAMES]),\n classifierNames: parseNames(read[KEY_CLASSIFIER_NAMES]),\n sdkVersion: read[KEY_SDK_VERSION] ?? \"\",\n needsSourceImage: cropSource === \"original\",\n hasMasks: kind === FUSION_KIND_DETECT_SEGMENT_CLASSIFY,\n segmenterNames: parseNames(read[KEY_SEGMENTER_NAMES]),\n maskThreshold: decodeFloat(read[KEY_MASK_THRESHOLD], 0.5),\n maskApplied: (read[KEY_MASK_APPLIED] ?? \"1\") !== \"0\",\n };\n}\n"],"mappings":";;AAoCA,IAAa,IAA8B,mBAW9B,IAAsC,2BAStC,IAAkB,QAGlB,IAAc,UAGd,IAAe,gBAGf,IAAc,mBAGd,IAAY,iBAUZ,IAAe,SAGf,IAAgB,UAGhB,IAAiB,WAGjB,IAAwB,kBAWxB,IAAe,SAEf,IAAe,SA+CtB,IAAW,QACX,IAAkB,eAClB,IAAiB,cACjB,IAAgB,aAChB,IAAkB,eAClB,IAAqB,kBACrB,IAAqB,kBACrB,IAAoB,iBACpB,IAAoB,iBACpB,IAAqB,kBACrB,IAAuB,oBACvB,IAAsB,mBACtB,IAAqB,kBACrB,IAAmB,gBAEnB,IAAU;AAQhB,SAAS,EAAW,GAA2D;CAC3E,IAAI,CAAC,GAAK,OAAO;CACjB,IAAM,IAAQ,EAAI,MAAM,GAAG;CAC3B,IAAI,EAAM,WAAW,GAAG,OAAO;CAC/B,IAAM,IAAQ,OAAO,EAAM,EAAE,GACvB,IAAS,OAAO,EAAM,EAAE;CAG9B,OAFI,CAAC,OAAO,UAAU,CAAK,KAAK,CAAC,OAAO,UAAU,CAAM,KACpD,IAAQ,KAAK,IAAS,IAAU,OAC7B,CAAC,GAAO,CAAM;AACzB;AASA,SAAS,EAAY,GAAyB,GAA0B;CACpE,IAAI,CAAC,GAAK,OAAO;CACjB,IAAM,IAAQ,OAAO,CAAG;CACxB,OAAO,OAAO,SAAS,CAAK,IAAI,IAAQ;AAC5C;AAgBA,SAAgB,EACZ,GACiB;CACjB,IAAI,CAAC,GAAU,OAAO;CAEtB,IAAM,IAA+B,CAAC;CACtC,KAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,CAAQ,GAC9C,AAAI,EAAI,WAAA,MAA0B,MAAG,EAAK,EAAI,MAAM,CAAsB,KAAK;CAEnF,IAAM,IAAO,EAAK;CAClB,IAAI,MAAA,qBAAwC,MAAA,2BACxC,OAAO;CAGX,IAAM,IAAY,EAAW,EAAK,EAAe,GAC3C,IAAW,EAAW,EAAK,EAAc;CAC/C,IAAI,MAAc,QAAQ,MAAa,MAAM,OAAO;CAEpD,IAAM,IAAS,EAAK,MAAuB,GACrC,IAAY,OAAO,CAAM,GACzB,IACF,MAAW,KAAW,CAAC,OAAO,UAAU,CAAS,KAAK,IAAY,IAAI,OAAO,GAE3E,IACF,EAAK,OAAqB,aAAa,aAAa;CAExD,OAAO;EACH;EACA;EACA;EACA;EACA;EACA,eAAe,EAAY,EAAK,IAAqB,GAAI;EACzD,cAAc,EAAY,EAAK,IAAoB,GAAI;EACvD,eAAe,EAAK,MAAsB,SAAS;EACnD,eAAe,EAAW,EAAK,EAAmB;EAClD,iBAAiB,EAAW,EAAK,EAAqB;EACtD,YAAY,EAAK,MAAoB;EACrC,kBAAkB,MAAe;EACjC,UAAU,MAAS;EACnB,gBAAgB,EAAW,EAAK,EAAoB;EACpD,eAAe,EAAY,EAAK,IAAqB,EAAG;EACxD,cAAc,EAAK,MAAqB,SAAS;CACrD;AACJ"}
|
package/dist/vision/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
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/
|
|
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/dtypes.cjs"),o=require("./core/graph.cjs"),s=require("./core/metadata.cjs"),c=require("./core/providers.cjs"),l=require("./core/session.cjs"),u=require("./normalization.cjs"),d=require("./io/image.cjs"),f=require("./fusion.cjs"),p=require("./preprocess/image.cjs"),m=require("./preprocess/pipeline.cjs"),h=require("./postprocess/classification.cjs"),g=require("./postprocess/detection.cjs"),_=require("./postprocess/segmentation.cjs"),v=require("./tasks/base.cjs"),y=require("./tasks/classifier.cjs"),b=require("./tasks/detectClassify.cjs"),x=require("./tasks/detector.cjs"),S=require("./tasks/segmenter.cjs");var C=`0.11.0`;exports.BoundingBox=t.BoundingBox,exports.Boxes=r.Boxes,exports.COCO_CLASSES=i.COCO_CLASSES,exports.CUSTOM_NORMALIZATION=u.CUSTOM_NORMALIZATION,exports.ClassificationResults=r.ClassificationResults,exports.Classifier=y.Classifier,exports.DEFAULT_MODEL_CACHE=l.DEFAULT_MODEL_CACHE,exports.DEFAULT_PROVIDERS=c.DEFAULT_PROVIDERS,exports.DEFAULT_TENSOR_TYPE=a.DEFAULT_TENSOR_TYPE,exports.DetectClassify=b.DetectClassify,exports.DetectClassifyResults=r.DetectClassifyResults,exports.DetectionResults=r.DetectionResults,exports.Detector=x.Detector,exports.FUSION_KIND_DETECT_CLASSIFY=f.FUSION_KIND_DETECT_CLASSIFY,exports.FUSION_KIND_DETECT_SEGMENT_CLASSIFY=f.FUSION_KIND_DETECT_SEGMENT_CLASSIFY,exports.FusionError=e.FusionError,exports.GRAPH_OPTIMIZATION_KEY=l.GRAPH_OPTIMIZATION_KEY,exports.IDENTITY_MEAN=u.IDENTITY_MEAN,exports.IDENTITY_STD=u.IDENTITY_STD,exports.IMAGENET_MEAN=u.IMAGENET_MEAN,exports.IMAGENET_STD=u.IMAGENET_STD,exports.INPUT_IMAGE=f.INPUT_IMAGE,exports.INPUT_PAD=f.INPUT_PAD,exports.INPUT_SCALE=f.INPUT_SCALE,exports.INPUT_SOURCE=f.INPUT_SOURCE,exports.ImageLoadError=e.ImageLoadError,exports.InferenceError=e.InferenceError,exports.LabelMapError=e.LabelMapError,exports.LetterboxPipeline=m.LetterboxPipeline,exports.METADATA_PREFIX=f.METADATA_PREFIX,exports.Mask=t.Mask,exports.Masks=r.Masks,exports.ModelLoadError=e.ModelLoadError,exports.NoDetectionsError=e.NoDetectionsError,exports.OUTPUT_BOXES=f.OUTPUT_BOXES,exports.OUTPUT_CLASSES=f.OUTPUT_CLASSES,exports.OUTPUT_MASKS=f.OUTPUT_MASKS,exports.OUTPUT_NUM_DETECTIONS=f.OUTPUT_NUM_DETECTIONS,exports.OUTPUT_PROBS=f.OUTPUT_PROBS,exports.OUTPUT_SCORES=f.OUTPUT_SCORES,exports.OrtSession=l.OrtSession,exports.OrtVisionError=e.OrtVisionError,exports.Probs=r.Probs,exports.ProviderNotAvailableError=e.ProviderNotAvailableError,exports.QUANTIZATION_KEY=l.QUANTIZATION_KEY,exports.RGBImage=t.RGBImage,exports.ResizePipeline=m.ResizePipeline,exports.SegmentationResults=r.SegmentationResults,exports.Segmenter=S.Segmenter,exports.SpeedTimer=n.SpeedTimer,exports.VERSION=C,exports.VisionTask=v.VisionTask,exports.asFloat32Array=a.asFloat32Array,exports.batchedNms=g.batchedNms,exports.classificationNumClasses=o.classificationNumClasses,exports.declaredShapesFrom=o.declaredShapesFrom,exports.decodeYolo=g.decodeYolo,exports.decodeYoloAnchors=g.decodeYoloAnchors,exports.decodeYoloSeg=_.decodeYoloSeg,exports.defaultLabels=i.defaultLabels,exports.detectProviders=c.detectProviders,exports.detectionNumClasses=o.detectionNumClasses,exports.fromCv2=p.fromCv2,exports.hasFloat16Array=a.hasFloat16Array,exports.isUltralyticsClassifier=u.isUltralyticsClassifier,exports.letterbox=p.letterbox,exports.letterboxToTensorData=m.letterboxToTensorData,exports.loadImage=d.loadImage,exports.modelNames=s.modelNames,exports.nms=g.nms,exports.normalize=p.normalize,exports.parseNames=s.parseNames,exports.readFusionSpec=f.readFusionSpec,exports.readModelInputTypes=s.readModelInputTypes,exports.readModelMetadata=s.readModelMetadata,exports.requireDetections=v.requireDetections,exports.resize=p.resize,exports.resizeToTensorData=m.resizeToTensorData,exports.resolveInputSize=o.resolveInputSize,exports.resolveLabels=i.resolveLabels,exports.resolveNormalization=u.resolveNormalization,exports.resolveProviders=c.resolveProviders,exports.softmax=h.softmax,exports.spatialInputSize=o.spatialInputSize,exports.tensorTypeFor=a.tensorTypeFor,exports.toCHW=p.toCHW,exports.toCv2=p.toCv2,exports.toFloat32=p.toFloat32,exports.toFloat32Tensor=p.toFloat32Tensor,exports.toTensor=p.toTensor,exports.topK=h.topK,exports.writePlanarFloat32=m.writePlanarFloat32,exports.zeroTensorData=m.zeroTensorData;
|
|
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.11.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 DetectClassifyResults,\n DetectionResults,\n Masks,\n Probs,\n SegmentationResults,\n} from \"./results\";\n\nexport {\n COCO_CLASSES,\n type LabelSpec,\n type ResolveLabelsOptions,\n defaultLabels,\n resolveLabels,\n} from \"./labels\";\n\nexport {\n FusionError,\n ImageLoadError,\n InferenceError,\n LabelMapError,\n ModelLoadError,\n NoDetectionsError,\n OrtVisionError,\n ProviderNotAvailableError,\n} from \"./core/exceptions\";\n\nexport {\n DEFAULT_MODEL_CACHE,\n GRAPH_OPTIMIZATION_KEY,\n type ModelSource,\n type OrtSessionOptions,\n OrtSession,\n QUANTIZATION_KEY,\n} from \"./core/session\";\nexport {\n type DeclaredDim,\n type DeclaredShape,\n type ResolveInputSizeOptions,\n classificationNumClasses,\n declaredShapesFrom,\n detectionNumClasses,\n resolveInputSize,\n spatialInputSize,\n} from \"./core/graph\";\nexport {\n DEFAULT_TENSOR_TYPE,\n type Float16ArrayLike,\n asFloat32Array,\n hasFloat16Array,\n tensorTypeFor,\n} from \"./core/dtypes\";\nexport { modelNames, parseNames, readModelInputTypes, readModelMetadata } from \"./core/metadata\";\nexport {\n DEFAULT_PROVIDERS,\n type ProviderSpec,\n detectProviders,\n resolveProviders,\n} from \"./core/providers\";\nexport { type Speed, SpeedTimer } from \"./core/timing\";\nexport {\n CUSTOM_NORMALIZATION,\n IDENTITY_MEAN,\n IDENTITY_STD,\n IMAGENET_MEAN,\n IMAGENET_STD,\n type Normalization,\n type ResolvedNormalization,\n isUltralyticsClassifier,\n resolveNormalization,\n} from \"./normalization\";\n\nexport { type ImageInput, loadImage } from \"./io/image\";\n\nexport {\n FUSION_KIND_DETECT_CLASSIFY,\n FUSION_KIND_DETECT_SEGMENT_CLASSIFY,\n INPUT_IMAGE,\n INPUT_PAD,\n INPUT_SCALE,\n INPUT_SOURCE,\n METADATA_PREFIX,\n OUTPUT_BOXES,\n OUTPUT_CLASSES,\n OUTPUT_MASKS,\n OUTPUT_NUM_DETECTIONS,\n OUTPUT_PROBS,\n OUTPUT_SCORES,\n type CropSource,\n type FusionSpec,\n readFusionSpec,\n} from \"./fusion\";\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 {\n type FusedLetterboxResult,\n type FusedResizeResult,\n LetterboxPipeline,\n ResizePipeline,\n letterboxToTensorData,\n resizeToTensorData,\n writePlanarFloat32,\n zeroTensorData,\n} from \"./preprocess/pipeline\";\n\nexport { type TopKResult, softmax, topK } from \"./postprocess/classification\";\n\nexport {\n type DecodeYoloAnchorsOptions,\n type DecodeYoloOptions,\n type DecodedAnchors,\n type DecodedDetection,\n batchedNms,\n decodeYolo,\n decodeYoloAnchors,\n nms,\n} from \"./postprocess/detection\";\n\nexport {\n type DecodeYoloSegOptions,\n type DecodedSegmentation,\n decodeYoloSeg,\n} from \"./postprocess/segmentation\";\n\nexport { VisionTask, requireDetections } from \"./tasks/base\";\nexport {\n type ClassifierOptions,\n type ClassifierPredictOptions,\n Classifier,\n} from \"./tasks/classifier\";\nexport {\n type DetectClassifyOptions,\n type DetectClassifyPredictOptions,\n DetectClassify,\n} from \"./tasks/detectClassify\";\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.11.0\";\n"],"mappings":"0wBAwLA,IAAa,EAAkB"}
|
package/dist/vision/index.js
CHANGED
|
@@ -3,26 +3,27 @@ import { BoundingBox as c, Mask as l, RGBImage as u } from "./types.js";
|
|
|
3
3
|
import { SpeedTimer as d } from "./core/timing.js";
|
|
4
4
|
import { Boxes as f, ClassificationResults as p, DetectClassifyResults as m, DetectionResults as h, Masks as g, Probs as _, SegmentationResults as v } from "./results.js";
|
|
5
5
|
import { COCO_CLASSES as y, defaultLabels as b, resolveLabels as x } from "./labels.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
6
|
+
import { DEFAULT_TENSOR_TYPE as S, asFloat32Array as C, hasFloat16Array as w, tensorTypeFor as T } from "./core/dtypes.js";
|
|
7
|
+
import { classificationNumClasses as E, declaredShapesFrom as D, detectionNumClasses as O, resolveInputSize as k, spatialInputSize as A } from "./core/graph.js";
|
|
8
|
+
import { modelNames as j, parseNames as M, readModelInputTypes as N, readModelMetadata as P } from "./core/metadata.js";
|
|
9
|
+
import { DEFAULT_PROVIDERS as F, detectProviders as I, resolveProviders as L } from "./core/providers.js";
|
|
10
|
+
import { DEFAULT_MODEL_CACHE as R, GRAPH_OPTIMIZATION_KEY as z, OrtSession as B, QUANTIZATION_KEY as V } from "./core/session.js";
|
|
11
|
+
import { CUSTOM_NORMALIZATION as H, IDENTITY_MEAN as U, IDENTITY_STD as W, IMAGENET_MEAN as G, IMAGENET_STD as K, isUltralyticsClassifier as q, resolveNormalization as J } from "./normalization.js";
|
|
12
|
+
import { loadImage as Y } from "./io/image.js";
|
|
13
|
+
import { FUSION_KIND_DETECT_CLASSIFY as X, FUSION_KIND_DETECT_SEGMENT_CLASSIFY as Z, INPUT_IMAGE as Q, INPUT_PAD as $, INPUT_SCALE as ee, INPUT_SOURCE as te, METADATA_PREFIX as ne, OUTPUT_BOXES as re, OUTPUT_CLASSES as ie, OUTPUT_MASKS as ae, OUTPUT_NUM_DETECTIONS as oe, OUTPUT_PROBS as se, OUTPUT_SCORES as ce, readFusionSpec as le } from "./fusion.js";
|
|
14
|
+
import { fromCv2 as ue, letterbox as de, normalize as fe, resize as pe, toCHW as me, toCv2 as he, toFloat32 as ge, toFloat32Tensor as _e, toTensor as ve } from "./preprocess/image.js";
|
|
15
|
+
import { LetterboxPipeline as ye, ResizePipeline as be, letterboxToTensorData as xe, resizeToTensorData as Se, writePlanarFloat32 as Ce, zeroTensorData as we } from "./preprocess/pipeline.js";
|
|
16
|
+
import { softmax as Te, topK as Ee } from "./postprocess/classification.js";
|
|
17
|
+
import { batchedNms as De, decodeYolo as Oe, decodeYoloAnchors as ke, nms as Ae } from "./postprocess/detection.js";
|
|
18
|
+
import { decodeYoloSeg as je } from "./postprocess/segmentation.js";
|
|
19
|
+
import { VisionTask as Me, requireDetections as Ne } from "./tasks/base.js";
|
|
20
|
+
import { Classifier as Pe } from "./tasks/classifier.js";
|
|
21
|
+
import { DetectClassify as Fe } from "./tasks/detectClassify.js";
|
|
22
|
+
import { Detector as Ie } from "./tasks/detector.js";
|
|
23
|
+
import { Segmenter as Le } from "./tasks/segmenter.js";
|
|
23
24
|
//#region src/vision/index.ts
|
|
24
|
-
var
|
|
25
|
+
var Re = "0.11.0";
|
|
25
26
|
//#endregion
|
|
26
|
-
export { c as BoundingBox, f as Boxes, y as COCO_CLASSES,
|
|
27
|
+
export { c as BoundingBox, f as Boxes, y as COCO_CLASSES, H as CUSTOM_NORMALIZATION, p as ClassificationResults, Pe as Classifier, R as DEFAULT_MODEL_CACHE, F as DEFAULT_PROVIDERS, S as DEFAULT_TENSOR_TYPE, Fe as DetectClassify, m as DetectClassifyResults, h as DetectionResults, Ie as Detector, X as FUSION_KIND_DETECT_CLASSIFY, Z as FUSION_KIND_DETECT_SEGMENT_CLASSIFY, e as FusionError, z as GRAPH_OPTIMIZATION_KEY, U as IDENTITY_MEAN, W as IDENTITY_STD, G as IMAGENET_MEAN, K as IMAGENET_STD, Q as INPUT_IMAGE, $ as INPUT_PAD, ee as INPUT_SCALE, te as INPUT_SOURCE, t as ImageLoadError, n as InferenceError, r as LabelMapError, ye as LetterboxPipeline, ne as METADATA_PREFIX, l as Mask, g as Masks, i as ModelLoadError, a as NoDetectionsError, re as OUTPUT_BOXES, ie as OUTPUT_CLASSES, ae as OUTPUT_MASKS, oe as OUTPUT_NUM_DETECTIONS, se as OUTPUT_PROBS, ce as OUTPUT_SCORES, B as OrtSession, o as OrtVisionError, _ as Probs, s as ProviderNotAvailableError, V as QUANTIZATION_KEY, u as RGBImage, be as ResizePipeline, v as SegmentationResults, Le as Segmenter, d as SpeedTimer, Re as VERSION, Me as VisionTask, C as asFloat32Array, De as batchedNms, E as classificationNumClasses, D as declaredShapesFrom, Oe as decodeYolo, ke as decodeYoloAnchors, je as decodeYoloSeg, b as defaultLabels, I as detectProviders, O as detectionNumClasses, ue as fromCv2, w as hasFloat16Array, q as isUltralyticsClassifier, de as letterbox, xe as letterboxToTensorData, Y as loadImage, j as modelNames, Ae as nms, fe as normalize, M as parseNames, le as readFusionSpec, N as readModelInputTypes, P as readModelMetadata, Ne as requireDetections, pe as resize, Se as resizeToTensorData, k as resolveInputSize, x as resolveLabels, J as resolveNormalization, L as resolveProviders, Te as softmax, A as spatialInputSize, T as tensorTypeFor, me as toCHW, he as toCv2, ge as toFloat32, _e as toFloat32Tensor, ve as toTensor, Ee as topK, Ce as writePlanarFloat32, we as zeroTensorData };
|
|
27
28
|
|
|
28
29
|
//# 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.11.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 DetectClassifyResults,\n DetectionResults,\n Masks,\n Probs,\n SegmentationResults,\n} from \"./results\";\n\nexport {\n COCO_CLASSES,\n type LabelSpec,\n type ResolveLabelsOptions,\n defaultLabels,\n resolveLabels,\n} from \"./labels\";\n\nexport {\n FusionError,\n ImageLoadError,\n InferenceError,\n LabelMapError,\n ModelLoadError,\n NoDetectionsError,\n OrtVisionError,\n ProviderNotAvailableError,\n} from \"./core/exceptions\";\n\nexport {\n DEFAULT_MODEL_CACHE,\n GRAPH_OPTIMIZATION_KEY,\n type ModelSource,\n type OrtSessionOptions,\n OrtSession,\n QUANTIZATION_KEY,\n} from \"./core/session\";\nexport {\n type DeclaredDim,\n type DeclaredShape,\n type ResolveInputSizeOptions,\n classificationNumClasses,\n declaredShapesFrom,\n detectionNumClasses,\n resolveInputSize,\n spatialInputSize,\n} from \"./core/graph\";\nexport {\n DEFAULT_TENSOR_TYPE,\n type Float16ArrayLike,\n asFloat32Array,\n hasFloat16Array,\n tensorTypeFor,\n} from \"./core/dtypes\";\nexport { modelNames, parseNames, readModelInputTypes, readModelMetadata } from \"./core/metadata\";\nexport {\n DEFAULT_PROVIDERS,\n type ProviderSpec,\n detectProviders,\n resolveProviders,\n} from \"./core/providers\";\nexport { type Speed, SpeedTimer } from \"./core/timing\";\nexport {\n CUSTOM_NORMALIZATION,\n IDENTITY_MEAN,\n IDENTITY_STD,\n IMAGENET_MEAN,\n IMAGENET_STD,\n type Normalization,\n type ResolvedNormalization,\n isUltralyticsClassifier,\n resolveNormalization,\n} from \"./normalization\";\n\nexport { type ImageInput, loadImage } from \"./io/image\";\n\nexport {\n FUSION_KIND_DETECT_CLASSIFY,\n FUSION_KIND_DETECT_SEGMENT_CLASSIFY,\n INPUT_IMAGE,\n INPUT_PAD,\n INPUT_SCALE,\n INPUT_SOURCE,\n METADATA_PREFIX,\n OUTPUT_BOXES,\n OUTPUT_CLASSES,\n OUTPUT_MASKS,\n OUTPUT_NUM_DETECTIONS,\n OUTPUT_PROBS,\n OUTPUT_SCORES,\n type CropSource,\n type FusionSpec,\n readFusionSpec,\n} from \"./fusion\";\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 {\n type FusedLetterboxResult,\n type FusedResizeResult,\n LetterboxPipeline,\n ResizePipeline,\n letterboxToTensorData,\n resizeToTensorData,\n writePlanarFloat32,\n zeroTensorData,\n} from \"./preprocess/pipeline\";\n\nexport { type TopKResult, softmax, topK } from \"./postprocess/classification\";\n\nexport {\n type DecodeYoloAnchorsOptions,\n type DecodeYoloOptions,\n type DecodedAnchors,\n type DecodedDetection,\n batchedNms,\n decodeYolo,\n decodeYoloAnchors,\n nms,\n} from \"./postprocess/detection\";\n\nexport {\n type DecodeYoloSegOptions,\n type DecodedSegmentation,\n decodeYoloSeg,\n} from \"./postprocess/segmentation\";\n\nexport { VisionTask, requireDetections } from \"./tasks/base\";\nexport {\n type ClassifierOptions,\n type ClassifierPredictOptions,\n Classifier,\n} from \"./tasks/classifier\";\nexport {\n type DetectClassifyOptions,\n type DetectClassifyPredictOptions,\n DetectClassify,\n} from \"./tasks/detectClassify\";\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.11.0\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAwLA,IAAa,KAAkB"}
|
package/dist/vision/io/image.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../core/exceptions.cjs"),t=require("../types.cjs"),n=require("../core/canvas.cjs");async function r(r){if(r instanceof t.RGBImage)return
|
|
1
|
+
const e=require("../core/exceptions.cjs"),t=require("../types.cjs"),n=require("../core/canvas.cjs");async function r(e){return(await i(e)).image}async function i(r){if(r instanceof t.RGBImage)return{image:r,canvas:null,owned:!1};if(typeof ImageData<`u`&&r instanceof ImageData)return{image:n.imageDataToRGBChecked(r).image,canvas:null,owned:!0};if(typeof r==`string`)return a(r);if(typeof Blob<`u`&&r instanceof Blob)return o(r);if(typeof HTMLImageElement<`u`&&r instanceof HTMLImageElement)return await s(r),u(r,r.naturalWidth,r.naturalHeight);if(typeof HTMLVideoElement<`u`&&r instanceof HTMLVideoElement){if(r.readyState<2)throw new e.ImageLoadError(`HTMLVideoElement has no current frame yet (readyState < HAVE_CURRENT_DATA). Wait for its 'loadeddata' event before predicting on it.`);return u(r,r.videoWidth,r.videoHeight,l(r))}if(typeof HTMLCanvasElement<`u`&&r instanceof HTMLCanvasElement||typeof OffscreenCanvas<`u`&&r instanceof OffscreenCanvas||typeof ImageBitmap<`u`&&r instanceof ImageBitmap)return u(r,r.width,r.height);if(typeof VideoFrame<`u`&&r instanceof VideoFrame)return u(r,r.displayWidth,r.displayHeight,r.format!==null&&c.has(r.format));throw new e.ImageLoadError(`Unsupported image source type: ${Object.prototype.toString.call(r)}`)}async function a(t){let n;try{n=await fetch(t)}catch(n){throw new e.ImageLoadError(`Failed to fetch image from ${t}: ${n.message}`,{cause:n})}if(!n.ok)throw new e.ImageLoadError(`Failed to fetch image from ${t}: HTTP ${n.status} ${n.statusText}`);return o(await n.blob())}async function o(t){let n;try{n=await createImageBitmap(t)}catch(t){throw new e.ImageLoadError(`Failed to decode image blob: ${t.message}`,{cause:t})}try{return u(n,n.width,n.height,t.type===`image/jpeg`)}finally{n.close()}}function s(t){return t.complete&&t.naturalWidth>0?Promise.resolve():new Promise((n,r)=>{let i=()=>{o(),n()},a=()=>{o(),r(new e.ImageLoadError(`Failed to load HTMLImageElement (load event errored)`))},o=()=>{t.removeEventListener(`load`,i),t.removeEventListener(`error`,a)};t.addEventListener(`load`,i,{once:!0}),t.addEventListener(`error`,a,{once:!0})})}var c=new Set([`I420`,`I422`,`I444`,`NV12`,`RGBX`,`BGRX`]);function l(e){return typeof MediaStream<`u`&&e.srcObject instanceof MediaStream}function u(r,i,a,o=!1){if(i===0||a===0)throw new e.ImageLoadError(`Cannot load image with zero dimension (${i}x${a}).`);let s=n.createCanvas(i,a),c=n.get2DContext(s);if(c.drawImage(r,0,0,i,a),o)return{image:t.RGBImage.deferred(i,a,()=>n.imageDataToRGBChecked(c.getImageData(0,0,i,a)).image.data),canvas:s,owned:!0};let{image:l,opaque:u}=n.imageDataToRGBChecked(c.getImageData(0,0,i,a));return{image:l,canvas:u?s:null,owned:!0}}exports.loadImage=r,exports.loadImageSource=i;
|
|
2
2
|
//# sourceMappingURL=image.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.cjs","names":[],"sources":["../../../src/vision/io/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Image loading utilities — convert any supported source into the canonical\n * {@link RGBImage} format.\n *\n * Browser-only: uses `fetch`, `createImageBitmap`, and a Canvas 2D context to\n * decode arbitrary inputs into a tightly-packed `Uint8Array` of HWC RGB pixels.\n */\n\nimport { createCanvas, get2DContext, imageDataToRGB } from \"../core/canvas\";\nimport { ImageLoadError } from \"../core/exceptions\";\nimport { RGBImage } from \"../types\";\n\n/** Anything {@link loadImage} accepts as an image input. */\nexport type ImageInput =\n | string\n | Blob\n | HTMLImageElement\n | HTMLCanvasElement\n | OffscreenCanvas\n | ImageBitmap\n | ImageData\n | RGBImage;\n\n/**\n * Load an image from any supported source into a HWC uint8 RGB array.\n *\n * @throws {@link ImageLoadError} if the source cannot be decoded or has an unsupported shape.\n */\nexport async function loadImage(source: ImageInput): Promise<RGBImage> {\n if (source instanceof RGBImage) {\n return source;\n }\n\n if (typeof ImageData !== \"undefined\" && source instanceof ImageData) {\n return imageDataToRGB(source);\n }\n\n if (typeof source === \"string\") {\n return loadFromUrl(source);\n }\n\n if (typeof Blob !== \"undefined\" && source instanceof Blob) {\n return loadFromBlob(source);\n }\n\n if (typeof HTMLImageElement !== \"undefined\" && source instanceof HTMLImageElement) {\n await waitForImageElement(source);\n return drawableToRGB(source, source.naturalWidth, source.naturalHeight);\n }\n\n if (typeof HTMLCanvasElement !== \"undefined\" && source instanceof HTMLCanvasElement) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof OffscreenCanvas !== \"undefined\" && source instanceof OffscreenCanvas) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n throw new ImageLoadError(\n `Unsupported image source type: ${Object.prototype.toString.call(source)}`,\n );\n}\n\nasync function loadFromUrl(url: string): Promise<RGBImage> {\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n throw new ImageLoadError(`Failed to fetch image from ${url}: ${(err as Error).message}`, {\n cause: err,\n });\n }\n if (!response.ok) {\n throw new ImageLoadError(\n `Failed to fetch image from ${url}: HTTP ${response.status} ${response.statusText}`,\n );\n }\n const blob = await response.blob();\n return loadFromBlob(blob);\n}\n\nasync function loadFromBlob(blob: Blob): Promise<RGBImage> {\n let bitmap: ImageBitmap;\n try {\n bitmap = await createImageBitmap(blob);\n } catch (err) {\n throw new ImageLoadError(`Failed to decode image blob: ${(err as Error).message}`, {\n cause: err,\n });\n }\n try {\n return drawableToRGB(bitmap, bitmap.width, bitmap.height);\n } finally {\n bitmap.close();\n }\n}\n\nfunction waitForImageElement(img: HTMLImageElement): Promise<void> {\n if (img.complete && img.naturalWidth > 0) {\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n const onLoad = (): void => {\n cleanup();\n resolve();\n };\n const onError = (): void => {\n cleanup();\n reject(new ImageLoadError(\"Failed to load HTMLImageElement (load event errored)\"));\n };\n const cleanup = (): void => {\n img.removeEventListener(\"load\", onLoad);\n img.removeEventListener(\"error\", onError);\n };\n img.addEventListener(\"load\", onLoad, { once: true });\n img.addEventListener(\"error\", onError, { once: true });\n });\n}\n\nfunction drawableToRGB(drawable: CanvasImageSource, width: number, height: number): RGBImage {\n if (width === 0 || height === 0) {\n throw new ImageLoadError(`Cannot load image with zero dimension (${width}x${height}).`);\n }\n const canvas = createCanvas(width, height);\n const ctx = get2DContext(canvas);\n ctx.drawImage(drawable, 0, 0);\n const imageData = ctx.getImageData(0, 0, width, height);\n return imageDataToRGB(imageData);\n}\n"],"mappings":"oGA6BA,eAAsB,EAAU,EAAuC,CACnE,GAAI,aAAkB,EAAA,SAClB,OAAO,EAGX,GAAI,OAAO,UAAc,KAAe,aAAkB,UACtD,OAAO,EAAA,eAAe,CAAM,EAGhC,GAAI,OAAO,GAAW,SAClB,OAAO,EAAY,CAAM,EAG7B,GAAI,OAAO,KAAS,KAAe,aAAkB,KACjD,OAAO,EAAa,CAAM,EAG9B,GAAI,OAAO,iBAAqB,KAAe,aAAkB,iBAE7D,OADA,MAAM,EAAoB,CAAM,EACzB,EAAc,EAAQ,EAAO,aAAc,EAAO,aAAa,EAW1E,GARI,OAAO,kBAAsB,KAAe,aAAkB,mBAI9D,OAAO,gBAAoB,KAAe,aAAkB,iBAI5D,OAAO,YAAgB,KAAe,aAAkB,YACxD,OAAO,EAAc,EAAQ,EAAO,MAAO,EAAO,MAAM,EAG5D,MAAM,IAAI,EAAA,eACN,kCAAkC,OAAO,UAAU,SAAS,KAAK,CAAM,GAC3E,CACJ,CAEA,eAAe,EAAY,EAAgC,CACvD,IAAI,EACJ,GAAI,CACA,EAAW,MAAM,MAAM,CAAG,CAC9B,OAAS,EAAK,CACV,MAAM,IAAI,EAAA,eAAe,8BAA8B,EAAI,IAAK,EAAc,UAAW,CACrF,MAAO,CACX,CAAC,CACL,CACA,GAAI,CAAC,EAAS,GACV,MAAM,IAAI,EAAA,eACN,8BAA8B,EAAI,SAAS,EAAS,OAAO,GAAG,EAAS,YAC3E,EAGJ,OAAO,EAAa,MADD,EAAS,KAAK,CACT,CAC5B,CAEA,eAAe,EAAa,EAA+B,CACvD,IAAI,EACJ,GAAI,CACA,EAAS,MAAM,kBAAkB,CAAI,CACzC,OAAS,EAAK,CACV,MAAM,IAAI,EAAA,eAAe,gCAAiC,EAAc,UAAW,CAC/E,MAAO,CACX,CAAC,CACL,CACA,GAAI,CACA,OAAO,EAAc,EAAQ,EAAO,MAAO,EAAO,MAAM,CAC5D,QAAU,CACN,EAAO,MAAM,CACjB,CACJ,CAEA,SAAS,EAAoB,EAAsC,CAI/D,OAHI,EAAI,UAAY,EAAI,aAAe,EAC5B,QAAQ,QAAQ,EAEpB,IAAI,SAAe,EAAS,IAAW,CAC1C,IAAM,MAAqB,CACvB,EAAQ,EACR,EAAQ,CACZ,EACM,MAAsB,CACxB,EAAQ,EACR,EAAO,IAAI,EAAA,eAAe,sDAAsD,CAAC,CACrF,EACM,MAAsB,CACxB,EAAI,oBAAoB,OAAQ,CAAM,EACtC,EAAI,oBAAoB,QAAS,CAAO,CAC5C,EACA,EAAI,iBAAiB,OAAQ,EAAQ,CAAE,KAAM,EAAK,CAAC,EACnD,EAAI,iBAAiB,QAAS,EAAS,CAAE,KAAM,EAAK,CAAC,CACzD,CAAC,CACL,CAEA,SAAS,EAAc,EAA6B,EAAe,EAA0B,CACzF,GAAI,IAAU,GAAK,IAAW,EAC1B,MAAM,IAAI,EAAA,eAAe,0CAA0C,EAAM,GAAG,EAAO,GAAG,EAE1F,IAAM,EAAS,EAAA,aAAa,EAAO,CAAM,EACnC,EAAM,EAAA,aAAa,CAAM,EAC/B,EAAI,UAAU,EAAU,EAAG,CAAC,EAC5B,IAAM,EAAY,EAAI,aAAa,EAAG,EAAG,EAAO,CAAM,EACtD,OAAO,EAAA,eAAe,CAAS,CACnC"}
|
|
1
|
+
{"version":3,"file":"image.cjs","names":[],"sources":["../../../src/vision/io/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Image loading utilities — convert any supported source into the canonical\n * {@link RGBImage} format.\n *\n * Browser-only: uses `fetch`, `createImageBitmap`, and a Canvas 2D context to\n * decode arbitrary inputs into a tightly-packed `Uint8Array` of HWC RGB pixels.\n */\n\nimport { createCanvas, get2DContext, imageDataToRGBChecked } from \"../core/canvas\";\nimport { ImageLoadError } from \"../core/exceptions\";\nimport { RGBImage } from \"../types\";\n\n/** Anything {@link loadImage} accepts as an image input. */\nexport type ImageInput =\n | string\n | Blob\n | HTMLImageElement\n | HTMLVideoElement\n | HTMLCanvasElement\n | OffscreenCanvas\n | ImageBitmap\n | VideoFrame\n | ImageData\n | RGBImage;\n\n/**\n * A decoded input, plus what the tasks can reuse from decoding it.\n *\n * Internal to the SDK: the tasks need more than {@link loadImage} returns, and\n * the extra fields are about avoiding work, not about the image itself.\n */\nexport interface LoadedImage {\n /** The input as the canonical HWC RGB image. */\n readonly image: RGBImage;\n /**\n * A full-resolution canvas holding exactly {@link image}'s pixels, or `null`.\n *\n * Decoding any drawable already paints it onto a canvas to read it back.\n * Handing that canvas to a preprocessing pipeline lets it `drawImage` the\n * frame straight into the model input, instead of rebuilding RGBA from\n * {@link image} and `putImageData`-ing it onto a canvas of its own — two\n * full-resolution passes and an allocation the size of the frame. Only set\n * when every pixel was opaque: a translucent pixel composites differently\n * from the RGB that dropping its alpha kept.\n */\n readonly canvas: CanvasImageSource | null;\n /**\n * Whether {@link image}'s buffer was allocated here rather than passed in.\n *\n * An `RGBImage` the caller handed over is theirs, and a video loop may well\n * refill the same buffer every frame. Anything derived from it lazily would\n * then read a later frame, so lazy crops are only taken on owned buffers.\n */\n readonly owned: boolean;\n}\n\n/**\n * Load an image from any supported source into a HWC uint8 RGB array.\n *\n * A video element must have its current frame available (`readyState >= 2`);\n * the frame showing at the time of the call is the one decoded. A `VideoFrame`\n * is read but not closed — it belongs to the caller.\n *\n * @throws {@link ImageLoadError} if the source cannot be decoded or has an unsupported shape.\n */\nexport async function loadImage(source: ImageInput): Promise<RGBImage> {\n return (await loadImageSource(source)).image;\n}\n\n/**\n * Decode an input like {@link loadImage}, keeping what preprocessing can reuse.\n *\n * @param source Any {@link ImageInput}.\n * @returns The image, the canvas it was painted on (when reusable), and\n * whether the SDK owns the pixel buffer.\n * @throws {@link ImageLoadError} if the source cannot be decoded.\n */\nexport async function loadImageSource(source: ImageInput): Promise<LoadedImage> {\n if (source instanceof RGBImage) {\n return { image: source, canvas: null, owned: false };\n }\n\n if (typeof ImageData !== \"undefined\" && source instanceof ImageData) {\n return { image: imageDataToRGBChecked(source).image, canvas: null, owned: true };\n }\n\n if (typeof source === \"string\") {\n return loadFromUrl(source);\n }\n\n if (typeof Blob !== \"undefined\" && source instanceof Blob) {\n return loadFromBlob(source);\n }\n\n if (typeof HTMLImageElement !== \"undefined\" && source instanceof HTMLImageElement) {\n await waitForImageElement(source);\n return drawableToRGB(source, source.naturalWidth, source.naturalHeight);\n }\n\n if (typeof HTMLVideoElement !== \"undefined\" && source instanceof HTMLVideoElement) {\n if (source.readyState < 2) {\n throw new ImageLoadError(\n \"HTMLVideoElement has no current frame yet (readyState < HAVE_CURRENT_DATA). \" +\n \"Wait for its 'loadeddata' event before predicting on it.\",\n );\n }\n return drawableToRGB(source, source.videoWidth, source.videoHeight, isLiveStream(source));\n }\n\n if (typeof HTMLCanvasElement !== \"undefined\" && source instanceof HTMLCanvasElement) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof OffscreenCanvas !== \"undefined\" && source instanceof OffscreenCanvas) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof VideoFrame !== \"undefined\" && source instanceof VideoFrame) {\n return drawableToRGB(\n source,\n source.displayWidth,\n source.displayHeight,\n source.format !== null && OPAQUE_FRAME_FORMATS.has(source.format),\n );\n }\n\n throw new ImageLoadError(\n `Unsupported image source type: ${Object.prototype.toString.call(source)}`,\n );\n}\n\nasync function loadFromUrl(url: string): Promise<LoadedImage> {\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n throw new ImageLoadError(`Failed to fetch image from ${url}: ${(err as Error).message}`, {\n cause: err,\n });\n }\n if (!response.ok) {\n throw new ImageLoadError(\n `Failed to fetch image from ${url}: HTTP ${response.status} ${response.statusText}`,\n );\n }\n const blob = await response.blob();\n return loadFromBlob(blob);\n}\n\nasync function loadFromBlob(blob: Blob): Promise<LoadedImage> {\n let bitmap: ImageBitmap;\n try {\n bitmap = await createImageBitmap(blob);\n } catch (err) {\n throw new ImageLoadError(`Failed to decode image blob: ${(err as Error).message}`, {\n cause: err,\n });\n }\n try {\n return drawableToRGB(bitmap, bitmap.width, bitmap.height, blob.type === \"image/jpeg\");\n } finally {\n bitmap.close();\n }\n}\n\nfunction waitForImageElement(img: HTMLImageElement): Promise<void> {\n if (img.complete && img.naturalWidth > 0) {\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n const onLoad = (): void => {\n cleanup();\n resolve();\n };\n const onError = (): void => {\n cleanup();\n reject(new ImageLoadError(\"Failed to load HTMLImageElement (load event errored)\"));\n };\n const cleanup = (): void => {\n img.removeEventListener(\"load\", onLoad);\n img.removeEventListener(\"error\", onError);\n };\n img.addEventListener(\"load\", onLoad, { once: true });\n img.addEventListener(\"error\", onError, { once: true });\n });\n}\n\n/**\n * `VideoFrame` pixel formats that carry no alpha channel.\n *\n * The `A`-suffixed planar formats and `RGBA`/`BGRA` do; a frame in one of\n * these never has a translucent pixel.\n */\nconst OPAQUE_FRAME_FORMATS: ReadonlySet<string> = new Set([\n \"I420\",\n \"I422\",\n \"I444\",\n \"NV12\",\n \"RGBX\",\n \"BGRX\",\n]);\n\n/**\n * Whether a video element is playing a live capture (camera, screen).\n *\n * `MediaStream` video tracks carry no alpha, so every frame is opaque. A video\n * playing a file may not be — VP9 with alpha exists — so it gets no such\n * promise.\n *\n * @param video The element.\n */\nfunction isLiveStream(video: HTMLVideoElement): boolean {\n return typeof MediaStream !== \"undefined\" && video.srcObject instanceof MediaStream;\n}\n\n/**\n * Paint a drawable onto a fresh canvas and read it back as RGB.\n *\n * When the source is known to be opaque without looking — a JPEG, a camera\n * frame, an alpha-less `VideoFrame` — the read-back is deferred: the image's\n * pixels come out of the canvas the first time something reads `data`. The\n * canvas is this call's own, so it still holds the frame of this moment\n * however late that read happens. Preprocessing draws from the canvas and\n * never reads `data`, so a loop that only consumes boxes skips the\n * full-resolution `getImageData` altogether.\n *\n * Any other source is read back now, because whether its canvas may stand in\n * for the RGB image depends on every pixel being opaque, and only the read\n * tells.\n *\n * @param drawable The source to decode.\n * @param width Its intrinsic width.\n * @param height Its intrinsic height.\n * @param knownOpaque Whether the source cannot contain a translucent pixel.\n * @returns The decoded image, with the canvas attached when it is opaque.\n * @throws {@link ImageLoadError} for a zero-sized source.\n */\nfunction drawableToRGB(\n drawable: CanvasImageSource,\n width: number,\n height: number,\n knownOpaque: boolean = false,\n): LoadedImage {\n if (width === 0 || height === 0) {\n throw new ImageLoadError(`Cannot load image with zero dimension (${width}x${height}).`);\n }\n const canvas = createCanvas(width, height);\n const ctx = get2DContext(canvas);\n ctx.drawImage(drawable, 0, 0, width, height);\n if (knownOpaque) {\n const image = RGBImage.deferred(\n width,\n height,\n () => imageDataToRGBChecked(ctx.getImageData(0, 0, width, height)).image.data,\n );\n return { image, canvas, owned: true };\n }\n const { image, opaque } = imageDataToRGBChecked(ctx.getImageData(0, 0, width, height));\n return { image, canvas: opaque ? canvas : null, owned: true };\n}\n"],"mappings":"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"}
|
package/dist/vision/io/image.js
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import { ImageLoadError as e } from "../core/exceptions.js";
|
|
2
2
|
import { RGBImage as t } from "../types.js";
|
|
3
|
-
import { createCanvas as n, get2DContext as r,
|
|
3
|
+
import { createCanvas as n, get2DContext as r, imageDataToRGBChecked as i } from "../core/canvas.js";
|
|
4
4
|
//#region src/vision/io/image.ts
|
|
5
|
-
async function a(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
async function a(e) {
|
|
6
|
+
return (await o(e)).image;
|
|
7
|
+
}
|
|
8
|
+
async function o(n) {
|
|
9
|
+
if (n instanceof t) return {
|
|
10
|
+
image: n,
|
|
11
|
+
canvas: null,
|
|
12
|
+
owned: !1
|
|
13
|
+
};
|
|
14
|
+
if (typeof ImageData < "u" && n instanceof ImageData) return {
|
|
15
|
+
image: i(n).image,
|
|
16
|
+
canvas: null,
|
|
17
|
+
owned: !0
|
|
18
|
+
};
|
|
19
|
+
if (typeof n == "string") return s(n);
|
|
20
|
+
if (typeof Blob < "u" && n instanceof Blob) return c(n);
|
|
21
|
+
if (typeof HTMLImageElement < "u" && n instanceof HTMLImageElement) return await l(n), f(n, n.naturalWidth, n.naturalHeight);
|
|
22
|
+
if (typeof HTMLVideoElement < "u" && n instanceof HTMLVideoElement) {
|
|
23
|
+
if (n.readyState < 2) throw new e("HTMLVideoElement has no current frame yet (readyState < HAVE_CURRENT_DATA). Wait for its 'loadeddata' event before predicting on it.");
|
|
24
|
+
return f(n, n.videoWidth, n.videoHeight, d(n));
|
|
25
|
+
}
|
|
26
|
+
if (typeof HTMLCanvasElement < "u" && n instanceof HTMLCanvasElement || typeof OffscreenCanvas < "u" && n instanceof OffscreenCanvas || typeof ImageBitmap < "u" && n instanceof ImageBitmap) return f(n, n.width, n.height);
|
|
27
|
+
if (typeof VideoFrame < "u" && n instanceof VideoFrame) return f(n, n.displayWidth, n.displayHeight, n.format !== null && u.has(n.format));
|
|
12
28
|
throw new e(`Unsupported image source type: ${Object.prototype.toString.call(n)}`);
|
|
13
29
|
}
|
|
14
|
-
async function
|
|
30
|
+
async function s(t) {
|
|
15
31
|
let n;
|
|
16
32
|
try {
|
|
17
33
|
n = await fetch(t);
|
|
@@ -19,9 +35,9 @@ async function o(t) {
|
|
|
19
35
|
throw new e(`Failed to fetch image from ${t}: ${n.message}`, { cause: n });
|
|
20
36
|
}
|
|
21
37
|
if (!n.ok) throw new e(`Failed to fetch image from ${t}: HTTP ${n.status} ${n.statusText}`);
|
|
22
|
-
return
|
|
38
|
+
return c(await n.blob());
|
|
23
39
|
}
|
|
24
|
-
async function
|
|
40
|
+
async function c(t) {
|
|
25
41
|
let n;
|
|
26
42
|
try {
|
|
27
43
|
n = await createImageBitmap(t);
|
|
@@ -29,12 +45,12 @@ async function s(t) {
|
|
|
29
45
|
throw new e(`Failed to decode image blob: ${t.message}`, { cause: t });
|
|
30
46
|
}
|
|
31
47
|
try {
|
|
32
|
-
return
|
|
48
|
+
return f(n, n.width, n.height, t.type === "image/jpeg");
|
|
33
49
|
} finally {
|
|
34
50
|
n.close();
|
|
35
51
|
}
|
|
36
52
|
}
|
|
37
|
-
function
|
|
53
|
+
function l(t) {
|
|
38
54
|
return t.complete && t.naturalWidth > 0 ? Promise.resolve() : new Promise((n, r) => {
|
|
39
55
|
let i = () => {
|
|
40
56
|
o(), n();
|
|
@@ -46,14 +62,33 @@ function c(t) {
|
|
|
46
62
|
t.addEventListener("load", i, { once: !0 }), t.addEventListener("error", a, { once: !0 });
|
|
47
63
|
});
|
|
48
64
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
var u = /* @__PURE__ */ new Set([
|
|
66
|
+
"I420",
|
|
67
|
+
"I422",
|
|
68
|
+
"I444",
|
|
69
|
+
"NV12",
|
|
70
|
+
"RGBX",
|
|
71
|
+
"BGRX"
|
|
72
|
+
]);
|
|
73
|
+
function d(e) {
|
|
74
|
+
return typeof MediaStream < "u" && e.srcObject instanceof MediaStream;
|
|
75
|
+
}
|
|
76
|
+
function f(a, o, s, c = !1) {
|
|
77
|
+
if (o === 0 || s === 0) throw new e(`Cannot load image with zero dimension (${o}x${s}).`);
|
|
78
|
+
let l = n(o, s), u = r(l);
|
|
79
|
+
if (u.drawImage(a, 0, 0, o, s), c) return {
|
|
80
|
+
image: t.deferred(o, s, () => i(u.getImageData(0, 0, o, s)).image.data),
|
|
81
|
+
canvas: l,
|
|
82
|
+
owned: !0
|
|
83
|
+
};
|
|
84
|
+
let { image: d, opaque: f } = i(u.getImageData(0, 0, o, s));
|
|
85
|
+
return {
|
|
86
|
+
image: d,
|
|
87
|
+
canvas: f ? l : null,
|
|
88
|
+
owned: !0
|
|
89
|
+
};
|
|
55
90
|
}
|
|
56
91
|
//#endregion
|
|
57
|
-
export { a as loadImage };
|
|
92
|
+
export { a as loadImage, o as loadImageSource };
|
|
58
93
|
|
|
59
94
|
//# sourceMappingURL=image.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","names":[],"sources":["../../../src/vision/io/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Image loading utilities — convert any supported source into the canonical\n * {@link RGBImage} format.\n *\n * Browser-only: uses `fetch`, `createImageBitmap`, and a Canvas 2D context to\n * decode arbitrary inputs into a tightly-packed `Uint8Array` of HWC RGB pixels.\n */\n\nimport { createCanvas, get2DContext, imageDataToRGB } from \"../core/canvas\";\nimport { ImageLoadError } from \"../core/exceptions\";\nimport { RGBImage } from \"../types\";\n\n/** Anything {@link loadImage} accepts as an image input. */\nexport type ImageInput =\n | string\n | Blob\n | HTMLImageElement\n | HTMLCanvasElement\n | OffscreenCanvas\n | ImageBitmap\n | ImageData\n | RGBImage;\n\n/**\n * Load an image from any supported source into a HWC uint8 RGB array.\n *\n * @throws {@link ImageLoadError} if the source cannot be decoded or has an unsupported shape.\n */\nexport async function loadImage(source: ImageInput): Promise<RGBImage> {\n if (source instanceof RGBImage) {\n return source;\n }\n\n if (typeof ImageData !== \"undefined\" && source instanceof ImageData) {\n return imageDataToRGB(source);\n }\n\n if (typeof source === \"string\") {\n return loadFromUrl(source);\n }\n\n if (typeof Blob !== \"undefined\" && source instanceof Blob) {\n return loadFromBlob(source);\n }\n\n if (typeof HTMLImageElement !== \"undefined\" && source instanceof HTMLImageElement) {\n await waitForImageElement(source);\n return drawableToRGB(source, source.naturalWidth, source.naturalHeight);\n }\n\n if (typeof HTMLCanvasElement !== \"undefined\" && source instanceof HTMLCanvasElement) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof OffscreenCanvas !== \"undefined\" && source instanceof OffscreenCanvas) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n throw new ImageLoadError(\n `Unsupported image source type: ${Object.prototype.toString.call(source)}`,\n );\n}\n\nasync function loadFromUrl(url: string): Promise<RGBImage> {\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n throw new ImageLoadError(`Failed to fetch image from ${url}: ${(err as Error).message}`, {\n cause: err,\n });\n }\n if (!response.ok) {\n throw new ImageLoadError(\n `Failed to fetch image from ${url}: HTTP ${response.status} ${response.statusText}`,\n );\n }\n const blob = await response.blob();\n return loadFromBlob(blob);\n}\n\nasync function loadFromBlob(blob: Blob): Promise<RGBImage> {\n let bitmap: ImageBitmap;\n try {\n bitmap = await createImageBitmap(blob);\n } catch (err) {\n throw new ImageLoadError(`Failed to decode image blob: ${(err as Error).message}`, {\n cause: err,\n });\n }\n try {\n return drawableToRGB(bitmap, bitmap.width, bitmap.height);\n } finally {\n bitmap.close();\n }\n}\n\nfunction waitForImageElement(img: HTMLImageElement): Promise<void> {\n if (img.complete && img.naturalWidth > 0) {\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n const onLoad = (): void => {\n cleanup();\n resolve();\n };\n const onError = (): void => {\n cleanup();\n reject(new ImageLoadError(\"Failed to load HTMLImageElement (load event errored)\"));\n };\n const cleanup = (): void => {\n img.removeEventListener(\"load\", onLoad);\n img.removeEventListener(\"error\", onError);\n };\n img.addEventListener(\"load\", onLoad, { once: true });\n img.addEventListener(\"error\", onError, { once: true });\n });\n}\n\nfunction drawableToRGB(drawable: CanvasImageSource, width: number, height: number): RGBImage {\n if (width === 0 || height === 0) {\n throw new ImageLoadError(`Cannot load image with zero dimension (${width}x${height}).`);\n }\n const canvas = createCanvas(width, height);\n const ctx = get2DContext(canvas);\n ctx.drawImage(drawable, 0, 0);\n const imageData = ctx.getImageData(0, 0, width, height);\n return imageDataToRGB(imageData);\n}\n"],"mappings":";;;;AA6BA,eAAsB,EAAU,GAAuC;CACnE,IAAI,aAAkB,GAClB,OAAO;CAGX,IAAI,OAAO,YAAc,OAAe,aAAkB,WACtD,OAAO,EAAe,CAAM;CAGhC,IAAI,OAAO,KAAW,UAClB,OAAO,EAAY,CAAM;CAG7B,IAAI,OAAO,OAAS,OAAe,aAAkB,MACjD,OAAO,EAAa,CAAM;CAG9B,IAAI,OAAO,mBAAqB,OAAe,aAAkB,kBAE7D,OADA,MAAM,EAAoB,CAAM,GACzB,EAAc,GAAQ,EAAO,cAAc,EAAO,aAAa;CAW1E,IARI,OAAO,oBAAsB,OAAe,aAAkB,qBAI9D,OAAO,kBAAoB,OAAe,aAAkB,mBAI5D,OAAO,cAAgB,OAAe,aAAkB,aACxD,OAAO,EAAc,GAAQ,EAAO,OAAO,EAAO,MAAM;CAG5D,MAAM,IAAI,EACN,kCAAkC,OAAO,UAAU,SAAS,KAAK,CAAM,GAC3E;AACJ;AAEA,eAAe,EAAY,GAAgC;CACvD,IAAI;CACJ,IAAI;EACA,IAAW,MAAM,MAAM,CAAG;CAC9B,SAAS,GAAK;EACV,MAAM,IAAI,EAAe,8BAA8B,EAAI,IAAK,EAAc,WAAW,EACrF,OAAO,EACX,CAAC;CACL;CACA,IAAI,CAAC,EAAS,IACV,MAAM,IAAI,EACN,8BAA8B,EAAI,SAAS,EAAS,OAAO,GAAG,EAAS,YAC3E;CAGJ,OAAO,EAAa,MADD,EAAS,KAAK,CACT;AAC5B;AAEA,eAAe,EAAa,GAA+B;CACvD,IAAI;CACJ,IAAI;EACA,IAAS,MAAM,kBAAkB,CAAI;CACzC,SAAS,GAAK;EACV,MAAM,IAAI,EAAe,gCAAiC,EAAc,WAAW,EAC/E,OAAO,EACX,CAAC;CACL;CACA,IAAI;EACA,OAAO,EAAc,GAAQ,EAAO,OAAO,EAAO,MAAM;CAC5D,UAAU;EACN,EAAO,MAAM;CACjB;AACJ;AAEA,SAAS,EAAoB,GAAsC;CAI/D,OAHI,EAAI,YAAY,EAAI,eAAe,IAC5B,QAAQ,QAAQ,IAEpB,IAAI,SAAe,GAAS,MAAW;EAC1C,IAAM,UAAqB;GAEvB,AADA,EAAQ,GACR,EAAQ;EACZ,GACM,UAAsB;GAExB,AADA,EAAQ,GACR,EAAO,IAAI,EAAe,sDAAsD,CAAC;EACrF,GACM,UAAsB;GAExB,AADA,EAAI,oBAAoB,QAAQ,CAAM,GACtC,EAAI,oBAAoB,SAAS,CAAO;EAC5C;EAEA,AADA,EAAI,iBAAiB,QAAQ,GAAQ,EAAE,MAAM,GAAK,CAAC,GACnD,EAAI,iBAAiB,SAAS,GAAS,EAAE,MAAM,GAAK,CAAC;CACzD,CAAC;AACL;AAEA,SAAS,EAAc,GAA6B,GAAe,GAA0B;CACzF,IAAI,MAAU,KAAK,MAAW,GAC1B,MAAM,IAAI,EAAe,0CAA0C,EAAM,GAAG,EAAO,GAAG;CAE1F,IAAM,IAAS,EAAa,GAAO,CAAM,GACnC,IAAM,EAAa,CAAM;CAC/B,EAAI,UAAU,GAAU,GAAG,CAAC;CAC5B,IAAM,IAAY,EAAI,aAAa,GAAG,GAAG,GAAO,CAAM;CACtD,OAAO,EAAe,CAAS;AACnC"}
|
|
1
|
+
{"version":3,"file":"image.js","names":[],"sources":["../../../src/vision/io/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Image loading utilities — convert any supported source into the canonical\n * {@link RGBImage} format.\n *\n * Browser-only: uses `fetch`, `createImageBitmap`, and a Canvas 2D context to\n * decode arbitrary inputs into a tightly-packed `Uint8Array` of HWC RGB pixels.\n */\n\nimport { createCanvas, get2DContext, imageDataToRGBChecked } from \"../core/canvas\";\nimport { ImageLoadError } from \"../core/exceptions\";\nimport { RGBImage } from \"../types\";\n\n/** Anything {@link loadImage} accepts as an image input. */\nexport type ImageInput =\n | string\n | Blob\n | HTMLImageElement\n | HTMLVideoElement\n | HTMLCanvasElement\n | OffscreenCanvas\n | ImageBitmap\n | VideoFrame\n | ImageData\n | RGBImage;\n\n/**\n * A decoded input, plus what the tasks can reuse from decoding it.\n *\n * Internal to the SDK: the tasks need more than {@link loadImage} returns, and\n * the extra fields are about avoiding work, not about the image itself.\n */\nexport interface LoadedImage {\n /** The input as the canonical HWC RGB image. */\n readonly image: RGBImage;\n /**\n * A full-resolution canvas holding exactly {@link image}'s pixels, or `null`.\n *\n * Decoding any drawable already paints it onto a canvas to read it back.\n * Handing that canvas to a preprocessing pipeline lets it `drawImage` the\n * frame straight into the model input, instead of rebuilding RGBA from\n * {@link image} and `putImageData`-ing it onto a canvas of its own — two\n * full-resolution passes and an allocation the size of the frame. Only set\n * when every pixel was opaque: a translucent pixel composites differently\n * from the RGB that dropping its alpha kept.\n */\n readonly canvas: CanvasImageSource | null;\n /**\n * Whether {@link image}'s buffer was allocated here rather than passed in.\n *\n * An `RGBImage` the caller handed over is theirs, and a video loop may well\n * refill the same buffer every frame. Anything derived from it lazily would\n * then read a later frame, so lazy crops are only taken on owned buffers.\n */\n readonly owned: boolean;\n}\n\n/**\n * Load an image from any supported source into a HWC uint8 RGB array.\n *\n * A video element must have its current frame available (`readyState >= 2`);\n * the frame showing at the time of the call is the one decoded. A `VideoFrame`\n * is read but not closed — it belongs to the caller.\n *\n * @throws {@link ImageLoadError} if the source cannot be decoded or has an unsupported shape.\n */\nexport async function loadImage(source: ImageInput): Promise<RGBImage> {\n return (await loadImageSource(source)).image;\n}\n\n/**\n * Decode an input like {@link loadImage}, keeping what preprocessing can reuse.\n *\n * @param source Any {@link ImageInput}.\n * @returns The image, the canvas it was painted on (when reusable), and\n * whether the SDK owns the pixel buffer.\n * @throws {@link ImageLoadError} if the source cannot be decoded.\n */\nexport async function loadImageSource(source: ImageInput): Promise<LoadedImage> {\n if (source instanceof RGBImage) {\n return { image: source, canvas: null, owned: false };\n }\n\n if (typeof ImageData !== \"undefined\" && source instanceof ImageData) {\n return { image: imageDataToRGBChecked(source).image, canvas: null, owned: true };\n }\n\n if (typeof source === \"string\") {\n return loadFromUrl(source);\n }\n\n if (typeof Blob !== \"undefined\" && source instanceof Blob) {\n return loadFromBlob(source);\n }\n\n if (typeof HTMLImageElement !== \"undefined\" && source instanceof HTMLImageElement) {\n await waitForImageElement(source);\n return drawableToRGB(source, source.naturalWidth, source.naturalHeight);\n }\n\n if (typeof HTMLVideoElement !== \"undefined\" && source instanceof HTMLVideoElement) {\n if (source.readyState < 2) {\n throw new ImageLoadError(\n \"HTMLVideoElement has no current frame yet (readyState < HAVE_CURRENT_DATA). \" +\n \"Wait for its 'loadeddata' event before predicting on it.\",\n );\n }\n return drawableToRGB(source, source.videoWidth, source.videoHeight, isLiveStream(source));\n }\n\n if (typeof HTMLCanvasElement !== \"undefined\" && source instanceof HTMLCanvasElement) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof OffscreenCanvas !== \"undefined\" && source instanceof OffscreenCanvas) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof VideoFrame !== \"undefined\" && source instanceof VideoFrame) {\n return drawableToRGB(\n source,\n source.displayWidth,\n source.displayHeight,\n source.format !== null && OPAQUE_FRAME_FORMATS.has(source.format),\n );\n }\n\n throw new ImageLoadError(\n `Unsupported image source type: ${Object.prototype.toString.call(source)}`,\n );\n}\n\nasync function loadFromUrl(url: string): Promise<LoadedImage> {\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n throw new ImageLoadError(`Failed to fetch image from ${url}: ${(err as Error).message}`, {\n cause: err,\n });\n }\n if (!response.ok) {\n throw new ImageLoadError(\n `Failed to fetch image from ${url}: HTTP ${response.status} ${response.statusText}`,\n );\n }\n const blob = await response.blob();\n return loadFromBlob(blob);\n}\n\nasync function loadFromBlob(blob: Blob): Promise<LoadedImage> {\n let bitmap: ImageBitmap;\n try {\n bitmap = await createImageBitmap(blob);\n } catch (err) {\n throw new ImageLoadError(`Failed to decode image blob: ${(err as Error).message}`, {\n cause: err,\n });\n }\n try {\n return drawableToRGB(bitmap, bitmap.width, bitmap.height, blob.type === \"image/jpeg\");\n } finally {\n bitmap.close();\n }\n}\n\nfunction waitForImageElement(img: HTMLImageElement): Promise<void> {\n if (img.complete && img.naturalWidth > 0) {\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n const onLoad = (): void => {\n cleanup();\n resolve();\n };\n const onError = (): void => {\n cleanup();\n reject(new ImageLoadError(\"Failed to load HTMLImageElement (load event errored)\"));\n };\n const cleanup = (): void => {\n img.removeEventListener(\"load\", onLoad);\n img.removeEventListener(\"error\", onError);\n };\n img.addEventListener(\"load\", onLoad, { once: true });\n img.addEventListener(\"error\", onError, { once: true });\n });\n}\n\n/**\n * `VideoFrame` pixel formats that carry no alpha channel.\n *\n * The `A`-suffixed planar formats and `RGBA`/`BGRA` do; a frame in one of\n * these never has a translucent pixel.\n */\nconst OPAQUE_FRAME_FORMATS: ReadonlySet<string> = new Set([\n \"I420\",\n \"I422\",\n \"I444\",\n \"NV12\",\n \"RGBX\",\n \"BGRX\",\n]);\n\n/**\n * Whether a video element is playing a live capture (camera, screen).\n *\n * `MediaStream` video tracks carry no alpha, so every frame is opaque. A video\n * playing a file may not be — VP9 with alpha exists — so it gets no such\n * promise.\n *\n * @param video The element.\n */\nfunction isLiveStream(video: HTMLVideoElement): boolean {\n return typeof MediaStream !== \"undefined\" && video.srcObject instanceof MediaStream;\n}\n\n/**\n * Paint a drawable onto a fresh canvas and read it back as RGB.\n *\n * When the source is known to be opaque without looking — a JPEG, a camera\n * frame, an alpha-less `VideoFrame` — the read-back is deferred: the image's\n * pixels come out of the canvas the first time something reads `data`. The\n * canvas is this call's own, so it still holds the frame of this moment\n * however late that read happens. Preprocessing draws from the canvas and\n * never reads `data`, so a loop that only consumes boxes skips the\n * full-resolution `getImageData` altogether.\n *\n * Any other source is read back now, because whether its canvas may stand in\n * for the RGB image depends on every pixel being opaque, and only the read\n * tells.\n *\n * @param drawable The source to decode.\n * @param width Its intrinsic width.\n * @param height Its intrinsic height.\n * @param knownOpaque Whether the source cannot contain a translucent pixel.\n * @returns The decoded image, with the canvas attached when it is opaque.\n * @throws {@link ImageLoadError} for a zero-sized source.\n */\nfunction drawableToRGB(\n drawable: CanvasImageSource,\n width: number,\n height: number,\n knownOpaque: boolean = false,\n): LoadedImage {\n if (width === 0 || height === 0) {\n throw new ImageLoadError(`Cannot load image with zero dimension (${width}x${height}).`);\n }\n const canvas = createCanvas(width, height);\n const ctx = get2DContext(canvas);\n ctx.drawImage(drawable, 0, 0, width, height);\n if (knownOpaque) {\n const image = RGBImage.deferred(\n width,\n height,\n () => imageDataToRGBChecked(ctx.getImageData(0, 0, width, height)).image.data,\n );\n return { image, canvas, owned: true };\n }\n const { image, opaque } = imageDataToRGBChecked(ctx.getImageData(0, 0, width, height));\n return { image, canvas: opaque ? canvas : null, owned: true };\n}\n"],"mappings":"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"}
|
|
@@ -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=
|
|
1
|
+
const e=require("../types.cjs");function t(e,t,n){let r=t.length;if(r===0)return new Int32Array;let i=Array(r);for(let e=0;e<r;e++)i[e]=e;i.sort((e,n)=>t[n]-t[e]||e-n);let a=new Float32Array(r*4),o=new Float32Array(r);for(let t=0;t<r;t++){let n=i[t]*4,r=e[n],s=e[n+1],c=e[n+2],l=e[n+3];a[t*4]=r,a[t*4+1]=s,a[t*4+2]=c,a[t*4+3]=l,o[t]=Math.max(0,c-r)*Math.max(0,l-s)}let s=n>=0,c=new Uint8Array(r),l=[];for(let e=0;e<r;e++){if(c[e])continue;l.push(i[e]);let t=a[e*4],u=a[e*4+1],d=a[e*4+2],f=a[e*4+3],p=o[e];for(let i=e+1;i<r;i++){if(c[i])continue;let e=a[i*4],r=a[i*4+1],l=a[i*4+2],m=a[i*4+3],h=Math.max(0,Math.min(d,l)-Math.max(t,e));if(h===0&&s)continue;let g=h*Math.max(0,Math.min(f,m)-Math.max(u,r)),_=p+o[i]-g;(_>0?g/_:0)>n&&(c[i]=1)}}return Int32Array.from(l)}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]||e-t),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 _=new Uint8Array(s),v=(4+c)*s;for(let t=4*s;t<v;t+=s)for(let n=0;n<s;n++)e[t+n]>=m&&(_[n]=1);let y=0,b=new Int32Array(s);for(let e=0;e<s;e++)_[e]===1&&(b[y++]=e);if(y===0)return i();let x=new Float32Array(y*4),S=new Float32Array(y),C=new Int32Array(y);for(let t=0;t<y;t++){let n=b[t],r=e[n],i=e[s+n],a=e[2*s+n],o=e[3*s+n],m=(r-a/2-d)/p,h=(i-o/2-f)/p,g=(r+a/2-d)/p,_=(i+o/2-f)/p;x[t*4]=Math.max(0,Math.min(l,m)),x[t*4+1]=Math.max(0,Math.min(u,h)),x[t*4+2]=Math.max(0,Math.min(l,g)),x[t*4+3]=Math.max(0,Math.min(u,_));let v=-1/0,y=0;for(let t=0,r=4*s+n;t<c;t++,r+=s){let n=e[r];n>v&&(v=n,y=t)}S[t]=v,C[t]=y}let w=n(x,S,C,h);if(w.length===0)return i();let T=Math.min(w.length,g),E=new Int32Array(T),D=new Float32Array(T*4),O=new Int32Array(T),k=new Float32Array(T);for(let e=0;e<T;e++){let t=w[e];E[e]=b[t],D[e*4]=x[t*4],D[e*4+1]=x[t*4+1],D[e*4+2]=x[t*4+2],D[e*4+3]=x[t*4+3],O[e]=C[t],k[e]=S[t]}return{anchorIndices:E,boxesXyxy:D,classIds:O,confidences:k}}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}exports.batchedNms=n,exports.decodeYolo=a,exports.decodeYoloAnchors=r,exports.nms=t;
|
|
2
2
|
//# sourceMappingURL=detection.cjs.map
|