a
    d                     @   s   d dl mZmZmZmZ d dlZd dlmZ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 esrdgZG d	d
 d
eZdS )    )AnyOptionalSequenceUnionN)Tensortensor)_psnrb_compute_psnrb_update)Metric)_MATPLOTLIB_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPE*PeakSignalNoiseRatioWithBlockedEffect.plotc                       s   e Zd ZU dZdZeed< dZeed< dZeed< e	ed< e	ed< e	ed	< e	ed
< de
edd fddZe	e	ddddZe	dddZdeee	ee	 f  ee edddZ  ZS )%PeakSignalNoiseRatioWithBlockedEffecta  Computes `Peak Signal to Noise Ratio With Blocked Effect`_ (PSNRB).

    .. math::
        \text{PSNRB}(I, J) = 10 * \log_{10} \left(\frac{\max(I)^2}{\text{MSE}(I, J)-\text{B}(I, J)}\right)

    Where :math:`\text{MSE}` denotes the `mean-squared-error`_ function. This metric is a modified version of PSNR that
    better supports evaluation of images with blocked artifacts, that oftens occur in compressed images.

    .. note::
        Metric only supports grayscale images. If you have RGB images, please convert them to grayscale first.

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

    - ``preds`` (:class:`~torch.Tensor`): Predictions from model of shape ``(N,1,H,W)``
    - ``target`` (:class:`~torch.Tensor`): Ground truth values of shape ``(N,1,H,W)``

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

    - ``psnrb`` (:class:`~torch.Tensor`): float scalar tensor with aggregated PSNRB value

    Args:
        block_size: integer indication the block size
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Example:
        >>> import torch
        >>> from torchmetrics.image import PeakSignalNoiseRatioWithBlockedEffect
        >>> metric = PeakSignalNoiseRatioWithBlockedEffect()
        >>> _ = torch.manual_seed(42)
        >>> preds = torch.rand(2, 1, 10, 10)
        >>> target = torch.rand(2, 1, 10, 10)
        >>> metric(preds, target)
        tensor(7.2893)

    Tis_differentiablehigher_is_betterFfull_state_updatesum_squared_errortotalbef
data_range   N)
block_sizekwargsreturnc                    s   t  jf i | t|ts,|dk r,td|| _| jdtddd | jdtddd | jd	tddd | jd
tddd d S )N   z4Argument ``block_size`` should be a positive integerr   g        sum)defaultZdist_reduce_fxr   r   r   r   max)super__init__
isinstanceint
ValueErrorr   Z	add_stater   )selfr   r   	__class__ a/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/image/psnrb.pyr    I   s    z.PeakSignalNoiseRatioWithBlockedEffect.__init__)predstargetr   c                 C   sd   t ||| jd\}}}|  j|7  _|  j|7  _|  j|7  _t| jt|t	| | _dS )z*Update state with predictions and targets.)r   N)
r	   r   r   r   r   torchmaximumr   r   min)r$   r)   r*   r   r   Zn_obsr'   r'   r(   updateX   s
    z,PeakSignalNoiseRatioWithBlockedEffect.update)r   c                 C   s   t | j| j| j| jS )z.Compute peak signal-to-noise ratio over state.)r   r   r   r   r   )r$   r'   r'   r(   compute`   s    z-PeakSignalNoiseRatioWithBlockedEffect.compute)valaxr   c                 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 import PeakSignalNoiseRatioWithBlockedEffect
            >>> metric = PeakSignalNoiseRatioWithBlockedEffect()
            >>> metric.update(torch.rand(2, 1, 10, 10), torch.rand(2, 1, 10, 10))
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.image import PeakSignalNoiseRatioWithBlockedEffect
            >>> metric = PeakSignalNoiseRatioWithBlockedEffect()
            >>> values = [ ]
            >>> for _ in range(10):
            ...     values.append(metric(torch.rand(2, 1, 10, 10), torch.rand(2, 1, 10, 10)))
            >>> fig_, ax_ = metric.plot(values)

        )Z_plot)r$   r0   r1   r'   r'   r(   plotd   s    (r   )r   )NN)__name__
__module____qualname____doc__r   bool__annotations__r   r   r   r"   r   r    r.   r/   r   r   r   r   r   r2   __classcell__r'   r'   r%   r(   r      s*   
#  r   )typingr   r   r   r   r+   r   r   Z#torchmetrics.functional.image.psnrbr   r	   Ztorchmetrics.metricr
   Ztorchmetrics.utilities.importsr   Ztorchmetrics.utilities.plotr   r   Z__doctest_skip__r   r'   r'   r'   r(   <module>   s   