
    ^j                       d dl mZ d dlmZ d dlmZ d dlZd dlmZ	 d dl
Zd dlmZ d dlmZmZmZmZ 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mZ ddZdej@                  f	 	 	 	 	 	 	 ddZ!ej@                  f	 	 	 	 	 	 	 ddZ" ee"dd      	 	 	 	 	 	 dd       Z#e G d d             Z$ eejJ                  dd       ed       G d d                    Z&y)    )annotations)Callable)	dataclassN)
TargetMode
deprecateddeprecated_classvoid)ORIENTED_BOX_COORDINATES)DetectionDataset)
Detections)box_iou_batchoriented_box_iou_batch)MetricTargetc                @    | t         j                  k(  rt        d      y )NzBMetricTarget.MASKS is not currently supported for ConfusionMatrix.)r   MASKS
ValueErrormetric_targets    h/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/metrics/detection.py_assert_supported_targetr      s%    ***P
 	
 +    Fc                   t        |       | j                  t        d      |t        j                  k(  r)| j
                  j                  t              }|Gt        |       dkD  rt        dt         d      t        j                  dt        j                        }nt        j                  |t        j                        }|j                  dk(  r$|j                  d	d d
k(  r|j                  dd      }|j                   t        |       dz  k7  r;t        dt         dt        |       dz   dt        |        d|j                    d	      |j                  dd      }n| j"                  }|t        j$                  | j                  j'                  t        j                        d	      g}|rF| j(                  t        d      |j+                  t        j$                  | j(                  d	             t        j,                  |d	      }|S )a
  
    Convert Supervision Detections to a numpy tensor for metric computation.

    Args:
        detections: Detections/Targets in the format of sv.Detections.
        with_confidence: Whether to include confidence as the last column.
        metric_target: The type of detection data to use.
            Supports `MetricTarget.BOXES` and
            `MetricTarget.ORIENTED_BOUNDING_BOXES`.

    Returns:
        Detections as a float32 numpy array. Shape depends on `metric_target`
        and `with_confidence`:

        | `metric_target`                        | `with_confidence` | shape     |
        |----------------------------------------|-------------------|-----------|
        | `MetricTarget.BOXES`                   | `False`           | `(N, 5)`  |
        | `MetricTarget.BOXES`                   | `True`            | `(N, 6)`  |
        | `MetricTarget.ORIENTED_BOUNDING_BOXES` | `False`           | `(N, 9)`  |
        | `MetricTarget.ORIENTED_BOUNDING_BOXES` | `True`            | `(N, 10)` |

        Column layout:

        - `BOXES`: ``[x_min, y_min, x_max, y_max, class_id [, confidence]]``
        - `ORIENTED_BOUNDING_BOXES`:
          ``[x1, y1, x2, y2, x3, y3, x4, y4, class_id [, confidence]]``

    Raises:
        ValueError: If `metric_target` is `MetricTarget.MASKS`.
        ValueError: If `detections.class_id` is `None`.
        ValueError: If `with_confidence=True` and `detections.confidence` is `None`.
        ValueError: If `metric_target` is `MetricTarget.ORIENTED_BOUNDING_BOXES`
            and `detections.data` does not contain `ORIENTED_BOX_COORDINATES`,
            or if the stored array does not have exactly `N * 8` elements.

    Examples:
        ```pycon
        >>> import numpy as np
        >>> import supervision as sv
        >>> from supervision.metrics.core import MetricTarget
        >>> from supervision.config import ORIENTED_BOX_COORDINATES
        >>> detections = sv.Detections(
        ...     xyxy=np.array([[0, 0, 10, 10]], dtype=np.float32),
        ...     class_id=np.array([0]),
        ...     confidence=np.array([0.9]),
        ... )
        >>> tensor = detections_to_tensor(detections, with_confidence=True)
        >>> tensor.shape
        (1, 6)
        >>> obb_coords = np.array([[0, 0, 10, 0, 10, 10, 0, 10]], dtype=np.float32)
        >>> det_obb = sv.Detections(
        ...     xyxy=np.array([[0, 0, 10, 10]], dtype=np.float32),
        ...     class_id=np.array([0]),
        ...     data={ORIENTED_BOX_COORDINATES: obb_coords},
        ... )
        >>> tensor_obb = detections_to_tensor(
        ...     det_obb, metric_target=MetricTarget.ORIENTED_BOUNDING_BOXES
        ... )
        >>> tensor_obb.shape
        (1, 9)

        ```
    NzCConfusionMatrix can only be calculated for Detections with class_idr   z'ORIENTED_BOUNDING_BOXES requested, but z  is missing from detections.data)r      dtype      )      r   z	Expected z to contain z elements (N=z& detections x 8 coordinates), but got z>. Each OBB must be stored as [x1, y1, x2, y2, x3, y3, x4, y4].zEConfusionMatrix can only be calculated for Detections with confidenceaxis)r   class_idr   r   ORIENTED_BOUNDING_BOXESdatagetr
   lennpemptyfloat32asarrayndimshapereshapesizexyxyexpand_dimsastype
confidenceappendconcatenate)
detectionswith_confidencer   obbbox_dataobb_arrarrays_to_concatresults           r   detections_to_tensorr=      s   H ]+"Q
 	
 <<<oo!!":;;:" =/00PR  xxbjj9HjjBJJ7G||q W]]12%6&%@!//"a0||s:22  89:*+ ,j/* +&||n -SS  r1-H?? 	
z**11"**=qA
   (W  	z/D/Da HI&(nn5EA&NFMr   c           	        t        |       t        |      k7  r$t        dt        |        dt        |       d      t        |       dkD  rt        | d   t        j                        rt        |d   t        j                        s*t        dt        | d          dt        |d          d      |t        j                  k(  rdnd	}|t        j                  k(  rd
nd}| d   j                  d   |k7  rt        d| d| d   j                   d      |d   j                  d   |k7  rt        d| d|d   j                   d      yy)z8
    Checks for shape consistency of input tensors.
    zNumber of predictions (z) andtargets (z) must be equal.r   z;Predictions and targets must be lists of numpy arrays. Got z and 	 instead.
      	      r   z Predictions must have shape (N, ). Got Targets must have shape (N, N)	r'   r   
isinstancer(   ndarraytyper   r$   r-   )predictionstargetsr   expected_pred_colsexpected_target_colss        r   _validate_input_tensorsrM      s    ;3w<'%c+&6%7 8G~%57
 	
 ;!+a."**5ZAJ

>
 KN+,E$wqz2B1C9N   <#G#GGBQ 	 ,"F"FFAA 	 q>"&8823E2F G"1~++,I7  1:A"66./C.D Eqz''(	3  7+ r   z0.29.0z0.32.0)targetdeprecated_in	remove_inc                    t        | |       y N)r	   rI   rJ   s     r   validate_input_tensorsrT      s     	gr   c                     e Zd ZU dZded<   ded<   ded<   ded<   ej                  Zd	ed
<   ddZdZ	e
ddej                  f	 	 	 	 	 	 	 	 	 	 	 	 	 dd       Ze
ddej                  f	 	 	 	 	 	 	 	 	 	 	 	 	 dd       Zeej                  f	 	 	 	 	 	 	 	 	 	 	 	 	 dd       Ze	 	 	 	 dd       Ze
ddej                  f	 	 	 	 	 	 	 	 	 	 	 dd       Z	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZy)ConfusionMatrixu  
    Confusion matrix for object detection tasks.

    Attributes:
        matrix: An 2D `np.ndarray` of shape `(len(classes) + 1, len(classes) + 1)`
            containing the number of `TP`, `FP`, `FN` and `TN` for each class.
        classes: Model class names.
        conf_threshold: Detection confidence threshold between `0` and `1`.
            Detections with lower confidence will be excluded from the matrix.
        iou_threshold: Detection IoU threshold between `0` and `1`.
            Detections with lower IoU will be classified as `FP`.
        metric_target: The type of detection data used for IoU computation.
            Informational metadata set by `from_detections` and `from_tensors`.
            Excluded from `__eq__` comparisons — two `ConfusionMatrix` instances
            with identical `matrix`, `classes`, `conf_threshold`, and
            `iou_threshold` compare as equal regardless of `metric_target`.
    npt.NDArray[np.int32]matrix	list[str]classesfloatconf_thresholdiou_thresholdr   r   c                $   t        |t              st        S t        j                  | j
                  |j
                        xrO | j                  |j                  k(  xr4 | j                  |j                  k(  xr | j                  |j                  k(  S rR   )	rF   rV   NotImplementedr(   array_equalrX   rZ   r\   r]   )selfothers     r   __eq__zConfusionMatrix.__eq__   sv    %1!!NN4;;5 :-:##u';';;: ""e&9&99		
r   Ng333333?      ?c                    g }g }t        ||      D ]?  \  }	}
|j                  t        |	d|             |j                  t        |
d|             A | j                  ||||||      S )a  
        Calculate confusion matrix based on predicted and ground-truth detections.

        Args:
            targets: Detections objects from ground-truth.
            predictions: Detections objects predicted by the model.
            classes: Model class names.
            conf_threshold: Detection confidence threshold between `0` and `1`.
                Detections with lower confidence will be excluded.
            iou_threshold: Detection IoU threshold between `0` and `1`.
                Detections with lower IoU will be classified as `FP`.
            metric_target: The type of detection data to use.
                Supports `MetricTarget.BOXES` (default) and
                `MetricTarget.ORIENTED_BOUNDING_BOXES`. When using
                `MetricTarget.ORIENTED_BOUNDING_BOXES`, each `Detections`
                object must include OBB coordinates in
                `detections.data[ORIENTED_BOX_COORDINATES]` as a float32
                array of shape `(N, 8)` (flat) or `(N, 4, 2)` (as stored by
                `from_ultralytics`); both are normalised to `(N, 8)` internally.
                `MetricTarget.MASKS` is not supported.

        Returns:
            New instance of ConfusionMatrix.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> import supervision as sv
            >>> targets = [
            ...     sv.Detections(
            ...         xyxy=np.array([[0, 0, 10, 10], [50, 50, 60, 60]]),
            ...         class_id=np.array([0, 0])
            ...     )
            ... ]
            >>> predictions = [
            ...     sv.Detections(
            ...         xyxy=np.array([[0, 0, 10, 10], [100, 100, 110, 110]]),
            ...         class_id=np.array([0, 0]),
            ...         confidence=np.array([0.9, 0.8])
            ...     )
            ... ]
            >>> confusion_matrix = sv.ConfusionMatrix.from_detections(
            ...     predictions=predictions,
            ...     targets=targets,
            ...     classes=['person']
            ... )
            >>> confusion_matrix.matrix
            array([[1., 1.],
                   [1., 0.]])

            ```
        T)r7   r   FrI   rJ   rZ   r\   r]   r   zipr4   r=   from_tensors)clsrI   rJ   rZ   r\   r]   r   prediction_tensorstarget_tensors
predictionrN   s              r   from_detectionszConfusionMatrix.from_detections   s    |  "%k7"; 
	J%%$M
 !!$E
	 *")''   
 	
r   c           
         t        |       t        |||       t        |      }t        j                  |dz   |dz   f      }t        ||      D ]  \  }	}
|| j                  |
|	||||      z  }!  | |||||      S )a 
  
        Calculate confusion matrix based on predicted and ground-truth detections.

        Args:
            predictions: Each element of the list describes a single
                image and has `shape = (M, 6)` or `shape = (M, 10)` depending on
                `metric_target`.
                If `MetricTarget.BOXES`, each row is in
                `(x_min, y_min, x_max, y_max, class, conf)` format.
                If `MetricTarget.ORIENTED_BOUNDING_BOXES`, each row is in
                `(x1, y1, x2, y2, x3, y3, x4, y4, class, conf)` format.
            targets: Each element of the list describes a single
                image and has `shape = (N, 5)` or `shape = (N, 9)` depending on
                `metric_target`.
                If `MetricTarget.BOXES`, each row is in
                `(x_min, y_min, x_max, y_max, class)` format.
                If `MetricTarget.ORIENTED_BOUNDING_BOXES`, each row is in
                `(x1, y1, x2, y2, x3, y3, x4, y4, class)` format.
            classes: Model class names.
            conf_threshold: Detection confidence threshold between `0` and `1`.
                Detections with lower confidence will be excluded.
            iou_threshold: Detection iou threshold between `0` and `1`.
                Detections with lower iou will be classified as `FP`.
            metric_target: The type of detection data to use.
                Determines expected tensor shapes (see Args above for column
                layouts). `MetricTarget.MASKS` is not supported.

        Returns:
            New instance of ConfusionMatrix.

        Examples:
            ```pycon
            >>> import supervision as sv
            >>> import numpy as np
            >>> targets = [
            ...     np.array([
            ...         [0.0, 0.0, 3.0, 3.0, 0],
            ...         [2.0, 2.0, 5.0, 5.0, 0],
            ...         [6.0, 1.0, 8.0, 3.0, 1],
            ...     ])
            ... ]
            >>> predictions = [
            ...     np.array([
            ...         [0.0, 0.0, 3.0, 3.0, 0, 0.9],
            ...         [0.1, 0.1, 3.0, 3.0, 0, 0.9],
            ...         [6.0, 1.0, 8.0, 3.0, 1, 0.8],
            ...     ])
            ... ]
            >>> confusion_matrix = sv.ConfusionMatrix.from_tensors(
            ...     predictions=predictions,
            ...     targets=targets,
            ...     classes=['person', 'dog']
            ... )
            >>> confusion_matrix.matrix
            array([[1., 0., 1.],
                   [0., 1., 0.],
                   [1., 0., 0.]])

            ```
        r   r   )rI   rJ   num_classesr\   r]   r   )rX   rZ   r\   r]   r   )r   rM   r'   r(   zerosrh   evaluate_detection_batch)rj   rI   rJ   rZ   r\   r]   r   rp   rX   
true_batchdetection_batchs              r   ri   zConfusionMatrix.from_tensorsA  s    L 	!/WMR'l;?K!O<=+.w+D 	'Jc22+"'-++ 3  F	 )''
 	
r   c           
     6   t        |       |t        j                  k(  rdnd}|t        j                  k(  rdnd}| j                  dk7  s| j                  d   |k7  rt        d| d| j                   d	      |j                  dk7  s|j                  d   |k7  rt        d
| d|j                   d	      t        j                  |dz   |dz   f      }|t        j                  k(  rdnd}	|	}
|	dz   }| dd|f   }| ||k\     }t        |      dk(  rDt        j                  |dd|
f   t        j                        }|D ]  }|||fxx   dz  cc<    |S t        |      dk(  rDt        j                  |dd|
f   t        j                        }|D ]  }|||fxx   dz  cc<    |S t        j                  |dd|
f   t        j                        }t        j                  |dd|
f   t        j                        }|ddd|	f   }|ddd|	f   }|t        j                  k(  rt        ||      }nt        ||      }||kD  }t        j                  |      \  }}|j                  dk(  rg }nr|||f   }||   }||   }||k(  }t        j                  | | f      }|D cg c]8  }t!        ||         t!        ||         t#        ||         t%        ||         f: }}t'               }t'               } |D ]L  \  }!}"}#}$|!|vs|"| vs||!   }||"   }|||fxx   dz  cc<   |j)                  |!       | j)                  |"       N t+        |      D ]  \  }!}|!|vs|||fxx   dz  cc<    t+        |      D ]  \  }"}|"| vs|||fxx   dz  cc<    |S c c}w )ad  
        Calculate confusion matrix for a batch of detections for a single image.

        Args:
            predictions: Batch prediction. Describes a single image and
                has `shape = (M, 6)` or `shape = (M, 10)` depending on
                `metric_target`.
                If `MetricTarget.BOXES`, each row is in
                `(x_min, y_min, x_max, y_max, class, conf)` format.
                If `MetricTarget.ORIENTED_BOUNDING_BOXES`, each row is in
                `(x1, y1, x2, y2, x3, y3, x4, y4, class, conf)` format.
            targets: Batch target labels. Describes a single image and
                has `shape = (N, 5)` or `shape = (N, 9)` depending on
                `metric_target`.
                If `MetricTarget.BOXES`, each row is in
                `(x_min, y_min, x_max, y_max, class)` format.
                If `MetricTarget.ORIENTED_BOUNDING_BOXES`, each row is in
                `(x1, y1, x2, y2, x3, y3, x4, y4, class)` format.
            num_classes: Number of classes.
            conf_threshold: Detection confidence threshold between `0` and `1`.
                Detections with lower confidence will be excluded.
            iou_threshold: Detection iou threshold between `0` and `1`.
                Detections with lower iou will be classified as `FP`.
            metric_target: The type of detection data to use.
                Determines IoU function (`box_iou_batch` vs
                `oriented_box_iou_batch`) and coordinate column count.
                `MetricTarget.MASKS` is not supported.

        Returns:
            Confusion matrix based on a single image.
        r@   rA   rB   rC   r   r   z Predictions must have shape (M, rD   r?   rE   r   r   Nr   r   )
boxes_trueboxes_detection)r   r   r$   r,   r-   r   r(   rq   r'   arrayint16r   r   nonzeror/   lexsortintr[   boolsetadd	enumerate)%rI   rJ   rp   r\   r]   r   rK   rL   result_matrix
coords_dimclass_id_idxconf_idxr3   detection_batch_filteredtrue_classesgt_classdetection_classes	det_class
true_boxesdetection_boxes	iou_batchiou_mask
gt_indicesdet_indicesvalid_matchesiousgt_match_classesdet_match_classesclass_matchessort_indicesidxmatched_gt_idxmatched_det_idxgt_idxdet_idxiouclass_matchs%                                        r   rr   z(ConfusionMatrix.evaluate_detection_batch  sK   P 	!/  <#G#GGBQ 	 ,"F"FFAA 	 q K$5$5a$8<N$N23E2F G"(()4  <<1a 04H H./C.D E}}oY0 
 +/;?!CD (<+O+OOQUV
!> H-
#.z^/K#L '(A-88GA|O$<BHHML( :h3494:  w<1 "(L9! / ;	k945:5;  xx< 8IHH$Q_5RXX
 Q^,
21kzk>B L@@@.%I &%I },"$**X"6
K ??aMZ45D+J7 1+ >,0AAM ::u}n&=>L (  
3(C()$s)$s+,	M  %1> 		--FGS+^+0N'/-g6	 h	12a72""6*##G,		- !*, 7 	:FH^+h3494	:
 #,,="> 	;GYo-k945:5	; Gs   "=Nc                >   | j                   d   dkD  r| | dddf   j                         ddd      } | t        j                  | dddf   d      d      } | | dddf   j                         ddd      } | t        j                  | dddf   d      d      } | }|S )z
        Deduplicate matches. If there are multiple matches for the same true or
        predicted box, only the one with the highest IoU is kept.
        r   Nr   r    r   Treturn_index)r-   argsortr(   unique)matchesr<   s     r   _drop_extra_matchesz#ConfusionMatrix._drop_extra_matches@  s     ==agadm335dd;<Gbii1DI!LMGgadm335dd;<Gbii1DI!LMG*1r   c                    g g }}|D ]0  \  }}	}
 ||	      }|j                  |       |j                  |
       2 | j                  |||j                  |||      S )ao  
        Calculate confusion matrix from dataset and callback function.

        Args:
            dataset: Object detection dataset used for evaluation.
            callback: Function that takes an image as input and returns a
                Detections object.
            conf_threshold: Detection confidence threshold between `0` and `1`.
                Detections with lower confidence will be excluded.
            iou_threshold: Detection IoU threshold between `0` and `1`.
                Detections with lower IoU will be classified as `FP`.
            metric_target: The type of detection data to use.
                Supports `MetricTarget.BOXES` and
                `MetricTarget.ORIENTED_BOUNDING_BOXES`. Passed through to
                `from_detections`. `MetricTarget.MASKS` is not supported.

        Returns:
            New instance of ConfusionMatrix.

        Example:
            ```python
            import supervision as sv
            from ultralytics import YOLO

            dataset = sv.DetectionDataset.from_yolo(...)

            model = YOLO(...)
            def callback(image: np.ndarray) -> sv.Detections:
                result = model(image)[0]
                return sv.Detections.from_ultralytics(result)

            confusion_matrix = sv.ConfusionMatrix.benchmark(
                dataset = dataset,
                callback = callback
            )

            print(confusion_matrix.matrix)
            # np.array([
            #     [0., 0., 0., 0.],
            #     [0., 1., 0., 1.],
            #     [0., 1., 1., 0.],
            #     [1., 1., 0., 0.]
            # ])
            ```
        rf   )r4   rn   rZ   )rj   datasetcallbackr\   r]   r   rI   rJ   _image
annotationpredictions_batchs               r   	benchmarkzConfusionMatrix.benchmarkP  sy    l  "2W$+ 	' Auj (01NN:&	' ""#OO)'' # 
 	
r   c                   | j                   j                         }|r)d}||j                  d      j                  dd      |z   z  }t        j
                  ||dk  <   t        j                  |dd      \  }}	||n| j                  }
|
d	uxr dt        |
      cxk  xr d
k  nc }|rg |
d}g |
d}t        |      }nd	}d	}t        |      }|	j                  |d      }|	j                  j                  ||	      }|j                  j                  dt	        j                  |             |d}nd}|	j!                  t	        j"                  d||      |       |	j%                  t	        j"                  d||      |       t        j&                  |	j)                         ddd       |dk  rdnd}|	j+                  dd|       |dk  rt-        |j.                  d         D ]x  }t-        |j.                  d         D ][  }|||f   }t	        j0                  |      r |	j3                  |||r|dn|ddd|d t	        j                  |      z  k  rd!nd"       ] z |r|	j5                  |d#$       |	j7                  d%       |	j9                  d&       |	j;                  d       |r#|j=                  |d'|j?                         d(       |S ))a  
        Create confusion matrix plot and save it at selected location.

        Args:
            save_path: Path to save the plot. If not provided,
                plot will be displayed.
            title: Title of the plot.
            classes: List of classes to be displayed on the plot.
                If not provided, all classes will be displayed.
            normalize: If True, normalize the confusion matrix.
            fig_size: Size of the plot.

        Returns:
            Confusion matrix plot.
        g:0yE>r   r   r    g{Gzt?Twhite)figsizetight_layout	facecolorNc   FNFPBlues)cmap)ax)vminvmaxr   )labelsZ   rightdefault)rotationharotation_mode2   r@   r   both)r"   which	labelsize   z.2fz.0fcenterrd   black)r   vacolor   )fontsize	PredictedTrue   )dpir   transparent) rX   copysumr.   r(   nanpltsubplotsrZ   r'   imshowfigurecolorbarmappableset_climnanmax
set_xticksarange
set_ytickssetpget_xticklabelstick_paramsranger-   isnantext	set_title
set_xlabel
set_ylabelset_facecolorsavefigget_facecolor)ra   	save_pathtitlerZ   	normalizefig_sizerx   epsfigr   class_namesuse_labels_for_ticksx_tick_labelsy_tick_labels	num_ticksimcbartick_intervalr   ijn_predss                         r   plotzConfusionMatrix.plot  s   0   "CUYYq\11!R83>?E!vveem,,xdgVR!(!4g$,,*$6VAK@P<USU<U0k040M0k040MM*I M ME
IYYu7Y+yy!!"!,ABIIe,<= MM
bii9m<]S
bii9m<]S##%wiX#b.Ba	
F&IFr>5;;q>* u{{1~. A#AqDkG88G,09wsm'#''&ryy/?)?? #*!(   	 LLL,
k"
f
!KKsc.?.?.At   
r   )rb   objectreturnr}   )rI   list[Detections]rJ   r   rZ   rY   r\   r[   r]   r[   r   r   r   rV   )rI   list[npt.NDArray[np.float32]]rJ   r   rZ   rY   r\   r[   r]   r[   r   r   r   rV   )rI   npt.NDArray[np.float32]rJ   r   rp   r|   r\   r[   r]   r[   r   r   r   rW   )r   r   r   r   )r   r   r   -Callable[[npt.NDArray[np.uint8]], Detections]r\   r[   r]   r[   r   r   r   rV   )NNNF)   r@   )r   
str | Noner   r  rZ   zlist[str] | Noner   r}   r   ztuple[int, int]r   zmatplotlib.figure.Figure)__name__
__module____qualname____doc____annotations__r   BOXESr   rc   __hash__classmethodrn   ri   staticmethodrr   r   r   r    r   r   rV   rV      sp   $ "!"."4"4M<4
 H !$"&2&8&8Q
%Q
 "Q
 	Q

 Q
 Q
 $Q
 
Q
 Q
f  !$"&2&8&8Y
2Y
 /Y
 	Y

 Y
 Y
 $Y
 
Y
 Y
v  '3&8&8`,`(` ` 	`
 ` $` 
` `D (	   
 !$"&2&8&8A
!A
 @A
 	A

 A
 $A
 
A
 A
J !% $($,WW W "	W
 W "W 
"Wr   rV   z0.27.0z0.31.0T)frozenc                      e Zd ZU dZded<   ded<   ded<   ded<   e	 	 	 	 	 	 dd       Ze	 	 	 	 	 	 dd	       Ze	 	 	 	 	 	 dd
       Ze		 	 	 	 	 	 dd       Z
e		 	 	 	 	 	 	 	 dd       Ze		 d	 	 	 	 	 	 	 	 	 	 	 dd       Zy)MeanAveragePrecisiona4  
    !!! deprecated "Deprecated"
        `MeanAveragePrecision` is **deprecated** and will be removed in
        `supervision-0.31.0`.

        The deprecated implementation provides results that are inconsistent with
        `pycocotools`. Please use
        `supervision.metrics.mean_average_precision.MeanAveragePrecision` instead,
        which matches the results of `pycocotools` and is now the recommended approach.

    Mean Average Precision for object detection tasks.

    Attributes:
        map50_95: Mean Average Precision (mAP) calculated over IoU thresholds
            ranging from `0.50` to `0.95` with a step size of `0.05`.
        map50: Mean Average Precision (mAP) calculated specifically at
            an IoU threshold of `0.50`.
        map75: Mean Average Precision (mAP) calculated specifically at
            an IoU threshold of `0.75`.
        per_class_ap50_95: Average Precision (AP) values calculated over
            IoU thresholds ranging from `0.50` to `0.95` with a step size of `0.05`,
            provided for each individual class.
    r[   map50_95map50map75npt.NDArray[np.float64]per_class_ap50_95c                    g }g }t        ||      D ]=  \  }}|j                  t        |d             |j                  t        |d             ? | j                  ||      S )ah  
        Calculate mean average precision based on predicted and ground-truth detections.

        Args:
            targets: Detections objects from ground-truth.
            predictions: Detections objects predicted by the model.
        Returns:
            New instance of ConfusionMatrix.

        Examples:
            ```pycon
            >>> import numpy as np
            >>> import supervision as sv
            >>> targets = [
            ...     sv.Detections(
            ...         xyxy=np.array([[0, 0, 10, 10]]),
            ...         class_id=np.array([0])
            ...     )
            ... ]
            >>> predictions = [
            ...     sv.Detections(
            ...         xyxy=np.array([[0, 0, 10, 10]]),
            ...         class_id=np.array([0]),
            ...         confidence=np.array([0.9])
            ...     )
            ... ]
            >>> mAP = sv.MeanAveragePrecision.from_detections(
            ...     predictions=predictions,
            ...     targets=targets,
            ... )
            >>> round(float(mAP.map50), 2)
            0.99

            ```
        T)r7   FrS   rg   )rj   rI   rJ   rk   rl   rm   rN   s          r   rn   z$MeanAveragePrecision.from_detections  s}    R  "%k7"; 	WJ%%$ZF !!"6vu"UV		W
 *"   
 	
r   c                    g g }}|D ]0  \  }}} ||      }|j                  |       |j                  |       2 | j                  ||      S )a  
        Calculate mean average precision from dataset and callback function.

        Args:
            dataset: Object detection dataset used for evaluation.
            callback: Function that takes
                an image as input and returns Detections object.
        Returns:
            New instance of MeanAveragePrecision.

        Example:
            ```python
            import supervision as sv
            from ultralytics import YOLO

            dataset = sv.DetectionDataset.from_yolo(...)

            model = YOLO(...)
            def callback(image: np.ndarray) -> sv.Detections:
                result = model(image)[0]
                return sv.Detections.from_ultralytics(result)

            mean_average_precision = sv.MeanAveragePrecision.benchmark(
                dataset = dataset,
                callback = callback
            )

            print(mean_average_precision.map50_95)
            # 0.433
            ```
        rS   )r4   rn   )	rj   r   r   rI   rJ   r   r   r   r   s	            r   r   zMeanAveragePrecision.benchmarkG  si    J  "2W$+ 	' Auj (01NN:&	' ""# # 
 	
r   c           	     H   t        ||       t        j                  ddd      }g }t        ||      D ]  \  }}|j                  d   dk(  rf|j                  d   rV|j                  t        j                  d|j                  ft              gt        j                  d      |dddf          ~|j                  d   s| j                  |||      }|j                  ||ddd	f   |dddf   |dddf   f        |rwt        | D cg c]  }t        j                  |d       }	} | j                  |	 }
|
dddf   j                         }|
ddd	f   j                         }|
j                         }nd
\  }}}t        j                  g       }
 | ||||
      S c c}w )aY  
        Calculate Mean Average Precision based on predicted and ground-truth
            detections at different threshold.

        Args:
            predictions: Each element of the list describes
                a single image and has `shape = (M, 6)` where `M` is
                the number of detected objects. Each row is expected to be
                in `(x_min, y_min, x_max, y_max, class, conf)` format.
            targets: Each element of the list describes a single
                image and has `shape = (N, 5)` where `N` is the
                number of ground-truth objects. Each row is expected to be in
                `(x_min, y_min, x_max, y_max, class)` format.
        Returns:
            New instance of MeanAveragePrecision.

        Examples:
            ```pycon
            >>> import supervision as sv
            >>> import numpy as np
            >>> targets = [
            ...     np.array([
            ...         [0.0, 0.0, 3.0, 3.0, 0],
            ...         [2.0, 2.0, 5.0, 5.0, 0],
            ...         [6.0, 1.0, 8.0, 3.0, 1],
            ...     ])
            ... ]
            >>> predictions = [
            ...     np.array([
            ...         [0.0, 0.0, 3.0, 3.0, 0, 0.9],
            ...         [0.1, 0.1, 3.0, 3.0, 0, 0.9],
            ...         [6.0, 1.0, 8.0, 3.0, 1, 0.8],
            ...     ])
            ... ]
            >>> mAP = sv.MeanAveragePrecision.from_tensors(
            ...     predictions=predictions,
            ...     targets=targets,
            ... )
            >>> round(float(mAP.map50), 2)
            0.81

            ```
        rd   gffffff?r@   r   r   )r   r   Nr   rC   )r   r   r   )r  r  r  r  )rM   r(   linspacerh   r-   r4   rq   r/   r}   _match_detection_batchr5   _average_precisions_per_classmeanrx   )rj   rI   rJ   iou_thresholdsstats	true_objspredicted_objsr   itemsconcatenated_statsaverage_precisionsr  r  r  s                 r   ri   z!MeanAveragePrecision.from_tensorsv  s   b 	 W5S$3 *-Wk)B 	%I~##A&!+??1%LLHHa)<)<%=TJXXf- &adO q!44"I~ &q!t,&q!t,!!Q$	!	4 HKU!Tu"..":!T!T!B!B!BDV!W&q!t,113E&q!t,113E)..0H%,"E5(!#"0	
 	
 "Us   Fc                   t        j                  dg| dgf      }t        j                  dg|dgf      }t        j                  t         j                  j	                  t        j                  |                  }t        j
                  ddd      }t        j                  |||      }t        t         d      r!t        j                  ||      }t        |      S  t        t         d      ||      }t        |      S )a  
        Compute the average precision using 101-point interpolation (COCO), given
            the recall and precision curves.

        Args:
            recall: The recall curve.
            precision: The precision curve.

        Returns:
            Average precision.
        g        g      ?r   r   e   	trapezoidtrapz)r(   r5   flipmaximum
accumulater  interphasattrr&  getattrr[   )recall	precisionextended_recallextended_precisionmax_accumulated_precisioninterpolated_recall_levelsinterpolated_precisionaverage_precisions           r   compute_average_precisionz.MeanAveragePrecision.compute_average_precision  s      ..3%#)?@^^cUIu,EF$&GGJJ!!"''*<"=>%
! &([[As%;"!#&9R"

 2{# "&(B! &''	 !5G 4&(B! &''r   c                   | j                   d   |j                   d   }}t        j                  ||ft              }t	        |ddddf   | ddddf         }|ddddf   | 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 )a   
        Match predictions with target labels based on IoU levels.

        Args:
            predictions: Batch prediction. Describes a single image and
                has `shape = (M, 6)` where `M` is the number of detected objects.
                Each row is expected to be in
                `(x_min, y_min, x_max, y_max, class, conf)` format.
            targets: Batch target labels. Describes a single image and
                has `shape = (N, 5)` where `N` is the number of ground-truth objects.
                Each row is expected to be in
                `(x_min, y_min, x_max, y_max, class)` format.
            iou_thresholds: Array contains different IoU thresholds.

        Returns:
            Matched prediction with target labels result.
        r   r   Nr   rC   r   r!   r   r    Tr   )r-   r(   rq   r}   r   r   wherestackhstackr   r   r2   r|   )rI   rJ   r  num_predictionsnum_iou_levelscorrectr   correct_classr   	iou_levelmatched_indicescombined_indices
iou_valuesr   r<   s                  r   r  z+MeanAveragePrecision._match_detection_batch  s   . +6*;*;A*>@T@TUV@W((O^<DIGArrENK2A2,>?1Q3;q!t+<<%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	= )0r   c                v   t        j                  |       }| |   } ||   }t        j                  |d      \  }}|j                  d   }t        j                  || j                  d   ft         j
                        }	t        |      D ]  \  }
}||k(  }||
   }|j                         }|dk(  s|dk(  r+d| |   z
  j                  d      }| |   j                  d      }|||z   z  }|||z   z  }t        | j                  d         D ]+  }t        j                  |dd|f   |dd|f         |	|
|f<   -  |	}|S )a  
        Compute the average precision, given the recall and precision curves.
        Source: https://github.com/rafaelpadilla/Object-Detection-Metrics.

        Args:
            matches: True positives.
            prediction_confidence: Objectness value from 0-1.
            prediction_class_ids: Predicted object classes.
            true_class_ids: True object classes.
            eps: Small value to prevent division by zero.

        Returns:
            Average precision for different IoU levels.
        T)return_countsr   r   r   N)r(   r   r   r-   rq   float64r   r   cumsumr   r  r6  )r   prediction_confidenceprediction_class_idstrue_class_idsr   sorted_indicesunique_classesclass_countsrp   r#  	class_idxr#   is_class
total_truetotal_predictionfalse_positivestrue_positivesr.  r/  iou_level_idxr<   s                        r   r  z2MeanAveragePrecision._average_precisions_per_class*  sn   , %:$:;.)3NC')yyt'T$$**1-68hh'--*+2::7
 $-^#< 	Ix+x7H%i0J'||~1$
a 78#44<<Q?O$X.55a8N#zC'78F&.?*JKI!&w}}Q'7!8 (BBq-/0)A}<L2M #9m#;<	( +=r   N)rI   r   rJ   r   r   r  )r   r   r   r  r   r  )rI   r   rJ   r   r   r  )r.  r  r/  r  r   r[   )rI   r   rJ   r   r  r   r   npt.NDArray[np.bool_])gؗҜ<)r   rT  rG  r   rH  rW   rI  rW   r   r[   r   r  )r  r  r  r  r  r  rn   r   ri   r  r6  r  r  r  r   r   r  r    sn   0 OLL..2
%2
 "2
 
	2
 2
h ,
!,
 @,
 
	,
 ,
\ ^
2^
 /^
 
	^
 ^
@ #('#(*#( 
#( #(J *,*(* 0* 
	* *X  5&565 45 .	5
 5 
!5 5r   r  )r   r   r   None)r6   r   r7   r}   r   r   r   r   )rI   r   rJ   r   r   r   r   rU  )rI   r   rJ   r   r   rU  )'
__future__r   collections.abcr   dataclassesr   
matplotlibmatplotlib.pyplotpyplotr   numpyr(   numpy.typingtypingnpt	deprecater   r   r   r	   supervision.configr
   supervision.dataset.corer   supervision.detection.corer   'supervision.detection.utils.iou_and_nmsr   r   supervision.metrics.corer   r   r	  r=   rM   rT   rV   NOTIFYr  r  r   r   <module>rg     sB   " $ !     D D 7 5 1 2
 ""."4"4rrr  r 	rp #/"4"4&.&*&  & 
	&R "
.* 

 c c cL 
 $l l lr   