
    3jE7                        S SK JrJrJr  S SKrS SKJr  S SKJr  / SQr " S S\R                  5      r
 SS\R                  S	\S
\S\S\S\\R                  \R                  \\R                     4   4S jjrSS\R                  S	\S
\S\S\R                  4
S jjr SS\R                  S\R                  S\R                  S	\S\R                  4
S jjrg)    )ListOptionalTupleN)nn)_torch_svd_cast)ZCAWhiteninglinear_transformzca_mean
zca_whitenc                      ^  \ rS rSrSr     SS\S\S\S\S\SS	4U 4S
 jjjrS\	R                  SS 4S jrSS\	R                  S\S\	R                  4S jjrS\	R                  S\	R                  4S jrSrU =r$ )r      a  Compute the ZCA whitening matrix transform and the mean vector and applies the transform to the data.

The data torch.Tensor is flattened, and the mean :math:`\mathbf{\mu}`
and covariance matrix :math:`\mathbf{\Sigma}` are computed from
the flattened data :math:`\mathbf{X} \in \mathbb{R}^{N \times D}`, where
:math:`N` is the sample size and :math:`D` is flattened dimensionality
(e.g. for a torch.Tensor with size 5x3x2x2 :math:`N = 5` and :math:`D = 12`). The ZCA whitening
transform is given by:

.. math::

    \mathbf{X}_{\text{zca}} = (\mathbf{X - \mu})(US^{-\frac{1}{2}}U^T)^T

where :math:`U` are the eigenvectors of :math:`\Sigma` and :math:`S` contain the corresponding
eigenvalues of :math:`\Sigma`. After the transform is applied, the output is reshaped to same shape.

Args:
    dim: Determines the dimension that represents the samples axis.
    eps: a small number used for numerical stability.
    unbiased: Whether to use the biased estimate of the covariance matrix.
    compute_inv: Compute the inverse transform matrix.
    detach_transforms: Detaches gradient from the ZCA fitting.

shape:
    - x: :math:`(D_0,...,D_{\text{dim}},...,D_N)` is a batch of N-D tensors.
    - x_whiten: :math:`(D_0,...,D_{\text{dim}},...,D_N)` same shape as input.

.. note::
   See a working example `here <https://colab.sandbox.google.com/github/kornia/tutorials/
   blob/master/source/zca_whitening.ipynb>`__.

Examples:
    >>> x = torch.tensor([[0,1],[1,0],[-1,0],[0,-1]], dtype = torch.float32)
    >>> zca = ZCAWhitening().fit(x)
    >>> x_whiten = zca(x)
    >>> zca = ZCAWhitening()
    >>> x_whiten = zca(x, include_fit = True) # Includes the fitting step
    >>> x_whiten = zca(x) # Can run now without the fitting set
    >>> # Enable backprop through ZCA fitting process
    >>> zca = ZCAWhitening(detach_transforms = False)
    >>> x_whiten = zca(x, include_fit = True) # Includes the fitting step

Note:
    This implementation uses :py:meth:`~torch.svd` which yields NaNs in the backwards step
    if the singular values are not unique. See `here <https://pytorch.org/docs/stable/torch.html#torch.svd>`_ for
    more information.

References:
    [1] `Stanford PCA & ZCA whitening tutorial <http://ufldl.stanford.edu/tutorial/unsupervised/PCAWhitening/>`_

dimepsunbiaseddetach_transformscompute_invreturnNc                 x   > [         TU ]  5         Xl        X l        X0l        X@l        XPl        SU l        U   U   U   g )NF)super__init__r   r   r   r   r   fitted)selfr   r   r   r   r   	__class__s         L/home/wildlama/miniconda3/lib/python3.13/site-packages/kornia/enhance/zca.pyr   ZCAWhitening.__init__Q   s;     	 !2&    xc                    [        XR                  U R                  U R                  U R                  5      u  p#nX0l        X l        Uc  [        R                  " S/5      U l	        OX@l	        U R                  (       a]  U R
                  R                  5       U l        U R                  R                  5       U l        U R                  R                  5       U l	        SU l        U $ )z}Fit ZCA whitening matrices to the data.

Args:
    x: Input data.

Returns:
    Returns a fitted ZCAWhiten object instance.

r   T)r
   r   r   r   r   mean_vectortransform_matrixtorchemptytransform_invr   detachr   )r   r   TmeanT_invs        r   fitZCAWhitening.fitg   s     "!XXt}}dhhHXHXY !=!&aS!1D!&!!#//668D$($9$9$@$@$BD!!%!3!3!:!:!<Dr   include_fitc                     U(       a  U R                  U5        U R                  (       d  [        S5      e[        XR                  U R
                  U R                  5      nU$ )zApply the whitening transform to the data.

Args:
    x: Input data.
    include_fit: Indicates whether to fit the data as part of the forward pass.

Returns:
    The transformed data.

TNeeds to be fitted first before running. Please call fit or set include_fit to True.)r(   r   RuntimeErrorr	   r    r   r   )r   r   r*   x_whitens       r   forwardZCAWhitening.forward   sK     HHQK{{uvv#A'<'<d>N>NPTPXPXYr   c                    U R                   (       d  [        S5      eU R                  (       d  [        S5      eU R                  c  [	        S5      eU R
                  R                  U R                  5      * n[        XR                  U5      nU$ )zmApply the inverse transform to the whitened data.

Args:
    x: Whitened data.

Returns:
    Original data.

r,   z;Did not compute inverse ZCA. Please set compute_inv to Truez<The transform inverse should be a torch.Tensor. Gotcha None.)	r   r-   r   r#   	TypeErrorr   mmr    r	   )r   r   mean_invys       r   inverse_transformZCAWhitening.inverse_transform   sz     {{uvv\]]%Z[["&"2"2"5"5d6K6K"L!LQ 2 2H=r   )	r   r   r   r   r   r   r#   r    r   )r   ư>TTF)F)__name__
__module____qualname____firstlineno____doc__intfloatboolr   r!   Tensorr(   r/   r6   __static_attributes____classcell__)r   s   @r   r   r      s    2l "&!33 3 	3
  3 3 
3 3,U\\ n 8 D U\\ *5<< ELL  r   r   inpr   r   r   return_inverser   c           	         [        U [        R                  5      (       d  [        S[	        U 5       35      e[        U[
        5      (       d  [        S[	        U5       35      e[        U[        5      (       d  [        S[	        U5       35      e[        U[        5      (       d  [        S[	        U5       35      e[        U[        5      (       d  [        S[	        U5       35      eU R                  5       nU[        U5      :  d  U[        U5      * :  a*  [        S[        U5      *  S[        U5      S-
   S	U 35      eUS
:  a  [        U5      U-   n[        R                  " [        R                  " S
U5      [        R                  " US-   [        U5      5      /5      n[        R                  " [        R                  " U/5      U/5      R                  5       nU R                  U5      nXQ   n	[        R                  " US
U XQS-   S -   5      n
[        [        R                   " U
5      R#                  5       5      n[        R$                  " US
SS9nUR'                  SU45      nUR'                  X45      U-
  nUR)                  5       R+                  U5      nU(       a  U[        U	S-
  5      -  nOU[        U	5      -  n[-        U5      u  nnnUR'                  SS5      n[        R.                  " UU-   5      nUR+                  UUR)                  5       -  5      nSnU(       a9  UR+                  [        R0                  " UU-   5      UR)                  5       -  5      nUUU4$ )a  Compute the ZCA whitening matrix and mean vector.

The output can be used with :py:meth:`~kornia.color.linear_transform`.
See :class:`~kornia.color.ZCAWhitening` for details.

Args:
    inp: input data torch.Tensor.
    dim: Specifies the dimension that serves as the samples dimension.
    unbiased: Whether to use the unbiased estimate of the covariance matrix.
    eps: a small number used for numerical stability.
    return_inverse: Whether to return the inverse ZCA transform.

Shapes:
    - inp: :math:`(D_0,...,D_{\text{dim}},...,D_N)` is a batch of N-D tensors.
    - transform_matrix: :math:`(\Pi_{d=0,d\neq \text{dim}}^N D_d, \Pi_{d=0,d\neq \text{dim}}^N D_d)`
    - mean_vector: :math:`(1, \Pi_{d=0,d\neq \text{dim}}^N D_d)`
    - inv_transform: same shape as the transform matrix

Returns:
    A tuple containing the ZCA matrix and the mean vector. If return_inverse is set to True,
    then it returns the inverse ZCA matrix, otherwise it returns None.

.. note::
   See a working example `here <https://colab.sandbox.google.com/github/kornia/tutorials/
   blob/master/source/zca_whitening.ipynb>`__.

Examples:
    >>> x = torch.tensor([[0,1],[1,0],[-1,0],[0,-1]], dtype = torch.float32)
    >>> transform_matrix, mean_vector,_ = zca_mean(x) # Returns transformation matrix and data mean
    >>> x = torch.rand(3,20,2,2)
    >>> transform_matrix, mean_vector, inv_transform = zca_mean(x, dim = 1, return_inverse = True)
    >>> # transform_matrix.size() equals (12,12) and the mean vector.size equal (1,12)

&Input type is not a torch.Tensor. Got eps type is not a float. Gotunbiased type is not bool. Got(Argument 'dim' must be of type int. Got z-Argument return_inverse must be of type bool 4Dimension out of range (expected to be in range of [,   ], but got r   NT)r   keepdim)
isinstancer!   rA   r2   typer?   r@   r>   sizelen
IndexErrorcatarangetensortolistpermuteproditemr&   reshapetr3   r   rsqrtsqrt)rD   r   r   r   rE   inp_size	feat_dims	new_orderinp_permuteNfeature_sizesnum_featuresr&   inp_center_flatcovUS_
S_inv_rootr%   r'   s                        r   r
   r
      s   J c5<<((@cLMMc5!!6tCykBCCh%%8h8HIJJc3B49+NOOnd++G^H\G]^__xxzH
c(msc(m^3BCM>BRRSTWX`TadeTeSffqruqvw
 	
 Qw(mc!		5<<3/cAgs8}1UVWI 99ellC5&99%EFMMOI++i(KALL!C8!GK3H!HIMEJJ}5::<=LKQED<<L)*D$/$7$78I$JT$QO




 
 
1CE!a%L E!Hnc"GAq!			"aA${{1s73JffZ!##%/0A$(Euzz!c'*QSSU23dE>r   c                    [        U [        R                  5      (       d  [        S[	        U 5       35      e[        U[
        5      (       d  [        S[	        U5       35      e[        U[        5      (       d  [        S[	        U5       35      e[        U[        5      (       d  [        S[	        U5       35      e[        XX#S5      u  pEn[        XXQ5      nU$ )a  Apply ZCA whitening transform.

See :class:`~kornia.color.ZCAWhitening` for details.

Args:
    inp: input data torch.Tensor.
    dim: Specifies the dimension that serves as the samples dimension.
    unbiased: Whether to use the unbiased estimate of the covariance matrix.
    eps: a small number used for numerical stability.

Returns:
    Whiten Input data.

.. note::
   See a working example `here <https://colab.sandbox.google.com/github/kornia/tutorials/
   blob/master/source/zca_whitening.ipynb>`__.

Examples:
    >>> x = torch.tensor([[0,1],[1,0],[-1,0]], dtype = torch.float32)
    >>> zca_whiten(x)
    tensor([[ 0.0000,  1.1547],
            [ 1.0000, -0.5773],
            [-1.0000, -0.5773]])

rG   rH   rI   rJ   F)
rQ   r!   rA   r2   rR   r?   r@   r>   r
   r	   )rD   r   r   r   	transformr&   rl   
inp_whitens           r   r   r     s    4 c5<<((@cLMMc5!!6tCykBCCh%%8h8HIJJc3B49+NOO!#H5AIQ!#$<Jr   r    r   c           	         U R                  5       nU[        U5      :  d  U[        U5      * :  a*  [        S[        U5      *  S[        U5      S-
   SU 35      eUS:  a  [        U5      U-   n[        R                  " [        R
                  " SU5      [        R
                  " US-   [        U5      5      /5      n[        R                  " [        R                  " U/5      U/5      n[        R                  " U5      nUR                  5       nUR                  5       n	[        R                  " USU XCS-   S -   5      n
[        [        R                  " U
5      R                  5       5      nU R                  U5      nUR                  SU45      nX-
  nUR                  U5      nUR                  UR                  5       5      nUR                  U	5      nU$ )a  Given a transformation matrix and a mean vector, this function will flatten the input
torch.Tensor along the given dimension and subtract the mean vector from it. Then the dot
product with the transformation matrix will be computed and then the resulting torch.Tensor
is reshaped to the original input shape.

.. math::

    \mathbf{X}_{T} = (\mathbf{X - \mu})(T)

Args:
    inp: Input data :math:`X`.
    transform_matrix: Transform matrix :math:`T`.
    mean_vector: mean vector :math:`\mu`.
    dim: Batch dimension.

Shapes:
    - inp: :math:`(D_0,...,D_{\text{dim}},...,D_N)` is a batch of N-D tensors.
    - transform_matrix: :math:`(\Pi_{d=0,d\neq \text{dim}}^N D_d, \Pi_{d=0,d\neq \text{dim}}^N D_d)`
    - mean_vector: :math:`(1, \Pi_{d=0,d\neq \text{dim}}^N D_d)`

Returns:
    Transformed data.

Example:
    >>> # Example where dim = 3
    >>> inp = torch.ones((10,3,4,5))
    >>> transform_mat = torch.ones((10*3*4,10*3*4))
    >>> mean = 2*torch.ones((1,10*3*4))
    >>> out = linear_transform(inp, transform_mat, mean, 3)
    >>> print(out.shape, out.unique())  # Should a be (10,3,4,5) torch.tensor of -120s
    torch.Size([10, 3, 4, 5]) tensor([-120.])

    >>> # Example where dim = 0
    >>> inp = torch.ones((10,2))
    >>> transform_mat = torch.ones((2,2))
    >>> mean = torch.zeros((1,2))
    >>> out = linear_transform(inp, transform_mat, mean)
    >>> print(out.shape, out.unique()) # Should a be (10,2) torch.tensor of 2s
    torch.Size([10, 2]) tensor([2.])

rK   rL   rM   rN   r   NrP   )rS   rT   rU   r!   rV   rW   rX   argsortrY   r>   r[   r\   rZ   r]   r3   )rD   r    r   r   ra   rb   permperm_invrc   	inv_orderrf   rg   rd   inp_flat
inp_centerinp_transformeds                   r   r	   r	   A  s   X xxzH
c(msc(m^3BCM>BRRSTWX`TadeTeSffqruqvw
 	
 Qw(mc!		5<<3/cAgs8}1UVWI99ellC5)956D}}T"H;;=I#??,ILL!C8!GK3H!HIMEJJ}5::<=L++i(K""B#56H'J mm$45O%--k.>.>.@AO%--i8Or   )r   Tr8   F)r   Tr8   )r   )typingr   r   r   r!   r   kornia.core.utilsr   __all__Moduler   rA   r>   r@   r?   r
   r   r	    r   r   <module>r~      s  $ ) (   -
HS299 Sn gl_	__/3_AF__c_
5<<x'==>_D*ELL *s *$ *E *]b]i]i *\ ^_K	K).KDILLKWZK
\\Kr   