
    ^jj                        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
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 d dlmZm Z  d dl!m"Z" erd dl#Z$e G d d             Z% G d de      Z&y)    )annotations)deepcopy)	dataclass)TYPE_CHECKINGAnycastN)pyplot)ORIENTED_BOX_COORDINATES)
Detections)box_iou_batchmask_iou_batchoriented_box_iou_batch)LEGACY_COLOR_PALETTE)MetricMetricTarget)ObjectSizeCategoryget_detection_size_category)ensure_pandas_installedc                      e Zd ZU dZded<   edd       Z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ed<   ddZ	ddZ
ddZy)MeanAverageRecallResultux  
    The results of the Mean Average 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.
        mAR_at_1: the Mean Average Recall, when considering only the top
            highest confidence detection for each class.
        mAR_at_10: the Mean Average Recall, when considering top 10
            highest confidence detections for each class.
        mAR_at_100: the Mean Average Recall, when considering top 100
            highest confidence detections for each class.
        recall_per_class: the recall scores per class and IoU threshold.
            Shape: `(num_target_classes, num_iou_thresholds)`
        max_detections: the array with maximum number of detections
            considered.
        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 Mean Average Recall
            metric results for small objects (area < 32²).
        medium_objects: the Mean Average Recall
            metric results for medium objects (32² ≤ area < 96²).
        large_objects: the Mean Average Recall
            metric results for large objects (area ≥ 96²).
    r   metric_targetc                2    t        | j                  d         S )Nr   floatrecall_scoresselfs    r/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/metrics/mean_average_recall.pymAR_at_1z MeanAverageRecallResult.mAR_at_1?       T''*++    c                2    t        | j                  d         S )N   r   r   s    r   	mAR_at_10z!MeanAverageRecallResult.mAR_at_10C   r    r!   c                2    t        | j                  d         S )N   r   r   s    r   
mAR_at_100z"MeanAverageRecallResult.mAR_at_100G   r    r!   npt.NDArray[np.float64]r   recall_per_classnpt.NDArray[np.int32]max_detectionsnpt.NDArray[np.float32]iou_thresholdsmatched_classeszMeanAverageRecallResult | Nonesmall_objectsmedium_objectslarge_objectsc                   | j                   j                   d| j                   d| j                  d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 MeanAverageRecall
            >>> 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])
            ... )
            >>> mar_metric = MeanAverageRecall()
            >>> mar_result = mar_metric.update(predictions, targets).compute()
            >>> print(mar_result)  # doctest: +ELLIPSIS
            MeanAverageRecallResult:
            Metric target:  MetricTarget.BOXES
            mAR @ 1:    1.0000
            mAR @ 10:   1.0000
            mAR @ 100:  1.0000
            max detections: [  1  10 100]
            IoU thresh:     [0.5  0.55 ... 0.95]
            mAR per class:
              0: [1. ... 1.]
            ...
            Medium objects:
              MeanAverageRecallResult:
              Metric target:  MetricTarget.BOXES
              mAR @ 1:    0.0000
              ...

            ```
        z:
Metric target:  z
mAR @ 1:    z.4fz
mAR @ 10:   z
mAR @ 100:  z
max detections: z
IoU thresh:     z
mAR per class:
r   z  No results
z  z: 
z
Small objects:
z
Medium objects:
z
Large objects:
)	__class____name__r   r   r$   r'   r+   r-   r)   sizezipr.   r/   strreplacer0   r1   )r   out_strclass_idrecall_of_classindentindenteds         r   __str__zMeanAverageRecallResult.__str__U   s   P ~~&&' (#112 3==- .>>#. /??3/ 0#223 4#223 4  	   %%*''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                4   t                ddl}| j                  | 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mAR @ 1zmAR @ 10z	mAR @ 100small_objects_medium_objects_large_objects_)index)r   pandasr   r$   r'   r/   	to_pandasitemsr0   r1   	DataFrame)r   pdpandas_datasmall_objects_dfkeyvaluemedium_objects_dflarge_objects_dfs           r   rG   z!MeanAverageRecallResult.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                    g d}| j                   | j                  | j                  g}t        d   gdz  }| j                  I| j                  }|g dz  }||j                   |j                  |j                  gz  }|t        d   gdz  z  }| j
                  I| j
                  }|g dz  }||j                   |j                  |j                  gz  }|t        d   gdz  z  }| j                  I| j                  }|g dz  }||j                   |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                  |	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 Mean Average Recall results.

        ![example_plot](            https://media.roboflow.com/supervision-docs/metrics/mAR_plot_example.png            ){ align=center width="800" }
        rA   r      N)zSmall: mAR @ 1zSmall: mAR @ 10zSmall: mAR @ 100)zMedium: mAR @ 1zMedium: mAR @ 10zMedium: mAR @ 100r&   )zLarge: mAR @ 1zLarge: mAR @ 10zLarge: mAR @ 100   	monospacezfont.family)
      )figsizer#   Valuebold)
fontweightz-Mean Average Recall, by Object Size
(target: )center)coloralign-   right)rotationhag{Gz?z.2fbottom)rb   vaz
sans-serif)r   r$   r'   r   r/   r0   r1   pltrcParamssubplotsset_ylim
set_ylabelr   rN   	set_titlerangelenbar
set_xticksset_xticklabels
get_heighttextget_x	get_widthtight_layoutshow)r   labelsvaluescolorsr/   r0   r1   _axtitlex_positionsbarsrm   y_values                 r   plotzMeanAverageRecallResult.plot   s    6--A&q)*Q.) ..MOOF&&''(( F
 +A./!33F*!00NRRF''(()) F
 +A./!33F) ..MOOF&&''(( F
 +A./!33F&1]#W-2
Aq
g&1<T=O=O=U=U<VVWX 	 	Uv.CK(vvk6xvH
k"
6B7; 	Cnn&GGG		cmmo11$3-  	 '3]#
r!   N)returnr   )r   r8   )r   zpd.DataFramer   None)r5   
__module____qualname____doc____annotations__propertyr   r$   r'   r?   rG   r    r!   r   r   r      s    :  , , , , , , +*--))++**112211CJ4>Gr!   r   c                  (   e Zd ZdZ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)MeanAverageRecalla<  
    Mean Average Recall (mAR) measures how well the model detects
    and retrieves relevant objects by averaging recall over multiple
    IoU thresholds, classes and detection limits.

    Intuitively, while Recall measures the ability to find all relevant
    objects, mAR narrows down how many detections are considered for each
    class. For example, mAR @ 100 considers the top 100 highest confidence
    detections for each class. mAR @ 1 considers only the highest
    confidence detection for each class.

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

        ```

    ![example_plot](
        https://media.roboflow.com/supervision-docs/metrics/mAR_plot_example.png
    ){ align=center width="800" }
    c                f    || _         g | _        g | _        t        j                  g d      | _        y)z
        Initialize the Mean Average Recall metric.

        Args:
            metric_target: The type of detection data to use.
        )r#   rU   d   N)_metric_target_predictions_list_targets_listnparrayr+   )r   r   s     r   __init__zMeanAverageRecall.__init__)  s-     ,35/1 hh|4r!   c                     g | _         g | _        y)zR
        Reset the metric to its initial state, clearing all stored data.
        N)r   r   r   s    r   resetzMeanAverageRecall.reset:  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listrl   
ValueErrorr   extendr   )r   predictionstargetss      r   updatezMeanAverageRecall.updateA  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 Mean Average Recall metric based on the stored predictions
        and ground-truth, at different IoU thresholds and maximum detection counts.

        Returns:
            The Mean Average Recall metric result.
        )_computer   r   '_filter_predictions_and_targets_by_sizer   SMALLr/   MEDIUMr0   LARGEr1   )r   resultsmall_predictionssmall_targetsmedium_predictionsmedium_targetslarge_predictionslarge_targetss           r   computezMeanAverageRecall.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                Z   t        j                  ddd      }g }t        ||      D ]  \  }}| j                  |      }| j                  |      }t	        |      dkD  s8t	        |      dk(  rw|j                  t        j                  d|j                  ft              t        j                  dt              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       |	|      }
t        j,                  t/        t0        j2                  t         j4                     |j6                               }|j                  |
|   t        j8                  t	        |            t/        t0        j2                  t         j:                     |j                        |   t/        t0        j2                  t         j:                     |j                        f        |st=        | j                  t        j                  |j>                  d         t        j                  d|j>                  d   f      | j@                  |t        j*                  g t              d d d 	      S t        | D cg c]  }t        jB                  |d       }} | jD                  | \  }}}t=        | j                  ||| j@                  ||d d d 	      S c c}w )	Ng      ?gffffff?rU   r   dtype)r   z-Unsupported metric target for IoU calculation)	r   r   r)   r+   r-   r.   r/   r0   r1   )#r   linspacer7   _detections_contentrl   appendzerosr6   boolintr;   r   r   BOXESr   MASKSr   ORIENTED_BOUNDING_BOXESr   r   _match_detection_batchr   argsortr   nptNDArrayfloat32
confidencearangeint32r   shaper+   concatenate#_compute_average_recall_for_classes)r   predictions_listtargets_listr-   statsr   r   prediction_contentstarget_contentsioumatchessorted_indicesrH   concatenated_statsrecall_scores_per_kr)   unique_classess                    r   r   zMeanAverageRecall._compute}  s*    S$3$'(8,$G 4	 K"&":":;"G"66w?O7|a{#q(LLHHa)<)<%=TJHHT5HHT5#,,	 **l.@.@@+O=PQ,,0B0BB,_>QR,,0T0TT4+-@ )K  #99&//; $,,XXb\"++7  ((XXb\&	G &(ZZckk"**5{7M7MNN&N LL#N3IIc+&67 RXX!68L8LM . !RXX!68H8HI	W4	l *"11 hh~';';A'>?!#1n.B.B1.E*F!G#22- "3 7"#"
 
 EHKP5bnnUA6PP4D446HI 	>-~ '----..)*

 
	
 Qs   N(c                p   t        j                  |d      \  }}g }| j                  D ]D  }| j                  |||k     |||k     ||      }	| j	                  |	      }
|j                  |
       F t        j                  |      }t        j                  |d      }t        j                  |d      }|
|fS )NT)return_countsr&   axisr#   )r   uniquer+   _compute_confusion_matrix_compute_recallr   r   mean)r   r   prediction_indicesprediction_class_idstrue_class_idsr   class_countsrecalls_at_kr+   confusion_matrixr)   average_recall_per_classr   s                r   r   z5MeanAverageRecall._compute_average_recall_for_classes  s     (*yyt'T$"11 	2N#==*^;<$%7.%HI	   $334DE 01	2 xx-#%77<a#@   8qA.>>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   r#   r   r&   T)return_index)r   r   r   r   	enumeratewherestackhstackr   r   astyper   )predictions_classestarget_classesr   r-   num_predictionsnum_iou_levelscorrectcorrect_classi	iou_levelmatched_indicescombined_indices
iou_valuesr   result_corrects                  r   r   z(MeanAverageRecall._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                  ||
      }nu|
dk(  rAt        j                  |      }t        j                  ||      }t        j                  |      }n/| |	   }|j                  d      }d|z
  j                  d      }|
|z
  }t        j                  |||gd      ||<    |}|S )a  
        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.
            max_detections: The maximum number of detections to
                consider for each class. Extra detections are considered false
                positives. By default, all detections are considered.

        Returns:
            shape (C, Th, 3), containing the true positives, false
                positives, and false negatives for each class and IoU threshold.
        r#   r   rR   r   r   )r   r   r   float64r   sumfullr   )sorted_matchessorted_prediction_class_idsr   r   num_thresholdsnum_classesr   	class_idxr;   is_classnum_truer   true_positivesfalse_positivesfalse_negativeslimited_matchesresult_confusion_matrixs                    r   r   z+MeanAverageRecall._compute_confusion_matrix  sL   < (--a0$**1-46HH.!,BJJ5
 $-^#< 	Ix2h>H#I.H&llnO!#!#.!9"$((>":"$''.("CQ!#.!9"$''./"J"$((>":"0":!0!4!4Q!7#$#6";";A">"*^";*,((/B+Y')	0 <L&&r!   c                    | j                   d   dk(  st        d| j                          | d   }| d   }||z   }t        j                  |dk(  d||z        }|}|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   rR   z/Confusion matrix must have shape (..., 3), got ).r   ).r&   r   )r   r   r   r   )r   r   r   denominatorrecallresult_recalls         r   r   z!MeanAverageRecall._compute_recallY  s      %%b)Q.A#))*,  *&1*62$6+*A~/KL17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   r   xyxyr   mask_make_empty_contentr   datagetr
   rl   r   r   r   r   )r   
detectionsresult_boxesresult_masksobb
result_obbs         r   r   z%MeanAverageRecall._detections_contentu  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   rS   r   )r   r   r   )r   rS   r&   r  )
r   r   r   r   emptyr   r   r   r   r   )r   empty_boxesempty_masks	empty_obbs       r   r  z%MeanAverageRecall._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   rN   r  r  r;   r   
tracker_idr	  rH   r   r   )r   r  size_categorynew_detectionssizes	size_maskrM   rN   s           r   _filter_detections_by_sizez,MeanAverageRecall._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.
        )r7   r   r  )r   r   r   r  new_predictions_listnew_targets_listr   r   s           r   r   z9MeanAverageRecall._filter_predictions_and_targets_by_size  sx      "$'(8,$G 	 K ''//]K ##//G		 $%555r!   N)r   r   r   )r   Detections | list[Detections]r   r!  r   r   )r   r   )r   list[Detections]r   r"  r   r   )
r   npt.NDArray[np.bool_]r   r*   r   r*   r   r*   r   zNtuple[npt.NDArray[np.float64], npt.NDArray[np.float64], npt.NDArray[np.int32]])
r   r*   r   r*   r   r,   r-   r,   r   r#  )
r   r#  r   r*   r   r*   r   r*   r   r(   )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]])r5   r   r   r   r   r   r   r   r   r   r   r   staticmethodr   r   r   r   r  r  r   r   r!   r   r   r     s   #N '3&8&85#5" 2 / 
	>:X
 0X
@PX
	 X
t"?&"? 2"? 4	"?
 ."?
"?H 2- % 0	
 
 < <'-<'%:<' .<' ,	<'
 
!<' <'| 1	  6J$J$5G	46*6 '6 *	6
 
36r!   r   )'
__future__r   copyr   dataclassesr   typingr   r   r   numpyr   numpy.typingr   
matplotlibr	   re   supervision.configr
   supervision.detection.corer   'supervision.detection.utils.iou_and_nmsr   r   r   supervision.draw.colorr   supervision.metrics.corer   r   %supervision.metrics.utils.object_sizer   r   supervision.metrics.utils.utilsr   rF   rJ   r   r   r   r!   r   <module>r4     sq    "  ! + +   $ 7 1 
 8 9 D a a aH6 6r!   