
    FPhU5                         d dl Z d dlmZ ddlmZ ddlmZ  ee j                  d      ZddZ	d Z
 G d d	ej                        Zdd
ZddZd Zy)    N   )check_version)bbox_iouz1.10.0c                 :   | j                   d   }|j                   \  }}}|j                  ddd      j                  dd      \  }}t        j                  | d   |z
  || d   z
  fd      j                  |||d      }	|	j                  d      j                  |      S )	z
    Select the positive anchor center in gt.

    Args:
        xy_centers (Tensor): shape(h*w, 2)
        gt_bboxes (Tensor): shape(b, n_boxes, 4)

    Returns:
        (Tensor): shape(b, n_boxes, h*w)
    r   r         N)dim   )shapeviewchunktorchcatamingt_)

xy_centers	gt_bboxeseps	n_anchorsbsn_boxes_ltrbbbox_deltass
             `C:\Users\daisl\Desktop\realtime-object-detection\venv\Lib\site-packages\ultralytics/utils/tal.pyselect_candidates_in_gtsr      s       #I__NB^^B1%++Aq1FB))Z-2BD9I4IJPQRWWXZ\cenprsKA""3''    c                    | j                  d      }|j                         dkD  r|j                  d      dkD  j                  d|d      }|j	                  d      }t        j                  | j                  | j                  | j                        }|j                  d|j                  d      d       t        j                  |||       j                         } | j                  d      }| j	                  d      }||| fS )aw  
    If an anchor box is assigned to multiple gts, the one with the highest IoI will be selected.

    Args:
        mask_pos (Tensor): shape(b, n_max_boxes, h*w)
        overlaps (Tensor): shape(b, n_max_boxes, h*w)

    Returns:
        target_gt_idx (Tensor): shape(b, h*w)
        fg_mask (Tensor): shape(b, h*w)
        mask_pos (Tensor): shape(b, n_max_boxes, h*w)
    r   r   dtypedevice)summax	unsqueezeexpandargmaxr   zerosr   r#   r$   scatter_wherefloat)mask_posoverlapsn_max_boxesfg_maskmask_multi_gtsmax_overlaps_idxis_max_overlapstarget_gt_idxs           r   select_highest_overlapsr6      s     ll2G{{}q!++A.2::2{BO#??1-++hnnHNNS[SbSbc  $4$>$>q$A1E;;~IOOQ,,r"OOB'M'8++r   c                   l     e Zd ZdZd fd	Z ej                         d        Zd Zd Z	d	dZ
d Z xZS )
TaskAlignedAssignerao  
    A task-aligned assigner for object detection.

    This class assigns ground-truth (gt) objects to anchors based on the task-aligned metric,
    which combines both classification and localization information.

    Attributes:
        topk (int): The number of top candidates to consider.
        num_classes (int): The number of object classes.
        alpha (float): The alpha parameter for the classification component of the task-aligned metric.
        beta (float): The beta parameter for the localization component of the task-aligned metric.
        eps (float): A small value to prevent division by zero.
    c                 v    t         |           || _        || _        || _        || _        || _        || _        y)zJInitialize a TaskAlignedAssigner object with customizable hyperparameters.N)super__init__topknum_classesbg_idxalphabetar   )selfr<   r=   r?   r@   r   	__class__s         r   r;   zTaskAlignedAssigner.__init__K   s9    	&!
	r   c                    |j                  d      | _        |j                  d      | _        | j                  dk(  r|j                  }t	        j
                  |d   | j                        j                  |      t	        j                  |      j                  |      t	        j                  |      j                  |      t	        j                  |d         j                  |      t	        j                  |d         j                  |      fS | j                  ||||||      \  }}	}
t        ||
| j                        \  }}}| j                  ||||      \  }}}|	|z  }	|	j                  dd      }|
|z  j                  dd      }|	|z  || j                  z   z  j                  d      j                  d      }||z  }||||j                         |fS )a  
        Compute the task-aligned assignment.
        Reference https://github.com/Nioolek/PPYOLOE_pytorch/blob/master/ppyoloe/assigner/tal_assigner.py

        Args:
            pd_scores (Tensor): shape(bs, num_total_anchors, num_classes)
            pd_bboxes (Tensor): shape(bs, num_total_anchors, 4)
            anc_points (Tensor): shape(num_total_anchors, 2)
            gt_labels (Tensor): shape(bs, n_max_boxes, 1)
            gt_bboxes (Tensor): shape(bs, n_max_boxes, 4)
            mask_gt (Tensor): shape(bs, n_max_boxes, 1)

        Returns:
            target_labels (Tensor): shape(bs, num_total_anchors)
            target_bboxes (Tensor): shape(bs, num_total_anchors, 4)
            target_scores (Tensor): shape(bs, num_total_anchors, num_classes)
            fg_mask (Tensor): shape(bs, num_total_anchors)
            target_gt_idx (Tensor): shape(bs, num_total_anchors)
        r   r   ).r   r   T)r
   keepdimr!   )sizer   r0   r$   r   	full_liker>   to
zeros_likeget_pos_maskr6   get_targetsamaxr   r'   bool)rA   	pd_scores	pd_bboxes
anc_points	gt_labelsr   mask_gtr$   r.   align_metricr/   r5   r1   target_labelstarget_bboxestarget_scorespos_align_metricspos_overlapsnorm_align_metrics                      r   forwardzTaskAlignedAssigner.forwardU   s   * ..#$>>!,q %%FOOIf$5t{{CFFvNPUP`P`ajPkPnPnouPv$$Y/226:E<L<LYW]M^<_<b<bci<j$$Yv%67::6BD D ,0+<+<Y	S\^gis=D,F(, ,C8XW[WgWg+h(w 7;6F6FyR[]jls6t3}m 	 (--"d-C 8+11b$1G)L8<MPTPXPX<XY__`bcmmnpq%(99m]GLLNMYYr   c                     t        ||      }| j                  ||||||z        \  }}	| j                  ||j                  dd| j                        j                               }
|
|z  |z  }|||	fS )z'Get in_gts mask, (b, max_num_obj, h*w).r   )	topk_mask)r   get_box_metricsselect_topk_candidatesr(   r<   rL   )rA   rM   rN   rP   r   rO   rQ   mask_in_gtsrR   r/   	mask_topkr.   s               r   rI   z TaskAlignedAssigner.get_pos_mask   s    .z9E!%!5!5iIW`bmpwbw!xh//WY[]_c_h_hHiHnHnHp/q	{*W4x//r   c                 4   |j                   d   }|j                         }t        j                  | j                  | j
                  |g|j                  |j                        }t        j                  | j                  | j
                  |g|j                  |j                        }t        j                  d| j                  | j
                  gt        j                        }	t        j                  | j                        j                  dd      j                  d| j
                        |	d<   |j                  d      |	d<   ||	d   d	d	|	d   f   |   ||<   |j                  d      j                  d| j
                  dd      |   }
|j                  d      j                  dd|d      |   }t        ||
d
d      j                  d      j                  d      ||<   |j!                  | j"                        |j!                  | j$                        z  }||fS )zICompute alignment metric given predicted and ground truth bounding boxes.r!   r"   r	   )r#   )endr   r   r   NFT)xywhCIoU)r   rL   r   r*   r   r0   r#   r$   longaranger   r(   squeezer'   r   clamp_powr?   r@   )rA   rM   rN   rP   r   rQ   nar/   bbox_scoresindpd_boxesgt_boxesrR   s                r   r\   z#TaskAlignedAssigner.get_box_metrics   s   __R ,,.;;)9)92>ioo^g^n^nokk477D,<,<b"Aajaqaqrkk1dggt'7'78

K$''*//A6==b$BRBRSA""2&A(QCF):;GDG &&q)00T5E5Er2NwW&&q)00RR@I$Xxe$OWWXZ[bbcde"tzz2X\\$))5LLX%%r   c           
         t        j                  || j                  d|      \  }}|2|j                  dd      d   | j                  kD  j	                  |      }|j                  | d       t        j                  |j                  t         j                  |j                        }t        j                  |ddddddf   t         j                  |j                        }t        | j                        D ]$  }|j                  d|dddd||dz   f   |       & |j                  |dkD  d       |j                  |j                        S )	ah  
        Select the top-k candidates based on the given metrics.

        Args:
            metrics (Tensor): A tensor of shape (b, max_num_obj, h*w), where b is the batch size,
                              max_num_obj is the maximum number of objects, and h*w represents the
                              total number of anchor points.
            largest (bool): If True, select the largest values; otherwise, select the smallest values.
            topk_mask (Tensor): An optional boolean tensor of shape (b, max_num_obj, topk), where
                                topk is the number of top candidates to consider. If not provided,
                                the top-k values are automatically computed based on the given metrics.

        Returns:
            (Tensor): A tensor of shape (b, max_num_obj, h*w) containing the selected top-k candidates.
        r   )r
   largestNT)rD   r   r"   r   )r   r<   r&   r   	expand_asmasked_fill_r*   r   int8r$   	ones_likerangescatter_add_rG   r#   )	rA   metricsro   r[   topk_metrics	topk_idxscount_tensoronesks	            r   r]   z*TaskAlignedAssigner.select_topk_candidates   s   $ #(**WdiiRQX"Yi%))"d);A>ITTU^_I	z1- {{7==

9K[K[\yArr2%**YM]M]^tyy!A%%b)Aq!AE'M*BDI "
 	!!,"2A6w}}--r   c                    t        j                  | j                  t         j                  |j                        d   }||| j
                  z  z   }|j                         j                         |   }|j                  dd      |   }|j                  d       t        j                  |j                  d   |j                  d   | j                  ft         j                  |j                        }|j                  d|j                  d      d       |d	d	d	d	d	f   j                  dd| j                        }	t        j                   |	dkD  |d      }|||fS )
a  
        Compute target labels, target bounding boxes, and target scores for the positive anchor points.

        Args:
            gt_labels (Tensor): Ground truth labels of shape (b, max_num_obj, 1), where b is the
                                batch size and max_num_obj is the maximum number of objects.
            gt_bboxes (Tensor): Ground truth bounding boxes of shape (b, max_num_obj, 4).
            target_gt_idx (Tensor): Indices of the assigned ground truth objects for positive
                                    anchor points, with shape (b, h*w), where h*w is the total
                                    number of anchor points.
            fg_mask (Tensor): A boolean tensor of shape (b, h*w) indicating the positive
                              (foreground) anchor points.

        Returns:
            (Tuple[Tensor, Tensor, Tensor]): A tuple containing the following tensors:
                - target_labels (Tensor): Shape (b, h*w), containing the target labels for
                                          positive anchor points.
                - target_bboxes (Tensor): Shape (b, h*w, 4), containing the target bounding boxes
                                          for positive anchor points.
                - target_scores (Tensor): Shape (b, h*w, num_classes), containing the target scores
                                          for positive anchor points, where num_classes is the number
                                          of object classes.
        )ra   r#   r$   ).Nr   r   r   r   r"   r	   N)r   re   r   int64r$   r0   rd   flattenr   rg   r*   r   r=   r+   r'   repeatr,   )
rA   rP   r   r5   r1   	batch_indrS   rT   rU   fg_scores_masks
             r   rJ   zTaskAlignedAssigner.get_targets   s0   4 LLTWWEKK	HXHXYZcd	%	D4D4D(DD!(002=A "r1-m< 	Q ]%8%8%;]=P=PQR=SUYUeUe$f*/+++8+?+?A 	q-"9"9""=qA At,33Aq$:J:JKNQ$6qIm]::r   )   P   g      ?g      @&.>)TN)__name__
__module____qualname____doc__r;   r   no_gradrY   rI   r\   r]   rJ   __classcell__)rB   s   @r   r8   r8   <   sA     U]]_,Z ,Z\
0&*".H-;r   r8   c           	         g g }}| J | d   j                   | d   j                  }}t        |      D ]  \  }}| |   j                  \  }	}	}
}t	        j
                  |||      |z   }t	        j
                  |
||      |z   }t        rt	        j                  ||d      nt	        j                  ||      \  }}|j                  t	        j                  ||fd      j                  dd             |j                  t	        j                  |
|z  df|||              t	        j                  |      t	        j                  |      fS )	zGenerate anchors from features.r   )ra   r$   r#   ij)indexingr   r	   r   r"   )r#   r$   	enumerater   r   re   
TORCH_1_10meshgridappendstackr   fullr   )featsstridesgrid_cell_offsetanchor_pointsstride_tensorr#   r$   istrider   hwsxsys                 r   make_anchorsr      s   #%r=M!HNNE!HOO6Ew'	61X^^
1a\\ae<?OO\\ae<?OO:DB6%..Y[]_J`BU[["b26;;BBCUZZQ
F%PVWX ( 99]#UYY}%===r   c                     | j                  d|      \  }}||z
  }||z   }|r%||z   dz  }||z
  }	t        j                  ||	f|      S t        j                  ||f|      S )z.Transform distance(ltrb) to box(xywh or xyxy).r	   )r   r   r   )
distancer   rb   r
   r   r   x1y1x2y2c_xywhs
             r   	dist2bboxr     sn    ^^As#FB2D2Dtq D[yy$S))99dD\3''r   c                     |j                  dd      \  }}t        j                  | |z
  || z
  fd      j                  d|dz
        S )z#Transform bbox(xyxy) to dist(ltrb).r	   r   r   g{Gz?)r   r   r   rg   )r   bboxreg_maxr   r   s        r   	bbox2distr     sJ    Ar"JD$99md*D=,@A2FMMaQX[_Q_``r   )r   )g      ?)Tr   )r   torch.nnnnchecksr   rv   r   __version__r   r   r6   Moduler8   r   r   r    r   r   <module>r      sR      ! 5,,h7
(&,:z;")) z;z>	(ar   