a
    yµÿf~…  ã                   @   sR  d dl Z d dlm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mZmZmZmZ d dlmZ ddlmZmZ ddlmZ G d	d
„ d
ejƒZG dd„ dejƒZG dd„ dejƒZG dd„ dejƒZG dd„ deƒZG dd„ dejƒZG dd„ dƒZ G dd„ de ƒZ!G dd„ de ƒZ"G dd„ dƒZ#G dd„ de ƒZ$G dd „ d ƒZ%dS )!é    N)Ú	OKS_SIGMA)Ú	crop_maskÚ	xywh2xyxyÚ	xyxy2xywh)ÚRotatedTaskAlignedAssignerÚTaskAlignedAssignerÚ	dist2bboxÚ	dist2rboxÚmake_anchors)Úautocasté   )Úbbox_iouÚprobiou)Ú	bbox2distc                       s.   e Zd ZdZ‡ fdd„Zeddd„ƒZ‡  ZS )	ÚVarifocalLosszO
    Varifocal loss by Zhang et al.

    https://arxiv.org/abs/2008.13367.
    c                    s   t ƒ  ¡  dS )z#Initialize the VarifocalLoss class.N©ÚsuperÚ__init__©Úself©Ú	__class__© úR/var/www/html/django/DPS/env/lib/python3.9/site-packages/ultralytics/utils/loss.pyr      s    zVarifocalLoss.__init__ç      è?ç       @c                 C   sv   ||   ¡  |¡ d|  ||  }tdd6 tj|  ¡ | ¡ dd|  d¡ ¡ }W d  ƒ n1 sh0    Y  |S )zComputes varfocal loss.r   F)ÚenabledÚnone©Z	reductionN)ÚsigmoidÚpowr   ÚFÚ binary_cross_entropy_with_logitsÚfloatÚmeanÚsum)Z
pred_scoreZgt_scoreÚlabelÚalphaÚgammaÚweightÚlossr   r   r   Úforward   s    "ÿÿ zVarifocalLoss.forward)r   r   ©Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Ústaticmethodr+   Ú__classcell__r   r   r   r   r      s   r   c                       s.   e Zd ZdZ‡ fdd„Zeddd„ƒZ‡  ZS )	Ú	FocalLosszjWraps focal loss around existing loss_fcn(), i.e. criteria = FocalLoss(nn.BCEWithLogitsLoss(), gamma=1.5).c                    s   t ƒ  ¡  dS )z3Initializer for FocalLoss class with no parameters.Nr   r   r   r   r   r   +   s    zFocalLoss.__init__ç      ø?ç      Ð?c           	      C   sz   t j| |dd}|  ¡ }|| d| d|   }d| | }||9 }|dkrl|| d| d|   }||9 }| d¡ ¡ S )zRCalculates and updates confusion matrix for object detection/classification tasks.r   r   r   ç      ð?r   )r!   r"   r   r$   r%   )	Úpredr&   r(   r'   r*   Z	pred_probZp_tZmodulating_factorZalpha_factorr   r   r   r+   /   s    zFocalLoss.forward)r4   r5   r,   r   r   r   r   r3   (   s   r3   c                       s0   e Zd ZdZd	ddœ‡ fdd„Zdd„ Z‡  ZS )
ÚDFLossz9Criterion class for computing DFL losses during training.é   N©Úreturnc                    s   t ƒ  ¡  || _dS )zInitialize the DFL module.N)r   r   Úreg_max©r   r<   r   r   r   r   D   s    
zDFLoss.__init__c                 C   s„   |  d| jd d ¡}| ¡ }|d }|| }d| }tj|| d¡dd |j¡| tj|| d¡dd |j¡|  jdddS )	z¹
        Return sum of left and right DFL losses.

        Distribution Focal Loss (DFL) proposed in Generalized Focal Loss
        https://ieeexplore.ieee.org/document/9792391
        r   r   g{®Gáz„?éÿÿÿÿr   r   T©Zkeepdim)Zclamp_r<   Úlongr!   Úcross_entropyÚviewÚshaper$   )r   Ú	pred_distÚtargetÚtlÚtrZwlÚwrr   r   r   Ú__call__I   s      ÿÿýzDFLoss.__call__)r9   )r-   r.   r/   r0   r   rI   r2   r   r   r   r   r8   A   s   r8   c                       s*   e Zd ZdZd‡ fdd„	Zdd„ Z‡  ZS )ÚBboxLossú>Criterion class for computing training losses during training.r9   c                    s$   t ƒ  ¡  |dkrt|ƒnd| _dS )úLInitialize the BboxLoss module with regularization maximum and DFL settings.r   N)r   r   r8   Údfl_lossr=   r   r   r   r   ^   s    
zBboxLoss.__init__c                 C   s¦   |  d¡|  d¡}t|| || ddd}	d|	 |   ¡ | }
| jrŒt||| jjd ƒ}|  ||  d| jj¡|| ¡| }|  ¡ | }nt d¡ 	|j
¡}|
|fS )ú	IoU loss.r>   FT)ÚxywhZCIoUr6   r   ç        )r%   Ú	unsqueezer   rM   r   r<   rB   ÚtorchÚtensorÚtoÚdevice©r   rD   Úpred_bboxesÚanchor_pointsÚtarget_bboxesÚtarget_scoresÚtarget_scores_sumÚfg_maskr)   ZiouZloss_iouZtarget_ltrbZloss_dflr   r   r   r+   c   s    $zBboxLoss.forward)r9   ©r-   r.   r/   r0   r   r+   r2   r   r   r   r   rJ   [   s   rJ   c                       s(   e Zd ZdZ‡ fdd„Zdd„ Z‡  ZS )ÚRotatedBboxLossrK   c                    s   t ƒ  |¡ dS )rL   Nr   r=   r   r   r   r   w   s    zRotatedBboxLoss.__init__c                 C   s°   |  d¡|  d¡}t|| || ƒ}	d|	 |   ¡ | }
| jr–t|t|ddd…f ƒ| jjd ƒ}|  ||  d| jj¡|| ¡| }|  ¡ | }nt 	d¡ 
|j¡}|
|fS )rN   r>   r6   .Né   r   rP   )r%   rQ   r   rM   r   r   r<   rB   rR   rS   rT   rU   rV   r   r   r   r+   {   s    $$zRotatedBboxLoss.forwardr]   r   r   r   r   r^   t   s   r^   c                       s.   e Zd ZdZddœ‡ fdd„Zdd„ Z‡  ZS )ÚKeypointLossú.Criterion class for computing training losses.Nr:   c                    s   t ƒ  ¡  || _dS )z"Initialize the KeypointLoss class.N)r   r   Úsigmas)r   rb   r   r   r   r      s    
zKeypointLoss.__init__c                 C   s   |d |d    d¡|d |d    d¡ }|jd tj|dkddd  }|d| j   d¡|d  d  }| dd¡dt | ¡ |   ¡ S )	z_Calculates keypoint loss factor and Euclidean distance loss for predicted and actual keypoints.©.r   é   ©.r   r   r   ©Údimg•Ö&è.>r>   )r    rC   rR   r%   rb   rB   Úexpr$   )r   Ú	pred_kptsZgt_kptsÚkpt_maskÚareaÚdZkpt_loss_factorÚer   r   r   r+   ”   s    ,  zKeypointLoss.forwardr]   r   r   r   r   r`   Œ   s   r`   c                   @   s2   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ ZdS )Úv8DetectionLossra   é
   c                 C   s®   t | ¡ ƒj}|j}|jd }tjdd| _|| _|j	| _	|j
| _
|j
|jd  | _|j| _|| _|jdk| _t|| j
ddd| _t|jƒ |¡| _tj|jtj|d	| _d
S )zdInitializes v8DetectionLoss with the model, defining model-related properties and BCE loss function.r>   r   r   r_   r   ç      à?ç      @©ZtopkZnum_classesr'   Úbeta)ÚdtyperU   N)ÚnextÚ
parametersrU   ÚargsÚmodelÚnnÚBCEWithLogitsLossÚbceÚhypÚstrideÚncr<   ÚnoÚuse_dflr   ÚassignerrJ   rT   Ú	bbox_lossrR   Zaranger#   Úproj)r   rx   Útal_topkrU   ÚhÚmr   r   r   r       s    
zv8DetectionLoss.__init__c                 C   sÞ   |j \}}|dkr,tj|d|d | jd}n®|dd…df }|jdd\}}	|	jtjd}	tj||	 ¡ |d | jd}t|ƒD ]4}
||
k}| 	¡ }|r~||dd…f ||
d|…f< q~t
|ddd	…f  |¡ƒ|ddd	…f< |S )
úXPreprocesses the target counts and matches with the input batch size to output a tensor.r   r   ©rU   NT©Zreturn_counts©rt   .é   )rC   rR   ÚzerosrU   ÚuniquerT   Úint32ÚmaxÚranger%   r   Úmul_)r   ÚtargetsÚ
batch_sizeÚscale_tensorÚnlÚneÚoutÚiÚ_ÚcountsÚjÚmatchesÚnr   r   r   Ú
preprocess´   s    
&zv8DetectionLoss.preprocessc                 C   sJ   | j r<|j\}}}| ||d|d ¡ d¡ | j |j¡¡}t||ddS )zUDecode predicted object bounding box coordinates from anchor points and distribution.r_   é   F)rO   )	r€   rC   rB   ÚsoftmaxÚmatmulrƒ   Útypert   r   )r   rX   rD   ÚbÚaÚcr   r   r   Úbbox_decodeÆ   s    *zv8DetectionLoss.bbox_decodec              	      s2  t jdˆjd}t|tƒr"|d n|‰ t  ‡ ‡fdd„ˆ D ƒd¡ ˆjd ˆjfd¡\}}| 	ddd¡ 
¡ }| 	ddd¡ 
¡ }|j}|jd }t jˆ d jdd	… ˆj|d
ˆjd  }tˆ ˆjdƒ\}	}
t  |d  dd¡|d  dd¡|d fd¡}ˆj| ˆj¡||g d¢ d}| dd¡\}}|jddd d¡}ˆ |	|¡}ˆ | ¡  ¡ | ¡ |
  |j¡|	|
 |||¡\}}}}}t| ¡ dƒ}ˆ || |¡¡ ¡ | |d< | ¡ râ||
 }ˆ |||	||||¡\|d< |d< |d  ˆjj9  < |d  ˆjj9  < |d  ˆjj 9  < | ¡ | | ¡ fS )úLCalculate the sum of the loss for box, cls and dfl multiplied by batch size.rŸ   rˆ   r   c                    s&   g | ]}|  ˆ d  jd  ˆjd¡‘qS ©r   r>   ©rB   rC   r   ©Ú.0Úxi©Zfeatsr   r   r   Ú
<listcomp>Ó   ó    z,v8DetectionLoss.__call__.<locals>.<listcomp>rd   r_   r   N©rU   rt   rp   Ú	batch_idxr>   ÚclsÚbboxes©r   r   r   r   ©r”   ©r   r_   Tr?   rP   )!rR   rŒ   rU   Ú
isinstanceÚtupleÚcatÚsplitr<   r~   ÚpermuteÚ
contiguousrt   rC   rS   r}   r
   rB   rž   rT   r%   Úgt_r¦   r   Údetachr   r¢   r   r{   r‚   r|   Úboxr²   Údfl)r   ÚpredsÚbatchr*   Úpred_distriÚpred_scoresrt   r“   ÚimgszrX   Ústride_tensorr’   Ú	gt_labelsÚ	gt_bboxesÚmask_gtrW   r™   rY   rZ   r\   r[   r   r­   r   rI   Ï   sF    ÿ
*. 
ù

ÿzv8DetectionLoss.__call__N)ro   )r-   r.   r/   r0   r   rž   r¦   rI   r   r   r   r   rn      s
   
	rn   c                       s‚   e Zd ZdZ‡ fdd„Zdd„ Zeejejejejejejdœdd„ƒZ	ejejejejejejejeje
ejd	œ
d
d„Z‡  ZS )Úv8SegmentationLossra   c                    s   t ƒ  |¡ |jj| _dS )zSInitializes the v8SegmentationLoss class, taking a de-paralleled model as argument.N)r   r   rw   Zoverlap_maskÚoverlap©r   rx   r   r   r   r     s    zv8SegmentationLoss.__init__c                    s,  t jdˆjd}t|ƒdkr |n|d \‰ }}|j\}}}}	t  ‡ ‡fdd„ˆ D ƒd¡ ˆjd ˆjfd¡\}
}| 	ddd¡ 
¡ }|
 	ddd¡ 
¡ }
| 	ddd¡ 
¡ }|j}t jˆ d jdd	… ˆj|d
ˆjd  }tˆ ˆjdƒ\}}zz|d  dd¡}t  ||d  dd¡|d fd¡}ˆj| ˆj¡||g d¢ d}| dd¡\}}|jddd d¡}W n0 ty’ } ztdƒ|‚W Y d	}~n
d	}~0 0 ˆ ||
¡}ˆ | ¡  ¡ | ¡ |  |j¡|| |||¡\}}}}}t| ¡ dƒ}ˆ || |¡¡ ¡ | |d< | ¡ r¤ˆ |
|||| |||¡\|d< |d< |d  ˆj¡ ¡ }t|jdd	… ƒ||	fkr‚t j!|d	 ||	fddd }ˆ "||||||||ˆj#¡	|d< n$|d  |d  ¡ |d  ¡  7  < |d  ˆj$j%9  < |d  ˆj$j%9  < |d  ˆj$j&9  < |d  ˆj$j'9  < | ¡ | | ¡ fS )ú1Calculate and return the loss for the YOLO model.r_   rˆ   rŸ   r   c                    s&   g | ]}|  ˆ d  jd  ˆjd¡‘qS r¨   r©   rª   r­   r   r   r®     r¯   z/v8SegmentationLoss.__call__.<locals>.<listcomp>rd   r   Nr°   rp   r±   r>   r²   r³   r´   rµ   r¶   Tr?   rP   u€  ERROR âŒ segment dataset incorrectly formatted or not a segment dataset.
This error can occur when incorrectly training a 'segment' model on a 'detect' dataset, i.e. 'yolo train model=yolov8n-seg.pt data=coco8.yaml'.
Verify your dataset is a correctly formatted 'segment' dataset using 'data=coco8-seg.yaml' as an example.
See https://docs.ultralytics.com/datasets/segment/ for help.ÚmaskséþÿÿÿZnearest)Úmode)(rR   rŒ   rU   ÚlenrC   r¹   rº   r<   r~   r»   r¼   rt   rS   r}   r
   rB   rž   rT   r%   r½   ÚRuntimeErrorÚ	TypeErrorr¦   r   r¾   r   r¢   r   r{   r‚   r#   r¸   r!   ZinterpolateÚcalculate_segmentation_lossrË   r|   r¿   r²   rÀ   )r   rÁ   rÂ   r*   Ú
pred_masksÚprotor“   r™   Úmask_hÚmask_wrÃ   rÄ   rt   rÅ   rX   rÆ   r±   r’   rÇ   rÈ   rÉ   rm   rW   rY   rZ   r\   Útarget_gt_idxr[   rÎ   r   r­   r   rI     sr    ÿ*" ÿú	
ú	
ù
ÿ
$zv8SegmentationLoss.__call__)Úgt_maskr7   rÖ   Úxyxyrk   r;   c                 C   s8   t  d||¡}tj|| dd}t||ƒjdd|  ¡ S )aX  
        Compute the instance segmentation loss for a single image.

        Args:
            gt_mask (torch.Tensor): Ground truth mask of shape (n, H, W), where n is the number of objects.
            pred (torch.Tensor): Predicted mask coefficients of shape (n, 32).
            proto (torch.Tensor): Prototype masks of shape (32, H, W).
            xyxy (torch.Tensor): Ground truth bounding boxes in xyxy format, normalized to [0, 1], of shape (n, 4).
            area (torch.Tensor): Area of each ground truth bounding box of shape (n,).

        Returns:
            (torch.Tensor): The calculated mask loss for a single image.

        Notes:
            The function uses the equation pred_mask = torch.einsum('in,nhw->ihw', pred, proto) to produce the
            predicted masks from the prototype masks and predicted mask coefficients.
        zin,nhw->ihwr   r   )r   rd   rf   )rR   Zeinsumr!   r"   r   r$   r%   )rÚ   r7   rÖ   rÛ   rk   Z	pred_maskr*   r   r   r   Úsingle_mask_lossc  s    z#v8SegmentationLoss.single_mask_loss)
r\   rÎ   rÙ   rY   r±   rÖ   rÕ   rÅ   rË   r;   c
              
   C   s"  |j \}
}
}}d}||g d¢  }t|ƒddd…f  d¡}|tj||||g|jd }tt|||||||ƒƒD ]¤\}}|\}}}}}}}| ¡ rø|| }|	r¾||d  	ddd¡k}| 
¡ }n|| 	d¡|k | }||  ||| ||| || ¡7 }qp||d  ¡ |d  ¡  7 }qp|| ¡  S )	aF  
        Calculate the loss for instance segmentation.

        Args:
            fg_mask (torch.Tensor): A binary tensor of shape (BS, N_anchors) indicating which anchors are positive.
            masks (torch.Tensor): Ground truth masks of shape (BS, H, W) if `overlap` is False, otherwise (BS, ?, H, W).
            target_gt_idx (torch.Tensor): Indexes of ground truth objects for each anchor of shape (BS, N_anchors).
            target_bboxes (torch.Tensor): Ground truth bounding boxes for each anchor of shape (BS, N_anchors, 4).
            batch_idx (torch.Tensor): Batch indices of shape (N_labels_in_batch, 1).
            proto (torch.Tensor): Prototype masks of shape (BS, 32, H, W).
            pred_masks (torch.Tensor): Predicted masks for each anchor of shape (BS, N_anchors, 32).
            imgsz (torch.Tensor): Size of the input image as a tensor of shape (2), i.e., (H, W).
            overlap (bool): Whether the masks in `masks` tensor overlap.

        Returns:
            (torch.Tensor): The calculated loss for instance segmentation.

        Notes:
            The batch loss can be computed for improved speed at higher memory usage.
            For example, pred_mask can be computed as follows:
                pred_mask = torch.einsum('in,nhw->ihw', pred, proto)  # (i, 32) @ (32, 160, 160) -> (i, 160, 160)
        r   r´   .rd   Nrˆ   r   r>   )rC   r   ÚprodrR   rS   rU   Ú	enumerateÚzipÚanyrB   r#   rÜ   r%   )r   r\   rÎ   rÙ   rY   r±   rÖ   rÕ   rÅ   rË   r™   r×   rØ   r*   Ztarget_bboxes_normalizedZmareaZmxyxyr˜   Zsingle_iZ	fg_mask_iZtarget_gt_idx_iZpred_masks_iZproto_iZmxyxy_iZmarea_iZmasks_iZmask_idxrÚ   r   r   r   rÔ   |  s$    " 
ÿz.v8SegmentationLoss.calculate_segmentation_loss)r-   r.   r/   r0   r   rI   r1   rR   ZTensorrÜ   ÚboolrÔ   r2   r   r   r   r   rÊ     s$   SþõrÊ   c                       s<   e Zd ZdZ‡ fdd„Zdd„ Zedd„ ƒZdd	„ Z‡  Z	S )
Ú
v8PoseLossra   c                    sv   t ƒ  |¡ |jd j| _t ¡ | _| jddgk}| jd }|rRt t	¡ 
| j¡ntj|| jd| }t|d| _dS )zaInitializes v8PoseLoss with model, sets keypoint variables and declares a keypoint loss instance.r>   é   rŸ   r   rˆ   )rb   N)r   r   rx   Ú	kpt_shapery   rz   Úbce_poserR   Z
from_numpyr   rT   rU   Zonesr`   Úkeypoint_loss)r   rx   Zis_poseZnkptrb   r   r   r   r   Â  s    

*zv8PoseLoss.__init__c              	      sø  t jdˆjd}t|d tƒr"|n|d \‰ }t  ‡ ‡fdd„ˆ D ƒd¡ ˆjd ˆjfd¡\}}| 	ddd¡ 
¡ }| 	ddd¡ 
¡ }| 	ddd¡ 
¡ }|j}t jˆ d jdd	… ˆj|d
ˆjd  }tˆ ˆjdƒ\}	}
|jd }|d  dd¡}t  ||d  dd¡|d fd¡}ˆj| ˆj¡||g d¢ d}| dd¡\}}|jddd d¡}ˆ |	|¡}ˆ |	|j|dgˆj¢R Ž ¡}ˆ | ¡  ¡ | ¡ |
  |j¡|	|
 |||¡\}}}}}t| ¡ dƒ}ˆ || |¡¡ ¡ | |d< | ¡ r€||
 }ˆ |||	||||¡\|d< |d< |d  ˆj¡ ¡   ¡ }|d  |d 9  < |d  |d 9  < ˆ !|||||
||¡\|d< |d< |d  ˆj"j#9  < |d  ˆj"j$9  < |d  ˆj"j%9  < |d  ˆj"j&9  < |d  ˆj"j'9  < | ¡ | | ¡ fS )z'Calculate the total loss and detach it.r‹   rˆ   r   r   c                    s&   g | ]}|  ˆ d  jd  ˆjd¡‘qS r¨   r©   rª   r­   r   r   r®   Ð  r¯   z'v8PoseLoss.__call__.<locals>.<listcomp>rd   r_   Nr°   rp   r±   r>   r²   r³   r´   rµ   r¶   Tr?   rP   rŸ   Ú	keypointsrc   re   )(rR   rŒ   rU   r·   Úlistr¹   rº   r<   r~   r»   r¼   rt   rS   rC   r}   r
   rB   rž   rT   r%   r½   r¦   Úkpts_decoderä   r   r¾   r   r¢   r   r{   r‚   r#   ÚcloneÚcalculate_keypoints_lossr|   r¿   ZposeZkobjr²   rÀ   )r   rÁ   rÂ   r*   ri   rÃ   rÄ   rt   rÅ   rX   rÆ   r“   r±   r’   rÇ   rÈ   rÉ   rW   r™   rY   rZ   r\   rÙ   r[   rç   r   r­   r   rI   Ì  s\    ÿ*
" 
ú	
ÿÿzv8PoseLoss.__call__c                 C   sh   |  ¡ }|ddd…f  d9  < |d  | dd…dgf d 7  < |d  | dd…d	gf d 7  < |S )
z1Decodes predicted keypoints to image coordinates..Nrd   r   rc   r   rp   re   r   )rê   )rX   ri   Úyr   r   r   ré     s
    ""zv8PoseLoss.kpts_decodec              
   C   sr  |  ¡ }t|ƒ}tj|ddd  ¡ }	tj||	|jd |jd f|jd}
t|ƒD ]&}|||k }||
|d|jd …f< qR| 	d¡ 	d¡}|
 
d| dd|jd |jd ¡¡}|| dddd¡ }d}d}| ¡ rj|| }t|| ƒdd…dd…f jddd	}|| }|jd d
kr&|d dknt |d d¡}|  ||||¡}|jd d
krj|  |d | ¡ ¡}||fS )aZ  
        Calculate the keypoints loss for the model.

        This function calculates the keypoints loss and keypoints object loss for a given batch. The keypoints loss is
        based on the difference between the predicted keypoints and ground truth keypoints. The keypoints object loss is
        a binary classification loss that classifies whether a keypoint is present or not.

        Args:
            masks (torch.Tensor): Binary mask tensor indicating object presence, shape (BS, N_anchors).
            target_gt_idx (torch.Tensor): Index tensor mapping anchors to ground truth objects, shape (BS, N_anchors).
            keypoints (torch.Tensor): Ground truth keypoints, shape (N_kpts_in_batch, N_kpts_per_object, kpts_dim).
            batch_idx (torch.Tensor): Batch index tensor for keypoints, shape (N_kpts_in_batch, 1).
            stride_tensor (torch.Tensor): Stride tensor for anchors, shape (N_anchors, 1).
            target_bboxes (torch.Tensor): Ground truth boxes in (x1, y1, x2, y2) format, shape (BS, N_anchors, 4).
            pred_kpts (torch.Tensor): Predicted keypoints, shape (BS, N_anchors, N_kpts_per_object, kpts_dim).

        Returns:
            (tuple): Returns a tuple containing:
                - kpts_loss (torch.Tensor): The keypoints loss.
                - kpts_obj_loss (torch.Tensor): The keypoints object loss.
        Tr‰   r   rd   rˆ   Nr   r>   r?   rŸ   ).rd   rc   )ÚflattenrÑ   rR   r   r   rŒ   rC   rU   r   rQ   ÚgatherÚexpandrB   rà   r   rÝ   Z	full_likeræ   rå   r#   )r   rÎ   rÙ   rç   r±   rÆ   rY   ri   r“   Zmax_kptsZbatched_keypointsr˜   Zkeypoints_iZtarget_gt_idx_expandedZselected_keypointsZ	kpts_lossZkpts_obj_lossZgt_kptrk   Zpred_kptrj   r   r   r   rë     s2    ÿÿ
&,z#v8PoseLoss.calculate_keypoints_loss)
r-   r.   r/   r0   r   rI   r1   ré   rë   r2   r   r   r   r   râ   ¿  s   
B
râ   c                   @   s   e Zd ZdZdd„ ZdS )Úv8ClassificationLossra   c                 C   s$   t j||d dd}| ¡ }||fS )zDCompute the classification loss between predictions and true labels.r²   r$   r   )r!   rA   r¾   )r   rÁ   rÂ   r*   Z
loss_itemsr   r   r   rI   ^  s    zv8ClassificationLoss.__call__N)r-   r.   r/   r0   rI   r   r   r   r   rð   [  s   rð   c                       s8   e Zd ZdZ‡ fdd„Zdd„ Zdd„ Zdd	„ Z‡  ZS )
Ú	v8OBBLosszdCalculates losses for object detection, classification, and box distribution in rotated YOLO models.c                    s8   t ƒ  |¡ td| jddd| _t| jƒ | j¡| _	dS )zdInitializes v8OBBLoss with model, assigner, and rotated bbox loss; note model must be de-paralleled.ro   rp   rq   rr   N)
r   r   r   r~   r   r^   r<   rT   rU   r‚   rÌ   r   r   r   r   h  s    zv8OBBLoss.__init__c                 C   sà   |j d dkr$tj|dd| jd}n¸|dd…df }|jdd\}}|jtjd}tj|| ¡ d| jd}t|ƒD ]h}||k}	|	 	¡ }
|
rr||	dd…f }|d	dd
…f  
|¡ tj||	dd…f |gdd||d|
…f< qr|S )r‡   r   é   rˆ   NTr‰   rŠ   rd   .r_   r   r>   rf   )rC   rR   rŒ   rU   r   rT   rŽ   r   r   r%   r‘   r¹   )r   r’   r“   r”   r—   r˜   r™   rš   r›   rœ   r   r³   r   r   r   rž   n  s    ,zv8OBBLoss.preprocessc              
      s$  t jdˆjd}t|d tƒr"|n|d \‰ }|jd }t  ‡ ‡fdd„ˆ D ƒd¡ ˆjd ˆj	fd¡\}}| 
ddd¡ ¡ }| 
ddd¡ ¡ }| 
ddd¡ ¡ }|j}t jˆ d jdd	… ˆj|d
ˆjd  }	tˆ ˆjdƒ\}
}zÐ|d  dd¡}t  ||d  dd¡|d  dd¡fd¡}|d	d	…df |	d  ¡  |d	d	…df |	d  ¡   }}||dk|dk@  }ˆj| ˆj¡||	g d¢ d}| dd¡\}}|jddd d¡}W n0 tyä } ztdƒ|‚W Y d	}~n
d	}~0 0 ˆ |
||¡}| ¡  ¡ }|dd	d…f  |9  < ˆ | ¡  ¡ | |j¡|
| |||¡\}}}}}t| ¡ dƒ}ˆ || |¡¡ ¡ | |d< | ¡ r¼|dd	d…f  |  < ˆ  |||
||||¡\|d< |d< n|d  |d  ¡ 7  < |d  ˆj!j"9  < |d  ˆj!j#9  < |d  ˆj!j$9  < | ¡ | | ¡ fS )rÍ   rŸ   rˆ   r   r   c                    s&   g | ]}|  ˆ d  jd  ˆjd¡‘qS r¨   r©   rª   r­   r   r   r®   …  r¯   z&v8OBBLoss.__call__.<locals>.<listcomp>rd   r_   Nr°   rp   r±   r>   r²   r³   r‹   r´   rµ   )r   r‹   Tr?   rP   uh  ERROR âŒ OBB dataset incorrectly formatted or not a OBB dataset.
This error can occur when incorrectly training a 'OBB' model on a 'detect' dataset, i.e. 'yolo train model=yolov8n-obb.pt data=dota8.yaml'.
Verify your dataset is a correctly formatted 'OBB' dataset using 'data=dota8.yaml' as an example.
See https://docs.ultralytics.com/datasets/obb/ for help..)%rR   rŒ   rU   r·   rè   rC   r¹   rº   r<   r~   r»   r¼   rt   rS   r}   r
   rB   Úitemrž   rT   r%   r½   rÒ   rÓ   r¦   rê   r¾   r   r   r¢   r   r{   r‚   r|   r¿   r²   rÀ   )r   rÁ   rÂ   r*   Ú
pred_angler“   rÃ   rÄ   rt   rÅ   rX   rÆ   r±   r’   ÚrwZrhrÇ   rÈ   rÉ   rm   rW   Zbboxes_for_assignerr™   rY   rZ   r\   r[   r   r­   r   rI   €  sb    
ÿ**: ÿú	

ú	
ÿzv8OBBLoss.__call__c                 C   sV   | j r<|j\}}}| ||d|d ¡ d¡ | j |j¡¡}tj	t
|||ƒ|fddS )a¹  
        Decode predicted object bounding box coordinates from anchor points and distribution.

        Args:
            anchor_points (torch.Tensor): Anchor points, (h*w, 2).
            pred_dist (torch.Tensor): Predicted rotated distance, (bs, h*w, 4).
            pred_angle (torch.Tensor): Predicted angle, (bs, h*w, 1).

        Returns:
            (torch.Tensor): Predicted rotated bounding boxes with angles, (bs, h*w, 5).
        r_   rŸ   r>   rf   )r€   rC   rB   r    r¡   rƒ   r¢   rt   rR   r¹   r	   )r   rX   rD   rô   r£   r¤   r¥   r   r   r   r¦   È  s    *zv8OBBLoss.bbox_decode)	r-   r.   r/   r0   r   rž   rI   r¦   r2   r   r   r   r   rñ   e  s
   Hrñ   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚE2EDetectLossra   c                 C   s    t |dd| _t |dd| _dS )zcInitialize E2EDetectLoss with one-to-many and one-to-one detection losses using the provided model.ro   )r„   r   N)rn   Úone2manyÚone2onerÌ   r   r   r   r   Ý  s    zE2EDetectLoss.__init__c                 C   s^   t |tƒr|d n|}|d }|  ||¡}|d }|  ||¡}|d |d  |d |d  fS )r§   r   r÷   rø   r   )r·   r¸   r÷   rø   )r   rÁ   rÂ   r÷   Zloss_one2manyrø   Zloss_one2oner   r   r   rI   â  s    zE2EDetectLoss.__call__N)r-   r.   r/   r0   r   rI   r   r   r   r   rö   Ú  s   rö   )&rR   Ztorch.nnry   Ztorch.nn.functionalZ
functionalr!   Zultralytics.utils.metricsr   Zultralytics.utils.opsr   r   r   Zultralytics.utils.talr   r   r   r	   r
   Zultralytics.utils.torch_utilsr   Zmetricsr   r   Útalr   ÚModuler   r3   r8   rJ   r^   r`   rn   rÊ   râ   rð   rñ   rö   r   r   r   r   Ú<module>   s,   k 8 
u