o
    .wi                     @   s   d dl mZ d dl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s=d	gZG d
d deZdS )    )Sequence)AnyOptional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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 )%PeakSignalNoiseRatioWithBlockedEffectad  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.

    .. attention::
        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:
        >>> from torch import rand
        >>> metric = PeakSignalNoiseRatioWithBlockedEffect()
        >>> preds = rand(2, 1, 10, 10)
        >>> target = 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   
block_sizekwargsreturnNc                    s   t  jd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)defaultdist_reduce_fxr   r   r   r   max )super__init__
isinstanceint
ValueErrorr   	add_stater   )selfr   r   	__class__r    U/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/image/psnrb.pyr"   I   s   z.PeakSignalNoiseRatioWithBlockedEffect.__init__predstargetc                 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   num_obsr    r    r*   updateX   s
   $z,PeakSignalNoiseRatioWithBlockedEffect.updatec                 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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 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)

        )_plot)r'   r3   r4   r    r    r*   plotd   s   (r   )r   )NN)__name__
__module____qualname____doc__r   bool__annotations__r   r   r   r$   r   r"   r1   r2   r   r   r   r   r   r6   __classcell__r    r    r(   r*   r      s6   
 "r   )collections.abcr   typingr   r   r   r-   r   r   #torchmetrics.functional.image.psnrbr   r	   torchmetrics.metricr
   torchmetrics.utilities.importsr   torchmetrics.utilities.plotr   r   __doctest_skip__r   r    r    r    r*   <module>   s   