
    ^jg                        d dl mZ d dlmZ d dlmZ d dlmZmZ d dl	Z
d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZmZmZ d d
lmZ d dlmZmZmZ d dlmZm Z  d dl!m"Z" erd dl#Z$ G d de      Z%e G d d             Z&y)    )annotations)deepcopy)	dataclass)TYPE_CHECKINGAnyN)pyplot)ORIENTED_BOX_COORDINATES)
Detections)box_iou_batchmask_iou_batchoriented_box_iou_batch)LEGACY_COLOR_PALETTE)AveragingMethodMetricMetricTarget)ObjectSizeCategoryget_detection_size_category)ensure_pandas_installedc                  B   e Zd ZdZej
                  ej                  f	 	 	 ddZddZ		 	 	 	 	 	 ddZ
ddZ	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 ddZe	 	 	 	 	 	 	 	 	 	 dd       Ze	 	 	 	 	 	 	 	 	 	 dd	       Ze	 	 	 	 dd
       ZddZddZ	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZy)Recalla  
    Recall is a metric used to evaluate object detection models. It is the ratio of
    true positive detections to the total number of ground truth instances. We calculate
    it at different IoU thresholds.

    In simple terms, Recall is a measure of a model's completeness, calculated as:

    `Recall = TP / (TP + FN)`

    Here, `TP` is the number of true positives (correct detections), and `FN` is the
    number of false negatives (missed detections).

    Examples:
        ```pycon
        >>> import numpy as np
        >>> import supervision as sv
        >>> from supervision.metrics import Recall
        >>> predictions = sv.Detections(
        ...     xyxy=np.array([[0, 0, 10, 10]]),
        ...     class_id=np.array([0]),
        ...     confidence=np.array([0.9])
        ... )
        >>> targets = sv.Detections(
        ...     xyxy=np.array([[0, 0, 10, 10]]),
        ...     class_id=np.array([0])
        ... )
        >>> recall_metric = Recall()
        >>> recall_result = recall_metric.update(predictions, targets).compute()
        >>> round(float(recall_result.recall_at_50), 2)
        1.0

        ```

    ![example_plot](
        https://media.roboflow.com/supervision-docs/metrics/recall_plot_example.png
    ){ align=center width="800" }
    c                <    || _         || _        g | _        g | _        y)a  
        Initialize the Recall metric.

        Args:
            metric_target: The type of detection data to use.
            averaging_method: The averaging method used to compute the
                recall. Determines how the recall is aggregated across classes.
        N)_metric_targetaveraging_method_predictions_list_targets_list)selfmetric_targetr   s      e/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/metrics/recall.py__init__zRecall.__init__E   s$     , 035/1    c                     g | _         g | _        y)zR
        Reset the metric to its initial state, clearing all stored data.
        N)r   r   r   s    r   resetzRecall.resetX   s     "$r    c                4   t        |t              s|g}t        |t              s|g}t        |      t        |      k7  r$t        dt        |       dt        |       d      | j                  j                  |       | j                  j                  |       | S )a  
        Add new predictions and targets to the metric, but do not compute the result.

        Args:
            predictions: The predicted detections.
            targets: The target detections.

        Returns:
            The updated metric instance.
        zThe number of predictions (z) and targets (z%) during the update must be the same.)
isinstancelistlen
ValueErrorr   extendr   )r   predictionstargetss      r   updatezRecall.update_   s     +t,&-K'4(iG{s7|+-c+.>-? @ \N*OQ 
 	%%k2!!'*r    c                ,   | j                  | j                  | j                        }| j                  | j                  | j                  t        j
                        \  }}| j                  ||      |_        | j                  | j                  | j                  t        j                        \  }}| j                  ||      |_        | j                  | j                  | j                  t        j                        \  }}| j                  ||      |_
        |S )z
        Calculate the recall metric based on the stored predictions and ground-truth
        data, at different IoU thresholds.

        Returns:
            The recall metric result.
        )_computer   r   '_filter_predictions_and_targets_by_sizer   SMALLsmall_objectsMEDIUMmedium_objectsLARGElarge_objects)r   resultsmall_predictionssmall_targetsmedium_predictionsmedium_targetslarge_predictionslarge_targetss           r   computezRecall.compute~   s     t55t7I7IJ+/+W+W""D$6$68J8P8P,
(=  $}}->N 88&&(:(:<N<U<U 	+N
 !%.@. Q+/+W+W""D$6$68J8P8P,
(=  $}}->Nr    c                   t        j                  ddd      }g }t        ||      D ]  \  }}| j                  |      }| j                  |      }t	        |      dkD  s8t	        |      dk(  r|j                  t        j                  d|j                  ft              t        j                  dt         j                        t        j                  dt              |j                  f       | j                  t        j                  k(  rt        ||      }	n_| j                  t        j                   k(  rt#        ||      }	n5| j                  t        j$                  k(  rt'        ||      }	nt)        d      | j+                  |j                  |j                  nt        j,                  g       |j                  |j                  nt        j,                  g       |	|      }
|j                  |
|j.                  |j                  |j                  f        |st1        | j                  | j2                  t        j                  |j4                  d         t        j                  d|j4                  d   f      |t        j,                  g t              d d d 	      S t        | D cg c]  }t        j6                  |d       }} | j8                  | \  }}}t1        | j                  | j2                  ||||d d d 	      S c c}w )	Ng      ?gffffff?
   r   dtype)r   z-Unsupported metric target for IoU calculation)	r   r   recall_scoresrecall_per_classiou_thresholdsmatched_classesr1   r3   r5   )nplinspacezip_detections_contentr'   appendzerossizeboolfloat32intclass_idr   r   BOXESr   MASKSr   ORIENTED_BOUNDING_BOXESr   r(   _match_detection_batcharray
confidenceRecallResultr   shapeconcatenate_compute_recall_for_classes)r   predictions_listtargets_listrD   statsr*   r+   prediction_contentstarget_contentsioumatchesitemsconcatenated_statsrB   rC   unique_classess                   r   r.   zRecall._compute   s    S$3$'(8,$G .	 K"&":":;"G"66w?O7|a{#q(LLHHa)<)<%=TJHHT<HHT5#,,	 **l.@.@@+O=PQ,,0B0BB,_>QR,,0T0TT4+-@ )K  #99&//; $,,XXb\"++7  ((XXb\&	G LL#'22'00#,,	O.	` "11!%!6!6 hh~';';A'>?!#1n.B.B1.E*F!G- "3 7"#"
 
 EHKP5bnnUA6PP,D,,.@A 	8' --!22'-)*

 
	
 Qs   %K?c                \   t        j                  |       }||   }||   }t        j                  |d      \  }}| j                  ||||      }| j	                  |      }	| j
                  t        j                  k(  rt        j                  |	d      }
n| j
                  t        j                  k(  r#|j                  d      }| j	                  |      }
nT| j
                  t        j                  k(  r7|j                  t         j                        }t        j                  |	d|      }

|	|fS )NT)return_countsr   axis)rh   weights)rF   argsortunique_compute_confusion_matrix_compute_recallr   r   MACROmeanMICROsumWEIGHTEDastyperN   average)r   ra   prediction_confidenceprediction_class_idstrue_class_idssorted_indicesrd   class_countsconfusion_matrixrC   rB   confusion_matrix_mergeds               r   rZ   z"Recall._compute_recall_for_classes   s    %:$:;.)3NC')yyt'T$  99)><

  //0@A   O$9$99GG$41=M""o&;&;;&6&:&:1&=# 001HIM""o&>&>>'..rzz:LJJ'7aVM.>>r    c                   | j                   d   |j                   d   }}t        j                  ||ft              }|d d d f   | k(  }t	        |      D ]  \  }}	t        j
                  ||	k\  |z        }
|
d   j                   d   s5t        j                  |
d      }||
   d d d f   }t        j                  ||g      }|
d   j                   d   dkD  rh||d d df   j                         d d d      }|t        j                  |d d df   d      d      }|t        j                  |d d df   d      d      }d||d d df   j                  t              |f<    |}|S )	Nr   r@      rg      T)return_index)rX   rF   rK   rM   	enumeratewherestackhstackrj   rk   rs   rO   )predictions_classestarget_classesr`   rD   num_predictionsnum_iou_levelscorrectcorrect_classi	iou_levelmatched_indicescombined_indices
iou_valuesra   result_corrects                  r   rT   zRecall._match_detection_batch  s~     %%a(  # ( ((O^<DI&q$w/3FF%n5 	=LAy hhy(8M'IJOq!''*#%88O!#D  1!T':
))%5z$BC"1%++A.2%gadm&;&;&=dd&CDG%bii1D&QRS&TUG%bii1D&QRS&TUG8<1,,S1145	= 18r    c                   | j                   d   }|j                   d   }t        j                  ||dft        j                        }t	        |      D ]  \  }}||k(  }	||   }
|	j                         }|dk(  rAt        j                  |      }t        j                  |      }t        j                  ||
      }nv|
dk(  rAt        j                  |      }t        j                  ||      }t        j                  |      }n0| |	   j                  d      }d| |	   z
  j                  d      }|
|z
  }t        j                  |||gd      ||<    |}|S )a3  
        Compute the confusion matrix for each class and IoU threshold.

        Assumes the matches and prediction_class_ids are sorted by confidence
        in descending order.

        Args:
            sorted_matches: shape (P, Th), that is True
                if the prediction is a true positive at the given IoU threshold.
            sorted_prediction_class_ids: shape (P,), containing
                the class id for each prediction.
            unique_classes: shape (C,), containing the unique
                class ids.
            class_counts: shape (C,), containing the number
                of true instances for each class.

        Returns:
            shape (C, Th, 3), containing the true positives, false
                positives, and false negatives for each class and IoU threshold.
        r}   r      r@   rg   )rX   rF   rK   float64r   rq   fullr   )sorted_matchessorted_prediction_class_idsrd   ry   num_thresholdsnum_classesrz   	class_idxrP   is_classnum_truer   true_positivesfalse_positivesfalse_negativesr6   s                   r   rl   z Recall._compute_confusion_matrix2  sI   8 (--a0$**1-46HH.!,BJJ5
 $-^#< 	Ix2h>H#I.H&llnO!#!#.!9"$((>":"$''.("CQ!#.!9"$''./"J"$((>":!/!9!=!=a!@#$~h'?#?"D"DQ"G"*^";*,((/B+Y'#	( +;r    c                    | j                   d   dk(  st        d| j                          | d   }| d   }||z   }t        j                  ||t        j                  |      |dk7        }|}|S )a[  
        Broadcastable function, computing the recall from the confusion matrix.

        Args:
            confusion_matrix: shape (N, ..., 3), where the last dimension
                contains the true positives, false positives, and false negatives.

        Returns:
            shape (N, ...), containing the recall for each element.
        r   r   z/Confusion matrix must have shape (..., 3), got ).r   ).r~   r   )outr   )rX   r(   rF   divide
zeros_like)rz   r   r   denominatorrecallresult_recalls         r   rm   zRecall._compute_recallk  s      %%b)Q.A#))*,  *&1*62$6n-"	
 28r    c                   | j                   t        j                  k(  r|j                  }|S | j                   t        j                  k(  r*|j
                  |j
                  }|S | j                         S | j                   t        j                  k(  rf|j                  j                  t              }|5t        |      dkD  r't        j                  |t        j                        }|S | j                         S t        d| j                          )z?Return boxes, masks or oriented bounding boxes from detections.r   r@   Invalid metric target: )r   r   rQ   xyxyrR   mask_make_empty_contentrS   datagetr	   r'   rF   rU   rN   r(   )r   
detectionsresult_boxesresult_masksobb
result_obbs         r   rI   zRecall._detections_content  s    ,"4"444>OOL,"4"44*6@oo##++--,"F"FF//%%&>?C3s8a<68hhs"**6U
!!++--243F3F2GHIIr    c                   | j                   t        j                  k(  r't        j                  dt        j
                        }|S | j                   t        j                  k(  rt        j                  dt              }|S | j                   t        j                  k(  r't        j                  dt        j
                        }|S t        d| j                          )N)r      r@   )r   r   r   )r   r   r~   r   )
r   r   rQ   rF   emptyrN   rR   rM   rS   r(   )r   empty_boxesempty_masks	empty_obbs       r   r   zRecall._make_empty_content  s    ,"4"443588F"**3UK,"4"4413)41PK,"F"FF13)2::1VI243F3F2GHIIr    c                ~   t        |      }|j                         s|t        j                  k(  r|S t	        || j
                        }||j                  k(  }|j                  |   |_        |j                  |j                  |   |_        |j                  |j                  |   |_	        |j                  |j                  |   |_
        |j                  |j                  |   |_        |j                  G|j                  j                         D ]*  \  }}t        j                  |      |   |j                  |<   , |S )zBReturn a copy of detections with contents filtered by object size.)r   is_emptyr   ANYr   r   valuer   r   rP   rV   
tracker_idr   rb   rF   rU   )r   r   size_categorynew_detectionssizes	size_maskkeyr   s           r   _filter_detections_by_sizez!Recall._filter_detections_by_size  s4    "*- M5G5K5K$K!!+ND<O<OP]000	,11)<*"0"5"5i"@N"".&4&=&=i&HN#$$0(6(A(A)(LN%$$0(6(A(A)(LN%*,11779 F
U+-88E?9+E##C(F r    c                    g }g }t        ||      D ]G  \  }}|j                  | j                  ||             |j                  | j                  ||             I ||fS )zI
        Filter predictions and targets by object size category.
        )rH   rJ   r   )r   r[   r\   r   new_predictions_listnew_targets_listr*   r+   s           r   r/   z.Recall._filter_predictions_and_targets_by_size  sx      "$'(8,$G 	 K ''//]K ##//G		 $%555r    N)r   r   r   r   returnNone)r*   Detections | list[Detections]r+   r   r   r   )r   rW   )r[   list[Detections]r\   r   r   rW   )
ra   npt.NDArray[np.bool_]ru   npt.NDArray[np.float32]rv   npt.NDArray[np.int32]rw   r   r   zNtuple[npt.NDArray[np.float64], npt.NDArray[np.float64], npt.NDArray[np.int32]])
r   r   r   r   r`   r   rD   r   r   r   )
r   r   r   r   rd   r   ry   r   r   npt.NDArray[np.float64])rz   r   r   r   )r   r
   r   npt.NDArray[Any])r   r   )r   r
   r   r   r   r
   )r[   r   r\   r   r   r   r   z)tuple[list[Detections], list[Detections]])__name__
__module____qualname____doc__r   rQ   r   rr   r   r#   r,   r=   r.   rZ   staticmethodrT   rl   rm   rI   r   r   r/    r    r   r   r      s   $P '3&8&8,;,D,D2#2 *2& 2 / 
	>:R
 0R
@PR
	R
h"?&"?  7"? 4	"?
 ."?
"?H 2- % 0	
 
 < 6-6%:6 .6 ,	6
 
!6 6p 1	  @J$J"$5G	46*6 '6 *	6
 
36r    r   c                      e Zd ZU dZded<   ded<   edd       Zedd       Zded	<   ded
<   ded<   ded<   ded<   ded<   ded<   ddZddZ	ddZ
y)rW   u  
    The results of the recall metric calculation.

    Defaults to `0` if no detections or targets were provided.

    Attributes:
        metric_target: the type of data used for the metric -
            boxes, masks or oriented bounding boxes.
        averaging_method: the averaging method used to compute the
            recall. Determines how the recall is aggregated across classes.
        recall_at_50: the recall at IoU threshold of `0.5`.
        recall_at_75: the recall at IoU threshold of `0.75`.
        recall_scores: the recall scores at each IoU threshold.
            Shape: `(num_iou_thresholds,)`
        recall_per_class: the recall scores per class and IoU threshold.
            Shape: `(num_target_classes, num_iou_thresholds)`
        iou_thresholds: the IoU thresholds used in the calculations.
        matched_classes: the class IDs of all matched classes.
            Corresponds to the rows of `recall_per_class`.
        small_objects: the Recall metric results
            for small objects (area < 32²).
        medium_objects: the Recall metric results
            for medium objects (32² ≤ area < 96²).
        large_objects: the Recall metric results
            for large objects (area ≥ 96²).
    r   r   r   r   c                2    t        | j                  d         S )Nr   floatrB   r"   s    r   recall_at_50zRecallResult.recall_at_50      T''*++r    c                2    t        | j                  d         S )N   r   r"   s    r   recall_at_75zRecallResult.recall_at_75  r   r    r   rB   rC   r   rD   r   rE   zRecallResult | Noner1   r3   r5   c                   | j                   j                   d| j                   d| j                   d| j                  dd| j
                  dd| j                   d| j                   d}| j                  j                  d	k(  r|d
z  }t        | j                  | j                        D ]  \  }}|d| d| dz  } d}| j                  3|t        | j                        j                  dd|       z   }|d| z  }| j                  3|t        | j                        j                  dd|       z   }|d| z  }| j                   3|t        | j                         j                  dd|       z   }|d| z  }|S )a=  
        Format as a pretty string.

        Example:
            ```pycon
            >>> import numpy as np
            >>> import supervision as sv
            >>> from supervision.metrics import Recall
            >>> predictions = sv.Detections(
            ...     xyxy=np.array([[0, 0, 10, 10]]),
            ...     class_id=np.array([0]),
            ...     confidence=np.array([0.9])
            ... )
            >>> targets = sv.Detections(
            ...     xyxy=np.array([[0, 0, 10, 10]]),
            ...     class_id=np.array([0])
            ... )
            >>> recall_metric = Recall()
            >>> recall_result = recall_metric.update(predictions, targets).compute()
            >>> print(recall_result)  # doctest: +ELLIPSIS
            RecallResult:
            Metric target:    MetricTarget.BOXES
            Averaging method: AveragingMethod.WEIGHTED
            R @ 50:     1.0000
            R @ 75:     1.0000
            R @ thresh: [1. ... 1.]
            IoU thresh: [0.5  0.55 ... 0.95]
            Recall per class:
              0: [1. ... 1.]
            ...
            Medium objects:
              RecallResult:
              Metric target:    MetricTarget.BOXES
              Averaging method: AveragingMethod.WEIGHTED
              R @ 50:     0.0000
              ...

            ```
        z:
Metric target:    z
Averaging method: z
R @ 50:     z.4fz
R @ 75:     z
R @ thresh: z
IoU thresh: z
Recall per class:
r   z  No results
z  z: 
z
Small objects:
z
Medium objects:
z
Large objects:
)	__class__r   r   r   r   r   rB   rD   rC   rL   rH   rE   r1   strreplacer3   r5   )r   out_strrP   recall_of_classindentindenteds         r   __str__zRecallResult.__str__  s   R ~~&&' (!!%!3!3 4 5!!%!6!6 7 8,,S1 2,,S1 2--. /../ 0"# 	   %%*''G),  $"7"7*
 	<%Ho H:R'8;;G	<
 )D$6$6 7 ? ?6(m TTH+H:66G*D$7$7 8 @ @F8} UUH,XJ77G)D$6$6 7 ? ?6(m TTH+H:66Gr    c                   t                ddl}| j                  | j                  d}| j                  :| j                  j                         }|j                         D ]  \  }}||d| <    | j                  :| j                  j                         }|j                         D ]  \  }}||d| <    | j                  :| j                  j                         }|j                         D ]  \  }}||d| <     |j                  |dg      S )zt
        Convert the result to a pandas DataFrame.

        Returns:
            The result as a DataFrame.
        r   N)zR@50zR@75small_objects_medium_objects_large_objects_)index)
r   pandasr   r   r1   	to_pandasrb   r3   r5   	DataFrame)r   pdpandas_datasmall_objects_dfr   r   medium_objects_dflarge_objects_dfs           r   r   zRecallResult.to_pandasU  s+    	 ! %%%%

 )#11;;=.446 <
U6;nSE23<* $ 3 3 = = ?/557 =
U7<ocU34=)#11;;=.446 <
U6;nSE23< r||Ks33r    c                   ddg}| j                   | j                  g}t        d   gdz  }| j                  >| j                  }|ddgz  }||j                   |j                  gz  }|t        d   gdz  z  }| j                  >| j                  }|d	d
gz  }||j                   |j                  gz  }|t        d   gdz  z  }| j
                  >| j
                  }|ddgz  }||j                   |j                  gz  }|t        d   gdz  z  }dt        j                  d<   t        j                  d      \  }}|j                  dd       |j                  dd       d| j                  j                   d| j                  j                   d}	|j                  |	d       t        t!        |            }
|j#                  |
||d      }|j%                  |
       |j'                  |dd       |D ]O  }|j)                         }|j+                  |j-                         |j/                         dz  z   |dz   |ddd !       Q d"t        j                  d<   t        j0                          t        j2                          y)#z
        Plot the recall results.

        ![example_plot](
            https://media.roboflow.com/supervision-docs/metrics/recall_plot_example.png
        ){ align=center width="800" }
        z	Recall@50z	Recall@75r   r~   NzSmall: R@50zSmall: R@75r   zMedium: R@50zMedium: R@75zLarge: R@50zLarge: R@75r   	monospacezfont.family)r?      )figsizer}   Valuebold)
fontweightz Recall, by Object Size
(target: z, averaging: )center)coloralign-   right)rotationhag{Gz?z.2fbottom)r  vaz
sans-serif)r   r   r   r1   r3   r5   pltrcParamssubplotsset_ylim
set_ylabelr   r   r   	set_titleranger'   bar
set_xticksset_xticklabels
get_heighttextget_x	get_widthtight_layoutshow)r   labelsvaluescolorsr1   r3   r5   _axtitlex_positionsbarsr  y_values                 r   plotzRecallResult.plots  s    {+##T%6%67&q)*Q.) ..M}m44F}11=3M3MNNF+A./!33F*!00N~~66F~22N4O4OPPF+A./!33F) ..M}m44F}11=3M3MNNF+A./!33F&1]#W-2
Aq
g&1,,223 400667q: 	
 	Uv.CK(vvk6xvH
k"
6B7; 	Cnn&GGG		cmmo11$3-  	 '3]#
r    N)r   r   )r   r   )r   zpd.DataFramer   )r   r   r   r   __annotations__propertyr   r   r   r   r   r   r    r   rW   rW     sx    6  %%, , , , +*--++**&&''&&DL4<>r    rW   )'
__future__r   copyr   dataclassesr   typingr   r   numpyrF   numpy.typingnpt
matplotlibr   r  supervision.configr	   supervision.detection.corer
   'supervision.detection.utils.iou_and_nmsr   r   r   supervision.draw.colorr   supervision.metrics.corer   r   r   %supervision.metrics.utils.object_sizer   r   supervision.metrics.utils.utilsr   r   r   r   rW   r   r    r   <module>r2     sq    "  ! %   $ 7 1 
 8 J J D}6V }6@ R R Rr    