U
    h!                     @  s   d dl mZ d dlZd dlZd dlmZ d dlmZmZ d dl	Z
d dlmZ d dlmZ d dlmZ d dlm  m  mZ d dlmZmZ d d	lmZmZ d d
lmZmZ d dlm Z  dgZ!G dd deZ"dS )    )annotationsN)Path)AnyLiteral)	ImageFont)AfterValidator)	Annotated)check_bboxesdenormalize_bboxes)check_01nondecreasing)BaseTransformInitSchemaImageOnlyTransform)	ColorType	TextImagec                      s   e Zd ZdZG dd deZd6dddddddddddd fddZeddddZddddZ	ddd dd!d"d#Z
d$d%dd&d'd(d)d*Zd'd'd'd+d,d-Zd$d.d/d$d0d1d2Zd'd/d/d'd3 fd4d5Z  ZS )7r   a  Apply text rendering transformations on images.

    This class supports rendering text directly onto images using a variety of configurations,
    such as custom fonts, font sizes, colors, and augmentation methods. The text can be placed
    inside specified bounding boxes.

    Args:
        font_path (str | Path): Path to the font file to use for rendering text.
        stopwords (list[str] | None): List of stopwords for text augmentation.
        augmentations (tuple[str | None, ...] | list[str | None]): List of text augmentations to apply.
            None: text is printed as is
            "insertion": insert random stop words into the text.
            "swap": swap random words in the text.
            "deletion": delete random words from the text.
        fraction_range (tuple[float, float]): Range for selecting a fraction of bounding boxes to modify.
        font_size_fraction_range (tuple[float, float]): Range for selecting the font size as a fraction of
            bounding box height.
        font_color (list[str] | str): List of possible font colors or a single font color.
        clear_bg (bool): Whether to clear the background before rendering text.
        metadata_key (str): Key to access metadata in the parameters.
        p (float): Probability of applying the transform.

    Targets:
        image

    Image types:
        uint8, float32

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

    Examples:
        >>> import albumentations as A
        >>> transform = A.Compose([
            A.TextImage(
                font_path=Path("/path/to/font.ttf"),
                stopwords=["the", "is", "in"],
                augmentations=("insertion", "deletion"),
                fraction_range=(0.5, 1.0),
                font_size_fraction_range=(0.5, 0.9),
                font_color=["red", "green", "blue"],
                metadata_key="text_metadata",
                p=0.5
            )
        ])
        >>> transformed = transform(image=my_image, text_metadata=my_metadata)
        >>> image = transformed['image']
        # This will render text on `my_image` based on the metadata provided in `my_metadata`.
    c                   @  sN   e Zd ZU ded< ded< ded< ded< ded	< d
ed< ded< ded< dS )zTextImage.InitSchema
str | Path	font_pathtuple[str, ...]	stopwordsz)tuple[str | None, ...] | list[str | None]augmentationszWAnnotated[tuple[float, float], AfterValidator(nondecreasing), AfterValidator(check_01)]fraction_rangefont_size_fraction_range'list[ColorType | str] | ColorType | str
font_colorboolclear_bgstrmetadata_keyN)__name__
__module____qualname____annotations__ r"   r"   P/tmp/pip-unpacked-wheel-e8onvpoz/albumentations/augmentations/text/transforms.py
InitSchemaI   s   
r$   ZtheisinatZofN      ?r+   g?g?blackFtextimage_metadataN      ?r   r   z8tuple[Literal[('insertion', 'swap', 'deletion')] | None]ztuple[float, float]r   r   r   zbool | NonefloatNone)r   r   r   r   r   r   r   r   always_applypreturnc                   sH   t  j|
|	d || _|| _|| _|| _t|| _|| _|| _	|| _
d S )N)r3   r2   )super__init__r   r   r   r   listr   r   r   r   )selfr   r   r   r   r   r   r   r   r2   r3   	__class__r"   r#   r6   W   s    
zTextImage.__init__z	list[str])r4   c                 C  s   | j gS r)   )r   r8   r"   r"   r#   targets_as_paramsn   s    zTextImage.targets_as_paramsc                 C  s   dS )N)r   r   r   r   r   r   r   r   r"   r;   r"   r"   r#   get_transform_init_args_namesr   s    z'TextImage.get_transform_init_args_namesz*Literal[('insertion', 'swap', 'deletion')])textfractionchoicer4   c                 C  s   dd |   D }t|}tdt|| }|dkrJt||| j}n4|dkr`t||}n|dkrvt	||}nt
dtdd	|  }||kr|S d
S )Nc                 S  s   g | ]}|r|qS r"   r"   ).0wordr"   r"   r#   
<listcomp>   s      z(TextImage.random_aug.<locals>.<listcomp>   Z	insertionZswapZdeletionz?Invalid choice. Choose from 'insertion', 'swap', or 'deletion'.z +  )stripsplitlenmaxintftextZinsert_random_stopwordsr   Zswap_random_wordsZdelete_random_words
ValueErrorresub)r8   r>   r?   r@   wordsZ	num_wordsZnum_words_to_modifyZresult_sentencer"   r"   r#   
random_aug~   s    zTextImage.random_augz
np.ndarrayz!tuple[float, float, float, float]rK   zdict[str, Any])imagebboxr>   
bbox_indexr4   c                 C  s   t t|g tt|g|jd d d }dd |d d D \}}}}	|	| }
tj| j }t	t
| jt||
 }| jr| jd kr|}n(t| j}|d kr|n| j|d|d}t| jtrt| jn| j}||||	f|||||dS )	N   r   c                 s  s   | ]}t |V  qd S r)   )rK   )rA   xr"   r"   r#   	<genexpr>   s     z0TextImage.preprocess_metadata.<locals>.<genexpr>   r/   )r@   )bbox_coordsrT   original_textr>   fontr   )r	   nparrayr
   shaperandomuniformr   r   Ztruetyper   r   rK   r   r@   rQ   
isinstancer   r7   )r8   rR   rS   r>   rT   Zdenormalized_bboxZx_minZy_minZx_maxZy_maxZbbox_heightZfont_size_fractionr[   Zaugmented_textZaugmentationr   r"   r"   r#   preprocess_metadata   s$     
zTextImage.preprocess_metadata)paramsdatar4   c                   s   |d  |j  g kr"dg iS ttr2gtjj }tt| }tt	t|} fdd|D }d|iS )NrR   overlay_datac                   s,   g | ]$}  | d  | d |qS )rS   r>   )rb   )rA   rT   rR   metadatar8   r"   r#   rC      s   z:TextImage.get_params_dependent_on_data.<locals>.<listcomp>)
r   ra   dictr_   r`   r   rK   rI   samplerange)r8   rc   rd   r?   Znum_bboxes_to_modifyZbbox_indices_to_updatere   r"   rf   r#   get_params_dependent_on_data   s"    
 
 z&TextImage.get_params_dependent_on_datazlist[dict[str, Any]]r   )imgre   rc   r4   c                 K  s   t j||| jdS )N)r   )rL   Zrender_textr   )r8   rl   re   rc   r"   r"   r#   apply   s    zTextImage.apply)rc   argskwargsr4   c                   s.   t  j|f||}dd |d D |d< |S )Nc                 S  s0   g | ](}|d  |d |d |d |d dqS )rY   r>   rZ   rT   r   )rY   r>   rZ   rT   r   r"   )rA   overlayr"   r"   r#   rC      s   z/TextImage.apply_with_params.<locals>.<listcomp>re   )r5   apply_with_params)r8   rc   rn   ro   resr9   r"   r#   rq      s
    
zTextImage.apply_with_params)	r%   r)   r*   r,   r-   Fr.   Nr/   )r   r   r    __doc__r   r$   r6   propertyr<   r=   rQ   rb   rk   rm   rq   __classcell__r"   r"   r9   r#   r      s(   2         (#)#
__future__r   r_   rN   pathlibr   typingr   r   Znumpyr\   ZPILr   Zpydanticr   Ztyping_extensionsr   Z,albumentations.augmentations.text.functionalr   r>   Z
functionalrL   Zalbumentations.core.bbox_utilsr	   r
   Zalbumentations.core.pydanticr   r   Z(albumentations.core.transforms_interfacer   r   Zalbumentations.core.typesr   __all__r   r"   r"   r"   r#   <module>   s   