tempest-react-sdk 0.33.2 → 0.35.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.
Files changed (87) hide show
  1. package/README.md +5 -3
  2. package/dist/components/AIChat/AIChat.cjs +2 -0
  3. package/dist/components/AIChat/AIChat.cjs.map +1 -0
  4. package/dist/components/AIChat/AIChat.js +141 -0
  5. package/dist/components/AIChat/AIChat.js.map +1 -0
  6. package/dist/components/AIChat/AIChat.module.cjs +2 -0
  7. package/dist/components/AIChat/AIChat.module.cjs.map +1 -0
  8. package/dist/components/AIChat/AIChat.module.js +58 -0
  9. package/dist/components/AIChat/AIChat.module.js.map +1 -0
  10. package/dist/components/AIChat/AIChatComposer.cjs +2 -0
  11. package/dist/components/AIChat/AIChatComposer.cjs.map +1 -0
  12. package/dist/components/AIChat/AIChatComposer.js +87 -0
  13. package/dist/components/AIChat/AIChatComposer.js.map +1 -0
  14. package/dist/components/AIChat/AIChatTurn.cjs +3 -0
  15. package/dist/components/AIChat/AIChatTurn.cjs.map +1 -0
  16. package/dist/components/AIChat/AIChatTurn.js +217 -0
  17. package/dist/components/AIChat/AIChatTurn.js.map +1 -0
  18. package/dist/components/AIChat/ai-chat-turns.cjs +2 -0
  19. package/dist/components/AIChat/ai-chat-turns.cjs.map +1 -0
  20. package/dist/components/AIChat/ai-chat-turns.js +90 -0
  21. package/dist/components/AIChat/ai-chat-turns.js.map +1 -0
  22. package/dist/perf/cache-size.cjs +2 -0
  23. package/dist/perf/cache-size.cjs.map +1 -0
  24. package/dist/perf/cache-size.js +16 -0
  25. package/dist/perf/cache-size.js.map +1 -0
  26. package/dist/perf/device.cjs +2 -0
  27. package/dist/perf/device.cjs.map +1 -0
  28. package/dist/perf/device.js +22 -0
  29. package/dist/perf/device.js.map +1 -0
  30. package/dist/perf/format.cjs +2 -0
  31. package/dist/perf/format.cjs.map +1 -0
  32. package/dist/perf/format.js +8 -0
  33. package/dist/perf/format.js.map +1 -0
  34. package/dist/perf/profiler.cjs +2 -0
  35. package/dist/perf/profiler.cjs.map +1 -0
  36. package/dist/perf/profiler.js +46 -0
  37. package/dist/perf/profiler.js.map +1 -0
  38. package/dist/styles.css +1 -1
  39. package/dist/tempest-react-sdk.cjs +1 -1
  40. package/dist/tempest-react-sdk.d.ts +626 -9
  41. package/dist/tempest-react-sdk.js +122 -114
  42. package/dist/vision/core/timing.cjs +2 -0
  43. package/dist/vision/core/timing.cjs.map +1 -0
  44. package/dist/vision/core/timing.js +24 -0
  45. package/dist/vision/core/timing.js.map +1 -0
  46. package/dist/vision/index.cjs +1 -1
  47. package/dist/vision/index.cjs.map +1 -1
  48. package/dist/vision/index.js +16 -15
  49. package/dist/vision/index.js.map +1 -1
  50. package/dist/vision/postprocess/detection.cjs +1 -1
  51. package/dist/vision/postprocess/detection.cjs.map +1 -1
  52. package/dist/vision/postprocess/detection.js +2 -2
  53. package/dist/vision/postprocess/detection.js.map +1 -1
  54. package/dist/vision/postprocess/segmentation.cjs +1 -1
  55. package/dist/vision/postprocess/segmentation.cjs.map +1 -1
  56. package/dist/vision/postprocess/segmentation.js +1 -1
  57. package/dist/vision/postprocess/segmentation.js.map +1 -1
  58. package/dist/vision/results.cjs +1 -1
  59. package/dist/vision/results.cjs.map +1 -1
  60. package/dist/vision/results.js +18 -13
  61. package/dist/vision/results.js.map +1 -1
  62. package/dist/vision/tasks/classifier.cjs +1 -1
  63. package/dist/vision/tasks/classifier.cjs.map +1 -1
  64. package/dist/vision/tasks/classifier.js +46 -39
  65. package/dist/vision/tasks/classifier.js.map +1 -1
  66. package/dist/vision/tasks/detector.cjs +1 -1
  67. package/dist/vision/tasks/detector.cjs.map +1 -1
  68. package/dist/vision/tasks/detector.js +40 -33
  69. package/dist/vision/tasks/detector.js.map +1 -1
  70. package/dist/vision/tasks/segmenter.cjs +1 -1
  71. package/dist/vision/tasks/segmenter.cjs.map +1 -1
  72. package/dist/vision/tasks/segmenter.js +35 -28
  73. package/dist/vision/tasks/segmenter.js.map +1 -1
  74. package/dist/vision.cjs +1 -1
  75. package/dist/vision.d.ts +68 -10
  76. package/dist/vision.js +19 -18
  77. package/dist/ws/create-web-socket.cjs +1 -1
  78. package/dist/ws/create-web-socket.cjs.map +1 -1
  79. package/dist/ws/create-web-socket.js +54 -37
  80. package/dist/ws/create-web-socket.js.map +1 -1
  81. package/dist/ws/use-web-socket.cjs +1 -1
  82. package/dist/ws/use-web-socket.cjs.map +1 -1
  83. package/dist/ws/use-web-socket.js +49 -18
  84. package/dist/ws/use-web-socket.js.map +1 -1
  85. package/package.json +1 -1
  86. package/template/src/lib/api.ts +27 -5
  87. package/template/src/stores/auth.ts +14 -0
@@ -118,10 +118,10 @@ function a(t, n, i) {
118
118
  }
119
119
  var o = !1, s = !1;
120
120
  function c(e, t, n) {
121
- return o || (o = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. The alias will be removed in 0.3.0.")), a(e, t, n);
121
+ return o || (o = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. The alias will be removed in 0.4.0.")), a(e, t, n);
122
122
  }
123
123
  function l(e, t, n) {
124
- return s || (s = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. The alias will be removed in 0.3.0.")), r(e, t, n);
124
+ return s || (s = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. The alias will be removed in 0.4.0.")), r(e, t, n);
125
125
  }
126
126
  //#endregion
127
127
  export { n as batchedNms, a as decodeYolo, r as decodeYoloAnchors, c as decodeYoloV8, l as decodeYoloV8Anchors, t as nms };
@@ -1 +1 @@
1
- {"version":3,"file":"detection.js","names":[],"sources":["../../../src/vision/postprocess/detection.ts"],"sourcesContent":["/**\n * Detection head postprocessing: anchor-free YOLO decoding + non-maximum suppression.\n *\n * The shared {@link decodeYoloAnchors} helper does the per-anchor work that\n * is identical for plain detection and segmentation (transpose, xywh→xyxy,\n * letterbox unmap, per-class NMS, sort & cap). {@link decodeYolo} is a thin\n * wrapper around it; the segmentation module ({@link ./segmentation.js})\n * calls the helper directly so it can also recover the per-anchor mask\n * coefficients.\n *\n * Works for any YOLO export with the post-v8 anchor-free head:\n * **YOLOv8 / v9 / v10 / v11 / v12** detect heads, all of which share the\n * `[1, 4 + nc, N]` output layout.\n */\n\nimport { BoundingBox } from \"../types\";\n\n/**\n * Greedy non-maximum suppression on axis-aligned bounding boxes.\n *\n * Mirrors `torchvision.ops.nms` (keeps boxes with the highest score, drops\n * any subsequent box whose IoU exceeds the threshold).\n *\n * @param boxes Flat array of length `4 * N` in xyxy order: `[x1,y1,x2,y2, ...]`.\n * @param scores Detection score per box, length `N`.\n * @param iouThreshold Boxes with IoU above this threshold relative to a kept box are suppressed.\n * @returns Indices of kept boxes, in descending score order.\n */\nexport function nms(boxes: Float32Array, scores: Float32Array, iouThreshold: number): Int32Array {\n const n = scores.length;\n if (n === 0) return new Int32Array(0);\n\n const areas = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const x1 = boxes[i * 4] as number;\n const y1 = boxes[i * 4 + 1] as number;\n const x2 = boxes[i * 4 + 2] as number;\n const y2 = boxes[i * 4 + 3] as number;\n areas[i] = Math.max(0, x2 - x1) * Math.max(0, y2 - y1);\n }\n\n const order = new Array<number>(n);\n for (let i = 0; i < n; i++) order[i] = i;\n order.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n\n const suppressed = new Uint8Array(n);\n const keep: number[] = [];\n\n for (let oi = 0; oi < order.length; oi++) {\n const i = order[oi] as number;\n if (suppressed[i]) continue;\n keep.push(i);\n\n const ax1 = boxes[i * 4] as number;\n const ay1 = boxes[i * 4 + 1] as number;\n const ax2 = boxes[i * 4 + 2] as number;\n const ay2 = boxes[i * 4 + 3] as number;\n const ai = areas[i] as number;\n\n for (let oj = oi + 1; oj < order.length; oj++) {\n const j = order[oj] as number;\n if (suppressed[j]) continue;\n\n const bx1 = boxes[j * 4] as number;\n const by1 = boxes[j * 4 + 1] as number;\n const bx2 = boxes[j * 4 + 2] as number;\n const by2 = boxes[j * 4 + 3] as number;\n\n const ix1 = Math.max(ax1, bx1);\n const iy1 = Math.max(ay1, by1);\n const ix2 = Math.min(ax2, bx2);\n const iy2 = Math.min(ay2, by2);\n const iw = Math.max(0, ix2 - ix1);\n const ih = Math.max(0, iy2 - iy1);\n const inter = iw * ih;\n const union = ai + (areas[j] as number) - inter;\n const iou = union > 0 ? inter / union : 0;\n if (iou > iouThreshold) suppressed[j] = 1;\n }\n }\n\n return Int32Array.from(keep);\n}\n\n/**\n * Per-class NMS — boxes are suppressed only by other boxes of the same class.\n *\n * Mirrors `torchvision.ops.batched_nms`.\n *\n * @param boxes Flat array of length `4 * N` in xyxy order.\n * @param scores Detection score per box, length `N`.\n * @param idxs Class index per box, length `N`. Boxes with different `idxs`\n * never suppress each other.\n * @param iouThreshold IoU threshold for suppression within a class.\n */\nexport function batchedNms(\n boxes: Float32Array,\n scores: Float32Array,\n idxs: Int32Array,\n iouThreshold: number,\n): Int32Array {\n if (scores.length === 0) return new Int32Array(0);\n\n const byClass = new Map<number, number[]>();\n for (let i = 0; i < idxs.length; i++) {\n const c = idxs[i] as number;\n const list = byClass.get(c);\n if (list === undefined) byClass.set(c, [i]);\n else list.push(i);\n }\n\n const keep: number[] = [];\n for (const indices of byClass.values()) {\n const m = indices.length;\n const subBoxes = new Float32Array(m * 4);\n const subScores = new Float32Array(m);\n for (let k = 0; k < m; k++) {\n const i = indices[k] as number;\n subBoxes[k * 4] = boxes[i * 4] as number;\n subBoxes[k * 4 + 1] = boxes[i * 4 + 1] as number;\n subBoxes[k * 4 + 2] = boxes[i * 4 + 2] as number;\n subBoxes[k * 4 + 3] = boxes[i * 4 + 3] as number;\n subScores[k] = scores[i] as number;\n }\n const subKeep = nms(subBoxes, subScores, iouThreshold);\n for (let k = 0; k < subKeep.length; k++) {\n keep.push(indices[subKeep[k] as number] as number);\n }\n }\n\n keep.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n return Int32Array.from(keep);\n}\n\nexport interface DecodeYoloAnchorsOptions {\n /** Number of class-score channels following the 4 box channels. */\n readonly numClasses: number;\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedAnchors {\n /** Indices into the original `numAnchors` axis, in descending confidence order. */\n readonly anchorIndices: Int32Array;\n /** `[k, 4]` boxes in original-image pixel coords, flat row-major xyxy. */\n readonly boxesXyxy: Float32Array;\n /** Predicted class id per survivor. */\n readonly classIds: Int32Array;\n /** Confidence per survivor. */\n readonly confidences: Float32Array;\n}\n\n/**\n * Shared YOLO per-anchor decode used by both detection and segmentation\n * (v8 / v9 / v10 / v11 / v12).\n *\n * Only the first `4 + numClasses` channels are read; later channels (e.g.\n * mask coefficients) are ignored — callers can fetch them via the returned\n * {@link DecodedAnchors.anchorIndices}.\n *\n * @param data Flat per-anchor output, length `channels * numAnchors`.\n * @param dims Dims as reported by ORT, e.g. `[1, 84, 8400]` (det) or\n * `[1, 116, 8400]` (seg). The leading batch dim must be 1.\n */\nexport function decodeYoloAnchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n let normalized = dims;\n if (normalized.length === 3) {\n if (normalized[0] !== 1) {\n throw new Error(`decodeYoloAnchors: expected batch size 1, got ${normalized[0]}.`);\n }\n normalized = [normalized[1] as number, normalized[2] as number];\n }\n if (normalized.length !== 2) {\n throw new Error(\n `decodeYoloAnchors: expected 2-D output after batch removal, got dims=${JSON.stringify(dims)}.`,\n );\n }\n const channels = normalized[0] as number;\n const numAnchors = normalized[1] as number;\n\n const {\n numClasses,\n originalWidth,\n originalHeight,\n padLeft,\n padTop,\n scale,\n confThreshold,\n iouThreshold,\n maxDetections,\n } = options;\n\n if (numClasses < 1 || numClasses + 4 > channels) {\n throw new Error(\n `decodeYoloAnchors: invalid numClasses=${numClasses} for channels=${channels}.`,\n );\n }\n if (data.length !== channels * numAnchors) {\n throw new Error(\n `decodeYoloAnchors: data length ${data.length} does not match channels*numAnchors=${channels * numAnchors}.`,\n );\n }\n\n type Candidate = {\n anchorIdx: number;\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n classId: number;\n confidence: number;\n };\n const candidates: Candidate[] = [];\n\n for (let a = 0; a < numAnchors; a++) {\n let bestCls = 0;\n let bestScore = -Infinity;\n for (let c = 0; c < numClasses; c++) {\n const s = data[(4 + c) * numAnchors + a];\n if (s !== undefined && s > bestScore) {\n bestScore = s;\n bestCls = c;\n }\n }\n if (bestScore < confThreshold) continue;\n\n const cx = data[a] as number;\n const cy = data[numAnchors + a] as number;\n const w = data[2 * numAnchors + a] as number;\n const h = data[3 * numAnchors + a] as number;\n\n let x1 = cx - w / 2;\n let y1 = cy - h / 2;\n let x2 = cx + w / 2;\n let y2 = cy + h / 2;\n\n x1 = (x1 - padLeft) / scale;\n y1 = (y1 - padTop) / scale;\n x2 = (x2 - padLeft) / scale;\n y2 = (y2 - padTop) / scale;\n\n x1 = Math.max(0, Math.min(originalWidth, x1));\n y1 = Math.max(0, Math.min(originalHeight, y1));\n x2 = Math.max(0, Math.min(originalWidth, x2));\n y2 = Math.max(0, Math.min(originalHeight, y2));\n\n candidates.push({ anchorIdx: a, x1, y1, x2, y2, classId: bestCls, confidence: bestScore });\n }\n\n if (candidates.length === 0) return emptyDecoded();\n\n // Build flat arrays then delegate to batchedNms — same algorithm as before\n // but funnelled through the public per-class NMS helper.\n const flatBoxes = new Float32Array(candidates.length * 4);\n const scoresArr = new Float32Array(candidates.length);\n const idxsArr = new Int32Array(candidates.length);\n for (let i = 0; i < candidates.length; i++) {\n const c = candidates[i] as Candidate;\n flatBoxes[i * 4] = c.x1;\n flatBoxes[i * 4 + 1] = c.y1;\n flatBoxes[i * 4 + 2] = c.x2;\n flatBoxes[i * 4 + 3] = c.y2;\n scoresArr[i] = c.confidence;\n idxsArr[i] = c.classId;\n }\n const kept = batchedNms(flatBoxes, scoresArr, idxsArr, iouThreshold);\n if (kept.length === 0) return emptyDecoded();\n\n const limited = Array.from(kept).slice(0, maxDetections);\n const k = limited.length;\n const anchorIndices = new Int32Array(k);\n const boxesXyxy = new Float32Array(k * 4);\n const classIds = new Int32Array(k);\n const confidences = new Float32Array(k);\n for (let i = 0; i < k; i++) {\n const c = candidates[limited[i] as number] as Candidate;\n anchorIndices[i] = c.anchorIdx;\n boxesXyxy[i * 4] = c.x1;\n boxesXyxy[i * 4 + 1] = c.y1;\n boxesXyxy[i * 4 + 2] = c.x2;\n boxesXyxy[i * 4 + 3] = c.y2;\n classIds[i] = c.classId;\n confidences[i] = c.confidence;\n }\n return { anchorIndices, boxesXyxy, classIds, confidences };\n}\n\nfunction emptyDecoded(): DecodedAnchors {\n return {\n anchorIndices: new Int32Array(0),\n boxesXyxy: new Float32Array(0),\n classIds: new Int32Array(0),\n confidences: new Float32Array(0),\n };\n}\n\nexport interface DecodeYoloOptions {\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedDetection {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n}\n\n/**\n * Decode an anchor-free YOLO detection output into a list of detections.\n *\n * Works for **YOLOv8 / v9 / v10 / v11 / v12** detect heads.\n *\n * Expected raw shape: `[1, 4 + numClasses, N]`. `numClasses` is inferred\n * from the channel count.\n */\nexport function decodeYolo(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n const channels = outputDims.length === 3 ? outputDims[1] : outputDims[0];\n if (channels === undefined || channels < 5) {\n throw new Error(`decodeYolo: invalid output channel count ${channels} (expected >= 5).`);\n }\n const numClasses = channels - 4;\n\n const decoded = decodeYoloAnchors(output, outputDims, {\n numClasses,\n ...options,\n });\n\n const results: DecodedDetection[] = [];\n for (let i = 0; i < decoded.classIds.length; i++) {\n results.push({\n bbox: new BoundingBox(\n decoded.boxesXyxy[i * 4] as number,\n decoded.boxesXyxy[i * 4 + 1] as number,\n decoded.boxesXyxy[i * 4 + 2] as number,\n decoded.boxesXyxy[i * 4 + 3] as number,\n ),\n classId: decoded.classIds[i] as number,\n confidence: decoded.confidences[i] as number,\n });\n }\n return results;\n}\n\nlet _warnedDecodeYoloV8 = false;\nlet _warnedDecodeYoloV8Anchors = false;\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYolo}. Same behavior; the\n * decoder covers v8/v9/v10/v11/v12 detect heads. Will be removed in 0.3.0.\n */\nexport function decodeYoloV8(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n if (!_warnedDecodeYoloV8) {\n _warnedDecodeYoloV8 = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. \" +\n \"The alias will be removed in 0.3.0.\",\n );\n }\n return decodeYolo(output, outputDims, options);\n}\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYoloAnchors}. Will be removed in 0.3.0.\n */\nexport function decodeYoloV8Anchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n if (!_warnedDecodeYoloV8Anchors) {\n _warnedDecodeYoloV8Anchors = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. \" +\n \"The alias will be removed in 0.3.0.\",\n );\n }\n return decodeYoloAnchors(data, dims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloAnchorsOptions}. */\nexport type DecodeYoloV8AnchorsOptions = DecodeYoloAnchorsOptions;\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloOptions}. */\nexport type DecodeYoloV8Options = DecodeYoloOptions;\n"],"mappings":"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"}
1
+ {"version":3,"file":"detection.js","names":[],"sources":["../../../src/vision/postprocess/detection.ts"],"sourcesContent":["/**\n * Detection head postprocessing: anchor-free YOLO decoding + non-maximum suppression.\n *\n * The shared {@link decodeYoloAnchors} helper does the per-anchor work that\n * is identical for plain detection and segmentation (transpose, xywh→xyxy,\n * letterbox unmap, per-class NMS, sort & cap). {@link decodeYolo} is a thin\n * wrapper around it; the segmentation module ({@link ./segmentation.js})\n * calls the helper directly so it can also recover the per-anchor mask\n * coefficients.\n *\n * Works for any YOLO export with the post-v8 anchor-free head:\n * **YOLOv8 / v9 / v10 / v11 / v12** detect heads, all of which share the\n * `[1, 4 + nc, N]` output layout.\n */\n\nimport { BoundingBox } from \"../types\";\n\n/**\n * Greedy non-maximum suppression on axis-aligned bounding boxes.\n *\n * Mirrors `torchvision.ops.nms` (keeps boxes with the highest score, drops\n * any subsequent box whose IoU exceeds the threshold).\n *\n * @param boxes Flat array of length `4 * N` in xyxy order: `[x1,y1,x2,y2, ...]`.\n * @param scores Detection score per box, length `N`.\n * @param iouThreshold Boxes with IoU above this threshold relative to a kept box are suppressed.\n * @returns Indices of kept boxes, in descending score order.\n */\nexport function nms(boxes: Float32Array, scores: Float32Array, iouThreshold: number): Int32Array {\n const n = scores.length;\n if (n === 0) return new Int32Array(0);\n\n const areas = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const x1 = boxes[i * 4] as number;\n const y1 = boxes[i * 4 + 1] as number;\n const x2 = boxes[i * 4 + 2] as number;\n const y2 = boxes[i * 4 + 3] as number;\n areas[i] = Math.max(0, x2 - x1) * Math.max(0, y2 - y1);\n }\n\n const order = new Array<number>(n);\n for (let i = 0; i < n; i++) order[i] = i;\n order.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n\n const suppressed = new Uint8Array(n);\n const keep: number[] = [];\n\n for (let oi = 0; oi < order.length; oi++) {\n const i = order[oi] as number;\n if (suppressed[i]) continue;\n keep.push(i);\n\n const ax1 = boxes[i * 4] as number;\n const ay1 = boxes[i * 4 + 1] as number;\n const ax2 = boxes[i * 4 + 2] as number;\n const ay2 = boxes[i * 4 + 3] as number;\n const ai = areas[i] as number;\n\n for (let oj = oi + 1; oj < order.length; oj++) {\n const j = order[oj] as number;\n if (suppressed[j]) continue;\n\n const bx1 = boxes[j * 4] as number;\n const by1 = boxes[j * 4 + 1] as number;\n const bx2 = boxes[j * 4 + 2] as number;\n const by2 = boxes[j * 4 + 3] as number;\n\n const ix1 = Math.max(ax1, bx1);\n const iy1 = Math.max(ay1, by1);\n const ix2 = Math.min(ax2, bx2);\n const iy2 = Math.min(ay2, by2);\n const iw = Math.max(0, ix2 - ix1);\n const ih = Math.max(0, iy2 - iy1);\n const inter = iw * ih;\n const union = ai + (areas[j] as number) - inter;\n const iou = union > 0 ? inter / union : 0;\n if (iou > iouThreshold) suppressed[j] = 1;\n }\n }\n\n return Int32Array.from(keep);\n}\n\n/**\n * Per-class NMS — boxes are suppressed only by other boxes of the same class.\n *\n * Mirrors `torchvision.ops.batched_nms`.\n *\n * @param boxes Flat array of length `4 * N` in xyxy order.\n * @param scores Detection score per box, length `N`.\n * @param idxs Class index per box, length `N`. Boxes with different `idxs`\n * never suppress each other.\n * @param iouThreshold IoU threshold for suppression within a class.\n */\nexport function batchedNms(\n boxes: Float32Array,\n scores: Float32Array,\n idxs: Int32Array,\n iouThreshold: number,\n): Int32Array {\n if (scores.length === 0) return new Int32Array(0);\n\n const byClass = new Map<number, number[]>();\n for (let i = 0; i < idxs.length; i++) {\n const c = idxs[i] as number;\n const list = byClass.get(c);\n if (list === undefined) byClass.set(c, [i]);\n else list.push(i);\n }\n\n const keep: number[] = [];\n for (const indices of byClass.values()) {\n const m = indices.length;\n const subBoxes = new Float32Array(m * 4);\n const subScores = new Float32Array(m);\n for (let k = 0; k < m; k++) {\n const i = indices[k] as number;\n subBoxes[k * 4] = boxes[i * 4] as number;\n subBoxes[k * 4 + 1] = boxes[i * 4 + 1] as number;\n subBoxes[k * 4 + 2] = boxes[i * 4 + 2] as number;\n subBoxes[k * 4 + 3] = boxes[i * 4 + 3] as number;\n subScores[k] = scores[i] as number;\n }\n const subKeep = nms(subBoxes, subScores, iouThreshold);\n for (let k = 0; k < subKeep.length; k++) {\n keep.push(indices[subKeep[k] as number] as number);\n }\n }\n\n keep.sort((a, b) => (scores[b] as number) - (scores[a] as number));\n return Int32Array.from(keep);\n}\n\nexport interface DecodeYoloAnchorsOptions {\n /** Number of class-score channels following the 4 box channels. */\n readonly numClasses: number;\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedAnchors {\n /** Indices into the original `numAnchors` axis, in descending confidence order. */\n readonly anchorIndices: Int32Array;\n /** `[k, 4]` boxes in original-image pixel coords, flat row-major xyxy. */\n readonly boxesXyxy: Float32Array;\n /** Predicted class id per survivor. */\n readonly classIds: Int32Array;\n /** Confidence per survivor. */\n readonly confidences: Float32Array;\n}\n\n/**\n * Shared YOLO per-anchor decode used by both detection and segmentation\n * (v8 / v9 / v10 / v11 / v12).\n *\n * Only the first `4 + numClasses` channels are read; later channels (e.g.\n * mask coefficients) are ignored — callers can fetch them via the returned\n * {@link DecodedAnchors.anchorIndices}.\n *\n * @param data Flat per-anchor output, length `channels * numAnchors`.\n * @param dims Dims as reported by ORT, e.g. `[1, 84, 8400]` (det) or\n * `[1, 116, 8400]` (seg). The leading batch dim must be 1.\n */\nexport function decodeYoloAnchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n let normalized = dims;\n if (normalized.length === 3) {\n if (normalized[0] !== 1) {\n throw new Error(`decodeYoloAnchors: expected batch size 1, got ${normalized[0]}.`);\n }\n normalized = [normalized[1] as number, normalized[2] as number];\n }\n if (normalized.length !== 2) {\n throw new Error(\n `decodeYoloAnchors: expected 2-D output after batch removal, got dims=${JSON.stringify(dims)}.`,\n );\n }\n const channels = normalized[0] as number;\n const numAnchors = normalized[1] as number;\n\n const {\n numClasses,\n originalWidth,\n originalHeight,\n padLeft,\n padTop,\n scale,\n confThreshold,\n iouThreshold,\n maxDetections,\n } = options;\n\n if (numClasses < 1 || numClasses + 4 > channels) {\n throw new Error(\n `decodeYoloAnchors: invalid numClasses=${numClasses} for channels=${channels}.`,\n );\n }\n if (data.length !== channels * numAnchors) {\n throw new Error(\n `decodeYoloAnchors: data length ${data.length} does not match channels*numAnchors=${channels * numAnchors}.`,\n );\n }\n\n type Candidate = {\n anchorIdx: number;\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n classId: number;\n confidence: number;\n };\n const candidates: Candidate[] = [];\n\n for (let a = 0; a < numAnchors; a++) {\n let bestCls = 0;\n let bestScore = -Infinity;\n for (let c = 0; c < numClasses; c++) {\n const s = data[(4 + c) * numAnchors + a];\n if (s !== undefined && s > bestScore) {\n bestScore = s;\n bestCls = c;\n }\n }\n if (bestScore < confThreshold) continue;\n\n const cx = data[a] as number;\n const cy = data[numAnchors + a] as number;\n const w = data[2 * numAnchors + a] as number;\n const h = data[3 * numAnchors + a] as number;\n\n let x1 = cx - w / 2;\n let y1 = cy - h / 2;\n let x2 = cx + w / 2;\n let y2 = cy + h / 2;\n\n x1 = (x1 - padLeft) / scale;\n y1 = (y1 - padTop) / scale;\n x2 = (x2 - padLeft) / scale;\n y2 = (y2 - padTop) / scale;\n\n x1 = Math.max(0, Math.min(originalWidth, x1));\n y1 = Math.max(0, Math.min(originalHeight, y1));\n x2 = Math.max(0, Math.min(originalWidth, x2));\n y2 = Math.max(0, Math.min(originalHeight, y2));\n\n candidates.push({ anchorIdx: a, x1, y1, x2, y2, classId: bestCls, confidence: bestScore });\n }\n\n if (candidates.length === 0) return emptyDecoded();\n\n // Build flat arrays then delegate to batchedNms — same algorithm as before\n // but funnelled through the public per-class NMS helper.\n const flatBoxes = new Float32Array(candidates.length * 4);\n const scoresArr = new Float32Array(candidates.length);\n const idxsArr = new Int32Array(candidates.length);\n for (let i = 0; i < candidates.length; i++) {\n const c = candidates[i] as Candidate;\n flatBoxes[i * 4] = c.x1;\n flatBoxes[i * 4 + 1] = c.y1;\n flatBoxes[i * 4 + 2] = c.x2;\n flatBoxes[i * 4 + 3] = c.y2;\n scoresArr[i] = c.confidence;\n idxsArr[i] = c.classId;\n }\n const kept = batchedNms(flatBoxes, scoresArr, idxsArr, iouThreshold);\n if (kept.length === 0) return emptyDecoded();\n\n const limited = Array.from(kept).slice(0, maxDetections);\n const k = limited.length;\n const anchorIndices = new Int32Array(k);\n const boxesXyxy = new Float32Array(k * 4);\n const classIds = new Int32Array(k);\n const confidences = new Float32Array(k);\n for (let i = 0; i < k; i++) {\n const c = candidates[limited[i] as number] as Candidate;\n anchorIndices[i] = c.anchorIdx;\n boxesXyxy[i * 4] = c.x1;\n boxesXyxy[i * 4 + 1] = c.y1;\n boxesXyxy[i * 4 + 2] = c.x2;\n boxesXyxy[i * 4 + 3] = c.y2;\n classIds[i] = c.classId;\n confidences[i] = c.confidence;\n }\n return { anchorIndices, boxesXyxy, classIds, confidences };\n}\n\nfunction emptyDecoded(): DecodedAnchors {\n return {\n anchorIndices: new Int32Array(0),\n boxesXyxy: new Float32Array(0),\n classIds: new Int32Array(0),\n confidences: new Float32Array(0),\n };\n}\n\nexport interface DecodeYoloOptions {\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly padLeft: number;\n readonly padTop: number;\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n}\n\nexport interface DecodedDetection {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n}\n\n/**\n * Decode an anchor-free YOLO detection output into a list of detections.\n *\n * Works for **YOLOv8 / v9 / v10 / v11 / v12** detect heads.\n *\n * Expected raw shape: `[1, 4 + numClasses, N]`. `numClasses` is inferred\n * from the channel count.\n */\nexport function decodeYolo(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n const channels = outputDims.length === 3 ? outputDims[1] : outputDims[0];\n if (channels === undefined || channels < 5) {\n throw new Error(`decodeYolo: invalid output channel count ${channels} (expected >= 5).`);\n }\n const numClasses = channels - 4;\n\n const decoded = decodeYoloAnchors(output, outputDims, {\n numClasses,\n ...options,\n });\n\n const results: DecodedDetection[] = [];\n for (let i = 0; i < decoded.classIds.length; i++) {\n results.push({\n bbox: new BoundingBox(\n decoded.boxesXyxy[i * 4] as number,\n decoded.boxesXyxy[i * 4 + 1] as number,\n decoded.boxesXyxy[i * 4 + 2] as number,\n decoded.boxesXyxy[i * 4 + 3] as number,\n ),\n classId: decoded.classIds[i] as number,\n confidence: decoded.confidences[i] as number,\n });\n }\n return results;\n}\n\nlet _warnedDecodeYoloV8 = false;\nlet _warnedDecodeYoloV8Anchors = false;\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYolo}. Same behavior; the\n * decoder covers v8/v9/v10/v11/v12 detect heads. Will be removed in 0.4.0.\n */\nexport function decodeYoloV8(\n output: Float32Array,\n outputDims: readonly number[],\n options: DecodeYoloOptions,\n): DecodedDetection[] {\n if (!_warnedDecodeYoloV8) {\n _warnedDecodeYoloV8 = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8 is deprecated since 0.2.0; use decodeYolo. \" +\n \"The alias will be removed in 0.4.0.\",\n );\n }\n return decodeYolo(output, outputDims, options);\n}\n\n/**\n * @deprecated since 0.2.0 — use {@link decodeYoloAnchors}. Will be removed in 0.4.0.\n */\nexport function decodeYoloV8Anchors(\n data: Float32Array,\n dims: readonly number[],\n options: DecodeYoloAnchorsOptions,\n): DecodedAnchors {\n if (!_warnedDecodeYoloV8Anchors) {\n _warnedDecodeYoloV8Anchors = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Anchors is deprecated since 0.2.0; use decodeYoloAnchors. \" +\n \"The alias will be removed in 0.4.0.\",\n );\n }\n return decodeYoloAnchors(data, dims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloAnchorsOptions}. */\nexport type DecodeYoloV8AnchorsOptions = DecodeYoloAnchorsOptions;\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloOptions}. */\nexport type DecodeYoloV8Options = DecodeYoloOptions;\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("../types.cjs"),t=require("./detection.cjs");function n(n,i,a,s,c){let l=s;if(l.length===4){if(l[0]!==1)throw Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${l[0]}.`);l=[l[1],l[2],l[3]]}if(l.length!==3)throw Error(`decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(s)}.`);let u=l[0],d=l[1],f=l[2],p=i.length===3?i[1]:i[0],m=i.length===3?i[2]:i[1];if(p===void 0||m===void 0)throw Error(`decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(i)}.`);let h=4+c.numClasses+u;if(p!==h)throw Error(`decodeYoloSeg: channels=${p} does not match 4 + numClasses(${c.numClasses}) + numMaskCoefs(${u}) = ${h}.`);if(a.length!==u*d*f)throw Error(`decodeYoloSeg: prototype length ${a.length} does not match dims=${JSON.stringify(s)}.`);let g=t.decodeYoloAnchors(n,i,{numClasses:c.numClasses,originalWidth:c.originalWidth,originalHeight:c.originalHeight,padLeft:c.padLeft,padTop:c.padTop,scale:c.scale,confThreshold:c.confThreshold,iouThreshold:c.iouThreshold,maxDetections:c.maxDetections});if(g.anchorIndices.length===0)return[];let _=c.maskThreshold??.5,v=f/c.inputWidth,y=d/c.inputHeight,b=d*f,x=(4+c.numClasses)*m,S=[];for(let t=0;t<g.anchorIndices.length;t++){let i=g.anchorIndices[t],s=g.boxesXyxy[t*4],l=g.boxesXyxy[t*4+1],p=g.boxesXyxy[t*4+2],h=g.boxesXyxy[t*4+3],C=new e.BoundingBox(s,l,p,h),w=g.classIds[t],T=g.confidences[t],E=Math.max(0,Math.trunc(p)-Math.trunc(s)),D=Math.max(0,Math.trunc(h)-Math.trunc(l));if(E===0||D===0){S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(new Uint8Array,0,0)});continue}let O=s*c.scale+c.padLeft,k=l*c.scale+c.padTop,A=p*c.scale+c.padLeft,j=h*c.scale+c.padTop,M=Math.max(0,Math.floor(O*v)),N=Math.max(0,Math.floor(k*y)),P=Math.min(f,Math.ceil(A*v)),F=Math.min(d,Math.ceil(j*y));if(P<=M||F<=N){S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(new Uint8Array(E*D),E,D)});continue}let I=P-M,L=F-N,R=new Float32Array(I*L);for(let e=0;e<L;e++){let t=N+e;for(let o=0;o<I;o++){let s=M+o,c=0;for(let e=0;e<u;e++){let r=n[x+e*m+i],o=a[e*b+t*f+s];c+=r*o}R[e*I+o]=r(c)}}let z=o(R,I,L,E,D),B=new Uint8Array(E*D);for(let e=0;e<B.length;e++)B[e]=z[e]>=_?255:0;S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(B,E,D)})}return S}function r(e){if(e>=0)return 1/(1+Math.exp(-e));let t=Math.exp(e);return t/(1+t)}var i=!1;function a(e,t,r,a,o){return i||(i=!0,console.warn(`[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. The alias will be removed in 0.3.0.`)),n(e,t,r,a,o)}function o(e,t,n,r,i){let a=new Float32Array(r*i);if(r===0||i===0||t===0||n===0)return a;if(r===t&&i===n)return a.set(e),a;let o=t/r,s=n/i;for(let c=0;c<i;c++){let i=(c+.5)*s-.5,l=Math.max(0,Math.floor(i)),u=Math.min(n-1,l+1),d=Math.max(0,Math.min(1,i-l));for(let n=0;n<r;n++){let i=(n+.5)*o-.5,s=Math.max(0,Math.floor(i)),f=Math.min(t-1,s+1),p=Math.max(0,Math.min(1,i-s)),m=e[l*t+s],h=e[l*t+f],g=e[u*t+s],_=e[u*t+f],v=m*(1-p)+h*p,y=g*(1-p)+_*p;a[c*r+n]=v*(1-d)+y*d}}return a}exports.decodeYoloSeg=n,exports.decodeYoloV8Seg=a;
1
+ const e=require("../types.cjs"),t=require("./detection.cjs");function n(n,i,a,s,c){let l=s;if(l.length===4){if(l[0]!==1)throw Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${l[0]}.`);l=[l[1],l[2],l[3]]}if(l.length!==3)throw Error(`decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(s)}.`);let u=l[0],d=l[1],f=l[2],p=i.length===3?i[1]:i[0],m=i.length===3?i[2]:i[1];if(p===void 0||m===void 0)throw Error(`decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(i)}.`);let h=4+c.numClasses+u;if(p!==h)throw Error(`decodeYoloSeg: channels=${p} does not match 4 + numClasses(${c.numClasses}) + numMaskCoefs(${u}) = ${h}.`);if(a.length!==u*d*f)throw Error(`decodeYoloSeg: prototype length ${a.length} does not match dims=${JSON.stringify(s)}.`);let g=t.decodeYoloAnchors(n,i,{numClasses:c.numClasses,originalWidth:c.originalWidth,originalHeight:c.originalHeight,padLeft:c.padLeft,padTop:c.padTop,scale:c.scale,confThreshold:c.confThreshold,iouThreshold:c.iouThreshold,maxDetections:c.maxDetections});if(g.anchorIndices.length===0)return[];let _=c.maskThreshold??.5,v=f/c.inputWidth,y=d/c.inputHeight,b=d*f,x=(4+c.numClasses)*m,S=[];for(let t=0;t<g.anchorIndices.length;t++){let i=g.anchorIndices[t],s=g.boxesXyxy[t*4],l=g.boxesXyxy[t*4+1],p=g.boxesXyxy[t*4+2],h=g.boxesXyxy[t*4+3],C=new e.BoundingBox(s,l,p,h),w=g.classIds[t],T=g.confidences[t],E=Math.max(0,Math.trunc(p)-Math.trunc(s)),D=Math.max(0,Math.trunc(h)-Math.trunc(l));if(E===0||D===0){S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(new Uint8Array,0,0)});continue}let O=s*c.scale+c.padLeft,k=l*c.scale+c.padTop,A=p*c.scale+c.padLeft,j=h*c.scale+c.padTop,M=Math.max(0,Math.floor(O*v)),N=Math.max(0,Math.floor(k*y)),P=Math.min(f,Math.ceil(A*v)),F=Math.min(d,Math.ceil(j*y));if(P<=M||F<=N){S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(new Uint8Array(E*D),E,D)});continue}let I=P-M,L=F-N,R=new Float32Array(I*L);for(let e=0;e<L;e++){let t=N+e;for(let o=0;o<I;o++){let s=M+o,c=0;for(let e=0;e<u;e++){let r=n[x+e*m+i],o=a[e*b+t*f+s];c+=r*o}R[e*I+o]=r(c)}}let z=o(R,I,L,E,D),B=new Uint8Array(E*D);for(let e=0;e<B.length;e++)B[e]=z[e]>=_?255:0;S.push({bbox:C,classId:w,confidence:T,mask:new e.Mask(B,E,D)})}return S}function r(e){if(e>=0)return 1/(1+Math.exp(-e));let t=Math.exp(e);return t/(1+t)}var i=!1;function a(e,t,r,a,o){return i||(i=!0,console.warn(`[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. The alias will be removed in 0.4.0.`)),n(e,t,r,a,o)}function o(e,t,n,r,i){let a=new Float32Array(r*i);if(r===0||i===0||t===0||n===0)return a;if(r===t&&i===n)return a.set(e),a;let o=t/r,s=n/i;for(let c=0;c<i;c++){let i=(c+.5)*s-.5,l=Math.max(0,Math.floor(i)),u=Math.min(n-1,l+1),d=Math.max(0,Math.min(1,i-l));for(let n=0;n<r;n++){let i=(n+.5)*o-.5,s=Math.max(0,Math.floor(i)),f=Math.min(t-1,s+1),p=Math.max(0,Math.min(1,i-s)),m=e[l*t+s],h=e[l*t+f],g=e[u*t+s],_=e[u*t+f],v=m*(1-p)+h*p,y=g*(1-p)+_*p;a[c*r+n]=v*(1-d)+y*d}}return a}exports.decodeYoloSeg=n,exports.decodeYoloV8Seg=a;
2
2
  //# sourceMappingURL=segmentation.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"segmentation.cjs","names":[],"sources":["../../../src/vision/postprocess/segmentation.ts"],"sourcesContent":["/**\n * Segmentation head postprocessing: YOLO instance-segmentation decoding.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg exports (and any later seg head\n * sharing the layout). The model produces two output tensors:\n *\n * - `output0` of shape `(1, 4 + numClasses + numMaskCoefs, numAnchors)` — the\n * same per-anchor predictions as plain YOLO detection plus an extra\n * `numMaskCoefs` (typically 32) channels of mask coefficients.\n * - `output1` of shape `(1, numMaskCoefs, maskH, maskW)` — a set of \"prototype\"\n * masks shared across all anchors.\n *\n * The per-anchor decode (xywh→xyxy, undo letterbox, per-class NMS, sort & cap)\n * is delegated to {@link decodeYoloAnchors}; this module only handles the\n * mask-specific work: matmul against prototypes, sigmoid, bilinear resize and\n * thresholding.\n */\n\nimport { decodeYoloAnchors } from \"./detection\";\nimport { BoundingBox, Mask } from \"../types\";\n\nexport interface DecodeYoloSegOptions {\n readonly numClasses: number;\n /** Model input `[width, height]` (post-letterbox). */\n readonly inputWidth: number;\n readonly inputHeight: number;\n /** Original image `[width, height]`. */\n readonly originalWidth: number;\n readonly originalHeight: number;\n /** Letterbox horizontal padding in input-tensor pixels. */\n readonly padLeft: number;\n /** Letterbox vertical padding in input-tensor pixels. */\n readonly padTop: number;\n /** Letterbox scale factor. */\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n /** Probability cutoff applied to the soft mask. Defaults to `0.5`. */\n readonly maskThreshold?: number;\n}\n\nexport interface DecodedSegmentation {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n /** Binary mask cropped to `bbox`. Width/height match `bbox.asIntXyxy()` extents. */\n readonly mask: Mask;\n}\n\n/**\n * Decode YOLO segmentation raw outputs into a list of segmented instances.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg.\n *\n * @param perAnchorData Flat `output0`, length `(4 + numClasses + numMaskCoefs) * numAnchors`.\n * @param perAnchorDims Dims as reported by ORT, e.g. `[1, 116, 8400]`.\n * @param prototypeData Flat `output1`, length `numMaskCoefs * maskH * maskW`.\n * @param prototypeDims Dims as reported by ORT, e.g. `[1, 32, 160, 160]`.\n */\nexport function decodeYoloSeg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n // Strip batch dim from prototypes; perAnchor batch is validated by the helper.\n let pDims = prototypeDims;\n if (pDims.length === 4) {\n if (pDims[0] !== 1) {\n throw new Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${pDims[0]}.`);\n }\n pDims = [pDims[1] as number, pDims[2] as number, pDims[3] as number];\n }\n if (pDims.length !== 3) {\n throw new Error(\n `decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n const numMaskCoefs = pDims[0] as number;\n const maskH = pDims[1] as number;\n const maskW = pDims[2] as number;\n\n const channels = perAnchorDims.length === 3 ? perAnchorDims[1] : perAnchorDims[0];\n const numAnchors = perAnchorDims.length === 3 ? perAnchorDims[2] : perAnchorDims[1];\n if (channels === undefined || numAnchors === undefined) {\n throw new Error(\n `decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(perAnchorDims)}.`,\n );\n }\n\n const expectedChannels = 4 + options.numClasses + numMaskCoefs;\n if (channels !== expectedChannels) {\n throw new Error(\n `decodeYoloSeg: channels=${channels} does not match 4 + numClasses(${options.numClasses}) + numMaskCoefs(${numMaskCoefs}) = ${expectedChannels}.`,\n );\n }\n if (prototypeData.length !== numMaskCoefs * maskH * maskW) {\n throw new Error(\n `decodeYoloSeg: prototype length ${prototypeData.length} does not match dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n\n const decoded = decodeYoloAnchors(perAnchorData, perAnchorDims, {\n numClasses: options.numClasses,\n originalWidth: options.originalWidth,\n originalHeight: options.originalHeight,\n padLeft: options.padLeft,\n padTop: options.padTop,\n scale: options.scale,\n confThreshold: options.confThreshold,\n iouThreshold: options.iouThreshold,\n maxDetections: options.maxDetections,\n });\n\n if (decoded.anchorIndices.length === 0) return [];\n\n const maskThreshold = options.maskThreshold ?? 0.5;\n const scaleX = maskW / options.inputWidth;\n const scaleY = maskH / options.inputHeight;\n const protoPlane = maskH * maskW;\n const coefBase = (4 + options.numClasses) * numAnchors;\n\n const results: DecodedSegmentation[] = [];\n\n for (let i = 0; i < decoded.anchorIndices.length; i++) {\n const a = decoded.anchorIndices[i] as number;\n const x1 = decoded.boxesXyxy[i * 4] as number;\n const y1 = decoded.boxesXyxy[i * 4 + 1] as number;\n const x2 = decoded.boxesXyxy[i * 4 + 2] as number;\n const y2 = decoded.boxesXyxy[i * 4 + 3] as number;\n const bbox = new BoundingBox(x1, y1, x2, y2);\n const classId = decoded.classIds[i] as number;\n const confidence = decoded.confidences[i] as number;\n\n const bboxW = Math.max(0, Math.trunc(x2) - Math.trunc(x1));\n const bboxH = Math.max(0, Math.trunc(y2) - Math.trunc(y1));\n\n if (bboxW === 0 || bboxH === 0) {\n results.push({ bbox, classId, confidence, mask: new Mask(new Uint8Array(0), 0, 0) });\n continue;\n }\n\n // Bbox in input-tensor coords, then in low-res mask coords.\n const ibx1 = x1 * options.scale + options.padLeft;\n const iby1 = y1 * options.scale + options.padTop;\n const ibx2 = x2 * options.scale + options.padLeft;\n const iby2 = y2 * options.scale + options.padTop;\n\n const mbx1 = Math.max(0, Math.floor(ibx1 * scaleX));\n const mby1 = Math.max(0, Math.floor(iby1 * scaleY));\n const mbx2 = Math.min(maskW, Math.ceil(ibx2 * scaleX));\n const mby2 = Math.min(maskH, Math.ceil(iby2 * scaleY));\n\n if (mbx2 <= mbx1 || mby2 <= mby1) {\n results.push({\n bbox,\n classId,\n confidence,\n mask: new Mask(new Uint8Array(bboxW * bboxH), bboxW, bboxH),\n });\n continue;\n }\n\n // Compute soft mask only within the prototype region under this bbox.\n const cropW = mbx2 - mbx1;\n const cropH = mby2 - mby1;\n const softCrop = new Float32Array(cropW * cropH);\n for (let y = 0; y < cropH; y++) {\n const py = mby1 + y;\n for (let x = 0; x < cropW; x++) {\n const px = mbx1 + x;\n let sum = 0;\n for (let kk = 0; kk < numMaskCoefs; kk++) {\n const coef = perAnchorData[coefBase + kk * numAnchors + a];\n const proto = prototypeData[kk * protoPlane + py * maskW + px];\n sum += coef * proto;\n }\n softCrop[y * cropW + x] = sigmoid(sum);\n }\n }\n\n const resized = resizeBilinear(softCrop, cropW, cropH, bboxW, bboxH);\n const binary = new Uint8Array(bboxW * bboxH);\n for (let j = 0; j < binary.length; j++) {\n binary[j] = resized[j] >= maskThreshold ? 255 : 0;\n }\n\n results.push({ bbox, classId, confidence, mask: new Mask(binary, bboxW, bboxH) });\n }\n\n return results;\n}\n\nfunction sigmoid(x: number): number {\n if (x >= 0) {\n return 1 / (1 + Math.exp(-x));\n }\n const e = Math.exp(x);\n return e / (1 + e);\n}\n\nlet _warnedDecodeYoloV8Seg = false;\n\n/** @deprecated since 0.2.0 — use {@link decodeYoloSeg}. Will be removed in 0.3.0. */\nexport function decodeYoloV8Seg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n if (!_warnedDecodeYoloV8Seg) {\n _warnedDecodeYoloV8Seg = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. \" +\n \"The alias will be removed in 0.3.0.\",\n );\n }\n return decodeYoloSeg(perAnchorData, perAnchorDims, prototypeData, prototypeDims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloSegOptions}. */\nexport type DecodeYoloV8SegOptions = DecodeYoloSegOptions;\n\nfunction resizeBilinear(\n src: Float32Array,\n srcWidth: number,\n srcHeight: number,\n targetWidth: number,\n targetHeight: number,\n): Float32Array {\n const out = new Float32Array(targetWidth * targetHeight);\n if (targetWidth === 0 || targetHeight === 0 || srcWidth === 0 || srcHeight === 0) {\n return out;\n }\n if (targetWidth === srcWidth && targetHeight === srcHeight) {\n out.set(src);\n return out;\n }\n const sx = srcWidth / targetWidth;\n const sy = srcHeight / targetHeight;\n for (let y = 0; y < targetHeight; y++) {\n const yy = (y + 0.5) * sy - 0.5;\n const y0 = Math.max(0, Math.floor(yy));\n const y1 = Math.min(srcHeight - 1, y0 + 1);\n const wy = Math.max(0, Math.min(1, yy - y0));\n for (let x = 0; x < targetWidth; x++) {\n const xx = (x + 0.5) * sx - 0.5;\n const x0 = Math.max(0, Math.floor(xx));\n const x1 = Math.min(srcWidth - 1, x0 + 1);\n const wx = Math.max(0, Math.min(1, xx - x0));\n const v00 = src[y0 * srcWidth + x0];\n const v01 = src[y0 * srcWidth + x1];\n const v10 = src[y1 * srcWidth + x0];\n const v11 = src[y1 * srcWidth + x1];\n const top = v00 * (1 - wx) + v01 * wx;\n const bot = v10 * (1 - wx) + v11 * wx;\n out[y * targetWidth + x] = top * (1 - wy) + bot * wy;\n }\n }\n return out;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"segmentation.cjs","names":[],"sources":["../../../src/vision/postprocess/segmentation.ts"],"sourcesContent":["/**\n * Segmentation head postprocessing: YOLO instance-segmentation decoding.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg exports (and any later seg head\n * sharing the layout). The model produces two output tensors:\n *\n * - `output0` of shape `(1, 4 + numClasses + numMaskCoefs, numAnchors)` — the\n * same per-anchor predictions as plain YOLO detection plus an extra\n * `numMaskCoefs` (typically 32) channels of mask coefficients.\n * - `output1` of shape `(1, numMaskCoefs, maskH, maskW)` — a set of \"prototype\"\n * masks shared across all anchors.\n *\n * The per-anchor decode (xywh→xyxy, undo letterbox, per-class NMS, sort & cap)\n * is delegated to {@link decodeYoloAnchors}; this module only handles the\n * mask-specific work: matmul against prototypes, sigmoid, bilinear resize and\n * thresholding.\n */\n\nimport { decodeYoloAnchors } from \"./detection\";\nimport { BoundingBox, Mask } from \"../types\";\n\nexport interface DecodeYoloSegOptions {\n readonly numClasses: number;\n /** Model input `[width, height]` (post-letterbox). */\n readonly inputWidth: number;\n readonly inputHeight: number;\n /** Original image `[width, height]`. */\n readonly originalWidth: number;\n readonly originalHeight: number;\n /** Letterbox horizontal padding in input-tensor pixels. */\n readonly padLeft: number;\n /** Letterbox vertical padding in input-tensor pixels. */\n readonly padTop: number;\n /** Letterbox scale factor. */\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n /** Probability cutoff applied to the soft mask. Defaults to `0.5`. */\n readonly maskThreshold?: number;\n}\n\nexport interface DecodedSegmentation {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n /** Binary mask cropped to `bbox`. Width/height match `bbox.asIntXyxy()` extents. */\n readonly mask: Mask;\n}\n\n/**\n * Decode YOLO segmentation raw outputs into a list of segmented instances.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg.\n *\n * @param perAnchorData Flat `output0`, length `(4 + numClasses + numMaskCoefs) * numAnchors`.\n * @param perAnchorDims Dims as reported by ORT, e.g. `[1, 116, 8400]`.\n * @param prototypeData Flat `output1`, length `numMaskCoefs * maskH * maskW`.\n * @param prototypeDims Dims as reported by ORT, e.g. `[1, 32, 160, 160]`.\n */\nexport function decodeYoloSeg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n // Strip batch dim from prototypes; perAnchor batch is validated by the helper.\n let pDims = prototypeDims;\n if (pDims.length === 4) {\n if (pDims[0] !== 1) {\n throw new Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${pDims[0]}.`);\n }\n pDims = [pDims[1] as number, pDims[2] as number, pDims[3] as number];\n }\n if (pDims.length !== 3) {\n throw new Error(\n `decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n const numMaskCoefs = pDims[0] as number;\n const maskH = pDims[1] as number;\n const maskW = pDims[2] as number;\n\n const channels = perAnchorDims.length === 3 ? perAnchorDims[1] : perAnchorDims[0];\n const numAnchors = perAnchorDims.length === 3 ? perAnchorDims[2] : perAnchorDims[1];\n if (channels === undefined || numAnchors === undefined) {\n throw new Error(\n `decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(perAnchorDims)}.`,\n );\n }\n\n const expectedChannels = 4 + options.numClasses + numMaskCoefs;\n if (channels !== expectedChannels) {\n throw new Error(\n `decodeYoloSeg: channels=${channels} does not match 4 + numClasses(${options.numClasses}) + numMaskCoefs(${numMaskCoefs}) = ${expectedChannels}.`,\n );\n }\n if (prototypeData.length !== numMaskCoefs * maskH * maskW) {\n throw new Error(\n `decodeYoloSeg: prototype length ${prototypeData.length} does not match dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n\n const decoded = decodeYoloAnchors(perAnchorData, perAnchorDims, {\n numClasses: options.numClasses,\n originalWidth: options.originalWidth,\n originalHeight: options.originalHeight,\n padLeft: options.padLeft,\n padTop: options.padTop,\n scale: options.scale,\n confThreshold: options.confThreshold,\n iouThreshold: options.iouThreshold,\n maxDetections: options.maxDetections,\n });\n\n if (decoded.anchorIndices.length === 0) return [];\n\n const maskThreshold = options.maskThreshold ?? 0.5;\n const scaleX = maskW / options.inputWidth;\n const scaleY = maskH / options.inputHeight;\n const protoPlane = maskH * maskW;\n const coefBase = (4 + options.numClasses) * numAnchors;\n\n const results: DecodedSegmentation[] = [];\n\n for (let i = 0; i < decoded.anchorIndices.length; i++) {\n const a = decoded.anchorIndices[i] as number;\n const x1 = decoded.boxesXyxy[i * 4] as number;\n const y1 = decoded.boxesXyxy[i * 4 + 1] as number;\n const x2 = decoded.boxesXyxy[i * 4 + 2] as number;\n const y2 = decoded.boxesXyxy[i * 4 + 3] as number;\n const bbox = new BoundingBox(x1, y1, x2, y2);\n const classId = decoded.classIds[i] as number;\n const confidence = decoded.confidences[i] as number;\n\n const bboxW = Math.max(0, Math.trunc(x2) - Math.trunc(x1));\n const bboxH = Math.max(0, Math.trunc(y2) - Math.trunc(y1));\n\n if (bboxW === 0 || bboxH === 0) {\n results.push({ bbox, classId, confidence, mask: new Mask(new Uint8Array(0), 0, 0) });\n continue;\n }\n\n // Bbox in input-tensor coords, then in low-res mask coords.\n const ibx1 = x1 * options.scale + options.padLeft;\n const iby1 = y1 * options.scale + options.padTop;\n const ibx2 = x2 * options.scale + options.padLeft;\n const iby2 = y2 * options.scale + options.padTop;\n\n const mbx1 = Math.max(0, Math.floor(ibx1 * scaleX));\n const mby1 = Math.max(0, Math.floor(iby1 * scaleY));\n const mbx2 = Math.min(maskW, Math.ceil(ibx2 * scaleX));\n const mby2 = Math.min(maskH, Math.ceil(iby2 * scaleY));\n\n if (mbx2 <= mbx1 || mby2 <= mby1) {\n results.push({\n bbox,\n classId,\n confidence,\n mask: new Mask(new Uint8Array(bboxW * bboxH), bboxW, bboxH),\n });\n continue;\n }\n\n // Compute soft mask only within the prototype region under this bbox.\n const cropW = mbx2 - mbx1;\n const cropH = mby2 - mby1;\n const softCrop = new Float32Array(cropW * cropH);\n for (let y = 0; y < cropH; y++) {\n const py = mby1 + y;\n for (let x = 0; x < cropW; x++) {\n const px = mbx1 + x;\n let sum = 0;\n for (let kk = 0; kk < numMaskCoefs; kk++) {\n const coef = perAnchorData[coefBase + kk * numAnchors + a];\n const proto = prototypeData[kk * protoPlane + py * maskW + px];\n sum += coef * proto;\n }\n softCrop[y * cropW + x] = sigmoid(sum);\n }\n }\n\n const resized = resizeBilinear(softCrop, cropW, cropH, bboxW, bboxH);\n const binary = new Uint8Array(bboxW * bboxH);\n for (let j = 0; j < binary.length; j++) {\n binary[j] = resized[j] >= maskThreshold ? 255 : 0;\n }\n\n results.push({ bbox, classId, confidence, mask: new Mask(binary, bboxW, bboxH) });\n }\n\n return results;\n}\n\nfunction sigmoid(x: number): number {\n if (x >= 0) {\n return 1 / (1 + Math.exp(-x));\n }\n const e = Math.exp(x);\n return e / (1 + e);\n}\n\nlet _warnedDecodeYoloV8Seg = false;\n\n/** @deprecated since 0.2.0 — use {@link decodeYoloSeg}. Will be removed in 0.4.0. */\nexport function decodeYoloV8Seg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n if (!_warnedDecodeYoloV8Seg) {\n _warnedDecodeYoloV8Seg = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. \" +\n \"The alias will be removed in 0.4.0.\",\n );\n }\n return decodeYoloSeg(perAnchorData, perAnchorDims, prototypeData, prototypeDims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloSegOptions}. */\nexport type DecodeYoloV8SegOptions = DecodeYoloSegOptions;\n\nfunction resizeBilinear(\n src: Float32Array,\n srcWidth: number,\n srcHeight: number,\n targetWidth: number,\n targetHeight: number,\n): Float32Array {\n const out = new Float32Array(targetWidth * targetHeight);\n if (targetWidth === 0 || targetHeight === 0 || srcWidth === 0 || srcHeight === 0) {\n return out;\n }\n if (targetWidth === srcWidth && targetHeight === srcHeight) {\n out.set(src);\n return out;\n }\n const sx = srcWidth / targetWidth;\n const sy = srcHeight / targetHeight;\n for (let y = 0; y < targetHeight; y++) {\n const yy = (y + 0.5) * sy - 0.5;\n const y0 = Math.max(0, Math.floor(yy));\n const y1 = Math.min(srcHeight - 1, y0 + 1);\n const wy = Math.max(0, Math.min(1, yy - y0));\n for (let x = 0; x < targetWidth; x++) {\n const xx = (x + 0.5) * sx - 0.5;\n const x0 = Math.max(0, Math.floor(xx));\n const x1 = Math.min(srcWidth - 1, x0 + 1);\n const wx = Math.max(0, Math.min(1, xx - x0));\n const v00 = src[y0 * srcWidth + x0];\n const v01 = src[y0 * srcWidth + x1];\n const v10 = src[y1 * srcWidth + x0];\n const v11 = src[y1 * srcWidth + x1];\n const top = v00 * (1 - wx) + v01 * wx;\n const bot = v10 * (1 - wx) + v11 * wx;\n out[y * targetWidth + x] = top * (1 - wy) + bot * wy;\n }\n }\n return out;\n}\n"],"mappings":"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"}
@@ -81,7 +81,7 @@ function i(e) {
81
81
  }
82
82
  var a = !1;
83
83
  function o(e, t, n, i, o) {
84
- return a || (a = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. The alias will be removed in 0.3.0.")), r(e, t, n, i, o);
84
+ return a || (a = !0, console.warn("[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. The alias will be removed in 0.4.0.")), r(e, t, n, i, o);
85
85
  }
86
86
  function s(e, t, n, r, i) {
87
87
  let a = new Float32Array(r * i);
@@ -1 +1 @@
1
- {"version":3,"file":"segmentation.js","names":[],"sources":["../../../src/vision/postprocess/segmentation.ts"],"sourcesContent":["/**\n * Segmentation head postprocessing: YOLO instance-segmentation decoding.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg exports (and any later seg head\n * sharing the layout). The model produces two output tensors:\n *\n * - `output0` of shape `(1, 4 + numClasses + numMaskCoefs, numAnchors)` — the\n * same per-anchor predictions as plain YOLO detection plus an extra\n * `numMaskCoefs` (typically 32) channels of mask coefficients.\n * - `output1` of shape `(1, numMaskCoefs, maskH, maskW)` — a set of \"prototype\"\n * masks shared across all anchors.\n *\n * The per-anchor decode (xywh→xyxy, undo letterbox, per-class NMS, sort & cap)\n * is delegated to {@link decodeYoloAnchors}; this module only handles the\n * mask-specific work: matmul against prototypes, sigmoid, bilinear resize and\n * thresholding.\n */\n\nimport { decodeYoloAnchors } from \"./detection\";\nimport { BoundingBox, Mask } from \"../types\";\n\nexport interface DecodeYoloSegOptions {\n readonly numClasses: number;\n /** Model input `[width, height]` (post-letterbox). */\n readonly inputWidth: number;\n readonly inputHeight: number;\n /** Original image `[width, height]`. */\n readonly originalWidth: number;\n readonly originalHeight: number;\n /** Letterbox horizontal padding in input-tensor pixels. */\n readonly padLeft: number;\n /** Letterbox vertical padding in input-tensor pixels. */\n readonly padTop: number;\n /** Letterbox scale factor. */\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n /** Probability cutoff applied to the soft mask. Defaults to `0.5`. */\n readonly maskThreshold?: number;\n}\n\nexport interface DecodedSegmentation {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n /** Binary mask cropped to `bbox`. Width/height match `bbox.asIntXyxy()` extents. */\n readonly mask: Mask;\n}\n\n/**\n * Decode YOLO segmentation raw outputs into a list of segmented instances.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg.\n *\n * @param perAnchorData Flat `output0`, length `(4 + numClasses + numMaskCoefs) * numAnchors`.\n * @param perAnchorDims Dims as reported by ORT, e.g. `[1, 116, 8400]`.\n * @param prototypeData Flat `output1`, length `numMaskCoefs * maskH * maskW`.\n * @param prototypeDims Dims as reported by ORT, e.g. `[1, 32, 160, 160]`.\n */\nexport function decodeYoloSeg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n // Strip batch dim from prototypes; perAnchor batch is validated by the helper.\n let pDims = prototypeDims;\n if (pDims.length === 4) {\n if (pDims[0] !== 1) {\n throw new Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${pDims[0]}.`);\n }\n pDims = [pDims[1] as number, pDims[2] as number, pDims[3] as number];\n }\n if (pDims.length !== 3) {\n throw new Error(\n `decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n const numMaskCoefs = pDims[0] as number;\n const maskH = pDims[1] as number;\n const maskW = pDims[2] as number;\n\n const channels = perAnchorDims.length === 3 ? perAnchorDims[1] : perAnchorDims[0];\n const numAnchors = perAnchorDims.length === 3 ? perAnchorDims[2] : perAnchorDims[1];\n if (channels === undefined || numAnchors === undefined) {\n throw new Error(\n `decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(perAnchorDims)}.`,\n );\n }\n\n const expectedChannels = 4 + options.numClasses + numMaskCoefs;\n if (channels !== expectedChannels) {\n throw new Error(\n `decodeYoloSeg: channels=${channels} does not match 4 + numClasses(${options.numClasses}) + numMaskCoefs(${numMaskCoefs}) = ${expectedChannels}.`,\n );\n }\n if (prototypeData.length !== numMaskCoefs * maskH * maskW) {\n throw new Error(\n `decodeYoloSeg: prototype length ${prototypeData.length} does not match dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n\n const decoded = decodeYoloAnchors(perAnchorData, perAnchorDims, {\n numClasses: options.numClasses,\n originalWidth: options.originalWidth,\n originalHeight: options.originalHeight,\n padLeft: options.padLeft,\n padTop: options.padTop,\n scale: options.scale,\n confThreshold: options.confThreshold,\n iouThreshold: options.iouThreshold,\n maxDetections: options.maxDetections,\n });\n\n if (decoded.anchorIndices.length === 0) return [];\n\n const maskThreshold = options.maskThreshold ?? 0.5;\n const scaleX = maskW / options.inputWidth;\n const scaleY = maskH / options.inputHeight;\n const protoPlane = maskH * maskW;\n const coefBase = (4 + options.numClasses) * numAnchors;\n\n const results: DecodedSegmentation[] = [];\n\n for (let i = 0; i < decoded.anchorIndices.length; i++) {\n const a = decoded.anchorIndices[i] as number;\n const x1 = decoded.boxesXyxy[i * 4] as number;\n const y1 = decoded.boxesXyxy[i * 4 + 1] as number;\n const x2 = decoded.boxesXyxy[i * 4 + 2] as number;\n const y2 = decoded.boxesXyxy[i * 4 + 3] as number;\n const bbox = new BoundingBox(x1, y1, x2, y2);\n const classId = decoded.classIds[i] as number;\n const confidence = decoded.confidences[i] as number;\n\n const bboxW = Math.max(0, Math.trunc(x2) - Math.trunc(x1));\n const bboxH = Math.max(0, Math.trunc(y2) - Math.trunc(y1));\n\n if (bboxW === 0 || bboxH === 0) {\n results.push({ bbox, classId, confidence, mask: new Mask(new Uint8Array(0), 0, 0) });\n continue;\n }\n\n // Bbox in input-tensor coords, then in low-res mask coords.\n const ibx1 = x1 * options.scale + options.padLeft;\n const iby1 = y1 * options.scale + options.padTop;\n const ibx2 = x2 * options.scale + options.padLeft;\n const iby2 = y2 * options.scale + options.padTop;\n\n const mbx1 = Math.max(0, Math.floor(ibx1 * scaleX));\n const mby1 = Math.max(0, Math.floor(iby1 * scaleY));\n const mbx2 = Math.min(maskW, Math.ceil(ibx2 * scaleX));\n const mby2 = Math.min(maskH, Math.ceil(iby2 * scaleY));\n\n if (mbx2 <= mbx1 || mby2 <= mby1) {\n results.push({\n bbox,\n classId,\n confidence,\n mask: new Mask(new Uint8Array(bboxW * bboxH), bboxW, bboxH),\n });\n continue;\n }\n\n // Compute soft mask only within the prototype region under this bbox.\n const cropW = mbx2 - mbx1;\n const cropH = mby2 - mby1;\n const softCrop = new Float32Array(cropW * cropH);\n for (let y = 0; y < cropH; y++) {\n const py = mby1 + y;\n for (let x = 0; x < cropW; x++) {\n const px = mbx1 + x;\n let sum = 0;\n for (let kk = 0; kk < numMaskCoefs; kk++) {\n const coef = perAnchorData[coefBase + kk * numAnchors + a];\n const proto = prototypeData[kk * protoPlane + py * maskW + px];\n sum += coef * proto;\n }\n softCrop[y * cropW + x] = sigmoid(sum);\n }\n }\n\n const resized = resizeBilinear(softCrop, cropW, cropH, bboxW, bboxH);\n const binary = new Uint8Array(bboxW * bboxH);\n for (let j = 0; j < binary.length; j++) {\n binary[j] = resized[j] >= maskThreshold ? 255 : 0;\n }\n\n results.push({ bbox, classId, confidence, mask: new Mask(binary, bboxW, bboxH) });\n }\n\n return results;\n}\n\nfunction sigmoid(x: number): number {\n if (x >= 0) {\n return 1 / (1 + Math.exp(-x));\n }\n const e = Math.exp(x);\n return e / (1 + e);\n}\n\nlet _warnedDecodeYoloV8Seg = false;\n\n/** @deprecated since 0.2.0 — use {@link decodeYoloSeg}. Will be removed in 0.3.0. */\nexport function decodeYoloV8Seg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n if (!_warnedDecodeYoloV8Seg) {\n _warnedDecodeYoloV8Seg = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. \" +\n \"The alias will be removed in 0.3.0.\",\n );\n }\n return decodeYoloSeg(perAnchorData, perAnchorDims, prototypeData, prototypeDims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloSegOptions}. */\nexport type DecodeYoloV8SegOptions = DecodeYoloSegOptions;\n\nfunction resizeBilinear(\n src: Float32Array,\n srcWidth: number,\n srcHeight: number,\n targetWidth: number,\n targetHeight: number,\n): Float32Array {\n const out = new Float32Array(targetWidth * targetHeight);\n if (targetWidth === 0 || targetHeight === 0 || srcWidth === 0 || srcHeight === 0) {\n return out;\n }\n if (targetWidth === srcWidth && targetHeight === srcHeight) {\n out.set(src);\n return out;\n }\n const sx = srcWidth / targetWidth;\n const sy = srcHeight / targetHeight;\n for (let y = 0; y < targetHeight; y++) {\n const yy = (y + 0.5) * sy - 0.5;\n const y0 = Math.max(0, Math.floor(yy));\n const y1 = Math.min(srcHeight - 1, y0 + 1);\n const wy = Math.max(0, Math.min(1, yy - y0));\n for (let x = 0; x < targetWidth; x++) {\n const xx = (x + 0.5) * sx - 0.5;\n const x0 = Math.max(0, Math.floor(xx));\n const x1 = Math.min(srcWidth - 1, x0 + 1);\n const wx = Math.max(0, Math.min(1, xx - x0));\n const v00 = src[y0 * srcWidth + x0];\n const v01 = src[y0 * srcWidth + x1];\n const v10 = src[y1 * srcWidth + x0];\n const v11 = src[y1 * srcWidth + x1];\n const top = v00 * (1 - wx) + v01 * wx;\n const bot = v10 * (1 - wx) + v11 * wx;\n out[y * targetWidth + x] = top * (1 - wy) + bot * wy;\n }\n }\n return out;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"segmentation.js","names":[],"sources":["../../../src/vision/postprocess/segmentation.ts"],"sourcesContent":["/**\n * Segmentation head postprocessing: YOLO instance-segmentation decoding.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg exports (and any later seg head\n * sharing the layout). The model produces two output tensors:\n *\n * - `output0` of shape `(1, 4 + numClasses + numMaskCoefs, numAnchors)` — the\n * same per-anchor predictions as plain YOLO detection plus an extra\n * `numMaskCoefs` (typically 32) channels of mask coefficients.\n * - `output1` of shape `(1, numMaskCoefs, maskH, maskW)` — a set of \"prototype\"\n * masks shared across all anchors.\n *\n * The per-anchor decode (xywh→xyxy, undo letterbox, per-class NMS, sort & cap)\n * is delegated to {@link decodeYoloAnchors}; this module only handles the\n * mask-specific work: matmul against prototypes, sigmoid, bilinear resize and\n * thresholding.\n */\n\nimport { decodeYoloAnchors } from \"./detection\";\nimport { BoundingBox, Mask } from \"../types\";\n\nexport interface DecodeYoloSegOptions {\n readonly numClasses: number;\n /** Model input `[width, height]` (post-letterbox). */\n readonly inputWidth: number;\n readonly inputHeight: number;\n /** Original image `[width, height]`. */\n readonly originalWidth: number;\n readonly originalHeight: number;\n /** Letterbox horizontal padding in input-tensor pixels. */\n readonly padLeft: number;\n /** Letterbox vertical padding in input-tensor pixels. */\n readonly padTop: number;\n /** Letterbox scale factor. */\n readonly scale: number;\n readonly confThreshold: number;\n readonly iouThreshold: number;\n readonly maxDetections: number;\n /** Probability cutoff applied to the soft mask. Defaults to `0.5`. */\n readonly maskThreshold?: number;\n}\n\nexport interface DecodedSegmentation {\n readonly bbox: BoundingBox;\n readonly classId: number;\n readonly confidence: number;\n /** Binary mask cropped to `bbox`. Width/height match `bbox.asIntXyxy()` extents. */\n readonly mask: Mask;\n}\n\n/**\n * Decode YOLO segmentation raw outputs into a list of segmented instances.\n *\n * Compatible with YOLOv8-seg / YOLOv11-seg.\n *\n * @param perAnchorData Flat `output0`, length `(4 + numClasses + numMaskCoefs) * numAnchors`.\n * @param perAnchorDims Dims as reported by ORT, e.g. `[1, 116, 8400]`.\n * @param prototypeData Flat `output1`, length `numMaskCoefs * maskH * maskW`.\n * @param prototypeDims Dims as reported by ORT, e.g. `[1, 32, 160, 160]`.\n */\nexport function decodeYoloSeg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n // Strip batch dim from prototypes; perAnchor batch is validated by the helper.\n let pDims = prototypeDims;\n if (pDims.length === 4) {\n if (pDims[0] !== 1) {\n throw new Error(`decodeYoloSeg: expected batch size 1 in prototypes, got ${pDims[0]}.`);\n }\n pDims = [pDims[1] as number, pDims[2] as number, pDims[3] as number];\n }\n if (pDims.length !== 3) {\n throw new Error(\n `decodeYoloSeg: expected 3-D prototypes after batch removal, got dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n const numMaskCoefs = pDims[0] as number;\n const maskH = pDims[1] as number;\n const maskW = pDims[2] as number;\n\n const channels = perAnchorDims.length === 3 ? perAnchorDims[1] : perAnchorDims[0];\n const numAnchors = perAnchorDims.length === 3 ? perAnchorDims[2] : perAnchorDims[1];\n if (channels === undefined || numAnchors === undefined) {\n throw new Error(\n `decodeYoloSeg: cannot read channels/numAnchors from dims=${JSON.stringify(perAnchorDims)}.`,\n );\n }\n\n const expectedChannels = 4 + options.numClasses + numMaskCoefs;\n if (channels !== expectedChannels) {\n throw new Error(\n `decodeYoloSeg: channels=${channels} does not match 4 + numClasses(${options.numClasses}) + numMaskCoefs(${numMaskCoefs}) = ${expectedChannels}.`,\n );\n }\n if (prototypeData.length !== numMaskCoefs * maskH * maskW) {\n throw new Error(\n `decodeYoloSeg: prototype length ${prototypeData.length} does not match dims=${JSON.stringify(prototypeDims)}.`,\n );\n }\n\n const decoded = decodeYoloAnchors(perAnchorData, perAnchorDims, {\n numClasses: options.numClasses,\n originalWidth: options.originalWidth,\n originalHeight: options.originalHeight,\n padLeft: options.padLeft,\n padTop: options.padTop,\n scale: options.scale,\n confThreshold: options.confThreshold,\n iouThreshold: options.iouThreshold,\n maxDetections: options.maxDetections,\n });\n\n if (decoded.anchorIndices.length === 0) return [];\n\n const maskThreshold = options.maskThreshold ?? 0.5;\n const scaleX = maskW / options.inputWidth;\n const scaleY = maskH / options.inputHeight;\n const protoPlane = maskH * maskW;\n const coefBase = (4 + options.numClasses) * numAnchors;\n\n const results: DecodedSegmentation[] = [];\n\n for (let i = 0; i < decoded.anchorIndices.length; i++) {\n const a = decoded.anchorIndices[i] as number;\n const x1 = decoded.boxesXyxy[i * 4] as number;\n const y1 = decoded.boxesXyxy[i * 4 + 1] as number;\n const x2 = decoded.boxesXyxy[i * 4 + 2] as number;\n const y2 = decoded.boxesXyxy[i * 4 + 3] as number;\n const bbox = new BoundingBox(x1, y1, x2, y2);\n const classId = decoded.classIds[i] as number;\n const confidence = decoded.confidences[i] as number;\n\n const bboxW = Math.max(0, Math.trunc(x2) - Math.trunc(x1));\n const bboxH = Math.max(0, Math.trunc(y2) - Math.trunc(y1));\n\n if (bboxW === 0 || bboxH === 0) {\n results.push({ bbox, classId, confidence, mask: new Mask(new Uint8Array(0), 0, 0) });\n continue;\n }\n\n // Bbox in input-tensor coords, then in low-res mask coords.\n const ibx1 = x1 * options.scale + options.padLeft;\n const iby1 = y1 * options.scale + options.padTop;\n const ibx2 = x2 * options.scale + options.padLeft;\n const iby2 = y2 * options.scale + options.padTop;\n\n const mbx1 = Math.max(0, Math.floor(ibx1 * scaleX));\n const mby1 = Math.max(0, Math.floor(iby1 * scaleY));\n const mbx2 = Math.min(maskW, Math.ceil(ibx2 * scaleX));\n const mby2 = Math.min(maskH, Math.ceil(iby2 * scaleY));\n\n if (mbx2 <= mbx1 || mby2 <= mby1) {\n results.push({\n bbox,\n classId,\n confidence,\n mask: new Mask(new Uint8Array(bboxW * bboxH), bboxW, bboxH),\n });\n continue;\n }\n\n // Compute soft mask only within the prototype region under this bbox.\n const cropW = mbx2 - mbx1;\n const cropH = mby2 - mby1;\n const softCrop = new Float32Array(cropW * cropH);\n for (let y = 0; y < cropH; y++) {\n const py = mby1 + y;\n for (let x = 0; x < cropW; x++) {\n const px = mbx1 + x;\n let sum = 0;\n for (let kk = 0; kk < numMaskCoefs; kk++) {\n const coef = perAnchorData[coefBase + kk * numAnchors + a];\n const proto = prototypeData[kk * protoPlane + py * maskW + px];\n sum += coef * proto;\n }\n softCrop[y * cropW + x] = sigmoid(sum);\n }\n }\n\n const resized = resizeBilinear(softCrop, cropW, cropH, bboxW, bboxH);\n const binary = new Uint8Array(bboxW * bboxH);\n for (let j = 0; j < binary.length; j++) {\n binary[j] = resized[j] >= maskThreshold ? 255 : 0;\n }\n\n results.push({ bbox, classId, confidence, mask: new Mask(binary, bboxW, bboxH) });\n }\n\n return results;\n}\n\nfunction sigmoid(x: number): number {\n if (x >= 0) {\n return 1 / (1 + Math.exp(-x));\n }\n const e = Math.exp(x);\n return e / (1 + e);\n}\n\nlet _warnedDecodeYoloV8Seg = false;\n\n/** @deprecated since 0.2.0 — use {@link decodeYoloSeg}. Will be removed in 0.4.0. */\nexport function decodeYoloV8Seg(\n perAnchorData: Float32Array,\n perAnchorDims: readonly number[],\n prototypeData: Float32Array,\n prototypeDims: readonly number[],\n options: DecodeYoloSegOptions,\n): DecodedSegmentation[] {\n if (!_warnedDecodeYoloV8Seg) {\n _warnedDecodeYoloV8Seg = true;\n console.warn(\n \"[@ort-vision-sdk/web] decodeYoloV8Seg is deprecated since 0.2.0; use decodeYoloSeg. \" +\n \"The alias will be removed in 0.4.0.\",\n );\n }\n return decodeYoloSeg(perAnchorData, perAnchorDims, prototypeData, prototypeDims, options);\n}\n\n/** @deprecated since 0.2.0 — use {@link DecodeYoloSegOptions}. */\nexport type DecodeYoloV8SegOptions = DecodeYoloSegOptions;\n\nfunction resizeBilinear(\n src: Float32Array,\n srcWidth: number,\n srcHeight: number,\n targetWidth: number,\n targetHeight: number,\n): Float32Array {\n const out = new Float32Array(targetWidth * targetHeight);\n if (targetWidth === 0 || targetHeight === 0 || srcWidth === 0 || srcHeight === 0) {\n return out;\n }\n if (targetWidth === srcWidth && targetHeight === srcHeight) {\n out.set(src);\n return out;\n }\n const sx = srcWidth / targetWidth;\n const sy = srcHeight / targetHeight;\n for (let y = 0; y < targetHeight; y++) {\n const yy = (y + 0.5) * sy - 0.5;\n const y0 = Math.max(0, Math.floor(yy));\n const y1 = Math.min(srcHeight - 1, y0 + 1);\n const wy = Math.max(0, Math.min(1, yy - y0));\n for (let x = 0; x < targetWidth; x++) {\n const xx = (x + 0.5) * sx - 0.5;\n const x0 = Math.max(0, Math.floor(xx));\n const x1 = Math.min(srcWidth - 1, x0 + 1);\n const wx = Math.max(0, Math.min(1, xx - x0));\n const v00 = src[y0 * srcWidth + x0];\n const v01 = src[y0 * srcWidth + x1];\n const v10 = src[y1 * srcWidth + x0];\n const v11 = src[y1 * srcWidth + x1];\n const top = v00 * (1 - wx) + v01 * wx;\n const bot = v10 * (1 - wx) + v11 * wx;\n out[y * targetWidth + x] = top * (1 - wy) + bot * wy;\n }\n }\n return out;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- var e=class{xyxy;cls;conf;origShape;constructor(e,t,n,r){this.xyxy=e,this.cls=t,this.conf=n,this.origShape=r}get length(){return this.cls.length}get shape(){return[this.length,4]}get xywh(){let e=new Float32Array(this.xyxy.length);for(let t=0;t<this.length;t++){let n=this.xyxy[t*4],r=this.xyxy[t*4+1],i=this.xyxy[t*4+2],a=this.xyxy[t*4+3];e[t*4]=(n+i)/2,e[t*4+1]=(r+a)/2,e[t*4+2]=i-n,e[t*4+3]=a-r}return e}get xyxyn(){let[e,t]=this.origShape,n=new Float32Array(this.xyxy.length);if(this.length===0||t<=0||e<=0)return n;for(let r=0;r<this.length;r++)n[r*4]=this.xyxy[r*4]/t,n[r*4+1]=this.xyxy[r*4+1]/e,n[r*4+2]=this.xyxy[r*4+2]/t,n[r*4+3]=this.xyxy[r*4+3]/e;return n}get xywhn(){let e=this.xywh,[t,n]=this.origShape;if(this.length===0||n<=0||t<=0)return e;for(let r=0;r<this.length;r++)e[r*4]=e[r*4]/n,e[r*4+1]=e[r*4+1]/t,e[r*4+2]=e[r*4+2]/n,e[r*4+3]=e[r*4+3]/t;return e}get data(){let e=new Float32Array(this.length*6);for(let t=0;t<this.length;t++)e[t*6]=this.xyxy[t*4],e[t*6+1]=this.xyxy[t*4+1],e[t*6+2]=this.xyxy[t*4+2],e[t*6+3]=this.xyxy[t*4+3],e[t*6+4]=this.conf[t],e[t*6+5]=this.cls[t];return e}},t=class{data;constructor(e){this.data=e}get length(){return this.data.length}get shape(){return[this.length]}get top1(){if(this.data.length===0)return 0;let e=0,t=this.data[0];for(let n=1;n<this.data.length;n++){let r=this.data[n];r>t&&(e=n,t=r)}return e}get top1conf(){return this.data.length===0?0:this.data[this.top1]}get top5(){return this._topK(5).indices}get top5conf(){return this._topK(5).values}_topK(e){let t=Math.min(e,this.data.length),n=[];for(let e=0;e<this.data.length;e++)n.push(e);n.sort((e,t)=>this.data[t]-this.data[e]);let r=new Int32Array(t),i=new Float32Array(t);for(let e=0;e<t;e++)r[e]=n[e],i[e]=this.data[n[e]];return{indices:r,values:i}}},n=class{data;xyxy;origShape;constructor(e,t,n){this.data=e,this.xyxy=t,this.origShape=n}get length(){return this.data.length}get shape(){return[this.length]}[Symbol.iterator](){return this.data[Symbol.iterator]()}},r=class{boxes;detections;names;origImg;origShape;path;speed;constructor(e,t,n,r,i,a=null,o={}){this.boxes=e,this.detections=t,this.names=n,this.origImg=r,this.origShape=i,this.path=a,this.speed=o}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}},i=class{probs;result;names;origImg;origShape;path;speed;constructor(e,t,n,r,i,a=null,o={}){this.probs=e,this.result=t,this.names=n,this.origImg=r,this.origShape=i,this.path=a,this.speed=o}get cls(){return this.probs.top1}get conf(){return this.probs.top1conf}get name(){return this.names[this.cls]??`class_${this.cls}`}get probabilities(){return this.result.probabilities}},a=class{boxes;masks;detections;names;origImg;origShape;path;speed;constructor(e,t,n,r,i,a,o=null,s={}){this.boxes=e,this.masks=t,this.detections=n,this.names=r,this.origImg=i,this.origShape=a,this.path=o,this.speed=s}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}};exports.Boxes=e,exports.ClassificationResults=i,exports.DetectionResults=r,exports.Masks=n,exports.Probs=t,exports.SegmentationResults=a;
1
+ var e={load:0,preprocess:0,inference:0,postprocess:0},t=class{xyxy;cls;conf;origShape;constructor(e,t,n,r){this.xyxy=e,this.cls=t,this.conf=n,this.origShape=r}get length(){return this.cls.length}get shape(){return[this.length,4]}get xywh(){let e=new Float32Array(this.xyxy.length);for(let t=0;t<this.length;t++){let n=this.xyxy[t*4],r=this.xyxy[t*4+1],i=this.xyxy[t*4+2],a=this.xyxy[t*4+3];e[t*4]=(n+i)/2,e[t*4+1]=(r+a)/2,e[t*4+2]=i-n,e[t*4+3]=a-r}return e}get xyxyn(){let[e,t]=this.origShape,n=new Float32Array(this.xyxy.length);if(this.length===0||t<=0||e<=0)return n;for(let r=0;r<this.length;r++)n[r*4]=this.xyxy[r*4]/t,n[r*4+1]=this.xyxy[r*4+1]/e,n[r*4+2]=this.xyxy[r*4+2]/t,n[r*4+3]=this.xyxy[r*4+3]/e;return n}get xywhn(){let e=this.xywh,[t,n]=this.origShape;if(this.length===0||n<=0||t<=0)return e;for(let r=0;r<this.length;r++)e[r*4]=e[r*4]/n,e[r*4+1]=e[r*4+1]/t,e[r*4+2]=e[r*4+2]/n,e[r*4+3]=e[r*4+3]/t;return e}get data(){let e=new Float32Array(this.length*6);for(let t=0;t<this.length;t++)e[t*6]=this.xyxy[t*4],e[t*6+1]=this.xyxy[t*4+1],e[t*6+2]=this.xyxy[t*4+2],e[t*6+3]=this.xyxy[t*4+3],e[t*6+4]=this.conf[t],e[t*6+5]=this.cls[t];return e}},n=class{data;constructor(e){this.data=e}get length(){return this.data.length}get shape(){return[this.length]}get top1(){if(this.data.length===0)return 0;let e=0,t=this.data[0];for(let n=1;n<this.data.length;n++){let r=this.data[n];r>t&&(e=n,t=r)}return e}get top1conf(){return this.data.length===0?0:this.data[this.top1]}get top5(){return this._topK(5).indices}get top5conf(){return this._topK(5).values}_topK(e){let t=Math.min(e,this.data.length),n=[];for(let e=0;e<this.data.length;e++)n.push(e);n.sort((e,t)=>this.data[t]-this.data[e]);let r=new Int32Array(t),i=new Float32Array(t);for(let e=0;e<t;e++)r[e]=n[e],i[e]=this.data[n[e]];return{indices:r,values:i}}},r=class{data;xyxy;origShape;constructor(e,t,n){this.data=e,this.xyxy=t,this.origShape=n}get length(){return this.data.length}get shape(){return[this.length]}[Symbol.iterator](){return this.data[Symbol.iterator]()}},i=class{boxes;detections;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o=null,s=e){this.boxes=t,this.detections=n,this.names=r,this.origImg=i,this.origShape=a,this.path=o,this.speed=s}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}},a=class{probs;result;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o=null,s=e){this.probs=t,this.result=n,this.names=r,this.origImg=i,this.origShape=a,this.path=o,this.speed=s}get cls(){return this.probs.top1}get conf(){return this.probs.top1conf}get name(){return this.names[this.cls]??`class_${this.cls}`}get probabilities(){return this.result.probabilities}},o=class{boxes;masks;detections;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o,s=null,c=e){this.boxes=t,this.masks=n,this.detections=r,this.names=i,this.origImg=a,this.origShape=o,this.path=s,this.speed=c}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}};exports.Boxes=t,exports.ClassificationResults=a,exports.DetectionResults=i,exports.Masks=r,exports.Probs=n,exports.SegmentationResults=o;
2
2
  //# sourceMappingURL=results.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"results.cjs","names":[],"sources":["../../src/vision/results.ts"],"sourcesContent":["/**\n * Per-image result envelopes — Ultralytics-style `Results` for the SDK.\n *\n * Each `predict()` call returns a 1-element array of these envelopes,\n * mirroring `YOLO(\"img.jpg\")`. Each envelope holds:\n *\n * - A bulk-array view of the predictions (`Boxes`, `Probs`, `Masks`) with\n * the exact attribute names Ultralytics uses (`xyxy`, `xywh`, `xyxyn`,\n * `xywhn`, `cls`, `conf`, `data`, `top1`, `top5`).\n * - Per-instance dataclasses (`DetectionResult`, `SegmentationResult`,\n * `ClassProbability`) for callers who prefer the OO interface.\n * - `names`: `Record<number, string>` matching Ultralytics' `model.names`.\n * - `origImg` / `origShape` / `path`: provenance for the original input.\n */\n\nimport {\n type ClassificationResult,\n type DetectionResult,\n type RGBImage,\n type SegmentationResult,\n} from \"./types\";\n\n/**\n * Bulk numpy-style view of detected boxes for a single image.\n *\n * Mirrors Ultralytics' `Boxes` interface. Coordinates in {@link xyxy} and\n * {@link xywh} are absolute pixels in the original image; the `*n` variants\n * are normalized to `[0, 1]` using `origShape`.\n */\nexport class Boxes {\n /**\n * @param xyxy Flat array of length `4 * N` in `[x1, y1, x2, y2, ...]` order.\n * @param cls One class index per box, length `N`.\n * @param conf One confidence per box, length `N`.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly xyxy: Float32Array,\n public readonly cls: Int32Array,\n public readonly conf: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of detected boxes. */\n get length(): number {\n return this.cls.length;\n }\n\n /** `[N, 4]` shape of the `xyxy` view. */\n get shape(): readonly [number, number] {\n return [this.length, 4];\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` flat array in absolute pixels. */\n get xywh(): Float32Array {\n const out = new Float32Array(this.xyxy.length);\n for (let i = 0; i < this.length; i++) {\n const x1 = this.xyxy[i * 4] as number;\n const y1 = this.xyxy[i * 4 + 1] as number;\n const x2 = this.xyxy[i * 4 + 2] as number;\n const y2 = this.xyxy[i * 4 + 3] as number;\n out[i * 4] = (x1 + x2) / 2;\n out[i * 4 + 1] = (y1 + y2) / 2;\n out[i * 4 + 2] = x2 - x1;\n out[i * 4 + 3] = y2 - y1;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[x1, y1, x2, y2]` normalized to `[0, 1]`. */\n get xyxyn(): Float32Array {\n const [h, w] = this.origShape;\n const out = new Float32Array(this.xyxy.length);\n if (this.length === 0 || w <= 0 || h <= 0) return out;\n for (let i = 0; i < this.length; i++) {\n out[i * 4] = (this.xyxy[i * 4] as number) / w;\n out[i * 4 + 1] = (this.xyxy[i * 4 + 1] as number) / h;\n out[i * 4 + 2] = (this.xyxy[i * 4 + 2] as number) / w;\n out[i * 4 + 3] = (this.xyxy[i * 4 + 3] as number) / h;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` normalized to `[0, 1]`. */\n get xywhn(): Float32Array {\n const xywh = this.xywh;\n const [h, w] = this.origShape;\n if (this.length === 0 || w <= 0 || h <= 0) return xywh;\n for (let i = 0; i < this.length; i++) {\n xywh[i * 4] = (xywh[i * 4] as number) / w;\n xywh[i * 4 + 1] = (xywh[i * 4 + 1] as number) / h;\n xywh[i * 4 + 2] = (xywh[i * 4 + 2] as number) / w;\n xywh[i * 4 + 3] = (xywh[i * 4 + 3] as number) / h;\n }\n return xywh;\n }\n\n /**\n * Concatenated `[N, 6]` array of `[x1, y1, x2, y2, conf, cls]`.\n *\n * Matches Ultralytics' `boxes.data`.\n */\n get data(): Float32Array {\n const out = new Float32Array(this.length * 6);\n for (let i = 0; i < this.length; i++) {\n out[i * 6] = this.xyxy[i * 4] as number;\n out[i * 6 + 1] = this.xyxy[i * 4 + 1] as number;\n out[i * 6 + 2] = this.xyxy[i * 4 + 2] as number;\n out[i * 6 + 3] = this.xyxy[i * 4 + 3] as number;\n out[i * 6 + 4] = this.conf[i] as number;\n out[i * 6 + 5] = this.cls[i] as number;\n }\n return out;\n }\n}\n\n/**\n * Top-k classification probabilities for a single image.\n *\n * Mirrors Ultralytics' `Probs` interface.\n */\nexport class Probs {\n /** @param data `[numClasses]` per-class probabilities, indexed by class id. */\n constructor(public readonly data: Float32Array) {}\n\n /** Number of classes. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[numClasses]` shape of the underlying vector. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n /** Index of the most probable class. */\n get top1(): number {\n if (this.data.length === 0) return 0;\n let best = 0;\n let bestVal = this.data[0] as number;\n for (let i = 1; i < this.data.length; i++) {\n const v = this.data[i] as number;\n if (v > bestVal) {\n best = i;\n bestVal = v;\n }\n }\n return best;\n }\n\n /** Probability of the top-1 class. */\n get top1conf(): number {\n if (this.data.length === 0) return 0;\n return this.data[this.top1] as number;\n }\n\n /** Indices of the top-5 most probable classes, descending. */\n get top5(): Int32Array {\n return this._topK(5).indices;\n }\n\n /** Probabilities of the top-5 classes, descending. */\n get top5conf(): Float32Array {\n return this._topK(5).values;\n }\n\n private _topK(k: number): { indices: Int32Array; values: Float32Array } {\n const n = Math.min(k, this.data.length);\n const order: number[] = [];\n for (let i = 0; i < this.data.length; i++) order.push(i);\n order.sort((a, b) => (this.data[b] as number) - (this.data[a] as number));\n const indices = new Int32Array(n);\n const values = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n indices[i] = order[i] as number;\n values[i] = this.data[order[i] as number] as number;\n }\n return { indices, values };\n }\n}\n\n/**\n * Per-instance binary masks for a single image.\n *\n * Each mask is cropped to its instance's bounding box. To paint masks onto\n * a full-image canvas, use `xyxy[i]` as the top-left target.\n */\nexport class Masks {\n /**\n * @param data Per-instance binary masks (`Mask` objects from `types.ts`).\n * @param xyxy Flat `[N, 4]` of bounding-box coordinates in original pixels.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly data: ReadonlyArray<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }>,\n public readonly xyxy: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of instance masks. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[N]` shape of the masks collection. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n [Symbol.iterator](): Iterator<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }> {\n return this.data[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image detection envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link DetectionResult} entries, so legacy\n * code that did `for (const d of detector.predict(img))` only needs an\n * extra `[0]` to bridge:\n *\n * ```typescript\n * for (const d of (await detector.predict(img))[0]) {\n * console.log(d.cls, d.conf, d.box.xyxy);\n * }\n * ```\n *\n * For numpy-style bulk access, use the `boxes` collection.\n */\nexport class DetectionResults implements Iterable<DetectionResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly detections: readonly DetectionResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Record<string, number>> = {},\n ) {}\n\n /** Number of surviving detections. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance detections. */\n get(index: number): DetectionResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<DetectionResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image classification envelope (Ultralytics-style `Results`).\n */\nexport class ClassificationResults {\n constructor(\n public readonly probs: Probs,\n public readonly result: ClassificationResult,\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Record<string, number>> = {},\n ) {}\n\n /** Top-1 class index (Ultralytics-style alias). */\n get cls(): number {\n return this.probs.top1;\n }\n\n /** Top-1 confidence (Ultralytics-style alias). */\n get conf(): number {\n return this.probs.top1conf;\n }\n\n /** Top-1 class name. */\n get name(): string {\n return this.names[this.cls] ?? `class_${this.cls}`;\n }\n\n /** Per-class probability list, sorted descending (legacy field). */\n get probabilities(): readonly ClassificationResult[\"probabilities\"][number][] {\n return this.result.probabilities;\n }\n}\n\n/**\n * Per-image instance-segmentation envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link SegmentationResult} entries. `boxes`\n * and `masks` mirror Ultralytics' bulk-array views.\n */\nexport class SegmentationResults implements Iterable<SegmentationResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly masks: Masks,\n public readonly detections: readonly SegmentationResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Record<string, number>> = {},\n ) {}\n\n /** Number of surviving instances. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance results. */\n get(index: number): SegmentationResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<SegmentationResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"results.cjs","names":[],"sources":["../../src/vision/results.ts"],"sourcesContent":["/**\n * Per-image result envelopes — Ultralytics-style `Results` for the SDK.\n *\n * Each `predict()` call returns a 1-element array of these envelopes,\n * mirroring `YOLO(\"img.jpg\")`. Each envelope holds:\n *\n * - A bulk-array view of the predictions (`Boxes`, `Probs`, `Masks`) with\n * the exact attribute names Ultralytics uses (`xyxy`, `xywh`, `xyxyn`,\n * `xywhn`, `cls`, `conf`, `data`, `top1`, `top5`).\n * - Per-instance dataclasses (`DetectionResult`, `SegmentationResult`,\n * `ClassProbability`) for callers who prefer the OO interface.\n * - `names`: `Record<number, string>` matching Ultralytics' `model.names`.\n * - `origImg` / `origShape` / `path`: provenance for the original input.\n * - `speed`: per-stage timings of the `predict()` call that produced it.\n */\n\nimport { type Speed } from \"./core/timing\";\nimport {\n type ClassificationResult,\n type DetectionResult,\n type RGBImage,\n type SegmentationResult,\n} from \"./types\";\n\n/**\n * Zero timings for an envelope built outside a `predict()` call.\n *\n * Hand-constructed envelopes (tests, adapters) have nothing to measure, and\n * zeros keep `speed.inference` a plain `number` at every call site instead of\n * forcing an optional check that only ever fires for synthetic data.\n */\nconst NO_SPEED: Speed = { load: 0, preprocess: 0, inference: 0, postprocess: 0 };\n\n/**\n * Bulk numpy-style view of detected boxes for a single image.\n *\n * Mirrors Ultralytics' `Boxes` interface. Coordinates in {@link xyxy} and\n * {@link xywh} are absolute pixels in the original image; the `*n` variants\n * are normalized to `[0, 1]` using `origShape`.\n */\nexport class Boxes {\n /**\n * @param xyxy Flat array of length `4 * N` in `[x1, y1, x2, y2, ...]` order.\n * @param cls One class index per box, length `N`.\n * @param conf One confidence per box, length `N`.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly xyxy: Float32Array,\n public readonly cls: Int32Array,\n public readonly conf: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of detected boxes. */\n get length(): number {\n return this.cls.length;\n }\n\n /** `[N, 4]` shape of the `xyxy` view. */\n get shape(): readonly [number, number] {\n return [this.length, 4];\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` flat array in absolute pixels. */\n get xywh(): Float32Array {\n const out = new Float32Array(this.xyxy.length);\n for (let i = 0; i < this.length; i++) {\n const x1 = this.xyxy[i * 4] as number;\n const y1 = this.xyxy[i * 4 + 1] as number;\n const x2 = this.xyxy[i * 4 + 2] as number;\n const y2 = this.xyxy[i * 4 + 3] as number;\n out[i * 4] = (x1 + x2) / 2;\n out[i * 4 + 1] = (y1 + y2) / 2;\n out[i * 4 + 2] = x2 - x1;\n out[i * 4 + 3] = y2 - y1;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[x1, y1, x2, y2]` normalized to `[0, 1]`. */\n get xyxyn(): Float32Array {\n const [h, w] = this.origShape;\n const out = new Float32Array(this.xyxy.length);\n if (this.length === 0 || w <= 0 || h <= 0) return out;\n for (let i = 0; i < this.length; i++) {\n out[i * 4] = (this.xyxy[i * 4] as number) / w;\n out[i * 4 + 1] = (this.xyxy[i * 4 + 1] as number) / h;\n out[i * 4 + 2] = (this.xyxy[i * 4 + 2] as number) / w;\n out[i * 4 + 3] = (this.xyxy[i * 4 + 3] as number) / h;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` normalized to `[0, 1]`. */\n get xywhn(): Float32Array {\n const xywh = this.xywh;\n const [h, w] = this.origShape;\n if (this.length === 0 || w <= 0 || h <= 0) return xywh;\n for (let i = 0; i < this.length; i++) {\n xywh[i * 4] = (xywh[i * 4] as number) / w;\n xywh[i * 4 + 1] = (xywh[i * 4 + 1] as number) / h;\n xywh[i * 4 + 2] = (xywh[i * 4 + 2] as number) / w;\n xywh[i * 4 + 3] = (xywh[i * 4 + 3] as number) / h;\n }\n return xywh;\n }\n\n /**\n * Concatenated `[N, 6]` array of `[x1, y1, x2, y2, conf, cls]`.\n *\n * Matches Ultralytics' `boxes.data`.\n */\n get data(): Float32Array {\n const out = new Float32Array(this.length * 6);\n for (let i = 0; i < this.length; i++) {\n out[i * 6] = this.xyxy[i * 4] as number;\n out[i * 6 + 1] = this.xyxy[i * 4 + 1] as number;\n out[i * 6 + 2] = this.xyxy[i * 4 + 2] as number;\n out[i * 6 + 3] = this.xyxy[i * 4 + 3] as number;\n out[i * 6 + 4] = this.conf[i] as number;\n out[i * 6 + 5] = this.cls[i] as number;\n }\n return out;\n }\n}\n\n/**\n * Top-k classification probabilities for a single image.\n *\n * Mirrors Ultralytics' `Probs` interface.\n */\nexport class Probs {\n /** @param data `[numClasses]` per-class probabilities, indexed by class id. */\n constructor(public readonly data: Float32Array) {}\n\n /** Number of classes. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[numClasses]` shape of the underlying vector. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n /** Index of the most probable class. */\n get top1(): number {\n if (this.data.length === 0) return 0;\n let best = 0;\n let bestVal = this.data[0] as number;\n for (let i = 1; i < this.data.length; i++) {\n const v = this.data[i] as number;\n if (v > bestVal) {\n best = i;\n bestVal = v;\n }\n }\n return best;\n }\n\n /** Probability of the top-1 class. */\n get top1conf(): number {\n if (this.data.length === 0) return 0;\n return this.data[this.top1] as number;\n }\n\n /** Indices of the top-5 most probable classes, descending. */\n get top5(): Int32Array {\n return this._topK(5).indices;\n }\n\n /** Probabilities of the top-5 classes, descending. */\n get top5conf(): Float32Array {\n return this._topK(5).values;\n }\n\n private _topK(k: number): { indices: Int32Array; values: Float32Array } {\n const n = Math.min(k, this.data.length);\n const order: number[] = [];\n for (let i = 0; i < this.data.length; i++) order.push(i);\n order.sort((a, b) => (this.data[b] as number) - (this.data[a] as number));\n const indices = new Int32Array(n);\n const values = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n indices[i] = order[i] as number;\n values[i] = this.data[order[i] as number] as number;\n }\n return { indices, values };\n }\n}\n\n/**\n * Per-instance binary masks for a single image.\n *\n * Each mask is cropped to its instance's bounding box. To paint masks onto\n * a full-image canvas, use `xyxy[i]` as the top-left target.\n */\nexport class Masks {\n /**\n * @param data Per-instance binary masks (`Mask` objects from `types.ts`).\n * @param xyxy Flat `[N, 4]` of bounding-box coordinates in original pixels.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly data: ReadonlyArray<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }>,\n public readonly xyxy: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of instance masks. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[N]` shape of the masks collection. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n [Symbol.iterator](): Iterator<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }> {\n return this.data[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image detection envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link DetectionResult} entries, so legacy\n * code that did `for (const d of detector.predict(img))` only needs an\n * extra `[0]` to bridge:\n *\n * ```typescript\n * for (const d of (await detector.predict(img))[0]) {\n * console.log(d.cls, d.conf, d.box.xyxy);\n * }\n * ```\n *\n * For numpy-style bulk access, use the `boxes` collection.\n */\nexport class DetectionResults implements Iterable<DetectionResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly detections: readonly DetectionResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving detections. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance detections. */\n get(index: number): DetectionResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<DetectionResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image classification envelope (Ultralytics-style `Results`).\n */\nexport class ClassificationResults {\n constructor(\n public readonly probs: Probs,\n public readonly result: ClassificationResult,\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Top-1 class index (Ultralytics-style alias). */\n get cls(): number {\n return this.probs.top1;\n }\n\n /** Top-1 confidence (Ultralytics-style alias). */\n get conf(): number {\n return this.probs.top1conf;\n }\n\n /** Top-1 class name. */\n get name(): string {\n return this.names[this.cls] ?? `class_${this.cls}`;\n }\n\n /** Per-class probability list, sorted descending (legacy field). */\n get probabilities(): readonly ClassificationResult[\"probabilities\"][number][] {\n return this.result.probabilities;\n }\n}\n\n/**\n * Per-image instance-segmentation envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link SegmentationResult} entries. `boxes`\n * and `masks` mirror Ultralytics' bulk-array views.\n */\nexport class SegmentationResults implements Iterable<SegmentationResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly masks: Masks,\n public readonly detections: readonly SegmentationResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving instances. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance results. */\n get(index: number): SegmentationResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<SegmentationResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,10 @@
1
1
  //#region src/vision/results.ts
2
- var e = class {
2
+ var e = {
3
+ load: 0,
4
+ preprocess: 0,
5
+ inference: 0,
6
+ postprocess: 0
7
+ }, t = class {
3
8
  xyxy;
4
9
  cls;
5
10
  conf;
@@ -38,7 +43,7 @@ var e = class {
38
43
  for (let t = 0; t < this.length; t++) e[t * 6] = this.xyxy[t * 4], e[t * 6 + 1] = this.xyxy[t * 4 + 1], e[t * 6 + 2] = this.xyxy[t * 4 + 2], e[t * 6 + 3] = this.xyxy[t * 4 + 3], e[t * 6 + 4] = this.conf[t], e[t * 6 + 5] = this.cls[t];
39
44
  return e;
40
45
  }
41
- }, t = class {
46
+ }, n = class {
42
47
  data;
43
48
  constructor(e) {
44
49
  this.data = e;
@@ -78,7 +83,7 @@ var e = class {
78
83
  values: i
79
84
  };
80
85
  }
81
- }, n = class {
86
+ }, r = class {
82
87
  data;
83
88
  xyxy;
84
89
  origShape;
@@ -94,7 +99,7 @@ var e = class {
94
99
  [Symbol.iterator]() {
95
100
  return this.data[Symbol.iterator]();
96
101
  }
97
- }, r = class {
102
+ }, i = class {
98
103
  boxes;
99
104
  detections;
100
105
  names;
@@ -102,8 +107,8 @@ var e = class {
102
107
  origShape;
103
108
  path;
104
109
  speed;
105
- constructor(e, t, n, r, i, a = null, o = {}) {
106
- this.boxes = e, this.detections = t, this.names = n, this.origImg = r, this.origShape = i, this.path = a, this.speed = o;
110
+ constructor(t, n, r, i, a, o = null, s = e) {
111
+ this.boxes = t, this.detections = n, this.names = r, this.origImg = i, this.origShape = a, this.path = o, this.speed = s;
107
112
  }
108
113
  get length() {
109
114
  return this.detections.length;
@@ -114,7 +119,7 @@ var e = class {
114
119
  [Symbol.iterator]() {
115
120
  return this.detections[Symbol.iterator]();
116
121
  }
117
- }, i = class {
122
+ }, a = class {
118
123
  probs;
119
124
  result;
120
125
  names;
@@ -122,8 +127,8 @@ var e = class {
122
127
  origShape;
123
128
  path;
124
129
  speed;
125
- constructor(e, t, n, r, i, a = null, o = {}) {
126
- this.probs = e, this.result = t, this.names = n, this.origImg = r, this.origShape = i, this.path = a, this.speed = o;
130
+ constructor(t, n, r, i, a, o = null, s = e) {
131
+ this.probs = t, this.result = n, this.names = r, this.origImg = i, this.origShape = a, this.path = o, this.speed = s;
127
132
  }
128
133
  get cls() {
129
134
  return this.probs.top1;
@@ -137,7 +142,7 @@ var e = class {
137
142
  get probabilities() {
138
143
  return this.result.probabilities;
139
144
  }
140
- }, a = class {
145
+ }, o = class {
141
146
  boxes;
142
147
  masks;
143
148
  detections;
@@ -146,8 +151,8 @@ var e = class {
146
151
  origShape;
147
152
  path;
148
153
  speed;
149
- constructor(e, t, n, r, i, a, o = null, s = {}) {
150
- this.boxes = e, this.masks = t, this.detections = n, this.names = r, this.origImg = i, this.origShape = a, this.path = o, this.speed = s;
154
+ constructor(t, n, r, i, a, o, s = null, c = e) {
155
+ this.boxes = t, this.masks = n, this.detections = r, this.names = i, this.origImg = a, this.origShape = o, this.path = s, this.speed = c;
151
156
  }
152
157
  get length() {
153
158
  return this.detections.length;
@@ -160,6 +165,6 @@ var e = class {
160
165
  }
161
166
  };
162
167
  //#endregion
163
- export { e as Boxes, i as ClassificationResults, r as DetectionResults, n as Masks, t as Probs, a as SegmentationResults };
168
+ export { t as Boxes, a as ClassificationResults, i as DetectionResults, r as Masks, n as Probs, o as SegmentationResults };
164
169
 
165
170
  //# sourceMappingURL=results.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"results.js","names":[],"sources":["../../src/vision/results.ts"],"sourcesContent":["/**\n * Per-image result envelopes — Ultralytics-style `Results` for the SDK.\n *\n * Each `predict()` call returns a 1-element array of these envelopes,\n * mirroring `YOLO(\"img.jpg\")`. Each envelope holds:\n *\n * - A bulk-array view of the predictions (`Boxes`, `Probs`, `Masks`) with\n * the exact attribute names Ultralytics uses (`xyxy`, `xywh`, `xyxyn`,\n * `xywhn`, `cls`, `conf`, `data`, `top1`, `top5`).\n * - Per-instance dataclasses (`DetectionResult`, `SegmentationResult`,\n * `ClassProbability`) for callers who prefer the OO interface.\n * - `names`: `Record<number, string>` matching Ultralytics' `model.names`.\n * - `origImg` / `origShape` / `path`: provenance for the original input.\n */\n\nimport {\n type ClassificationResult,\n type DetectionResult,\n type RGBImage,\n type SegmentationResult,\n} from \"./types\";\n\n/**\n * Bulk numpy-style view of detected boxes for a single image.\n *\n * Mirrors Ultralytics' `Boxes` interface. Coordinates in {@link xyxy} and\n * {@link xywh} are absolute pixels in the original image; the `*n` variants\n * are normalized to `[0, 1]` using `origShape`.\n */\nexport class Boxes {\n /**\n * @param xyxy Flat array of length `4 * N` in `[x1, y1, x2, y2, ...]` order.\n * @param cls One class index per box, length `N`.\n * @param conf One confidence per box, length `N`.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly xyxy: Float32Array,\n public readonly cls: Int32Array,\n public readonly conf: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of detected boxes. */\n get length(): number {\n return this.cls.length;\n }\n\n /** `[N, 4]` shape of the `xyxy` view. */\n get shape(): readonly [number, number] {\n return [this.length, 4];\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` flat array in absolute pixels. */\n get xywh(): Float32Array {\n const out = new Float32Array(this.xyxy.length);\n for (let i = 0; i < this.length; i++) {\n const x1 = this.xyxy[i * 4] as number;\n const y1 = this.xyxy[i * 4 + 1] as number;\n const x2 = this.xyxy[i * 4 + 2] as number;\n const y2 = this.xyxy[i * 4 + 3] as number;\n out[i * 4] = (x1 + x2) / 2;\n out[i * 4 + 1] = (y1 + y2) / 2;\n out[i * 4 + 2] = x2 - x1;\n out[i * 4 + 3] = y2 - y1;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[x1, y1, x2, y2]` normalized to `[0, 1]`. */\n get xyxyn(): Float32Array {\n const [h, w] = this.origShape;\n const out = new Float32Array(this.xyxy.length);\n if (this.length === 0 || w <= 0 || h <= 0) return out;\n for (let i = 0; i < this.length; i++) {\n out[i * 4] = (this.xyxy[i * 4] as number) / w;\n out[i * 4 + 1] = (this.xyxy[i * 4 + 1] as number) / h;\n out[i * 4 + 2] = (this.xyxy[i * 4 + 2] as number) / w;\n out[i * 4 + 3] = (this.xyxy[i * 4 + 3] as number) / h;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` normalized to `[0, 1]`. */\n get xywhn(): Float32Array {\n const xywh = this.xywh;\n const [h, w] = this.origShape;\n if (this.length === 0 || w <= 0 || h <= 0) return xywh;\n for (let i = 0; i < this.length; i++) {\n xywh[i * 4] = (xywh[i * 4] as number) / w;\n xywh[i * 4 + 1] = (xywh[i * 4 + 1] as number) / h;\n xywh[i * 4 + 2] = (xywh[i * 4 + 2] as number) / w;\n xywh[i * 4 + 3] = (xywh[i * 4 + 3] as number) / h;\n }\n return xywh;\n }\n\n /**\n * Concatenated `[N, 6]` array of `[x1, y1, x2, y2, conf, cls]`.\n *\n * Matches Ultralytics' `boxes.data`.\n */\n get data(): Float32Array {\n const out = new Float32Array(this.length * 6);\n for (let i = 0; i < this.length; i++) {\n out[i * 6] = this.xyxy[i * 4] as number;\n out[i * 6 + 1] = this.xyxy[i * 4 + 1] as number;\n out[i * 6 + 2] = this.xyxy[i * 4 + 2] as number;\n out[i * 6 + 3] = this.xyxy[i * 4 + 3] as number;\n out[i * 6 + 4] = this.conf[i] as number;\n out[i * 6 + 5] = this.cls[i] as number;\n }\n return out;\n }\n}\n\n/**\n * Top-k classification probabilities for a single image.\n *\n * Mirrors Ultralytics' `Probs` interface.\n */\nexport class Probs {\n /** @param data `[numClasses]` per-class probabilities, indexed by class id. */\n constructor(public readonly data: Float32Array) {}\n\n /** Number of classes. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[numClasses]` shape of the underlying vector. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n /** Index of the most probable class. */\n get top1(): number {\n if (this.data.length === 0) return 0;\n let best = 0;\n let bestVal = this.data[0] as number;\n for (let i = 1; i < this.data.length; i++) {\n const v = this.data[i] as number;\n if (v > bestVal) {\n best = i;\n bestVal = v;\n }\n }\n return best;\n }\n\n /** Probability of the top-1 class. */\n get top1conf(): number {\n if (this.data.length === 0) return 0;\n return this.data[this.top1] as number;\n }\n\n /** Indices of the top-5 most probable classes, descending. */\n get top5(): Int32Array {\n return this._topK(5).indices;\n }\n\n /** Probabilities of the top-5 classes, descending. */\n get top5conf(): Float32Array {\n return this._topK(5).values;\n }\n\n private _topK(k: number): { indices: Int32Array; values: Float32Array } {\n const n = Math.min(k, this.data.length);\n const order: number[] = [];\n for (let i = 0; i < this.data.length; i++) order.push(i);\n order.sort((a, b) => (this.data[b] as number) - (this.data[a] as number));\n const indices = new Int32Array(n);\n const values = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n indices[i] = order[i] as number;\n values[i] = this.data[order[i] as number] as number;\n }\n return { indices, values };\n }\n}\n\n/**\n * Per-instance binary masks for a single image.\n *\n * Each mask is cropped to its instance's bounding box. To paint masks onto\n * a full-image canvas, use `xyxy[i]` as the top-left target.\n */\nexport class Masks {\n /**\n * @param data Per-instance binary masks (`Mask` objects from `types.ts`).\n * @param xyxy Flat `[N, 4]` of bounding-box coordinates in original pixels.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly data: ReadonlyArray<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }>,\n public readonly xyxy: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of instance masks. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[N]` shape of the masks collection. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n [Symbol.iterator](): Iterator<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }> {\n return this.data[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image detection envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link DetectionResult} entries, so legacy\n * code that did `for (const d of detector.predict(img))` only needs an\n * extra `[0]` to bridge:\n *\n * ```typescript\n * for (const d of (await detector.predict(img))[0]) {\n * console.log(d.cls, d.conf, d.box.xyxy);\n * }\n * ```\n *\n * For numpy-style bulk access, use the `boxes` collection.\n */\nexport class DetectionResults implements Iterable<DetectionResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly detections: readonly DetectionResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Record<string, number>> = {},\n ) {}\n\n /** Number of surviving detections. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance detections. */\n get(index: number): DetectionResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<DetectionResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image classification envelope (Ultralytics-style `Results`).\n */\nexport class ClassificationResults {\n constructor(\n public readonly probs: Probs,\n public readonly result: ClassificationResult,\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Record<string, number>> = {},\n ) {}\n\n /** Top-1 class index (Ultralytics-style alias). */\n get cls(): number {\n return this.probs.top1;\n }\n\n /** Top-1 confidence (Ultralytics-style alias). */\n get conf(): number {\n return this.probs.top1conf;\n }\n\n /** Top-1 class name. */\n get name(): string {\n return this.names[this.cls] ?? `class_${this.cls}`;\n }\n\n /** Per-class probability list, sorted descending (legacy field). */\n get probabilities(): readonly ClassificationResult[\"probabilities\"][number][] {\n return this.result.probabilities;\n }\n}\n\n/**\n * Per-image instance-segmentation envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link SegmentationResult} entries. `boxes`\n * and `masks` mirror Ultralytics' bulk-array views.\n */\nexport class SegmentationResults implements Iterable<SegmentationResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly masks: Masks,\n public readonly detections: readonly SegmentationResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Record<string, number>> = {},\n ) {}\n\n /** Number of surviving instances. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance results. */\n get(index: number): SegmentationResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<SegmentationResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"results.js","names":[],"sources":["../../src/vision/results.ts"],"sourcesContent":["/**\n * Per-image result envelopes — Ultralytics-style `Results` for the SDK.\n *\n * Each `predict()` call returns a 1-element array of these envelopes,\n * mirroring `YOLO(\"img.jpg\")`. Each envelope holds:\n *\n * - A bulk-array view of the predictions (`Boxes`, `Probs`, `Masks`) with\n * the exact attribute names Ultralytics uses (`xyxy`, `xywh`, `xyxyn`,\n * `xywhn`, `cls`, `conf`, `data`, `top1`, `top5`).\n * - Per-instance dataclasses (`DetectionResult`, `SegmentationResult`,\n * `ClassProbability`) for callers who prefer the OO interface.\n * - `names`: `Record<number, string>` matching Ultralytics' `model.names`.\n * - `origImg` / `origShape` / `path`: provenance for the original input.\n * - `speed`: per-stage timings of the `predict()` call that produced it.\n */\n\nimport { type Speed } from \"./core/timing\";\nimport {\n type ClassificationResult,\n type DetectionResult,\n type RGBImage,\n type SegmentationResult,\n} from \"./types\";\n\n/**\n * Zero timings for an envelope built outside a `predict()` call.\n *\n * Hand-constructed envelopes (tests, adapters) have nothing to measure, and\n * zeros keep `speed.inference` a plain `number` at every call site instead of\n * forcing an optional check that only ever fires for synthetic data.\n */\nconst NO_SPEED: Speed = { load: 0, preprocess: 0, inference: 0, postprocess: 0 };\n\n/**\n * Bulk numpy-style view of detected boxes for a single image.\n *\n * Mirrors Ultralytics' `Boxes` interface. Coordinates in {@link xyxy} and\n * {@link xywh} are absolute pixels in the original image; the `*n` variants\n * are normalized to `[0, 1]` using `origShape`.\n */\nexport class Boxes {\n /**\n * @param xyxy Flat array of length `4 * N` in `[x1, y1, x2, y2, ...]` order.\n * @param cls One class index per box, length `N`.\n * @param conf One confidence per box, length `N`.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly xyxy: Float32Array,\n public readonly cls: Int32Array,\n public readonly conf: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of detected boxes. */\n get length(): number {\n return this.cls.length;\n }\n\n /** `[N, 4]` shape of the `xyxy` view. */\n get shape(): readonly [number, number] {\n return [this.length, 4];\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` flat array in absolute pixels. */\n get xywh(): Float32Array {\n const out = new Float32Array(this.xyxy.length);\n for (let i = 0; i < this.length; i++) {\n const x1 = this.xyxy[i * 4] as number;\n const y1 = this.xyxy[i * 4 + 1] as number;\n const x2 = this.xyxy[i * 4 + 2] as number;\n const y2 = this.xyxy[i * 4 + 3] as number;\n out[i * 4] = (x1 + x2) / 2;\n out[i * 4 + 1] = (y1 + y2) / 2;\n out[i * 4 + 2] = x2 - x1;\n out[i * 4 + 3] = y2 - y1;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[x1, y1, x2, y2]` normalized to `[0, 1]`. */\n get xyxyn(): Float32Array {\n const [h, w] = this.origShape;\n const out = new Float32Array(this.xyxy.length);\n if (this.length === 0 || w <= 0 || h <= 0) return out;\n for (let i = 0; i < this.length; i++) {\n out[i * 4] = (this.xyxy[i * 4] as number) / w;\n out[i * 4 + 1] = (this.xyxy[i * 4 + 1] as number) / h;\n out[i * 4 + 2] = (this.xyxy[i * 4 + 2] as number) / w;\n out[i * 4 + 3] = (this.xyxy[i * 4 + 3] as number) / h;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` normalized to `[0, 1]`. */\n get xywhn(): Float32Array {\n const xywh = this.xywh;\n const [h, w] = this.origShape;\n if (this.length === 0 || w <= 0 || h <= 0) return xywh;\n for (let i = 0; i < this.length; i++) {\n xywh[i * 4] = (xywh[i * 4] as number) / w;\n xywh[i * 4 + 1] = (xywh[i * 4 + 1] as number) / h;\n xywh[i * 4 + 2] = (xywh[i * 4 + 2] as number) / w;\n xywh[i * 4 + 3] = (xywh[i * 4 + 3] as number) / h;\n }\n return xywh;\n }\n\n /**\n * Concatenated `[N, 6]` array of `[x1, y1, x2, y2, conf, cls]`.\n *\n * Matches Ultralytics' `boxes.data`.\n */\n get data(): Float32Array {\n const out = new Float32Array(this.length * 6);\n for (let i = 0; i < this.length; i++) {\n out[i * 6] = this.xyxy[i * 4] as number;\n out[i * 6 + 1] = this.xyxy[i * 4 + 1] as number;\n out[i * 6 + 2] = this.xyxy[i * 4 + 2] as number;\n out[i * 6 + 3] = this.xyxy[i * 4 + 3] as number;\n out[i * 6 + 4] = this.conf[i] as number;\n out[i * 6 + 5] = this.cls[i] as number;\n }\n return out;\n }\n}\n\n/**\n * Top-k classification probabilities for a single image.\n *\n * Mirrors Ultralytics' `Probs` interface.\n */\nexport class Probs {\n /** @param data `[numClasses]` per-class probabilities, indexed by class id. */\n constructor(public readonly data: Float32Array) {}\n\n /** Number of classes. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[numClasses]` shape of the underlying vector. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n /** Index of the most probable class. */\n get top1(): number {\n if (this.data.length === 0) return 0;\n let best = 0;\n let bestVal = this.data[0] as number;\n for (let i = 1; i < this.data.length; i++) {\n const v = this.data[i] as number;\n if (v > bestVal) {\n best = i;\n bestVal = v;\n }\n }\n return best;\n }\n\n /** Probability of the top-1 class. */\n get top1conf(): number {\n if (this.data.length === 0) return 0;\n return this.data[this.top1] as number;\n }\n\n /** Indices of the top-5 most probable classes, descending. */\n get top5(): Int32Array {\n return this._topK(5).indices;\n }\n\n /** Probabilities of the top-5 classes, descending. */\n get top5conf(): Float32Array {\n return this._topK(5).values;\n }\n\n private _topK(k: number): { indices: Int32Array; values: Float32Array } {\n const n = Math.min(k, this.data.length);\n const order: number[] = [];\n for (let i = 0; i < this.data.length; i++) order.push(i);\n order.sort((a, b) => (this.data[b] as number) - (this.data[a] as number));\n const indices = new Int32Array(n);\n const values = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n indices[i] = order[i] as number;\n values[i] = this.data[order[i] as number] as number;\n }\n return { indices, values };\n }\n}\n\n/**\n * Per-instance binary masks for a single image.\n *\n * Each mask is cropped to its instance's bounding box. To paint masks onto\n * a full-image canvas, use `xyxy[i]` as the top-left target.\n */\nexport class Masks {\n /**\n * @param data Per-instance binary masks (`Mask` objects from `types.ts`).\n * @param xyxy Flat `[N, 4]` of bounding-box coordinates in original pixels.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly data: ReadonlyArray<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }>,\n public readonly xyxy: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of instance masks. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[N]` shape of the masks collection. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n [Symbol.iterator](): Iterator<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }> {\n return this.data[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image detection envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link DetectionResult} entries, so legacy\n * code that did `for (const d of detector.predict(img))` only needs an\n * extra `[0]` to bridge:\n *\n * ```typescript\n * for (const d of (await detector.predict(img))[0]) {\n * console.log(d.cls, d.conf, d.box.xyxy);\n * }\n * ```\n *\n * For numpy-style bulk access, use the `boxes` collection.\n */\nexport class DetectionResults implements Iterable<DetectionResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly detections: readonly DetectionResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving detections. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance detections. */\n get(index: number): DetectionResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<DetectionResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image classification envelope (Ultralytics-style `Results`).\n */\nexport class ClassificationResults {\n constructor(\n public readonly probs: Probs,\n public readonly result: ClassificationResult,\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Top-1 class index (Ultralytics-style alias). */\n get cls(): number {\n return this.probs.top1;\n }\n\n /** Top-1 confidence (Ultralytics-style alias). */\n get conf(): number {\n return this.probs.top1conf;\n }\n\n /** Top-1 class name. */\n get name(): string {\n return this.names[this.cls] ?? `class_${this.cls}`;\n }\n\n /** Per-class probability list, sorted descending (legacy field). */\n get probabilities(): readonly ClassificationResult[\"probabilities\"][number][] {\n return this.result.probabilities;\n }\n}\n\n/**\n * Per-image instance-segmentation envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link SegmentationResult} entries. `boxes`\n * and `masks` mirror Ultralytics' bulk-array views.\n */\nexport class SegmentationResults implements Iterable<SegmentationResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly masks: Masks,\n public readonly detections: readonly SegmentationResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving instances. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance results. */\n get(index: number): SegmentationResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<SegmentationResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("../results.cjs"),t=require("../labels.cjs"),n=require("../core/session.cjs"),r=require("../io/image.cjs"),i=require("../preprocess/image.cjs"),a=require("../postprocess/classification.cjs"),o=require("./base.cjs");var s=[.485,.456,.406],c=[.229,.224,.225],l=class l extends o.VisionTask{_labels;_names;_inputSize;_mean;_std;_applySoftmax;constructor(e,t,n,r,i,a,o){super(e),this._labels=t,this._names=n,this._inputSize=r,this._mean=i,this._std=a,this._applySoftmax=o}static async create(e,r){let i=await n.OrtSession.create(e,r),a=t.resolveLabels(r.labels,{numClasses:r.numClasses}),o={};for(let e=0;e<a.length;e++)o[e]=a[e];return new l(i,a,o,r.inputSize??[224,224],r.mean??s,r.std??c,r.applySoftmax??!0)}get labels(){return this._labels}get names(){return this._names}get numClasses(){return this._labels.length}async call(e,t={}){return this.predict(e,t)}async predict(t,n={}){let i=typeof t==`string`?t:null,o=await r.loadImage(t),s=this._preprocess(o),c=await this._session.run({[this._session.inputName]:s}),l=this._session.outputNames[0];if(l===void 0)throw Error(`Classifier model has no outputs.`);let u=c[l];if(u===void 0)throw Error(`Classifier model output ${l} missing from run() result.`);let d=this._postprocess(u.data),{indices:f,values:p}=a.topK(d,n.topK??null),m=[];for(let e=0;e<f.length;e++){let t=f[e],n=this._labels[t]??`class_${t}`;m.push({classId:t,className:n,probability:p[e],cls:t,name:n,conf:p[e]})}if(m.length===0)throw Error(`Classifier produced no probabilities (empty output).`);let h=m[0],g={classId:h.classId,className:h.className,confidence:h.probability,cls:h.classId,name:h.className,conf:h.probability,image:o,probabilities:m},_=[o.height,o.width];return[new e.ClassificationResults(new e.Probs(d),g,this._names,o,_,i)]}_preprocess(e){let[t,n]=this._inputSize,r=i.resize(e,t,n);return i.toFloat32Tensor(i.toCHW(i.normalize(r,this._mean,this._std),r.width,r.height,3),[1,3,r.height,r.width])}_postprocess(e){return this._applySoftmax?a.softmax(e):new Float32Array(e)}};exports.Classifier=l;
1
+ const e=require("../core/timing.cjs"),t=require("../results.cjs"),n=require("../labels.cjs"),r=require("../core/session.cjs"),i=require("../io/image.cjs"),a=require("../preprocess/image.cjs"),o=require("../postprocess/classification.cjs"),s=require("./base.cjs");var c=[.485,.456,.406],l=[.229,.224,.225],u=class u extends s.VisionTask{_labels;_names;_inputSize;_mean;_std;_applySoftmax;constructor(e,t,n,r,i,a,o){super(e),this._labels=t,this._names=n,this._inputSize=r,this._mean=i,this._std=a,this._applySoftmax=o}static async create(e,t){let i=await r.OrtSession.create(e,t),a=n.resolveLabels(t.labels,{numClasses:t.numClasses}),o={};for(let e=0;e<a.length;e++)o[e]=a[e];return new u(i,a,o,t.inputSize??[224,224],t.mean??c,t.std??l,t.applySoftmax??!0)}get labels(){return this._labels}get names(){return this._names}get numClasses(){return this._labels.length}async call(e,t={}){return this.predict(e,t)}async predict(n,r={}){let a=new e.SpeedTimer,s=typeof n==`string`?n:null,c=await i.loadImage(n);a.stage(`load`);let l=this._preprocess(c);a.stage(`preprocess`);let u=await this._session.run({[this._session.inputName]:l});a.stage(`inference`);let d=this._session.outputNames[0];if(d===void 0)throw Error(`Classifier model has no outputs.`);let f=u[d];if(f===void 0)throw Error(`Classifier model output ${d} missing from run() result.`);let p=this._postprocess(f.data),{indices:m,values:h}=o.topK(p,r.topK??null),g=[];for(let e=0;e<m.length;e++){let t=m[e],n=this._labels[t]??`class_${t}`;g.push({classId:t,className:n,probability:h[e],cls:t,name:n,conf:h[e]})}if(g.length===0)throw Error(`Classifier produced no probabilities (empty output).`);let _=g[0],v={classId:_.classId,className:_.className,confidence:_.probability,cls:_.classId,name:_.className,conf:_.probability,image:c,probabilities:g},y=[c.height,c.width],b=new t.Probs(p);return a.stage(`postprocess`),[new t.ClassificationResults(b,v,this._names,c,y,s,a.speed())]}_preprocess(e){let[t,n]=this._inputSize,r=a.resize(e,t,n);return a.toFloat32Tensor(a.toCHW(a.normalize(r,this._mean,this._std),r.width,r.height,3),[1,3,r.height,r.width])}_postprocess(e){return this._applySoftmax?o.softmax(e):new Float32Array(e)}};exports.Classifier=u;
2
2
  //# sourceMappingURL=classifier.cjs.map