supervision 0.2.0 → 0.2.2

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 (56) hide show
  1. package/dist/index.d.ts +6 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +140 -25
  4. package/dist/index.js.map +1 -1
  5. package/dist/mask-preparation.worker.js +9 -0
  6. package/dist/mask-preparation.worker.js.map +1 -1
  7. package/dist/renderers/annotation-shape-styles.d.ts +3 -1
  8. package/dist/renderers/annotation-shape-styles.d.ts.map +1 -1
  9. package/dist/renderers/media-renderer-core.d.ts.map +1 -1
  10. package/dist/renderers/media-renderer-scene.d.ts +4 -0
  11. package/dist/renderers/media-renderer-scene.d.ts.map +1 -1
  12. package/dist/renderers/pixi-interaction-layer.d.ts.map +1 -1
  13. package/dist/renderers/pixi-mask-brush-preview.d.ts +1 -0
  14. package/dist/renderers/pixi-mask-brush-preview.d.ts.map +1 -1
  15. package/dist/renderers/pixi-media-scene.d.ts.map +1 -1
  16. package/dist/sessions/media-session.d.ts.map +1 -1
  17. package/dist/tracking.worker.js +9 -0
  18. package/dist/tracking.worker.js.map +1 -1
  19. package/dist/types/media-renderer.d.ts +2 -0
  20. package/dist/types/media-renderer.d.ts.map +1 -1
  21. package/node_modules/supervision-js-core/dist/index.d.ts +9 -2
  22. package/node_modules/supervision-js-core/dist/index.d.ts.map +1 -1
  23. package/node_modules/supervision-js-core/dist/index.js +406 -79
  24. package/node_modules/supervision-js-core/dist/index.js.map +1 -1
  25. package/node_modules/supervision-js-core/dist/interactions/annotation-handles.d.ts.map +1 -1
  26. package/node_modules/supervision-js-core/dist/interactions/detection-picker.d.ts.map +1 -1
  27. package/node_modules/supervision-js-core/dist/styles/annotation-renderer-presentation.d.ts.map +1 -1
  28. package/node_modules/supervision-js-core/dist/styles/annotation-renderer-registry.d.ts +1 -1
  29. package/node_modules/supervision-js-core/dist/styles/annotation-renderer-registry.d.ts.map +1 -1
  30. package/node_modules/supervision-js-core/dist/styles/default-annotation-presentation.d.ts +8 -0
  31. package/node_modules/supervision-js-core/dist/styles/default-annotation-presentation.d.ts.map +1 -1
  32. package/node_modules/supervision-js-core/dist/styles/oriented-box-style.d.ts +35 -0
  33. package/node_modules/supervision-js-core/dist/styles/oriented-box-style.d.ts.map +1 -0
  34. package/node_modules/supervision-js-core/dist/styles/percentage-bar-style.d.ts +19 -0
  35. package/node_modules/supervision-js-core/dist/styles/percentage-bar-style.d.ts.map +1 -0
  36. package/node_modules/supervision-js-core/dist/styles/source-presentation.d.ts +4 -0
  37. package/node_modules/supervision-js-core/dist/styles/source-presentation.d.ts.map +1 -1
  38. package/node_modules/supervision-js-core/dist/types/annotation-renderer.d.ts +20 -2
  39. package/node_modules/supervision-js-core/dist/types/annotation-renderer.d.ts.map +1 -1
  40. package/node_modules/supervision-js-core/dist/types/detections.d.ts +15 -0
  41. package/node_modules/supervision-js-core/dist/types/detections.d.ts.map +1 -1
  42. package/node_modules/supervision-js-core/dist/types/interaction.d.ts +1 -0
  43. package/node_modules/supervision-js-core/dist/types/interaction.d.ts.map +1 -1
  44. package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts +4 -0
  45. package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts.map +1 -1
  46. package/node_modules/supervision-js-core/dist/types/oriented-box-style.d.ts +27 -0
  47. package/node_modules/supervision-js-core/dist/types/oriented-box-style.d.ts.map +1 -0
  48. package/node_modules/supervision-js-core/dist/types/percentage-bar-style.d.ts +76 -0
  49. package/node_modules/supervision-js-core/dist/types/percentage-bar-style.d.ts.map +1 -0
  50. package/node_modules/supervision-js-core/dist/types/shape-style.d.ts +1 -1
  51. package/node_modules/supervision-js-core/dist/types/shape-style.d.ts.map +1 -1
  52. package/node_modules/supervision-js-core/dist/utils/detection-frames.d.ts.map +1 -1
  53. package/node_modules/supervision-js-core/dist/utils/detection-projection.d.ts +6 -6
  54. package/node_modules/supervision-js-core/dist/utils/detection-projection.d.ts.map +1 -1
  55. package/node_modules/supervision-js-core/dist/utils/geometry.d.ts.map +1 -1
  56. package/package.json +1 -1
@@ -120,6 +120,13 @@ function copyDetectionFrame(frame) {
120
120
  metadata: detection.metadata
121
121
  ? copyDetectionMetadata(detection.metadata)
122
122
  : undefined,
123
+ orientedBox: detection.orientedBox
124
+ ? {
125
+ points: detection.orientedBox.points.map((point) => ({
126
+ ...point,
127
+ })),
128
+ }
129
+ : undefined,
123
130
  polygon: detection.polygon
124
131
  ? {
125
132
  points: detection.polygon.points.map((point) => ({ ...point })),
@@ -252,6 +259,17 @@ function validateDetectionFrames(detectionFrames) {
252
259
  }
253
260
  validatePoints(detection.polygon?.points, () => `${detectionPath()}.polygon`, 3);
254
261
  validatePoints(detection.polyline?.points, () => `${detectionPath()}.polyline`, 2);
262
+ if (detection.orientedBox !== undefined) {
263
+ const points = detection.orientedBox?.points;
264
+ const path = () => `${detectionPath()}.orientedBox.points`;
265
+ if (!Array.isArray(points) || points.length !== 4) {
266
+ throw new Error(`${path()} must contain exactly 4 points.`);
267
+ }
268
+ for (let index = 0; index < points.length; index += 1) {
269
+ validateNumber(points[index]?.x, () => `${path()}[${index}].x`);
270
+ validateNumber(points[index]?.y, () => `${path()}[${index}].y`);
271
+ }
272
+ }
255
273
  if (detection.keypoints) {
256
274
  validatePoints(detection.keypoints.points, () => `${detectionPath()}.keypoints`, 1);
257
275
  if (detection.keypoints.visibility !== undefined &&
@@ -1374,12 +1392,12 @@ function createColdDetectionFrameSource(options) {
1374
1392
  * Projects one detection frame from its declared source coordinate space into
1375
1393
  * `target`.
1376
1394
  *
1377
- * Rectangles, polygons, polylines, and keypoints are scaled. Masks are left
1378
- * untouched because a `DetectionMask` already carries the mask-pixel
1379
- * dimensions its `counts` are encoded against; scaling them here would apply
1380
- * the ratio twice. Frames without `coordinateSpace`, with a degenerate space,
1381
- * or already in the target space are returned unchanged so mixed producers can
1382
- * share one source.
1395
+ * Rectangles, polygons, oriented boxes, polylines, and keypoints are scaled.
1396
+ * Masks are left untouched because a `DetectionMask` already carries the
1397
+ * mask-pixel dimensions its `counts` are encoded against; scaling them here
1398
+ * would apply the ratio twice. Frames without `coordinateSpace`, with a
1399
+ * degenerate space, or already in the target space are returned unchanged so
1400
+ * mixed producers can share one source.
1383
1401
  */
1384
1402
  function projectDetectionFrame(frame, target) {
1385
1403
  const space = frame.coordinateSpace;
@@ -1420,6 +1438,9 @@ function projectDetection(detection, scaleX, scaleY) {
1420
1438
  ...(detection.polygon
1421
1439
  ? { polygon: scalePolygon(detection.polygon, scaleX, scaleY) }
1422
1440
  : {}),
1441
+ ...(detection.orientedBox
1442
+ ? { orientedBox: scaleOrientedBox(detection.orientedBox, scaleX, scaleY) }
1443
+ : {}),
1423
1444
  ...(detection.polyline
1424
1445
  ? { polyline: scalePolyline(detection.polyline, scaleX, scaleY) }
1425
1446
  : {}),
@@ -1439,6 +1460,30 @@ function scaleRect(rect, scaleX, scaleY) {
1439
1460
  function scalePolygon(polygon, scaleX, scaleY) {
1440
1461
  return { points: scalePoints(polygon.points, scaleX, scaleY) };
1441
1462
  }
1463
+ /**
1464
+ * Scales an explicit oriented-box quadrilateral by independent axis factors.
1465
+ *
1466
+ * A uniform scale keeps every vertex angle intact, but `scaleX` and `scaleY`
1467
+ * can differ when the source and target aspect ratios do not match. That
1468
+ * skews the quadrilateral's angles exactly the way it already skews a scaled
1469
+ * `Rect` or polygon, so a non-uniform projection stays internally consistent
1470
+ * across every detection geometry kind instead of only axis-aligned ones.
1471
+ */
1472
+ function scaleOrientedBox(orientedBox, scaleX, scaleY) {
1473
+ // `points` is typed as an exact 4-tuple, but a caller that bypasses the
1474
+ // type system (e.g. a detection deserialized from untyped data, the same
1475
+ // scenario BaseOrientedBoxStyle's own points.length !== 4 guard defends
1476
+ // against) can hand this an array of a different length. Scale whatever
1477
+ // length was actually given instead of destructuring into a synthetic
1478
+ // four-element tuple: destructuring a 3-point array pads a real
1479
+ // `undefined` into the fourth slot (which crashes downstream reading
1480
+ // `.x`/`.y`), and destructuring a 5+-point array silently truncates it
1481
+ // into an apparently-valid box. Preserving the real length lets the
1482
+ // style's own guard see and reject the malformed cardinality instead of
1483
+ // this function corrupting it into something that looks valid or crashes.
1484
+ const scaled = scalePoints(orientedBox.points, scaleX, scaleY);
1485
+ return { points: scaled };
1486
+ }
1442
1487
  function scalePolyline(polyline, scaleX, scaleY) {
1443
1488
  return { points: scalePoints(polyline.points, scaleX, scaleY) };
1444
1489
  }
@@ -4440,6 +4485,7 @@ function getPointsRect(points) {
4440
4485
  function getDetectionRect(detection) {
4441
4486
  return (detection.rect ??
4442
4487
  getPointsRect(detection.polygon?.points ?? []) ??
4488
+ getPointsRect(detection.orientedBox?.points ?? []) ??
4443
4489
  getPointsRect(detection.polyline?.points ?? []) ??
4444
4490
  getPointsRect(detection.keypoints?.points ?? []));
4445
4491
  }
@@ -4699,6 +4745,7 @@ var DetectionPickTarget;
4699
4745
  DetectionPickTarget["Keypoint"] = "keypoint";
4700
4746
  DetectionPickTarget["Label"] = "label";
4701
4747
  DetectionPickTarget["Mask"] = "mask";
4748
+ DetectionPickTarget["OrientedBox"] = "orientedBox";
4702
4749
  DetectionPickTarget["Polygon"] = "polygon";
4703
4750
  DetectionPickTarget["Polyline"] = "polyline";
4704
4751
  })(DetectionPickTarget || (DetectionPickTarget = {}));
@@ -4757,6 +4804,10 @@ function pickDetectionAtPoint(frame, point, options = {}) {
4757
4804
  if (detection.polygon && pointInPolygon(point, detection.polygon.points)) {
4758
4805
  pushCandidate(DetectionPickTarget.Polygon, Math.max(1, polygonArea(detection.polygon.points)));
4759
4806
  }
4807
+ if (detection.orientedBox &&
4808
+ pointInPolygon(point, detection.orientedBox.points)) {
4809
+ pushCandidate(DetectionPickTarget.OrientedBox, Math.max(1, polygonArea(detection.orientedBox.points)));
4810
+ }
4760
4811
  if (detection.polyline) {
4761
4812
  const segmentIndex = findHitSegment(point, detection.polyline.points, polylinePadding);
4762
4813
  if (segmentIndex !== -1) {
@@ -5282,6 +5333,13 @@ function offsetDetection(detection, dx, dy) {
5282
5333
  ...(detection.polygon
5283
5334
  ? { polygon: { points: detection.polygon.points.map(offsetPoint) } }
5284
5335
  : {}),
5336
+ ...(detection.orientedBox
5337
+ ? {
5338
+ orientedBox: {
5339
+ points: detection.orientedBox.points.map(offsetPoint),
5340
+ },
5341
+ }
5342
+ : {}),
5285
5343
  ...(detection.polyline
5286
5344
  ? { polyline: { points: detection.polyline.points.map(offsetPoint) } }
5287
5345
  : {}),
@@ -6460,6 +6518,272 @@ class BaseMarkerStyle {
6460
6518
  }
6461
6519
  }
6462
6520
 
6521
+ const DEFAULT_ORIENTED_BOX_STROKE_ALPHA = 1;
6522
+ const DEFAULT_ORIENTED_BOX_STROKE_COLOR = 0x00ff66;
6523
+ const DEFAULT_ORIENTED_BOX_STROKE_WIDTH = 2;
6524
+ const DEFAULT_ORIENTED_BOX_FILL_ALPHA = 0.16;
6525
+ /**
6526
+ * Default configurable oriented-box style.
6527
+ *
6528
+ * Converts detections carrying explicit `orientedBox` quadrilateral geometry
6529
+ * into a renderer-neutral closed-path draw instruction, the same fill/stroke
6530
+ * shape `BasePolygonStyle` produces. A quadrilateral is skipped, rather than
6531
+ * emitted as an invalid or degenerate draw instruction, when it has fewer
6532
+ * or more than four vertices, a non-finite (NaN/Infinity) coordinate, or exactly
6533
+ * zero area (`polygonArea` already returns 0 for fewer than three points).
6534
+ * There is no near-zero/epsilon tolerance; only exact zero area is rejected.
6535
+ */
6536
+ class BaseOrientedBoxStyle {
6537
+ options;
6538
+ constructor(options = {}) {
6539
+ this.options = options;
6540
+ }
6541
+ resolve(detection, context) {
6542
+ const points = detection.orientedBox?.points;
6543
+ if (!points ||
6544
+ points.length !== 4 ||
6545
+ points.some((point) => !Number.isFinite(point.x) || !Number.isFinite(point.y)) ||
6546
+ context.hidden ||
6547
+ polygonArea(points) === 0 ||
6548
+ this.options.shouldRender?.(detection, context) === false) {
6549
+ return undefined;
6550
+ }
6551
+ const fill = resolveStyleValue(this.options.fill, detection, context);
6552
+ const stroke = resolveStyleValue(this.options.stroke, detection, context);
6553
+ return {
6554
+ points,
6555
+ ...(fill === null
6556
+ ? {}
6557
+ : {
6558
+ fill: {
6559
+ alpha: fill?.alpha ?? DEFAULT_ORIENTED_BOX_FILL_ALPHA,
6560
+ color: fill?.color ?? DEFAULT_ORIENTED_BOX_STROKE_COLOR,
6561
+ },
6562
+ }),
6563
+ ...(stroke === null
6564
+ ? {}
6565
+ : {
6566
+ stroke: resolveStrokeStyle(stroke, {
6567
+ alpha: DEFAULT_ORIENTED_BOX_STROKE_ALPHA,
6568
+ color: DEFAULT_ORIENTED_BOX_STROKE_COLOR,
6569
+ width: DEFAULT_ORIENTED_BOX_STROKE_WIDTH,
6570
+ }),
6571
+ }),
6572
+ };
6573
+ }
6574
+ }
6575
+
6576
+ var PercentageBarPlacement;
6577
+ (function (PercentageBarPlacement) {
6578
+ PercentageBarPlacement["Top"] = "top";
6579
+ PercentageBarPlacement["Bottom"] = "bottom";
6580
+ PercentageBarPlacement["InsideTop"] = "insideTop";
6581
+ PercentageBarPlacement["InsideBottom"] = "insideBottom";
6582
+ })(PercentageBarPlacement || (PercentageBarPlacement = {}));
6583
+
6584
+ const SUPERVISION_ROBOFLOW_COLOR = 0xa351fb;
6585
+ const DEFAULT_DETECTION_COLOR_SEQUENCE = [
6586
+ createClassColorStyle(0x38bdf8, 0x164e63, 0xecfeff, 0x7dd3fc),
6587
+ createClassColorStyle(0x22c55e, 0x14532d, 0xf0fdf4, 0x86efac),
6588
+ createClassColorStyle(0xa78bfa, 0x4c1d95, 0xf5f3ff, 0xc4b5fd),
6589
+ createClassColorStyle(0xfacc15, 0x713f12, 0xfffbeb, 0xfde047),
6590
+ createClassColorStyle(0xf97316, 0x7c2d12, 0xfff7ed, 0xffa23a),
6591
+ createClassColorStyle(0xf472b6, 0x831843, 0xfdf2f8, 0xf9a8d4),
6592
+ createClassColorStyle(0x60a5fa, 0x1e3a8a, 0xeff6ff, 0x93c5fd),
6593
+ createClassColorStyle(0xfb7185, 0x881337, 0xfff1f2, 0xfda4af),
6594
+ createClassColorStyle(0x34d399, 0x064e3b, 0xecfdf5, 0x6ee7b7),
6595
+ createClassColorStyle(0xe879f9, 0x701a75, 0xfdf4ff, 0xf0abfc),
6596
+ ];
6597
+ const DEFAULT_DETECTION_CLASS_STYLES = {
6598
+ basketball: DEFAULT_DETECTION_COLOR_SEQUENCE[4],
6599
+ bed: DEFAULT_DETECTION_COLOR_SEQUENCE[5],
6600
+ bottle: DEFAULT_DETECTION_COLOR_SEQUENCE[4],
6601
+ "cell phone": DEFAULT_DETECTION_COLOR_SEQUENCE[8],
6602
+ cow: DEFAULT_DETECTION_COLOR_SEQUENCE[2],
6603
+ cup: DEFAULT_DETECTION_COLOR_SEQUENCE[3],
6604
+ horse: DEFAULT_DETECTION_COLOR_SEQUENCE[0],
6605
+ keyboard: DEFAULT_DETECTION_COLOR_SEQUENCE[1],
6606
+ knife: DEFAULT_DETECTION_COLOR_SEQUENCE[7],
6607
+ laptop: DEFAULT_DETECTION_COLOR_SEQUENCE[6],
6608
+ person: DEFAULT_DETECTION_COLOR_SEQUENCE[1],
6609
+ "potted plant": DEFAULT_DETECTION_COLOR_SEQUENCE[8],
6610
+ "sports ball": DEFAULT_DETECTION_COLOR_SEQUENCE[4],
6611
+ tv: DEFAULT_DETECTION_COLOR_SEQUENCE[2],
6612
+ "white team player": createClassColorStyle(0xf8fafc, 0x334155, 0xffffff, 0xffffff),
6613
+ "yellow team player": DEFAULT_DETECTION_COLOR_SEQUENCE[3],
6614
+ };
6615
+ // The "worklet" directives below are inert everywhere except React Native:
6616
+ // browsers and Node see a no-op string, while React Native's worklets Babel
6617
+ // plugin makes these functions callable inside frame worklets, so every
6618
+ // platform resolves detection colors through this one implementation.
6619
+ // Worklet constraint on ordering: the plugin turns marked declarations into
6620
+ // non-hoisted assignments that capture each other at module-init time, so
6621
+ // helpers must be defined before the functions that call them.
6622
+ function normalizeDetectionClassName(className) {
6623
+ "worklet";
6624
+ return (className ?? "")
6625
+ .trim()
6626
+ .toLowerCase()
6627
+ .replace(/[_-]/g, " ")
6628
+ .replace(/\s+/g, " ");
6629
+ }
6630
+ function hashClassName(className) {
6631
+ "worklet";
6632
+ let hash = 0;
6633
+ for (let index = 0; index < className.length; index += 1) {
6634
+ hash = (hash * 31 + className.charCodeAt(index)) >>> 0;
6635
+ }
6636
+ return hash;
6637
+ }
6638
+ function resolveDetectionClassColorStyle(className) {
6639
+ "worklet";
6640
+ const normalizedClassName = normalizeDetectionClassName(className);
6641
+ const knownStyle = DEFAULT_DETECTION_CLASS_STYLES[normalizedClassName];
6642
+ if (knownStyle) {
6643
+ return knownStyle;
6644
+ }
6645
+ return DEFAULT_DETECTION_COLOR_SEQUENCE[hashClassName(normalizedClassName) % DEFAULT_DETECTION_COLOR_SEQUENCE.length];
6646
+ }
6647
+ function createClassColorStyle(fill, labelBackground, labelText, stroke) {
6648
+ return {
6649
+ fill,
6650
+ labelBackground,
6651
+ labelText,
6652
+ stroke,
6653
+ };
6654
+ }
6655
+
6656
+ const DEFAULT_BAR_HEIGHT = 8;
6657
+ const DEFAULT_BACKGROUND_FILL = { alpha: 0.75, color: 0x0f172a };
6658
+ const DEFAULT_PROGRESS_ALPHA = 1;
6659
+ /**
6660
+ * Configurable percentage bar style anchored to detection rectangles.
6661
+ *
6662
+ * Converts a detection's confidence or custom numeric metric into a
6663
+ * proportional progress bar positioned relative to the detection bounding box.
6664
+ */
6665
+ class BasePercentageBarStyle {
6666
+ options;
6667
+ constructor(options = {}) {
6668
+ this.options = options;
6669
+ }
6670
+ resolve(detection, context) {
6671
+ if (context.hidden ||
6672
+ this.options.shouldRender?.(detection, context) === false) {
6673
+ return undefined;
6674
+ }
6675
+ const rect = getDetectionRect(detection);
6676
+ if (!rect || rect.width <= 0 || rect.height <= 0) {
6677
+ return undefined;
6678
+ }
6679
+ const rawValue = resolveStyleValue(this.options.value, detection, context) ??
6680
+ detection.confidence ??
6681
+ 0;
6682
+ const value = Math.min(1, Math.max(0, Number.isFinite(rawValue) ? rawValue : 0));
6683
+ const height = resolveStyleValue(this.options.height, detection, context) ??
6684
+ DEFAULT_BAR_HEIGHT;
6685
+ if (!Number.isFinite(height) || height <= 0) {
6686
+ return undefined;
6687
+ }
6688
+ const resolvedWidth = resolveStyleValue(this.options.width, detection, context);
6689
+ const width = resolvedWidth !== undefined &&
6690
+ Number.isFinite(resolvedWidth) &&
6691
+ resolvedWidth > 0
6692
+ ? resolvedWidth
6693
+ : rect.width;
6694
+ const placement = resolveStyleValue(this.options.placement, detection, context) ??
6695
+ PercentageBarPlacement.Top;
6696
+ const offset = resolveStyleValue(this.options.offset, detection, context);
6697
+ const offsetX = offset?.x ?? 0;
6698
+ const offsetY = (offset?.y ?? 0) + (this.options.offsetY ?? 0);
6699
+ const rectTop = rect.y - rect.height / 2;
6700
+ const rectBottom = rect.y + rect.height / 2;
6701
+ const barLeft = rect.x - width / 2 + offsetX;
6702
+ let barTop;
6703
+ switch (placement) {
6704
+ case PercentageBarPlacement.Bottom:
6705
+ barTop = rectBottom + offsetY;
6706
+ break;
6707
+ case PercentageBarPlacement.InsideTop:
6708
+ barTop = rectTop + offsetY;
6709
+ break;
6710
+ case PercentageBarPlacement.InsideBottom:
6711
+ barTop = rectBottom - height + offsetY;
6712
+ break;
6713
+ case PercentageBarPlacement.Top:
6714
+ default:
6715
+ barTop = rectTop - height + offsetY;
6716
+ break;
6717
+ }
6718
+ const backgroundRect = {
6719
+ height,
6720
+ width,
6721
+ x: barLeft + width / 2,
6722
+ y: barTop + height / 2,
6723
+ };
6724
+ const valueWidth = width * value;
6725
+ const valueRect = {
6726
+ height,
6727
+ width: valueWidth,
6728
+ x: barLeft + valueWidth / 2,
6729
+ y: barTop + height / 2,
6730
+ };
6731
+ const background = this.resolveBackground(detection, context);
6732
+ const fill = this.resolveFill(detection, context);
6733
+ const border = this.resolveBorder(detection, context);
6734
+ if (!background && !fill && !border) {
6735
+ return undefined;
6736
+ }
6737
+ return {
6738
+ ...(background ? { background } : {}),
6739
+ ...(border ? { border } : {}),
6740
+ ...(fill ? { fill } : {}),
6741
+ backgroundRect,
6742
+ value,
6743
+ valueRect,
6744
+ };
6745
+ }
6746
+ resolveBackground(detection, context) {
6747
+ const background = resolveStyleValue(this.options.background, detection, context);
6748
+ if (background === null) {
6749
+ return undefined;
6750
+ }
6751
+ return {
6752
+ alpha: background?.alpha ?? DEFAULT_BACKGROUND_FILL.alpha,
6753
+ color: background?.color ?? DEFAULT_BACKGROUND_FILL.color,
6754
+ };
6755
+ }
6756
+ resolveFill(detection, context) {
6757
+ const fill = resolveStyleValue(this.options.fill, detection, context);
6758
+ if (fill === null) {
6759
+ return undefined;
6760
+ }
6761
+ if (fill) {
6762
+ return {
6763
+ alpha: fill.alpha ?? DEFAULT_PROGRESS_ALPHA,
6764
+ color: fill.color ??
6765
+ resolveDetectionClassColorStyle(detection.className).stroke,
6766
+ };
6767
+ }
6768
+ const classColor = resolveDetectionClassColorStyle(detection.className);
6769
+ return {
6770
+ alpha: DEFAULT_PROGRESS_ALPHA,
6771
+ color: classColor.stroke,
6772
+ };
6773
+ }
6774
+ resolveBorder(detection, context) {
6775
+ const border = resolveStyleValue(this.options.border, detection, context);
6776
+ if (!border) {
6777
+ return undefined;
6778
+ }
6779
+ return resolveStrokeStyle(border, {
6780
+ alpha: 1,
6781
+ color: 0xffffff,
6782
+ width: 1,
6783
+ });
6784
+ }
6785
+ }
6786
+
6463
6787
  class BasePolygonStyle {
6464
6788
  options;
6465
6789
  constructor(options = {}) {
@@ -6611,78 +6935,6 @@ class BaseKeypointStyle {
6611
6935
  }
6612
6936
  }
6613
6937
 
6614
- const SUPERVISION_ROBOFLOW_COLOR = 0xa351fb;
6615
- const DEFAULT_DETECTION_COLOR_SEQUENCE = [
6616
- createClassColorStyle(0x38bdf8, 0x164e63, 0xecfeff, 0x7dd3fc),
6617
- createClassColorStyle(0x22c55e, 0x14532d, 0xf0fdf4, 0x86efac),
6618
- createClassColorStyle(0xa78bfa, 0x4c1d95, 0xf5f3ff, 0xc4b5fd),
6619
- createClassColorStyle(0xfacc15, 0x713f12, 0xfffbeb, 0xfde047),
6620
- createClassColorStyle(0xf97316, 0x7c2d12, 0xfff7ed, 0xffa23a),
6621
- createClassColorStyle(0xf472b6, 0x831843, 0xfdf2f8, 0xf9a8d4),
6622
- createClassColorStyle(0x60a5fa, 0x1e3a8a, 0xeff6ff, 0x93c5fd),
6623
- createClassColorStyle(0xfb7185, 0x881337, 0xfff1f2, 0xfda4af),
6624
- createClassColorStyle(0x34d399, 0x064e3b, 0xecfdf5, 0x6ee7b7),
6625
- createClassColorStyle(0xe879f9, 0x701a75, 0xfdf4ff, 0xf0abfc),
6626
- ];
6627
- const DEFAULT_DETECTION_CLASS_STYLES = {
6628
- basketball: DEFAULT_DETECTION_COLOR_SEQUENCE[4],
6629
- bed: DEFAULT_DETECTION_COLOR_SEQUENCE[5],
6630
- bottle: DEFAULT_DETECTION_COLOR_SEQUENCE[4],
6631
- "cell phone": DEFAULT_DETECTION_COLOR_SEQUENCE[8],
6632
- cow: DEFAULT_DETECTION_COLOR_SEQUENCE[2],
6633
- cup: DEFAULT_DETECTION_COLOR_SEQUENCE[3],
6634
- horse: DEFAULT_DETECTION_COLOR_SEQUENCE[0],
6635
- keyboard: DEFAULT_DETECTION_COLOR_SEQUENCE[1],
6636
- knife: DEFAULT_DETECTION_COLOR_SEQUENCE[7],
6637
- laptop: DEFAULT_DETECTION_COLOR_SEQUENCE[6],
6638
- person: DEFAULT_DETECTION_COLOR_SEQUENCE[1],
6639
- "potted plant": DEFAULT_DETECTION_COLOR_SEQUENCE[8],
6640
- "sports ball": DEFAULT_DETECTION_COLOR_SEQUENCE[4],
6641
- tv: DEFAULT_DETECTION_COLOR_SEQUENCE[2],
6642
- "white team player": createClassColorStyle(0xf8fafc, 0x334155, 0xffffff, 0xffffff),
6643
- "yellow team player": DEFAULT_DETECTION_COLOR_SEQUENCE[3],
6644
- };
6645
- // The "worklet" directives below are inert everywhere except React Native:
6646
- // browsers and Node see a no-op string, while React Native's worklets Babel
6647
- // plugin makes these functions callable inside frame worklets, so every
6648
- // platform resolves detection colors through this one implementation.
6649
- // Worklet constraint on ordering: the plugin turns marked declarations into
6650
- // non-hoisted assignments that capture each other at module-init time, so
6651
- // helpers must be defined before the functions that call them.
6652
- function normalizeDetectionClassName(className) {
6653
- "worklet";
6654
- return (className ?? "")
6655
- .trim()
6656
- .toLowerCase()
6657
- .replace(/[_-]/g, " ")
6658
- .replace(/\s+/g, " ");
6659
- }
6660
- function hashClassName(className) {
6661
- "worklet";
6662
- let hash = 0;
6663
- for (let index = 0; index < className.length; index += 1) {
6664
- hash = (hash * 31 + className.charCodeAt(index)) >>> 0;
6665
- }
6666
- return hash;
6667
- }
6668
- function resolveDetectionClassColorStyle(className) {
6669
- "worklet";
6670
- const normalizedClassName = normalizeDetectionClassName(className);
6671
- const knownStyle = DEFAULT_DETECTION_CLASS_STYLES[normalizedClassName];
6672
- if (knownStyle) {
6673
- return knownStyle;
6674
- }
6675
- return DEFAULT_DETECTION_COLOR_SEQUENCE[hashClassName(normalizedClassName) % DEFAULT_DETECTION_COLOR_SEQUENCE.length];
6676
- }
6677
- function createClassColorStyle(fill, labelBackground, labelText, stroke) {
6678
- return {
6679
- fill,
6680
- labelBackground,
6681
- labelText,
6682
- stroke,
6683
- };
6684
- }
6685
-
6686
6938
  const DEFAULT_BOX_CORNER_RADIUS = 1;
6687
6939
  const DEFAULT_ELLIPSE_AXIS_RATIO = 0.35;
6688
6940
  const DEFAULT_ELLIPSE_START_ANGLE = (-45 * Math.PI) / 180;
@@ -6867,6 +7119,24 @@ function createDefaultMaskHaloStyle(options = {}) {
6867
7119
  },
6868
7120
  };
6869
7121
  }
7122
+ /**
7123
+ * Canonical opt-in oriented-box presentation, styled the same as the default
7124
+ * polygon fill/stroke so the two closed shapes read consistently together.
7125
+ */
7126
+ function createDefaultOrientedBoxStyle(options = {}) {
7127
+ const getClassColor = createClassColorResolver(options);
7128
+ return new BaseOrientedBoxStyle({
7129
+ fill: (detection) => ({
7130
+ alpha: DEFAULT_FILL_ALPHA,
7131
+ color: getClassColor(detection),
7132
+ }),
7133
+ stroke: (detection) => ({
7134
+ alpha: 1,
7135
+ color: getClassColor(detection),
7136
+ width: DEFAULT_OUTLINE_WIDTH,
7137
+ }),
7138
+ });
7139
+ }
6870
7140
  function createDefaultPolygonStyle(options = {}) {
6871
7141
  const getClassColor = createClassColorResolver(options);
6872
7142
  return new BasePolygonStyle({
@@ -6896,6 +7166,15 @@ function createDefaultPolylineStyle(options = {}) {
6896
7166
  }),
6897
7167
  });
6898
7168
  }
7169
+ function createDefaultPercentageBarStyle(options = {}) {
7170
+ const getClassColor = createClassColorResolver(options);
7171
+ return new BasePercentageBarStyle({
7172
+ fill: (detection) => ({
7173
+ alpha: 1,
7174
+ color: getClassColor(detection),
7175
+ }),
7176
+ });
7177
+ }
6899
7178
  function createClassColorResolver(options) {
6900
7179
  return (detection) => resolveDefaultClassColor(detection, options.getClassColor);
6901
7180
  }
@@ -6921,6 +7200,8 @@ const annotationRendererKinds = [
6921
7200
  "mask",
6922
7201
  "maskHalo",
6923
7202
  "marker",
7203
+ "orientedBox",
7204
+ "percentageBar",
6924
7205
  "polygon",
6925
7206
  "polyline",
6926
7207
  "region",
@@ -6971,6 +7252,8 @@ const annotationRenderers = {
6971
7252
  mask: (options) => createAnnotationRenderer("mask", options),
6972
7253
  maskHalo: (options) => createAnnotationRenderer("maskHalo", options),
6973
7254
  marker: (options) => createAnnotationRenderer("marker", options),
7255
+ orientedBox: (options) => createAnnotationRenderer("orientedBox", options),
7256
+ percentageBar: (options) => createAnnotationRenderer("percentageBar", options),
6974
7257
  polygon: (options) => createAnnotationRenderer("polygon", options),
6975
7258
  polyline: (options) => createAnnotationRenderer("polyline", options),
6976
7259
  region: (options) => ({ kind: "region", ...options }),
@@ -7023,6 +7306,16 @@ const annotationRendererRegistry = {
7023
7306
  createCanonicalStyle: createDefaultMarkerStyle,
7024
7307
  styleField: "markerStyle",
7025
7308
  },
7309
+ orientedBox: {
7310
+ cardinality: "singleton",
7311
+ createCanonicalStyle: createDefaultOrientedBoxStyle,
7312
+ styleField: "orientedBoxStyle",
7313
+ },
7314
+ percentageBar: {
7315
+ cardinality: "singleton",
7316
+ createCanonicalStyle: createDefaultPercentageBarStyle,
7317
+ styleField: "percentageBarStyle",
7318
+ },
7026
7319
  polygon: {
7027
7320
  cardinality: "singleton",
7028
7321
  createCanonicalStyle: createDefaultPolygonStyle,
@@ -7066,6 +7359,8 @@ function resolveAnnotationRendererPresentation(presentation) {
7066
7359
  maskHaloStyle: null,
7067
7360
  maskStyle: null,
7068
7361
  markerStyle: null,
7362
+ orientedBoxStyle: null,
7363
+ percentageBarStyle: null,
7069
7364
  polygonStyle: null,
7070
7365
  polylineStyle: null,
7071
7366
  };
@@ -7137,6 +7432,12 @@ function createSourceAwarePresentation(globalPresentation = {}, sources, options
7137
7432
  markerStyle: shouldApplySourceStyle("markerStyle")
7138
7433
  ? new SourceAwareMarkerStyle(normalizeGlobalMarkerStyle(globalPresentation.markerStyle), sourcePresentations)
7139
7434
  : globalPresentation.markerStyle,
7435
+ orientedBoxStyle: shouldApplySourceStyle("orientedBoxStyle")
7436
+ ? new SourceAwareOrientedBoxStyle(globalPresentation.orientedBoxStyle ?? null, sourcePresentations)
7437
+ : globalPresentation.orientedBoxStyle,
7438
+ percentageBarStyle: shouldApplySourceStyle("percentageBarStyle")
7439
+ ? new SourceAwarePercentageBarStyle(normalizeGlobalPercentageBarStyle(globalPresentation.percentageBarStyle), sourcePresentations)
7440
+ : globalPresentation.percentageBarStyle,
7140
7441
  maskHaloStyle: shouldApplySourceStyle("maskHaloStyle")
7141
7442
  ? new SourceAwareMaskHaloStyle(normalizeGlobalMaskHaloStyle(globalPresentation.maskHaloStyle), sourcePresentations)
7142
7443
  : globalPresentation.maskHaloStyle,
@@ -7237,6 +7538,29 @@ class SourceAwareMarkerStyle {
7237
7538
  return style?.resolve(detection, context);
7238
7539
  }
7239
7540
  }
7541
+ class SourceAwareOrientedBoxStyle {
7542
+ globalStyle;
7543
+ sourcePresentations;
7544
+ constructor(globalStyle, sourcePresentations) {
7545
+ this.globalStyle = globalStyle;
7546
+ this.sourcePresentations = sourcePresentations;
7547
+ }
7548
+ resolve(detection, context) {
7549
+ return resolveSourceStyle(detection, this.globalStyle, this.sourcePresentations, "orientedBoxStyle")?.resolve(detection, context);
7550
+ }
7551
+ }
7552
+ class SourceAwarePercentageBarStyle {
7553
+ globalStyle;
7554
+ sourcePresentations;
7555
+ constructor(globalStyle, sourcePresentations) {
7556
+ this.globalStyle = globalStyle;
7557
+ this.sourcePresentations = sourcePresentations;
7558
+ }
7559
+ resolve(detection, context) {
7560
+ const style = resolveSourceStyle(detection, this.globalStyle, this.sourcePresentations, "percentageBarStyle");
7561
+ return style?.resolve(detection, context);
7562
+ }
7563
+ }
7240
7564
  class SourceAwarePolygonStyle {
7241
7565
  globalStyle;
7242
7566
  sourcePresentations;
@@ -7298,6 +7622,9 @@ function normalizeGlobalMaskHaloStyle(style) {
7298
7622
  function normalizeGlobalMarkerStyle(style) {
7299
7623
  return style === undefined ? new BaseMarkerStyle() : style;
7300
7624
  }
7625
+ function normalizeGlobalPercentageBarStyle(style) {
7626
+ return style === undefined ? new BasePercentageBarStyle() : style;
7627
+ }
7301
7628
  function normalizeGlobalPolygonStyle(style) {
7302
7629
  return style === undefined ? new BasePolygonStyle() : style;
7303
7630
  }
@@ -8039,5 +8366,5 @@ var MediaSessionActivityStatus;
8039
8366
  MediaSessionActivityStatus["Waiting"] = "waiting";
8040
8367
  })(MediaSessionActivityStatus || (MediaSessionActivityStatus = {}));
8041
8368
 
8042
- export { AnnotationFrameMutationKind, AnnotationGeometryKind, AnnotationGestureStateKind, AnnotationHandleKind, BaseBoxCornerStyle, BaseBoxStyle, BaseFocusStyle, BaseInteractionStyle, BaseKeypointStyle, BaseLabelStyle, BaseMarkerStyle, BaseMaskStyle, BasePolygonStyle, BasePolylineStyle, BoxShape, StrokeAlignment as BoxStrokeAlignment, DEFAULT_DETECTION_CLASS_STYLES, DEFAULT_DETECTION_COLOR_SEQUENCE, DetectionBufferStatus, DetectionFrameRetentionMode, DetectionFrameSelectionMode, DetectionInteractionState, DetectionMaskEncoding, DetectionMaskPayloadFormat, DetectionPickTarget, FocusTargetMode, KeypointMarkerShape, KeypointVisibility, LabelPlacement, LabelVisibilityMode, MAX_ID_MASK_PALETTE_ENTRIES, MAX_ID_MASK_STROKE_WIDTH, MarkerShape, MarkerSizeSpace, MaskRenderMode, MediaErrorKind, MediaInteractionMode, MediaRendererFit, MediaRendererPlaybackState, MediaSessionActivityKind, MediaSessionActivityStatus, MediaSessionMode, MediaSessionStatus, MediaSourceStatus, PlaybackGateReach, RegionRendererComposeMode, RegionRendererCoverageKind, RegionRendererMediaEffectKind, RegionRendererRegionKind, RegionRendererSizeSpace, RegionRendererSourceKind, SUPERVISION_ROBOFLOW_COLOR, ShapeInstructionKind, StrokeAlignment, TrackingGeometry, annotationRendererKinds, annotationRenderers, applyAnnotationHandleDrag, canReuseMaskStyleArtifacts, centerRectToTopLeftRect, computeDetectionMaskRect, computeMaskBounds, containsPoint, convertDetectionBoxToMask, convertDetectionBoxToPolygon, convertDetectionMaskToBox, convertDetectionMaskToPolygon, convertDetectionPolygonToBox, convertDetectionPolygonToMask, copySortedDetectionFrames, createAnnotationEditingEngine, createArrayDetectionFrameSource, createBufferedDetectionTimeline, createByteTrackTracker, createCBIoUTracker, createColdDetectionFrameSource, createCompositeDetectionFrameSource, createDefaultAnnotationPresentation, createDetectionPickKey, createEditableAnnotationFrameSession, createIdMaskFrame, createIdleDetectionBufferState, createMemoryColdDetectionFrameStore, createOCSortTracker, createProjectedDetectionFrameSource, createSortTracker, createSourceAwarePresentation, createViewportController, createWritableDetectionFrameSource, decodeCompressedRleCounts, decodeCompressedRleMask, decodeDetectionMaskPayload, deleteAnnotationVertex, detectMaskBorders, detectionFrameOverlapsRange, detectionPostProcessors, distanceToSegment, encodeBinaryMask, encodeBinaryMaskWithBounds, encodeCompressedRleCounts, encodeDetectionMaskPayload, extractDetectionMaskRectRuns, extractMaskContour, extractMaskRectRuns, filterDetectionFramesForRange, findClosestAnnotationSegment, followDetectionPickAcrossFrames, getAnnotationHandles, getBufferedDetectionTimelineFrameSnapshot, getDetectionRect, getPointsRect, haveSameDetectionPickIdentities, includeDefined, isDeflatedBase64DetectionMaskPayload, lightenColor, mediaToScreen, mergeDetectionMasks, mergeDetectionPolygonsByClass, normalizeDetectionClassName, offsetDetection, pickAnnotationHandle, pickDetectionAtPoint, pickDetectionByMaskId, pointInPolygon, polygonArea, polygonToRect, projectDetectionFrame, projectDetectionFrameForTracking, projectDetectionFrames, rasterizePolygonToMask, rasterizeRectToMask, rebaseDetectionPickToFrame, rectArea, rectToPolygon, resolveAnnotationRendererPresentation, resolveAnnotationRendererStyleFields, resolveAnnotationStyleState, resolveContrastTextColor, resolveDetectionClassColorStyle, resolveEllipseSegmentCount, resolveIdMaskPaletteId, resolveIdMaskStrokeTexels, resolveMarkerGeometry, resolveMaskStyleOpacity, resolveStyleValue, sampleEllipseArc, screenToMedia, selectDetectionFrame, topLeftRectToCenterRect, validateDetectionFrames, writeIdMaskPaletteEntry };
8369
+ export { AnnotationFrameMutationKind, AnnotationGeometryKind, AnnotationGestureStateKind, AnnotationHandleKind, BaseBoxCornerStyle, BaseBoxStyle, BaseFocusStyle, BaseInteractionStyle, BaseKeypointStyle, BaseLabelStyle, BaseMarkerStyle, BaseMaskStyle, BaseOrientedBoxStyle, BasePercentageBarStyle, BasePolygonStyle, BasePolylineStyle, BoxShape, StrokeAlignment as BoxStrokeAlignment, DEFAULT_DETECTION_CLASS_STYLES, DEFAULT_DETECTION_COLOR_SEQUENCE, DetectionBufferStatus, DetectionFrameRetentionMode, DetectionFrameSelectionMode, DetectionInteractionState, DetectionMaskEncoding, DetectionMaskPayloadFormat, DetectionPickTarget, FocusTargetMode, KeypointMarkerShape, KeypointVisibility, LabelPlacement, LabelVisibilityMode, MAX_ID_MASK_PALETTE_ENTRIES, MAX_ID_MASK_STROKE_WIDTH, MarkerShape, MarkerSizeSpace, MaskRenderMode, MediaErrorKind, MediaInteractionMode, MediaRendererFit, MediaRendererPlaybackState, MediaSessionActivityKind, MediaSessionActivityStatus, MediaSessionMode, MediaSessionStatus, MediaSourceStatus, PercentageBarPlacement, PlaybackGateReach, RegionRendererComposeMode, RegionRendererCoverageKind, RegionRendererMediaEffectKind, RegionRendererRegionKind, RegionRendererSizeSpace, RegionRendererSourceKind, SUPERVISION_ROBOFLOW_COLOR, ShapeInstructionKind, StrokeAlignment, TrackingGeometry, annotationRendererKinds, annotationRenderers, applyAnnotationHandleDrag, canReuseMaskStyleArtifacts, centerRectToTopLeftRect, computeDetectionMaskRect, computeMaskBounds, containsPoint, convertDetectionBoxToMask, convertDetectionBoxToPolygon, convertDetectionMaskToBox, convertDetectionMaskToPolygon, convertDetectionPolygonToBox, convertDetectionPolygonToMask, copySortedDetectionFrames, createAnnotationEditingEngine, createArrayDetectionFrameSource, createBufferedDetectionTimeline, createByteTrackTracker, createCBIoUTracker, createColdDetectionFrameSource, createCompositeDetectionFrameSource, createDefaultAnnotationPresentation, createDetectionPickKey, createEditableAnnotationFrameSession, createIdMaskFrame, createIdleDetectionBufferState, createMemoryColdDetectionFrameStore, createOCSortTracker, createProjectedDetectionFrameSource, createSortTracker, createSourceAwarePresentation, createViewportController, createWritableDetectionFrameSource, decodeCompressedRleCounts, decodeCompressedRleMask, decodeDetectionMaskPayload, deleteAnnotationVertex, detectMaskBorders, detectionFrameOverlapsRange, detectionPostProcessors, distanceToSegment, encodeBinaryMask, encodeBinaryMaskWithBounds, encodeCompressedRleCounts, encodeDetectionMaskPayload, extractDetectionMaskRectRuns, extractMaskContour, extractMaskRectRuns, filterDetectionFramesForRange, findClosestAnnotationSegment, followDetectionPickAcrossFrames, getAnnotationHandles, getBufferedDetectionTimelineFrameSnapshot, getDetectionRect, getPointsRect, haveSameDetectionPickIdentities, includeDefined, isDeflatedBase64DetectionMaskPayload, lightenColor, mediaToScreen, mergeDetectionMasks, mergeDetectionPolygonsByClass, normalizeDetectionClassName, offsetDetection, pickAnnotationHandle, pickDetectionAtPoint, pickDetectionByMaskId, pointInPolygon, polygonArea, polygonToRect, projectDetectionFrame, projectDetectionFrameForTracking, projectDetectionFrames, rasterizePolygonToMask, rasterizeRectToMask, rebaseDetectionPickToFrame, rectArea, rectToPolygon, resolveAnnotationRendererPresentation, resolveAnnotationRendererStyleFields, resolveAnnotationStyleState, resolveContrastTextColor, resolveDetectionClassColorStyle, resolveEllipseSegmentCount, resolveIdMaskPaletteId, resolveIdMaskStrokeTexels, resolveMarkerGeometry, resolveMaskStyleOpacity, resolveStyleValue, sampleEllipseArc, screenToMedia, selectDetectionFrame, topLeftRectToCenterRect, validateDetectionFrames, writeIdMaskPaletteEntry };
8043
8370
  //# sourceMappingURL=index.js.map