o
    yi                  	   @   s  d dl Z d dl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mZ d dlmZ d dlmZmZ erAd dlmZmZmZ n	d Z ZZdgZerSd dlmZ ndZdgZe eZd$d	ee d
edefddZ	d$dee dee d
e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'	d$deeeef  deeeef  d
eddfddZ(d edefd!d"Z)G d#d deZ*dS )%    N)AnyDictListOptionalSequenceTupleUnion)	IntTensorTensor)Metric)_PYCOCOTOOLS_AVAILABLE_TORCHVISION_GREATER_EQUAL_0_8)box_areabox_convertbox_iouMeanAveragePrecisionbboxinputiou_typereturnc                 C   sj   t | dkr
tg S |dkrtt| S |dkr-dd | D } t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   r   segmc                 S      g | ]}|d  |d dqS r      )sizecounts .0ir   r   R/home/ubuntu/.local/lib/python3.10/site-packages/torchmetrics/detection/mean_ap.py
<listcomp>5       z compute_area.<locals>.<listcomp>float	IOU type  is not supported)
lenr
   r   torchstacktensor
mask_utilsareaastype	Exception)r   r   r+   r   r   r    compute_area(   s   r.   detgtc                 C   s@   |dkrt t| t|S |dkrt| |S td| d)zMCompute IOU between detections and ground-truth using the specified iou_type.r   r   r$   r%   )r   r'   r(   	_segm_iour-   )r/   r0   r   r   r   r    compute_iou=   s
   
r2   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| NzNo such attribute: AttributeErrorselfr4   r   r   r    __getattr__O   s   zBaseMetricResults.__getattr__valueNc                 C   s   || |< d S Nr   )r9   r4   r;   r   r   r    __setattr__U   s   zBaseMetricResults.__setattr__c                 C   s   || v r| |= t d| r5   r6   r8   r   r   r    __delattr__X   s   zBaseMetricResults.__delattr__)	__name__
__module____qualname____doc__strr
   r:   r=   r>   r   r   r   r    r3   L   s
    r3   c                   @      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_largeNr?   r@   rA   rB   	__slots__r   r   r   r    rE   ^       rE   c                   @   rD   )MARMetricResultsz$Class to wrap the final mAR results.)mar_1mar_10mar_100	mar_small
mar_medium	mar_largeNrL   r   r   r   r    rO   d   rN   rO   c                   @   rD   )COCOMetricResultszMClass to wrap the final COCO metric results including various mAP/mAR values.)rF   rG   rH   rI   rJ   rK   rP   rQ   rR   rS   rT   rU   map_per_classmar_100_per_classNrL   r   r   r   r    rV   j   rN   rV   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. 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   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   s   g | ]}d qS )Fr   )r   _r   r   r    r!      s    )r'   r)   r*   iou)r/   r0   det_coco_formatgt_coco_formatr   r   r    r1      s   r1   predstargetsc                    sF  t | ts	tdt |tstdt| t|krtd|dkr$dnd  ddfD ]tfd	d
| D r@td dq+ dfD ]tfdd
|D rZtd dqEt fdd
| D rntd  dtdd
 | D r{tdtdd
 | D rtdt fdd
|D rtd  dtdd
 |D rtdt|D ]-\}}|  d|d dkrtd  d| d|  d d|d d d	qt| D ]B\}}|  d|d d  kr|d dks n td  d | d!|  d d"|d d d#|d d dqd$S )%z8Ensure the correct input format of `preds` and `targets`z0Expected argument `preds` to be of type Sequencez1Expected argument `target` to be of type Sequencez>Expected argument `preds` and `target` to have the same lengthr   boxesmasksscoreslabelsc                 3       | ]} |vV  qd S r<   r   r   pkr   r    	<genexpr>       z#_input_validator.<locals>.<genexpr>z.Expected all dicts in `preds` to contain the `z` keyc                 3   rc   r<   r   rd   rf   r   r    rh      ri   z/Expected all dicts in `target` to contain the `c                 3        | ]}t |  tuV  qd S r<   typer
   r   prediou_attributer   r    rh          zExpected all z  in `preds` to be of type Tensorc                 s        | ]}t |d  tuV  qdS )ra   Nrk   rm   r   r   r    rh      rq   z3Expected all scores in `preds` to be of type Tensorc                 s   rr   rb   Nrk   rm   r   r   r    rh      rq   z3Expected all labels in `preds` to be of type Tensorc                 3   rj   r<   rk   r   targetro   r   r    rh      rq   z! in `target` to be of type Tensorc                 s   rr   rs   rk   rt   r   r   r    rh      rq   z4Expected all labels in `target` to be of type Tensorr   zInput z and labels of sample z. in targets have a different length (expected z labels, got )z, labels and scores of sample z2 in predictions have a different length (expected z labels and scores, got z labels and N)
isinstancer   
ValueErrorr&   any	enumerater   )r]   r^   r   r   itemr   )rp   rg   r    _input_validator   s`   

6r|   r_   c                 C   s$   |   dkr| jdkr| dS | S )zIEmpty tensors can cause problems in DDP mode, this methods corrects them.r   r   )numelndim	unsqueeze)r_   r   r   r    _fix_empty_tensors   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< e
e ed< e
e ed	< e
e ed
< e
e ed< e
e ed< 						dYdede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dZd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d+eeef d,edeeef f
d-d.Zd/ed$ed0ed&ed+eeef d,edeeef fd1d2Zd$ed%ed+eeef d&ed3edee fd4d5Zed6ed7ed8ed9ed3ed:edefd;d<Z			=	>d[d?ed@edAee d+edBedefdCdDZdEe
dee e!f fdFdGZ"dHedIedee e!f fdJdKZ#edLedMedNedOedPedQedRe$ded&edSedTedeeeef fdUdVZ%defdWdXZ&  Z'S )\r   az  Computes the `Mean-Average-Precision (mAP) and Mean-Average-Recall (mAR)`_ for object detection predictions.
    Optionally, the mAP and mAR values can be calculated per class.

    Predicted boxes and targets have to be in Pascal VOC format
    (xmin-top left, ymin-top left, xmax-bottom right, ymax-bottom right).
    See the :meth:`update` method for more information about the input format to this metric.

    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)

    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 <https://github.com/cocodataset/cocoapi/tree/master/PythonAPI/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 ``seqm`` 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:
        >>> import torch
        >>> from torchmetrics.detection.mean_ap import MeanAveragePrecision
        >>> preds = [
        ...   dict(
        ...     boxes=torch.tensor([[258.0, 41.0, 606.0, 285.0]]),
        ...     scores=torch.tensor([0.536]),
        ...     labels=torch.tensor([0]),
        ...   )
        ... ]
        >>> target = [
        ...   dict(
        ...     boxes=torch.tensor([[214.0, 41.0, 562.0, 285.0]]),
        ...     labels=torch.tensor([0]),
        ...   )
        ... ]
        >>> metric = MeanAveragePrecision()
        >>> metric.update(preds, target)
        >>> from pprint import pprint
        >>> pprint(metric.compute())
        {'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_differentiableNhigher_is_betterTfull_state_update
detectionsdetection_scoresdetection_labelsgroundtruthsgroundtruth_labelsxyxyr   
box_formatr   iou_thresholdsrec_thresholdsmax_detection_thresholdsclass_metricskwargsr   c                    s  t  jdi | tstdd}d}	||vr!td| d| || _|p2tddtdd	 	 | _
|pBtd
dtdd	 	 | _tt|pLg d\}
}|
	 | _||	vrdtd|	 d| |dkrntsnt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`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]`.)r   xywhcxcywh)r   r   z,Expected argument `box_format` to be one of z	 but got       ?gffffff?g!@r   g        g      ?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 booleanr   )defaultdist_reduce_fxr   r   r   r   r   )super__init__r   ModuleNotFoundErrorrx   r   r'   linspaceroundtolistr   r   sortr	   r   r   r   r#   bbox_area_rangesrw   boolr   	add_state)r9   r   r   r   r   r   r   r   allowed_box_formatsallowed_iou_typesmax_det_thrrY   	__class__r   r    r   f  s@   
  

zMeanAveragePrecision.__init__r]   ru   c                 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   rb   ra   N)	r|   r   _get_safe_item_valuesr   appendr   r   r   r   )r9   r]   ru   r{   r   r   r   r   r    update  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keysgetattrrw   r   tupletor   setattr)r9   r4   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   | j dkrt|d }| dkrt|| jdd}|S | j dkrFg }|d   D ]}tt	
|}|t|d |d	 f q*t|S td
| j  d)Nr   r_   r   r   )in_fmtout_fmtr   r`   r   r   r$   r%   )r   r   r}   r   r   r   numpyr*   encodenpasfortranarrayr   r   r-   )r9   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 )zJReturns a list of unique classes found in ground truth and detection data.r   )r&   r   r   r'   catuniquer   )r9   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  Computes the Intersection over Union (IoU) for ground truth and detection 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   r0   r   r    r!         z5MeanAveragePrecision._compute_iou.<locals>.<listcomp>c                    r   r   r   r   r/   r   r    r!     r   T
descendingc                    r   r   r   r   r   r   r    r!     r   N)r   r   r   nonzerosqueezer   r&   r
   r   r'   argsortr2   r   r   device)
r9   r   r   r   gt_label_maskdet_label_maskra   scores_filteredindsiousr   r/   r0   r    _compute_iou  s$   


z!MeanAveragePrecision._compute_iour0   r   
area_rangenb_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 )zSome GT 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&   r.   r   r   r   r'   r   uint8r   zerosfloat32)r9   r0   r   r   r   nb_gtareasignore_area	gt_ignorerY   nb_det
det_ignorer   r   r    __evaluate_image_gt_no_preds  s   z1MeanAveragePrecision.__evaluate_image_gt_no_predsr/   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 )zSome predictions but no GT.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   )r'   r   r   r   r   r   r&   r.   r   r   reshaperepeat_interleave)r9   r/   r   r   r   r   r   r   r   ra   r   scores_sorteddtindr   	det_areasdet_ignore_areaarr   r   r   r    __evaluate_image_preds_no_gt  s(   



z1MeanAveragePrecision.__evaluate_image_preds_no_gtr   c                    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!   U  r   z8MeanAveragePrecision._evaluate_image.<locals>.<listcomp>c                    r   r   r   r   r   r   r    r!   V  r   r   c                    r   r   r   r   r   r   r    r!   h  r   Tr   c                    r   r   r   r   r   r   r    r!   l  r   r   r   )r   r   r   r   r   r   r&   r   1_MeanAveragePrecision__evaluate_image_gt_no_preds1_MeanAveragePrecision__evaluate_image_preds_no_gtrw   dictr.   r   r   r   r'   
logical_orr   r   r   r   r   r}   rz   r   _find_best_gt_matchr   logical_andr   )r9   r   r   r   r   r   r   r   r   r   r   ignore_area_sortedgtindra   r   r   r   r   r   
gt_matchesdet_matchesr   r   idx_ioutidx_detrY   mr   r   r   r   r   r    _evaluate_image0  sx   





:

	




z$MeanAveragePrecision._evaluate_imagethrr   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   previously_matchedremove_maskgt_ious	match_idxr   r   r    r     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   rg   )r   r   r    r!         z3MeanAveragePrecision._summarize.<locals>.<listcomp>c                    r  r   r   r  r  r   r    r!     r  	precisionNrecallr   r         )
rz   r   r   r   r   indexr&   r'   r)   mean)r9   r	  r
  r  r   r  	area_inds	mdet_indsprecr  	mean_precr   r   r  r    
_summarize  s"     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_detectionsr9   r   r    
<dictcomp>  s    z3MeanAveragePrecision._calculate.<locals>.<dictcomp>c                    s2   g | ]} D ]}D ]} |||q
qqS r   )r  )r   r   r+   img_id)area_rangesimg_idsr   r  r9   r   r    r!     s    
z3MeanAveragePrecision._calculate.<locals>.<listcomp>)idx_clsidx_bbox_areaidx_max_det_thrs	eval_imgsr   r   nb_imgsnb_bbox_areas)ranger&   r   r   r   valuesr   r   r'   onesr)   rz   r   8_MeanAveragePrecision__calculate_recall_precision_scores)r9   r  r%  r   nb_rec_thrs
nb_classesr'  nb_max_det_thrsr&  r  r  ra   rec_thresholds_tensorr"  rY   r#  r$  r   r   )r   r  r!  r   r  r9   r    
_calculate  sL   





zMeanAveragePrecision._calculate
precisionsrecallsc                 C   s2  t ||d}t }| |d|_| j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| < qg| 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  Tr   r   )r  r  g      ?r   r  r   r   Fr  mar_)r   rE   r  rF   r   r   rG   r'   r)   rH   rI   rJ   rK   rO   rS   rT   rU   )r9   r1  r2  r	  map_metricslast_max_det_thrmar_metricsr   r   r   r    _summarize_results  s(   	



z'MeanAveragePrecision._summarize_resultsr  r  ra   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j|dtjd}tj|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s2tjt|dd  |d d  |!fddd}"||"7 }t|"dkrtj||	|jdd}| |krI| 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!   K  r  zLMeanAveragePrecision.__calculate_recall_precision_scores.<locals>.<listcomp>c                 S   s   g | ]}|d ur|qS r<   r   r   er   r   r    r!   L  s    c                    s   g | ]
}|d  d  qS )r   Nr   r:  r   r   r    r!   P  r  Tr   c                    $   g | ]}|d  ddd f qS )r   Nr   r:  r<  r   r    r!   Z     $ r   )axisc                    r=  )r   Nr   r:  r<  r   r    r!   [  r>  c                 S   s   g | ]}|d  qS )r   r   r:  r   r   r    r!   \  r   Fr   )r?  r   r   )r   )r   )min)right)r&   r(  r'   r   is_cudar   r   r   r   r   count_nonzeror   logical_notcumsumr#   rz   zipfinfofloat64epsr   r   r*  r   clampsearchsortedmaxr  )$r  r  ra   r"  r#  r$  r%  r   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ndrcprr  score	diff_zerodiffnum_indsr   )r%  r8  r9  r   r    #__calculate_recall_precision_scores9  sT   
((
.
z8MeanAveragePrecision.__calculate_recall_precision_scoresc                 C   s$  |   }| |\}}| ||\}}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	< |S )
zComputes metric.r  N   )dimr   r3  r   )r   
_per_class)r   r0  r7  r'   r)   r   rz   r   r   rF   r   r#   rV   r   rW   )r9   classesr1  r2  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_idxrY   cls_precisionscls_recallscls_mapcls_marmetricsr   r   r    compute  s,   

zMeanAveragePrecision.compute)r   r   NNNF)r   N)TNr   r   )(r?   r@   rA   rB   r   r   __annotations__r   r   r   r   r
   rC   r#   intr   r   r   r   r   r   r   r   r   r   r   r   r   r  staticmethodr   r  rE   rO   r0  r7  listr+  ro  __classcell__r   r   r   r    r      s  
  


	.1
"*





!

d
-9"	
F)r   )+loggingtypingr   r   r   r   r   r   r   r   r   r'   r	   r
   torchmetrics.metricr   torchmetrics.utilities.importsr   r   torchvision.opsr   r   r   __doctest_skip__pycocotools.maskmaskr*   	getLoggerr?   logrC   r.   r2   r   r3   rE   rO   rV   ndarrayr1   r|   r   r   r   r   r   r    <module>   sX   $

6
.