a
    dM                     @   s   d dl Z d dlmZ d dlmZmZmZmZmZm	Z	m
Z
 d dlmZ d dlmZmZmZmZ d dlmZ d dlmZ d dlmZ d d	lmZmZ d d
lmZ d dlmZ d dlm Z  d dl!m"Z"m#Z# d dl$m%Z% d dl&m'Z' dgZ(G dd deZ)dS )    N)zip_longest)AnyDictListOptionalTupleUnioncast)Tensor)AugmentationBase3DGeometricAugmentationBase2DIntensityAugmentationBase2DRandomErasing)MixAugmentationBaseV2)_AugmentationBase)SequentialBase)ImageSequential	ParamItem)PatchSequential)ApplyInverse)VideoSequential)DataKeyResample)Boxes)eye_likeAugmentationSequentialc                       s  e Zd ZdZejgdddddejeej	ddide
eef ee
eeef  ee ee ee e
eeeeef f eee  eeeeef f dd	 fdd	Zeed
ddZeee dddZdddeeee  eee
eeef   e
eee f dddZd ee ee e
eeeee f ee eee ee f f dddZeee dddZeee dddZddddeee eee  eee
eeef   e
eeeee f ee eee ee f f d fddZ   Z!S )!r   a  AugmentationSequential for handling multiple input types like inputs, masks, keypoints at once.

    .. image:: https://kornia-tutorials.readthedocs.io/en/latest/_images/data_augmentation_sequential_5_1.png
        :width: 49 %
    .. image:: https://kornia-tutorials.readthedocs.io/en/latest/_images/data_augmentation_sequential_7_0.png
        :width: 49 %

    Args:
        *args: a list of kornia augmentation modules.
        data_keys: the input type sequential for applying augmentations.
            Accepts "input", "mask", "bbox", "bbox_xyxy", "bbox_xywh", "keypoints".
        same_on_batch: apply the same transformation across the batch.
            If None, it will not overwrite the function-wise settings.
        keepdim: whether to keep the output shape the same as input (True) or broadcast it
            to the batch form (False). If None, it will not overwrite the function-wise settings.
        random_apply: randomly select a sublist (order agnostic) of args to
            apply transformation.
            If int, a fixed number of transformations will be selected.
            If (a,), x number of transformations (a <= x <= len(args)) will be selected.
            If (a, b), x number of transformations (a <= x <= b) will be selected.
            If True, the whole list of args will be processed as a sequence in a random order.
            If False, the whole list of args will be processed as a sequence in original order.
        extra_args: to control the behaviour for each datakeys. By default, masks are handled
            by nearest interpolation strategies.

    .. note::
        Mix augmentations (e.g. RandomMixUp, RandomCutMix) can only be working with "input" data key.
        It is not clear how to deal with the conversions of masks, bounding boxes and keypoints.

    .. note::
        See a working example `here <https://kornia-tutorials.readthedocs.io/en/
        latest/data_augmentation_sequential.html>`__.

    Examples:
        >>> import kornia
        >>> input = torch.randn(2, 3, 5, 6)
        >>> mask = torch.ones(2, 3, 5, 6)
        >>> bbox = torch.tensor([[
        ...     [1., 1.],
        ...     [2., 1.],
        ...     [2., 2.],
        ...     [1., 2.],
        ... ]]).expand(2, -1, -1)
        >>> points = torch.tensor([[[1., 1.]]]).expand(2, -1, -1)
        >>> aug_list = AugmentationSequential(
        ...     kornia.augmentation.ColorJiggle(0.1, 0.1, 0.1, 0.1, p=1.0),
        ...     kornia.augmentation.RandomAffine(360, p=1.0),
        ...     data_keys=["input", "mask", "bbox", "keypoints"],
        ...     same_on_batch=False,
        ...     random_apply=10,
        ... )
        >>> out = aug_list(input, mask, bbox, points)
        >>> [o.shape for o in out]
        [torch.Size([2, 3, 5, 6]), torch.Size([2, 3, 5, 6]), torch.Size([2, 4, 2]), torch.Size([2, 1, 2])]
        >>> # apply the exact augmentation again.
        >>> out_rep = aug_list(input, mask, bbox, points, params=aug_list._params)
        >>> [(o == o_rep).all() for o, o_rep in zip(out, out_rep)]
        [tensor(True), tensor(True), tensor(True), tensor(True)]
        >>> # inverse the augmentations
        >>> out_inv = aug_list.inverse(*out)
        >>> [o.shape for o in out_inv]
        [torch.Size([2, 3, 5, 6]), torch.Size([2, 3, 5, 6]), torch.Size([2, 4, 2]), torch.Size([2, 1, 2])]

    This example demonstrates the integration of VideoSequential and AugmentationSequential.

        >>> import kornia
        >>> input = torch.randn(2, 3, 5, 6)[None]
        >>> mask = torch.ones(2, 3, 5, 6)[None]
        >>> bbox = torch.tensor([[
        ...     [1., 1.],
        ...     [2., 1.],
        ...     [2., 2.],
        ...     [1., 2.],
        ... ]]).expand(2, -1, -1)[None]
        >>> points = torch.tensor([[[1., 1.]]]).expand(2, -1, -1)[None]
        >>> aug_list = AugmentationSequential(
        ...     VideoSequential(
        ...         kornia.augmentation.ColorJiggle(0.1, 0.1, 0.1, 0.1, p=1.0),
        ...         kornia.augmentation.RandomAffine(360, p=1.0),
        ...     ),
        ...     data_keys=["input", "mask", "bbox", "keypoints"]
        ... )
        >>> out = aug_list(input, mask, bbox, points)
        >>> [o.shape for o in out]
        [torch.Size([1, 2, 3, 5, 6]), torch.Size([1, 2, 3, 5, 6]), torch.Size([1, 2, 4, 2]), torch.Size([1, 2, 1, 2])]

    Perform ``OneOf`` transformation with ``random_apply=1`` and ``random_apply_weights`` in ``AugmentationSequential``.

        >>> import kornia
        >>> input = torch.randn(2, 3, 5, 6)[None]
        >>> mask = torch.ones(2, 3, 5, 6)[None]
        >>> bbox = torch.tensor([[
        ...     [1., 1.],
        ...     [2., 1.],
        ...     [2., 2.],
        ...     [1., 2.],
        ... ]]).expand(2, -1, -1)[None]
        >>> points = torch.tensor([[[1., 1.]]]).expand(2, -1, -1)[None]
        >>> aug_list = AugmentationSequential(
        ...     VideoSequential(
        ...         kornia.augmentation.RandomAffine(360, p=1.0),
        ...     ),
        ...     VideoSequential(
        ...         kornia.augmentation.ColorJiggle(0.1, 0.1, 0.1, 0.1, p=1.0),
        ...     ),
        ...     data_keys=["input", "mask", "bbox", "keypoints"],
        ...     random_apply=1,
        ...     random_apply_weights=[0.5, 0.3]
        ... )
        >>> out = aug_list(input, mask, bbox, points)
        >>> [o.shape for o in out]
        [torch.Size([1, 2, 3, 5, 6]), torch.Size([1, 2, 3, 5, 6]), torch.Size([1, 2, 4, 2]), torch.Size([1, 2, 1, 2])]
    NFT)ZresampleZalign_corners)	data_keyssame_on_batchreturn_transformkeepdimrandom_applyrandom_apply_weights
extra_args)	argsr   r   r   r   r    r!   r"   returnc          
         s   t  j||||||d dd |D | _tdd | jD sTtdt d| d| jd	 tjkrvtd
tj dd| _d| _	|D ]@}	t
|	tr|	 std t
|	trd| _t
|	trd| _	qd | _|| _d S )N)r   r   r   r    r!   c                 S   s   g | ]}t |qS  r   get.0inpr%   r%   n/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/augmentation/container/augment.py
<listcomp>       z3AugmentationSequential.__init__.<locals>.<listcomp>c                 s   s   | ]}|t v V  qd S N)r   )r)   Zin_typer%   r%   r+   	<genexpr>   r-   z2AugmentationSequential.__init__.<locals>.<genexpr>z`data_keys` must be in z. Got .r   zThe first input must be FzSGeometric transformation detected in PatchSeqeuntial, which would break bbox, mask.T)super__init__r   allAssertionErrorr   INPUTNotImplementedErrorcontains_video_sequentialcontains_3d_augmentation
isinstancer   is_intensity_onlywarningswarnr   r   _transform_matrixr"   )
selfr   r   r   r   r    r!   r"   r#   arg	__class__r%   r+   r2      s0    	


zAugmentationSequential.__init__)inputr$   c                 C   s   | j rtd|S td|S dS )zReturn identity matrix.      N)r8   r   )r>   rB   r%   r%   r+   identity_matrix   s    
z&AugmentationSequential.identity_matrix)r$   c                 C   s   | j S r.   )r=   )r>   r%   r%   r+   transform_matrix   s    z'AugmentationSequential.transform_matrixparamsr   )r#   rH   r   r$   c             	   G   s6  |du r"t tttttf  | j}dd |D }t|t|kr^tdt| dt| d| j	|d|i}|du r| j
du rtd| j
}dgt| }tt||D ]^\}\}}tj| jv r| jtj }	ni }	|tjkrt|ttfr|\}
}nt|tfr|j}
n|}
tt| |ddd	 |ddd	 D ]\\}}}t|ttfrp||v rj|| n|}nd}t|tr|tv rt|tsq:t|tr| r|tv rq:t|tr6|tjtjfvr6|
d
}|
jd	g|
j dd R  }
t!j"|
||||	d}
|
j|d	g|
j dd R  }
nt|t#rLt$dnt|t%rt|tv rtt!"|
|||}
nht|t&ttfr|tv rt!j"|
||||	d}
n6t|t'frtd| dnt$d| d| dq:t|tfr|
|_(|) ||< q|
||< qt|dkr2t|ttfr2|d
 S |S )zReverse the transformation applied.

        Number of input tensors must align with the number of``data_keys``. If ``data_keys`` is not set, use
        ``self.data_keys`` by default.
        Nc                 S   s   g | ]}t |qS r%   r&   r(   r%   r%   r+   r,      r-   z2AugmentationSequential.inverse.<locals>.<listcomp>zBThe number of inputs must align with the number of data_keys, Got  and r0   r   zrNo parameters available for inversing, please run a forward pass first or passing valid params into this function.r      r"      4Geometric involved PatchSequential is not supported.Unsupported Sequential 	data_key  is not implemented for )*r	   r   r   strintr   r   lenr4   _arguments_preproc_params
ValueError	enumeratezipr5   r"   r9   tuplelistr   datar   Zget_forward_sequencer   r   r   r   r:   r   MASKsizeviewshaper   Zinverse_by_keyr   r6   r   r   r   _data	to_tensor)r>   rH   r   r#   
_data_keysoutputsidxr?   dcater"   rB   _namemoduleparam
batch_sizer%   r%   r+   inverse   s    

6 
 

zAugmentationSequential.inverse)outputlabelr$   c                 C   s`   t |dkr,t|ttfr,| jr,|d |fS t |dkrNt|ttfrN|d S | jr\||fS |S )NrM   r   )rT   r9   rZ   r[   return_label)r>   rm   rn   r%   r%   r+   __packup_output__  s     z(AugmentationSequential.__packup_output__)r#   r   c                G   s2   t |t |kr.tdt | dt | dd S )NzBThe number of inputs must align with the number of data_keys. Got rI   r0   )rT   r4   )r>   r   r#   r%   r%   r+   _validate_args_datakeys(  s    z.AugmentationSequential._validate_args_datakeysc                G   s   g }t ||D ]\}}t|tjtjtjfv r<|| qt|tjtjtj	fv rt|tjfv rnd}nHt|tjfv rd}n0t|tj	fv rd}nt
dt|j d|tj||d qtd| dq|S )	NZvertices_plusZxyxyZxywhzUnsupported mode `z`.)modezinput type of z is not implemented.)rY   r   r'   r5   r]   Z	KEYPOINTSappendBBOX	BBOX_XYXY	BBOX_XYWHrW   rh   r   Zfrom_tensorr6   )r>   r   r#   r*   r?   rf   rr   r%   r%   r+   rU   /  s    z)AugmentationSequential._arguments_preproc)rn   rH   r   )r#   rn   rH   r   r$   c             
      s  |du r| j }ndd |D }|| _ | j|d|i | j|d|i}|du rtj|v r||tj }|}t|ttfrt	dt
| d| js| jr| j|dd\}}	n| j|d	d\}}	| |	}nt	d
dgt| }
| jp|dup| || _tt||D ]z\}\}}|| jv r.| j| }ni }|tjkr|| }t j||||d}| j||d| _| jrttttf |\}}n
tt|}||
|< qt|tfr|j}n|}|D ]}| |j}t|t r|tv rt|t!sqt|t"r|# r|tv rqt|t$r|tjtj%fvr|&d}|j'dg|j(dd R  }t)j*||||||d\}}|j'|dg|j(dd R  }nt|t+rt,dnt|t-t"t!fr|tv rt)j*||||||d\}}nnt|t.r|tj/tj0fv r
tj1}|||j|gd}n6t|t2fr>t	d| dnt,d| d| dqt|tfrz||_3|4 |
|< n||
|< q| 5|
|S )zHCompute multiple tensors simultaneously according to ``self.data_keys``.Nc                 S   s   g | ]}t |qS r%   r&   r(   r%   r%   r+   r,   N  r-   z2AugmentationSequential.forward.<locals>.<listcomp>r   z `INPUT` should be a tensor but `z` received.)rD      )Z	dim_range)rK   rC   z;`params` must be provided whilst INPUT is not in data_keys.)rH   r"   )rH   r   rJ   rK   rL   rM   rN   rG   rO   r0   rP   rQ   )6r   rq   rU   r   r5   indexr9   rZ   r[   rW   typer7   r8   Zautofill_dimZforward_parametersrT   ro   Zcontains_label_operationsrX   rY   r"   r1   forwardZget_transformation_matrixr=   r	   r   r
   r   r\   Zget_submodulerh   r   r   r   r:   r   r]   r^   r_   r`   r   Zapply_by_keyr   r6   r   r   ru   rv   rt   r   ra   rb   rp   )r>   rn   rH   r   r#   rc   _inputr*   rg   Z	out_shaperd   re   r?   rf   r"   Z_inpZ_outrB   rj   ri   rk   r@   r%   r+   rz   B  s    	


 
 
zAugmentationSequential.forward)N)"__name__
__module____qualname____doc__r   r5   r]   dictr   ZNEARESTr   r   r   r   rR   rS   r   boolr   floatr   r   r2   r
   rE   propertyrF   r   rl   rp   rq   rU   rz   __classcell__r%   r%   r@   r+   r      s^   u

)
\ .
.)*r;   	itertoolsr   typingr   r   r   r   r   r   r	   Ztorchr
   Zkornia.augmentationr   r   r   r   Z kornia.augmentation._2d.mix.baser   Zkornia.augmentation.baser   Z"kornia.augmentation.container.baser   Z#kornia.augmentation.container.imager   r   Z#kornia.augmentation.container.patchr   Z#kornia.augmentation.container.utilsr   Z#kornia.augmentation.container.videor   Zkornia.constantsr   r   Zkornia.geometry.boxesr   Zkornia.utilsr   __all__r   r%   r%   r%   r+   <module>   s    $