a
    d}3                     @   s   d dl mZmZmZmZmZmZmZ d dlZd dl	m
Z
 d dl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mZmZ d dlmZmZ d	gZG d
d	 d	eZdS )    )AnyDictListOptionalTupleUnioncastN)
RandomCrop)MixAugmentationBaseMixAugmentationBaseV2)_AugmentationBase)SequentialBase)ImageSequential	ParamItem_get_new_batch_shape)InputApplyInverseMaskApplyInverseVideoSequentialc                
       st  e Zd ZdZdddddejeeee	ee
e	e	f f eee  dd fdd	Zeje	ejd
ddZeje	ejdddZejeej e	e
ejeej f dddZejeej e	e
ejeej f dddZejee dddZdi fejeee  eeef ejd fddZddi fejeej eee  eeef eeje
ejejf f d fddZ  ZS )r   a  VideoSequential for processing 5-dim video data like (B, T, C, H, W) and (B, C, T, H, W).

    `VideoSequential` is used to replace `nn.Sequential` for processing video data augmentations.
    By default, `VideoSequential` enabled `same_on_frame` to make sure the same augmentations happen
    across temporal dimension. Meanwhile, it will not affect other augmentation behaviours like the
    settings on `same_on_batch`, etc.

    Args:
        *args: a list of augmentation module.
        data_format: only BCTHW and BTCHW are supported.
        same_on_frame: apply the same transformation across the channel per frame.
        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 None, the whole list of args will be processed as a sequence.

    Note:
        Transformation matrix returned only considers the transformation applied in ``kornia.augmentation`` module.
        Those transformations in ``kornia.geometry`` will not be taken into account.

    Example:
        If set `same_on_frame` to True, we would expect the same augmentation has been applied to each
        timeframe.

        >>> input, label = torch.randn(2, 3, 1, 5, 6).repeat(1, 1, 4, 1, 1), torch.tensor([0, 1])
        >>> aug_list = VideoSequential(
        ...     kornia.augmentation.ColorJiggle(0.1, 0.1, 0.1, 0.1, p=1.0),
        ...     kornia.color.BgrToRgb(),
        ...     kornia.augmentation.RandomAffine(360, p=1.0),
        ...     random_apply=10,
        ...     data_format="BCTHW",
        ...     same_on_frame=True)
        >>> output = aug_list(input)
        >>> (output[0, :, 0] == output[0, :, 1]).all()
        tensor(True)
        >>> (output[0, :, 1] == output[0, :, 2]).all()
        tensor(True)
        >>> (output[0, :, 2] == output[0, :, 3]).all()
        tensor(True)

        If set `same_on_frame` to False:

        >>> aug_list = VideoSequential(
        ...     kornia.augmentation.ColorJiggle(0.1, 0.1, 0.1, 0.1, p=1.0),
        ...     kornia.augmentation.RandomAffine(360, p=1.0),
        ...     kornia.augmentation.RandomMixUp(p=1.0),
        ... data_format="BCTHW",
        ... same_on_frame=False)
        >>> output, lab = aug_list(input)
        >>> output.shape, lab.shape
        (torch.Size([2, 3, 4, 5, 6]), torch.Size([2, 4, 3]))
        >>> (output[0, :, 0] == output[0, :, 1]).all()
        tensor(False)

        Reproduce with provided params.
        >>> out2, lab2 = aug_list(input, label, params=aug_list._params)
        >>> torch.equal(output, out2)
        True

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

        >>> import kornia
        >>> input, label = torch.randn(2, 3, 1, 5, 6).repeat(1, 1, 4, 1, 1), torch.tensor([0, 1])
        >>> aug_list = VideoSequential(
        ...     kornia.augmentation.ColorJiggle(0.1, 0.1, 0.1, 0.1, p=1.0),
        ...     kornia.augmentation.RandomAffine(360, p=1.0),
        ...     kornia.augmentation.RandomMixUp(p=1.0),
        ... data_format="BCTHW",
        ... same_on_frame=False,
        ... random_apply=1,
        ... random_apply_weights=[0.5, 0.3, 0.8]
        ... )
        >>> out= aug_list(input, label)
        >>> out[0].shape
        torch.Size([2, 3, 4, 5, 6])
    BTCHWTFN)data_formatsame_on_framerandom_applyrandom_apply_weights)argsr   r   r   r   returnc                   sl   t  j|d d ||d || _| | _| jdvrBtd| d|  | jdkrXd| _n| jdkrhd| _d S )	N)Zsame_on_batchZkeepdimr   r   )BCTHWr   z-Only `BCTHW` and `BTCHW` are supported. Got `z`.r      r      )super__init__r   upperr   AssertionError_temporal_channel)selfr   r   r   r   r   	__class__ l/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/augmentation/container/video.pyr   a   s     



zVideoSequential.__init__)batch_shapechennel_indexr   c                 C   s$   t tj|d | ||d d   S )Nr   )r   torchSize)r#   r(   r)   r&   r&   r'   '__infer_channel_exclusive_batch_shape__z   s    z7VideoSequential.__infer_channel_exclusive_batch_shape__)param	frame_numr   c                 C   sV   |ddddf j d|gdgt|jdd  R  }|jdgt|jdd R  S )af  Repeat parameters across channels.

        The input is shaped as (B, ...), while to output (B * same_on_frame, ...), which
        to guarantee that the same transformation would happen for each frame.

        (B1, B2, ..., Bn) => (B1, ... B1, B2, ..., B2, ..., Bn, ..., Bn)
                              | ch_size | | ch_size |  ..., | ch_size |
        N.r   )repeatlenshapereshapelist)r#   r-   r.   Zrepeatedr&   r&   r'    __repeat_param_across_channels__~   s    	6z0VideoSequential.__repeat_param_across_channels__)inputlabelr.   r   c                 C   s   | j dkr|dd}| j dkr |d ur|j|jd d krH|d}nb|j|jd d krt|d d|d}n6|jt|jd |jd  gkrntd|j d	|jdg|jdd  R  }||fS )
Nr   r   r   r   r/   ).Nr   zInvalid label shape of .)	r   	transposer2   viewr0   r*   r+   NotImplementedErrorr3   r#   r6   r7   r.   r&   r&   r'   _input_shape_convert_in   s    

"z'VideoSequential._input_shape_convert_inc                 C   sb   |j d|g|jdd  R  }| jdkr4|dd}| jdkr>|d urZ| |d|d}||fS )Nr/   r   r   r   r   r   )r:   r2   r   r9   sizer<   r&   r&   r'   _input_shape_convert_back   s    

z)VideoSequential._input_shape_convert_back)r(   r   c              	   C   s  || j  }|  }| || j }| jsFt|d | g|dd  }g }|D ]L\}}t|tr||}| jr|d 	|dd|d< |d 	|dd|d< t
||}nt|tfr||}	| jrtdt
||	}nt|tttfr~||}| jrr| D ]j\}
}|
dkr<t|tjjst|tjjr<q|
dkrX||
|i q||
| ||i qt
||}n
t
|d }t||}|| qN|S )Nr   r   srcdstz:Sequential is currently unsupported for ``same_on_frame``.orderZforward_input_shape)r"   Zget_forward_sequencer,   r   r*   r+   
isinstancer	   Zforward_parameters_precropr0   r   r   forward_parameters
ValueErrorr   r
   r   itemskorniaZaugmentationZColorJiggleZColorJitterupdater5   r   append)r#   r(   r.   Znamed_modulesparamsnamemoduleZ	mod_paramr-   Z	seq_paramkvr&   r&   r'   rD      sJ    
 







z"VideoSequential.forward_parameters)r6   rJ   
extra_argsr   c                    s   | j ttfv r.|| j}| |d|\}}n&|d}|jdg|jdd R  }t j	|||d}| j ttfv r| 
|d|\}}n|j|dg|jdd R  }|S )zInverse transformation.

        Used to inverse a tensor according to the performed transformation by a forward pass, or with respect to
        provided parameters.
        Nr   r/   r   rO   r   )apply_inverse_funcr   r   r>   r"   r=   r:   r2   r   inverser?   )r#   r6   rJ   rO   r.   _
batch_sizer$   r&   r'   rR      s    
zVideoSequential.inverse)r6   r7   rJ   rO   r   c           
         s  t |jdkr td|j d|du r4| |j}| jttfv rb|| j}| 	|||\}}n<|durxt
d| |d}|jdg|jdd R  }t j||||d	}| jrtttjtjf |\}}nttj|}t|ttfrd| jttfv r$| |d ||\}	}|	|d
 f}n>|dur<t
d| |d j|dg|d jd
d R  }nZ| jttfv r| |||\}}n6|durt
d| |j|dg|jd
d R  }| ||S )z'Define the video computation performed.   z"Input must be a 5-dim tensor. Got r8   NzInvalid label value. Got r   r/   r   rP   r   )r1   r2   r!   rD   rQ   r   r   r>   r"   r=   rE   r:   r   forwardZreturn_labelr   r   r*   TensorrC   tupler4   r?   Z__packup_output__)
r#   r6   r7   rJ   rO   r.   rT   outoutputZ_outr$   r&   r'   rV      s8    

(
zVideoSequential.forward)__name__
__module____qualname____doc__nnModulestrboolr   intr   r   r   floatr   r*   r+   r,   rW   r5   r=   r?   r   rD   r   r   rR   rV   __classcell__r&   r&   r$   r'   r      sJ   R
-

)typingr   r   r   r   r   r   r   r*   Ztorch.nnr_   rG   Zkornia.augmentationr	   Z kornia.augmentation._2d.mix.baser
   r   Zkornia.augmentation.baser   Z"kornia.augmentation.container.baser   Z#kornia.augmentation.container.imager   r   r   Z#kornia.augmentation.container.utilsr   r   __all__r   r&   r&   r&   r'   <module>   s   $