o
    oi=                     @   s   d dl mZ d dlmZmZmZ d dlmZmZm	Z	 d dl
mZmZ d dlmZ dedee defd	d
Z	ddededededededefddZG dd deZdS )    )List)ModuleTensorpad)KORNIA_CHECKKORNIA_CHECK_IS_TENSORKORNIA_CHECK_SHAPE)filter3dget_gaussian_kernel3d)_compute_paddingimgcropping_shapereturnc              	   C   s:   t | |d  |d  |d  |d  |d  |d  fS )z.Crop out the part of "valid" convolution area.            r      )r   )r   r    r   I/home/ubuntu/.local/lib/python3.10/site-packages/kornia/metrics/ssim3d.py_crop   s   r         ?-q=sameimg1img2window_sizemax_valepspaddingc                 C   s  t |  t | t| g d t|g d t| j|jkd| j d|j  t|ts5tdt| t|||fd}d| d }d| d }t	| |}	t	||}
g }|d	kru|jd
d \}}}t
|||g}t|	|}	t|
|}
n|dkrz	 |	d }|
d }|	|
 }t	| d |}t	|d |}t	| | |}|d	krt||}t||}t||}n|dkr	 || }|| }|| }d| | d| |  }|| | || |  }|||  S )ab  Compute the Structural Similarity (SSIM) index map between two images.

    Measures the (SSIM) index between each element in the input `x` and target `y`.

    The index can be described as:

    .. math::

      \text{SSIM}(x, y) = \frac{(2\mu_x\mu_y+c_1)(2\sigma_{xy}+c_2)}
      {(\mu_x^2+\mu_y^2+c_1)(\sigma_x^2+\sigma_y^2+c_2)}

    where:
      - :math:`c_1=(k_1 L)^2` and :math:`c_2=(k_2 L)^2` are two variables to
        stabilize the division with weak denominator.
      - :math:`L` is the dynamic range of the pixel-values (typically this is
        :math:`2^{\#\text{bits per pixel}}-1`).

    Args:
        img1: the first input image with shape :math:`(B, C, D, H, W)`.
        img2: the second input image with shape :math:`(B, C, D, H, W)`.
        window_size: the size of the gaussian kernel to smooth the images.
        max_val: the dynamic range of the images.
        eps: Small value for numerically stability when dividing.
        padding: ``'same'`` | ``'valid'``. Whether to only use the "valid" convolution
         area to compute SSIM to match the MATLAB implementation of original SSIM paper.

    Returns:
       The ssim index map with shape :math:`(B, C, D, H, W)`.

    Examples:
        >>> input1 = torch.rand(1, 4, 5, 5, 5)
        >>> input2 = torch.rand(1, 4, 5, 5, 5)
        >>> ssim_map = ssim3d(input1, input2, 5)  # 1x4x5x5x5

    )BCDHWz,img1 and img2 shapes must be the same. Got: z and z'Input max_val type is not a float. Got )      ?r%   r%   g{Gz?r   gQ?validNr   g       @)r   r   r   shape
isinstancefloat	TypeErrortyper
   r	   r   r   )r   r   r   r   r   r   kernelC1C2mu1mu2r   depthheightwidthmu1_sqmu2_sqmu1_mu2
mu_img1_sq
mu_img2_sqmu_img1_img2	sigma1_sq	sigma2_sqsigma12numdenr   r   r   ssim3d)   sL   &"





r@   c                       sN   e Zd ZdZddedededed	d
f
 fddZdeded	efddZ	  Z
S )SSIM3Da=  Create a module that computes the Structural Similarity (SSIM) index between two 3D images.

    Measures the (SSIM) index between each element in the input `x` and target `y`.

    The index can be described as:

    .. math::

      \text{SSIM}(x, y) = \frac{(2\mu_x\mu_y+c_1)(2\sigma_{xy}+c_2)}
      {(\mu_x^2+\mu_y^2+c_1)(\sigma_x^2+\sigma_y^2+c_2)}

    where:
      - :math:`c_1=(k_1 L)^2` and :math:`c_2=(k_2 L)^2` are two variables to
        stabilize the division with weak denominator.
      - :math:`L` is the dynamic range of the pixel-values (typically this is
        :math:`2^{\#\text{bits per pixel}}-1`).

    Args:
        window_size: the size of the gaussian kernel to smooth the images.
        max_val: the dynamic range of the images.
        eps: Small value for numerically stability when dividing.
        padding: ``'same'`` | ``'valid'``. Whether to only use the "valid" convolution
         area to compute SSIM to match the MATLAB implementation of original SSIM paper.

    Shape:
        - Input: :math:`(B, C, D, H, W)`.
        - Target :math:`(B, C, D, H, W)`.
        - Output: :math:`(B, C, D, H, W)`.

    Examples:
        >>> input1 = torch.rand(1, 4, 5, 5, 5)
        >>> input2 = torch.rand(1, 4, 5, 5, 5)
        >>> ssim = SSIM3D(5)
        >>> ssim_map = ssim(input1, input2)  # 1x4x5x5x5

    r   r   r   r   r   r   r   r   Nc                    s&   t    || _|| _|| _|| _d S N)super__init__r   r   r   r   )selfr   r   r   r   	__class__r   r   rD      s
   

zSSIM3D.__init__r   r   c                 C   s   t ||| j| j| j| jS rB   )r@   r   r   r   r   )rE   r   r   r   r   r   forward   s   zSSIM3D.forwardr   r   r   )__name__
__module____qualname____doc__intr*   strrD   r   rH   __classcell__r   r   rF   r   rA      s    $%rA   NrI   )typingr   kornia.corer   r   r   kornia.core.checkr   r   r   kornia.filtersr	   r
   kornia.filters.filterr   rN   r   r*   rO   r@   rA   r   r   r   r   <module>   s.   
^