o
    WhG                     @   s   d dl mZ d dlmZ d dlZd dlZd dlm  m	Z
 d dlmZ d dlmZmZmZ d dlmZ d dlmZmZmZ d dlmZmZ G d	d
 d
eZdS )    )
ThreadPool)PathN)DetectionValidator)LOGGERNUM_THREADSops)check_requirements)SegmentMetricsbox_ioumask_iou)output_to_targetplot_imagesc                       s   e Zd ZdZd" fdd	Z fddZ fddZd	d
 Z fddZ fddZ	 fddZ
dd Zdd Zd#ddZdd Zdd Zdd Zdd Zd d! Z  ZS )$SegmentationValidatora  
    A class extending the DetectionValidator class for validation based on a segmentation model.

    This validator handles the evaluation of segmentation models, processing both bounding box and mask predictions
    to compute metrics such as mAP for both detection and segmentation tasks.

    Attributes:
        plot_masks (list): List to store masks for plotting.
        process (callable): Function to process masks based on save_json and save_txt flags.
        args (namespace): Arguments for the validator.
        metrics (SegmentMetrics): Metrics calculator for segmentation tasks.
        stats (dict): Dictionary to store statistics during validation.

    Examples:
        >>> from ultralytics.models.yolo.segment import SegmentationValidator
        >>> args = dict(model="yolo11n-seg.pt", data="coco8-seg.yaml")
        >>> validator = SegmentationValidator(args=args)
        >>> validator()
    Nc                    s:   t  ||||| d| _d| _d| j_t| jd| _dS )a  
        Initialize SegmentationValidator and set task to 'segment', metrics to SegmentMetrics.

        Args:
            dataloader (torch.utils.data.DataLoader, optional): Dataloader to use for validation.
            save_dir (Path, optional): Directory to save results.
            pbar (Any, optional): Progress bar for displaying progress.
            args (namespace, optional): Arguments for the validator.
            _callbacks (list, optional): List of callback functions.
        Nsegment)save_dir)	super__init__
plot_masksprocessargstaskr	   r   metrics)self
dataloaderr   pbarr   
_callbacks	__class__ W/var/www/vscode/kcb/lib/python3.10/site-packages/ultralytics/models/yolo/segment/val.pyr   &   s
   zSegmentationValidator.__init__c                    s(   t  |}|d | j |d< |S )zDPreprocess batch by converting masks to float and sending to device.masks)r   
preprocesstodevicefloat)r   batchr   r   r   r!   7   s   z SegmentationValidator.preprocessc                    sZ   t  | g | _| jjrtd | jjs| jjrtjntj	| _
tg g g g g g d| _dS )z
        Initialize metrics and select mask processing function based on save_json flag.

        Args:
            model (torch.nn.Module): Model to validate.
        pycocotools>=2.0.6)tp_mtpconfpred_cls
target_cls
target_imgN)r   init_metricsr   r   	save_jsonr   save_txtr   process_mask_nativeprocess_maskr   dictstats)r   modelr   r   r   r-   =   s   z"SegmentationValidator.init_metricsc                 C   s   dd S )z5Return a formatted description of evaluation metrics.z,%22s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s)ClassImages	InstanceszBox(PRmAP50	mAP50-95)zMask(Pr8   r9   r:   r   )r   r   r   r   get_descL   s   zSegmentationValidator.get_descc                    s<   t  |d }t|d dkr|d d n|d }||fS )a6  
        Post-process YOLO predictions and return output detections with proto.

        Args:
            preds (list): Raw predictions from the model.

        Returns:
            p (torch.Tensor): Processed detection predictions.
            proto (torch.Tensor): Prototype masks for segmentation.
        r         )r   postprocesslen)r   predspprotor   r   r   r?   \   s   $z!SegmentationValidator.postprocessc                    s<   t  ||}| jjr|gn|d |k}|d | |d< |S )a+  
        Prepare a batch for training or inference by processing images and targets.

        Args:
            si (int): Batch index.
            batch (dict): Batch data containing images and targets.

        Returns:
            (dict): Prepared batch with processed images and targets.
        	batch_idxr    )r   _prepare_batchr   overlap_mask)r   sir%   prepared_batchmidxr   r   r   rE   k   s   z$SegmentationValidator._prepare_batchc                    sL   t  ||}| j||ddddf |ddddf |d d}||fS )a  
        Prepare predictions for evaluation by processing bounding boxes and masks.

        Args:
            pred (torch.Tensor): Raw predictions from the model.
            pbatch (dict): Prepared batch data.
            proto (torch.Tensor): Prototype masks for segmentation.

        Returns:
            predn (torch.Tensor): Processed bounding box predictions.
            pred_masks (torch.Tensor): Processed mask predictions.
        N      imgsz)shape)r   _prepare_predr   )r   predpbatchrC   predn
pred_masksr   r   r   rN   {   s   6z#SegmentationValidator._prepare_predc                 C   s  t t|d |d D ]Y\}\}}|  jd7  _t|}ttjd| jdtjd| jdtj|| jtj	| jdtj|| jtj	| jdd}| 
||}|d|d}	}
t|	}|	|d< |	 |d	< |dkr|r| j D ]}| j| ||  qo| jjr| jjd
|
|	d q|d}| jjrd|d
d
df< | |||\}}|d
d
df |d< |d
d
df |d< |r| ||
|	|d< | j||
|	||| jjdd|d< | jjr| j||
|	 | j D ]}| j| ||  qtj|tjd}| jjr| jdk r| j|d
d   |jd dkrtd | jj rD| !||d | t"j#|$ddd%  & |d |d | d | jj're| (||| jj)|d | j*d t+|d | j, d  qd
S ) z
        Update metrics with the current batch predictions and targets.

        Args:
            preds (list): Predictions from the model.
            batch (dict): Batch data containing images and targets.
        r   r<   r#   )dtyper#   )r)   r*   r(   r'   clsbboxr+   r,   N)
detections	gt_bboxesgt_clsr       rK   r)   r*   r(   T)r    r'   rT   r=   2   zBLimiting validation plots to first 50 items per image for speed...im_file   	ori_shape	ratio_pad)r`   labelsz.txt)-	enumeratezipseenr@   r2   torchzerosr#   niouboolrE   popuniquer3   keysappendr   plotsconfusion_matrixprocess_batch
single_clsrN   _process_batchrF   	as_tensoruint8batch_ir   cpurM   r   warningr.   pred_to_jsonr   scale_imagepermute
contiguousnumpyr/   save_one_txt	save_confr   r   stem)r   rA   r%   rG   rO   rC   nprstatrP   rU   rV   nlkgt_masksrQ   rR   r   r   r   update_metrics   sz   $






	 z$SegmentationValidator.update_metricsc                 O   s   | j | j_ | j| j_dS )a  
        Finalize evaluation metrics by setting the speed attribute in the metrics object.

        This method is called at the end of validation to set the processing speed for the metrics calculations.
        It transfers the validator's speed measurement to the metrics object for reporting.

        Args:
            *args (Any): Variable length argument list.
            **kwargs (Any): Arbitrary keyword arguments.
        N)speedr   rn   )r   r   kwargsr   r   r   finalize_metrics   s   
z&SegmentationValidator.finalize_metricsFc                 C   s   |r`|r't |}tj||jd|ddd }	||dd}t||	kdd}|jdd |jdd krLtj	|d |jdd dddd	 }|
d
}t||jd	 d||jd	 d}
nt||ddddf }
| |dddf ||
S )a  
        Compute correct prediction matrix for a batch based on bounding boxes and optional masks.

        Args:
            detections (torch.Tensor): Tensor of shape (N, 6) representing detected bounding boxes and
                associated confidence scores and class indices. Each row is of the format [x1, y1, x2, y2, conf, class].
            gt_bboxes (torch.Tensor): Tensor of shape (M, 4) representing ground truth bounding box coordinates.
                Each row is of the format [x1, y1, x2, y2].
            gt_cls (torch.Tensor): Tensor of shape (M,) representing ground truth class indices.
            pred_masks (torch.Tensor, optional): Tensor representing predicted masks, if available. The shape should
                match the ground truth masks.
            gt_masks (torch.Tensor, optional): Tensor of shape (M, H, W) representing ground truth masks, if available.
            overlap (bool): Flag indicating if overlapping masks should be considered.
            masks (bool): Flag indicating if the batch contains mask data.

        Returns:
            (torch.Tensor): A correct prediction matrix of shape (N, 10), where 10 represents different IoU levels.

        Note:
            - If `masks` is True, the function computes IoU between predicted and ground truth masks.
            - If `overlap` is True and `masks` is True, overlapping masks are taken into account when computing IoU.

        Examples:
            >>> detections = torch.tensor([[25, 30, 200, 300, 0.8, 1], [50, 60, 180, 290, 0.75, 0]])
            >>> gt_bboxes = torch.tensor([[24, 29, 199, 299], [55, 65, 185, 295]])
            >>> gt_cls = torch.tensor([1, 0])
            >>> correct_preds = validator._process_batch(detections, gt_bboxes, gt_cls)
        rS   r<   g      ?g        NbilinearF)modealign_cornersr   g      ?r>   rK   rZ   )r@   re   aranger#   viewrepeatwhererM   Finterpolategt_r   r
   match_predictions)r   rW   rX   rY   rR   r   overlapr    r   indexiour   r   r   rq      s   $
(z$SegmentationValidator._process_batchc                 C   sN   t |d |d |d d|d |d |d | jd| d	 | j| jd
	 dS )z
        Plot validation samples with bounding box labels and masks.

        Args:
            batch (dict): Batch data containing images and targets.
            ni (int): Batch index.
        imgrD   rU   r>   bboxesr    r]   	val_batchz_labels.jpg)r    pathsfnamenameson_plotN)r   squeezer   r   r   )r   r%   nir   r   r   plot_val_samples  s   
z&SegmentationValidator.plot_val_samplesc                 C   sp   t |d gt|d ddt| jrtj| jddn| jR |d | jd| d | j| jd	 | j	  d
S )z
        Plot batch predictions with masks and bounding boxes.

        Args:
            batch (dict): Batch data containing images.
            preds (list): Predictions from the model.
            ni (int): Batch index.
        r   r   r\   )max_det)dimr]   r   z	_pred.jpg)r   r   r   r   N)
r   r   r@   r   re   catr   r   r   clear)r   r%   rA   r   r   r   r   plot_predictions'  s   		z&SegmentationValidator.plot_predictionsc                 C   sV   ddl m} |tj|d |d ftjdd| j|ddddf |dj||d dS )	a  
        Save YOLO detections to a txt file in normalized coordinates in a specific format.

        Args:
            predn (torch.Tensor): Predictions in the format [x1, y1, x2, y2, conf, cls].
            pred_masks (torch.Tensor): Predicted masks.
            save_conf (bool): Whether to save confidence scores.
            shape (tuple): Original image shape.
            file (Path): File path to save the detections.
        r   )Resultsr<   r[   NrJ   )pathr   boxesr    )r}   )ultralytics.engine.resultsr   nprf   rs   r   r/   )r   rQ   rR   r}   rM   filer   r   r   r   r|   ;  s   
z"SegmentationValidator.save_one_txtc              	      s&  ddl m   fdd}t|j}| rt|n|}t|ddddf }|ddddf  |ddddf d 8  < t	|d}t
t}|||}	W d   n1 s[w   Y  tt| | D ]%\}
\}}| j|| jt|d	  d
d |D t|d d	|	|
 d qkdS )a  
        Save one JSON result for COCO evaluation.

        Args:
            predn (torch.Tensor): Predictions in the format [x1, y1, x2, y2, conf, cls].
            filename (str): Image filename.
            pred_masks (numpy.ndarray): Predicted masks.

        Examples:
             >>> result = {"image_id": 42, "category_id": 18, "bbox": [258.15, 41.29, 348.26, 243.78], "score": 0.236}
        r   encodec                    s@    t j| dddddf dddd }|d d|d< |S )z:Encode predicted masks as RLE and append results to jdict.Nr   rs   )orderrT   r   countszutf-8)r   asarraydecode)xrler   r   r   single_encode^  s   *z9SegmentationValidator.pred_to_json.<locals>.single_encodeNrK   r^   )r^   r   r<   rZ   c                 S   s   g | ]}t |d qS )r=   )round.0r   r   r   r   
<listcomp>p  s    z6SegmentationValidator.pred_to_json.<locals>.<listcomp>)image_idcategory_idrV   scoresegmentation)pycocotools.maskr   r   r~   	isnumericintr   	xyxy2xywhr   	transposer   r   maprb   rc   tolistjdictrl   	class_mapr   )r   rQ   filenamerR   r   r~   r   boxpoolrlesirB   br   r   r   rw   P  s(   
0
"z"SegmentationValidator.pred_to_jsonc              
   C   s  | j jrU| js| jrUt| jrU| jd }| jd d | jr"dnd| j j d }| jr0dnd}t	
d	| d
| d| d z||fD ]}| sSJ | dqFt| jrZdnd | jrddlm} ddlm} |t|}|t|}	|||	d|||	dg}
n!ddlm}m} |t|}|t|}	|||	d|||	dg}
t|
D ]{\}}dd | jjjD |j_|  |  |  | jr|   |d d }| jr|j!dd n	|j"d |j"d g\|| j#j$|d  < || j#j$| < | jr&|dkrdnd}|j"d  |d!| d"< |j"d# |d$| d"< |j"d% |d&| d"< q| jr4|d' |d(< W |S W |S  t%yT } zt	&| d)|  W Y d}~|S d}~ww |S )*z6Return COCO-style object detection evaluation metrics.zpredictions.jsonr   annotationszinstances_val2017.jsonlvis_v1_z.jsonpycocotoolslvisz
Evaluating z mAP using z and z...z file not foundr&   zlvis>=0.5.3r   )COCO)COCOevalrV   segm)LVISLVISEvalc                 S   s   g | ]	}t t|jqS r   )r   r   r~   r   r   r   r   r     s    z3SegmentationValidator.eval_json.<locals>.<listcomp>rK   r^   NAPAP50r<   BMAPrzmetrics/APr()APczmetrics/APc(APfzmetrics/APf(zmetrics/mAP50-95(B)fitnessz unable to run: )'r   r.   is_lvisis_cocor@   r   r   datasplitr   infois_filer   pycocotools.cocor   pycocotools.cocoevalr   strloadResr   r   r   
_load_jsonrb   r   datasetim_filesparamsimgIdsevaluate
accumulate	summarizeprint_resultsr3   resultsr   rk   	Exceptionrv   )r   r3   	pred_json	anno_jsonpkgr   r   r   annorO   valsr   r   r   evalidxtager   r   r   	eval_jsonv  sf   $
&"zSegmentationValidator.eval_json)NNNNN)NNFF)__name__
__module____qualname____doc__r   r!   r-   r;   r?   rE   rN   r   r   rq   r   r   r|   rw   r   __classcell__r   r   r   r   r      s"    M
,&r   )multiprocessing.poolr   pathlibr   r{   r   re   torch.nn.functionalnn
functionalr   ultralytics.models.yolo.detectr   ultralytics.utilsr   r   r   ultralytics.utils.checksr   ultralytics.utils.metricsr	   r
   r   ultralytics.utils.plottingr   r   r   r   r   r   r   <module>   s   