o
    isF                     @  s$  d dl mZ d dlmZ d dlmZ d dlZd dlZd dl	m
Z
mZmZ d dlmZmZmZ d dlmZ d dlmZ d d	lmZ d d
lmZmZ d dlmZmZ dGdHddZdIddZdJddZdKd!d"Z 	dLdMd&d'Z!	(	)dNdOd.d/Z"d(ej#ej$fdPd5d6Z%dQd:d;Z&dRd>d?Z'	AdSdTdEdFZ(dS )U    )annotations)Sequence)deepcopyN)	DtypeLikeNdarrayOrTensorNdarrayTensor)COMPUTE_DTYPE	TO_REMOVEget_spatial_dims)Resize)create_scale)look_up_option)ensure_tupleensure_tuple_rep)convert_data_typeconvert_to_dst_typeTpointstorch.Tensoraffineinclude_shiftboolreturnc                 C  s   t | d}|r6tj| tj| jd d| j| jdgdddd}t||}|d|ddf dd}|S | dd}t|d|d|f |}|dd}|S )a  
    This internal function applies affine matrices to the point coordinate

    Args:
        points: point coordinates, Nx2 or Nx3 torch tensor or ndarray, representing [x, y] or [x, y, z]
        affine: affine matrix to be applied to the point coordinates, sized (spatial_dims+1,spatial_dims+1)
        include_shift: default True, whether the function apply translation (shift) in the affine transform

    Returns:
        transformed point coordinates, with same data type as ``points``, does not share memory with ``points``
    )r   r      )devicedtypedimN)	r
   torchcatonesshaper   r   	transposematmul)r   r   r   spatial_dimsZpoints_affine r$   i/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/apps/detection/transforms/box_ops.py_apply_affine_to_points   s   
 r&   boxesr   r   c                 C  s   t | tj^}}|jtd}t||d^}}t|d}t|ddd|f |dd}t|dd|df |dd}tjtj	||gdddd\}}tj
tj	||gdddd\}	}tj||	gd	d}
t|
| d^}}|S )
a  
    This function applies affine matrices to the boxes

    Args:
        boxes: bounding boxes, Nx4 or Nx6 torch tensor or ndarray. The box mode is assumed to be StandardMode
        affine: affine matrix to be applied to the box coordinates, sized (spatial_dims+1,spatial_dims+1)

    Returns:
        returned affine transformed boxes, with same data type as ``boxes``, does not share memory with ``boxes``
    r   srcdstr'   NT)r      r   r   )r   r   Tensortor   r   r
   r&   minstackmaxr   )r'   r   boxes_t_Zaffine_tr#   ltrbZlt_newZrb_newZboxes_t_affineZboxes_affiner$   r$   r%   apply_affine_to_boxes>   s   
  r7   zoomSequence[float] | floatc                 C  s"   t | d}t||d}t| |dS )al  
    Zoom boxes

    Args:
        boxes: bounding boxes, Nx4 or Nx6 torch tensor or ndarray. The box mode is assumed to be StandardMode
        zoom: The zoom factor along the spatial axes.
            If a float, zoom is the same for each spatial axis.
            If a sequence, zoom should contain one value for each spatial axis.

    Returns:
        zoomed boxes, with same data type as ``boxes``, does not share memory with ``boxes``

    Example:
        .. code-block:: python

            boxes = torch.ones(1,4)
            zoom_boxes(boxes, zoom=[0.5,2.2]) #  will return tensor([[0.5, 2.2, 0.5, 2.2]])
    r,   )r#   scaling_factor)r'   r   )r
   r   r7   )r'   r8   r#   r   r$   r$   r%   
zoom_boxesf   s   
r;   src_spatial_sizeSequence[int] | intdst_spatial_sizec                   sB   t | d}t|t |  fddt|D }t| |dS )a  
    Resize boxes when the corresponding image is resized

    Args:
        boxes: source bounding boxes, Nx4 or Nx6 torch tensor or ndarray. The box mode is assumed to be ``StandardMode``
        src_spatial_size: source image spatial size.
        dst_spatial_size: target image spatial size.

    Returns:
        resized boxes, with same data type as ``boxes``, does not share memory with ``boxes``

    Example:
        .. code-block:: python

            boxes = torch.ones(1,4)
            src_spatial_size = [100, 100]
            dst_spatial_size = [128, 256]
            resize_boxes(boxes, src_spatial_size, dst_spatial_size) #  will return tensor([[1.28, 2.56, 1.28, 2.56]])
    r,   c                   s    g | ]} | t |  qS r$   )float.0axisr>   r<   r$   r%   
<listcomp>   s     z resize_boxes.<locals>.<listcomp>)r'   r8   )r
   r   ranger;   )r'   r<   r>   r#   r8   r$   rC   r%   resize_boxes   s
   


rF   spatial_size	flip_axesSequence[int] | int | Nonec                 C  s   t | d}t||}|du rttd|}t|}t| tjr#|  nt	| }|D ].}|| | dd|f  t
 |dd|| f< || | dd|| f  t
 |dd|f< q)|S )a  
    Flip boxes when the corresponding image is flipped

    Args:
        boxes: bounding boxes, Nx4 or Nx6 torch tensor or ndarray. The box mode is assumed to be ``StandardMode``
        spatial_size: image spatial size.
        flip_axes: spatial axes along which to flip over. Default is None.
            The default `axis=None` will flip over all of the axes of the input array.
            If axis is negative it counts from the last to the first axis.
            If axis is a tuple of ints, flipping is performed on all of the axes
            specified in the tuple.

    Returns:
        flipped boxes, with same data type as ``boxes``, does not share memory with ``boxes``
    r,   Nr   )r
   r   tuplerE   r   
isinstancer   r.   cloner   r	   )r'   rG   rH   r#   Z_flip_boxesrB   r$   r$   r%   
flip_boxes   s   

,.rM   Flabelsbg_labelintellipse_maskc                   sR  t | dt|}|jd dkr,tjd| tjdt| }t|| tjd^}}|S |t|kr>t	dt| d| |jd | jd krLt	dtj|jd f| tjdt| }t
| tjtjdd td	d	d	f t|krt	d
t|d^}}tjd D ]  fddtD }	|rt|	d }
d d tjg tjdt| }tfddtD }tfddtj| D }t|  |||
d k< t|	ddd}||d	 d }ntj|	tjdt|   } g}| fddtD  ||t|< qt|| tjdd S )au  
    Convert box to int16 mask image, which has the same size with the input image.

    Args:
        boxes: bounding boxes, Nx4 or Nx6 torch tensor or ndarray. The box mode is assumed to be ``StandardMode``.
        labels: classification foreground(fg) labels corresponding to `boxes`, dtype should be int, sized (N,).
        spatial_size: image spatial size.
        bg_label: background labels for the output mask image, make sure it is smaller than any fg labels.
        ellipse_mask: bool.

            - If True, it assumes the object shape is close to ellipse or ellipsoid.
            - If False, it assumes the object shape is close to rectangle or cube and well occupies the bounding box.
            - If the users are going to apply random rotation as data augmentation, we suggest setting ellipse_mask=True
              See also Kalra et al. "Towards Rotation Invariance in Object Detection", ICCV 2021.

    Return:
        - int16 array, sized (num_box, H, W). Each channel represents a box.
            The foreground region in channel c has intensity of labels[c].
            The background intensity is bg_label.
    r,   r   )r   r(   r*   r+   r   zGbg_label should be smaller than any foreground box labels.
min(labels)=z, while bg_label=z1Number of labels should equal to number of boxes.Nz%Some boxes are larger than the image.r)   c                   s(   g | ]} | f  |f  qS r$   r$   r@   bboxes_npr#   r$   r%   rD      s   ( z'convert_box_to_mask.<locals>.<listcomp>g       @r   c                 3  s    | ]}t d  V  qdS )r   Nslice)rA   r4   )max_box_sizer$   r%   	<genexpr>  s    z&convert_box_to_mask.<locals>.<genexpr>c                 3  s    | ]	}|  d  V  qdS )r-   Nr$   )rA   grid)centerr$   r%   rZ     s    r-   nearestF)rG   modeanti_aliasingc                 3  s.    | ]}t  |f  | f V  qd S NrW   )rA   drT   r$   r%   rZ     s   , )r
   r   r    npr   int16r   r   r0   
ValueErrorr   ndarrayint32anyarrayrE   r2   rJ   sumogridr   extend)r'   rO   rG   rP   rR   boxes_mask_np
boxes_maskr4   	labels_npbox_sizeradiusZboxes_only_maskrangesdist_from_centerresizerZslicingr$   )rU   rV   r\   rY   r#   r%   convert_box_to_mask   sL   

&$  rt   rm   	box_dtypeDtypeLike | torch.dtypelabel_dtype'tuple[NdarrayOrTensor, NdarrayOrTensor]c              	   C  s  t t| jddg t| jdd }t|d}t| tj^}}g }g }	t|jd D ]k}
t	||
df | }|d jd dkrBq+g }|D ]	}|
t| qF|D ]}|
t|d t  qR|
| |dkr{|	
||
|d d |d d f  |dkr|	
||
|d d |d d |d d f  q+t|dkrtdd| gtdg}}nt|t|	}}t|| |d	^}}t|| |d	^}}||fS )
a  
    Convert int16 mask image to box, which has the same size with the input image

    Args:
        boxes_mask: int16 array, sized (num_box, H, W). Each channel represents a box.
            The foreground region in channel c has intensity of labels[c].
            The background intensity is bg_label.
        bg_label: background labels for the boxes_mask
        box_dtype: output dtype for boxes
        label_dtype: output dtype for labels

    Return:
        - bounding boxes, Nx4 or Nx6 torch tensor or ndarray. The box mode is assumed to be ``StandardMode``.
        - classification foreground(fg) labels, dtype should be int, sized (N,).
          r   N)rG   r   .r-   rS   )r   lenr    listr
   r   rb   re   rE   nonzeroappendr0   r2   r	   zerosasarrayr   )rm   rP   ru   rw   rG   r#   rl   r4   
boxes_listZlabels_listrU   
fg_indicesZboxes_bZfd_irV   rn   r'   rO   r$   r$   r%   convert_mask_to_box  s6   

$."r   +Sequence[NdarrayOrTensor] | NdarrayOrTensorkeeptuple | NdarrayOrTensorc                 C  s|   t | d}g }t|tjd }|D ]}t|tjd }||df }|t||dd  qt| tjtjfr:|d S t	|S )au  
    For element in labels, select indices keep from it.

    Args:
        labels: Sequence of array. Each element represents classification labels or scores
            corresponding to ``boxes``, sized (N,).
        keep: the indices to keep, same length with each element in labels.

    Return:
        selected labels, does not share memory with original labels.
    Tr   .r)   )
r   r   r   r.   r~   r   rK   rb   re   rJ   )rO   r   Zlabels_tupleZlabels_select_listkeep_titemlabels_tr$   r$   r%   select_labelsH  s   
r   axis1axis2c                 C  s   t | d}t| tjr|  }nt| }|dd||gf |dd||gf< |dd|| || gf |dd|| || gf< |S )a  
    Interchange two axes of boxes.

    Args:
        boxes: bounding boxes, Nx4 or Nx6 torch tensor or ndarray. The box mode is assumed to be ``StandardMode``
        axis1: First axis.
        axis2: Second axis.

    Returns:
        boxes with two axes interchanged.

    r,   N)r
   rK   r   r.   rL   r   )r'   r   r   r#   Z
boxes_swapr$   r$   r%   swapaxes_boxese  s   

$r   r   r   r   kaxestuple[int, int]c                 C  s`  t | d}tt||}t|}t|dkrtd|d |d ks.t|d |d  |kr2td|d |ksL|d | k sL|d |ksL|d | k rWtd| d| d	|d
; }|dkra| S |dkrstt| ||d ||d S |dkrt| ||d }t||d |d S t| |d |d }||d  ||d  ||d < ||d < t|||d S )a@  
    Rotate boxes by 90 degrees in the plane specified by axes.
    Rotation direction is from the first towards the second axis.

    Args:
        boxes: bounding boxes, Nx4 or Nx6 torch tensor or ndarray. The box mode is assumed to be ``StandardMode``
        spatial_size: image spatial size.
        k : number of times the array is rotated by 90 degrees.
        axes: (2,) array_like
            The array is rotated in the plane defined by the axes. Axes must be different.

    Returns:
        A rotated view of `boxes`.

    Notes:
        ``rot90_boxes(boxes, spatial_size, k=1, axes=(1,0))``  is the reverse of
        ``rot90_boxes(boxes, spatial_size, k=1, axes=(0,1))``
        ``rot90_boxes(boxes, spatial_size, k=1, axes=(1,0))`` is equivalent to
        ``rot90_boxes(boxes, spatial_size, k=-1, axes=(0,1))``
    r,   r-   zlen(axes) must be 2.r   r   zAxes must be different.zAxes=z  out of range for array of ndim=.rz   )	r
   r|   r   r   r{   rd   absrM   r   )r'   rG   r   r   r#   spatial_size_Zboxes_r$   r$   r%   rot90_boxes  s(   
(4*r   )T)r   r   r   r   r   r   r   r   )r'   r   r   r   r   r   )r'   r   r8   r9   r   r   )r'   r   r<   r=   r>   r=   r   r   r`   )r'   r   rG   r=   rH   rI   r   r   )rN   F)r'   r   rO   r   rG   r=   rP   rQ   rR   r   r   r   )
rm   r   rP   rQ   ru   rv   rw   rv   r   rx   )rO   r   r   r   r   r   )r'   r   r   rQ   r   rQ   r   r   )r   r   )
r'   r   rG   r=   r   rQ   r   r   r   r   ))
__future__r   collections.abcr   copyr   numpyrb   r   monai.config.type_definitionsr   r   r   monai.data.box_utilsr   r	   r
   monai.transformsr   monai.transforms.utilsr   monai.utilsr   monai.utils.miscr   r   monai.utils.type_conversionr   r   r&   r7   r;   rF   rM   rt   float32longr   r   r   r   r$   r$   r$   r%   <module>   s:   
!
(
!&R
5
