o
    .wiz                  	   @   s  d dl Z d dlmZ d dlmZmZmZmZmZm	Z	 d dl
Zd dlZd dlmZ d dlmZmZ d dlmZmZ d dlmZ d dlmZ d dlmZmZmZ d d	lmZmZ es[d
gZ er_escd
dgZ e !e"Z#d"de$e ded defddZ%	d"de$e de$e ded defddZ&G dd de'Z(G dd de(Z)G dd de(Z*G dd de(Z+de$e,ej-ej-f  de$e,ej-ej-f  defdd Z.G d!d deZ/dS )#    N)Sequence)AnyCallableListLiteralOptionalUnion)	IntTensorTensor)_fix_empty_tensors_input_validator)Metric)_cumsum)_MATPLOTLIB_AVAILABLE_PYCOCOTOOLS_AVAILABLE_TORCHVISION_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPEMeanAveragePrecision.plotMeanAveragePrecisionbboxinputsiou_typer   segmreturnc                 C   s~   ddl m} ddlm} t| dkrtg S |dkr!|t| S |dkr7dd | D } t|	| 
dS td	| d
)z~Compute area of input depending on the specified iou_type.

    Default output for empty input is :class:`~torch.Tensor`

    r   N)box_arear   r   c                 S      g | ]}|d  |d dqS r      )sizecounts .0ir"   r"   \/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/detection/_mean_ap.py
<listcomp>5       z compute_area.<locals>.<listcomp>float	IOU type  is not supported)pycocotools.maskmasktorchvision.opsr   lenr
   torchstacktensorareaastype	Exception)r   r   
mask_utilsr   r"   r"   r&   compute_area&   s   r7   detgtc                 C   sL   ddl m} |dkr|t| t|S |dkrt| |S td| d)zMCompute IOU between detections and ground-truth using the specified iou_type.r   )box_iour   r   r*   r+   )r.   r:   r0   r1   	_segm_iour5   )r8   r9   r   r:   r"   r"   r&   compute_iou;   s   
r<   c                   @   sJ   e Zd ZdZdedefddZdededdfdd	Zdeddfd
dZdS )BaseMetricResultsz>Base metric class, that allows fields for pre-defined metrics.keyr   c                 C   s   || v r| | S t d| )z Get a specific metric attribute.No such attribute: AttributeErrorselfr>   r"   r"   r&   __getattr__M   s   zBaseMetricResults.__getattr__valueNc                 C   s   || |< dS )z Set a specific metric attribute.Nr"   )rC   r>   rE   r"   r"   r&   __setattr__T   s   zBaseMetricResults.__setattr__c                 C   s   || v r| |= t d| )z#Delete a specific metric attribute.r?   r@   rB   r"   r"   r&   __delattr__X   s   zBaseMetricResults.__delattr__)	__name__
__module____qualname____doc__strr
   rD   rF   rG   r"   r"   r"   r&   r=   J   s
    r=   c                   @      e Zd ZdZdZdS )MAPMetricResultsz$Class to wrap the final mAP results.)classesmapmap_50map_75	map_large
map_medium	map_smallNrH   rI   rJ   rK   	__slots__r"   r"   r"   r&   rN   _       rN   c                   @   rM   )MARMetricResultsz$Class to wrap the final mAR results.)mar_1mar_10mar_100	mar_large
mar_medium	mar_smallNrV   r"   r"   r"   r&   rY   e   rX   rY   c                   @   rM   )COCOMetricResultszMClass to wrap the final COCO metric results including various mAP/mAR values.)rP   rQ   rR   rS   rT   map_per_classrU   rZ   r[   r\   mar_100_per_classr]   r^   r_   NrV   r"   r"   r"   r&   r`   k   rX   r`   c                 C   sF   ddl m} dd | D }dd |D }t|||dd |D S )a
  Compute IOU between detections and ground-truths using mask-IOU.

    Implementation is based on pycocotools toolkit for mask_utils.

    Args:
       det: A list of detection masks as ``[(RLE_SIZE, RLE_COUNTS)]``, where ``RLE_SIZE`` is (width, height) dimension
           of the input and RLE_COUNTS is its RLE representation;

       gt: A list of ground-truth masks as ``[(RLE_SIZE, RLE_COUNTS)]``, where ``RLE_SIZE`` is (width, height) dimension
           of the input and RLE_COUNTS is its RLE representation;

    r   Nc                 S   r   r   r"   r#   r"   r"   r&   r'      r(   z_segm_iou.<locals>.<listcomp>c                 S   r   r   r"   r#   r"   r"   r&   r'      r(   c                 S      g | ]}d qS )Fr"   r$   _r"   r"   r&   r'          )r,   r-   r0   r2   iou)r8   r9   r6   det_coco_formatgt_coco_formatr"   r"   r&   r;      s   r;   c                       s  e Zd ZU dZdZeed< dZee ed< dZ	eed< dZ
eed< d	Zeed
< ee ed< ee ed< ee ed< ee ed< ee ed< 						dldeded deee  deee  deee  dededdf fddZdeeeef  deeeef  ddfd d!Zdmd"d#Zd$eeef deeef fd%d&Zdefd'd(Zd)ed*ed+edefd,d-Zd.ed/ed0eeef d1edeeef f
d2d3Zd4ed)ed5ed+ed0eeef d1edeeef fd6d7Zd)ed*ed0eeef d+ed8edee fd9d:Ze d;ed<ed=ed>ed8ed?edefd@dAZ!			B	CdndDedEedFee d0edGedefdHdIZ"dJedee#e$f fdKdLZ%dMedNedee#e$f fdOdPZ&e dQedRedSedTedUedVedWeded+edXedYedeeeef fdZd[Z'defd\d]Z(d^e)de*j+j,f fd_d`Z-dodaee) dbee ddf fdcddZ.e 	dpdeeeeef  dbee dee fdfdgZ/	dodheeeeef e0eeef  f  diee1 de2fdjdkZ3  Z4S )qr   a  Compute the `Mean-Average-Precision (mAP) and Mean-Average-Recall (mAR)`_ for object detection predictions.

    .. math::
        \text{mAP} = \frac{1}{n} \sum_{i=1}^{n} AP_i

    where :math:`AP_i` is the average precision for class :math:`i` and :math:`n` is the number of classes. The average
    precision is defined as the area under the precision-recall curve. If argument `class_metrics` is set to ``True``,
    the metric will also return the mAP/mAR per class.

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

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

        - boxes: (:class:`~torch.FloatTensor`) of shape ``(num_boxes, 4)`` containing ``num_boxes`` detection
          boxes of the format specified in the constructor.
          By default, this method expects ``(xmin, ymin, xmax, ymax)`` in absolute image coordinates.
        - scores: :class:`~torch.FloatTensor` of shape ``(num_boxes)`` containing detection scores for the boxes.
        - labels: :class:`~torch.IntTensor` of shape ``(num_boxes)`` containing 0-indexed detection classes for
          the boxes.
        - masks: :class:`~torch.bool` of shape ``(num_boxes, image_height, image_width)`` containing boolean masks.
          Only required when `iou_type="segm"`.

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

        - boxes: :class:`~torch.FloatTensor` of shape ``(num_boxes, 4)`` containing ``num_boxes`` ground truth
          boxes of the format specified in the constructor.
          By default, this method expects ``(xmin, ymin, xmax, ymax)`` in absolute image coordinates.
        - labels: :class:`~torch.IntTensor` of shape ``(num_boxes)`` containing 0-indexed ground truth
          classes for the boxes.
        - masks: :class:`~torch.bool` of shape ``(num_boxes, image_height, image_width)`` containing boolean masks.
          Only required when `iou_type="segm"`.

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

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

        - map: (:class:`~torch.Tensor`)
        - map_small: (:class:`~torch.Tensor`)
        - map_medium:(:class:`~torch.Tensor`)
        - map_large: (:class:`~torch.Tensor`)
        - mar_1: (:class:`~torch.Tensor`)
        - mar_10: (:class:`~torch.Tensor`)
        - mar_100: (:class:`~torch.Tensor`)
        - mar_small: (:class:`~torch.Tensor`)
        - mar_medium: (:class:`~torch.Tensor`)
        - mar_large: (:class:`~torch.Tensor`)
        - map_50: (:class:`~torch.Tensor`) (-1 if 0.5 not in the list of iou thresholds)
        - map_75: (:class:`~torch.Tensor`) (-1 if 0.75 not in the list of iou thresholds)
        - map_per_class: (:class:`~torch.Tensor`) (-1 if class metrics are disabled)
        - mar_100_per_class: (:class:`~torch.Tensor`) (-1 if class metrics are disabled)
        - classes (:class:`~torch.Tensor`)

    For an example on how to use this metric check the `torchmetrics mAP example`_.

    .. attention::
        The ``map`` score is calculated with @[ IoU=self.iou_thresholds | area=all | max_dets=max_detection_thresholds ]
        **Caution:** If the initialization parameters are changed, dictionary keys for mAR can change as well.
        The default properties are also accessible via fields and will raise an ``AttributeError`` if not available.

    .. important::
        This metric is following the mAP implementation of `pycocotools`_ a standard implementation for the mAP metric
        for object detection.

    .. hint::
        This metric requires you to have `torchvision` version 0.8.0 or newer installed
        (with corresponding version 1.7.0 of torch or newer). This metric requires `pycocotools`
        installed when iou_type is `segm`. Please install with ``pip install torchvision`` or
        ``pip install torchmetrics[detection]``.

    Args:
        box_format:
            Input format of given boxes. Supported formats are ``[`xyxy`, `xywh`, `cxcywh`]``.
        iou_type:
            Type of input (either masks or bounding-boxes) used for computing IOU.
            Supported IOU types are ``["bbox", "segm"]``.
            If using ``"segm"``, masks should be provided (see :meth:`update`).
        iou_thresholds:
            IoU thresholds for evaluation. If set to ``None`` it corresponds to the stepped range ``[0.5,...,0.95]``
            with step ``0.05``. Else provide a list of floats.
        rec_thresholds:
            Recall thresholds for evaluation. If set to ``None`` it corresponds to the stepped range ``[0,...,1]``
            with step ``0.01``. Else provide a list of floats.
        max_detection_thresholds:
            Thresholds on max detections per image. If set to `None` will use thresholds ``[1, 10, 100]``.
            Else, please provide a list of ints.
        class_metrics:
            Option to enable per-class metrics for mAP and mAR_100. Has a performance impact.
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ModuleNotFoundError:
            If ``torchvision`` is not installed or version installed is lower than 0.8.0
        ModuleNotFoundError:
            If ``iou_type`` is equal to ``segm`` and ``pycocotools`` is not installed
        ValueError:
            If ``class_metrics`` is not a boolean
        ValueError:
            If ``preds`` is not of type (:class:`~List[Dict[str, Tensor]]`)
        ValueError:
            If ``target`` is not of type ``List[Dict[str, Tensor]]``
        ValueError:
            If ``preds`` and ``target`` are not of the same length
        ValueError:
            If any of ``preds.boxes``, ``preds.scores`` and ``preds.labels`` are not of the same length
        ValueError:
            If any of ``target.boxes`` and ``target.labels`` are not of the same length
        ValueError:
            If any box is not type float and of length 4
        ValueError:
            If any class is not type int and of length 1
        ValueError:
            If any score is not type float and of length 1

    Example:
        >>> from torch import tensor
        >>> from torchmetrics.detection import MeanAveragePrecision
        >>> preds = [
        ...   dict(
        ...     boxes=tensor([[258.0, 41.0, 606.0, 285.0]]),
        ...     scores=tensor([0.536]),
        ...     labels=tensor([0]),
        ...   )
        ... ]
        >>> target = [
        ...   dict(
        ...     boxes=tensor([[214.0, 41.0, 562.0, 285.0]]),
        ...     labels=tensor([0]),
        ...   )
        ... ]
        >>> metric = MeanAveragePrecision()
        >>> metric.update(preds, target)
        >>> from pprint import pprint
        >>> pprint(metric.compute())
        {'classes': tensor(0, dtype=torch.int32),
         'map': tensor(0.6000),
         'map_50': tensor(1.),
         'map_75': tensor(1.),
         'map_large': tensor(0.6000),
         'map_medium': tensor(-1.),
         'map_per_class': tensor(-1.),
         'map_small': tensor(-1.),
         'mar_1': tensor(0.6000),
         'mar_10': tensor(0.6000),
         'mar_100': tensor(0.6000),
         'mar_100_per_class': tensor(-1.),
         'mar_large': tensor(0.6000),
         'mar_medium': tensor(-1.),
         'mar_small': tensor(-1.)}

    Fis_differentiableThigher_is_betterfull_state_update        plot_lower_bound      ?plot_upper_bound
detectionsdetection_scoresdetection_labelsgroundtruthsgroundtruth_labelsxyxyr   N
box_formatr   r   iou_thresholdsrec_thresholdsmax_detection_thresholdsclass_metricskwargsr   c                    s  t  jdi | tstdtstdd}d}	||vr'td| d| || _|p8tddt	d	d
 
 | _|pHtddt	dd
 
 | _tt|pRg d\}
}|

 | _||	vrjtd|	 d| |dkrttsttd|| _tdtdftdtdftdtdftdtdfd| _t|tstd|| _| jdg d d | jdg d d | jdg d d | jdg d d | jdg d d d S )Nz`MAP` metric requires that `pycocotools` installed. Please install with `pip install pycocotools` or `pip install torchmetrics[detection]`z`MeanAveragePrecision` metric requires that `torchvision` is installed. Please install with `pip install torchmetrics[detection]`.)rv   xywhcxcywh)r   r   z,Expected argument `box_format` to be one of z	 but got       ?gffffff?g!@r   rm   ro   g      Y@)r   
   d   z*Expected argument `iou_type` to be one of r   zBWhen `iou_type` is set to 'segm', pycocotools need to be installedr   g    _Bi   i $  )allsmallmediumlargez1Expected argument `class_metrics` to be a booleanrq   )defaultdist_reduce_fxrr   rs   rt   ru   r"   )super__init__r   ModuleNotFoundErrorr   
ValueErrorrw   r0   linspaceroundtolistrx   ry   sortr	   rz   r   r)   bbox_area_ranges
isinstanceboolr{   	add_state)rC   rw   r   rx   ry   rz   r{   r|   allowed_box_formatsallowed_iou_typesmax_det_thresholdre   	__class__r"   r&   r   ;  sH   
  

zMeanAveragePrecision.__init__predstargetc                 C   s   t ||| jd |D ]}| |}| j| | j|d  | j|d  q
|D ]}| |}| j| | j|d  q*dS )z*Update state with predictions and targets.r   labelsscoresN)	r   r   _get_safe_item_valuesrq   appendrs   rr   rt   ru   )rC   r   r   itemrq   rt   r"   r"   r&   updatep  s   

zMeanAveragePrecision.updatec                 C   s\   | j D ](}t| |}g }t|tr%|D ]}t|ts|d}|| qt| || qdS )z+Move list states to cpu to save GPU memory.cpuN)	_defaultsgetattrr   r   tupletor   setattr)rC   r>   current_valcurrent_to_cpucur_vr"   r"   r&   _move_list_states_to_cpu  s   




z-MeanAveragePrecision._move_list_states_to_cpur   c                 C   s   dd l m} ddlm} | jdkr't|d }| dkr%||| jdd}|S | jdkrRg }|d  	 D ]}|
t|}|t|d	 |d
 f q6t|S td| j d)Nr   )box_convertr   boxesrv   )in_fmtout_fmtr   masksr    r!   r*   r+   )r,   r-   r.   r   r   r   numelrw   r   numpyencodenpasfortranarrayr   r   r5   )rC   r   r6   r   r   r   r%   rler"   r"   r&   r     s   

z*MeanAveragePrecision._get_safe_item_valuesc                 C   s:   t | jdkst | jdkrt| j| j   S g S )zIReturn a list of unique classes found in ground truth and detection data.r   )r/   rs   ru   r0   catuniquer   )rC   r"   r"   r&   _get_classes  s   z!MeanAveragePrecision._get_classesidxclass_idmax_detc           	         s  | j | | j|  | j| |k d}| j| |k d}t|dks.t|dkr2tg S fdd|D  fdd|D  tdksPt dkrTtg S | j| }|| j| |k }t	j
|dd} fdd|D  t |kr~ d	|  t | j| jS )
a  Compute the Intersection over Union (IoU) between bounding boxes for the given image and class.

        Args:
            idx:
                Image Id, equivalent to the index of supplied samples
            class_id:
                Class Id of the supplied ground truth and detection labels
            max_det:
                Maximum number of evaluated detection bounding boxes

        r   r   c                       g | ]} | qS r"   r"   r#   r9   r"   r&   r'         z5MeanAveragePrecision._compute_iou.<locals>.<listcomp>c                    r   r"   r"   r#   r8   r"   r&   r'     r   T
descendingc                    r   r"   r"   r#   r   r"   r&   r'     r   N)rt   rq   ru   nonzerosqueezers   r/   r
   rr   r0   argsortr<   r   r   device)	rC   r   r   r   gt_label_maskdet_label_maskr   scores_filteredindsr"   r8   r9   r&   _compute_iou  s"   


z!MeanAveragePrecision._compute_iour9   r   
area_rangenum_iou_thrsc                    s    fdd|D  t  }t | jd| j}||d k ||d kB }t|tj\}}	|tj}d}
tj	||
ftj| jd}tj	||
ftj| jdtj	||ftj| jdtj	|
tj
| jd||dS )z7Evaluate images with a ground truth but no predictions.c                    r   r"   r"   r#   r   r"   r&   r'     r   zEMeanAveragePrecision.__evaluate_image_gt_no_preds.<locals>.<listcomp>r   r   r   dtyper   	dtMatches	gtMatchesdtScoresgtIgnoredtIgnore)r/   r7   r   r   r   r0   r   uint8r   zerosfloat32)rC   r9   r   r   r   num_gtareasignore_area	gt_ignorere   num_det
det_ignorer"   r   r&   __evaluate_image_gt_no_preds  s   z1MeanAveragePrecision.__evaluate_image_gt_no_predsr8   r   c                    s  d}t j|t j| jd} fdd|D  | j| }	|	| }
t j|
dd\}} fdd|D  t |kr< d|  t }t | jd		| j}||d k ||d
 kB }|
d
|f}t ||d}t j||ft j| jdt j||ft j| jd|	| j|	| j|	| jdS )z6Evaluate images with a prediction but no ground truth.r   r   c                    r   r"   r"   r#   r   r"   r&   r'     r   zEMeanAveragePrecision.__evaluate_image_preds_no_gt.<locals>.<listcomp>Tr   c                    r   r"   r"   r#   r   r"   r&   r'     r   Nr   r   r   )r0   r   r   r   rr   r   r/   r7   r   r   reshaperepeat_interleave)rC   r8   r   r   r   r   r   r   r   r   r   scores_sorteddtindr   	det_areasdet_ignore_areaarr   r"   r   r&   __evaluate_image_preds_no_gt  s(   



z1MeanAveragePrecision.__evaluate_image_preds_no_gtiousc                    s  | j | | j|  | j| |k d}| j| |k d}t|dkr0t|dkr0dS t| j}t|dkrIt|dkrI| |||S t|dkr_t|dkr_| 	 |||||S fdd|D  fdd|D  tdkrt dkrdS t
 tr g t
trgt| jd| j}	t|	|d k |	|d k}
t|
tj\}}|tj| j}fdd|D | j| }|| }tj|d	d
\}} fdd|D  t |kr d|  t|||f dkr|||f dd|f n|||f }t| j}t}t }tj||ftj| jd}tj||ftj| jd}|}tj||ftj| jd}t|dkrt| jD ]4\}}t D ]*\}}t||||||}|dkrgqR|| |||f< d|||f< d|||f< qRqJt | jd| j}||d k ||d kB }|d|f}t|t|dkt||d}|| j|| j|| j|| j|| jdS )a  Perform evaluation for single class and image.

        Args:
            idx:
                Image Id, equivalent to the index of supplied samples.
            class_id:
                Class Id of the supplied ground truth and detection labels.
            area_range:
                List of lower and upper bounding box area threshold.
            max_det:
                Maximum number of evaluated detection bounding boxes.
            ious:
                IoU results for image and class.

        r   r   Nc                    r   r"   r"   r#   r   r"   r&   r'   0  r   z8MeanAveragePrecision._evaluate_image.<locals>.<listcomp>c                    r   r"   r"   r#   r   r"   r&   r'   1  r   r   c                    r   r"   r"   r#   r   r"   r&   r'   C  r   Tr   c                    r   r"   r"   r#   r   r"   r&   r'   G  r   r   r   )rt   rq   ru   r   r   rs   r/   rx   1_MeanAveragePrecision__evaluate_image_gt_no_preds1_MeanAveragePrecision__evaluate_image_preds_no_gtr   dictr7   r   r   r   r0   
logical_orr   r   r   rr   r   r   	enumerater   _find_best_gt_matchr   logical_andr   )rC   r   r   r   r   r   r   r   r   r   r   ignore_area_sortedgtindr   r   r   r   r   r   
gt_matchesdet_matchesr   r   idx_ioutidx_detre   mr   r   r   r"   r   r&   _evaluate_image  sx   





:

	




z$MeanAveragePrecision._evaluate_image	thresholdr   r   r   r   c           
      C   s>   || }||B }|| |  }|   }	||	 | kr|	S dS )a0  Return id of best ground truth match with current detection.

        Args:
            threshold:
                Current threshold value.
            gt_matches:
                Tensor showing if a ground truth matches for threshold ``t`` exists.
            idx_iou:
                Id of threshold ``t``.
            gt_ignore:
                Tensor showing if ground truth should be ignored.
            ious:
                IoUs for all combinations of detection and ground truth.
            idx_det:
                Id of current detection.

        r   )argmaxr   )
r   r   r   r   r   r   previously_matchedremove_maskgt_ious	match_idxr"   r"   r&   r   o  s   z(MeanAveragePrecision._find_best_gt_matchr   r   resultsavg_preciou_thresholdmax_detsc           
         s   fddt | j D }fddt | jD }|rH|d }|dur8| j|}	||	dddd||f }n8|dddddd||f }n(|d }|durd| j|}	||	dddd||f }n|dddd||f }t||dk dkrtd	gS t	||dk S )
a  Perform evaluation for single class and image.

        Args:
            results:
                Dictionary including precision, recall and scores for all combinations.
            avg_prec:
                Calculate average precision. Else calculate average recall.
            iou_threshold:
                IoU threshold. If set to ``None`` it all values are used. Else results are filtered.
            area_range:
                Bounding box area range key.
            max_dets:
                Maximum detections.

        c                       g | ]
\}}| kr|qS r"   r"   r$   r%   k)r   r"   r&   r'         z3MeanAveragePrecision._summarize.<locals>.<listcomp>c                    r  r"   r"   r  r  r"   r&   r'     r  	precisionNrecallr   r         )
r   r   keysrz   rx   indexr/   r0   r2   mean)
rC   r  r  r  r   r  	area_inds	mdet_indsprecr   r"   r   r  r&   
_summarize  s    2zMeanAveragePrecision._summarize	class_idsc                    s>  t tjjd j  fddD  fddD }tj}tj}t}tj}tj}t}t	|||||f }	t	||||f }
t	|||||f }t
j}tD ]+\}}tjD ]!\}}tjD ]\}}tj|
|	|||||||||d\}
}	}qqxqo|	|
fS )zCalculate the precision and recall for all supplied classes to calculate mAP/mAR.

        Args:
            class_ids:
                List of label class Ids.

        r   c              	      s*   i | ]} D ]}||f ||qqS r"   )r   )r$   r   r   )r  max_detectionsrC   r"   r&   
<dictcomp>  s    z3MeanAveragePrecision._calculate.<locals>.<dictcomp>c                    s2   g | ]} D ]}D ]} |||q
qqS r"   )r   )r$   r   r3   img_id)area_rangesimg_idsr   r  rC   r"   r&   r'     s    
z3MeanAveragePrecision._calculate.<locals>.<listcomp>)idx_clsidx_bbox_areaidx_max_det_thresholds	eval_imgsry   r   num_imgsnum_bbox_areas)ranger/   rt   rz   r   valuesrx   ry   r0   onesr2   r   r   8_MeanAveragePrecision__calculate_recall_precision_scores)rC   r  r  r   num_rec_thrsnum_classesr   num_max_det_thresholdsr  r
  r  r   rec_thresholds_tensorr  re   r  r  r   r"   )r  r  r  r   r  rC   r&   
_calculate  sL   





zMeanAveragePrecision._calculate
precisionsrecallsc                 C   s4  ||d}t  }| jd }| j|d|d|_d| jv r&| j|dd|d|_ntdg|_d| jv r=| j|dd|d|_ntdg|_| j|dd|d	|_	| j|dd
|d	|_
| j|dd|d	|_t }| jD ]}| j|d|d|d| < qh| j|dd|d	|_| j|dd
|d	|_| j|dd|d	|_||fS )zSummarizes the precision and recall values to calculate mAP/mAR.

        Args:
            precisions:
                Precision values for different thresholds
            recalls:
                Recall values for different thresholds

        )r
  r  r   Tr	  r   )r  r  g      ?r   r  r   r   Fmar_)rN   rz   r  rP   rx   rQ   r0   r2   rR   rU   rT   rS   rY   r_   r^   r]   )rC   r*  r+  r  map_metricslast_max_det_thresholdmar_metricsr   r"   r"   r&   _summarize_results  s(   





z'MeanAveragePrecision._summarize_resultsr  r
  r   r  r  r  r  r  r   c           $         s  t |}||
 |	 ||	  fddt|	D }dd |D }|s)| ||fS tfdd|D }|jrA|jtju rAtjn|j}tj|	|dd}|| }tjfdd|D dd	d d |f }tjfd
d|D dd	d d |f }tdd |D }t
|dk}|dkr| ||fS t|t|}tt|t|}t|dtjd}t|dtjd}tt||D ]\}\}}t |}|| }||| ttjj  }t|f}t|f} |r|d nd| ||||f< tjd|jd}!tjd|jd}"t|"dks0tjt|dd  |d d  |!fddd}"||"7 }t|"dkrtj||	|jdd}| |krG| n|}#|d |# }|| |d |#< || | d |#< |||d d |||f< | ||d d |||f< q| ||fS )Nc                    s   g | ]
}  |  qS r"   r"   r#   )r  idx_bbox_area_pointeridx_cls_pointerr"   r&   r'   )  r  zLMeanAveragePrecision.__calculate_recall_precision_scores.<locals>.<listcomp>c                 S   s   g | ]}|d ur|qS Nr"   r$   er"   r"   r&   r'   *  s    c                    s   g | ]
}|d  d  qS )r   Nr"   r4  r   r"   r&   r'   .  r  Tr   c                    $   g | ]}|d  ddd f qS )r   Nr"   r4  r6  r"   r&   r'   8     $ r   )axisc                    r7  )r   Nr"   r4  r6  r"   r&   r'   9  r8  c                 S   s   g | ]}|d  qS )r   r"   r4  r"   r"   r&   r'   :  r   Fr   )dimr   r   )r   )r   )min)right)r/   r!  r0   r   is_cudar   r   r   r   r   count_nonzeror   logical_notr   r)   r   zipfinfofloat64epsr   r   r#  r   clampsearchsortedmaxr   )$r  r
  r   r  r  r  r  ry   r   r  r   r%  img_eval_cls_bbox
det_scoresr   r   det_scores_sortedr   r   r   npigtpsfpstp_sumfp_sumr   tpfptp_lenrcprr  score	diff_zerodiffnum_indsr"   )r  r1  r2  r   r&   #__calculate_recall_precision_scores  sT   
((
.
z8MeanAveragePrecision.__calculate_recall_precision_scoresc                 C   s6  |   }| |\}}| ||\}}tdg}tdg}| jrug }g }	t|D ]:\}
}|dddd|
f jdd}|dd|
f jdd}| ||\}}||j	 |	|d| j
d    q*tj|tjd}tj|	tjd}t }|| || ||_||d| j
d  d	< tj|tjd|_|S )
zCompute metric.r  N   )r:  r   r,  r   )r   
_per_class)r   r)  r0  r0   r2   r{   r   	unsqueezer   rP   rz   r)   r`   r   ra   intrO   )rC   rO   r*  r+  map_valmar_valmap_per_class_valuesmar_max_dets_per_class_valuesmap_per_class_listmar_max_dets_per_class_list	class_idxre   cls_precisionscls_recallscls_mapcls_marmetricsr"   r"   r&   compute]  s.   

zMeanAveragePrecision.computefnc                    s.   | j dkrt j|dd}|S t |}|S )zCustom apply function.

        Excludes the detections and groundtruths from the casting when the iou_type is set to `segm` as the state is
        no longer a tensor but a tuple.

        r   )rq   rt   )exclude_state)r   r   _apply)rC   rj  thisr   r"   r&   rl  |  s
   
zMeanAveragePrecision._applydist_sync_fnprocess_groupc                    sB   t  j||d | jdkr| | j|| _| | j|| _dS dS )zCustom sync function.

        For the iou_type `segm` the detections and groundtruths are no longer tensors but tuples. Therefore, we need
        to gather the list of tuples and then convert it back to a list of tuples.

        )rn  ro  r   N)r   
_sync_distr   _gather_tuple_listrq   rt   )rC   rn  ro  r   r"   r&   rp    s
   
zMeanAveragePrecision._sync_distlist_to_gatherc                    sZ   t j|dt j|d dd tD  t j | |d  fddtt d D S )z.Gather a list of tuples over multiple devices.)groupc                 S   rc   r3  r"   rd   r"   r"   r&   r'     rf   z;MeanAveragePrecision._gather_tuple_list.<locals>.<listcomp>c                    s&   g | ]}t D ]} | | qqS r"   )r!  )r$   r   ranklist_gathered
world_sizer"   r&   r'     s   & r   )distget_world_sizebarrierr!  all_gather_objectr/   )rr  ro  r"   ru  r&   rq    s
    z'MeanAveragePrecision._gather_tuple_listvalaxc                 C   s   |  ||S )a  Plot a single or multiple values from the metric.

        Args:
            val: Either a single result from calling `metric.forward` or `metric.compute` or a list of these results.
                If no value is provided, will automatically call `metric.compute` and plot that result.
            ax: An matplotlib axis object. If provided will add plot to that axis

        Returns:
            Figure object and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> from torch import tensor
            >>> from torchmetrics.detection.mean_ap import MeanAveragePrecision
            >>> preds = [dict(
            ...     boxes=tensor([[258.0, 41.0, 606.0, 285.0]]),
            ...     scores=tensor([0.536]),
            ...     labels=tensor([0]),
            ... )]
            >>> target = [dict(
            ...     boxes=tensor([[214.0, 41.0, 562.0, 285.0]]),
            ...     labels=tensor([0]),
            ... )]
            >>> metric = MeanAveragePrecision()
            >>> metric.update(preds, target)
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.detection.mean_ap import MeanAveragePrecision
            >>> preds = lambda: [dict(
            ...     boxes=torch.tensor([[258.0, 41.0, 606.0, 285.0]]) + torch.randint(10, (1,4)),
            ...     scores=torch.tensor([0.536]) + 0.1*torch.rand(1),
            ...     labels=torch.tensor([0]),
            ... )]
            >>> target = [dict(
            ...     boxes=torch.tensor([[214.0, 41.0, 562.0, 285.0]]),
            ...     labels=torch.tensor([0]),
            ... )]
            >>> metric = MeanAveragePrecision()
            >>> vals = []
            >>> for _ in range(20):
            ...     vals.append(metric(preds(), target))
            >>> fig_, ax_ = metric.plot(vals)

        )_plot)rC   r|  r}  r"   r"   r&   plot  s   9r   )rv   r   NNNF)r   N)TNr   r   )NNr3  )5rH   rI   rJ   rK   rj   r   __annotations__rk   r   rl   rn   r)   rp   r   r
   rL   r   listr\  r   r   r   r   r   r   r   r   r   r   r   r   r   staticmethodr   r  rN   rY   r)  r0  r$  ri  r   r0   nnModulerl  rp  rq  r   r   r   r  __classcell__r"   r"   r   r&   r      sB  
  


	.5
"(





'

d 
-:#	
E$")r   )0loggingcollections.abcr   typingr   r   r   r   r   r   r   r   r0   torch.distributeddistributedrx  r	   r
   torchmetrics.detection.helpersr   r   torchmetrics.metricr   torchmetrics.utilities.datar   torchmetrics.utilities.importsr   r   r   torchmetrics.utilities.plotr   r   __doctest_skip__	getLoggerrH   logr  r7   r<   r   r=   rN   rY   r`   r   ndarrayr;   r   r"   r"   r"   r&   <module>   sD    
 
6