o
    .wi                     @   s   d dl mZ d dlmZmZmZmZ d dlZd dl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mZ d d	lmZmZ d d
lmZmZ esQdgZercdddZerbeesbddgZnddgZG dd deZdS )    )Sequence)AnyClassVarOptionalUnionN)Tensor)Literal)_LPIPS_lpips_compute_lpips_update_NoTrainLpips)Metric)_SKIP_SLOW_DOCTEST_try_proceed_with_timeout)_MATPLOTLIB_AVAILABLE_TORCHVISION_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPE*LearnedPerceptualImagePatchSimilarity.plotreturnc                   C   s   t ddd d S )NTvgg)
pretrainednet)r	    r   r   T/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/image/lpip.py_download_lpips    s   r   %LearnedPerceptualImagePatchSimilarityc                       s  e Zd ZU dZdZeed< dZeed< dZeed< dZ	e
ed< d	Ze
ed
< eed< eed< dZeed< dgZeee  ed< 			d&ded ded dededdf
 fddZdededdfddZdefd d!Z	d'd"eeeee f  d#ee defd$d%Z  ZS )(r   ad	  The Learned Perceptual Image Patch Similarity (`LPIPS_`) calculates perceptual similarity between two images.

    LPIPS essentially computes the similarity between the activations of two image patches for some pre-defined network.
    This measure has been shown to match human perception well. A low LPIPS score means that image patches are
    perceptual similar.

    Both input image patches are expected to have shape ``(N, 3, H, W)``. The minimum size of `H, W` depends on the
    chosen backbone (see `net_type` arg).

    .. hint::
        Using this metrics requires you to have ``torchvision`` package installed. Either install as
        ``pip install torchmetrics[image]`` or ``pip install torchvision``.

    As input to ``forward`` and ``update`` the metric accepts the following input

    - ``img1`` (:class:`~torch.Tensor`): tensor with images of shape ``(N, 3, H, W)``
    - ``img2`` (:class:`~torch.Tensor`): tensor with images of shape ``(N, 3, H, W)``

    As output of `forward` and `compute` the metric returns the following output

    - ``lpips`` (:class:`~torch.Tensor`): returns float scalar tensor with average LPIPS value over samples

    Args:
        net_type: str indicating backbone network type to use. Choose between `'alex'`, `'vgg'` or `'squeeze'`
        reduction: str indicating how to reduce over the batch dimension. Choose between `'sum'` or `'mean'`.
        normalize: by default this is ``False`` meaning that the input is expected to be in the [-1,1] range. If set
            to ``True`` will instead expect input to be in the ``[0,1]`` range.
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ModuleNotFoundError:
            If ``torchvision`` package is not installed
        ValueError:
            If ``net_type`` is not one of ``"vgg"``, ``"alex"`` or ``"squeeze"``
        ValueError:
            If ``reduction`` is not one of ``"mean"`` or ``"sum"``

    Example:
        >>> from torch import rand
        >>> from torchmetrics.image.lpip import LearnedPerceptualImagePatchSimilarity
        >>> lpips = LearnedPerceptualImagePatchSimilarity(net_type='squeeze')
        >>> # LPIPS needs the images to be in the [-1, 1] range.
        >>> img1 = (rand(10, 3, 100, 100) * 2) - 1
        >>> img2 = (rand(10, 3, 100, 100) * 2) - 1
        >>> lpips(img1, img2)
        tensor(0.1024)

    Tis_differentiableFhigher_is_betterfull_state_update        plot_lower_boundg      ?plot_upper_bound
sum_scorestotalr   feature_network__jit_ignored_attributes__alexmeannet_typer   r'   squeeze	reduction)sumr(   	normalizekwargsr   Nc                    s   t  jdi | tstdd}||vr td| d| dt|d| _d}||vr6td| d| || _t|t	sEtd	| || _
| jd
tddd | jdtddd d S )NzLPIPS metric requires that torchvision is installed. Either install as `pip install torchmetrics[image]` or `pip install torchvision`.r*   z#Argument `net_type` must be one of z
, but got .)r   )r(   r-   z$Argument `reduction` must be one of z/Argument `normalize` should be an bool but got r#   r    r-   )dist_reduce_fxr$   r   )super__init__r   ModuleNotFoundError
ValueErrorr   r   r,   
isinstanceboolr.   	add_statetorchtensor)selfr)   r,   r.   r/   valid_net_typevalid_reduction	__class__r   r   r3   h   s$   
z.LearnedPerceptualImagePatchSimilarity.__init__img1img2c                 C   s<   t ||| j| jd\}}|  j| 7  _|  j|7  _dS )z(Update internal states with lpips score.)r   r.   N)r   r   r.   r#   r-   r$   )r;   r@   rA   lossr$   r   r   r   update   s   z,LearnedPerceptualImagePatchSimilarity.updatec                 C   s   t | j| j| jS )z+Compute final perceptual similarity metric.)r
   r#   r$   r,   )r;   r   r   r   compute   s   z-LearnedPerceptualImagePatchSimilarity.computevalaxc                 C   s   |  ||S )a  Plot a single or multiple values from the metric.

        Args:
            val: Either a single result from calling `metric.forward` or `metric.compute` or a list of these results.
                If no value is provided, will automatically call `metric.compute` and plot that result.
            ax: An matplotlib axis object. If provided will add plot to that axis

        Returns:
            Figure and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single value
            >>> import torch
            >>> from torchmetrics.image.lpip import LearnedPerceptualImagePatchSimilarity
            >>> metric = LearnedPerceptualImagePatchSimilarity(net_type='squeeze')
            >>> metric.update(torch.rand(10, 3, 100, 100), torch.rand(10, 3, 100, 100))
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.image.lpip import LearnedPerceptualImagePatchSimilarity
            >>> metric = LearnedPerceptualImagePatchSimilarity(net_type='squeeze')
            >>> values = [ ]
            >>> for _ in range(3):
            ...     values.append(metric(torch.rand(10, 3, 100, 100), torch.rand(10, 3, 100, 100)))
            >>> fig_, ax_ = metric.plot(values)

        )_plot)r;   rE   rF   r   r   r   plot   s   (r   )r'   r(   F)NN)__name__
__module____qualname____doc__r   r7   __annotations__r   r   r!   floatr"   r   r%   strr&   r   listr   r   r3   rC   rD   r   r   r   r   r   rH   __classcell__r   r   r>   r   r   )   sF   
 1 )r   N)collections.abcr   typingr   r   r   r   r9   r   typing_extensionsr   #torchmetrics.functional.image.lpipsr	   r
   r   r   torchmetrics.metricr   torchmetrics.utilities.checksr   r   torchmetrics.utilities.importsr   r   torchmetrics.utilities.plotr   r   __doctest_skip__r   r   r   r   r   r   <module>   s&   
