
    hQ                       S r SSKJ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Jr  SSKrSSKJr  S	S
KJr  S	SKJrJr  \(       a  SSKr\\S   \4   rSS jrSS jrS S jrS!S jr  " S S\\5      r! " S S\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r(\  S(       S)S jj5       r)\  S(       S*S jj5       r)  S(       S+S jjr)g),a  Module containing utility functions and classes for the core Albumentations framework.

This module provides a collection of helper functions and base classes used throughout
the Albumentations library. It includes utilities for shape handling, parameter processing,
data conversion, and serialization. The module defines abstract base classes for data
processors that implement the conversion logic between different data formats used in
the transformation pipeline.
    )annotations)ABCabstractmethod)Sequence)Real)TYPE_CHECKINGAnyLiteralcastoverloadN)LabelManager   )Serializable)PAIRNumberdepthheightwidthc                   [        U [        R                  5      (       a  U R                  SS $  SSKnUR
                  " U 5      (       a  U R                  SS $  [        S[        U 5       35      e! [         a     N#f = f)a2  Extract height and width dimensions from an image.

Args:
    img (np.ndarray | torch.Tensor): Image as either numpy array (HWC format)
        or torch tensor (CHW format).

Returns:
    tuple[int, int]: Image dimensions as (height, width).

Raises:
    RuntimeError: If the image type is not supported.

N   r   zUnsupported image type: 	
isinstancenpndarrayshapetorch	is_tensorImportErrorRuntimeErrortype)imgr   s     S/var/www/fran/franai/venv/lib/python3.13/site-packages/albumentations/core/utils.pyget_image_shaper%      s~     #rzz""yy!}??399RS>!   1$s)=
>>     )A2 2
A?>A?c                   [        U [        R                  5      (       a  U R                  SS $  SSKnUR
                  " U 5      (       a  U R                  SS $  [        S[        U 5       35      e! [         a     N#f = f)aK  Extract depth, height, and width dimensions from a volume.

Args:
    vol (np.ndarray | torch.Tensor): Volume as either numpy array (DHWC format)
        or torch tensor (CDHW format).

Returns:
    tuple[int, int, int]: Volume dimensions as (depth, height, width).

Raises:
    RuntimeError: If the volume type is not supported.

N   r   zUnsupported volume type: r   )volr   s     r$   get_volume_shaper+   8   s~     #rzz""yy!}??399RS>!   249+>
??  r&   c                    SU ;   a  [        U S   5      u  pnXUS.$ SU ;   a  [        U S   5      u  p#X#S.$ SU ;   a  [        U S   S   5      u  p#X#S.$ [        SU R                  5       5      e)a  Extract spatial dimensions from input data dictionary containing image or volume.

Args:
    data (dict[str, Any]): Dictionary containing image or volume data with one of:
        - 'volume': 3D array of shape (D, H, W, C) [numpy] or (C, D, H, W) [torch]
        - 'image': 2D array of shape (H, W, C) [numpy] or (C, H, W) [torch]
        - 'images': Batch of arrays of shape (N, H, W, C) [numpy] or (N, C, H, W) [torch]

Returns:
    dict[Literal["depth", "height", "width"], int]: Dictionary containing spatial dimensions

volumer   image)r   r   imagesr   z No image or volume found in data)r+   r%   
ValueErrorkeys)datar   r   r   s       r$   	get_shaper3   R   s     4/X?u5AA$'W6 114'Xq(9: 11
7
EE    c                    / nU R                  5        HA  u  p#[        U[        5      (       a  SU S3O
[        U5      nUR                  U SU 35        MC     SR	                  U5      $ )zFormat a dictionary of arguments into a string representation.

Args:
    args_dict (dict[str, Any]): Dictionary of argument names and values.

Returns:
    str: Formatted string of arguments in the form "key1='value1', key2=value2".

'=z, )itemsr   strappendjoin)	args_dictformatted_argskvv_formatteds        r$   format_argsrA   k   se     N!",Q"4"4!Ah#a&1[M23 " 99^$$r4   c                  ,    \ rS rSrSrSS jrSS jrSrg)	Params|   zBase class for parameter handling in transforms.

Args:
    format (Any): The format of the data this parameter object will process.
    label_fields (Sequence[str] | None): List of fields that are joined with the data, such as labels.

c                    Xl         X l        g Nformatlabel_fields)selfrH   rI   s      r$   __init__Params.__init__   s    (r4   c                4    U R                   U R                  S.$ )zReturn a dictionary containing the private parameters of this object.

Returns:
    dict[str, Any]: Dictionary with format and label_fields parameters.

rG   rG   rJ   s    r$   to_dict_privateParams.to_dict_private   s     ++t7H7HIIr4   rG   N)rH   r	   rI   zSequence[str] | None)returndict[str, Any])__name__
__module____qualname____firstlineno____doc__rK   rO   __static_attributes__ r4   r$   rC   rC   |   s    )Jr4   rC   c                  `   \ rS rSrSrSSS jjr\\SS j5       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rS$S jrS!S jrSS jr S%       S&S jjr\S'S j5       r\S(S j5       r\      S'S j5       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rSrg),DataProcessor   a3  Abstract base class for data processors.

Data processors handle the conversion, validation, and filtering of data
during transformations.

Args:
    params (Params): Parameters for data processing.
    additional_targets (dict[str, str] | None): Dictionary mapping additional target names to their types.

Nc                    Xl         U R                  /U l        0 U l        [	        5       U l        Ub  U R                  U5        g g rF   )paramsdefault_data_namedata_fieldsis_sequence_inputr   label_manageradd_targets)rJ   r^   additional_targetss      r$   rK   DataProcessor.__init__   sD     22324)^)/0 *r4   c                    [         e)zXReturn the default name of the data field.

Returns:
    str: Default data field name.

)NotImplementedErrorrN   s    r$   r_   DataProcessor.default_data_name   s
     "!r4   c                    UR                  5        HB  u  p#X0R                  :X  d  M  X R                  ;  d  M'  U R                  R                  U5        MD     g)zFAdd targets to transform them the same way as one of existing targets.N)r8   r_   r`   r:   )rJ   rd   r>   r?   s       r$   rc   DataProcessor.add_targets   sB    &,,.DA***q8H8H/H  ''* /r4   c                    g)zmValidate input data before processing.

Args:
    data (dict[str, Any]): Input data dictionary to validate.

NrY   )rJ   r2   s     r$   ensure_data_validDataProcessor.ensure_data_valid       r4   c                    g)zyValidate transforms before applying them.

Args:
    transforms (Sequence[object]): Sequence of transforms to validate.

NrY   )rJ   
transformss     r$   ensure_transforms_valid%DataProcessor.ensure_transforms_valid   rn   r4   c                ~    [        U5      nU R                  X5      nU R                  U5      nU R                  U5      $ )zProcess data after transformation.

Args:
    data (dict[str, Any]): Data dictionary after transformation.

Returns:
    dict[str, Any]: Processed data dictionary.

)r3   _process_data_fieldsremove_label_fields_from_data_convert_sequence_inputsrJ   r2   r   s      r$   postprocessDataProcessor.postprocess   s>     $((511$7,,T22r4   c                    [        U R                  5      [        UR                  5       5      -   H  nU R                  X1U   U5      X'   M     U$ rF   )setr`   r1   _process_single_fieldrJ   r2   r   	data_names       r$   rt   "DataProcessor._process_data_fields   sF    T--.TYY[1AAI"88OUZ[DO Br4   c                    U R                  X#5      nUS:X  a  [        U5      S:X  a  U R                  5       nU R                  X#SS9$ )N	keypointsr   from	direction)filterlen_create_empty_keypoints_arraycheck_and_convert)rJ   r~   
field_datar   s       r$   r|   #DataProcessor._process_single_field   sG    [[3
#J1(<;;=J%%j6%JJr4   c                    [         R                  " / [         R                  S9R                  S[	        U R
                  R                  5      5      $ )Ndtyper   )r   arrayfloat32reshaper   r^   rH   rN   s    r$   r   +DataProcessor._create_empty_keypoints_array   s3    xx"**-55aT[[=O=O9PQQr4   c                    [        U R                  5      [        UR                  5       5      -   H:  nU R                  R	                  US5      (       d  M&  X   R                  5       X'   M<     U$ )NF)r{   r`   r1   ra   gettolistrJ   r2   r~   s      r$   rv   &DataProcessor._convert_sequence_inputs   sZ    T--.TYY[1AAI%%)))U;;"&/"8"8": B r4   c                   [        U5      n[        U R                  5      [        UR                  5       5      -   Ha  n[	        X   [
        5      (       a8  SU R                  U'   [        R                  " X   [        R                  S9X'   MR  SU R                  U'   Mc     U R                  U5      n[        U R                  5      [        UR                  5       5      -   H  nU R                  X   USS9X'   M     g)zfProcess data before transformation.

Args:
    data (dict[str, Any]): Data dictionary to preprocess.

Tr   Ftor   N)r3   r{   r`   r1   r   r   ra   r   r   r   add_label_fields_to_datar   r}   s       r$   
preprocessDataProcessor.preprocess   s     $T--.TYY[1AAI$/84448&&y1"$((4?"**"M49&&y1 B ,,T2T--.TYY[1AAI"44T_eW[4\DO Br4   c                    U R                   R                  S:X  a  U R                  X5        U$ US:X  a  U R                  OU R                  nU" X5      $ )a  Check and convert data between Albumentations and external formats.

Args:
    data (np.ndarray): Input data array.
    shape (ShapeType): Shape information containing dimensions.
    direction (Literal["to", "from"], optional): Conversion direction.
        "to" converts to Albumentations format, "from" converts from it.
        Defaults to "to".

Returns:
    np.ndarray: Converted data array.

albumentationsr   )r^   rH   checkconvert_to_albumentationsconvert_from_albumentations)rJ   r2   r   r   process_funcs        r$   r   DataProcessor.check_and_convert  sN    & ;;!11JJt#K9Bd9Jt55PTPpPpD((r4   c                    g)zFilter data based on shapes.

Args:
    data (np.ndarray): Data to filter.
    shape (ShapeType): Shape information containing dimensions.

Returns:
    np.ndarray: Filtered data.

NrY   rw   s      r$   r   DataProcessor.filter  rn   r4   c                    g)zValidate data structure against shape requirements.

Args:
    data (np.ndarray): Data to validate.
    shape (ShapeType): Shape information containing dimensions.

NrY   rw   s      r$   r   DataProcessor.check*  rn   r4   c                    g)zConvert data from external format to Albumentations internal format.

Args:
    data (np.ndarray): Data in external format.
    shape (ShapeType): Shape information containing dimensions.

Returns:
    np.ndarray: Data in Albumentations format.

NrY   rw   s      r$   r   'DataProcessor.convert_to_albumentations4  rn   r4   c                    g)zConvert data from Albumentations internal format to external format.

Args:
    data (np.ndarray): Data in Albumentations format.
    shape (ShapeType): Shape information containing dimensions.

Returns:
    np.ndarray: Data in external format.

NrY   rw   s      r$   r   )DataProcessor.convert_from_albumentationsE  rn   r4   c                    U R                   R                  (       d  U$ [        U R                  5      [        UR	                  5       5      -   H+  nX   R
                  (       d  M  U R                  X5      X'   M-     U$ )zAdd label fields to data arrays.

This method processes label fields and joins them with the corresponding data arrays.

Args:
    data (dict[str, Any]): Input data dictionary.

Returns:
    dict[str, Any]: Data with label fields added.

)r^   rI   r{   r`   r1   size_process_label_fieldsr   s      r$   r   &DataProcessor.add_label_fields_to_dataV  sc     {{''KT--.TYY[1AAI?''"88IDO B
 r4   c                   X   nU R                   R                  bf  U R                   R                   HL  nU R                  XU5        U R                  R	                  X$X   5      n[
        R                  " X545      nX	 MN     U$ rF   )r^   rI   _validate_label_field_lengthrb   process_fieldr   hstack)rJ   r2   r~   
data_arraylabel_fieldencoded_labelss         r$   r   #DataProcessor._process_label_fieldsl  sx    _
;;##/#{{7711$;O!%!3!3!A!A)Z^Zk!lYY
'CD
%	  8
 r4   c                    [        X   5      [        X   5      :w  a.  [        SU SU S[        X   5       S[        X   5       S3	5      eg )NzThe lengths of z and z do not match. Got z respectively.)r   r0   )rJ   r2   r~   r   s       r$   r   *DataProcessor._validate_label_field_lengthv  sa    t3t'8#99!)E+ ?4?+,E#d6G2H1IY  :r4   c                   U R                   R                  (       d  U$ [        U R                  5      [        UR	                  5       5      -   H:  nX   R
                  (       d  U R                  U5        M)  U R                  X5        M<     U$ )zRemove label fields from data arrays and restore them as separate entries.

Args:
    data (dict[str, Any]): Input data dictionary with combined label fields.

Returns:
    dict[str, Any]: Data with label fields extracted as separate entries.

)r^   rI   r{   r`   r1   r   _handle_empty_data_array_remove_label_fieldsr   s      r$   ru   +DataProcessor.remove_label_fields_from_data}  sm     {{''KT--.TYY[1AAI?''--d3%%d6	 B r4   c                    U R                   R                  b:  U R                   R                   H  nU R                  R                  5       X'   M!     g g rF   )r^   rI   rb   handle_empty_data)rJ   r2   r   s      r$   r   &DataProcessor._handle_empty_data_array  sB    ;;##/#{{77$($6$6$H$H$J!  8 0r4   c                Z   U R                   R                  c  g X   n[        U R                   R                  5      nUR                  S   U-
  n[	        U R                   R                  5       H.  u  pgUS S 2XV-   4   nU R
                  R                  X'U5      X'   M0     US S 2S U24   X'   g )Nr   )r^   rI   r   r   	enumeraterb   restore_field)	rJ   r2   r~   r   num_label_fieldsnon_label_columnsidxr   r   s	            r$   r   "DataProcessor._remove_label_fields  s    ;;##+_
t{{778&,,Q/2BB )$++*B*B CC'+<+B(BCN $ 2 2 @ @Yg hD !D %Q(:):(:%:;r4   )r`   ra   rb   r^   rF   )r^   rC   rd   zdict[str, str] | None)rQ   r9   )rd   zdict[str, str]rQ   None)r2   rR   rQ   r   )rp   zSequence[object]rQ   r   )r2   rR   rQ   rR   )r2   rR   r   	ShapeTyperQ   rR   )r~   r9   r   r	   r   r   rQ   r	   )rQ   
np.ndarray)r   )r2   r   r   r   r   zLiteral['to', 'from']rQ   r   )r2   r   r   r   rQ   r   )r2   r   r   r   rQ   r   )r2   rR   r~   r9   rQ   r   )r2   rR   r~   r9   r   r9   rQ   r   )r2   rR   r~   r9   rQ   r   )rS   rT   rU   rV   rW   rK   propertyr   r_   rc   rl   rq   rx   rt   r|   r   rv   r   r   r   r   r   r   r   r   r   ru   r   r   rX   rY   r4   r$   r[   r[      s/   	1 "  "+3
KR]0 ,0	)) ) )	)
 
)6 
 
     
	     
	  ,*K
<r4   r[   c                (    U b  Ub  [        S5      egg)a"  Validate that 'low' and 'bias' parameters are not used together.

Args:
    low (float | Sequence[int] | Sequence[float] | None): Lower bound value.
    bias (float | None): Bias value to be added to both min and max values.

Raises:
    ValueError: If both 'low' and 'bias' are provided.

Nz3Arguments 'low' and 'bias' cannot be used together.)r0   )lowbiass     r$   validate_argsr     s!     4+NOO ,r4   c                j    [        U 5      [        :w  a  [        S5      e[        U 5      [	        U 5      4$ )a'  Process a sequence and return it as a (min, max) tuple.

Args:
    param (Sequence[Number]): Sequence of numeric values.

Returns:
    tuple[Number, Number]: Tuple containing (min_value, max_value) from the sequence.

Raises:
    ValueError: If the sequence doesn't contain exactly 2 elements.

z)Sequence must contain exactly 2 elements.)r   r   r0   minmax)params    r$   process_sequencer     s/     5zTDEEu:s5z!!r4   c                L    [        U[        5      (       a  X:  a  X4$ X4$ U * U 4$ )a  Process a scalar value and optional low bound into a (min, max) tuple.

Args:
    param (Number): Scalar numeric value.
    low (Number | None): Optional lower bound.

Returns:
    tuple[Number, Number]: Tuple containing (min_value, max_value) where:
        - If low is provided: (low, param) if low < param else (param, low)
        - If low is None: (-param, param) creating a symmetric range around zero

)r   r   )r   r   s     r$   process_scalarr     s0     #t"{|<<65=r4   c                    X -   X!-   4$ )a  Apply a bias to both values in a range.

Args:
    min_val (Number): Minimum value.
    max_val (Number): Maximum value.
    bias (Number): Value to add to both min and max.

Returns:
    tuple[Number, Number]: Tuple containing (min_val + bias, max_val + bias).

rY   )min_valmax_valr   s      r$   
apply_biasr     s     >4>))r4   c                    [        U[        5      (       a  [        U 5      [        U5      4$ [        U 5      [        U5      4$ )at  Ensure output is of the same type (int or float) as the input parameter.

Args:
    min_val (Number): Minimum value.
    max_val (Number): Maximum value.
    param (Number): Original parameter used to determine the output type.

Returns:
    tuple[int, int] | tuple[float, float]: Tuple with values converted to int if param is int,
    otherwise values remain as float.

)r   intfloat)r   r   r   s      r$   ensure_int_outputr     s8    " ,6eS+A+ACL#g,'ggX]^eXfGggr4   c                    [        U [        R                  5      (       a  [        R                  " U 5      n U $ [        U [        5      (       a  [        [        [        U 5      5      n U $ )zEnsure that numpy arrays are contiguous in memory.

Args:
    arg (np.ndarray | Sequence[np.ndarray]): A numpy array or sequence of numpy arrays.

Returns:
    np.ndarray | list[np.ndarray]: Contiguous array(s) with the same data.

)r   r   r   ascontiguousarrayr   listmapensure_contiguous_output)args    r$   r   r     sR     #rzz""""3' J 
C	"	"3/56Jr4   c                    g rF   rY   r   r   r   s      r$   to_tupler     s    
 r4   c                    g rF   rY   r   s      r$   r   r     s    
 r4   c           	     L   [        X5        [        U [        5      (       a  [        U 5      u  p4O9[        U [        5      (       a  [        U [        SU5      5      u  p4O[        S5      eUb  [        X4U5      u  p4[        X4[        U [        [        45      (       a  U 5      $ U5      $ )a  Convert input argument to a min-max tuple.

This function processes various input types and returns a tuple representing a range.
It handles single values, sequences, and can apply optional low bounds or biases.

Args:
    param (tuple[float, float] | float | tuple[int, int] | int): The primary input value. Can be:
        - A single int or float: Converted to a symmetric range around zero.
        - A tuple of two ints or two floats: Used directly as min and max values.

    low (tuple[float, float] | float | None, optional): A lower bound value. Used when param is a single value.
        If provided, the result will be (low, param) or (param, low), depending on which is smaller.
        Cannot be used together with 'bias'. Defaults to None.

    bias (float | int | None, optional): A value to be added to both elements of the resulting tuple.
        Cannot be used together with 'low'. Defaults to None.

Returns:
    tuple[int, int] | tuple[float, float]: A tuple representing the processed range.
        - If input is int-based, returns tuple[int, int]
        - If input is float-based, returns tuple[float, float]

Raises:
    ValueError: If both 'low' and 'bias' are provided.
    TypeError: If 'param' is neither a scalar nor a sequence of 2 elements.

Examples:
    >>> to_tuple(5)
    (-5, 5)
    >>> to_tuple(5.0)
    (-5.0, 5.0)
    >>> to_tuple((1, 10))
    (1, 10)
    >>> to_tuple(5, low=3)
    (3, 5)
    >>> to_tuple(5, bias=1)
    (-4, 6)

Notes:
    - When 'param' is a single value and 'low' is not provided, the function creates a symmetric range around zero.
    - The function preserves the type (int or float) of the input in the output.
    - If a sequence is provided, it must contain exactly 2 elements.

r   zEArgument 'param' must be either a scalar or a sequence of 2 elements.)r   r   r   r   r   r   r   	TypeErrorr   r   r   r   )r   r   r   r   r   s        r$   r   r      s    b #%""+E2	E4	 	 )%fc1BC_``%g=W
53PU,8W8Wuee]deer4   )r#   np.ndarray | torch.TensorrQ   tuple[int, int])r*   r   rQ   ztuple[int, int, int])r2   rR   rQ   r   )r<   rR   rQ   r9   )r   z.float | Sequence[int] | Sequence[float] | Noner   float | NonerQ   r   )r   zSequence[Number]rQ   tuple[Number, Number])r   r   r   zNumber | NonerQ   r   )r   r   r   r   r   r   rQ   r   )r   r   r   r   r   r   rQ   z%tuple[int, int] | tuple[float, float])r   z!np.ndarray | Sequence[np.ndarray]rQ   znp.ndarray | list[np.ndarray])NN)r   zint | tuple[int, int]r   zint | tuple[int, int] | Noner   r   rQ   r   )r   zfloat | tuple[float, float]r   z"float | tuple[float, float] | Noner   r   rQ   ztuple[float, float])r   z-float | tuple[float, float] | tuple[int, int]r   z4float | tuple[float, float] | tuple[int, int] | Noner   r   rQ   z%tuple[float, float] | tuple[int, int])*rW   
__future__r   abcr   r   collections.abcr   numbersr   typingr   r	   r
   r   r   numpyr   !albumentations.core.label_managerr   serializationr   type_definitionsr   r   r   dictr   r   r%   r+   r3   rA   rC   r[   r   r   r   r   r   r   r   rY   r4   r$   <module>r      s   # # $  > >  : ' *34c9:	?4@4F2%"J\3 J.P<C P<fP	7P
P 
P$"$$*hhh h +	h(" 
 )- 	%  	 
 
 /3&	+  	 
 AE=f8=f	==f =f +	=fr4   