
    |h6                     z    d dl mZ d dl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mZ  G d de
      Zy)	    )Path)AnyDictTupleN)DetectionValidator)LOGGERops)	OKS_SIGMAPoseMetricskpt_iouc            
       :    e Zd ZdZdd fdZdeeef   deeef   f fdZdefdZ	de
j                  j                  ddf fd	Zd
e
j                  deee
j                  f   f fdZdedeeef   deeef   f fdZdeeef   deeef   deeef   f fdZd
eee
j                  f   deeef   deeej(                  f   f fdZdeee
j                  f   dedeeef   deddf
dZdeee
j                  f   deddfdZdeeef   deeef   f fdZ xZS )PoseValidatora  
    A class extending the DetectionValidator class for validation based on a pose model.

    This validator is specifically designed for pose estimation tasks, handling keypoints and implementing
    specialized metrics for pose evaluation.

    Attributes:
        sigma (np.ndarray): Sigma values for OKS calculation, either OKS_SIGMA or ones divided by number of keypoints.
        kpt_shape (List[int]): Shape of the keypoints, typically [17, 3] for COCO format.
        args (dict): Arguments for the validator including task set to "pose".
        metrics (PoseMetrics): Metrics object for pose evaluation.

    Methods:
        preprocess: Preprocess batch by converting keypoints data to float and moving it to the device.
        get_desc: Return description of evaluation metrics in string format.
        init_metrics: Initialize pose estimation metrics for YOLO model.
        _prepare_batch: Prepare a batch for processing by converting keypoints to float and scaling to original
            dimensions.
        _prepare_pred: Prepare and scale keypoints in predictions for pose processing.
        _process_batch: Return correct prediction matrix by computing Intersection over Union (IoU) between
            detections and ground truth.
        plot_val_samples: Plot and save validation set samples with ground truth bounding boxes and keypoints.
        plot_predictions: Plot and save model predictions with bounding boxes and keypoints.
        save_one_txt: Save YOLO pose detections to a text file in normalized coordinates.
        pred_to_json: Convert YOLO predictions to COCO JSON format.
        eval_json: Evaluate object detection model using COCO JSON format.

    Examples:
        >>> from ultralytics.models.yolo.pose import PoseValidator
        >>> args = dict(model="yolo11n-pose.pt", data="coco8-pose.yaml")
        >>> validator = PoseValidator(args=args)
        >>> validator()
    Nreturnc                 J   t         |   ||||       d| _        d| _        d| j                  _        t               | _        t        | j                  j                  t              r>| j                  j                  j                         dk(  rt        j                  d       yyy)a  
        Initialize a PoseValidator object for pose estimation validation.

        This validator is specifically designed for pose estimation tasks, handling keypoints and implementing
        specialized metrics for pose evaluation.

        Args:
            dataloader (torch.utils.data.DataLoader, optional): Dataloader to be used for validation.
            save_dir (Path | str, optional): Directory to save results.
            args (dict, optional): Arguments for the validator including task set to "pose".
            _callbacks (list, optional): List of callback functions to be executed during validation.

        Examples:
            >>> from ultralytics.models.yolo.pose import PoseValidator
            >>> args = dict(model="yolo11n-pose.pt", data="coco8-pose.yaml")
            >>> validator = PoseValidator(args=args)
            >>> validator()

        Notes:
            This class extends DetectionValidator with pose-specific functionality. It initializes with sigma values
            for OKS calculation and sets up PoseMetrics for evaluation. A warning is displayed when using Apple MPS
            due to a known bug with pose models.
        Nposempsz}Apple MPS known Pose bug. Recommend 'device=cpu' for Pose models. See https://github.com/ultralytics/ultralytics/issues/4031.)super__init__sigma	kpt_shapeargstaskr   metrics
isinstancedevicestrlowerr   warning)self
dataloadersave_dirr   
_callbacks	__class__s        _/var/www/html/test/engine/venv/lib/python3.12/site-packages/ultralytics/models/yolo/pose/val.pyr   zPoseValidator.__init__1   s    0 	XtZ@
		"}dii&&,1A1A1G1G1IU1RNNN 2S,    batchc                     t         |   |      }|d   j                  | j                        j	                         |d<   |S )zSPreprocess batch by converting keypoints data to float and moving it to the device.	keypoints)r   
preprocesstor   float)r   r&   r#   s     r$   r)   zPoseValidator.preprocessT   s>    "5)";/224;;?EEGkr%   c                     ddz  S )z:Return description of evaluation metrics in string format.z,%22s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s)ClassImages	InstanceszBox(PRmAP50	mAP50-95)zPose(Pr0   r1   r2    )r   s    r$   get_desczPoseValidator.get_descZ   s    $ )
 
 	
r%   modelc                     t         |   |       | j                  d   | _        | j                  ddgk(  }| j                  d   }|rt        | _        yt        j                  |      |z  | _        y)z
        Initialize evaluation metrics for YOLO pose validation.

        Args:
            model (torch.nn.Module): Model to validate.
        r         r   N)r   init_metricsdatar   r
   nponesr   )r   r5   is_posenkptr#   s       r$   r9   zPoseValidator.init_metricsj   s^     	U#;/..RG+~~a ")Y
rwwt}t/C
r%   predsc                     t         |   |      }|D ]1  } |j                  d      j                  dg| j                   |d<   3 |S )a  
        Postprocess YOLO predictions to extract and reshape keypoints for pose estimation.

        This method extends the parent class postprocessing by extracting keypoints from the 'extra'
        field of predictions and reshaping them according to the keypoint shape configuration.
        The keypoints are reshaped from a flattened format to the proper dimensional structure
        (typically [N, 17, 3] for COCO pose format).

        Args:
            preds (torch.Tensor): Raw prediction tensor from the YOLO pose model containing
                bounding boxes, confidence scores, class predictions, and keypoint data.

        Returns:
            (Dict[torch.Tensor]): Dict of processed prediction dictionaries, each containing:
                - 'bboxes': Bounding box coordinates
                - 'conf': Confidence scores
                - 'cls': Class predictions
                - 'keypoints': Reshaped keypoint coordinates with shape (-1, *self.kpt_shape)

        Note:
            If no keypoints are present in a prediction (empty keypoints), that prediction
            is skipped and continues to the next one. The keypoints are extracted from the
            'extra' field which contains additional task-specific data beyond basic detection.
        extrar(   )r   postprocesspopviewr   )r   r?   predr#   s      r$   rC   zPoseValidator.postprocessw   sS    2 #E* 	LD 6 1 6 6r KDNN KD	Lr%   sic                     t         |   ||      }|d   |d   |k(     }|d   \  }}|j                         }|dxx   |z  cc<   |dxx   |z  cc<   t        j                  |d   ||d   |d         }||d<   |S )	a`  
        Prepare a batch for processing by converting keypoints to float and scaling to original dimensions.

        Args:
            si (int): Batch index.
            batch (Dict[str, Any]): Dictionary containing batch data with keys like 'keypoints', 'batch_idx', etc.

        Returns:
            (Dict[str, Any]): Prepared batch with keypoints scaled to original image dimensions.

        Notes:
            This method extends the parent class's _prepare_batch method by adding keypoint processing.
            Keypoints are scaled from normalized coordinates to original image dimensions.
        r(   	batch_idximgsz).r   ).   	ori_shape	ratio_padrM   )r   _prepare_batchcloner	   scale_coords)r   rG   r&   pbatchkptshwr#   s          r$   rO   zPoseValidator._prepare_batch   s     'E2[!%"4":;g1zz|VVwvk7JV\]hVij"{r%   rF   rR   c                     t         |   ||      }t        j                  |d   |j	                  d      j                         |d   |d         |d<   |S )am  
        Prepare and scale keypoints in predictions for pose processing.

        This method extends the parent class's _prepare_pred method to handle keypoint scaling. It first calls
        the parent method to get the basic prediction boxes, then extracts and scales the keypoint coordinates
        to match the original image dimensions.

        Args:
            pred (Dict[str, torch.Tensor]): Post-processed predictions from the model.
            pbatch (Dict[str, Any]): Processed batch dictionary containing image information including:
                - imgsz: Image size used for inference
                - ori_shape: Original image shape
                - ratio_pad: Ratio and padding information for coordinate scaling

        Returns:
            (Dict[str, Any]): Processed prediction dictionary with keypoints scaled to original image dimensions.
        rJ   r(   rL   rM   rN   )r   _prepare_predr	   rQ   getrP   )r   rF   rR   prednr#   s       r$   rW   zPoseValidator._prepare_pred   s]    $ %dF3 --7OTXXk288:F;<O[abm[n
k r%   c                    t         |   ||      }|d   }t        |      dk(  st        |d         dk(  r4t        j                  t        |d         | j
                  ft              }nt        j                  |d         ddddf   j                  d      dz  }t        |d	   |d	   | j                  |
      }| j                  |d   ||      j                         j                         }|j                  d|i       |S )az  
        Return correct prediction matrix by computing Intersection over Union (IoU) between detections and ground truth.

        Args:
            preds (Dict[str, torch.Tensor]): Dictionary containing prediction data with keys 'cls' for class predictions
                and 'keypoints' for keypoint predictions.
            batch (Dict[str, Any]): Dictionary containing ground truth data with keys 'cls' for class labels,
                'bboxes' for bounding boxes, and 'keypoints' for keypoint annotations.

        Returns:
            (Dict[str, np.ndarray]): Dictionary containing the correct prediction matrix including 'tp_p' for pose
                true positives across 10 IoU levels.

        Notes:
            `0.53` scale factor used in area computation is referenced from
            https://github.com/jin-s13/xtcocoapi/blob/master/xtcocotools/cocoeval.py#L384.
        clsr   dtypebboxesN   rK   g(\?r(   )r   areatp_p)r   _process_batchlenr;   zerosniouboolr	   	xyxy2xywhprodr   r   match_predictionscpunumpyupdate)	r   r?   r&   tpgt_clsra   r`   iour#   s	           r$   rb   zPoseValidator._process_batch   s    $ W#E51uv;!s5<0A588Su.		:$GD ==x1!QR%8==a@4GD%,eK.@

Y]^C))%,DHHJPPRD
		64.!	r%   rY   	save_confshapefilec                 :   ddl m}  |t        j                  |d   |d   ft        j                        d| j
                  t        j                  |d   |d   j                  d      |d	   j                  d      gd
      |d         j                  ||       y)az  
        Save YOLO pose detections to a text file in normalized coordinates.

        Args:
            predn (Dict[str, torch.Tensor]): Dictionary containing predictions with keys 'bboxes', 'conf', 'cls' and 'keypoints.
            save_conf (bool): Whether to save confidence scores.
            shape (Tuple[int, int]): Shape of the original image (height, width).
            file (Path): Output file path to save detections.

        Notes:
            The output format is: class_id x_center y_center width height confidence keypoints where keypoints are
            normalized (x, y, visibility) values for each point.
        r   )ResultsrK   r\   Nr^   confrB   r[   )dimr(   )pathnamesboxesr(   )rp   )
ultralytics.engine.resultsrt   r;   rd   uint8rx   torchcat	unsqueezesave_txt)r   rY   rp   rq   rr   rt   s         r$   save_one_txtzPoseValidator.save_one_txt   s     	7HHeAha):**))U8_eFm.E.Eb.I5QV<KaKabdKeflmnK(	
 (49(
-r%   filenamec                 d   t        |      j                  }|j                         rt        |      n|}t	        j
                  |d         }|ddddfxx   |ddddf   dz  z  cc<   t        |j                         |d   j                         |d   j                         |d   j                  dd      j                               D ]`  \  }}}}	| j                  j                  || j                  t        |         |D 
cg c]  }
t        |
d       c}
|	t        |d	      d
       b yc c}
w )a3  
        Convert YOLO predictions to COCO JSON format.

        This method takes prediction tensors and a filename, converts the bounding boxes from YOLO format
        to COCO format, and appends the results to the internal JSON dictionary (self.jdict).

        Args:
            predn (Dict[str, torch.Tensor]): Prediction dictionary containing 'bboxes', 'conf', 'cls',
                and 'keypoints' tensors.
            filename (str): Path to the image file for which predictions are being processed.

        Notes:
            The method extracts the image ID from the filename stem (either as an integer if numeric, or as a string),
            converts bounding boxes from xyxy to xywh format, and adjusts coordinates from center to top-left corner
            before saving to the JSON dictionary.
        r^   Nr_   ru   r[   r(   rK   r8      )image_idcategory_idbboxr(   score)r   stem	isnumericintr	   rg   ziptolistflattenjdictappend	class_mapround)r   rY   r   r   r   boxbsckxs              r$   pred_to_jsonzPoseValidator.pred_to_json   s   " H~"" $ 03t9dmmE(O,ArrE
c!QR%j1n$
JJL&M  "%L!+&&q!,335	
 	JAq!Q JJ (#'>>#a&#9234QU1a[4!""1a[	 5s   D-statsc                 v    | j                   d   dz  }| j                  dz  }t        |   |||ddgddg      S )	z7Evaluate object detection model using COCO JSON format.rw   z)annotations/person_keypoints_val2017.jsonzpredictions.jsonr   r(   BoxPose)suffix)r:   r!   r   coco_evaluate)r   r   	anno_json	pred_jsonr#   s       r$   	eval_jsonzPoseValidator.eval_json!  sM    IIf%(SS	MM$66	w$UIy6;BWafhn`o$ppr%   )NNNN)r   N)__name__
__module____qualname____doc__r   r   r   r   r)   r4   r|   nnModuler9   TensorrC   r   rO   rW   r;   ndarrayrb   rf   r   r   r   r   r   __classcell__)r#   s   @r$   r   r      s    D!FS#X 4S> 
# 
 D%((// Dd D $sELL7H2I < T#s(^ S#X 2$sCx. $sCx. TRUWZRZ^ 0Dell):$; DcN W[\_acakak\kWl <.$sELL'8"9 .d .SXY\^aYaSb .jn .sw .0#$sELL'8"9 #S #T #JqtCH~ q$sCx. q qr%   r   )pathlibr   typingr   r   r   rk   r;   r|   ultralytics.models.yolo.detectr   ultralytics.utilsr   r	   ultralytics.utils.metricsr
   r   r   r   r3   r%   r$   <module>r      s3     # #   = ) E EWq& Wqr%   