
    hL                        S r SSKJr  SSKrSSKJr  SSKJrJrJ	r	J
r
  SSKrSSKrSSKJrJr  SSKJr  SSKJr  SS	KJrJrJrJr  SS
KJr  SSKJrJr  SSK J!r!J"r"  SSK#J$r$J%r%  SS/r& " S S\"5      r' " S S\"5      r(g)ae  Transforms that combine multiple images and their associated annotations.

This module contains transformations that take multiple input sources (e.g., a primary image
and additional images provided via metadata) and combine them into a single output.
Examples include overlaying elements (`OverlayElements`) or creating complex compositions
like `Mosaic`.
    )annotationsN)deepcopy)	AnnotatedAnyLiteralcast)AfterValidatormodel_validator)Self)
functional)BboxProcessorcheck_bboxesdenormalize_bboxesfilter_bboxes)KeypointsProcessor)check_range_boundsnondecreasing)BaseTransformInitSchemaDualTransform)LENGTH_RAW_BBOXTargetsMosaicOverlayElementsc                     ^  \ rS rSrSr\R                  \R                  4r " S S\	5      r
  S   SU 4S jjjr\SS j5       r\        SS j5       rSS jr        SS	 jr        SS
 jrSrU =r$ )r      a;  Apply overlay elements such as images and masks onto an input image. This transformation can be used to add
various objects (e.g., stickers, logos) to images with optional masks and bounding boxes for better placement
control.

Args:
    metadata_key (str): Additional target key for metadata. Default `overlay_metadata`.
    p (float): Probability of applying the transformation. Default: 0.5.

Possible Metadata Fields:
    - image (np.ndarray): The overlay image to be applied. This is a required field.
    - bbox (list[int]): The bounding box specifying the region where the overlay should be applied. It should
                        contain four floats: [y_min, x_min, y_max, x_max]. If `label_id` is provided, it should
                        be appended as the fifth element in the bbox. BBox should be in Albumentations format,
                        that is the same as normalized Pascal VOC format
                        [x_min / width, y_min / height, x_max / width, y_max / height]
    - mask (np.ndarray): An optional mask that defines the non-rectangular region of the overlay image. If not
                         provided, the entire overlay image is used.
    - mask_id (int): An optional identifier for the mask. If provided, the regions specified by the mask will
                     be labeled with this identifier in the output mask.

Targets:
    image, mask

Image types:
    uint8, float32

References:
    doc-augmentation: https://github.com/danaaubakirova/doc-augmentation

Examples:
    >>> import numpy as np
    >>> import albumentations as A
    >>> import cv2
    >>>
    >>> # Prepare primary data (base image and mask)
    >>> image = np.zeros((300, 300, 3), dtype=np.uint8)
    >>> mask = np.zeros((300, 300), dtype=np.uint8)
    >>>
    >>> # 1. Create a simple overlay image (a red square)
    >>> overlay_image1 = np.zeros((50, 50, 3), dtype=np.uint8)
    >>> overlay_image1[:, :, 0] = 255  # Red color
    >>>
    >>> # 2. Create another overlay with a mask (a blue circle with transparency)
    >>> overlay_image2 = np.zeros((80, 80, 3), dtype=np.uint8)
    >>> overlay_image2[:, :, 2] = 255  # Blue color
    >>> overlay_mask2 = np.zeros((80, 80), dtype=np.uint8)
    >>> # Create a circular mask
    >>> center = (40, 40)
    >>> radius = 30
    >>> for i in range(80):
    ...     for j in range(80):
    ...         if (i - center[0])**2 + (j - center[1])**2 < radius**2:
    ...             overlay_mask2[i, j] = 255
    >>>
    >>> # 3. Create an overlay with both bbox and mask_id
    >>> overlay_image3 = np.zeros((60, 120, 3), dtype=np.uint8)
    >>> overlay_image3[:, :, 1] = 255  # Green color
    >>> # Create a rectangular mask with rounded corners
    >>> overlay_mask3 = np.zeros((60, 120), dtype=np.uint8)
    >>> cv2.rectangle(overlay_mask3, (10, 10), (110, 50), 255, -1)
    >>>
    >>> # Create the metadata list - each item is a dictionary with overlay information
    >>> overlay_metadata = [
    ...     {
    ...         'image': overlay_image1,
    ...         # No bbox provided - will be placed randomly
    ...     },
    ...     {
    ...         'image': overlay_image2,
    ...         'bbox': [0.6, 0.1, 0.9, 0.4],  # Normalized coordinates [x_min, y_min, x_max, y_max]
    ...         'mask': overlay_mask2,
    ...         'mask_id': 1  # This overlay will update the mask with id 1
    ...     },
    ...     {
    ...         'image': overlay_image3,
    ...         'bbox': [0.1, 0.7, 0.5, 0.9],  # Bottom left placement
    ...         'mask': overlay_mask3,
    ...         'mask_id': 2  # This overlay will update the mask with id 2
    ...     }
    ... ]
    >>>
    >>> # Create the transform
    >>> transform = A.Compose([
    ...     A.OverlayElements(p=1.0),
    ... ])
    >>>
    >>> # Apply the transform
    >>> result = transform(
    ...     image=image,
    ...     mask=mask,
    ...     overlay_metadata=overlay_metadata  # Pass metadata using the default key
    ... )
    >>>
    >>> # Get results with overlays applied
    >>> result_image = result['image']  # Image with the three overlays applied
    >>> result_mask = result['mask']    # Mask with regions labeled using the mask_id values
    >>>
    >>> # Let's verify the mask contains the specified mask_id values
    >>> has_mask_id_1 = np.any(result_mask == 1)  # Should be True
    >>> has_mask_id_2 = np.any(result_mask == 2)  # Should be True

c                       \ rS rSr% S\S'   Srg)OverlayElements.InitSchema   strmetadata_key N)__name__
__module____qualname____firstlineno____annotations____static_attributes__r!       h/var/www/fran/franai/venv/lib/python3.13/site-packages/albumentations/augmentations/mixing/transforms.py
InitSchemar      s    r(   r*   c                ,   > [         TU ]  US9  Xl        g N)p)super__init__r    )selfr    r-   	__class__s      r)   r/   OverlayElements.__init__   s    
 	1(r(   c                    U R                   /$ zGet list of targets that should be passed as parameters to transforms.

Returns:
    list[str]: List containing the metadata key name

r    r0   s    r)   targets_as_params!OverlayElements.targets_as_params        !!""r(   c                   U S   nUR                   SS u  pEUSS u  pgSU ;   Ga   U S   n[        R                  " U/5      n	[        U	5        [	        XSS 5      S   n
S U
SS  5       u  ppSU ;   a0  U S   n[
        R                  " XU-
  X-
  4[
        R                  S	9nO)[        R                  " X-
  X-
  4[        R                  S
9n[
        R                  " X=U-
  X-
  4[
        R                  S	9nX4n[        U5      [        :X  a  SU ;   a	  XXU S   /nOXX/USS Q7nOXd:  d  Xu:  a6  [
        R                  " X7U4[
        R                  S	9nUR                   SS u  pESU ;   a  U S   O"[        R                  " U[        R                  S
9nXu-
  nXd-
  nUR                  SU5      nUR                  SU5      nUU4nUUUU-   UU-   /nSU ;   a	  / UQU S   PnUUUUS.nSU ;   a  U S   US'   U$ )a  Process overlay metadata to prepare for application.

Args:
    metadata (dict[str, Any]): Dictionary containing overlay data such as image, mask, bbox
    img_shape (tuple[int, int]): Shape of the target image as (height, width)
    random_state (random.Random): Random state object for reproducible randomness

Returns:
    dict[str, Any]: Processed overlay data including resized overlay image, mask,
                    offset coordinates, and bounding box information

imageN   bboxr   c              3  8   #    U  H  n[        U5      v   M     g 7fN)int).0xs     r)   	<genexpr>6OverlayElements.preprocess_metadata.<locals>.<genexpr>   s     )P:OQ#a&&:Os      mask)interpolationdtypebbox_id)overlay_imageoverlay_maskoffsetr=   mask_id)shapenparrayr   r   cv2resizeINTER_NEARESTonesuint8
INTER_AREAlenr   	ones_likerandint)metadata	img_shaperandom_staterK   overlay_heightoverlay_widthimage_heightimage_widthr=   bbox_npdenormalized_bboxx_miny_minx_maxy_maxrF   rM   max_x_offsetmax_y_offsetoffset_xoffset_yresults                         r)   preprocess_metadata#OverlayElements.preprocess_metadata   sJ   $ !)(5(;(;BQ(?%$-bqM!XF#Dhhv&G! 27bqM J1 M)P:KBQ:O)P&E%!'zz$(FVYVgVghwwu}=RXXNJJ}u}em6TdgdrdrsM^F4yO+	X0EeHY4GHe>T!"X>,0K #

=:Ueheses t0=0C0CBQ0G-'-'98F#r||Macaiai?jD&6L'8L#++A|<H#++A|<H)F =(>)	D H$33x	23 + 	
   ( 3F9r(   c                    X R                      nUS   n[        U[        5      (       a/  U Vs/ s H  oPR                  XTU R                  5      PM      nnSU0$ U R                  X4U R                  5      /nSU0$ s  snf )a;  Generate parameters for overlay transform based on input data.

Args:
    params (dict[str, Any]): Dictionary of existing parameters
    data (dict[str, Any]): Dictionary containing input data with image and metadata

Returns:
    dict[str, Any]: Dictionary containing processed overlay data ready for application

rO   overlay_data)r    
isinstancelistrm   	py_random)r0   paramsdatar[   r\   mdrp   s          r)   get_params_dependent_on_data,OverlayElements.get_params_dependent_on_data   s     ))*7O	h%%^fg^fXZ44RDNNS^fLg
 L
 	
 !44X$..YZL L
 	
	 hs   %A9c                `    U H'  nUS   nUS   nUS   n[         R                  " XXgS9nM)     U$ )a  Apply overlay elements to the input image.

Args:
    img (np.ndarray): Input image
    overlay_data (list[dict[str, Any]]): List of dictionaries containing overlay information
    **params (Any): Additional parameters

Returns:
    np.ndarray: Image with overlays applied

rK   rL   rM   )rM   )fmixingcopy_and_paste_blend)r0   imgrp   rt   ru   rK   rL   rM   s           r)   applyOverlayElements.apply  sD    " !D 1M/L(^F..s<_C	 !
 
r(   c                    U HX  nSU;   d  M  US   c  M  US   nUS   nUS   nUu  pXR                   S   -   n
XR                   S   -   nXU
2X24   nX|US:  '   MZ     U$ )a5  Apply overlay masks to the input mask.

Args:
    mask (np.ndarray): Input mask
    overlay_data (list[dict[str, Any]]): List of dictionaries containing overlay information
    **params (Any): Additional parameters

Returns:
    np.ndarray: Mask with overlay masks applied using the specified mask_id values

rN   rL   rM   r      )rO   )r0   rF   rp   rt   ru   rL   rM   rN   re   rd   rg   rf   mask_sections                r)   apply_to_maskOverlayElements.apply_to_mask  s    " !DD T)_%@#N3hy/% 2 21 55 2 21 55#%K$<=18\A-. ! r(   r5   )overlay_metadata      ?)r    r   r-   floatreturnz	list[str])r[   dict[str, Any]r\   tuple[int, int]r]   zrandom.Randomr   r   rt   r   ru   r   r   r   )r|   
np.ndarrayrp   list[dict[str, Any]]rt   r   r   r   )rF   r   rp   r   rt   r   r   r   )r"   r#   r$   r%   __doc__r   IMAGEMASK_targetsr   r*   r/   propertyr7   staticmethodrm   rw   r}   r   r'   __classcell__r1   s   @r)   r   r      s   eN w||,H, 
 /)) ) ) # # M M"M $M 
	M M^
. + 	
 
0 + 	
 
 r(   c                    ^  \ rS rSrSr\R                  \R                  \R                  \R                  4r
 " S S\5      rSSSSS\R                  \R                  S	S	S
S4                       SU 4S jjjr\SS j5       rSS jrSS jr      SS jr        SS jrS S jr\S!S j5       rS"S jr          S#S jr          S$S jr        S%S jr        S&S jrSrU =r $ )'r   i=  a  Combine multiple images and their annotations into a single image using a mosaic grid layout.

This transform takes a primary input image (and its annotations) and combines it with
additional images/annotations provided via metadata. It calculates the geometry for
a mosaic grid, selects additional items, preprocesses annotations consistently
(handling label encoding updates), applies geometric transformations, and assembles
the final output.

Args:
    grid_yx (tuple[int, int]): The number of rows (y) and columns (x) in the mosaic grid.
        Determines the maximum number of images involved (grid_yx[0] * grid_yx[1]).
        Default: (2, 2).
    target_size (tuple[int, int]): The desired output (height, width) for the final mosaic image.
        after cropping the mosaic grid.
    cell_shape (tuple[int, int]): cell shape of each cell in the mosaic grid.
    metadata_key (str): Key in the input dictionary specifying the list of additional data dictionaries
        for the mosaic. Each dictionary in the list should represent one potential additional item.
        Expected keys: 'image' (required, np.ndarray), and optionally 'mask' (np.ndarray),
        'bboxes' (np.ndarray), 'keypoints' (np.ndarray), and any relevant label fields
        (e.g., 'class_labels') corresponding to those specified in `Compose`'s `bbox_params` or
        `keypoint_params`. Default: "mosaic_metadata".
    center_range (tuple[float, float]): Range [0.0-1.0] to sample the center point of the mosaic view
        relative to the valid central region of the conceptual large grid. This affects which parts
        of the assembled grid are visible in the final crop. Default: (0.3, 0.7).
    interpolation (int): OpenCV interpolation flag used for resizing images during geometric processing.
        Default: cv2.INTER_LINEAR.
    mask_interpolation (int): OpenCV interpolation flag used for resizing masks during geometric processing.
        Default: cv2.INTER_NEAREST.
    fill (tuple[float, ...] | float): Value used for padding images if needed during geometric processing.
        Default: 0.
    fill_mask (tuple[float, ...] | float): Value used for padding masks if needed during geometric processing.
        Default: 0.
    p (float): Probability of applying the transform. Default: 0.5.

Workflow (`get_params_dependent_on_data`):
    1. Calculate Geometry & Visible Cells: Determine which grid cells are visible in the final
       `target_size` crop and their placement coordinates on the output canvas.
    2. Validate Raw Additional Metadata: Filter the list provided via `metadata_key`,
       keeping only valid items (dicts with an 'image' key).
    3. Select Subset of Raw Additional Metadata: Choose a subset of the valid raw items based
       on the number of visible cells requiring additional data.
    4. Preprocess Selected Raw Additional Items: Preprocess bboxes/keypoints for the *selected*
       additional items *only*. This uses shared processors from `Compose`, updating their
       internal state (e.g., `LabelEncoder`) based on labels in these selected items.
    5. Prepare Primary Data: Extract preprocessed primary data fields from the input `data` dictionary
        into a `primary` dictionary.
    6. Determine & Perform Replication: If fewer additional items were selected than needed,
       replicate the preprocessed primary data as required.
    7. Combine Final Items: Create the list of all preprocessed items (primary, selected additional,
       replicated primary) that will be used.
    8. Assign Items to VISIBLE Grid Cells
    9. Process Geometry & Shift Coordinates: For each assigned item:
        a. Apply geometric transforms (Crop, Resize, Pad) to image/mask.
        b. Apply geometric shift to the *preprocessed* bboxes/keypoints based on cell placement.
   10. Return Parameters: Return the processed cell data (image, mask, shifted bboxes, shifted kps)
       keyed by placement coordinates.

Label Handling:
    - The transform relies on `bbox_processor` and `keypoint_processor` provided by `Compose`.
    - `Compose.preprocess` initially fits the processors' `LabelEncoder` on the primary data.
    - This transform (`Mosaic`) preprocesses the *selected* additional raw items using the same
      processors. If new labels are found, the shared `LabelEncoder` state is updated via its
      `update` method.
    - `Compose.postprocess` uses the final updated encoder state to decode all labels present
      in the mosaic output for the current `Compose` call.
    - The encoder state is transient per `Compose` call.

Targets:
    image, mask, bboxes, keypoints

Image types:
    uint8, float32

Reference:
    YOLOv4: Optimal Speed and Accuracy of Object Detection: https://arxiv.org/pdf/2004.10934

Examples:
    >>> import numpy as np
    >>> import albumentations as A
    >>> import cv2
    >>>
    >>> # Prepare primary data
    >>> primary_image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
    >>> primary_mask = np.random.randint(0, 2, (100, 100), dtype=np.uint8)
    >>> primary_bboxes = np.array([[10, 10, 40, 40], [50, 50, 90, 90]], dtype=np.float32)
    >>> primary_labels = [1, 2]
    >>>
    >>> # Prepare additional images for mosaic
    >>> additional_image1 = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
    >>> additional_mask1 = np.random.randint(0, 2, (100, 100), dtype=np.uint8)
    >>> additional_bboxes1 = np.array([[20, 20, 60, 60]], dtype=np.float32)
    >>> additional_labels1 = [3]
    >>>
    >>> additional_image2 = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
    >>> additional_mask2 = np.random.randint(0, 2, (100, 100), dtype=np.uint8)
    >>> additional_bboxes2 = np.array([[30, 30, 70, 70]], dtype=np.float32)
    >>> additional_labels2 = [4]
    >>>
    >>> additional_image3 = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
    >>> additional_mask3 = np.random.randint(0, 2, (100, 100), dtype=np.uint8)
    >>> additional_bboxes3 = np.array([[5, 5, 45, 45]], dtype=np.float32)
    >>> additional_labels3 = [5]
    >>>
    >>> # Create metadata for additional images - structured as a list of dicts
    >>> mosaic_metadata = [
    ...     {
    ...         'image': additional_image1,
    ...         'mask': additional_mask1,
    ...         'bboxes': additional_bboxes1,
    ...         'labels': additional_labels1
    ...     },
    ...     {
    ...         'image': additional_image2,
    ...         'mask': additional_mask2,
    ...         'bboxes': additional_bboxes2,
    ...         'labels': additional_labels2
    ...     },
    ...     {
    ...         'image': additional_image3,
    ...         'mask': additional_mask3,
    ...         'bboxes': additional_bboxes3,
    ...         'labels': additional_labels3
    ...     }
    ... ]
    >>>
    >>> # Create the transform with Mosaic
    >>> transform = A.Compose([
    ...     A.Mosaic(
    ...         grid_yx=(2, 2),
    ...         target_size=(200, 200),
    ...         cell_shape=(120, 120),
    ...         center_range=(0.4, 0.6),
    ...         fit_mode="cover",
    ...         p=1.0
    ...     ),
    ... ], bbox_params=A.BboxParams(format='pascal_voc', label_fields=['labels']))
    >>>
    >>> # Apply the transform
    >>> transformed = transform(
    ...     image=primary_image,
    ...     mask=primary_mask,
    ...     bboxes=primary_bboxes,
    ...     labels=primary_labels,
    ...     mosaic_metadata=mosaic_metadata  # Pass the metadata using the default key
    ... )
    >>>
    >>> # Access the transformed data
    >>> mosaic_image = transformed['image']        # Combined mosaic image
    >>> mosaic_mask = transformed['mask']          # Combined mosaic mask
    >>> mosaic_bboxes = transformed['bboxes']      # Combined and repositioned bboxes
    >>> mosaic_labels = transformed['labels']      # Combined labels from all images

c                      \ rS rSr% S\S'   S\S'   S\S'   S\S'   S	\S
'   S\S'   S\S'   S\S'   S\S'   S\S'   \" SS9SS j5       rSrg)Mosaic.InitSchemai  r   grid_yxzGAnnotated[tuple[int, int], AfterValidator(check_range_bounds(1, None))]target_size
cell_shaper   r    zgAnnotated[tuple[float, float], AfterValidator(check_range_bounds(0, 1)), AfterValidator(nondecreasing)]center_rangeLiteral[cv2.INTER_NEAREST, cv2.INTER_NEAREST_EXACT, cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_LANCZOS4, cv2.INTER_LINEAR_EXACT]rG   mask_interpolationtuple[float, ...] | floatfill	fill_maskLiteral['cover', 'contain']fit_modeafter)modec                    U R                   S   U R                  S   -  U R                  S   :  d0  U R                   S   U R                  S   -  U R                  S   :  a  [        S5      eU $ )Nr   r   z;Target size should be smaller than cell cell_size * grid_yx)r   r   r   
ValueErrorr6   s    r)   _check_cell_shape#Mosaic.InitSchema._check_cell_shape   sg     "T\\!_4t7G7G7JJ??1%Q7$:J:J1:MM !^__Kr(   r!   N)r   r   )r"   r#   r$   r%   r&   r
   r   r'   r!   r(   r)   r*   r     sm      
 	

 	
 
 	


 	

 	
 (',,--	g	&	 
'	r(   r*   )r<   r<   )   r   )g333333?gffffff?coverr   mosaic_metadatar   c                   > [         TU ]  US9  Xl        X l        Xl        X@l        X`l        Xpl        Xl        Xl	        XPl
        X0l        g r,   )r.   r/   r   r   r    r   rG   r   r   r   r   r   )r0   r   r   r   r   r   rG   r   r   r   r    r-   r1   s               r)   r/   Mosaic.__init__	  sL    < 	1&((*"4	" $r(   c                    U R                   /$ r4   r5   r6   s    r)   r7   Mosaic.targets_as_params4  r9   r(   c                    [         R                  " U R                  U R                  U R                  U R
                  U R                  S9n[         R                  " U R                  U R                  U R                  US9$ )N)r   r   r   r   rs   )r   r   r   	center_xy)rz   calculate_mosaic_center_pointr   r   r   r   rs   calculate_cell_placements)r0   ru   r   s      r)   _calculate_geometryMosaic._calculate_geometry>  sh    99LL((**nn
	 00LL((	
 	
r(   c                    [         R                  " UR                  U R                  5      U R                  U5      n[	        U5      U:  a  U R
                  R                  X25      $ U$ r?   )rz   filter_valid_metadatagetr    rX   rs   sample)r0   ru   num_additional_neededvalid_itemss       r)   _select_additional_itemsMosaic._select_additional_itemsO  sV    33DHHT=N=N4OQUQbQbdhi{33>>((LLr(   c                    SU;   d  SU;   aM  [        SU R                  S5      5      n[        SU R                  S5      5      n[        R                  " XU5      $ [        S[	        U5      5      $ )Nbboxes	keypointsr   r   !list[fmixing.ProcessedMosaicItem])r   get_processorrz    preprocess_selected_mosaic_itemsrr   )r0   additional_itemsru   bbox_processorkeypoint_processors        r)   _preprocess_additional_items#Mosaic._preprocess_additional_itemsU  sl    
 t{d2!/43E3Eh3OPN!%&:D<N<N{<[!\;;<L^pqq7>N9OPPr(   c                    [        SU[        U5      -
  5      n[        U5       Vs/ s H  n[        U5      PM     nnU/UQUQ$ s  snf )Nr   )maxrX   ranger   )r0   primaryr   
num_needednum_replications_
replicateds          r)   _prepare_final_itemsMosaic._prepare_final_items`  sW     q*s3C/D"DE167G1HI1HAhw'1H
I8*8Z88 Js   Ac                   U R                  U5      n[        U5      n[        SUS-
  5      nU R                  X%5      nU R	                  Xb5      nU R                  U5      nU R                  XU5      n	[        R                  " [        U	5      UU R                  S9n
[        R                  " U R                  U R                  U
U	U R                  U R                  b  U R                  OU R                  U R                  U R                   U R"                  S9	nSU;   d  SU;   a  [        R$                  " XR                  S9nXR'                  US   R(                  5      S	.nS
U;   a!  U R'                  US
   R(                  5      US'   U$ )zPOrchestrates the steps to calculate mosaic parameters by calling helper methods.r   r   )	num_itemscell_placementsrs   )	canvas_shaper   placement_to_item_indexfinal_items_for_gridr   r   r   rG   r   r   r   )r   r;   )processed_cellstarget_shaperF   target_mask_shape)r   rX   r   r   r   get_primary_datar   rz   assign_items_to_grid_cellsrs   process_all_mosaic_geometriesr   r   r   r   r   rG   r   shift_all_coordinates_get_target_shaperO   )r0   rt   ru   r   	num_cellsr   r   preprocessed_additionalr   final_itemsr   r   rl   s                r)   rw   #Mosaic.get_params_dependent_on_dataj  sg   2248(	 #Ay1} 588U"&"C"CDT"[''-//Rgh")"D"D+&+nn#
 "??))$;!,(,(Bdnn		]],,#66

 t{d2%;;OZjZjkO%4F\F\]abi]j]p]pFqrT>*.*@*@fASAS*TF&'r(   c                    U R                  S5      nUb  UR                  5       nU R                  S5      nUb  UR                  5       nU R                  S5      nUb  UR                  5       nU S   UUUS.$ )zGet a copy of the primary data (data passed in `data` parameter) to avoid modifying the original data.

Args:
    data (dict[str, Any]): Dictionary containing the primary data.

Returns:
    fmixing.ProcessedMosaicItem: A copy of the primary data.

rF   r   r   r;   )r;   rF   r   r   )r   copy)ru   rF   r   r   s       r)   r   Mosaic.get_primary_data  s|     xx99;D(#[[]FHH[)	 !(I']"	
 	
r(   c                d    [        U5      nU R                  S   US'   U R                  S   US'   U$ )Nr   r   )rr   r   )r0   np_shaper   s      r)   r   Mosaic._get_target_shape  s9    H~**1-Q**1-Qr(   c                Z    [         R                  " UUUR                  SU R                  S9$ )a_  Apply mosaic transformation to the input image.

Args:
    img (np.ndarray): Input image
    processed_cells (dict[tuple[int, int, int, int], dict[str, Any]]): Dictionary of processed cell data
    target_shape (tuple[int, int]): Shape of the target image.
    **params (Any): Additional parameters

Returns:
    np.ndarray: Mosaic transformed image

r;   r   r   rI   data_keyr   )rz   $assemble_mosaic_from_processed_cellsrI   r   )r0   r|   r   r   rt   s        r)   r}   Mosaic.apply  s.    & ;;+%))
 	
r(   c                Z    [         R                  " UUUR                  SU R                  S9$ )ak  Apply mosaic transformation to the input mask.

Args:
    mask (np.ndarray): Input mask.
    processed_cells (dict): Dictionary of processed cell data containing cropped/padded mask segments.
    target_mask_shape (tuple[int, int]): Shape of the target mask.
    **params (Any): Additional parameters (unused).

Returns:
    np.ndarray: Mosaic transformed mask.

rF   r   )rz   r   rI   r   )r0   rF   r   r   rt   s        r)   r   Mosaic.apply_to_mask  s.    & ;;+***
 	
r(   c           
     r   / nUR                  5        H+  nUS   nUR                  S:  d  M  UR                  U5        M-     U(       d.  [        R                  " SUR
                  S   4UR                  S9$ [        R                  " USS9n[        SU R                  S5      5      nU R                  S   U R                  S   S.n	[        UU	UR                  R                  UR                  R                  UR                  R                  UR                  R                   UR                  R"                  S9$ )	a  Applies mosaic transformation to bounding boxes.

Args:
    bboxes (np.ndarray): Original bounding boxes (ignored).
    processed_cells (dict): Dictionary mapping placement coords to processed cell data
                            (containing shifted bboxes in absolute pixel coords).
    **params (Any): Additional parameters (unused).

Returns:
    np.ndarray: Final combined, filtered, bounding boxes.

r   r   r   rH   axisr   )heightwidth)min_areamin_visibility	min_width
min_heightmax_accept_ratio)valuessizeappendrP   emptyrO   rI   concatenater   r   r   r   rt   r   r   r   r   r   )
r0   r   r   rt   all_shifted_bboxes	cell_datashifted_bboxescombined_bboxesr   
shape_dicts
             r)   apply_to_bboxesMosaic.apply_to_bboxes  s   $  (//1I&x0N""Q&")).9 2
 "88QQ0EE ..);!D ot/A/A(/KL &&q)%%a(F

 #**33)00??$++55%,,77+22CC
 	
r(   c                   / nUR                  5        H+  nUS   nUR                  S:  d  M  UR                  U5        M-     U(       d.  [        R                  " SUR
                  S   4UR                  S9$ [        R                  " USS9nU R                  u  pUSS2S4   S:  USS2S4   U	:  -  USS2S4   S:  -  USS2S4   U:  -  n
Xz   $ )as  Applies mosaic transformation to keypoints.

Args:
    keypoints (np.ndarray): Original keypoints (ignored).
    processed_cells (dict): Dictionary mapping placement coords to processed cell data
                            (containing shifted keypoints).
    **params (Any): Additional parameters (unused).

Returns:
    np.ndarray: Final combined, filtered keypoints.

r   r   r   rH   r   N)	r   r   r   rP   r   rO   rI   r  r   )r0   r   r   rt   all_shifted_keypointsr  shifted_keypointscombined_keypointstarget_htarget_wvalid_indicess              r)   apply_to_keypointsMosaic.apply_to_keypoints  s    $ !#(//1I )+ 6 %%)%,,->? 2
 %88Q	 239??KK^^,AJ "--1%*!!Q$'(24!!Q$'1,. "!Q$'(24 	 "00r(   )
r   r   r   r   r   r   rG   r   r    r   )r   r   r   r   r   r   r   ztuple[float, float]r   r   rG   r   r   r   r   r   r   r   r    r   r-   r   r   Noner   )ru   r   r   zlist[tuple[int, int, int, int]])ru   r   r   r@   r   r   )r   r   ru   r   r   r   )r   fmixing.ProcessedMosaicItemr   r   r   r@   r   r   r   )ru   r   r   r  )r   ztuple[int, ...]r   z	list[int])
r|   r   r   /dict[tuple[int, int, int, int], dict[str, Any]]r   r   rt   r   r   r   )
rF   r   r   r  r   r   rt   r   r   r   )r   r   r   r  rt   r   r   r   )r   r   r   r  rt   r   r   r   )!r"   r#   r$   r%   r   r   r   r   BBOXES	KEYPOINTSr   r   r*   rR   INTER_LINEARrT   r/   r   r7   r   r   r   r   rw   r   r   r   r}   r   r  r  r'   r   r   s   @r)   r   r   =  sE   Xt w||W^^W=N=NOH-, -b $*'1&0,607  *+/0-9)% )% %)% $	)%
 *)% .)%
)% 
!)%2 (3)%4 -5)%6 7)%8 9)%: 
;)% )%V # #
"	Q.	Q 	Q 
+		Q9,9 <9 	9
 
+9&P 
 
4

 I
 &	

 
 

6

 I
 +	

 
 

6.
.
 I.
 	.

 
.
`'1'1 I'1 	'1
 
'1 '1r(   ))r   
__future__r   randomr   r   typingr   r   r   r   rR   numpyrP   pydanticr	   r
   typing_extensionsr   #albumentations.augmentations.mixingr   rz   albumentations.core.bbox_utilsr   r   r   r   #albumentations.core.keypoints_utilsr   albumentations.core.pydanticr   r   (albumentations.core.transforms_interfacer   r   $albumentations.core.type_definitionsr   r   __all__r   r   r!   r(   r)   <module>r%     sd    #   0 0 
  4 " E i i B J [ I&
'\m \~C1] C1r(   