
    hI                    &   S r SSKJr  SSKJr  SSKJrJr  SSKr	SSK
Jr  SSKJrJr  SS	KJrJrJr  / S
QrSr " S S\5      r " S S\5      r\" S5      SS j5       r\" S5            SS j5       rSS jr\" S5       S          S!S jj5       r\" S5       S          S"S jj5       r\" S5      S#S j5       r\" S5      SS j5       r     S$               S%S jjrS&S jrS'S jr SS jr!      S(S jr"      S)S jr#g)*a  Utilities for handling bounding box operations during image augmentation.

This module provides tools for processing bounding boxes in various formats (COCO, Pascal VOC, YOLO),
converting between coordinate systems, normalizing and denormalizing coordinates, filtering
boxes based on visibility and size criteria, and performing transformations on boxes to match
image augmentations. It forms the core functionality for all bounding box-related operations
in the albumentations library.
    )annotations)Sequence)AnyLiteralN)handle_empty_array)MONO_CHANNEL_DIMENSIONS$NUM_BBOXES_COLUMNS_IN_ALBUMENTATIONS   )DataProcessorParams	ShapeType)	
BboxParamsBboxProcessorcheck_bboxes"convert_bboxes_from_albumentations convert_bboxes_to_albumentationsdenormalize_bboxesfilter_bboxesnormalize_bboxesunion_of_bboxes   c                     ^  \ rS rSrSr         S	                   S
U 4S jjjrSU 4S jjr\SS j5       r\SS j5       r	SS jr
SrU =r$ )r   %   a#  Parameters for bounding box transforms.

Args:
    format (Literal["coco", "pascal_voc", "albumentations", "yolo"]): Format of bounding boxes.
        Should be one of:
        - 'coco': [x_min, y_min, width, height], e.g. [97, 12, 150, 200].
        - 'pascal_voc': [x_min, y_min, x_max, y_max], e.g. [97, 12, 247, 212].
        - 'albumentations': like pascal_voc but normalized in [0, 1] range, e.g. [0.2, 0.3, 0.4, 0.5].
        - 'yolo': [x_center, y_center, width, height] normalized in [0, 1] range, e.g. [0.1, 0.2, 0.3, 0.4].

    label_fields (Sequence[str] | None): List of fields that are joined with boxes,
        e.g., ['class_labels', 'scores']. Default: None.

    min_area (float): Minimum area of a bounding box. All bounding boxes whose visible area in pixels is less than
        this value will be removed. Default: 0.0.

    min_visibility (float): Minimum fraction of area for a bounding box to remain this box in the result.
        Should be in [0.0, 1.0] range. Default: 0.0.

    min_width (float): Minimum width of a bounding box in pixels or normalized units. Bounding boxes with width
        less than this value will be removed. Default: 0.0.

    min_height (float): Minimum height of a bounding box in pixels or normalized units. Bounding boxes with height
        less than this value will be removed. Default: 0.0.

    check_each_transform (bool): If True, performs checks for each dual transform. Default: True.

    clip (bool): If True, clips bounding boxes to image boundaries before applying any transform. Default: False.

    filter_invalid_bboxes (bool): If True, filters out invalid bounding boxes (e.g., boxes with negative dimensions
        or boxes where x_max < x_min or y_max < y_min) at the beginning of the pipeline. If clip=True, filtering
        is applied after clipping. Default: False.

    max_accept_ratio (float | None): Maximum allowed aspect ratio for bounding boxes. The aspect ratio is calculated
        as max(width/height, height/width), so it's always >= 1. Boxes with aspect ratio greater than this value
        will be filtered out. For example, if max_accept_ratio=3.0, boxes with width:height or height:width ratios
        greater than 3:1 will be removed. Set to None to disable aspect ratio filtering. Default: None.


Note:
    The processing order for bounding boxes is:
    1. Convert to albumentations format (normalized pascal_voc)
    2. Clip boxes to image boundaries (if clip=True)
    3. Filter invalid boxes (if filter_invalid_bboxes=True)
    4. Apply transformations
    5. Filter boxes based on min_area, min_visibility, min_width, min_height
    6. Convert back to the original format

Examples:
    >>> # Create BboxParams for COCO format with class labels
    >>> bbox_params = BboxParams(
    ...     format='coco',
    ...     label_fields=['class_labels'],
    ...     min_area=1024,
    ...     min_visibility=0.1
    ... )

    >>> # Create BboxParams that clips and filters invalid boxes
    >>> bbox_params = BboxParams(
    ...     format='pascal_voc',
    ...     clip=True,
    ...     filter_invalid_bboxes=True
    ... )
    >>> # Create BboxParams that filters extremely elongated boxes
    >>> bbox_params = BboxParams(
    ...     format='yolo',
    ...     max_accept_ratio=5.0,  # Filter boxes with aspect ratio > 5:1
    ...     clip=True
    ... )

c                   > [         TU ]  X5        X0l        X@l        XPl        X`l        Xpl        Xl        Xl        U
b  U
S:  a  [        S5      eXl
        g )N      ?z]max_accept_ratio must be >= 1.0 when provided, as aspect ratio is calculated as max(w/h, h/w))super__init__min_areamin_visibility	min_width
min_heightcheck_each_transformclipfilter_invalid_bboxes
ValueErrormax_accept_ratio)selfformatlabel_fieldsr   r   r    r!   r"   r#   r$   r&   	__class__s              X/var/www/fran/franai/venv/lib/python3.13/site-packages/albumentations/core/bbox_utils.pyr   BboxParams.__init__n   s^     	. ,"$$8!	%:"',<s,Bo  !1    c           
        > [         TU ]  5       nUR                  U R                  U R                  U R
                  U R                  U R                  U R                  U R                  S.5        U$ )zGet the private dictionary representation of bounding box parameters.

Returns:
    dict[str, Any]: Dictionary containing the bounding box parameters.

)r   r   r    r!   r"   r#   r&   )
r   to_dict_privateupdater   r   r    r!   r"   r#   r&   )r'   datar*   s     r+   r/   BboxParams.to_dict_private   sa     w&( MM"&"5"5!^^"oo(,(A(A		$($9$9
	
 r-   c                    g)zCheck if the bounding box parameters are serializable.

Returns:
    bool: Always returns True as BboxParams is serializable.

T clss    r+   is_serializableBboxParams.is_serializable   s     r-   c                    g)zMGet the full name of the class.

Returns:
    str: The string "BboxParams".

r   r4   r5   s    r+   get_class_fullnameBboxParams.get_class_fullname   s     r-   c                    SU R                    SU R                   SU R                   SU R                   SU R                   SU R
                   SU R                   SU R                   S	3$ )
NzBboxParams(format=z, label_fields=z, min_area=z, min_visibility=z, min_width=z, min_height=z, check_each_transform=z, clip=))r(   r)   r   r   r    r!   r"   r#   r'   s    r+   __repr__BboxParams.__repr__   s}     _T=N=N<O{[_[h[hZi j#223<?O}]a]l]l\m n%%)%>%>$?wtyykQRT	
r-   )r"   r#   r$   r&   r   r!   r   r    )	N        rA   rA   rA   TFFN)r(   z7Literal['coco', 'pascal_voc', 'albumentations', 'yolo']r)   zSequence[Any] | Noner   floatr   rB   r    rB   r!   rB   r"   boolr#   rC   r$   rC   r&   float | None)returndict[str, Any])rE   rC   rE   str)__name__
__module____qualname____firstlineno____doc__r   r/   classmethodr7   r:   r?   __static_attributes____classcell__r*   s   @r+   r   r   %   s    FV .2 #%)&+)-1G1 +1 	1
 1 1 1 #1 1  $1 '1 16*    
 
r-   r   c                     ^  \ rS rSrSrSSU 4S jjjr\SS j5       rSS jrSS jr	 S       SS jjr
SS jrSS	 jrSS
 jrSrU =r$ )r      a  Processor for bounding box transformations.

This class handles the preprocessing and postprocessing of bounding boxes during augmentation pipeline,
including format conversion, validation, clipping, and filtering.

Args:
    params (BboxParams): Parameters that control bounding box processing.
        See BboxParams class for details.
    additional_targets (dict[str, str] | None): Dictionary with additional targets to process.
        Keys are names of additional targets, values are their types.
        For example: {'bbox2': 'bboxes'} will handle 'bbox2' as another bounding box target.
        Default: None.

Note:
    The processing order for bounding boxes is:
    1. Convert to albumentations format (normalized pascal_voc)
    2. Clip boxes to image boundaries (if params.clip=True)
    3. Filter invalid boxes (if params.filter_invalid_bboxes=True)
    4. Apply transformations
    5. Filter boxes based on min_area, min_visibility, min_width, min_height
    6. Convert back to the original format

Examples:
    >>> import albumentations as A
    >>> # Process COCO format bboxes with class labels
    >>> params = A.BboxParams(
    ...     format='coco',
    ...     label_fields=['class_labels'],
    ...     min_area=1024,
    ...     min_visibility=0.1
    ... )
    >>> processor = BboxProcessor(params)
    >>>
    >>> # Process multiple bbox fields
    >>> params = A.BboxParams('pascal_voc')
    >>> processor = BboxProcessor(
    ...     params,
    ...     additional_targets={'bbox2': 'bboxes'}
    ... )

c                $   > [         TU ]  X5        g N)r   r   )r'   paramsadditional_targetsr*   s      r+   r   BboxProcessor.__init__   s    4r-   c                    g)zkReturns the default key for bounding box data in transformations.

Returns:
    str: The string 'bboxes'.

bboxesr4   r>   s    r+   default_data_nameBboxProcessor.default_data_name   s     r-   c                   ^ U R                   R                  (       a<  [        U4S jU R                   R                   5       5      (       d  Sn[        U5      egg)ac  Validates the input bounding box data.

Checks that:
- Bounding boxes have labels (either in the bbox array or in label_fields)
- All specified label_fields exist in the data

Args:
    data (dict[str, Any]): Dict with bounding boxes and optional label fields.

Raises:
    ValueError: If bounding boxes don't have labels or if label_fields are invalid.

c              3  ,   >#    U  H	  oT;   v   M     g 7frU   r4   ).0ir1   s     r+   	<genexpr>2BboxProcessor.ensure_data_valid.<locals>.<genexpr>   s     /\C[aT	C[s   zOYour 'label_fields' are not valid - them must have same names as params in dictN)rV   r)   allr%   )r'   r1   msgs    ` r+   ensure_data_validBboxProcessor.ensure_data_valid   sD     ;;##C/\4;;C[C[/\,\,\cCS/! -]#r-   c           
         U   [        UUU R                  R                  U R                  R                  U R                  R                  U R                  R
                  U R                  R                  S9$ )a  Filter bounding boxes based on size and visibility criteria.

Args:
    data (np.ndarray): Array of bounding boxes in Albumentations format.
    shape (ShapeType): Shape information for validation.

Returns:
    np.ndarray: Filtered bounding boxes that meet the criteria.

)r   r   r    r!   r&   )r   rV   r   r   r    r!   r&   r'   r1   shapes      r+   filterBboxProcessor.filter  s[     	[[));;55kk++{{--![[99
 	
r-   c           	     D   US:X  a  U R                   R                  S:X  a  UnO [        UU R                   R                  USS9nU R                   R                  (       a:  UR                  S:  a*  [
        R                  " USS2SS24   SS5      USS2SS24'   U R                   R                  (       a  [        UUSSSSS	9nU R                  XB5        U$ U R                  X5        U R                   R                  S:X  a  U$ [        XR                   R                  U5      $ )
a#  Converts bounding boxes between formats and applies preprocessing/postprocessing.

Args:
    data (np.ndarray): Array of bounding boxes to process.
    shape (ShapeType): Image shape as dict with height and width keys.
    direction (Literal["to", "from"]): Direction of conversion:
        - "to": Convert from original format to albumentations format
        - "from": Convert from albumentations format to original format
        Default: "to".

Returns:
    np.ndarray: Processed bounding boxes.

Note:
    When direction="to":
    1. Converts to albumentations format
    2. Clips boxes if params.clip=True
    3. Filters invalid boxes if params.filter_invalid_bboxes=True
    4. Validates remaining boxes

    When direction="from":
    1. Validates boxes
    2. Converts back to original format

toalbumentationsFcheck_validityr   N   r
   r   r   r    r!   )
rV   r(   r   r#   sizenpr$   r   checkr   )r'   r1   ri   	directionconverted_datas        r+   check_and_convertBboxProcessor.check_and_convert  s   > {{!!%55!%!AKK&&#(	" {{N$7$7!$;(*q"1"u0Eq!(Lq"1"u% {{00!."#$ " JJ~-!!

4;;!11K1$8J8JERRr-   c                    [        U5        g)zCheck if bounding boxes are valid.

Args:
    data (np.ndarray): Array of bounding boxes to validate.
    shape (ShapeType): Shape to check against.

N)r   rh   s      r+   ru   BboxProcessor.check[  s     	Tr-   c           	     z    [         R                  " [        XR                  R                  USS9UR
                  S9$ )a  Convert bounding boxes from internal Albumentations format to the specified format.

Args:
    data (np.ndarray): Bounding boxes in Albumentations format.
    shape (ShapeType): Shape information for validation.

Returns:
    np.ndarray: Converted bounding boxes in the target format.

Tro   dtype)rt   arrayr   rV   r(   r~   rh   s      r+   convert_from_albumentations)BboxProcessor.convert_from_albumentationse  s3     xx.t[[5G5G_cd**
 	
r-   c           	         U R                   R                  (       a9  [        XR                   R                  USS9n[	        X2SSSSS9n[        U5        U$ [        XR                   R                  USS9$ )a  Convert bounding boxes from the specified format to internal Albumentations format.

Args:
    data (np.ndarray): Bounding boxes in source format.
    shape (ShapeType): Shape information for validation.

Returns:
    np.ndarray: Converted bounding boxes in Albumentations format.

Fro   r   rr   T)rV   r#   r   r(   r   r   )r'   r1   ri   data_nps       r+   convert_to_albumentations'BboxProcessor.convert_to_albumentationsu  sf     ;;6t[[=O=OQVglmG#GQq\]jklG!N/kk6H6H%`deer-   r4   rU   )rV   r   rW   zdict[str, str] | NonerG   )r1   rF   rE   None)r1   
np.ndarrayri   r   rE   r   )rm   )r1   r   ri   r   rv   zLiteral['to', 'from']rE   r   )r1   r   ri   r   rE   r   )rI   rJ   rK   rL   rM   r   propertyr[   re   rj   rx   ru   r   r   rO   rP   rQ   s   @r+   r   r      s}    (T5 5  "$
4 ,0	?S?S ?S )	?S
 
?SB
 f fr-   r   rZ   c                    [        U[        5      (       a  USS u  p#O	US   US   p2U R                  5       R                  [        5      nUSS2SS/4==   U-  ss'   USS2SS/4==   U-  ss'   U$ )a*  Normalize array of bounding boxes.

Args:
    bboxes (np.ndarray): Denormalized bounding boxes `[(x_min, y_min, x_max, y_max, ...)]`.
    shape (ShapeType | tuple[int, int]): Image shape `(height, width)`.

Returns:
    np.ndarray: Normalized bounding boxes `[(x_min, y_min, x_max, y_max, ...)]`.

N   heightwidthr   r
      )
isinstancetuplecopyastyperB   )rZ   ri   rowscols
normalizeds        r+   r   r     s{     %2AY
d8_eGnd%%e,Jq1a&yT!q1a&yT!r-   c                    [        U[        5      (       a
  US   US   4O	US   US   4nU [        R                  " / UQUQS/U R                  S   S-
  -  Q[
        S9-  $ )a,  Denormalize array of bounding boxes.

Args:
    bboxes (np.ndarray): Normalized bounding boxes `[(x_min, y_min, x_max, y_max, ...)]`.
    shape (ShapeType | tuple[int, int]): Image shape `(height, width)`.

Returns:
    np.ndarray: Denormalized bounding boxes `[(x_min, y_min, x_max, y_max, ...)]`.

r
   r   r   r   rq   r}   )r   r   rt   r   ri   rB   )rZ   ri   scale_factorss      r+   r   r     st     -7ue,D,DU1XuQx(5QX>[`ai[jJkM BHH[}[}[sfllSToXYFY?Z[chiiir-   c                    [        U 5      S:X  a#  [        R                  " / [        R                  S9$ US   US   p2U SS2S4   U SS2S4   -
  U-  nU SS2S4   U SS2S4   -
  U-  nXE-  $ )	ao  Calculate areas for multiple bounding boxes.
This function computes the areas of bounding boxes given their normalized coordinates
and the dimensions of the image they belong to. The bounding boxes are expected to be
in the format [x_min, y_min, x_max, y_max] with normalized coordinates (0 to 1).

Args:
    bboxes (np.ndarray): A numpy array of shape (N, 4+) where N is the number of bounding boxes.
                         Each row contains [x_min, y_min, x_max, y_max] in normalized coordinates.
                         Additional columns beyond the first 4 are ignored.
    shape (ShapeType): A tuple containing the height and width of the image (height, width).

Returns:
    np.ndarray: A 1D numpy array of shape (N,) containing the areas of the bounding boxes in pixels.
                Returns an empty array if the input `bboxes` is empty.

Note:
    - The function assumes that the input bounding boxes are valid (i.e., x_max > x_min and y_max > y_min).
      Invalid bounding boxes may result in negative areas.
    - The function preserves the input array and creates a copy for internal calculations.
    - The returned areas are in pixel units, not normalized.

Example:
    >>> bboxes = np.array([[0.1, 0.1, 0.5, 0.5], [0.2, 0.2, 0.8, 0.8]])
    >>> image_shape = (100, 100)
    >>> areas = calculate_bbox_areas(bboxes, image_shape)
    >>> print(areas)
    [1600. 3600.]

r   r}   r   r   Nr   r   r
   )lenrt   r   float32)rZ   ri   r   r   widthsheightss         r+   calculate_bbox_areas_in_pixelsr     s    < 6{axx"**-- (OU7^E QTlVAqD\)U2Fad|fQTl*f4Gr-   c                   US;  a  [        SU S35      eU R                  5       R                  [        R                  5      n [        R
                  " U 5      nU SS2SS24   USS2SS24'   US:X  aU  U SS2S4   USS2S4'   U SS2S4   USS2S4'   U SS2S4   U SS2S	4   -   USS2S	4'   U SS2S4   U SS2S
4   -   USS2S
4'   OUS:X  a  U(       aD  [        R                  " U SS2SS24   S:*  U SS2SS24   S:  -  5      (       a  [        SU  35      eU SS2S	4   S	-  U SS2S
4   S	-  peU SS2S4   U-
  USS2S4'   U SS2S4   U-
  USS2S4'   U SS2S4   U-   USS2S	4'   U SS2S4   U-   USS2S
4'   OU SS2SS24   USS2SS24'   US:w  a  [        USS2SS24   U5      USS2SS24'   U(       a  [        U5        U$ )a2  Convert bounding boxes from a specified format to the format used by albumentations:
normalized coordinates of top-left and bottom-right corners of the bounding box in the form of
`(x_min, y_min, x_max, y_max)` e.g. `(0.15, 0.27, 0.67, 0.5)`.

Args:
    bboxes (np.ndarray): A numpy array of bounding boxes with shape (num_bboxes, 4+).
    source_format (Literal["coco", "pascal_voc", "yolo"]): Format of the input bounding boxes.
    shape (ShapeType): Image shape (height, width).
    check_validity (bool): Check if all boxes are valid boxes.

Returns:
    np.ndarray: An array of bounding boxes in albumentations format with shape (num_bboxes, 4+).

Raises:
    ValueError: If `source_format` is not 'coco', 'pascal_voc', or 'yolo'.
    ValueError: If in YOLO format, any coordinates are not in the range (0, 1].

   cocoyolo
pascal_voczUnknown source_format 8. Supported formats are: 'coco', 'pascal_voc' and 'yolo'Nrq   r   r   r
   r   r   r   zFIn YOLO format all coordinates must be float and in range (0, 1], got )	r%   r   r   rt   r   
zeros_likeanyr   r   )rZ   source_formatri   rp   converted_bboxesw_halfh_halfs          r+   r   r     s2   2 ::$]O3kl
 	
 [[]!!"**-F}}V,$QUmQU!'1A!'1A!'1q!t!<A!'1q!t!<A	&	 bfffQUmq&8VArrE]Q=N%OPPeflemnoo1)6!Q$<!+;!'1!6A!'1!6A!'1!6A!'1!6A"(BQB-BQB"23CArrE3JE"RBQB%&r-   c                   US;  a  [        SU S35      eU(       a  [        U 5        [        R                  " U 5      nU SS2SS24   USS2SS24'   US:w  a  [	        U SS2SS24   U5      O
U SS2SS24   nUS:X  aV  USS2S4   USS2S4'   USS2S	4   USS2S	4'   USS2S
4   USS2S4   -
  USS2S
4'   USS2S4   USS2S	4   -
  USS2S4'   U$ US:X  ap  USS2S4   USS2S
4   -   S
-  USS2S4'   USS2S	4   USS2S4   -   S
-  USS2S	4'   USS2S
4   USS2S4   -
  USS2S
4'   USS2S4   USS2S	4   -
  USS2S4'   U$ XTSS2SS24'   U$ )a  Convert bounding boxes from the format used by albumentations to a specified format.

Args:
    bboxes (np.ndarray): A numpy array of albumentations bounding boxes with shape (num_bboxes, 4+).
            The first 4 columns are [x_min, y_min, x_max, y_max].
    target_format (Literal["coco", "pascal_voc", "yolo"]): Required format of the output bounding boxes.
    shape (ShapeType): Image shape (height, width).
    check_validity (bool): Check if all boxes are valid boxes.

Returns:
    np.ndarray: An array of bounding boxes in the target format with shape (num_bboxes, 4+).

Raises:
    ValueError: If `target_format` is not 'coco', 'pascal_voc' or 'yolo'.

r   zUnknown target_format r   Nrq   r   r   r   r
   r   r   )r%   r   rt   r   r   )rZ   target_formatri   rp   r   denormalized_bboxess         r+   r   r     s   . ::$]O3kl
 	
 V}}V,$QUmQUFSW]F],VArrE]EBcijkmonomojocp!4QT!:A!4QT!:A!4QT!:=PQRTUQU=V!VA!4QT!:=PQRTUQU=V!VA  
&	 "5ad";>QRSUVRV>W"W[\!\A"5ad";>QRSUVRV>W"W[\!\A!4QT!:=PQRTUQU=V!VA!4QT!:=PQRTUQU=V!VA  #6BQBr-   c           	     :   U SS2SS24   S:  U SS2SS24   S:*  -  n[         R                  " U SS2SS24   S5      n[         R                  " U SS2SS24   S5      nX-  U-  n[         R                  " U5      (       d  [         R                  " [         R                  " USS9) 5      S   S   nX   n/ SQ[         R                  " XE   ) 5      S   S      nU[         R                  " XE   ) 5      S   S      n[	        SU SU S	U S
35      eU SS2S4   U SS2S4   :  U SS2S4   U SS2S4   :  -  n	[         R                  " U	5      (       dK  [         R                  " U	) 5      S   S   nX   nUS   US   ::  a  [	        SU S
35      e[	        SU S
35      eg)zCheck if bounding boxes are valid.

Args:
    bboxes (np.ndarray): A numpy array of bounding boxes with shape (num_bboxes, 4+).

Raises:
    ValueError: If any bounding box is invalid.

Nrq   r   r
   axis)x_miny_minx_maxy_maxz	Expected z
 for bbox z$ to be in the range [0.0, 1.0], got .r   r   z.x_max is less than or equal to x_min for bbox z.y_max is less than or equal to y_min for bbox )rt   iscloserc   wherer%   )
rZ   in_rangeclose_to_zeroclose_to_onevalid_rangeinvalid_idxinvalid_bboxinvalid_coordinvalid_valuevalid_orders
             r+   r   r   P  s    q"1"u"va!e}'9:HJJva!e}a0M::fQUmQ/L*\9K66+hh{ ;;<Q?B*<RXX{G_F_=`ab=cde=fg$RXX{/G.G%H%KA%NOj>bcpbqqrs
 	

 !Q$<&A,.6!Q$<&A,3NOK66+hh|,Q/2*?l1o-Ml^[\]^^I,WXYZZ r-   c           	        US   US   p2[        X5      n[        R                  " USS2SS/4   SX4SS2SS/4   S9USS2SS/4'   [        R                  " USS2SS/4   SX$SS2SS/4   S9USS2SS/4'   [        XA5      $ )	a  Clip bounding boxes to the image shape.

Args:
    bboxes (np.ndarray): A numpy array of bounding boxes with shape (num_bboxes, 4+).
    shape (ShapeType): The shape of the image/volume:
                       - For 2D: {'height': int, 'width': int}
                       - For 3D: {'height': int, 'width': int, 'depth': int}

Returns:
    np.ndarray: A numpy array of bounding boxes with shape (num_bboxes, 4+).

r   r   Nr   r   )outr
   r   )r   rt   r#   r   )rZ   ri   r   r   denorm_bboxess        r+   clip_bboxesr   v  s     (OU7^E 'v5M&  "ww}QAY'?E]^abde`f]fOghM!aV)!ww}QAY'?F^_bcefag^gPhiM!aV) M11r-   c                   Sn[        U 5      S:X  a3  [        R                  " / [        R                  S9R	                  SS5      $ [        X5      n[        X5      n	[        X5      n
[        U	SS2SS24   U5      nUSS2S4   USS2S4   -
  nUSS2S4   USS2S4   -
  nUb&  [        R                  " XU-   -  XU-   -  5      nX:*  nO[        R                  " U[        S9nX:  XU-
  :  -  XU-   -  U:  -  XU-
  :  -  XU-
  :  -  U-  nU	U   n[        U5      S:X  a3  [        R                  " / [        R                  S9R	                  SS5      $ U$ )	a"  Remove bounding boxes that either lie outside of the visible area by more than min_visibility
or whose area in pixels is under the threshold set by `min_area`. Also crops boxes to final image size.

Args:
    bboxes (np.ndarray): A numpy array of bounding boxes with shape (num_bboxes, 4+).
    shape (ShapeType): The shape of the image/volume:
                       - For 2D: {'height': int, 'width': int}
                       - For 3D: {'height': int, 'width': int, 'depth': int}
    min_area (float): Minimum area of a bounding box in pixels. Default: 0.0.
    min_visibility (float): Minimum fraction of area for a bounding box to remain. Default: 0.0.
    min_width (float): Minimum width of a bounding box in pixels. Default: 0.0.
    min_height (float): Minimum height of a bounding box in pixels. Default: 0.0.
    max_accept_ratio (float | None): Maximum allowed aspect ratio, calculated as max(width/height, height/width).
        Boxes with higher ratios will be filtered out. Default: None.

Returns:
    np.ndarray: Filtered bounding boxes.

gHz>r   r}   rq   Nr   r   r
   )r   rt   r   r   reshaper   r   r   maximum	ones_likerC   )rZ   ri   r   r   r    r!   r&   epsilondenormalized_box_areasclipped_bboxesclipped_box_areasr   clipped_widthsclipped_heightsaspect_ratiosvalid_ratiosmaskfiltered_bboxess                     r+   r   r     s   8 G
6{axx"**-55a;; <FJ !/N 7~M -^ArrE-BEJ(A.1DQT1JJN)!Q$/2Ead2KKO #

7878
 %8||$:$G 
 	*7 22	4 @A^S	U 00	2 722		4
 	 	 %T*O;>;OST;T288Bbjj)11!Q7iZiir-   c                   U R                   (       d  gUS:X  a  gU R                  S   S:X  a  U S   SS $ Sn[        R                  " U SS2SS24   SS9u  p4[        R                  " U SS2SS24   SS9u  pVXS-
  nXd-
  nXq-  S-  n	X-  S-  n
X9-  nXJ-  nXY-  nXj-  n[        XS-
  5      U:  d  [        Xd-
  5      U:  a  g[        R                  " X4XV/[        R                  S	9$ )
a  Calculate union of bounding boxes. Boxes could be in albumentations or Pascal Voc format.

Args:
    bboxes (np.ndarray): List of bounding boxes
    erosion_rate (float): How much each bounding box can be shrunk, useful for erosive cropping.
        Set this in range [0, 1]. 0 will not be erosive at all, 1.0 can make any bbox lose its volume.

Returns:
    np.ndarray | None: A bounding box `(x_min, y_min, x_max, y_max)` or None if no bboxes are given or if
                the bounding boxes become invalid after erosion.

Nr
   r   rq   gư>r   r   g      ?r}   )rs   ri   rt   minmaxabsr   r   )rZ   erosion_rater   r   r   r   r   r   r   	erosion_x	erosion_ys              r+   r   r     s     ;;q||A!ay!}G66&BQB-a0LE66&AaC.q1LEME]F$s*I%+I	E	E	E	E
5=G#s5='9G'C88U50

CCr-   c                x   [        U R                  5      [        :X  a  U [        R                  S4   n [        R
                  " U SS9n[        R
                  " U SS9n[        R                  " U R                  S   S4[        R                  S9n[        [        X5      5       H  u  nu  pV[        R
                  " U5      (       a  [        R
                  " U5      (       d  / SQX4'   MF  [        R                  " U5      S   SS	/   u  px[        R                  " U5      S   SS	/   u  pXU
S-   US-   /X4'   M     U$ )
ao  Create bounding boxes from binary masks (fast version)

Args:
    masks (np.ndarray): Binary masks of shape (H, W) or (N, H, W) where N is the number of masks,
                       and H, W are the height and width of each mask.

Returns:
    np.ndarray: An array of bounding boxes with shape (N, 4), where each row is
               (x_min, y_min, x_max, y_max).

.r   r   r
   r   rq   r}   )r   r   r   r   )r   ri   r   rt   newaxisr   zerosint32	enumeratezipr   )masksr   r   rZ   r`   rowcolr   r   r   r   s              r+   bboxes_from_masksr     s     5;;22bjj#o&66%a D66%a DXXu{{1~q):F"3t?3:Cvvc{{"&&++(FI88C=+QG4LE88C=+QG4LEuqy%!)<FI 4 Mr-   c                v   [        U[        5      (       a
  US   US   p2OUSS u  p#[        R                  " [	        U 5      X#4[        R
                  S9n[        R                  SU2SU24   u  pV[        U SS2SS24   R                  [        5      5       H  u  nu  ppX:*  Xj:  -  X:*  -  X[:  -  XG'   M      U$ )a  Convert bounding boxes to masks.

Args:
    bboxes (np.ndarray): A numpy array of bounding boxes with shape (num_bboxes, 4+).
    shape (ShapeType | tuple[int, int]): Image shape (height, width).

Returns:
    np.ndarray: A numpy array of masks with shape (num_bboxes, height, width).

r   r   Nr   r}   rq   )
r   dictrt   r   r   uint8ogridr   r   int)rZ   ri   r   r   r   yxr`   r   r   r   r   s               r+   masks_from_bboxesr   7  s     %hwbq	HHc&k61BE88GVGVeVO$DA+4VArrE]5I5I#5N+O''E%J19-<	J ,P Lr-   c                   USS u  p#[        U 5      n[        R                  " X#U4[        R                  S9n[	        U 5       H  u  pg[        [        USS 5      u  pp[        S[        US-
  U5      5      n[        S[        US-
  U
5      5      n
[        S[        US-
  U	5      5      n	[        S[        US-
  U5      5      nSXYUS-   2XS-   2U4'   M     U$ )a3  Convert bounding boxes to a single mask.

Args:
    bboxes (np.ndarray): A numpy array of bounding boxes with shape (num_bboxes, 4+).
    image_shape (tuple[int, int]): Image shape (height, width).

Returns:
    np.ndarray: A numpy array of shape (height, width) with 1s where any bounding box is present.

Nr   r}   rq   r   r
   )	r   rt   r   r   r   maproundr   r   )rZ   image_shaper   r   	num_boxes
bbox_masksidxboxr   r   r   r   s               r+   bboxes_to_maskr   P  s      OMFFI 6)4BHHEJ f%%(BQ%8"eAs519e,-As519e,-As6A:u-.As6A:u-.@A
519$eai&7<= & r-   c                   U R                   S   n/ nU R                   S   nUS:X  a.  [        R                  " SUR                   S   4UR                  S9$ [	        U5       H  nU SU4   n[        R
                  " U5      (       ak  [        R                  " U5      u  pgUR                  5       UR                  5       pUR                  5       UR                  5       pUR                  XX/5        M  UR                  XSS24   5        M     [        R                  " U5      nUR                   S   [        :  a   [        R                  " X1SS2SS24   /5      $ U$ )a1  Convert masks back to bounding boxes.

Args:
    masks (np.ndarray): A numpy array of masks with shape (num_masks, height, width).
    original_bboxes (np.ndarray): Original bounding boxes with shape (num_bboxes, 4+).

Returns:
    np.ndarray: A numpy array of bounding boxes with shape (num_masks, 4+).

r   r   r
   r}   .Nrq   )ri   rt   r   r~   ranger   r   r   r   appendr   r	   column_stack)r   original_bboxesr   
new_bboxesr   r   y_coordsx_coordsr   r   r   r   s               r+   mask_to_bboxesr   p  s/    BIJBIA~xxO11!45_=R=RSSYS#X66$<<!#$H#<<>8<<>5#<<>8<<>5uU:; o2A2g67   *%J   #&JJ 	QU%;<= r-   )rZ   r   ri   zShapeType | tuple[int, int]rE   r   )rZ   r   ri   r   rE   r   )F)
rZ   r   r   %Literal['coco', 'pascal_voc', 'yolo']ri   r   rp   rC   rE   r   )
rZ   r   r   r   ri   r   rp   rC   rE   r   )rZ   r   rE   r   )rA   rA   r   r   N)rZ   r   ri   r   r   rB   r   rB   r    rB   r!   rB   r&   rD   rE   r   )rZ   r   r   rB   rE   znp.ndarray | None)r   r   rE   r   )rZ   r   r   ztuple[int, int]rE   r   )r   r   r   r   rE   r   )$rM   
__future__r   collections.abcr   typingr   r   numpyrt   "albumentations.augmentations.utilsr   $albumentations.core.type_definitionsr   r	   utilsr   r   r   __all__BBOX_WITH_LABEL_SHAPEr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r4   r-   r+   <module>r     s@   # $   A n 3 3
  R
 R
jLfM Lf^ H , Hjj&j j j((V H
 !	8888 8 	8
 8 8v H
 !	0080 0 	0
 0 0f H"[ "[J H'2 '2Z %)GjGjGj Gj 	Gj
 Gj Gj #Gj GjT)DX@2  @((( (r-   