a
    dj                     @   s  d dl Z d dlmZmZ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sd	gZ erd d
l!m"Z"m#Z#m$Z$ nd Z# Z$Z"d	dgZ erd dl%m&Z' ndZ'd	dgZ e (e)Z*dee e+edddZ,d ee ee e+edddZ-G dd de.Z/G dd de/Z0G dd de/Z1G dd de/Z2eeej3ej3f  eeej3ej3f  edddZ4G dd deZ5dS )!    N)AnyCallableDictListOptionalSequenceTupleUnion)	IntTensorTensor)_fix_empty_tensors_input_validator)Metric)_cumsum)_MATPLOTLIB_AVAILABLE_PYCOCOTOOLS_AVAILABLE_TORCHVISION_GREATER_EQUAL_0_8)_AX_TYPE_PLOT_OUT_TYPEMeanAveragePrecision.plot)box_areabox_convertbox_iouMeanAveragePrecisionbbox)inputsiou_typereturnc                 C   sj   t | dkrtg S |dkr*tt| S |dkrVdd | D } tt| dS t	d| dd	S )
z~Compute area of input depending on the specified iou_type.

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

    r   r   segmc                 S   s   g | ]}|d  |d dqS r      )sizecounts .0ir#   r#   h/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/detection/_mean_ap.py
<listcomp>;       z compute_area.<locals>.<listcomp>float	IOU type  is not supportedN)
lenr   r   torchstacktensor
mask_utilsareaZastype	Exception)r   r   r#   r#   r'   compute_area/   s    r4   )detgtr   r   c                 C   sD   |dkrt t| t|S |dkr0t| |S td| ddS )zMCompute IOU between detections and ground-truth using the specified iou_type.r   r   r+   r,   N)r   r.   r/   	_segm_iour3   )r5   r6   r   r#   r#   r'   compute_iouA   s
    
r8   c                   @   sB   e Zd ZdZeedddZeeddddZedd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| dS )z Get a specific metric attribute.No such attribute: NAttributeErrorselfr:   r#   r#   r'   __getattr__Q   s    zBaseMetricResults.__getattr__N)r:   valuer   c                 C   s   || |< dS )z Set a specific metric attribute.Nr#   )r?   r:   rA   r#   r#   r'   __setattr__X   s    zBaseMetricResults.__setattr__c                 C   s    || v r| |= t d| dS )z#Delete a specific metric attribute.r;   Nr<   r>   r#   r#   r'   __delattr__\   s    zBaseMetricResults.__delattr__)	__name__
__module____qualname____doc__strr   r@   rB   rC   r#   r#   r#   r'   r9   N   s   r9   c                   @   s   e Zd ZdZdZdS )MAPMetricResultsz$Class to wrap the final mAP results.)mapmap_50map_75	map_small
map_medium	map_largeclassesNrD   rE   rF   rG   	__slots__r#   r#   r#   r'   rI   c   s   rI   c                   @   s   e Zd ZdZdZdS )MARMetricResultsz$Class to wrap the final mAR results.)mar_1mar_10mar_100	mar_small
mar_medium	mar_largeNrQ   r#   r#   r#   r'   rS   i   s   rS   c                   @   s   e Zd ZdZdZdS )COCOMetricResultszMClass to wrap the final COCO metric results including various mAP/mAR values.)rJ   rK   rL   rM   rN   rO   rT   rU   rV   rW   rX   rY   map_per_classZmar_100_per_classNrQ   r#   r#   r#   r'   rZ   o   s   rZ   )r5   r6   r   c                 C   s:   dd | D }dd |D }t 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;

    c                 S   s   g | ]}|d  |d dqS r   r#   r$   r#   r#   r'   r(      r)   z_segm_iou.<locals>.<listcomp>c                 S   s   g | ]}|d  |d dqS r   r#   r$   r#   r#   r'   r(      r)   c                 S   s   g | ]}d qS )Fr#   r%   _r#   r#   r'   r(      r)   )r.   r0   r1   Ziou)r5   r6   Zdet_coco_formatZgt_coco_formatr#   r#   r'   r7      s    r7   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< dLeeeee  eee  eee  eedd fddZeeeef  eeeef  ddddZddddZeeef eeef dddZeddd Zeeeed!d"d#Zeeeeef eeeef d$d%d&Zeeeeeeef eeeef d'd(d)Zeeeeef eeee d*d+d,Zeeeeeeeed-d.d/Z dMeeee eeed2d3d4Z!eee"e#f d5d6d7Z$eeee"e#f d8d9d:Z%eeeeeeee&eeeeeeeef d;d<d=Z'edd>d?Z(e)e*j+j,d@ fdAdBZ-dNee) ee ddC fdDdEZ.edOee ee ee dFdGdHZ/dPeeeeef e0eeef  f  ee1 e2dI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`_.

    .. note::
        ``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.

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

    .. note::
        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   iou_thresholdsrec_thresholdsmax_detection_thresholdsclass_metricskwargsr   c                    s  t  jf i | tstdd}d}	||vrBtd| d| || _|pdtddtdd	 	 | _
|ptd
dtdd	 	 | _tt|pg d\}
}|
	 | _||	vrtd|	 d| |dkrtstd|| _tdtdftdtdftdtdftdtdfd| _t|ts6t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`MeanAveragePrecision` metric requires that `torchvision` version 0.8.0 or newer is installed. Please install with `pip install torchvision>=0.8` or `pip install torchmetrics[detection]`.)rj   ZxywhZcxcywh)r   r   z,Expected argument `box_format` to be one of z	 but got       ?gffffff?g!@r    ra   rc   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 booleanre   )defaultZdist_reduce_fxrf   rg   rh   ri   )super__init__r   ModuleNotFoundError
ValueErrorrk   r.   Zlinspaceroundtolistrl   rm   sortr
   rn   r   r   r*   bbox_area_ranges
isinstanceboolro   Z	add_state)r?   rk   r   rl   rm   rn   ro   rp   Zallowed_box_formatsZallowed_iou_typesZmax_det_thrr]   	__class__r#   r'   rz   <  s@    
  
zMeanAveragePrecision.__init__)predstargetr   c                 C   s   t ||| jd |D ]:}| |}| j| | j|d  | j|d  q|D ]*}| |}| j| | j|d  qTdS )z*Update state with predictions and targets.r   labelsscoresN)	r   r   _get_safe_item_valuesre   appendrg   rf   rh   ri   )r?   r   r   itemre   rh   r#   r#   r'   updatem  s    

zMeanAveragePrecision.update)r   c                 C   s\   | j D ]P}t| |}g }t|trJ|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)r?   r:   Zcurrent_valZcurrent_to_cpuZcur_vr#   r#   r'   _move_list_states_to_cpu}  s    




z-MeanAveragePrecision._move_list_states_to_cpu)r   r   c                 C   s   | j dkr6t|d }| dkr2t|| jdd}|S | j dkrg }|d   D ].}tt	
|}|t|d |d	 f qTt|S td
| j  dd S )Nr   boxesr   rj   )Zin_fmtZout_fmtr   masksr!   r"   r+   r,   )r   r   numelr   rk   r   numpyr1   encodenpZasfortranarrayr   r   r3   )r?   r   r   r   r&   Zrler#   r#   r'   r     s    

z*MeanAveragePrecision._get_safe_item_valuesc                 C   s:   t | jdkst | jdkr6t| j| j   S g S )zIReturn a list of unique classes found in ground truth and detection data.r   )r-   rg   ri   r.   catuniquer~   )r?   r#   r#   r'   _get_classes  s    z!MeanAveragePrecision._get_classes)idxclass_idmax_detr   c           	         s  | j | | j|  | j| |k d}| j| |k d}t|dks\t|dkrdtg S fdd|D  fdd|D  tdkst dkrt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                    s   g | ]} | qS r#   r#   r$   r6   r#   r'   r(     r)   z5MeanAveragePrecision._compute_iou.<locals>.<listcomp>c                    s   g | ]} | qS r#   r#   r$   r5   r#   r'   r(     r)   TZ
descendingc                    s   g | ]} | qS r#   r#   r$   r   r#   r'   r(     r)   N)rh   re   ri   nonzerosqueezerg   r-   r   rf   r.   argsortr8   r   r   device)	r?   r   r   r   gt_label_maskdet_label_maskr   scores_filteredindsr#   r5   r6   r'   _compute_iou  s"    


z!MeanAveragePrecision._compute_iou)r6   r   
area_rangenb_iou_thrsr   c                    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                    s   g | ]} | qS r#   r#   r$   r   r#   r'   r(     r)   zEMeanAveragePrecision.__evaluate_image_gt_no_preds.<locals>.<listcomp>r   r   r    dtyper   	dtMatchesZ	gtMatchesdtScoresgtIgnoredtIgnore)r-   r4   r   r   r   r.   r   uint8r   zerosfloat32)r?   r6   r   r   r   nb_gtareasignore_area	gt_ignorer]   nb_det
det_ignorer#   r   r'   Z__evaluate_image_gt_no_preds  s    z1MeanAveragePrecision.__evaluate_image_gt_no_preds)r5   r   r   r   r   r   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rx 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                    s   g | ]} | qS r#   r#   r$   r   r#   r'   r(     r)   zEMeanAveragePrecision.__evaluate_image_preds_no_gt.<locals>.<listcomp>Tr   c                    s   g | ]} | qS r#   r#   r$   r   r#   r'   r(     r)   Nr   r    r   )r.   r   r   r   rf   r   r-   r4   r   r   reshaperepeat_interleave)r?   r5   r   r   r   r   r   r   r   r   r   scores_sorteddtindr   	det_areasdet_ignore_areaarr   r#   r   r'   Z__evaluate_image_preds_no_gt  s(    



z1MeanAveragePrecision.__evaluate_image_preds_no_gt)r   r   r   r   iousr   c                    s  | j | | j|  | j| |k d}| j| |k d}t|dkr`t|dkr`dS t| j}t|dkrt|dkr| |||S t|dkrt|dkr| 	 |||||S fdd|D  fdd|D  tdkrt dkrd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 ]h\}}t D ]T\}}t||||||}|dkrԐq|| |||f< d|||f< d|||f< qqt | 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                    s   g | ]} | qS r#   r#   r$   r   r#   r'   r(   $  r)   z8MeanAveragePrecision._evaluate_image.<locals>.<listcomp>c                    s   g | ]} | qS r#   r#   r$   r   r#   r'   r(   %  r)   r   c                    s   g | ]} | qS r#   r#   r$   r   r#   r'   r(   7  r)   Tr   c                    s   g | ]} | qS r#   r#   r$   r   r#   r'   r(   ;  r)   r   r   )rh   re   ri   r   r   rg   r-   rl   1_MeanAveragePrecision__evaluate_image_gt_no_preds1_MeanAveragePrecision__evaluate_image_preds_no_gtr   dictr4   r   r   r   r.   
logical_orr   r   r   rf   r   r   	enumerater   _find_best_gt_matchr   logical_andr   )r?   r   r   r   r   r   r   r   r   r   r   Zignore_area_sortedZgtindr   r   r   r   r   r   
gt_matchesdet_matchesr   r   idx_ioutidx_detr]   mr   r   r   r#   r   r'   _evaluate_image  sv    



:






z$MeanAveragePrecision._evaluate_image)thrr   r   r   r   r   r   c           
      C   s>   || }||B }|| |  }|   }	||	 | kr:|	S dS )a*  Return id of best ground truth match with current detection.

        Args:
            thr:
                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   Zpreviously_matchedZremove_maskZgt_iousZ	match_idxr#   r#   r'   r   c  s    z(MeanAveragePrecision._find_best_gt_matchrt   rs   )resultsavg_preciou_thresholdr   max_detsr   c           
         s   fddt | j D }fddt | jD }|r|d }|durp| j|}	||	dddd||f }q|dddddd||f }nP|d }|dur| j|}	||	dddd||f }n|dddd||f }t||dk dkrt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                    s   g | ]\}}| kr|qS r#   r#   r%   r&   k)r   r#   r'   r(     r)   z3MeanAveragePrecision._summarize.<locals>.<listcomp>c                    s   g | ]\}}| kr|qS r#   r#   r   r   r#   r'   r(     r)   	precisionNrecallr   r         )
r   r   keysrn   rl   indexr-   r.   r0   mean)
r?   r   r   r   r   r   Z	area_indsZ	mdet_indsprecr   r#   r   r   r'   
_summarize  s     zMeanAveragePrecision._summarize)	class_idsr   c                    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 ]X\}}tjD ]D\}}tjD ]0\}}tj|
|	|||||||||d\}
}	}qqq|	|
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_detectionsr?   r#   r'   
<dictcomp>  s   z3MeanAveragePrecision._calculate.<locals>.<dictcomp>c                    s2   g | ]*} D ] }D ]} |||qqqS r#   )r   )r%   r   r2   Zimg_id)area_rangesimg_idsr   r   r?   r#   r'   r(     s   z3MeanAveragePrecision._calculate.<locals>.<listcomp>)idx_clsidx_bbox_areaidx_max_det_thrs	eval_imgsrm   r   nb_imgsnb_bbox_areas)ranger-   rh   rn   r   valuesrl   rm   r.   onesr0   r   r   8_MeanAveragePrecision__calculate_recall_precision_scores)r?   r   r   r   nb_rec_thrsZ
nb_classesr   Znb_max_det_thrsr   r   r   r   Zrec_thresholds_tensorr   r]   r   r   r   r#   )r   r   r   r   r   r?   r'   
_calculate  sH    





zMeanAveragePrecision._calculate)
precisionsrecallsr   c                 C   s4  ||d}t  }| jd }| j|d|d|_d| jv rL| j|dd|d|_ntdg|_d| jv rz| 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| < q| 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   rq   )r   r   g      ?ru   r   rv   rw   Fmar_)rI   rn   r   rJ   rl   rK   r.   r0   rL   rM   rN   rO   rS   rW   rX   rY   )r?   r   r   r   Zmap_metricsZlast_max_det_thrZmar_metricsr   r#   r#   r'   _summarize_results  s(    





z'MeanAveragePrecision._summarize_results)r   r   r   r   r   r   r   rm   r   r   r   r   c           $         s  t |}||
 |	 ||	  fddt|	D }dd |D }|sR| ||fS tfdd|D }|jr|jtju rt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 ]b\}\}}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sZtjt|dd  |d d  |!fddd}"||"7 }qtj||	|jdd}| |kr| 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(     r)   c                    s   g | ]}|d  d  qS )r   Nr#   r  r   r#   r'   r(   "  r)   Tr   c                    s$   g | ]}|d  ddd f qS )r   Nr#   r  r  r#   r'   r(   ,  r)   r    )Zaxisc                    s$   g | ]}|d  ddd f qS )r   Nr#   r  r  r#   r'   r(   -  r)   c                 S   s   g | ]}|d  qS )r   r#   r  r#   r#   r'   r(   .  r)   Fr   )dimr   r   )r    )r   )min)right)r-   r   r.   r   Zis_cudar   r   r   r   r   Zcount_nonzeror   Zlogical_notr   r*   r   zipZfinfofloat64Zepsr   r   r   rt   clampZsearchsortedmaxr   )$r   r   r   r   r   r   r   rm   r   r   r   r   Zimg_eval_cls_bboxZ
det_scoresr   r   Zdet_scores_sortedr   r   r   ZnpigZtpsZfpsZtp_sumZfp_sumr   tpfpZndrcprr   ZscoreZ	diff_zerodiffZnum_indsr#   )r   r   r   r   r'   Z#__calculate_recall_precision_scores  sR    
((

.z8MeanAveragePrecision.__calculate_recall_precision_scoresc                 C   s6  |   }| |\}}| ||\}}tdg}tdg}| jrg }g }	t|D ]t\}
}|dddd|
f jdd}|dd|
f jdd}| ||\}}||j	 |	|d| j
d    qTt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   Z
_per_class)r   r   r   r.   r0   ro   r   Z	unsqueezer   rJ   rn   r*   rZ   r   r[   intrP   )r?   rP   r   r   Zmap_valZmar_valZmap_per_class_valuesZmar_max_dets_per_class_valuesZmap_per_class_listZmar_max_dets_per_class_listZ	class_idxr]   Zcls_precisionsZcls_recallsZcls_mapZcls_marZmetricsr#   r#   r'   computeQ  s.    

zMeanAveragePrecision.compute)fnr   c                    s,   | j dkrt j|dd}n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   )re   rh   )Zexclude_state)r   ry   _apply)r?   r  thisr   r#   r'   r  p  s    
zMeanAveragePrecision._apply)dist_sync_fnprocess_groupr   c                    s>   t  j||d | jdkr:| | j|| _| | j|| _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.

        )r  r  r   N)ry   
_sync_distr   _gather_tuple_listre   rh   )r?   r  r  r   r#   r'   r  }  s    
zMeanAveragePrecision._sync_dist)list_to_gatherr  r   c                    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   s   g | ]}d qS r   r#   r\   r#   r#   r'   r(     r)   z;MeanAveragePrecision._gather_tuple_list.<locals>.<listcomp>c                    s&   g | ]}t D ]} | | qqS r#   )r   )r%   r   ZrankZlist_gatheredZ
world_sizer#   r'   r(     r)   r   )distZget_world_sizeZbarrierr   Zall_gather_objectr-   )r  r  r#   r  r'   r    s
    z'MeanAveragePrecision._gather_tuple_list)valaxr   c                 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)

        )Z_plot)r?   r  r  r#   r#   r'   plot  s    9r   )rj   r   NNNF)TNrt   rs   )NN)N)NN)5rD   rE   rF   rG   r^   r   __annotations__r_   r   r`   rb   r*   rd   r   r   rH   r  r   rz   r   r   r   r	   r   r   r   r   r   r   r   r   staticmethodr   r   rI   rS   r   r   listr   r  r   r.   nnModuler  r  r  r   r   r   r   __classcell__r#   r#   r   r'   r      s   
       


1* )

"d     -:#E " ()r   )r   )6loggingtypingr   r   r   r   r   r   r   r	   r   r   r.   Ztorch.distributedZdistributedr  r
   r   Ztorchmetrics.detection.helpersr   r   Ztorchmetrics.metricr   Ztorchmetrics.utilities.datar   Ztorchmetrics.utilities.importsr   r   r   Ztorchmetrics.utilities.plotr   r   Z__doctest_skip__Ztorchvision.opsr   r   r   Zpycocotools.maskmaskr1   	getLoggerrD   logrH   r4   r8   r   r9   rI   rS   rZ   Zndarrayr7   r   r#   r#   r#   r'   <module>   sF   (
 2