Ë
    ýÿæi‹3  ã                   óÂ   — 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
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 d d
lmZmZ esddgZnesdgZ G d„ de«      Zy)é    )ÚSequence)ÚAnyÚListÚOptionalÚUnionN)ÚTensor)Ú_fix_empty_tensorsÚ_input_validator)Ú_iou_computeÚ_iou_update)ÚMetric)Údim_zero_cat)Ú_MATPLOTLIB_AVAILABLEÚ_TORCHVISION_AVAILABLE)Ú_AX_TYPEÚ_PLOT_OUT_TYPEÚIntersectionOverUnionzIntersectionOverUnion.plotc                   ó–  ‡ — e Zd ZU dZdZeed<   dZee   ed<   dZ	eed<   e
e   ed<   e
e   ed<   e
e   ed	<   d
Zeed<   dZeed<   	 	 	 	 d#dedee   dedededdfˆ fd„Zedededefd„«       Zedededefd„«       Zdeeeef      deeeef      ddfd„Zdedefd„Zdefd„Zdefd„Z	 d$d eeeee   f      d!ee   defd"„Zˆ xZ S )%r   aÍ  Computes Intersection Over Union (IoU).

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

    - ``preds`` (:class:`~List`): A list consisting of dictionaries each containing the key-values
      (each dictionary corresponds to a single image). Parameters that should be provided per dict:

        - ``boxes`` (:class:`~torch.Tensor`): float tensor of shape ``(num_boxes, 4)`` containing ``num_boxes``
          detection boxes of the format specified in the constructor.
          By default, this method expects ``(xmin, ymin, xmax, ymax)`` in absolute image coordinates.
        - labels: ``IntTensor`` of shape ``(num_boxes)`` containing 0-indexed detection classes for
          the boxes.

    - ``target`` (:class:`~List`): A list consisting of dictionaries each containing the key-values
      (each dictionary corresponds to a single image). Parameters that should be provided per dict:

        - ``boxes`` (:class:`~torch.Tensor`): float tensor of shape ``(num_boxes, 4)`` containing ``num_boxes`` ground
          truth boxes of the format specified in the constructor.
          By default, this method expects ``(xmin, ymin, xmax, ymax)`` in absolute image coordinates.
        - ``labels`` (:class:`~torch.Tensor`): integer tensor of shape ``(num_boxes)`` containing 0-indexed ground truth
          classes for the boxes.

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

    - ``iou_dict``: A dictionary containing the following key-values:

        - iou: (:class:`~torch.Tensor`)
        - iou/cl_{cl}: (:class:`~torch.Tensor`), if argument ``class metrics=True``

    Args:
        box_format:
            Input format of given boxes. Supported formats are ``[`xyxy`, `xywh`, `cxcywh`]``.
        iou_thresholds:
            Optional IoU thresholds for evaluation. If set to `None` the threshold is ignored.
        class_metrics:
            Option to enable per-class metrics for IoU. Has a performance impact.
        respect_labels:
            Ignore values from boxes that do not have the same label as the ground truth box. Else will compute Iou
                between all pairs of boxes.
        kwargs:
            Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Example::

        >>> import torch
        >>> from torchmetrics.detection import IntersectionOverUnion
        >>> preds = [
        ...    {
        ...        "boxes": torch.tensor([
        ...             [296.55, 93.96, 314.97, 152.79],
        ...             [298.55, 98.96, 314.97, 151.79]]),
        ...        "labels": torch.tensor([4, 5]),
        ...    }
        ... ]
        >>> target = [
        ...    {
        ...        "boxes": torch.tensor([[300.00, 100.00, 315.00, 150.00]]),
        ...        "labels": torch.tensor([5]),
        ...    }
        ... ]
        >>> metric = IntersectionOverUnion()
        >>> metric(preds, target)
        {'iou': tensor(0.8614)}

    Example::

        The metric can also return the score per class:

        >>> import torch
        >>> from torchmetrics.detection import IntersectionOverUnion
        >>> preds = [
        ...    {
        ...        "boxes": torch.tensor([
        ...             [296.55, 93.96, 314.97, 152.79],
        ...             [298.55, 98.96, 314.97, 151.79]]),
        ...        "labels": torch.tensor([4, 5]),
        ...    }
        ... ]
        >>> target = [
        ...    {
        ...        "boxes": torch.tensor([
        ...               [300.00, 100.00, 315.00, 150.00],
        ...               [300.00, 100.00, 315.00, 150.00]
        ...        ]),
        ...        "labels": torch.tensor([4, 5]),
        ...    }
        ... ]
        >>> metric = IntersectionOverUnion(class_metrics=True)
        >>> metric(preds, target)
        {'iou': tensor(0.7756), 'iou/cl_4': tensor(0.6898), 'iou/cl_5': tensor(0.8614)}

    Raises:
        ModuleNotFoundError:
            If torchvision is not installed with version 0.8.0 or newer.

    FÚis_differentiableTÚhigher_is_betterÚfull_state_updateÚgroundtruth_labelsÚpred_labelsÚ
iou_matrixÚiouÚ	_iou_typeg      ð¿Ú_invalid_valNÚ
box_formatÚiou_thresholdÚclass_metricsÚrespect_labelsÚkwargsÚreturnc                 óÈ  •— t        ‰| �  di |¤Ž t        s't        d| j                  j                  «       › d�«      ‚d}||vrt        d|› d|› �«      ‚|| _        || _        t        |t        «      st        d«      ‚|| _        t        |t        «      st        d«      ‚|| _        | j                  dg d ¬	«       | j                  d
g d ¬	«       | j                  dg d ¬	«       y )NzMetric `zf` requires that `torchvision` is installed. Please install with `pip install torchmetrics[detection]`.)ÚxyxyÚxywhÚcxcywhz,Expected argument `box_format` to be one of z	 but got z1Expected argument `class_metrics` to be a booleanz2Expected argument `respect_labels` to be a booleanr   )ÚdefaultÚdist_reduce_fxr   r   © )ÚsuperÚ__init__r   ÚModuleNotFoundErrorr   ÚupperÚ
ValueErrorr   r   Ú
isinstanceÚboolr    r!   Ú	add_state)Úselfr   r   r    r!   r"   Úallowed_box_formatsÚ	__class__s          €úo/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/torchmetrics/detection/iou.pyr,   zIntersectionOverUnion.__init__�   s÷   ø€ ô 	‰ÑÑ"˜6Ò"å%Ü%Ø˜4Ÿ>™>×/Ñ/Ó1Ð2ð 3Nð Nóð ð
 9ÐØÐ0Ñ0ÜÐKÐL_ÐK`Ð`iÐjtÐiuÐvÓwÐwà$ˆŒØ*ˆÔä˜-¬Ô.ÜÐPÓQÐQØ*ˆÔä˜.¬$Ô/ÜÐQÓRÐRØ,ˆÔà�‰Ð+°RÈˆÔMØ�‰�}¨bÀˆÔFØ�‰�|¨RÀˆÕEó    Úargsc                  ó   — t        | i |¤ŽS ©N)r   ©r8   r"   s     r6   Ú_iou_update_fnz$IntersectionOverUnion._iou_update_fn°   s   € ä˜DÐ+ FÑ+Ð+r7   c                  ó   — t        | i |¤ŽS r:   )r   r;   s     r6   Ú_iou_compute_fnz%IntersectionOverUnion._iou_compute_fn´   s   € ä˜TÐ, VÑ,Ð,r7   ÚpredsÚtargetc                 óØ  — t        ||d¬«       t        ||«      D �]L  \  }}| j                  |d   «      }| j                  |d   «      }| j                  j	                  |d   «       | j
                  j	                  |d   «       | j                  ||| j                  | j                  «      }| j                  r“|j                  «       dkD  r=|j                  «       dkD  r*|d   j                  d«      |d   j                  d«      k(  }n3t        j                  |j                  d   t        |j                   ¬«      }| j                  || <   | j"                  j	                  |«       �ŒO y)	z*Update state with predictions and targets.T)Úignore_scoreÚboxesÚlabelsr   é   )ÚdtypeÚdeviceN)r
   ÚzipÚ_get_safe_item_valuesr   Úappendr   r<   r   r   r!   ÚnumelÚ	unsqueezeÚtorchÚeyeÚshaper1   rG   r   )	r3   r?   r@   Úp_iÚt_iÚ	det_boxesÚgt_boxesr   Úlabel_eqs	            r6   ÚupdatezIntersectionOverUnion.update¸   s5  € ä˜ °TÕ:ä˜E 6×*‰HˆC�Ø×2Ñ2°3°w±<Ó@ˆIØ×1Ñ1°#°g±,Ó?ˆHØ×#Ñ#×*Ñ*¨3¨x©=Ô9Ø×Ñ×#Ñ# C¨¡MÔ2à×,Ñ,¨Y¸À$×BTÑBTÐVZ×VgÑVgÓhˆJØ×"Ò"Ø—?‘?Ó$ qÒ(¨X¯^©^Ó-=ÀÒ-AØ" 8™}×6Ñ6°qÓ9¸SÀ¹]×=TÑ=TÐUVÓ=WÑW‘Hä$Ÿy™y¨×)9Ñ)9¸!Ñ)<ÄDÐQ[×QbÑQbÔc�HØ(,×(9Ñ(9�
˜H˜9Ñ%Ø�O‰O×"Ñ" :Ö.ñ +r7   rC   c                 óx   — ddl m} t        |«      }|j                  «       dkD  r ||| j                  d¬«      }|S )Nr   )Úbox_convertr%   )Úin_fmtÚout_fmt)Útorchvision.opsrW   r	   rK   r   )r3   rC   rW   s      r6   rI   z+IntersectionOverUnion._get_safe_item_valuesË   s4   € Ý/ä" 5Ó)ˆØ�;‰;‹=˜1ÒÙ ¨d¯o©oÀvÔNˆEØˆr7   c                 ó¬   — t        | j                  «      dkD  r;t        j                  | j                  «      j	                  «       j                  «       S g S )zJReturns a list of unique classes found in ground truth and detection data.r   )Úlenr   rM   ÚcatÚuniqueÚtolist)r3   s    r6   Ú_get_gt_classesz%IntersectionOverUnion._get_gt_classesÓ   sA   € äˆt×&Ñ&Ó'¨!Ò+Ü—9‘9˜T×4Ñ4Ó5×<Ñ<Ó>×EÑEÓGÐGØˆ	r7   c                 óô  — | j                   D �cg c]7  }t        j                  || j                  k7  «      sŒ&||| j                  k7     ‘Œ9 }}|r$t        j                  |d«      j                  «       n t        j                  d| j                  ¬«      }| j                  › |i}t        j                  |«      r/t        j                  d|j                  ¬«      || j                  › <   | j                  �rt        t        | j                  «      t        | j                  «      g«      }|j                  «       dkD  r|j                  «       j!                  «       ng }|D �]  }t        j"                  |«      }t        j"                  |«      }	t%        | j                   | j                  «      D ]I  \  }}
|dd…|
|k(  f   }||| j                  k7     }||j'                  «       z  }|	|j                  «       z  }	ŒK |	j)                  «       dk(  rB|j+                  | j                  › d|› �t        j                  d|j                  ¬«      i«       Œï|j+                  | j                  › d|› �||	z  i«       �Œ |S c c}w )z@Computes IoU based on inputs passed in to ``update`` previously.r   g        )rG   Nz/cl_)r   rM   Úanyr   r]   ÚmeanÚtensorrG   r   Úisnanr    r   r   r   rK   r^   r_   Ú
zeros_likerH   ÚsumÚitemrU   )r3   ÚmatÚvalid_matricesÚscoreÚresultsÚ
all_labelsÚclassesÚclÚ
masked_iouÚobservedÚgt_labÚscoresÚvalid_scoress                r6   ÚcomputezIntersectionOverUnion.computeÙ   s!  € ð 6:·_²_ó
Ù5D¨cÌÏ	É	ÐRUÐY]×YjÑYjÑRjÕHkˆC��t×(Ñ(Ñ(Ó)°_ð 	ð 
ñ 8F”—	‘	˜.¨!Ó,×1Ñ1Ô3Ì5Ï<É<ÐX[Ðdh×doÑdoÔKpˆØ)-¯©Ð(8¸5Ð%AˆÜ�;‰;�uÔÜ+0¯<©<¸ÀEÇLÁLÔ+QˆG�t—~‘~Ð&Ñ(Ø×Óä%¤|°D×4KÑ4KÓ'LÌlÐ[_×[kÑ[kÓNlÐ&mÓnˆJØ6@×6FÑ6FÓ6HÈ1Ò6L�j×'Ñ'Ó)×0Ñ0Ô2ÐRTˆGÜ�Ü"×-Ñ-¨eÓ4�
Ü ×+Ñ+¨EÓ2�ä#& t§¡¸×8OÑ8OÖ#P‘K�C˜Ø ¢ F¨b¡L Ñ1�FØ#)¨&°D×4EÑ4EÑ*EÑ#F�LØ ,×"2Ñ"2Ó"4Ñ4�JØ × 2Ñ 2Ó 4Ñ4‘Hð	 $Qð —=‘=“? aÒ'Ø—N‘N t§~¡~Ð&6°d¸2¸$Ð$?ÄÇÁÈcÐZ_×ZfÑZfÔAgÐ#hÕià—N‘N t§~¡~Ð&6°d¸2¸$Ð$?ÀÈhÑAVÐ#WÖXð ð ˆùò3
s
   �'I5·I5ÚvalÚaxc                 ó&   — | j                  ||«      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 object and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> import torch
            >>> from torchmetrics.detection import IntersectionOverUnion
            >>> preds = [
            ...    {
            ...        "boxes": torch.tensor([[296.55, 93.96, 314.97, 152.79], [298.55, 98.96, 314.97, 151.79]]),
            ...        "scores": torch.tensor([0.236, 0.56]),
            ...        "labels": torch.tensor([4, 5]),
            ...    }
            ... ]
            >>> target = [
            ...    {
            ...        "boxes": torch.tensor([[300.00, 100.00, 315.00, 150.00]]),
            ...        "labels": torch.tensor([5]),
            ...    }
            ... ]
            >>> metric = IntersectionOverUnion()
            >>> metric.update(preds, target)
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.detection import IntersectionOverUnion
            >>> preds = [
            ...    {
            ...        "boxes": torch.tensor([[296.55, 93.96, 314.97, 152.79], [298.55, 98.96, 314.97, 151.79]]),
            ...        "scores": torch.tensor([0.236, 0.56]),
            ...        "labels": torch.tensor([4, 5]),
            ...    }
            ... ]
            >>> target = lambda : [
            ...    {
            ...        "boxes": torch.tensor([[300.00, 100.00, 315.00, 150.00]]) + torch.randint(-10, 10, (1, 4)),
            ...        "labels": torch.tensor([5]),
            ...    }
            ... ]
            >>> metric = IntersectionOverUnion()
            >>> vals = []
            >>> for _ in range(20):
            ...     vals.append(metric(preds, target()))
            >>> fig_, ax_ = metric.plot(vals)

        )Ú_plot)r3   rv   rw   s      r6   ÚplotzIntersectionOverUnion.plot÷   s   € ðB �z‰z˜#˜rÓ"Ð"r7   )r%   NFT)NN)!Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r1   Ú__annotations__r   r   r   r   r   r   Ústrr   Úfloatr   r,   Ústaticmethodr<   r>   ÚlistÚdictrU   rI   r`   ru   r   r   r   r   rz   Ú__classcell__)r5   s   @r6   r   r   !   s²  ø… ñ_ðB $Ð�tÓ#Ø'+Ð�h˜t‘nÓ+Ø"Ð�tÓ"à˜V™Ó$Ø�f‘ÓØ�V‘ÓØ€IˆsÓØ€L�%Óð !Ø)-Ø#Ø#ñ!Fàð!Fð   ‘ð!Fð ð	!Fð
 ð!Fð ð!Fð 
õ!FðF ð,˜cð ,¨Sð ,°Vò ,ó ð,ð ð-˜sð -¨cð -°fò -ó ð-ð/˜D  c¨6 kÑ!2Ñ3ð /¸TÀ$ÀsÈFÀ{ÑBSÑ=Tð /ÐY]ó /ð&¨6ð °fó ð ó ð˜ó ð> _cñA#Ø˜E &¨(°6Ñ*:Ð":Ñ;Ñ<ðA#ØIQÐRZÑI[ðA#à	÷A#r7   )Úcollections.abcr   Útypingr   r   r   r   rM   r   Útorchmetrics.detection.helpersr	   r
   Ú%torchmetrics.functional.detection.iour   r   Útorchmetrics.metricr   Útorchmetrics.utilities.datar   Útorchmetrics.utilities.importsr   r   Útorchmetrics.utilities.plotr   r   Ú__doctest_skip__r   r*   r7   r6   Ú<module>r�      sQ   ðõ %ß -Ó -ã Ý ç Oß KÝ &Ý 4ß Xß @áØ/Ð1MÐNÑÙ	Ø4Ð5ÐôW#˜Fõ W#r7   