
    ^j                    &   d dl mZ d dlZd dlmZ d dlmZ d dlmZm	Z	 d dl
Z
d dlZd dlmZ d dlmZ d dlmZ  G d d	e      Z G d
 de      Zej*                  f	 	 	 	 	 	 	 d'dZej*                  f	 	 	 	 	 	 	 d(dZd)dZ	 	 	 	 	 	 	 	 d*dZd+dZd+dZ	 	 	 	 	 	 d,dZej*                  f	 	 	 	 	 	 	 d-dZej*                  f	 	 	 	 	 	 	 d.dZej*                  f	 	 	 	 	 	 	 d/dZej*                  df	 	 	 	 	 	 	 	 	 d0dZ dej*                  df	 	 	 	 	 	 	 	 	 	 	 d1dZ!	 	 	 	 d2dZ"	 	 	 	 	 	 	 	 d3dZ#dej*                  f	 	 	 	 	 	 	 d4dZ$dej*                  f	 	 	 	 	 	 	 	 	 d5dZ%ddej*                  f	 	 	 	 	 	 	 	 	 	 	 d6dZ&	 	 	 	 	 	 	 	 d7d Z'	 	 	 	 	 	 d8d!Z(dej*                  f	 	 	 	 	 	 	 d9d"Z)dej*                  f	 	 	 	 	 	 	 d9d#Z*dej*                  f	 	 	 	 	 	 	 	 	 d:d$Z+dej*                  f	 	 	 	 	 	 	 	 	 d;d%Z,dej*                  f	 	 	 	 	 	 	 	 	 d;d&Z-y)<    )annotationsN)Callable)Enum)Anycast)CompactMask)resize_masksc                  @    e Zd ZdZdZdZdZedd       Zed	d       Z	y)
OverlapFiltera;  
    Enum specifying the strategy for filtering overlapping detections.

    Attributes:
        NONE: Do not filter detections based on overlap.
        NON_MAX_SUPPRESSION: Filter detections using non-max suppression. This means,
            detections that overlap by more than a set threshold will be discarded,
            except for the one with the highest confidence.
        NON_MAX_MERGE: Merge detections with non-max merging. This means,
            detections that overlap by more than a set threshold will be merged
            into a single detection.
    nonenon_max_suppressionnon_max_mergec                .    t        t        d |             S )Nc                    | j                   S Nvaluemembers    r/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/detection/utils/iou_and_nms.py<lambda>z$OverlapFilter.list.<locals>.<lambda>$   
    v||     listmapclss    r   r   zOverlapFilter.list"       C3S9::r   c                   t        ||       r|S t        |t              r|j                         }	  | |      S t        dt        |       d| j                   d      # t        $ r  t        d| d| j	                                w xY wNzInvalid value: z. Must be one of zInvalid value type: z. Must be an instance of z or str.)
isinstancestrlower
ValueErrorr   type__name__r   r   s     r   
from_valuezOverlapFilter.from_value&       eS!LeS!KKMEY5z! "4;-/H||nH&
 	
  Y ?5'9J388:,!WXXY   A )BNreturnz	list[str])r   zOverlapFilter | strr-   r   )
r'   
__module____qualname____doc__NONENON_MAX_SUPPRESSIONNON_MAX_MERGEclassmethodr   r)    r   r   r   r      s?     D/#M; ; 
 
r   r   c                  <    e Zd ZdZdZdZedd       Zedd       Zy)	OverlapMetrica  
    Enum specifying the metric for measuring overlap between detections.

    Attributes:
        IOU: Intersection over Union. A region-overlap metric that compares
            two shapes (usually bounding boxes or masks) by normalising the
            shared area with the area of their union.
        IOS: Intersection over Smaller, a region-overlap metric that compares
            two shapes (usually bounding boxes or masks) by normalising the
            shared area with the smaller of the two shapes.
    IOUIOSc                .    t        t        d |             S )Nc                    | j                   S r   r   r   s    r   r   z$OverlapMetric.list.<locals>.<lambda>H   r   r   r   r   s    r   r   zOverlapMetric.listF   r   r   c                   t        ||       r|S t        |t              r|j                         }	  | |      S t        dt        |       d| j                   d      # t        $ r  t        d| d| j	                                w xY wr!   )r"   r#   upperr%   r   r&   r'   r(   s     r   r)   zOverlapMetric.from_valueJ   r*   r+   Nr,   )r   OverlapMetric | strr-   r7   )	r'   r.   r/   r0   r8   r9   r4   r   r)   r5   r   r   r7   r7   6   s9    
 C
C; ; 
 
r   r7   c                $   t         j                  |      }t        j                  |       \  }}}}t        j                  |      \  }}}	}
t	        ||      }t	        ||      }t        ||	      }t        ||
      }t	        d||z
        }t	        d||z
        }||z  }||z
  ||z
  z  }|	|z
  |
|z
  z  }|t         j                  k(  r	||z   |z
  }n/|t         j                  k(  rt        ||      }nt        d| d      |dk  ryt        ||z        S )a.  
    Compute overlap metric between two bounding boxes.

    Supports standard IOU (intersection-over-union) and IOS
    (intersection-over-smaller-area) metrics. Returns the overlap value in range
    `[0, 1]`.

    Args:
        box_true: Ground truth box in format
          `(x_min, y_min, x_max, y_max)`.
        box_detection: Detected box in format
          `(x_min, y_min, x_max, y_max)`.
        overlap_metric: Overlap type.
          Use `OverlapMetric.IOU` for IOU or
          `OverlapMetric.IOS` for IOS. Defaults to `OverlapMetric.IOU`.

    Returns:
        Overlap value between boxes in `[0, 1]`.

    Raises:
        ValueError: If `overlap_metric` is not IOU or IOS.

    Examples:
        ```pycon
        >>> import supervision as sv
        >>> box_true = [100, 100, 200, 200]
        >>> box_detection = [150, 150, 250, 250]
        >>> sv.box_iou(box_true, box_detection, overlap_metric=sv.OverlapMetric.IOU)
        0.142857...
        >>> sv.box_iou(box_true, box_detection, overlap_metric=sv.OverlapMetric.IOS)
        0.25

        ```
            overlap_metric 5 is not supported, only 'IOU' and 'IOS' are supported)
r7   r)   nparraymaxminr8   r9   r%   float)box_truebox_detectionoverlap_metric
x_min_true
y_min_true
x_max_true
y_max_true	x_min_det	y_min_det	x_max_det	y_max_detx_min_intery_min_interx_max_intery_max_interinter_winter_h
area_inter	area_truearea_det	area_norms                        r   box_iour]   Z   s:   N #--n=N57XXh5G2J
J
13-1H.Iy)Yj),Kj),Kj),Kj),K#{[01G#{[01G7"Jj(Z*-DEII%)i*?@H***(:5		=,,	,	8,	n- .1 1
 	

 Ci'((r   c                   t         j                  |      }| j                  \  }}}}|j                  \  }}}	}
| j                  d   |j                  d   }}|dk(  s|dk(  rPt	        t
        j                  t        j                     t        j                  ||ft        j                              S t        j                  ||ft        j                        }t        j                  |      }t        j                  |      }t        j                  |      }t        j                  |dddf   |dddf   |       t        j                  |dddf   |	dddf   |       t        j                  |dddf   |dddf   |       t        j                  |dddf   |
dddf   |       t        j                  |||       t        j                  |||       t        j                  |dd|       t        j                  |dd|       ||z  }||z
  ||z
  z  }|	|z
  |
|z
  z  }|t         j                  k(  r|dddf   |dddf   z   |z
  }nG|t         j                   k(  r%t        j                  |dddf   |dddf         }nt#        d| d      t        j$                  |t        j                        }t        j&                  ||||dkD         |S )	a/  
    Compute pairwise overlap scores between batches of bounding boxes.

    Supports standard IOU (intersection-over-union) and IOS
    (intersection-over-smaller-area) metrics for all `boxes_true` and
    `boxes_detection` pairs. Returns a matrix of overlap values in range
    `[0, 1]`, matching each box from the first batch to each from the second.

    Args:
        boxes_true: Array of reference boxes in
            shape `(N, 4)` as `(x_min, y_min, x_max, y_max)`.
        boxes_detection: Array of detected boxes in
            shape `(M, 4)` as `(x_min, y_min, x_max, y_max)`.
        overlap_metric: Overlap type.
            Use `OverlapMetric.IOU` for intersection-over-union,
            `OverlapMetric.IOS` for intersection-over-smaller-area.
            Defaults to `OverlapMetric.IOU`.

    Returns:
        Overlap matrix of shape `(N, M)`, where entry
            `[i, j]` is the overlap between `boxes_true[i]` and
            `boxes_detection[j]`.

    Raises:
        ValueError: If `overlap_metric` is not IOU or IOS.

    Examples:
        ```pycon
        >>> import numpy as np
        >>> import supervision as sv
        >>> boxes_true = np.array([
        ...     [100, 100, 200, 200],
        ...     [300, 300, 400, 400]
        ... ])
        >>> boxes_detection = np.array([
        ...     [150, 150, 250, 250],
        ...     [320, 320, 420, 420]
        ... ])
        >>> sv.box_iou_batch(
        ...     boxes_true, boxes_detection, overlap_metric=sv.OverlapMetric.IOU
        ... )
        array([[0.14285..., 0.        ],
               [0.        , 0.47058...]], dtype=float32)
        >>> sv.box_iou_batch(
        ...     boxes_true, boxes_detection, overlap_metric=sv.OverlapMetric.IOS
        ... )
        array([[0.25, 0.  ],
               [0.  , 0.64]], dtype=float32)

        ```
    r   dtypeN)outr@   rA   rB   ra   where)r7   r)   Tshaper   nptNDArrayrC   float32empty
empty_likemaximumminimumsubtractclipr8   r9   r%   
zeros_likedivide)
boxes_trueboxes_detectionrJ   rK   rL   rM   rN   rO   rP   rQ   rR   
count_true	count_detrS   rU   rT   rV   rY   rZ   r[   r\   ra   s                         r   box_iou_batchru      s   p #--n=N5?\\2J
J
1@1B1B.Iy)Y&,,Q/1F1Fq1I	JQ)q.KK

#RXXz9.ERZZ%X
 	
 ((J	2"**EK--,K--,K--,KJJz!T'"IdAg$6KHJJz!T'"IdAg$6KHJJz!T'"IdAg$6KHJJz!T'"IdAg$6KH KK[k:KK[k:GGKd4GGKd4{*Jj(Z*-DEII%)i*?@H***ag&$')::ZG		=,,	,JJyD18D!G3DE	n- .1 1
 	

 $&==2::#NCIIj)IMBJr   c                &   t        j                  d      }| d   | d   | d   | d   z   | d   | d   z   f\  }}}}|d   |d   |d   |d   z   |d   |d   z   f\  }}	}
}t        ||      }t        ||
      }t        ||	      }t        ||      }t        ||z
  d      t        ||z
  d      z  }t        |
|z
  d      t        ||	z
  d      z  }t        ||z
  d      t        ||z
  d      z  }|rt	        |||z   z        S t	        |||z   |z
  |z   z        S )ax  
    Calculate the Jaccard index (intersection over union) between two bounding boxes.
    If a gt object is marked as "iscrowd", a dt is allowed to match any subregion
    of the gt. Choosing gt'=intersect(dt,gt). Since by definition union(gt',dt)=dt, computing
    iou(gt,dt,iscrowd) = iou(gt',dt) = area(intersect(gt,dt)) / area(dt)

    Args:
        box_a: Box coordinates in the format [x, y, width, height].
        box_b: Box coordinates in the format [x, y, width, height].
        iscrowd: Flag indicating if the second box is a crowd region or not.

    Returns:
        Jaccard index between the two bounding boxes.
       r         r@   )rC   spacingrE   rF   rG   )box_abox_bis_crowdEPSxayax2ay2axbybx2by2bxix2iyiy2iAaAbAis                      r   _jaccardr     sH     **Q-CQxq58eAh+>a5QR8@SSBCQxq58eAh+>a5QR8@SSBC 
RB
c3-C	RB
c3-C 
S2Xs	c#(C0	0B	S2Xs	c#(C0	0B	S2Xs	c#(C0	0BR28_%%rBw|c)*++r   c                   t        |      t        |       k(  sJ d       t        |      dk(  st        |       dk(  r>t        t        j                  t        j
                     t	        j                  g             S t	        j                  t        |      t        |       ft        j
                        }t        |       D ]-  \  }}t        |      D ]  \  }}t        ||||         |||f<    / |S )a  
    Calculate the intersection over union (IoU) between detection bounding boxes (dt)
    and ground-truth bounding boxes (gt).
    Reference: https://github.com/rafaelpadilla/review_object_detection_metrics

    Args:
        boxes_true: List of ground-truth bounding boxes in the
            format [x, y, width, height].
        boxes_detection: List of detection bounding boxes in the
            format [x, y, width, height].
        is_crowd: List indicating if each ground-truth bounding box
            is a crowd region or not.

    Returns:
        Array of IoU values of shape (len(dt), len(gt)).

    Examples:
        ```pycon
        >>> import numpy as np
        >>> import supervision as sv
        >>> boxes_true = [
        ...     [10, 20, 30, 40],  # x, y, w, h
        ...     [15, 25, 35, 45]
        ... ]
        >>> boxes_detection = [
        ...     [12, 22, 28, 38],
        ...     [16, 26, 36, 46]
        ... ]
        >>> is_crowd = [False, False]
        >>> ious = sv.box_iou_batch_with_jaccard(
        ...     boxes_true=boxes_true,
        ...     boxes_detection=boxes_detection,
        ...     is_crowd=is_crowd
        ... )
        >>> ious  # doctest: +ELLIPSIS
        array([[0.886..., 0.496...],
               [0.4  ..., 0.862...]])

        ```
    z4`is_crowd` must have the same length as `boxes_true`r   r_   )
lenr   rf   rg   rC   float64rD   zeros	enumerater   )rq   rr   r}   iousgt_idxgt_boxdet_idxdet_boxs           r   box_iou_batch_with_jaccardr   0  s    Z x=C
O+ >+ ?q C
Oq$8CKK

+RXXb\::$&HH	_	s:/rzz%D $J/ P )/ : 	PGW$,Wfhv>N$OD&!	PP Kr   c           	     B   | dddddf   }| dddddf   }|t        j                  |dd      z  t        j                  |dd      |z  z
  }t        t        j                  t         j
                     dt        j                  |j                  d            z        S )zCompute the area of each oriented-box polygon using the shoelace formula.

    Args:
        polygons: ``(N, 4, 2)`` array of polygon corners.

    Returns:
        ``(N,)`` array of polygon areas.
    Nr   rw   axis      ?)rC   rollr   rf   rg   floatingabssum)polygonsxycrosss       r   _polygon_areasr   k  s     	AqAAqA2A&&BQ)?!)CCEBKK(#uyyay7H0I*IJJr   c                    | dddddf   }| dddddf   }t        j                  |j                  d      |j                  d      |j                  d      |j                  d      gd      S )zCompute the axis-aligned bounding envelope of each oriented box.

    Args:
        polygons: ``(N, 4, 2)`` array of polygon corners.

    Returns:
        ``(N, 4)`` array of ``(x_min, y_min, x_max, y_max)`` envelopes.
    Nr   rw   r   )rC   stackrF   rE   )r   xsyss      r   _aabb_envelopesr   z  sk     
!Q'	B	!Q'	B88	QQQQHq r   c                   | dddddf   }|dddddf   }t        j                  |d   |d         t        j                  |d   |d         kD  t        j                  |d   |d         t        j                  |d   |d         kD  z  }t        t        t
        j                  t         j                     t
        j                  t         j                     f   t        j                  |            S )a*  Return index pairs ``(i, j)`` whose axis-aligned envelopes overlap.

    Uses a fused boolean evaluation to halve peak transient memory compared to
    named-intermediate form (4 separate NxM float64 arrays vs 1 boolean array).

    Note:
        This gate is a correctness guarantee, not an approximation: if two
        axis-aligned bounding boxes do not overlap, the convex polygons they
        contain cannot overlap either.

    Args:
        envelopes_true: ``(N, 4)`` array of ``(x_min, y_min, x_max, y_max)``
            envelopes for the ground-truth boxes.
        envelopes_detection: ``(M, 4)`` array of ``(x_min, y_min, x_max, y_max)``
            envelopes for the detection boxes.

    Returns:
        A pair of 1-D index arrays ``(rows, cols)`` identifying the overlapping
        pairs.
    N).rx   ).r   ).ry   ).rw   )	rC   rl   rk   r   tuplerf   rg   intpnonzero)envelopes_trueenvelopes_detectionetedoverlaps        r   _overlapping_envelope_pairsr     s    0 
4
	#B	T1aZ	(B


2f:r&z*RZZ6
BvJ-OO	BvJ6
	+bjjFRZ.P	PRG ckk"''*CKK,@@A2::gCVWWr   c                V   d| fd|ffD ]  \  }}|j                   dk(  r.|j                  dd dk7  rt        d| d|j                   d	      |j                   d
k(  r.|j                  d   dk7  rt        d| d|j                   d      |j                   dvst        d| d|j                   d       |t        j                  k(  rd}n%|t        j
                  k(  rd}nt        d| d      | |u }| j                  ddd
      j                  t        j                        } |j                  ddd
      j                  t        j                        }t        |       t        |      }}|dk(  s|dk(  r't        j                  ||ft        j                        S t        |       }	t        |      }
t        |       }|r|n
t        |      }t        ||      \  }}|r||k  }||   ||   }}| D cg c]!  }|j                  t        j                        # }}|D cg c]!  }|j                  t        j                        # }}t        j                  ||ft        j                        }t!        ||      D ]h  \  }}t#        j$                  ||   ||         \  }}|dk  r+|r|	|   |
|   z   |z
  nt'        |	|   |
|         }|dkD  sS||z  }||||f<   |sb||||f<   j t)        t*        j,                  t        j.                     t        j0                  |dd            S c c}w c c}w )u  
    Compute pairwise overlap scores between two sets of oriented bounding boxes
    using the configured `overlap_metric`.

    Overlap areas are computed exactly via convex-polygon intersection, gated by
    a cheap axis-aligned envelope pre-filter — no rasterization is involved, so
    the result is exact (free of pixel-quantization error) and independent of the
    coordinate magnitudes.

    `boxes_true` and `boxes_detection` are expected to be in
    `((x1, y1), (x2, y2), (x3, y3), (x4, y4))` format.

    Note:
        Inputs must be **convex** quads with finite coordinates. Self-intersecting
        or non-convex polygons produce undefined results via
        ``cv2.intersectConvexConvex``. NaN or Inf coordinates propagate silently
        as ``0.0`` — validate inputs before calling if needed.

        When ``boxes_true is boxes_detection`` (the same Python object, not just
        equal values), the function computes only the upper triangle of the
        matrix and mirrors it. This optimization is used automatically by the
        NMS/NMM callers that pass the same array twice. A defensive ``.copy()``
        at the call site would disable the optimization silently — see the
        NMS caller comment for context.

    Args:
        boxes_true: A `np.ndarray` representing ground-truth boxes.
            `shape = (N, 4, 2)` where `N` is number of true objects.
            Last axis convention: `[..., 0]` = x-coordinates,
            `[..., 1]` = y-coordinates.
        boxes_detection: A `np.ndarray` representing detection boxes.
            `shape = (M, 4, 2)` where `M` is number of detected objects.
            Last axis convention: `[..., 0]` = x-coordinates,
            `[..., 1]` = y-coordinates.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of oriented boxes (e.g., IoU, IoS).

    Returns:
        Overlap matrix of shape `(N, M)`, where entry `[i, j]` is the overlap
        score between `boxes_true[i]` and `boxes_detection[j]`, in the range
        `[0, 1]` under the configured :attr:`overlap_metric`.

    Raises:
        ValueError: If ``boxes_true`` or ``boxes_detection`` is 3-D with inner
            dimensions other than ``(4, 2)``.
        ValueError: If ``boxes_true`` or ``boxes_detection`` is 2-D with a
            column count other than 8.
        ValueError: If ``boxes_true`` or ``boxes_detection`` is not 2-D or 3-D.
        ValueError: If ``overlap_metric`` is not
            :attr:`~supervision.config.OverlapMetric.IOU` or
            :attr:`~supervision.config.OverlapMetric.IOS`.

    Examples:
        >>> import numpy as np
        >>> import supervision as sv
        >>> a = np.array([[[0, 0], [2, 0], [2, 2], [0, 2]]], dtype=np.float32)
        >>> b = np.array([[[1, 0], [3, 0], [3, 2], [1, 2]]], dtype=np.float32)
        >>> sv.oriented_box_iou_batch(a, b)  # doctest: +ELLIPSIS
        array([[0.333...]])
    rq   rr   ry   rw   N   rx   `` has shape V   ; expected (N, 4, 2) — each box must have exactly 4 corners with (x, y) coordinates.rx      F; expected (N, 8) for flat YOLO format or (N, 4, 2) for corner format.rx   ry   1` must be 2-D (N, 8) or 3-D (N, 4, 2), got shape .TFrA   rB   r   r   r   r_   r@   g      ?)ndimre   r%   r7   r8   r9   reshapeastyperC   r   r   r   r   r   r   rh   zipcv2intersectConvexConvexrF   r   rf   rg   r   rn   )rq   rr   rJ   namearrnormalize_by_unionis_self_comparisonnm
areas_trueareas_detectionr   r   rowscolsr=   boxpolygons_truepolygons_detectionr   ijintersection_denominatorscores                             r   oriented_box_iou_batchr     sR   D $Z03Do2VW 	c88q=SYYqr]f4D6cii[ 1T U  XX]syy|q0D6cii[ 1> ?  XXV#D6J399+UVW   ***!	=,,	,"n- .1 1
 	
 $6##B1-44RZZ@J%--b!Q7>>rzzJOz?C0qAAvaxxAbjj11
+J$_5O$Z0N,//2R  -^=PQJD$%[$u+d7ABSZZ

+BMB<KLS#**RZZ0LL$&HHaV2::$FDD$ #133!03
a 1 " qMOA..=Z]OA$67 	
 ? ;.EDAJ!"QT
#, BKK("''$S*ABB5 CLs   /&L!&L&c                   t        |       }t        |      }t        j                  ||ft              }|dk(  s|dk(  r|S | j                  }|j                  }| j
                  j                  t        j                        }|dddf   }	|dddf   }
|dddf   }|dddf   }|j
                  j                  t        j                        }|dddf   }|dddf   }|dddf   }|dddf   }t        j                  |	dddf   |dddf         }t        j                  |
dddf   |dddf         }t        j                  |dddf   |dddf         }t        j                  |dddf   |dddf         }||k  ||k  z  }i }i }t        j                  |      D ]  }t        |d         t        |d         }}||vr| j                  |      ||<   ||vr|j                  |      ||<   t        |||f         }t        |||f         }t        |||f         }t        |||f         }t        |	|         t        |
|         }!} ||   ||!z
  ||!z
  dz   || z
  || z
  dz   f   }"t        ||         t        ||         }$}#||   ||$z
  ||$z
  dz   ||#z
  ||#z
  dz   f   }%t        t        j                  |"|%      j                               }&t        ||         }'t        ||         }(|t        j                   k(  r|'|(z   |&z
  })|)dkD  r|&|)z  nd|||f<   |t        j"                  k(  rt%        |'|(      }*|*dkD  r|&|*z  nd|||f<   t'        d| d	       |S )
u.  Compute pairwise overlap between two :class:`CompactMask` collections.

    Avoids materialising full ``(N, H, W)`` arrays by:

    1. Vectorised bounding-box pre-filter — pairs whose boxes do not overlap
       get IoU = 0 without any mask decoding.
    2. Sub-crop decoding — for overlapping pairs, only the intersection region
       of each crop is decoded and compared.
    3. Crop caching — each individual crop is decoded at most once even when it
       participates in many pairs.

    The result is numerically identical to running the dense
    :func:`mask_iou_batch` on ``np.asarray(masks_true)`` /
    ``np.asarray(masks_detection)``.

    Args:
        masks_true: :class:`~supervision.detection.compact_mask.CompactMask`
            holding the ground-truth masks.
        masks_detection: :class:`~supervision.detection.compact_mask.CompactMask`
            holding the detection masks.
        overlap_metric: :class:`OverlapMetric` — ``IOU`` or ``IOS``.

    Returns:
        Float array of shape ``(N1, N2)`` with pairwise overlap values.
    r_   r   Nrw   rx   ry   r@   rA   rB   )r   rC   r   rG   area	bbox_xyxyr   int32rk   rl   argwhereintcroplogical_andr   r7   r8   r9   rF   r%   )+
masks_truemasks_detectionrJ   n1n2resultareas_aareas_bbboxes_ax1ay1ar   r   bboxes_bx1by1br   r   ix1iy1ix2iy2bbox_overlapcrops_acrops_bidx_pairidx_aidx_blx1ly1lx2ly2ox_aoy_asub_aox_boy_bsub_binterarea_a_iarea_b_junionsmalls+                                              r   compact_mask_iou_batchr
  9  s   < *oB/"B')xxR'FF	Qw"'%/__G%4%9%9G '1&:&:&A&A"((&KH!)!Q$C!)!Q$C!)!Q$C!)!Q$C&5&?&?&F&Frxx&PH!)!Q$C!)!Q$C!)!Q$C!)!Q$C "$C4L#dAg,!GC!#C4L#dAg,!GC!#C4L#dAg,!GC!#C4L#dAg,!GC+.#:#**EL 13G02GKK- !8A;'Xa[)9u'__U3GEN,11%8GEN#eUl#$#eUl#$#eUl#$#eUl#$U_c#e*odsTzC$JN:C$JtVW<WWXU_c#e*odsTzC$JN:C$JtVW<WWXBNN5%04467wu~&wu~&]...x'%/E49AI55=3F5%< }000(+E49AI55=3F5%< !.!1 25 5 =!F Mr   c                >   t        t        j                  | j                  dd             }|dk  rt        j                  nt        j
                  }| j                  | j                  d   |      j                  |d      }|j                  |j                  d   |      j                  |d      }t        j                  ddd      5  ||j                  z  }ddd       |j                  d	      }|j                  d	      }	|t        j                  k(  rE|dddf   |	z   z
  }
t        j                  ||
t        j                  |t        
      |
dk7        }nu|t        j                   k(  rSt        j"                  |dddf   |	      }t        j                  |t        j                  |t        
      |dk7        }nt%        d| d      t        j&                  |      }t)        t*        j,                  t        j.                     |      S # 1 sw Y   ;xY w)a  
    Internal function.
    Compute Intersection over Union (IoU) of two sets of masks -
        `masks_true` and `masks_detection`.

    Args:
        masks_true: 3D `np.ndarray` representing ground-truth masks.
        masks_detection: 3D `np.ndarray` representing detection masks.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of masks (e.g., IoU, IoS).

    Returns:
        Pairwise IoU of masks from `masks_true` and `masks_detection`.
    rw   N   r   F)copyignore)rp   overinvalidr   r_   rb   rA   rB   )r   rC   prodre   rh   r   r   r   errstaterd   r   r7   r8   rp   ro   rG   r9   rl   r%   
nan_to_numr   rf   rg   r   )r   r   rJ   pixelscount_dtype	true_flatdetection_flatintersection_areamasks_true_areamasks_detection_area
union_arear   
small_areas                r   _mask_iou_batch_splitr    s   . ))!"-./F &%"**RZZK"":#3#3A#6?FF% G I %,,_-B-B1-EvNUU% V N 
H8X	F X;D~GWGW;WX  mmm+O)--1-5***$QW-0DDGXX
yy/u=/	
 
=,,	,ZZ4 8:NO
yy/u=/	
 n- .1 1
 	

 ==DBKK($//=X Xs   	HHi   c           	        t        | t              rt        |t              rt        | ||      S t        | t              rt        j                  |       } t        |t              rt        j                  |      }| j
                  dk7  s|j
                  dk7  r&t        d| j
                   d|j
                   d      | j                  dd |j                  dd k7  r,t        d| j                  dd  d|j                  dd  d      | j                  d	   d	k(  s|j                  d	   d	k(  rt        | ||      S | j                  d   | j                  d
   z  }|dk  rdnd}|dz  dz  }|j                  d	   |z  |z  }||z  d|j                  d	   z  dz  z   }||cxkD  rd	kD  r,n n)t        j                  d|dz  dz   d| dt        d
       || j                  d	   |z  z   |k  rt        | ||      S g }	t        ||z
  |z  d      }
t        d	| j                  d	   |
      D ]$  }|	j                  t        | |||
z    ||             & t        t         j"                  t        j$                     t        j&                  |	            S )a  
    Compute Intersection over Union (IoU) of two sets of masks -
        `masks_true` and `masks_detection`.

    Accepts both dense ``(N, H, W)`` boolean arrays and
    :class:`~supervision.detection.compact_mask.CompactMask` objects.
    When both inputs are :class:`~supervision.detection.compact_mask.CompactMask`,
    the computation uses :func:`compact_mask_iou_batch` to avoid materialising
    full ``(N, H, W)`` arrays.

    Args:
        masks_true: 3D `np.ndarray` representing ground-truth masks.
        masks_detection: 3D `np.ndarray` representing detection masks.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of masks (e.g., IoU, IoS).
        memory_limit: Memory limit in MB, default is 1024 * 5 MB (5GB).
            Controls chunking of ``masks_true`` so that flattened detection
            masks plus each chunk's buffers stay within this limit. A
            ``UserWarning`` is raised when ``masks_detection`` alone
            exceeds the limit, as chunking cannot reduce peak memory
            below that floor. Ignored when both inputs are
            :class:`~supervision.detection.compact_mask.CompactMask`.

    Returns:
        Pairwise IoU of masks from `masks_true` and `masks_detection`.

    Raises:
        ValueError: If ``masks_true`` or ``masks_detection`` are not 3D
            ``(N, H, W)`` arrays, or if they do not share the same
            spatial dimensions ``(H, W)``.
    ry   z>masks_true and masks_detection must be 3D (N, H, W); got ndim=z
 and ndim=r   rw   Nz?masks_true and masks_detection must share the same (H, W); got  and r   rx   r  r   r   i   zdetection masks (z MB) exceed memory_limit (z: MB); chunking cannot reduce peak memory below this floor.)
stacklevel)r"   r   r
  rC   asarrayr   r%   re   r  warningswarnUserWarningrE   rangeappendr   rf   rg   r   vstack)r   r   rJ   memory_limitr  itemsizelimit_bytesdetection_bytesper_true_rowr   stepchunk_starts               r   mask_iou_batchr/    s   L *k*z/;/W%j/>RR *k*ZZ
+
/;/**_5!33q8OO$J/C/C.DAG
 	
 44QR88M#$E/*?*?*C)DAG
 	

 a?#8#8#;q#@$Z.QQ a :#3#3A#66FeOqH%,K%++A.7(BOH$q?+@+@+C'Ca'GGL(q(4 74 ?@ A)N +'' 	
 ))!,|;;{J$Z.QQDo-,>BDQ
 0 0 3T: 
!;t);<	

 BKK("))D/::r   r   i  c                r   d|cxk  rdk  sn J d| d       | j                   \  }}|dk(  r(t        j                  | t        j                  |      f   } | dddf   j	                         ddd   }| |   } ||   }t        |||      }| dddf   }	t        j                  |t        	      }
t        |      D ]B  }|
|   s	||   |kD  |	|   |	k(  z  }t        j                  ||dz   d d
|
|dz   d       |
|dz   d D t        t        j                  t        j                     |
|j	                                  S )u  
    Perform Non-Maximum Suppression (NMS) on segmentation predictions.

    IoU is computed exactly on the full-resolution masks for both dense and
    :class:`~supervision.detection.compact_mask.CompactMask` inputs.  The
    ``mask_dimension`` parameter is kept for backward compatibility but is no
    longer used — dense masks are **not** resized before IoU computation.

    Args:
        predictions: A 2D array of object detection predictions in
            the format of `(x_min, y_min, x_max, y_max, score)`
            or `(x_min, y_min, x_max, y_max, score, class)`. Shape: `(N, 5)` or
            `(N, 6)`, where N is the number of predictions.
        masks: A 3D array of binary masks corresponding to the predictions.
            Shape: `(N, H, W)`, where N is the number of predictions, and H, W are the
            dimensions of each mask.
        iou_threshold: The intersection-over-union threshold
            to use for non-maximum suppression.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of masks (e.g., IoU, IoS).
        mask_dimension: Deprecated, no longer used. Kept for backward
            compatibility.

    Returns:
        A boolean array indicating which predictions to keep after
            non-maximum suppression.

    Raises:
        AssertionError: If `iou_threshold` is not within the closed
            range from `0` to `1`.
    r   rw   BValue of `iou_threshold` must be in the closed range from 0 to 1,  given.   Nr   r   r_   F)re   rC   c_r   argsortr/  onesboolr%  rc   r   rf   rg   bool_)predictionsmasksiou_thresholdrJ   mask_dimensionr   columns
sort_indexr   
categorieskeeprow_idx	conditions                r   mask_non_max_suppressionrC  @  s]   L "" L/	""  %%MD'!|eeK$78QT"**,TrT2Jj)K*E%7DQT"J774t$D; =g67#z1I #%(('A+-(%gkm1D#D1 BHH%tJ,>,>,@'ABBr   c                    | j                   \  }}|dk(  r(t        j                  | t        j                  |      f   } t        j                  | dddf   j                               }| |   } | dddf   }|| |fS )zAdd an agnostic class column when missing, sort by descending score.

    Returns the score-descending sort index, the reordered predictions, and the
    category vector for the loop callers to consume.
    r3  Nr   )re   rC   r4  r   flipr5  )r9  r   r=  r>  r?  s        r   _prepare_predictions_for_nmsrF    sz      %%MD'!|eeK$78QT*2245Jj)KQT"J{J..r   c                    t        |       }| t        j                  |      z
  } t        j                  |t              }t        t        | |            D ]  \  }\  }}||   s||kD  ||k(  z  }|| z  }! |S )a  Greedy NMS suppression loop given a precomputed pairwise IoU matrix.

    Assumes `ious` is square with row/column order matching `categories`.
    Detections sharing a category whose IoU exceeds `iou_threshold` are dropped
    in favour of the higher-confidence entry.
    r_   )r   rC   eyer6  r7  r   r   )	r   r?  r;  r   r@  indexioucategoryrB  s	            r   _nms_loop_from_iou_matrixrL    s     t9D"&&,D"$''$d";D"+Cj,A"B !XE{=(Z8-CD	yj 	!
 Kr   c                    d|cxk  rdk  sn J d| d       t        |       \  }} }t        | ddddf   | ddddf   |      }t        |||      }t        t        j
                  t        j                     ||j                                  S )a  
    Perform Non-Maximum Suppression (NMS) on object detection predictions.

    Args:
        predictions: An array of object detection predictions in
            the format of `(x_min, y_min, x_max, y_max, score)`
            or `(x_min, y_min, x_max, y_max, score, class)`.
        iou_threshold: The intersection-over-union threshold
            to use for non-maximum suppression.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of boxes (e.g., IoU, IoS).

    Returns:
        A boolean array indicating which predictions to keep after
            non-maximum suppression.

    Raises:
        AssertionError: If `iou_threshold` is not within the
            closed range from `0` to `1`.
    r   rw   r1  r2  Nr   )	rF  ru   rL  r   rf   rg   rC   r8  r5  )r9  r;  rJ   r>  r?  r   r@  s          r   box_non_max_suppressionrN    s    2 "" L/	"" +G{*S'JZQU+[BQB-?PD$T:}EDBHH%tJ,>,>,@'ABBr   c                   g }| dddf   }|j                         }t        |      dkD  r*t        |d         }|dd }t        |      dk(  r|j                  |g       	 |S ||   d   }|g}	t        |      dkD  rt	        ||   ||      }
|
j                         |k\  }|j                         sn||   }t        j                  j                  t        j                  ||   |g      dd      }|	j                  t        j                  |      j                                ||    }t        |      dkD  r|j                  |	       t        |      dkD  r*|S )a  
    Apply greedy version of non-maximum merging to avoid detecting too many

    Args:
        predictions: An array of shape `(n, 5)` containing
            the bounding boxes coordinates in format `[x1, y1, x2, y2]`
            and the confidence scores.
        masks: A 3D array of binary masks corresponding to
            the predictions.
        iou_threshold: The intersection-over-union threshold
            to use for non-maximum suppression. Defaults to 0.5.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of masks (e.g., IoU, IoS).

    Returns:
        Groups of prediction indices to be merged.
            Each group may have 1 or more elements.
    Nr   r   r   N.T)r   keepdims)r5  r   r   r&  r/  flattenanyrC   
logical_orreduceconcatenateextendrE  tolist)r9  r:  r;  rJ   merge_groupsscoresorderidxmerge_candidatecandidate_groupsr   above_threshold	above_idxs                r   _group_overlapping_masksra    sa   0 %'LAFNNE
e*q.%)ncr
u:?&& #  *Y/5%j1n!%,PD59\\^}5TO"&&(o.I mm22i 0/BC 3 O
 ##BGGI$6$=$=$?@?*+E %j1n 	,-1 e*q.2 r   c                   t        |t              r t        t        j                  |      |      }nt        ||      }|}| j
                  d   dk(  rt        | |||      S | dddf   }g }t        j                  |      D ]Z  }t        j                  ||k(        d   }	t        | |	   ||	   ||      }
|
D ]$  }|j                  |	|   j                                & \ |D ]  }t        |      dk(  st        d|        |S )aH  
    Perform Non-Maximum Merging (NMM) on segmentation predictions.

    Args:
        predictions: A 2D array of object detection predictions in
            the format of `(x_min, y_min, x_max, y_max, score)`
            or `(x_min, y_min, x_max, y_max, score, class)`. Shape: `(N, 5)` or
            `(N, 6)`, where N is the number of predictions.
        masks: A 3D array of binary masks corresponding to the predictions.
            Shape: `(N, H, W)`, where N is the number of predictions, and H, W are the
            dimensions of each mask.
        iou_threshold: The intersection-over-union threshold
            to use for non-maximum suppression.
        mask_dimension: The dimension to which the masks should be
            resized before computing IOU values. Defaults to 640.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of masks (e.g., IoU, IoS).

    Returns:
        A list of groups of prediction indices. Each inner list contains
            the indices of predictions whose masks overlap above `iou_threshold`
            according to the chosen `overlap_metric`, and should be merged or
            kept together as a single detection by non-maximum merging.

    Raises:
        AssertionError: If `iou_threshold` is not within the closed
            range from `0` to `1`.
    rw   r3  Nr   6Empty group detected when non-max-merging detections: )r"   r   r	   rC   r!  re   ra  uniquerc   r&  rX  r   r%   )r9  r:  r;  r<  rJ   masks_resizedcategory_idsrY  category_idcurr_indicesmerge_class_groupsmerge_class_groupmerge_groups                r   mask_non_max_mergerl    s6   H %% RZZ.?UN3Mq '~
 	
 q!t$LLyy. 
Jxx ;<Q?5%,'	
 "4 	J-> ? F F HI	J
J $ {q HW 
 r   c                ~   g }| dddf   }|j                         }t        |      dkD  rt        |d         }|dd }t        |      dk(  r|j                  |g       	 |S  |||      }||k\  }|gt	        j
                  ||         j                         }	|j                  |	       ||    }t        |      dkD  r|S )aU  Greedy non-maximum merging loop, independent of how overlap is computed.

    ``iou_against_candidate(order_indices, candidate_idx)`` must return the IoU
    vector between every prediction in ``order_indices`` and the candidate at
    ``candidate_idx``. Predictions whose IoU meets ``iou_threshold`` are
    grouped with the candidate.
    Nr   r   r   )r5  r   r   r&  rC   rE  rX  )
r9  iou_against_candidater;  rY  rZ  r[  r\  r   r_  rk  s
             r   _greedy_nmm_via_iou_callbackro  Q  s     %'LAFNNE
e*q.%)ncr
u:?&  %UC0-/FRWWU?%;<CCEFK(&' e*q. r   c                   | j                   d   dk(  rKt        j                  t        |       t              } ||      D cg c]  }||   j                          c}S | dddf   }g }t        j                  |      D ]L  }t        j                  ||k(        d   } ||      D ]$  }|j                  ||   j                                & N |D ]  }	t        |	      dk(  st        d|        |S c c}w )a  Dispatch NMM grouping per class, then translate local indices back to
    the global row positions of ``predictions``.

    ``group_within(global_indices)`` must return merge groups expressed in
    terms of *positions inside `global_indices`*, not absolute row positions.
    When ``predictions`` has no class column, a single pass over all rows is
    performed instead of per-category iteration.
    rw   r3  r_   Nr   rc  )
re   rC   aranger   r   rX  rd  rc   r&  r%   )
r9  group_withinglobal_indicesgrouprf  rY  rg  rh  local_grouprk  s
             r   _non_max_merge_per_categoryrv  p  s    q 3{#33?8D^8T
/4N5!((*
 	
 q!t$L$&Lyy. Dxx ;<Q?'5 	DK[ 9 @ @ BC	DD
 $ {q HW 
 !
s   C2c                :     	 	 	 	 	 	 d fd}t         ||      S )a  
    Apply greedy version of non-maximum merging to avoid detecting too many
    overlapping bounding boxes for a given object.

    Args:
        predictions: An array of shape `(n, 5)` containing
            the bounding boxes coordinates in format `[x1, y1, x2, y2]`
            and the confidence scores.
        iou_threshold: The intersection-over-union threshold
            to use for non-maximum suppression. Defaults to 0.5.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of boxes (e.g., IoU, IoS).

    Returns:
        Groups of prediction indices to be merged.
            Each group may have 1 or more elements.
    c                j    t        |    d d d df   ||dz   d df         j                         S )Nr   rw   )ru   rR  )r[  r\  rJ   r9  s     r   rn  z7_group_overlapping_boxes.<locals>.iou_against_candidate  sL     q"1"u%cAgrr)*
 ')		r   r[  npt.NDArray[np.int_]r\  r   r-   npt.NDArray[np.floating]ro  )r9  r;  rJ   rn  s   ` ` r   _group_overlapping_boxesr}    s7    .#*-	! (*M r   c                0     d fd}t         |      S )a0  
    Apply greedy version of non-maximum merging per category to avoid detecting
    too many overlapping bounding boxes for a given object.

    Args:
        predictions: An array of shape `(n, 5)` or `(n, 6)`
            containing the bounding boxes coordinates in format `[x1, y1, x2, y2]`,
            the confidence scores and class_ids. Omit class_id column to allow
            detections of different classes to be merged.
        iou_threshold: The intersection-over-union threshold
            to use for non-maximum suppression. Defaults to 0.5.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of boxes (e.g., IoU, IoS).

    Returns:
        list[list[int]]: Groups of prediction indices be merged.
            Each group may have 1 or more elements.
    c                $    t        |          S r   )r}  )rs  r;  rJ   r9  s    r   rr  z'box_non_max_merge.<locals>.group_within  s    ''
 	
r   rs  rz  r-   list[list[int]])rv  )r9  r;  rJ   rr  s   ``` r   box_non_max_merger    s    0

 '{LAAr   c                h   d|cxk  rdk  sn J d| d       d| fd|ffD ]  \  }}|dk(  r=|j                   dk7  s|j                  d   dvrt        d	| d
|j                   d      H|j                   dk(  r.|j                  dd dk7  rt        d	| d
|j                   d      |j                   dk(  r.|j                  d   dk7  rt        d	| d
|j                   d      |j                   dvst        d	| d|j                   d       t        |       t        |      k7  r$t        dt        |        dt        |       d      t	        |       \  }}}||   }t        |||      }	t        |	||      }
t        t        j                  t        j                     |
|j                                  S )u  
    Perform Non-Maximum Suppression on oriented bounding box predictions.

    Overlap is computed via :func:`oriented_box_iou_batch` on the four
    corners of each box, so detections whose axis-aligned bounding boxes
    overlap heavily but whose oriented bodies do not are kept — unlike
    :func:`box_non_max_suppression`, which would suppress them.

    Args:
        predictions: An array of object detection predictions in the
            format ``(x_min, y_min, x_max, y_max, score)`` or
            ``(x_min, y_min, x_max, y_max, score, class)``. Shape ``(N, 5)``
            or ``(N, 6)``. Only the score (column 4) and optional class
            (column 5) are read; the axis-aligned coordinates are not used.
        oriented_boxes: Array of shape ``(N, 4, 2)`` containing the four
            ``(x, y)`` corners of each oriented box, aligned with
            ``predictions`` row-by-row.
        iou_threshold: The intersection-over-union threshold to use for
            non-maximum suppression.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of oriented boxes (e.g., IoU, IoS).

    Returns:
        A boolean array of shape ``(N,)`` indicating which predictions
            to keep after non-maximum suppression.

    Raises:
        AssertionError: If ``iou_threshold`` is not within the closed
            range from 0 to 1.
        ValueError: If ``predictions`` and ``oriented_boxes`` have
            mismatched lengths or invalid shapes.

    Examples:
        >>> import numpy as np
        >>> import supervision as sv
        >>> oriented_boxes = np.array([
        ...     [[10, 10], [50, 10], [50, 30], [10, 30]],
        ...     [[11, 11], [51, 11], [51, 31], [11, 31]],
        ... ], dtype=np.float32)
        >>> predictions = np.array([
        ...     [10, 10, 50, 30, 0.9, 0],
        ...     [11, 11, 51, 31, 0.8, 0],
        ... ], dtype=np.float32)
        >>> keep = sv.oriented_box_non_max_suppression(
        ...     predictions=predictions,
        ...     oriented_boxes=oriented_boxes,
        ...     iou_threshold=0.5,
        ... )
        >>> keep
        array([ True, False])
    r   rw   r1  r2  r9  oriented_boxesrx   r3     r   r   ; expected (N, 5) or (N, 6).ry   Nr   r   r   r   r   r   r   B`predictions` and `oriented_boxes` must have the same length, got r  )r   re   r%   r   rF  r   rL  r   rf   rg   rC   r8  r5  )r9  r  r;  rJ   r   r   r>  r   r?  r   r@  s              r    oriented_box_non_max_suppressionr    s   r "" L/	"" %k25E~4VW 	c= xx1}		!F : v\#))4PQ  88q=SYYqr]f4D6cii[ 1T U  XX]syy|q0D6cii[ 1> ?  XXV#D6J399+UVW %* ;3~..{#$E#n*=)>aA
 	
 !=[ IJ:#J/N!...QD$T:}EDBHH%tJ,>,>,@'ABBr   c                :    	 	 	 	 	 	 dfd}t        | ||      S )z
    Greedy non-maximum merging on oriented boxes. Mirrors
    :func:`_group_overlapping_boxes` but uses :func:`oriented_box_iou_batch`.
    c                L    t        |    |   d         j                         S )NrP  )r   rR  )r[  r\  r  rJ   s     r   rn  z@_group_overlapping_oriented_boxes.<locals>.iou_against_candidate@  s3     &5!3	*
 ')		r   ry  r|  )r9  r  r;  rJ   rn  s    ` ` r   !_group_overlapping_oriented_boxesr  5  s7    #*-	! (*M r   c                    d fdffD ]  \  }}|dk(  r=|j                   dk7  s|j                  d   dvrt        d| d|j                   d      H|j                   d	k(  r.|j                  dd
 dk7  rt        d| d|j                   d      |j                   dk(  r.|j                  d   dk7  rt        d| d|j                   d      |j                   dvst        d| d|j                   d       t               t              k7  r$t        dt                dt               d      dcxk  rdk  sn J d d       d fd}t	         |      S )u  
    Perform Non-Maximum Merging on oriented bounding box predictions,
    grouped per category.

    Mirrors :func:`box_non_max_merge` but uses oriented-box IoU, so groups
    of rotated detections sharing the same body — rather than the same
    axis-aligned bounding box — are merged.

    Args:
        predictions: An array of shape ``(n, 5)`` or ``(n, 6)`` containing
            the axis-aligned coordinates ``[x1, y1, x2, y2]``, confidence
            scores, and optionally class ids. Only the score and optional
            class are used by the grouping logic; overlap is computed on
            ``oriented_boxes``.
        oriented_boxes: Array of shape ``(N, 4, 2)`` containing the four
            ``(x, y)`` corners of each oriented box.
        iou_threshold: The intersection-over-union threshold to use for
            non-maximum merging.
        overlap_metric: Metric used to compute the degree of overlap
            between pairs of oriented boxes (e.g., IoU, IoS).

    Returns:
        Groups of prediction indices to be merged. Each group may have 1
            or more elements.

    Raises:
        AssertionError: If ``iou_threshold`` is not within the closed
            range from 0 to 1.
        ValueError: If ``predictions`` and ``oriented_boxes`` have
            mismatched lengths or invalid shapes.

    Examples:
        >>> import numpy as np
        >>> import supervision as sv
        >>> oriented_boxes = np.array([
        ...     [[10, 10], [50, 10], [50, 30], [10, 30]],
        ...     [[11, 11], [51, 11], [51, 31], [11, 31]],
        ... ], dtype=np.float32)
        >>> predictions = np.array([
        ...     [10, 10, 50, 30, 0.9, 0],
        ...     [11, 11, 51, 31, 0.8, 0],
        ... ], dtype=np.float32)
        >>> groups = sv.oriented_box_non_max_merge(
        ...     predictions=predictions,
        ...     oriented_boxes=oriented_boxes,
        ...     iou_threshold=0.5,
        ... )
        >>> len(groups)
        1
    r9  r  rx   rw   r  r   r   r  ry   Nr   r   r   r   r   r   r   r  r  r   r1  r2  c                ,    t        |    |          S r   )r  )rs  r;  r  rJ   r9  s    r   rr  z0oriented_box_non_max_merge.<locals>.group_within  s&    0'>*	
 	
r   r  )r   re   r%   r   rv  )r9  r  r;  rJ   r   r   rr  s   ````   r   oriented_box_non_max_merger  N  s   p %k25E~4VW 	c= xx1}		!F : v\#))4PQ  88q=SYYqr]f4D6cii[ 1T U  XX]syy|q0D6cii[ 1> ?  XXV#D6J399+UVW %* ;3~..{#$E#n*=)>aA
 	
 "" L/	""

 
 '{LAAr   )rH   &list[float] | npt.NDArray[np.floating]rI   r  rJ   r>   r-   rG   )rq   npt.NDArray[np.number]rr   r  rJ   r>   r-   znpt.NDArray[np.float32])r{   list[float]r|   r  r}   r7  r-   rG   )rq   list[list[float]]rr   r  r}   z
list[bool]r-   npt.NDArray[np.float64])r   r{  r-   r{  )r   r{  r   r{  r-   z1tuple[npt.NDArray[np.intp], npt.NDArray[np.intp]])rq   r  rr   r  rJ   r7   r-   r{  )r   r   r   r   rJ   r7   r-   r{  )r   npt.NDArray[Any]r   r  rJ   r7   r-   r{  )
r   r  r   r  rJ   r7   r(  r   r-   r{  )r9  r{  r:  r  r;  rG   rJ   r7   r<  r   r-   npt.NDArray[np.bool_])r9  r{  r-   zOtuple[npt.NDArray[np.int_], npt.NDArray[np.floating], npt.NDArray[np.floating]])r   r{  r?  r{  r;  rG   r-   r  )r9  r{  r;  rG   rJ   r7   r-   r  )
r9  r  r:  r  r;  rG   rJ   r7   r-   r  )r9  r{  r:  r  r;  rG   r<  r   rJ   r7   r-   r  )r9  r  rn  z?Callable[[npt.NDArray[np.int_], int], npt.NDArray[np.floating]]r;  rG   r-   r  )r9  r  rr  z1Callable[[npt.NDArray[np.int_]], list[list[int]]]r-   r  )r9  r  r;  rG   rJ   r7   r-   r  )
r9  r{  r  r{  r;  rG   rJ   r7   r-   r  )
r9  r{  r  r{  r;  rG   rJ   r7   r-   r  ).
__future__r   r"  collections.abcr   enumr   typingr   r   r   numpyrC   numpy.typingrf   "supervision.detection.compact_maskr   !supervision.detection.utils.masksr	   r   r7   r8   r]   ru   r   r   r   r   r   r   r
  r  r/  rC  rF  rL  rN  ra  rl  ro  rv  r}  r  r  r  r  r5   r   r   <module>r     s   "  $   
   : :#
D #
L!
D !
N +8*;*;E)4E)9E) (E) 	E)V +8*;*;c&c+c (c 	cL%,P8!8&8 8 	8vK X,X1X 7XF %2$5$5LC&LC+LC "LC 	LCd %2$5$5ddd "d 	dT %2$5$5=0 =0%=0 "=0 	=0F %2$5$5 	]; ];%]; "]; 	];
 ];F $1$5$5@C)@C@C @C "	@C
 @C @CF/)/T/"
"(  	0 $1$5$5 C) C C " C 	 CL $1$5$5	6(6"6 6 "	6
 6x $1$5$5H)HH H 	H
 "H HV(
  >(C F $1$5$5"("" "" 	"N $1$5$5B(BB "B 	BF $1$5$5	\C)\C,\C \C "	\C
 \CD $1$5$5	),  "	
 8 $1$5$5	_B)_B,_B _B "	_B
 _Br   