o
    .wi1                  &   @   s  d dl Z d dlZd dlZd dlmZ d dlmZ d dlmZ d dl	m
Z
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 d dlmZ d d	lmZmZmZ es\es\d
dgZ		d?deeeef  deeeef  deed e ed df f de!ddf
ddZ"dedefddZ#	d@deed e ed df f de ed df fddZ$ded de e%e%ef fddZ&G d d! d!Z'd"e(ddfd#d$Z)	dAdeed eed df f d%ed&ee( d'e'd(eee
f d)e!de ee ee  f fd*d+Z*d,ee d-ee dee( fd.d/Z+d'e'd-ee d0ee d1ee d2ee d3ee d,ee d4ee d5ee d6ee deed eed df f d7ed8 d9ee, d:ee, d&ee( d;e!d<e!deeef f$d=d>Z-dS )B    N)Sequence)version)
ModuleType)AnyDictListLiteralOptionalTupleUnion)apply_to_collection)Tensor)rank_zero_warn)_FASTER_COCO_EVAL_AVAILABLE_PYCOCOTOOLS_AVAILABLE _PYCOCOTOOLS_GREATER_EQUAL_2_0_9CocoBackend.tm_to_cocoCocoBackend.coco_to_tmbboxFpredstargetsiou_typer   segm.ignore_scorereturnc                    s  t |tr|f}dddtfdd|D r td| dfdd	|D }t | ts5td
|  t |tsAtd| t| t|krWtdt|  dt| g |d|sadgng  D ]tfdd| D rytd dqdg |dD ]tfdd|D rtd dq|D ] t fdd| D std  dq|stdd | D stdtdd | D std|D ] t fdd|D std  dqtdd |D stdt|D ]3\}}|D ], |  	d |d 	d kr%td!  d"| d#|  	d  d$|d 	d  d%	qq|r,d&S t| D ]J\}}|D ]B |  	d |d 	d   krS|d 	d kswn td!  d'| d(|  	d  d)|d 	d  d*|d 	d  d%q6q0d&S )+z9Ensure the correct input format of `preds` and `targets`.boxesmasksr   c                 3       | ]}| vV  qd S N .0tpname_mapr    [/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/detection/helpers.py	<genexpr>4       z#_input_validator.<locals>.<genexpr>z	IOU type z is not supportedc                    s   g | ]} | qS r    r    r!   r$   r    r&   
<listcomp>6   s    z$_input_validator.<locals>.<listcomp>z:Expected argument `preds` to be of type Sequence, but got z;Expected argument `target` to be of type Sequence, but got zHExpected argument `preds` and `target` to have the same length, but got z and labelsscoresc                 3       | ]} |vV  qd S r   r    r"   pkr    r&   r'   B   r(   z.Expected all dicts in `preds` to contain the `z` keyc                 3   r,   r   r    r-   r/   r    r&   r'   F   r(   z/Expected all dicts in `target` to contain the `c                 3       | ]
}t |  tV  qd S r   
isinstancer   r"   predivnr    r&   r'   J       zExpected all z  in `preds` to be of type Tensorc                 s       | ]
}t |d  tV  qdS )r+   Nr2   r4   r    r    r&   r'   L   r8   z3Expected all scores in `preds` to be of type Tensorc                 s   r9   r*   Nr2   r4   r    r    r&   r'   N   r8   z3Expected all labels in `preds` to be of type Tensorc                 3   r1   r   r2   r"   targetr6   r    r&   r'   Q   r8   z! in `target` to be of type Tensorc                 s   r9   r:   r2   r;   r    r    r&   r'   S   r8   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 )Nz', labels and scores of sample z2 in predictions have a different length (expected z labels and scores, got z labels and )
r3   strany	Exceptionr   
ValueErrorlenall	enumeratesize)r   r   r   r   item_val_nameiitemr    )r7   r0   r%   r&   _input_validator)   s   



8rI   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      )numelndim	unsqueeze)r   r    r    r&   _fix_empty_tensorsi   s   
rN   c                    sB   d t | tr
| f} t fdd| D rtd  d|  | S )z+Validate that iou type argument is correct.)r   r   c                 3   r   r   r    r!   allowed_iou_typesr    r&   r'   w   r(   z)_validate_iou_type_arg.<locals>.<genexpr>z*Expected argument `iou_type` to be one of z or a tuple of, but got )r3   r>   r?   rA   )r   r    rO   r&   _validate_iou_type_argp   s   
rQ   backendpycocotoolsfaster_coco_evalc                 C   s|   | dkr!t s
tdddlm} ddlm} ddlm} |||fS ts'tdddl	m} ddl	m
} dd	lm} |||fS )
z-Load the backend tools for the given backend.rT   zBackend `pycocotools` in metric `MeanAveragePrecision`  metric requires that `pycocotools` is installed. Please install with `pip install pycocotools` or `pip install torchmetrics[detection]`r   N)COCO)COCOevalzBackend `faster_coco_eval` in metric `MeanAveragePrecision`  metric requires that `faster-coco-eval` is installed. Please install with `pip install faster-coco-eval`.)COCOeval_faster)mask)r   ModuleNotFoundErrorpycocotools.maskrY   pycocotools.cocorV   pycocotools.cocoevalrW   r   rU   rX   faster_coco_eval.core)rR   
mask_utilsrV   rW   r    r    r&   _load_coco_backend_tools~   s"   

r`   c                   @   s  e Zd ZdZded ddfddZedefdd	Zedefd
dZ	edefddZ
		d7dee dee dee dee dee dee dee dee dee deed eed df f ded deeef fddZd ee d!ed"ee deeef fd#d$Ze		%d8d&ed'edeed eed df f ded deeeeef  eeeef  f f
d(d)Z	*		d9dee dee dee dee dee dee dee dee dee d+edeed eed df f ded ddfd,d-Z							d:d.ee d/ee d0eee  d1eee  d2eee  d3eee  d4eee  deed eed df f ded defd5d6ZdS );CocoBackendaI  Backend implementation for COCO-style Mean Average Precision (mAP) calculation.

    This class provides the core functionality for evaluating object detection and instance
    segmentation predictions using the Common Objects in Context (COCO) evaluation protocol.
    It supports both the standard 'pycocotools' and optimized 'faster_coco_eval' backends.

    It's used for calculation of mAP in MeanAveragePrecision class. It's a backend that abstracts
    away the mAP calculation with coco package

    Args:
        backend (str): Either 'pycocotools' or 'faster_coco_eval'

    rR   rS   r   Nc                 C   s    |dvrt d| || _d S )NrS   zUExpected argument `backend` to be one of ('pycocotools', 'faster_coco_eval') but got )rA   rR   )selfrR   r    r    r&   __init__   s
   
zCocoBackend.__init__c                 C   s   t | j\}}}|S )z.Returns the coco module for the given backend.r`   rR   )rb   coco_r    r    r&   re         zCocoBackend.cococ                 C   s   t | j\}}}|S )z3Returns the coco eval module for the given backend.rd   )rb   rf   cocoevalr    r    r&   rh      rg   zCocoBackend.cocoevalc                 C   s   t | j\}}}|S )z4Returns the mask utils object for the given backend.rd   )rb   rf   r_   r    r    r&   r_      rg   zCocoBackend.mask_utilsr   microgroundtruth_labelsgroundtruth_boxgroundtruth_maskgroundtruth_crowdsgroundtruth_areadetection_labelsdetection_boxdetection_maskdetection_scoresr   r   .averagemacrorj   c              
   C   s2  |dkrt |tdd }t |tdd }|  |  }}t|dks)t|dkr6t||    ng }| j	|t|dkrC|ndt|dkrL|nd|||
||d|_
| j	|t|dkra|ndt|dkrj|nd|	|
||d|_
tt  |  |  W d   ||fS 1 sw   Y  ||fS )	z=Returns the coco datasets for the target and the predictions.rj   c                 S   
   t | S r   torch
zeros_likexr    r    r&   <lambda>      
 z0CocoBackend._get_coco_datasets.<locals>.<lambda>c                 S   rw   r   rx   r{   r    r    r&   r}      r~   r   N)r*   r   r   crowdsarear   
all_labelsrt   )r*   r   r   r+   r   r   rt   )r   r   re   rB   ry   catuniquecputolist_get_coco_formatdataset
contextlibredirect_stdoutioStringIOcreateIndex)rb   rk   rl   rm   rn   ro   rp   rq   rr   rs   r   rt   coco_target
coco_predsr   r    r    r&   _get_coco_datasets   sD   



zCocoBackend._get_coco_datasetsstatsprefixmax_detection_thresholdsc                 C   sp  |}| dt j|d gt jd| dt j|d gt jd| dt j|d gt jd| dt j|d	 gt jd| d
t j|d gt jd| dt j|d gt jd| d|d  t j|d gt jd| d|d  t j|d gt jd| d|d  t j|d gt jd| dt j|d gt jd| dt j|d gt jd| dt j|d gt jdiS )z;Converts the output of COCOeval.stats to a dict of tensors.mapr   dtypemap_50rJ   map_75   	map_small   
map_medium   	map_large   mar_         	mar_small	   
mar_medium
   	mar_large   ry   tensorfloat32)rb   r   r   r   mdtr    r    r&   _coco_stats_to_tensor_dict   s   $$$z&CocoBackend._coco_stats_to_tensor_dictrT   r   r   c                 C   s  t |}t|\}}}tt  ||}|| }W d   n1 s&w   Y  |jd }|jd }	i }
|D ]t}|d |
vrcg g g d|
|d < d|v rWg |
|d  d< d|v rcg |
|d  d< d|v rt|
|d  d |d  d|v r|
|d  d |	| |
|d  d	 |d
  |
|d  d |d  |
|d  d |d  q9i }|	D ]f}|d |vrg g d||d < d|v rg ||d  d< d|v rg ||d  d< d|v r||d  d |d  d|v r||d  d |	| ||d  d |d  ||d  d	 |d
  q|
D ]%}||vr?g g d||< d|v r4g || d< d|v r?g || d< qg g }}|
D ]}t
j|| d t
jdt
j|| d	 t
jdd}d|v ryt
jt|| d t
jd|d< d|v rt
jt|| d t
jd|d< || t
j|
| d	 t
jdt
j|
| d t
jdt
j|
| d t
jdd}d|v rt
j|
| d t
jd|d< d|v rt
jt|
| d t
jd|d< || qH||fS )a  Utility function for converting .json coco format files to the input format of the mAP metric.

        The function accepts a file for the predictions and a file for the target in coco format and converts them to
        a list of dictionaries containing the boxes, labels and scores in the input format of mAP metric.

        Args:
            coco_preds: Path to the json file containing the predictions in coco format
            coco_target: Path to the json file containing the targets in coco format
            iou_type: Type of input, either `bbox` for bounding boxes or `segm` for segmentation masks
            backend: Backend to use for the conversion. Either `pycocotools` or `faster_coco_eval`.

        Returns:
            A tuple containing the predictions and targets in the input format of mAP metric. Each element of the
            tuple is a list of dictionaries containing the boxes, labels and scores.

        Example:
            >>> # File formats are defined at https://cocodataset.org/#format-data
            >>> # Example files can be found at
            >>> # https://github.com/cocodataset/cocoapi/tree/master/results
            >>> from torchmetrics.detection import MeanAveragePrecision
            >>> preds, target = MeanAveragePrecision().coco_to_tm(
            ...   "instances_val2014_fakebbox100_results.json",
            ...   "val2014_fake_eval_res.txt.json"
            ...   iou_type="bbox"
            ... )  # doctest: +SKIP

        Nannotationsimage_id)r*   iscrowdr   r   r   r   r   r*   category_idr   r   )r+   r*   r+   scorer   )rQ   r`   r   r   r   r   loadResr   append	annToMaskry   r   r   int32nparrayuint8)r   r   r   rR   re   rf   gtdt
gt_dataset
dt_datasetr<   tr   r.   r0   batched_predsbatched_targetkeybpbtr    r    r&   
coco_to_tm
  s   "






"
"


"r   tm_map_inputnamec              
   C   s  t |dkst |dkrt||    ng }| j|t |dkr&|ndt |dkr/|nd|||||d}| j|t |dkrC|ndt |dkrL|nd|	|||d}d|v rt|d tdd d	|d< t|d t	j
t	jfd
d d	|d< t|tdd d	}t|t	j
t	jfdd d	}tj|d dd}tj|dd}t|
 dd}|| W d   n1 sw   Y  t|
 dd}|| W d   dS 1 sw   Y  dS )a  Utility function for converting the input for mAP metric to coco format and saving it to a json file.

        This function should be used after calling `.update(...)` or `.forward(...)` on all data that should be written
        to the file, as the input is then internally cached. The function then converts to information to coco format
        and writes it to json files.

        Args:
            groundtruth_labels: List of tensors containing the ground truth labels
            groundtruth_box: List of tensors containing the ground truth bounding boxes
            groundtruth_mask: List of tensors containing the ground truth segmentation masks
            groundtruth_crowds: List of tensors indicating whether ground truth annotations are crowd annotations
            groundtruth_area: List of tensors containing the area of ground truth annotations
            detection_labels: List of tensors containing the predicted labels
            detection_box: List of tensors containing the predicted bounding boxes
            detection_mask: List of tensors containing the predicted segmentation masks
            detection_scores: List of tensors containing the confidence scores for predictions
            name: Name of the output file, which will be appended with "_preds.json" and "_target.json"
            iou_type: Type of IoU calculation to use. Can be either "bbox" for bounding box or "segm" for segmentation
            average: Type of averaging to use. Can be either "macro" or "micro"

        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(iou_type="bbox")
            >>> metric.update(preds, target)
            >>> metric.tm_to_coco("tm_map_input")

        r   N)r*   r   r   r   r   r   r   rt   )r*   r   r   r+   r   r   rt   r   r   c                 S   
   |  dS Nzutf-8decoder{   r    r    r&   r}     r~   z(CocoBackend.tm_to_coco.<locals>.<lambda>)r   functionc                 S      t | S r   intr{   r    r    r&   r}         c                 S   r   r   r   r{   r    r    r&   r}     r~   c                 S   r   r   r   r{   r    r    r&   r}     r   r   )indentz_preds.jsonwz_target.json)rB   ry   r   r   r   r   r   r   bytesr   uint32uint64jsondumpsopenwrite)rb   rk   rl   rm   rn   ro   rp   rq   rr   rs   r   r   rt   r   target_datasetpreds_dataset
preds_jsontarget_jsonfr    r    r&   
tm_to_cocoz  sX   :
	


"r   r*   r   r   r   r+   r   r   c
              
   C   s  g }
g }d}t |D ]Y\}}|dur|| }|  }|dur0|| }t|dkr0|du r0q
|  }|
d|i d|v r`t|dkr`|d d d |d d d |
d d< |
d d< t |D ]\}}|durp|| }|durt|dkr|| }|d |d d	}d
|v rt|dkrtd| d| dt| dt|tstd| d| dt| dd}d}|dur|| |   dkr|| |   }n&d|v r| j	
|n|d |d  }t|dkr|d |d  }| j	
|}|||||dur|| |   ndd}|dur||d< ||d< |dur(||d
< |dur1||d< |durZ|| |   }t|tsVtd| d| dt| d||d< || |d7 }qdq
|	dkrqdd |D ndddg}|
||d }trd!d"td# i|d$< |S )%zTransforms and returns all cached targets or predictions in COCO format.

        Format is defined at
        https://cocodataset.org/#format-data

        rJ   Nr   idr   heightwidth)rE   countsr   r   zInvalid input box of sample z
, element z (expected 4 values, got r=   zInvalid input class of sample z+ (expected value of type integer, got type r   r   )r   r   r   r   r   	area_bbox	area_segmsegmentationzInvalid input score of sample z) (expected value of type float, got type r   rj   c                 S   s   g | ]	}|t |d qS )r   r   )r>   )r"   rG   r    r    r&   r)   =  s    z0CocoBackend._get_coco_format.<locals>.<listcomp>0r   )imagesr   
categoriesdescriptionz:Dummy info generated by tm_to_coco to support pycocotools rT   info)rD   r   r   rB   r   rA   r3   r   typer_   r   floatr   r   )rb   r*   r   r   r   r+   r   r   r   rt   r   r   annotation_idr   image_labelsimage_boxesimage_masksr0   image_label	image_box
image_maskarea_stat_boxarea_stat_mask	area_stat
annotationr   classesresultr    r    r&   r     s   2
 $ 





$7zCocoBackend._get_coco_format)ri   rj   )ri   rT   )r   ri   rj   )NNNNNri   rj   )__name__
__module____qualname____doc__r   rc   propertyobjectre   rh   r_   r   r   r   tupler   listr   r>   r   dictr   staticmethodr   r   r	   r   r    r    r    r&   ra      s    	


6

"z	

l




	
ra   limitc                 C   s   t d|  dt d S )NzEncountered more than aY   detections in a single image. This means that certain detections with the lowest scores will be ignored, that may have an undesirable impact on performance. Please consider adjusting the `max_detection_threshold` to suit your use case. To disable this warning, set attribute class `warn_on_many_detections=False`, after initializing the metric.)r   UserWarning)r  r    r    r&   _warning_on_too_many_detectionsJ  s   
r  
box_formatr   coco_backendrH   warnc                    s   ddl m} ddgd| v r%t|d }| dkr!|||dd}|d< d| v rRg }|d	   D ]}	|jt	|	}
|
t|
d
 |
d f q3t|d< dtdtf fdd}|rn|dsh|drnt d  S )a.  Convert and return the boxes or masks from the item depending on the iou_type.

    Args:
        iou_type:
            Type of input to process. Supported types are:
                - "bbox": Process bounding boxes
                - "segm": Process segmentation masks
        box_format:
            Input format of given boxes. Supported formats are:
                - 'xyxy': boxes are represented via corners, x1, y1 being top left and x2, y2 being bottom right.
                - 'xywh': boxes are represented via corner, width and height, x1, y2 being top left, w, h being
                  width and height.
                - 'cxcywh': boxes are represented via centre, width and height, cx, cy being center of box, w, h being
                  width and height.
        max_detection_thresholds:
            List of thresholds on maximum detections per image. Used to determine if warnings should be raised
            when the number of detections exceeds these thresholds.
        coco_backend:
            The COCO evaluation backend class type to use for processing the items.
        item:
            Input dictionary containing the boxes or masks to be processed, along with other detection information.
        warn:
            Whether to warn if the number of boxes or masks exceeds the max_detection_thresholds.
            Default is False.

    Returns:
        A tuple containing processed boxes or masks depending on the iou_type. The first element is the
        tensor representation, and the second element contains additional metadata if applicable.

    r   )box_convertNr   r   xywh)in_fmtout_fmtr   r   rE   r   rJ   idxr   c                    s$   |  }|d u r
dS t | d kS )NFr   )rB   )r  valr   outputr    r&   _valid_output_len  s   z0_get_safe_item_values.<locals>._valid_output_lenr   )torchvision.opsr  rN   rK   r   numpyr_   encoder   asfortranarrayr   r  r   boolr  )r   r	  r   r
  rH   r  r  r   r   rG   rler  r    r  r&   _get_safe_item_valuesT  s"   &r  rp   rk   c                 C   s6   t | dkst |dkrt| |    S g S )Nr   )rB   ry   r   r   r   r   rp   rk   r    r    r&   _get_classes  s   r  rl   rm   rn   ro   rq   rr   rs   rt   ru   iou_thresholdsrec_thresholdsclass_metricsextended_summaryc                  C   s  | j |||||||||	|
|d\}}i }tt  |
D ]}t|
dkr*dn| d}t|
dkrF|jd D ]}|d|  |d< q:t|jdksTt|jdkrc|| j	d	d
g ||d q| j
|||d}tj|tjd|j_tj|tjd|j_||j_|  |  |  |j}|| j	|||d i }|r| dt|jtjdd | dt|jd | dt|jd | dt|jd i}|| |rl| j |||||||||	|
dd\}}| j
|||d}tj|tjd|j_tj|tjd|j_||j_g }g }t||dD ]E}|g|j_tt  |  |  |  |j}W d    n	1 s>w   Y  |t|d g |t|d g qtj|tjd}tj|tjd}ntjdgtjd}tjdgtjd}t|
dkrdn| d}|| d|| d|d  d|i qW d    n	1 sw   Y  |dtjt||dtj di |S )N)rt   rJ    rf   r   area_r   r      g      )r   r   )iouTyper   iousc                 S   s   t j| t jdS )Nr   r   r{   r    r    r&   r}     s    z*_calculate_map_with_coco.<locals>.<lambda>	precisionrecallr+   rv   r  r   r   map_per_classr   
_per_classr   )!r   r   r   r   r   rB   r   imgsupdater   rh   r   r   float64paramsiouThrsrecThrsmaxDetsevaluate
accumulate	summarizer   r   r&  ndarrayry   r   evalr  catIdsr   r   r   ) r
  rk   rl   rm   rn   ro   rp   rq   rr   rs   r   rt   r  r  r   r   r!  r   r   result_dicti_typer   anno	coco_evalr   summarymap_per_class_listmar_per_class_listclass_idclass_statsmap_per_class_valuesmar_per_class_valuesr    r    r&   _calculate_map_with_coco  s   







\rC  )r   Fri   )F).r   r   r   collections.abcr   importlib.metadatar   typesr   typingr   r   r   r   r	   r
   r   r  r   ry   lightning_utilitiesr   r   torchmetrics.utilitiesr   torchmetrics.utilities.importsr   r   r   __doctest_skip__r  r>   r  r  rI   rN   rQ   r  r`   ra   r   r  r  r  r   rC  r    r    r    r&   <module>   s   $	
@
    5

"@	

