
    ^jr                        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)	Precisiona/  
    Precision is a metric used to evaluate object detection models. It is the ratio of
    true positive detections to the total number of predicted detections. We calculate
    it at different IoU thresholds.

    In simple terms, Precision is a measure of a model's accuracy, calculated as:

    `Precision = TP / (TP + FP)`

    Here, `TP` is the number of true positives (correct detections), and `FP` is the
    number of false positive detections (detected, but incorrectly).

    Examples:
        ```pycon
        >>> import numpy as np
        >>> import supervision as sv
        >>> from supervision.metrics import Precision
        >>> 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])
        ... )
        >>> precision_metric = Precision()
        >>> precision_result = precision_metric.update(predictions, targets).compute()
        >>> round(float(precision_result.precision_at_50), 2)
        1.0

        ```

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

        Args:
            metric_target: The type of detection data to use.
            averaging_method: The averaging method used to compute the
                precision. Determines how the precision is aggregated across classes.
        N)_metric_targetaveraging_method_predictions_list_targets_list)selfmetric_targetr   s      h/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/metrics/precision.py__init__zPrecision.__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Precision.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Precision.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 precision metric based on the stored predictions and ground-truth
        data, at different IoU thresholds.

        Returns:
            The precision 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Precision.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k(  rt	        |      dkD  r|j
                  |j                  ^|j                  t        j                  t	        |      |j                  ft         j                        |j                  |j
                  t        j                  dt         j                        f       t	        |      dkD  st	        |      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      | j1                  |j
                  |j
                  nt        j2                  g       |j
                  |j
                  nt        j2                  g       |	|      }
|j                  |
|j                  |j
                  |j
                  f        |st5        | j                  | j6                  t        j                  |j8                  d         t        j                  d|j8                  d   f      |t        j2                  g t              ddd		      S t        | D cg c]  }t        j:                  |d       }} | j<                  | \  }}}t5        | j                  | j6                  ||||ddd		      S c c}w )
a  Build per-image stats tuples and delegate to class-level computation.

        Each stats tuple is ``(matches, confidence, class_ids, true_class_ids)``:
        - Both empty: skip (no information).
        - Targets empty, predictions present: all predictions are FPs; true_class_ids
          is ``zeros((0,))``.
        - Targets present: IoU matching produces ``matches`` array.
        g      ?gffffff?
   r   Ndtype)r   z-Unsupported metric target for IoU calculation)	r   r   precision_scoresprecision_per_classiou_thresholdsmatched_classesr1   r3   r5   )nplinspacezip_detections_contentr'   class_id
confidenceappendzerossizebool_int32boolfloat32intr   r   BOXESr   MASKSr   ORIENTED_BOUNDING_BOXESr   r(   _match_detection_batcharrayPrecisionResultr   shapeconcatenate_compute_precision_for_classes)r   predictions_listtargets_listrD   statsr*   r+   prediction_contentstarget_contentsioumatchesitemsconcatenated_statsrB   rC   unique_classess                   r   r.   zPrecision._compute   sQ    S$3$'(8,$G =	 K"&":":;"G"66w?O7|q S%5%9 ''/;3I3I3Q -~/B/BC288 $..#,,RXX6	 W!{#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#,,	m=	~ ""11!%!6!6!#.*>*>q*A!B$&HHa1E1Ea1H-I$J- "3 7"#"
 
 EHKP5bnnUA6PP/D//1CD 	>-~ --!22- 3)*

 
	
 Qs    N:c                   t        j                  |       }||   }||   }t        j                  t        j                  ||f            }t        j                  |d      \  }}t        j                  |j
                  d   t              }	||	t        j                  ||      <   | j                  ||||	      }
| j                  |
      }| j                  t        j                  k(  rt        j                  |d      }n| j                  t        j                  k(  r#|
j                  d      }| j                  |      }n| j                  t        j                   k(  rm|	j#                  t         j$                        }	|	j                         dk(  r#t        j                  |j
                  d         }nt        j&                  |d|	      }||fS )zCompute precision scores from concatenated stats across all images.

        ``unique_classes`` is the union of GT and predicted classes so that
        predictions of classes absent from GT still count as false positives.
        T)return_countsr   r@   axis   )rj   weights)rF   argsortuniquer[   rM   rZ   rS   searchsorted_compute_confusion_matrix_compute_precisionr   r   MACROmeanMICROsumWEIGHTEDastyperR   average)r   rc   prediction_confidenceprediction_class_idstrue_class_idssorted_indicesrf   true_classestrue_countsclass_countsconfusion_matrixrC   rB   confusion_matrix_mergeds                 r   r\   z(Precision._compute_precision_for_classes  s     %:$:;.)3NC NNN,@AB
 %'IInD$Q!kxx 4 4Q 7sCFQR__^\BC  99)><

 #556FG   O$9$99!ww':C""o&;&;;&6&:&:1&=##667NO""o&>&>>'..rzz:L!Q& $&88,?,E,Ea,H#I #%::'a$   !4nDDr    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@   rk   ri      T)return_index)rZ   rF   rM   rQ   	enumeratewherestackhstackrm   rn   rw   rS   )predictions_classestarget_classesrb   rD   num_predictionsnum_iou_levelscorrectcorrect_classi	iou_levelmatched_indicescombined_indices
iou_valuesrc   result_corrects                  r   rW   z Precision._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.
        rk   r      r@   ri   )rZ   rF   rM   float64r   ru   fullr   )sorted_matchessorted_prediction_class_idsrf   r   num_thresholdsnum_classesr   	class_idxrJ   is_classnum_truer   true_positivesfalse_positivesfalse_negativesresult_matrixs                   r   rp   z#Precision._compute_confusion_matrix^  sK   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'#	( 2Br    c                    | j                   d   dk(  st        d| j                          | d   }| d   }||z   }t        j                  ||t        j                  |      |dk7        }|}|S )aa  
        Broadcastable function, computing the precision 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 precision for each element.
        r   r   z/Confusion matrix must have shape (..., 3), got ).r   ).rk   r   )outr   )rZ   r(   rF   divide
zeros_like)r   r   r   denominator	precisionresult_precisions         r   rq   zPrecision._compute_precision  s      %%b)Q.A#))*,  *&1*62$6IIn-"	
	 5>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   rT   xyxyrU   mask_make_empty_contentrV   datagetr	   r'   rF   rX   rR   r(   )r   
detectionsresult_boxesresult_masksobb
result_obbs         r   rI   zPrecision._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   rT   rF   emptyrR   rU   rQ   rV   r(   )r   empty_boxesempty_masks	empty_obbs       r   r   zPrecision._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   rJ   rK   
tracker_idr   rd   rF   rX   )r   r   size_categorynew_detectionssizes	size_maskkeyr   s           r   _filter_detections_by_sizez$Precision._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   rL   r   )r   r]   r^   r   new_predictions_listnew_targets_listr*   r+   s           r   r/   z1Precision._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   rY   )r]   list[Detections]r^   r   r   rY   )
rc   npt.NDArray[np.bool_]ry   npt.NDArray[np.float32]rz   npt.NDArray[np.int32]r{   r   r   zNtuple[npt.NDArray[np.float64], npt.NDArray[np.float64], npt.NDArray[np.int32]])
r   r   r   r   rb   r   rD   r   r   r   )
r   r   r   r   rf   r   r   r   r   npt.NDArray[np.float64])r   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   rT   r   rv   r   r#   r,   r=   r.   r\   staticmethodrW   rp   rq   rI   r   r   r/    r    r   r   r      s   $P '3&8&8,;,D,D2#2 *2& 2 / 
	>:i
 0i
@Pi
	i
V7E&7E  77E 4	7E
 .7E
7Er 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)rY   u  
    The results of the precision 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
            precision. Determines how the precision is aggregated across classes.
        precision_at_50: the precision at IoU threshold of `0.5`.
        precision_at_75: the precision at IoU threshold of `0.75`.
        precision_scores: the precision scores at each IoU threshold.
            Shape: `(num_iou_thresholds,)`
        precision_per_class: the precision scores per class and
            IoU threshold. Shape: `(num_classes, num_iou_thresholds)`
        iou_thresholds: the IoU thresholds used in the calculations.
        matched_classes: the class IDs present in either predictions or ground
            truth. Corresponds to the rows of `precision_per_class`. Classes
            that appear only in predictions (no ground-truth instances) are
            included; their per-threshold precision values will be `0.0`.
        small_objects: the Precision metric results
            for small objects (area < 32²).
        medium_objects: the Precision metric results
            for medium objects (32² ≤ area < 96²).
        large_objects: the Precision metric results
            for large objects (area ≥ 96²).
    r   r   r   r   c                2    t        | j                  d         S )Nr   floatrB   r"   s    r   precision_at_50zPrecisionResult.precision_at_50*      T**1-..r    c                2    t        | j                  d         S )N   r   r"   s    r   precision_at_75zPrecisionResult.precision_at_75.  r   r    r   rB   rC   r   rD   r   rE   zPrecisionResult | 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 Precision
            >>> 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])
            ... )
            >>> precision_metric = Precision()
            >>> precision_result = precision_metric.update(
            ...     predictions, targets
            ... ).compute()
            >>> print(precision_result)  # doctest: +ELLIPSIS
            PrecisionResult:
            Metric target:    MetricTarget.BOXES
            Averaging method: AveragingMethod.WEIGHTED
            P @ 50:     1.0000
            P @ 75:     1.0000
            P @ thresh: [1. ... 1.]
            IoU thresh: [0.5  0.55 ... 0.95]
            Precision per class:
              0: [1. ... 1.]
            ...
            Medium objects:
              PrecisionResult:
              Metric target:    MetricTarget.BOXES
              Averaging method: AveragingMethod.WEIGHTED
              P @ 50:     0.0000
              ...

            ```
        z:
Metric target:    z
Averaging method: z
P @ 50:     z.4fz
P @ 75:     z
P @ thresh: z
IoU thresh: z
Precision 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   rN   rH   rE   r1   strreplacer3   r5   )r   out_strrJ   precision_of_classindentindenteds         r   __str__zPrecisionResult.__str__;  s   V ~~&&' (!!%!3!3 4 5!!%!6!6 7 8//4 5//4 5001 2../ 0%& 	 ##((A-''G,/  $":":-
 	?(H( H:R(:';2>>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P@50zP@75small_objects_medium_objects_large_objects_)index)
r   pandasr   r   r1   	to_pandasrd   r3   r5   	DataFrame)r   pdpandas_datasmall_objects_dfr   r   medium_objects_dflarge_objects_dfs           r   r   zPrecisionResult.to_pandas  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 precision results.

        ![example_plot](
            https://media.roboflow.com/supervision-docs/metrics/precision_plot_example.png
        ){ align=center width="800" }
        zPrecision@50zPrecision@75r   r   NzSmall: P@50zSmall: P@75r   zMedium: P@50zMedium: P@75zLarge: P@50zLarge: P@75r   	monospacezfont.family)r?      )figsizerk   Valuebold)
fontweightz#Precision, 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PrecisionResult.plot  s    !.1&&(<(<=&q)*Q.) ..M}m44F}44m6S6STTF+A./!33F*!00N~~66F~55~7U7UVVF+A./!33F) ..M}m44F}44m6S6STTF+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   rY   rY     sx    :  %%/ / / / .-00++**))**))FP4<>r    rY   )'
__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   rY   r   r    r   <module>r8     sq    "  ! %   $ 7 1 
 8 J J Dg6 g6T V V Vr    