Ë
    ¼Ó^jÊ¿  ã                  ó  — U d Z ddlmZ ddlZddlmZ ddlmZ ddlZ	ddl
mZ ddlmZmZ dd„Z	 	 	 	 	 	 	 	 dd	„Z	 	 	 	 	 	 	 	 dd
„Z	 	 	 	 	 	 dd„Z	 	 	 	 	 	 	 	 	 	 	 	 dd„ZdZded<   dZded<   	 	 	 	 	 	 	 	 	 	 	 	 dd„Z G d„ d«      Zy)uê  Crop-RLE compact mask storage for memory-efficient instance segmentation.

Dense ``(N, H, W)`` boolean masks use O(NÂ·HÂ·W) memory, which becomes
prohibitive for aerial imagery (e.g. 1000 objects x 4K image ~ 8.3 GB).
:class:`CompactMask` stores each mask as a run-length encoding of its
bounding-box crop, reducing typical usage to tens of MB.

The bounding boxes (``xyxy``) already present in ``Detections`` serve as the
crop boundaries, so no extra metadata is required from the caller.
é    )ÚannotationsN)ÚIterator)ÚAny)Ú_mask_to_rle_countsÚ_rle_counts_to_maskÚintc                óJ   — t        t        j                  | ddd…   «      «      S )aÏ  Return the number of ``True`` pixels in a run-length encoded mask.

    Args:
        rle: int32 array of run lengths as produced by :func:`_mask_to_rle_counts`.

    Returns:
        Total number of ``True`` pixels.

    Examples:
        ```pycon
        >>> import numpy as np
        >>> from supervision.detection.compact_mask import _rle_area
        >>> rle = np.array([1, 2, 1, 1, 1], dtype=np.int32)
        >>> _rle_area(rle)
        3

        ```
    é   Né   )r   ÚnpÚsum)Úrles    úm/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/detection/compact_mask.pyÚ	_rle_arear      s"   € ô& Œr�v‰v�c˜!˜$˜Q˜$‘iÓ Ó!Ð!ó    c                ó8  — t        |«      D �cg c]  }g ‘Œ }}d}d}t        | «      D ]Î  \  }}|dz  dk(  }	t        |«      }
|
dkD  rª||z
  }t        |
|«      }t	        ||   «      dk(  r|	rV||   j                  d«       nA|	t	        ||   «      dz
  dz  dk(  k(  r'||   dxx   |z  cc<   |
|z  }
||z  }||k\  rd}|dz  }Œ||   j                  |«       |
|z  }
||z  }||k\  rd}|dz  }|
dkD  rŒª||k\  sŒÎ n t        |«      D ]  }||   rŒ	|g||<   Œ |S c c}w )aÚ  Split a flat F-order RLE into per-column run lists.

    With F-order (column-major) RLE the flat pixel sequence visits all rows
    of column 0, then all rows of column 1, etc.  Each column therefore
    contains ``crop_h`` contiguous pixels.

    Runs that cross column boundaries are split at the boundary.  Each
    returned list starts with a ``False``-run count (possibly 0), matching
    the convention of :func:`_mask_to_rle_counts`.

    Args:
        rle: int32 run-length array as produced by
            :func:`~supervision.detection.utils.converters._mask_to_rle_counts`.
        crop_h: Number of rows (pixels per column).
        crop_w: Number of columns.

    Returns:
        List of ``crop_w`` run lists, one per column.  Each list sums to
        ``crop_h``.

    Examples:
        ```pycon
        >>> import numpy as np
        >>> from supervision.detection.compact_mask import _rle_split_cols
        >>> from supervision.detection.utils.converters import _mask_to_rle_counts
        >>> mask = np.array([[True, False], [True, True]], dtype=bool)
        >>> rle = _mask_to_rle_counts(mask)
        >>> rle.tolist()
        [0, 2, 1, 1]
        >>> _rle_split_cols(rle, 2, 2)
        [[0, 2], [1, 1]]

        ```
    r   r   r
   éÿÿÿÿ)ÚrangeÚ	enumerater   ÚminÚlenÚappend)r   Úcrop_hÚcrop_wÚ_Úper_colÚcolÚrowÚrun_idxÚrun_lenÚis_trueÚ	remainingÚspace_in_colÚtakeÚcs                 r   Ú_rle_split_colsr&   1   s{  € ôN -2°&«MÖ: q¢Ð:€GÐ:Ø
€CØ
€Cä% c›Nò Ñˆ�Ø˜A‘+ Ñ"ˆÜ˜“Lˆ	Ø˜!ŠmØ! C™<ˆLÜ�y ,Ó/ˆDÜ�7˜3‘<Ó  AÒ%ÙØ˜C‘L×'Ñ'¨Õ*ð œc '¨#¡,Ó/°!Ñ3°qÑ8¸AÑ=Ò>Ø˜‘˜RÓ  DÑ(Ó Ø˜TÑ!�	Ø�t‘�Ø˜&’=Ø�CØ˜1‘H�CØØ�C‰L×Ñ Ô%Ø˜ÑˆIØ�4‰KˆCØ�fŠ}Ø�Ø�q‘�ð+ ˜!‹mð, �&‹=Ùð5ô: �6‹]ò "ˆØ�q‹zØ ˜ˆG�AŠJð"ð €NùòK  ;s   Ž	Dc                óÐ  — t        |«      }|dk(  rdgS t        j                  |t        j                  ¬«      }d}t	        | «      D ]  \  }}|dz  dk(  ||||z    ||z  }Œ ||k  rd||d ||   }|j                  t        j                  «      }	t        j                  t        j                  |	«      «      }
t        j                  t        |
«      dz   t        j                  ¬«      }t        j                  t        |
«      dz   t        j                  ¬«      }d|d<   |
dz   |dd |
dz   |dd ||d<   ||z
  j                  «       }t        |d   «      r|j                  dd«       |S )uZ  Scale one column's run list to a new height using a precomputed row map.

    Each output row is mapped to a source row via ``row_map``, which
    implements nearest-neighbour resampling in the vertical direction.

    Args:
        col_runs: Per-column run list starting with a ``False``-run count.
        src_h: Height of the source column (sum of ``col_runs``).
        row_map: int32 array of length ``new_crop_h``; ``row_map[r']`` is the
            source row index for output row ``r'``.  Use
            ``(np.arange(new_crop_h) * src_h // new_crop_h)`` for
            ``cv2.INTER_NEAREST``-compatible mapping.

    Returns:
        Scaled run list of total length ``len(row_map)``, always starting
        with a ``False``-run count.

    Examples:
        ```pycon
        >>> import numpy as np
        >>> from supervision.detection.compact_mask import _rle_scale_col
        >>> col_runs = [0, 2, 2]   # F=0, T=2, F=2  â†’ [T, T, F, F]
        >>> row_map = np.array([0, 1, 2, 3, 0, 1, 2, 3], dtype=np.int32)
        >>> _rle_scale_col(col_runs, 4, row_map)
        [0, 2, 2, 2, 2]

        ```
    r   ©Údtyper   r
   FNr   )r   r   ÚemptyÚbool_r   ÚviewÚuint8ÚflatnonzeroÚdiffÚint64ÚtolistÚboolÚinsert)Úcol_runsÚsrc_hÚrow_mapÚ
new_crop_hÚ
src_valuesÚposÚriÚrlÚ
out_valuesÚ	out_uint8Ú
boundariesÚ
run_startsÚrun_endsÚresult_runss                 r   Ú_rle_scale_colrB   €   s[  € ôB �W“€JØ�Q‚Øˆsˆ
ô )+¯©°¼b¿h¹hÔ(G€JØ
€CÜ˜HÓ%ò ‰ˆˆBØ%'¨!¡V¨q¡[ˆ
�3˜˜r™Ð"Øˆr‰	‰ðð ˆU‚{Ø ˆ
�3�4Ðð ˜GÑ$€Jð —‘¤§¡Ó)€IÜ—‘¤§¡¨	Ó 2Ó3€JÜ(*¯©´°Z³À1Ñ1DÌBÏHÉHÔ(U€JÜ&(§h¡h¬s°:«ÀÑ/BÌ"Ï(É(Ô&S€HØ€Jˆq�MØ !‘^€Jˆqˆr€NØ ‘N€HˆSˆb€MØ€HˆR�LØ&¨Ñ3×;Ñ;Ó=€KäˆJ�q‰MÔØ×Ñ˜1˜aÔ ØÐr   c                óž  — g }| D ]�  }|s|j                  |«       Œt        |«      dz
  dz  dk(  }|s%|dxx   |d   z  cc<   |j                  |dd «       ŒR|d   dk(  r3t        |«      dkD  r%|dxx   |d   z  cc<   |j                  |dd «       Œ�|j                  |«       ŒŸ t        j                  |r|n|gt        j                  ¬«      S )a¿  Concatenate per-column run lists into a flat RLE, merging junctions.

    Each column run list starts with a ``False``-run count. Two junction types
    can be merged across column boundaries:

    * ``False``/``False``: the trailing False run merges with the leading False
      run of the next column (leading count may be zero).
    * ``True``/``True``: when the accumulated output ends on a True run and the
      next column's leading False count is zero (column starts with True), the
      two True runs are merged to avoid inserting a zero-length False run that
      would inflate ``len(rle)`` and skew the density metric in
      :func:`_resize_crop`.

    Args:
        scaled_cols: List of per-column run lists, each starting with a
            ``False``-run count.
        new_total: Total pixel count of the output (fallback for empty input).

    Returns:
        Flat int32 RLE array starting with a ``False``-run count.

    Examples:
        ```pycon
        >>> import numpy as np
        >>> from supervision.detection.compact_mask import _rle_join_cols
        >>> cols = [[1, 2], [1, 2]]  # each col: F=1, T=2
        >>> _rle_join_cols(cols, 6).tolist()
        [1, 2, 1, 2]

        ```
    r
   r   r   r   Nr(   )Úextendr   r   ÚarrayÚint32)Úscaled_colsÚ	new_totalÚoutput_runsr4   Úlast_is_trues        r   Ú_rle_join_colsrK   Á   sÖ   € ðF  €KØò -ˆÙØ×Ñ˜xÕ(ä Ó,¨qÑ0°AÑ5¸Ñ:ˆLáØ˜B“ 8¨A¡;Ñ.“Ø×"Ñ" 8¨A¨B <Õ0Ø˜!‘ Ò!¤c¨(£m°aÒ&7ð ˜B“ 8¨A¡;Ñ.“Ø×"Ñ" 8¨A¨B <Õ0à×"Ñ" 8Õ,ð-ô" �8‰8¡;‘K°Y°KÄrÇxÁxÔPÐPr   c                ó   — ||z  }||z  dk(  s|dk(  r&t        j                  dgt         j                  ¬«      S t        | «      dk(  s't	        t        j
                  | ddd…   «      «      dk(  r&t        j                  |gt         j                  ¬«      S t        | «      dk(  r/| d   dk(  r't        j                  d|gt         j                  ¬«      S t        | ||«      }t        j                  |«      |z  |z  j                  t         j                  «      }t        j                  |«      |z  |z  j                  t         j                  «      }i }	g }
|D ]-  }||	vrt        ||   ||«      |	|<   |
j                  |	|   «       Œ/ t        |
|«      S )a   Resize an F-order RLE-encoded crop via nearest-neighbour resampling.

    Manipulates run lengths directly without decoding to a full 2D boolean
    array.  Delegates to :func:`_rle_split_cols`, :func:`_rle_scale_col`,
    and :func:`_rle_join_cols`.

    The nearest-neighbour mapping ``src = floor(dst * src_size / dst_size)``
    is bit-exact with ``cv2.INTER_NEAREST``.

    Args:
        rle: int32 array of F-order run lengths as produced by
            :func:`~supervision.detection.utils.converters._mask_to_rle_counts`.
            Starts with a ``False``-run count (may be 0).
        crop_h: Height of the original crop.
        crop_w: Width of the original crop.
        new_crop_h: Height of the resized crop.
        new_crop_w: Width of the resized crop.

    Returns:
        int32 array of F-order run lengths for the resized crop, starting
        with the ``False``-run count.

    Examples:
        Upscale a 3x3 mask with a diagonal True stripe to 6x6:

        ```pycon
        >>> import numpy as np
        >>> from supervision.detection.compact_mask import _rle_resize
        >>> from supervision.detection.utils.converters import (
        ...     _mask_to_rle_counts, _rle_counts_to_mask,
        ... )
        >>> mask = np.array([
        ...     [True,  False, False],
        ...     [False, True,  False],
        ...     [False, False, True ],
        ... ], dtype=bool)
        >>> rle = _mask_to_rle_counts(mask)
        >>> resized_rle = _rle_resize(rle, 3, 3, 6, 6)
        >>> result = _rle_counts_to_mask(resized_rle, 6, 6)
        >>> result.astype(int)
        array([[1, 1, 0, 0, 0, 0],
               [1, 1, 0, 0, 0, 0],
               [0, 0, 1, 1, 0, 0],
               [0, 0, 1, 1, 0, 0],
               [0, 0, 0, 0, 1, 1],
               [0, 0, 0, 0, 1, 1]])

        ```
    r   r(   r
   Nr   )r   rE   rF   r   r   r   r&   ÚarangeÚastyperB   r   rK   )r   r   r   r7   Ú
new_crop_wrH   r   Úcol_mapr6   Ú	col_cacherG   Úsrc_cs               r   Ú_rle_resizerS   ù   sc  € ðp ˜ZÑ'€Ià��˜!Ò˜y¨Aš~Ü�x‰x˜˜¤2§8¡8Ô,Ð,Ü
ˆ3ƒx�1‚}œœBŸF™F 3 q t¨! t¡9Ó-Ó.°!Ò3Ü�x‰x˜˜¬2¯8©8Ô4Ð4Ü
ˆ3ƒx�1‚}˜˜Q™ 1šÜ�x‰x˜˜I˜¬b¯h©hÔ7Ð7ä˜c 6¨6Ó2€Gô �y‰y˜Ó$ vÑ-°Ñ;×CÑCÄBÇHÁHÓM€Gô �y‰y˜Ó$ vÑ-°Ñ;×CÑCÄBÇHÁHÓM€Gð ')€IØ€KØò -ˆØ˜	Ñ!Ü-¨g°e©n¸fÀgÓNˆI�eÑØ×Ñ˜9 UÑ+Õ,ð-ô
 ˜+ yÓ1Ð1r   g      Ð?ÚfloatÚ_L3_DENSITY_THRESHOLDé   Ú_PARALLEL_THRESHOLDc                óª  — ddl }t        | «      dk(  r)t        j                  ||z  gt        j                  ¬«      S t        | «      t        d||z  «      z  t        k  rt        | ||||«      S t        | ||«      }|j                  |j                  t        j                  «      ||f|j                  ¬«      j                  t        «      }t!        |«      S )uß  Resize one RLE crop to ``(new_h, new_w)``, choosing the fastest path.

    Dispatch order:

    1. **All-False fast path** â€” returns a single False run; no decode.
    2. **L3 direct RLE path** â€” used when run density is below
       :data:`_L3_DENSITY_THRESHOLD`; manipulates run lengths without
       allocating a 2D array.
    3. **cv2 fallback** â€” decodes to ``uint8``, calls
       ``cv2.resize(INTER_NEAREST)``, re-encodes; used for dense masks.

    Args:
        rle: int32 run-length array for the source crop.
        orig_h: Height of the source crop.
        orig_w: Width of the source crop.
        new_h: Target height.
        new_w: Target width.

    Returns:
        int32 RLE array for the resized crop.
    r   Nr(   r
   )Úinterpolation)Úcv2r   r   rE   rF   r   ÚmaxrU   rS   r   Úresizer,   r-   ÚINTER_NEARESTrN   r2   r   )r   Úorig_hÚorig_wÚnew_hÚnew_wrZ   ÚcropÚresizeds           r   Ú_resize_croprd   U  sÀ   € ó8 ô �ƒ~˜ÒÜ�x‰x˜ ™˜¬r¯x©xÔ8Ð8ô ˆ3ƒx”#�a˜ &™Ó)Ñ)Ô,AÒAÜ˜3 ¨°°uÓ=Ð=ô ˜s F¨FÓ3€DØ�j‰jØ�	‰	”"—(‘(ÓØ	�ˆØ×'Ñ'ð ó ÷ �fŒTƒlð	 ô
 ˜wÓ'Ð'r   c                  ó2  — e Zd ZdZdZ	 	 	 	 	 	 	 	 	 	 dd„Ze	 	 	 	 	 	 	 	 dd„«       Zdd„Zdd„Z	dd„Z
dd„Zedd	„«       Zedd
„«       Zedd„«       Zedd„«       Zed d„«       Zd!d"d„Z	 	 	 	 d#d„Zd!d$d„Zd%d„Zed&d„«       Zd'd„Z	 	 	 	 	 	 	 	 d(d„Zd)d„Zy)*ÚCompactMaskuÎ  Memory-efficient crop-RLE mask storage for instance segmentation.

    Instead of storing N full ``(H, W)`` boolean arrays, :class:`CompactMask`
    encodes each mask as a run-length sequence of its bounding-box crop.  This
    reduces memory from O(NÂ·HÂ·W) to roughly O(NÂ·bbox_area), which is orders of
    magnitude smaller for sparse masks on high-resolution images.

    The class exposes a duck-typed interface compatible with ``np.ndarray``
    masks used elsewhere in ``supervision``:

    * ``mask[int]`` â†’ dense ``(H, W)`` bool array (annotators, converters).
    * ``mask[slice | list | ndarray]`` â†’ new :class:`CompactMask` (filtering).
    * ``np.asarray(mask)`` â†’ dense ``(N, H, W)`` bool array (numpy interop).
    * ``mask.shape``, ``mask.dtype``, ``mask.area`` â€” match the dense API.

    :class:`CompactMask` is **not** a drop-in ``np.ndarray`` replacement.
    When you need to call arbitrary ndarray methods (``astype``, ``reshape``,
    ``ravel``, ``any``, ``all``, â€¦) call :meth:`to_dense` first:
    ``cm.to_dense().astype(np.uint8)``.  :meth:`to_dense` is the single
    explicit materialisation boundary.

    .. note:: **RLE encoding â€” COCO / pycocotools pixel-scan order**

        :class:`CompactMask` uses **column-major (Fortran-order, F-order)**
        run-lengths scoped to each mask's bounding-box crop, matching the
        pixel-scan order used by the COCO API (pycocotools).  The crop scope
        still differs from the full-image scope used by pycocotools, so a
        :class:`CompactMask` RLE cannot be passed directly to
        ``maskUtils.iou()`` or ``maskUtils.decode()`` without re-scoping to
        the full canvas.  Use :meth:`to_dense` to obtain a standard boolean
        array for pycocotools interop.

        This scan order is part of CompactMask's internal RLE representation.
        Switching from row-major (C-order) to column-major (F-order) is a
        backward-incompatible format change for any persisted or serialized
        :class:`CompactMask` state, including pickled objects and any
        external storage of ``._rles``.  Older stored RLE arrays will decode
        incorrectly under the new convention.

        Migration note: load or decode legacy masks with the older version,
        materialize them to dense boolean arrays, and then re-encode them
        with the current version (for example via :meth:`to_dense` followed
        by :meth:`from_dense`) before persisting them again.

    Args:
        rles: List of N int32 run-length arrays.
        crop_shapes: Array of shape ``(N, 2)`` â€” ``(crop_h, crop_w)`` per mask.
        offsets: Array of shape ``(N, 2)`` â€” ``(x1, y1)`` bounding-box origins.
        image_shape: ``(H, W)`` of the full image.

    Examples:
        ```pycon
        >>> import numpy as np
        >>> from supervision.detection.compact_mask import CompactMask
        >>> masks = np.zeros((2, 100, 100), dtype=bool)
        >>> masks[0, 10:20, 10:20] = True
        >>> masks[1, 50:70, 50:80] = True
        >>> xyxy = np.array([[10, 10, 19, 19], [50, 50, 79, 69]], dtype=np.float32)
        >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(100, 100))
        >>> len(cm)
        2
        >>> cm.shape
        (2, 100, 100)

        ```
    )Ú_crop_shapesÚ_image_shapeÚ_offsetsÚ_rlesc                ó<   — || _         || _        || _        || _        y ©N)rj   rg   ri   rh   )ÚselfÚrlesÚcrop_shapesÚoffsetsÚimage_shapes        r   Ú__init__zCompactMask.__init__Ë  s"   € ð 37ˆŒ
Ø3>ˆÔØ/6ˆŒØ-8ˆÕr   c                ó,  — |\  }}t        |«      }|dk(  rQ | g t        j                  dt        j                  ¬«      t        j                  dt        j                  ¬«      |«      S g }g }g }	t	        |«      D �]E  }
||
   \  }}}}t        t        dt        t        |«      |dz
  «      «      «      }t        t        dt        t        |«      |dz
  «      «      «      }t        t        dt        t        |«      |dz
  «      «      «      }t        t        dt        t        |«      |dz
  «      «      «      }||k  s||k  r t        j                  dt        ¬«      }||}}n||
||dz   …||dz   …f   }||z
  dz   }||z
  dz   }|j                  t        |«      «       |j                  ||f«       |	j                  ||f«       �ŒH t        j                  |t        j                  ¬«      }t        j                  |	t        j                  ¬«      } | ||||«      S )at  Create a :class:`CompactMask` from a dense ``(N, H, W)`` bool array.

        Bounding boxes are clipped to image bounds and interpreted in the
        supervision ``xyxy`` convention (inclusive max coordinates). A
        box with invalid ordering (``x2 < x1`` or ``y2 < y1``) is replaced by
        a ``1x1`` all-False crop to avoid degenerate RLE.

        Args:
            masks: Dense boolean mask array of shape ``(N, H, W)``.
            xyxy: Bounding boxes of shape ``(N, 4)`` in ``[x1, y1, x2, y2]``
                format.
            image_shape: ``(H, W)`` of the full image.

        Returns:
            A new :class:`CompactMask` instance.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 100, 100), dtype=bool)
            >>> masks[0, 10:20, 10:20] = True
            >>> xyxy = np.array([[10, 10, 19, 19]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(100, 100))
            >>> cm.shape
            (1, 100, 100)

            ```
        r   ©r   r   r(   r
   ©r
   r
   )r   r   r*   rF   r   r   r[   r   Úzerosr2   r   r   rE   )ÚclsÚmasksÚxyxyrq   Úimg_hÚimg_wÚ	num_masksrn   Úcrop_shapes_listÚoffsets_listÚmask_idxÚx1Úy1Úx2Úy2Úx1cÚy1cÚx2cÚy2crb   r   r   ro   rp   s                           r   Ú
from_densezCompactMask.from_denseÛ  sâ  € ðH #‰ˆˆuÜ˜“Jˆ	à˜Š>ÙØÜ—‘˜¤r§x¡xÔ0Ü—‘˜¤r§x¡xÔ0Øó	ð ð -/ˆØ24ÐØ.0ˆä˜iÓ(ó 	,ˆHØ! (™^‰NˆB��B˜Ü”c˜!œS¤ R£¨%°!©)Ó4Ó5Ó6ˆCÜ”c˜!œS¤ R£¨%°!©)Ó4Ó5Ó6ˆCÜ”c˜!œS¤ R£¨%°!©)Ó4Ó5Ó6ˆCÜ”c˜!œS¤ R£¨%°!©)Ó4Ó5Ó6ˆCð �SŠy˜C #šIÜ—x‘x ¬dÔ3�Ø �S‘à˜X s¨S°1©W }°c¸CÀ!¹G°mÐCÑD�à˜3‘Y ‘]ˆFØ˜3‘Y ‘]ˆFØ�K‰KÔ+¨DÓ1Ô2Ø×#Ñ# V¨VÐ$4Ô5Ø×Ñ  c 
Ö+ð'	,ô* —h‘hÐ/´r·x±xÔ@ˆÜ—(‘(˜<¬r¯x©xÔ8ˆÙ�4˜ g¨{Ó;Ð;r   c                óÒ  — t        | j                  «      }| j                  \  }}t        j                  |||ft
        ¬«      }t        |«      D ]–  }t        | j                  |df   «      t        | j                  |df   «      }}t        | j                  |df   «      t        | j                  |df   «      }	}t        | j                  |   ||«      }
|
|||	|	|z   …|||z   …f<   Œ˜ |S )aj  Materialise all masks as a dense ``(N, H, W)`` boolean array.

        Returns:
            Boolean array of shape ``(N, H, W)``.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 50, 50), dtype=bool)
            >>> masks[0, 10:20, 10:30] = True
            >>> xyxy = np.array([[10, 10, 29, 19]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(50, 50))
            >>> cm.to_dense().shape
            (1, 50, 50)

            ```
        r(   r   r
   )r   rj   rh   r   rv   r2   r   r   rg   ri   r   )rm   r|   rz   r{   Úresultr   r   r   r€   r�   rb   s              r   Úto_densezCompactMask.to_dense+  sô   € ô& ˜Ÿ
™
“Oˆ	Ø×(Ñ(‰ˆˆuÜ(*¯©°)¸UÀEÐ1JÔRVÔ(WˆÜ˜iÓ(ò 	HˆHä�D×%Ñ% h° kÑ2Ó3Ü�D×%Ñ% h° kÑ2Ó3ð ˆFô ˜Ÿ™ x° {Ñ3Ó4´c¸$¿-¹-ÈÐRSÈÑ:TÓ6U�ˆBÜ& t§z¡z°(Ñ';¸VÀVÓLˆDØCGˆF�8˜R " v¡+Ð-¨r°B¸±KÐ/?Ð?Ò@ð	Hð ˆr   c                óž   — t        | j                  |df   «      }t        | j                  |df   «      }t        | j                  |   ||«      S )u"  Decode a single mask crop without allocating the full image array.

        This is an O(crop_area) operation â€” ideal for annotators that only
        need the cropped region.

        Args:
            index: Index of the mask to decode.

        Returns:
            Boolean array of shape ``(crop_h, crop_w)``.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 100, 100), dtype=bool)
            >>> masks[0, 20:30, 10:40] = True
            >>> xyxy = np.array([[10, 20, 39, 29]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(100, 100))
            >>> cm.crop(0).shape
            (10, 30)

            ```
        r   r
   )r   rg   r   rj   )rm   Úindexr   r   s       r   rb   zCompactMask.cropK  sN   € ô2 �T×&Ñ& u¨a xÑ0Ó1ˆÜ�T×&Ñ& u¨a xÑ0Ó1ˆÜ" 4§:¡:¨eÑ#4°f¸fÓEÐEr   c                ó,   — t        | j                  «      S )aÀ  Return the number of masks.

        Returns:
            Number of masks N.

        Examples:
            ```pycon
            >>> from supervision.detection.compact_mask import CompactMask
            >>> import numpy as np
            >>> cm = CompactMask(
            ...     [], np.empty((0, 2), dtype=np.int32),
            ...     np.empty((0, 2), dtype=np.int32), (100, 100))
            >>> len(cm)
            0

            ```
        )r   rj   ©rm   s    r   Ú__len__zCompactMask.__len__l  s   € ô$ �4—:‘:‹Ðr   c              #  óL   K  — t        t        | «      «      D ]	  }| |   –— Œ y­w)z6Iterate over masks as dense ``(H, W)`` boolean arrays.N)r   r   )rm   r   s     r   Ú__iter__zCompactMask.__iter__€  s(   è ø€ äœc $›iÓ(ò 	!ˆHØ�x‘.Ó ñ	!ùs   ‚"$c                ó<   — | j                   \  }}t        | «      ||fS )aì  Return ``(N, H, W)`` matching the dense mask convention.

        Returns:
            Tuple ``(N, H, W)``.

        Examples:
            ```pycon
            >>> from supervision.detection.compact_mask import CompactMask
            >>> import numpy as np
            >>> cm = CompactMask(
            ...     [], np.empty((0, 2), dtype=np.int32),
            ...     np.empty((0, 2), dtype=np.int32), (480, 640))
            >>> cm.shape
            (0, 480, 640)

            ```
        )rh   r   )rm   rz   r{   s      r   ÚshapezCompactMask.shape…  s$   € ð& ×(Ñ(‰ˆˆuÜ�D“	˜5 %Ð(Ð(r   c                ó   — | j                   S )ak  Return per-mask crop origins as ``(x1, y1)`` integer offsets.

        Returns:
            Array of shape ``(N, 2)`` with ``int32`` offsets.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 10, 10), dtype=bool)
            >>> masks[0, 2:4, 3:5] = True
            >>> xyxy = np.array([[3, 2, 4, 3]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(10, 10))
            >>> cm.offsets.tolist()
            [[3, 2]]

            ```
        )ri   r�   s    r   rp   zCompactMask.offsets›  s   € ð( �}‰}Ðr   c                óˆ  — t        | «      dk(  r%t        j                  dt        j                  ¬«      S | j                  dd…df   }| j                  dd…df   }|| j
                  dd…df   z   dz
  }|| j
                  dd…df   z   dz
  }t        j                  ||||f«      j                  t        j                  d¬«      S )aü  Return per-mask inclusive bounding boxes in ``xyxy`` format.

        Boxes are derived from crop metadata:
        ``x2 = x1 + crop_w - 1``, ``y2 = y1 + crop_h - 1``.

        Returns:
            Array of shape ``(N, 4)`` with ``int32`` boxes
            ``[x1, y1, x2, y2]``.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 10, 10), dtype=bool)
            >>> masks[0, 2:5, 3:7] = True
            >>> xyxy = np.array([[3, 2, 6, 4]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(10, 10))
            >>> cm.bbox_xyxy.tolist()
            [[3, 2, 6, 4]]

            ```
        r   )r   é   r(   Nr
   F)Úcopy)r   r   r*   rF   ri   rg   Úcolumn_stackrN   )rm   r€   r�   r‚   rƒ   s        r   Ú	bbox_xyxyzCompactMask.bbox_xyxy±  s°   € ô0 ˆt‹9˜Š>Ü—8‘8˜F¬"¯(©(Ô3Ð3à$(§M¡M²!°Q°$Ñ$7ˆØ$(§M¡M²!°Q°$Ñ$7ˆØ$&¨×):Ñ):º1¸a¸4Ñ)@Ñ$@À1Ñ$DˆØ$&¨×):Ñ):º1¸a¸4Ñ)@Ñ$@À1Ñ$DˆÜ�‰  B¨¨BÐ/Ó0×7Ñ7¼¿¹ÀuÐ7ÓMÐMr   c                ó4   — t        j                  t        «      S )uØ  Return ``np.dtype(bool)`` â€” always.

        Returns:
            ``np.dtype(bool)``.

        Examples:
            ```pycon
            >>> from supervision.detection.compact_mask import CompactMask
            >>> import numpy as np
            >>> cm = CompactMask(
            ...     [], np.empty((0, 2), dtype=np.int32),
            ...     np.empty((0, 2), dtype=np.int32), (100, 100))
            >>> cm.dtype
            dtype('bool')

            ```
        )r   r)   r2   r�   s    r   r)   zCompactMask.dtypeÒ  s   € ô& �x‰xœ‹~Ðr   c                ó˜   — t        j                  | j                  D �cg c]  }t        |«      ‘Œ c}t         j                  ¬«      S c c}w )aÄ  Compute the area (``True`` pixel count) of each mask.

        Returns:
            int64 array of shape ``(N,)`` with per-mask pixel counts.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((2, 100, 100), dtype=bool)
            >>> masks[0, 0:10, 0:10] = True  # 100 pixels
            >>> masks[1, 0:5, 0:5] = True    # 25 pixels
            >>> xyxy = np.array([[0, 0, 9, 9], [0, 0, 4, 4]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(100, 100))
            >>> cm.area.tolist()
            [100, 25]

            ```
        r(   )r   rE   rj   r   r0   )rm   r   s     r   ÚareazCompactMask.areaç  s/   € ô* �x‰x°4·:±:Ö>¨Cœ 3�Ò>ÄbÇhÁhÔOÐOùÒ>s   žANc                ód   — |dk(  r| j                   S | j                  «       j                  |¬«      S )a"  NumPy-compatible sum with a fast path for per-mask area.

        When ``axis=(1, 2)``, returns the per-mask True-pixel count via
        :attr:`area` without materialising the full dense array.

        Args:
            axis: Axis or axes to sum over.

        Returns:
            Sum result matching NumPy semantics.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 10, 10), dtype=bool)
            >>> masks[0, 0:3, 0:3] = True
            >>> xyxy = np.array([[0, 0, 2, 2]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(10, 10))
            >>> cm.sum(axis=(1, 2)).tolist()
            [9]

            ```
        )r
   r   ©Úaxis)r�   r‹   r   )rm   r    s     r   r   zCompactMask.sumþ  s/   € ð2 �6Š>Ø—9‘9ÐØ�}‰}‹×"Ñ"¨Ð"Ó-Ð-r   c                óÂ  — t        |t        t        j                  f«      rÌt        |«      }| j                  \  }}t        j
                  ||ft        ¬«      }t        | j                  |df   «      }t        | j                  |df   «      }t        | j                  |df   «      }t        | j                  |df   «      }	t        | j                  |   ||«      }
|
||	|	|z   …|||z   …f<   |S t        |t        «      r?t        | j                  |   | j                  |   | j                  |   | j                  «      S t        |t        j                  «      r,|j                  t        k(  rt        j                  |«      d   }nt        |t         «      rAt#        d„ |D «       «      r/t        j$                  t        j&                  |t        ¬«      «      }n.t        j&                  t!        |«      t        j(                  ¬«      }|D �cg c]  }| j                  t        |«         ‘Œ }}| j                  |   }| j                  |   }t        |||| j                  «      S c c}w )u8  Index into the mask collection.

        * ``int`` â†’ dense ``(H, W)`` bool array (for annotators, iterators).
        * ``slice | list | ndarray`` â†’ new :class:`CompactMask` (for filtering).

        Args:
            index: An integer returns a dense ``(H, W)`` mask.  Any other
                supported index type returns a new :class:`CompactMask`.

        Returns:
            Dense ``(H, W)`` ``np.ndarray`` for integer index, or a new
            :class:`CompactMask` for all other index types.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((3, 20, 20), dtype=bool)
            >>> xyxy = np.array(
            ...     [[0,0,5,5],[5,5,10,10],[10,10,15,15]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(20, 20))
            >>> cm[0].shape        # int â†’ dense (H, W)
            (20, 20)
            >>> len(cm[[0, 2]])    # list â†’ CompactMask
            2

            ```
        r(   r   r
   c              3  ó\   K  — | ]$  }t        |t        t        j                  f«      –— Œ& y ­wrl   )Ú
isinstancer2   r   r+   )Ú.0Úitems     r   ú	<genexpr>z*CompactMask.__getitem__.<locals>.<genexpr>S  s%   è ø€ ò -
Ø37ŒJ�tœd¤B§H¡HÐ-×.ñ-
ùs   ‚*,)r£   r   r   Úintegerrh   rv   r2   rg   ri   r   rj   Úslicerf   Úndarrayr)   ÚwhereÚlistÚallr.   ÚasarrayÚintp)rm   r�   Úidxrz   r{   rŠ   r   r   r€   r�   rb   Úidx_arrr   Únew_rlesÚnew_crop_shapesÚnew_offsetss                   r   Ú__getitem__zCompactMask.__getitem__  s  € ô@ �eœc¤2§:¡:Ð.Ô/Ü�e“*ˆCØ×,Ñ,‰LˆE�5Ü,.¯H©H°e¸U°^Ì4Ô,PˆFÜ˜×*Ñ*¨3°¨6Ñ2Ó3ˆFÜ˜×*Ñ*¨3°¨6Ñ2Ó3ˆFÜ�T—]‘] 3¨ 6Ñ*Ó+ˆBÜ�T—]‘] 3¨ 6Ñ*Ó+ˆBÜ& t§z¡z°#¡¸ÀÓGˆDØ9=ˆF�2˜˜V™Ð# R¨"¨v©+Ð%5Ð5Ñ6ØˆMô �eœUÔ#ÜØ—
‘
˜5Ñ!Ø×!Ñ! %Ñ(Ø—‘˜eÑ$Ø×!Ñ!ó	ð ô �eœRŸZ™ZÔ(¨U¯[©[¼DÒ-@Ü—h‘h˜u“o aÑ(‰GÜ˜œtÔ$¬ñ -
Ø;@ô-
ô *
ô —n‘n¤R§Z¡Z°¼TÔ%BÓC‰Gä—j‘j¤ e£´B·G±GÔ<ˆGà>EÖF°(�D—J‘Jœs 8›}Ó-ÐFˆÐFØ15×1BÑ1BÀ7Ñ1KˆØ-1¯]©]¸7Ñ-CˆÜ˜8 _°kÀ4×CTÑCTÓUÐUùò Gs   ÈIc                óL   — | j                  «       }|�|j                  |«      S |S )aÑ  NumPy interop: materialise as a dense ``(N, H, W)`` array.

        Called by ``np.asarray(compact_mask)`` and similar NumPy functions.

        Args:
            dtype: Optional dtype to cast the result to.

        Returns:
            Dense boolean array of shape ``(N, H, W)``.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 10, 10), dtype=bool)
            >>> xyxy = np.array([[0, 0, 5, 5]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(10, 10))
            >>> np.asarray(cm).shape
            (1, 10, 10)

            ```
        )r‹   rN   )rm   r)   rŠ   s      r   Ú	__array__zCompactMask.__array___  s)   € ð. —‘“ˆØÐØ—=‘= Ó'Ð'Øˆr   c                ó2  — t        |t        «      r;t        t        j                  | j                  «       |j                  «       «      «      S t        |t        j                  «      r-t        t        j                  | j                  «       |«      «      S t        S )aÖ  Element-wise equality with another :class:`CompactMask` or ndarray.

        Args:
            other: Another :class:`CompactMask` or ``np.ndarray``.

        Returns:
            ``True`` if all masks are pixel-identical.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 10, 10), dtype=bool)
            >>> xyxy = np.array([[0, 0, 5, 5]], dtype=np.float32)
            >>> cm1 = CompactMask.from_dense(masks, xyxy, image_shape=(10, 10))
            >>> cm2 = CompactMask.from_dense(masks, xyxy, image_shape=(10, 10))
            >>> cm1 == cm2
            True

            ```
        )r£   rf   r2   r   Úarray_equalr‹   r©   ÚNotImplemented)rm   Úothers     r   Ú__eq__zCompactMask.__eq__{  sa   € ô, �eœ[Ô)ÜœŸ™ t§}¡}£¸¿¹Ó8HÓIÓJÐJÜ�eœRŸZ™ZÔ(ÜœŸ™ t§}¡}£¸Ó>Ó?Ð?ÜÐr   c                óÖ  — | st        d«      ‚| d   j                  }| dd D ],  }|j                  |k7  sŒt        d|› d|j                  › �«      ‚ g }| D ]  }|j                  |j                  «       Œ t	        j
                  | D �cg c]  }|j                  ‘Œ c}d¬«      }t	        j
                  | D �cg c]  }|j                  ‘Œ c}d¬«      }t        ||||«      S c c}w c c}w )af  Concatenate multiple :class:`CompactMask` objects into one.

        All inputs must have the same ``image_shape``.

        Args:
            masks_list: Non-empty list of :class:`CompactMask` objects.

        Returns:
            A new :class:`CompactMask` containing every mask from the inputs,
            in order.

        Raises:
            ValueError: If ``masks_list`` is empty or image shapes differ.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks1 = np.zeros((2, 50, 50), dtype=bool)
            >>> masks2 = np.zeros((3, 50, 50), dtype=bool)
            >>> xyxy1 = np.array([[0,0,10,10],[10,10,20,20]], dtype=np.float32)
            >>> xyxy2 = np.array(
            ...     [[0,0,5,5],[5,5,10,10],[10,10,15,15]], dtype=np.float32)
            >>> cm1 = CompactMask.from_dense(masks1, xyxy1, image_shape=(50, 50))
            >>> cm2 = CompactMask.from_dense(masks2, xyxy2, image_shape=(50, 50))
            >>> len(CompactMask.merge([cm1, cm2]))
            5

            ```
        z2Cannot merge an empty list of CompactMask objects.r   r
   Nz>Cannot merge CompactMask objects with different image shapes: z vs rŸ   )	Ú
ValueErrorrh   rD   rj   r   Úconcatenaterg   ri   rf   )Ú
masks_listrq   Úcmr±   r²   r³   s         r   ÚmergezCompactMask.merge›  sô   € ñ@ ÜÐQÓRÐRà  ‘m×0Ñ0ˆØ˜Q˜R�.ò 	ˆBØ�‰ +Ó-Ü ØTØ"�m 4¨¯©Ð'8ð:óð ð	ð 13ˆØò 	&ˆBØ�O‰O˜BŸH™HÕ%ð	&ô
 24·±Ø'1Ö2 ˆR�_‹_Ò2¸ô2
ˆô .0¯^©^Ø#-Ö.˜RˆR�[‹[Ò.°Qô.
ˆô ˜8 _°kÀ;ÓOÐOùò 3ùò /s   ÂC!Â7C&c           	     ó*  — t        | j                  «      }|dk(  r^t        g t        j                  dt        j
                  ¬«      t        j                  dt        j
                  ¬«      | j                  «      S g }g }g }t        |«      D �]©  }| j                  |«      }t        | j                  |df   «      }t        | j                  |df   «      }t        j                  |d¬«      }	t        j                  |d¬«      }
|	j                  «       sX|j                  t        t        j                  dt        ¬«      «      «       |j                  d«       |j                  ||f«       Œßt        j                   |	«      d   }t        j                   |
«      d   }t        |d   «      t        |d   «      }}t        |d   «      t        |d   «      }}|||dz   …||dz   …f   }|j                  t        |«      «       |j                  ||z
  dz   ||z
  dz   f«       |j                  ||z   ||z   f«       �Œ¬ t        |t        j"                  |t        j
                  ¬«      t        j"                  |t        j
                  ¬«      | j                  «      S )u­  Re-encode all masks using tight bounding boxes.

        When the original ``xyxy`` boxes are padded or loose â€” common with
        object-detector outputs and full-image boxes used in tests â€” each RLE
        crop encodes more background (``False``) pixels than necessary.  This
        method decodes every crop, trims it to the minimal rectangle that
        contains all ``True`` pixels, and re-encodes.  All-``False`` masks are
        normalised to a ``1x1`` all-``False`` crop.

        The call is O(sum of crop areas) â€” suitable as a one-time cleanup
        after accumulating many merges (e.g. after
        :class:`~supervision.detection.tools.inference_slicer.InferenceSlicer`
        tiles are merged).

        Returns:
            A new :class:`CompactMask` with minimal-area crops and updated
            offsets.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 10, 10), dtype=bool)
            >>> masks[0, 3:7, 3:7] = True
            >>> # Deliberately loose bbox: covers the full image.
            >>> xyxy = np.array([[0, 0, 9, 9]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(10, 10))
            >>> repacked = cm.repack()
            >>> repacked.offsets.tolist()  # tight origin: x1=3, y1=3
            [[3, 3]]

            ```
        r   rt   r(   r
   rŸ   ru   r   )r   rj   rf   r   r*   rF   rh   r   rb   r   ri   Úanyr   r   rv   r2   rª   rE   )rm   r|   r±   Únew_crop_shapes_listÚnew_offsets_listr   rb   Úx1_offÚy1_offÚrows_anyÚcols_anyÚ	y_indicesÚ	x_indicesÚy_minÚy_maxÚx_minÚx_maxÚtights                     r   ÚrepackzCompactMask.repackØ  s5  € ôD ˜Ÿ
™
“Oˆ	Ø˜Š>ÜØÜ—‘˜¤r§x¡xÔ0Ü—‘˜¤r§x¡xÔ0Ø×!Ñ!ó	ð ð 13ˆØ68ÐØ24Ðä˜iÓ(ó 	FˆHØ—9‘9˜XÓ&ˆDÜ˜Ÿ™ x° {Ñ3Ó4ˆFÜ˜Ÿ™ x° {Ñ3Ó4ˆFä—v‘v˜d¨Ô+ˆHÜ—v‘v˜d¨Ô+ˆHà—<‘<”>à—‘Ô 3´B·H±H¸VÌ4Ô4PÓ QÔRØ$×+Ñ+¨FÔ3Ø ×'Ñ'¨°Ð(8Ô9ØäŸ™ Ó*¨1Ñ-ˆIÜŸ™ Ó*¨1Ñ-ˆIÜ˜y¨™|Ó,¬c°)¸B±-Ó.@�5ˆEÜ˜y¨™|Ó,¬c°)¸B±-Ó.@�5ˆEà˜ ¨¡Ð*¨E°E¸A±IÐ,=Ð=Ñ>ˆEØ�O‰OÔ/°Ó6Ô7Ø ×'Ñ'¨°©¸Ñ):¸EÀE¹MÈAÑ<MÐ(NÔOØ×#Ñ# V¨e¡^°V¸e±^Ð$DÖEð/	Fô2 ØÜ�H‰HÐ)´·±Ô:Ü�H‰HÐ%¬R¯X©XÔ6Ø×Ñó	
ð 	
r   c           	     ót  — |\  }}|dk  s|dk  rt        d«      ‚t        | «      }|dk(  rTt        g t        j                  dt        j
                  ¬«      t        j                  dt        j
                  ¬«      |«      S | j                  t        j                  ||gt        j
                  ¬«      z   }|dd…df   }|dd…df   }	|| j                  dd…df   z   dz
  }
|	| j                  dd…df   z   dz
  }|dk  |	dk  z  |
|k\  z  ||k\  z  }|j                  «       s9t        t        | j                  «      | j                  j                  «       ||«      S g }g }g }t        |«      D �]ú  }t        ||   «      }t        |	|   «      }t        |
|   «      }t        ||   «      }||   su|j                  | j                  |   «       |j                  t        | j                  |df   «      t        | j                  |df   «      f«       |j                  ||f«       Œ¶t!        d|«      }t!        d|«      }t#        |dz
  |«      }t#        |dz
  |«      }||kD  s||kD  r‹t#        t!        |d«      |dz
  «      }t#        t!        |d«      |dz
  «      }|j                  t%        t        j&                  dt(        ¬«      «      «       |j                  d«       |j                  ||f«       �Œ�| j+                  |«      }|||z
  ||z
  dz   …||z
  ||z
  dz   …f   }|j                  t%        |«      «       |j                  ||z
  dz   ||z
  dz   f«       |j                  ||f«       �Œý t        |t        j                  |t        j
                  ¬«      t        j                  |t        j
                  ¬«      |«      S )aâ  Return a new :class:`CompactMask` with adjusted offsets and image shape.

        Used by :class:`~supervision.detection.tools.inference_slicer.InferenceSlicer`
        to relocate tile-local masks into full-image coordinates without
        materialising the dense ``(N, H, W)`` array.

        Args:
            dx: Pixels to add to every mask's ``x1`` offset.
            dy: Pixels to add to every mask's ``y1`` offset.
            new_image_shape: ``(H, W)`` of the full (destination) image.

        Returns:
            New :class:`CompactMask` with updated offsets and image shape.
            Crops are clipped to stay inside ``new_image_shape``; masks fully
            outside are represented as ``1x1`` all-False crops.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 20, 20), dtype=bool)
            >>> xyxy = np.array([[5, 5, 15, 15]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(20, 20))
            >>> cm2 = cm.with_offset(100, 200, new_image_shape=(400, 400))
            >>> cm2.offsets[0].tolist()
            [105, 205]

            ```
        r   ú0new_image_shape must contain positive dimensionsrt   r(   Nr
   ru   )r½   r   rf   r   r*   rF   ri   rE   rg   rÃ   r«   rj   r˜   r   r   r   r[   r   r   rv   r2   rb   )rm   ÚdxÚdyÚnew_image_shaper`   ra   r|   r³   Úx1sÚy1sÚx2sÚy2sÚ
needs_clipÚout_rlesÚout_crop_shapesÚout_offsets_listr   r€   r�   r‚   rƒ   Úix1Úiy1Úix2Úiy2Úanchor_xÚanchor_yrb   Úclippeds                                r   Úwith_offsetzCompactMask.with_offset+  s›  € ðF '‰ˆˆuØ�AŠ:˜ !šÜÐOÓPÐPä˜“Iˆ	Ø˜Š>ÜØÜ—‘˜¤r§x¡xÔ0Ü—‘˜¤r§x¡xÔ0Øó	ð ð .2¯]©]¼R¿X¹XØ�ˆHœBŸH™Hô>
ñ .
ˆð š!˜Q˜$ÑˆØš!˜Q˜$ÑˆØ�D×%Ñ%¢a¨ dÑ+Ñ+¨aÑ/ˆØ�D×%Ñ%¢a¨ dÑ+Ñ+¨aÑ/ˆð �1‰W˜˜q™Ñ! S¨E¡\Ñ2°c¸U±lÑCð 	ð �~‰~ÔäÜ�T—Z‘ZÓ Ø×!Ñ!×&Ñ&Ó(ØØó	ð ð 13ˆØ13ˆØ24Ðä˜iÓ(ó "	0ˆHÜ�S˜‘]Ó#ˆBÜ�S˜‘]Ó#ˆBÜ�S˜‘]Ó#ˆBÜ�S˜‘]Ó#ˆBà˜hÒ'Ø—‘ §
¡
¨8Ñ 4Ô5Ø×&Ñ&ä˜D×-Ñ-¨h¸¨kÑ:Ó;Ü˜D×-Ñ-¨h¸¨kÑ:Ó;ðôð !×'Ñ'¨¨R¨Ô1Øä�a˜“*ˆCÜ�a˜“*ˆCÜ�e˜a‘i Ó$ˆCÜ�e˜a‘i Ó$ˆCà�SŠy˜C #šIÜœs 2 q›z¨5°1©9Ó5�Üœs 2 q›z¨5°1©9Ó5�Ø—‘Ô 3´B·H±H¸VÌ4Ô4PÓ QÔRØ×&Ñ& vÔ.Ø ×'Ñ'¨°8Ð(<Ô=Ùà—9‘9˜XÓ&ˆDØ˜3 ™8 c¨B¡h°¡lÐ2°C¸"±H¸sÀR¹xÈ!¹|Ð4KÐKÑLˆGØ�O‰OÔ/°Ó8Ô9Ø×"Ñ" C¨#¡I°¡M°3¸±9¸q±=Ð#AÔBØ×#Ñ# S¨# JÖ/ðE"	0ôH ØÜ�H‰H�_¬B¯H©HÔ5Ü�H‰HÐ%¬R¯X©XÔ6Øó	
ð 	
r   c                ó†	  — ddl m} |\  }}|dk  s|dk  rt        d«      ‚||f| j                  k(  rQt	        t        | j                  «      | j                  j                  «       | j                  j                  «       |«      S t        | «      dk(  rTt	        g t        j                  dt        j                  ¬«      t        j                  dt        j                  ¬«      |«      S | j                  \  }}||z  }||z  }| j                  dd…df   j                  t        j                  «      }	| j                  dd…df   j                  t        j                  «      }
|	| j                  dd…df   z   dz
  }|
| j                  dd…df   z   dz
  }t        j                   t        j"                  |	|z  «      d|dz
  «      j                  t        j                  «      }t        j                   t        j"                  |
|z  «      d|dz
  «      j                  t        j                  «      }t        j                   t        j"                  ||z  «      d|dz
  «      j                  t        j                  «      }t        j                   t        j"                  ||z  «      d|dz
  «      j                  t        j                  «      }t        j$                  d||z
  dz   «      j                  t        j                  «      }t        j$                  d||z
  dz   «      j                  t        j                  «      }| j                  dd…df   }| j                  dd…df   }t'        t        | «      «      D �cg c]F  }| j                  |   t)        ||   «      t)        ||   «      t)        ||   «      t)        ||   «      f‘ŒH }}t        | «      }|t*        k\  rO |t-        |t/        j0                  «       xs d«      ¬	«      5 }t        |j3                  d
„ |«      «      }ddd«       n|D �cg c]
  }t5        |Ž ‘Œ }}t        j6                  ||f«      j                  t        j                  «      }t        j6                  ||f«      j                  t        j                  «      }t	        |||«      S c c}w # 1 sw Y   Œ„xY wc c}w )u4  Return a new CompactMask scaled to a different image resolution.

        Each crop mask is resized with nearest-neighbour interpolation.
        Sparse masks use direct RLE arithmetic (:func:`_rle_resize`); dense
        masks fall back to ``cv2.resize(INTER_NEAREST)``.  Offsets and crop
        dimensions are scaled proportionally to the new image size.

        Performance notes:

        * Coordinate arithmetic is fully vectorised (no Python loop over N).
        * All-``False`` crops skip decode/resize entirely.
        * For N >= 8, resize runs in a thread pool â€” NumPy and OpenCV
          release the GIL so crops execute in parallel on multi-core CPUs.

        Args:
            new_image_shape: ``(H, W)`` of the target image.

        Returns:
            New :class:`CompactMask` with updated ``image_shape``, scaled
            offsets, scaled crop shapes, and re-encoded RLE crops.

        Raises:
            ValueError: If any dimension in *new_image_shape* is ``<= 0``.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> from supervision.detection.compact_mask import CompactMask
            >>> masks = np.zeros((1, 100, 100), dtype=bool)
            >>> masks[0, 20:40, 30:60] = True
            >>> xyxy = np.array([[30, 20, 59, 39]], dtype=np.float32)
            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(100, 100))
            >>> small = cm.resize((50, 50))
            >>> small.shape
            (1, 50, 50)
            >>> small.offsets[0].tolist()
            [15, 10]

            ```
        r   )ÚThreadPoolExecutorrÓ   rt   r(   Nr
   r—   )Úmax_workersc                ó   — t        | Ž S rl   )rd   )Úas    r   ú<lambda>z$CompactMask.resize.<locals>.<lambda>  s   € ¤|°QÐ'7€ r   )Úconcurrent.futuresrè   r½   rh   rf   r«   rj   rg   r˜   ri   r   r   r*   rF   rN   Úfloat64ÚclipÚroundÚmaximumr   r   rW   r   ÚosÚ	cpu_countÚmaprd   r™   )rm   rÖ   rè   r`   ra   rz   r{   ÚsxÚsyr×   rØ   rÙ   rÚ   Únew_x1sÚnew_y1sÚnew_x2sÚnew_y2sÚnew_crop_wsÚnew_crop_hsÚorig_crop_hsÚorig_crop_wsÚiÚargsÚnÚpoolr±   rë   r²   r³   s                                r   r\   zCompactMask.resize¨  sö  € õR 	:à&‰ˆˆuØ�AŠ:˜ !šÜÐOÓPÐPð
 �5ˆ>˜T×.Ñ.Ò.ÜÜ�T—Z‘ZÓ Ø×!Ñ!×&Ñ&Ó(Ø—‘×"Ñ"Ó$Øó	ð ô ˆt‹9˜Š>ÜØÜ—‘˜¤r§x¡xÔ0Ü—‘˜¤r§x¡xÔ0Øó	ð ð ×(Ñ(‰ˆˆuØ�U‰]ˆØ�U‰]ˆð �m‰mšA˜q˜DÑ!×(Ñ(¬¯©Ó4ˆØ�m‰mšA˜q˜DÑ!×(Ñ(¬¯©Ó4ˆØ�D×%Ñ%¢a¨ dÑ+Ñ+¨aÑ/ˆØ�D×%Ñ%¢a¨ dÑ+Ñ+¨aÑ/ˆä—'‘'œ"Ÿ(™( 3¨¡8Ó,¨a°¸±Ó;×BÑBÄ2Ç8Á8ÓLˆÜ—'‘'œ"Ÿ(™( 3¨¡8Ó,¨a°¸±Ó;×BÑBÄ2Ç8Á8ÓLˆÜ—'‘'œ"Ÿ(™( 3¨¡8Ó,¨a°¸±Ó;×BÑBÄ2Ç8Á8ÓLˆÜ—'‘'œ"Ÿ(™( 3¨¡8Ó,¨a°¸±Ó;×BÑBÄ2Ç8Á8ÓLˆÜ-/¯Z©ZØˆw˜Ñ  1Ñ$ó.
ç
‰&”—‘Ó
ð 	ô .0¯Z©ZØˆw˜Ñ  1Ñ$ó.
ç
‰&”—‘Ó
ð 	ð
 ×(Ñ(ª¨A¨Ñ.ˆØ×(Ñ(ª¨A¨Ñ.ˆô œ3˜t›9Ó%ö	
ð ð —
‘
˜1‘Ü�L ‘OÓ$Ü�L ‘OÓ$Ü�K ‘NÓ#Ü�K ‘NÓ#òð	
ˆð 	
ô �‹IˆØÔ#Ò#Ù#´°A´r·|±|³~Ò7JÈÓ0KÔLð ÐPTÜ8<Ø—H‘HÑ7¸Ó>ó9�÷ð ð
 37Ö7¨Qœ aÒ(Ð7ˆHÐ7äŸ/™/¨;¸Ð*DÓE×LÑLÌRÏXÉXÓVˆÜ—o‘o w°Ð&8Ó9×@Ñ@ÄÇÁÓJˆÜ˜8 _°kÀ?ÓSÐSùò-	
÷ð üò
 8s   Í2AR-Ï<R2Ð&R>Ò2R;)
rn   zlist[npt.NDArray[np.int32]]ro   únpt.NDArray[np.int32]rp   r  rq   útuple[int, int]ÚreturnÚNone)rx   únpt.NDArray[np.bool_]ry   únpt.NDArray[Any]rq   r  r  rf   )r  r  )r�   r   r  r  )r  r   )r  zIterator[npt.NDArray[np.bool_]])r  ztuple[int, int, int])r  r  )r  znp.dtype[Any])r  znpt.NDArray[np.int64]rl   )r    zint | tuple[int, ...] | Noner  znpt.NDArray[Any] | int)r�   z*int | slice | list[Any] | npt.NDArray[Any]r  z#npt.NDArray[np.bool_] | CompactMask)r)   znp.dtype[Any] | Noner  r  )rº   Úobjectr  r2   )r¿   zlist[CompactMask]r  rf   )r  rf   )rÔ   r   rÕ   r   rÖ   r  r  rf   )rÖ   r  r  rf   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__rr   Úclassmethodrˆ   r‹   rb   r�   r’   Úpropertyr”   rp   rš   r)   r�   r   r´   r¶   r»   ÚstaticmethodrÁ   rÑ   ræ   r\   © r   r   rf   rf   …  s‹  „ ñAðF F€Ið
9à)ð
9ð +ð
9ð 'ð	
9ð
 %ð
9ð 
ó
9ð  ðI<à$ðI<ð ðI<ð %ð	I<ð
 
òI<ó ðI<ó^ó@FóBó(!ð
 ò)ó ð)ð* òó ðð* òNó ðNð@ òó ðð( òPó ðPô,.ð:BVà9ðBVð 
-óBVôHó8ð@ ò:Pó ð:PóxM
ðfw
àðw
ð ðw
ð )ð	w
ð
 
ów
ôzrTr   rf   )r   r  r  r   )r   r  r   r   r   r   r  úlist[list[int]])r4   ú	list[int]r5   r   r6   r  r  r  )rG   r  rH   r   r  r  )r   r  r   r   r   r   r7   r   rO   r   r  r  )r   r  r^   r   r_   r   r`   r   ra   r   r  r  )r  Ú
__future__r   rò   Úcollections.abcr   Útypingr   Únumpyr   Únumpy.typingÚnptÚ&supervision.detection.utils.convertersr   r   r   r&   rB   rK   rS   rU   Ú__annotations__rW   rd   rf   r  r   r   ú<module>r     sN  ðò	õ #ã 	Ý $Ý ã Ý ÷ó"ð,LØ	ðLàðLð ðLð ó	Lð^>Øð>àð>ð #ð>ð ó	>ðB5QØ ð5Qàð5Qð ó5QðpQ2Ø	ðQ2àðQ2ð ðQ2ð ð	Q2ð
 ðQ2ð óQ2ðn  $Ð �uÓ #àÐ �SÓ ð-(Ø	ð-(àð-(ð ð-(ð ð	-(ð
 ð-(ð ó-(÷`UTò UTr   