o
    VhS.                     @   sd   d dl Z d dlmZmZ d dl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dS )
    N)ListOptional)nnTensor   )	ImageListc                       s   e Zd ZdZdeej iZ		d fdd	Zej	e
dfdee d	ee d
ejdej
def
ddZd
ejdej
fddZdee fddZdeee  deee  dee fddZdedee dee fddZ  ZS )AnchorGeneratora  
    Module that generates anchors for a set of feature maps and
    image sizes.

    The module support computing anchors at multiple sizes and aspect ratios
    per feature map. This module assumes aspect ratio = height / width for
    each anchor.

    sizes and aspect_ratios should have the same number of elements, and it should
    correspond to the number of feature maps.

    sizes[i] and aspect_ratios[i] can have an arbitrary number of elements,
    and AnchorGenerator will output a set of sizes[i] * aspect_ratios[i] anchors
    per spatial location for feature map i.

    Args:
        sizes (Tuple[Tuple[int]]):
        aspect_ratios (Tuple[Tuple[float]]):
    cell_anchors)      i   )      ?      ?g       @c                    sx   t    t|d ttfstdd |D }t|d ttfs'|ft| }| _| _ fddt||D  _	d S )Nr   c                 s   s    | ]}|fV  qd S )N ).0sr   r   ]/var/www/vscode/kcb/lib/python3.10/site-packages/torchvision/models/detection/anchor_utils.py	<genexpr>,   s    z+AnchorGenerator.__init__.<locals>.<genexpr>c                    s   g | ]
\}}  ||qS r   )generate_anchors)r   sizeaspect_ratioselfr   r   
<listcomp>2   s    z,AnchorGenerator.__init__.<locals>.<listcomp>)
super__init__
isinstancelisttuplelensizesaspect_ratioszipr	   )r   r!   r"   	__class__r   r   r   #   s   

zAnchorGenerator.__init__cpuscalesr"   dtypedevicereturnc           
      C   s   t j|||d}t j|||d}t |}d| }|d d d f |d d d f  d}|d d d f |d d d f  d}t j| | ||gddd }	|	 S )Nr(   r)   r   dim   )torch	as_tensorsqrtviewstackround)
r   r'   r"   r(   r)   h_ratiosw_ratioswshsbase_anchorsr   r   r   r   :   s   
&&z AnchorGenerator.generate_anchorsc                    s    fdd| j D | _ d S )Nc                    s   g | ]	}|j  d qS )r+   )to)r   cell_anchorr)   r(   r   r   r   M       z4AnchorGenerator.set_cell_anchors.<locals>.<listcomp>)r	   )r   r(   r)   r   r=   r   set_cell_anchorsL   s   z AnchorGenerator.set_cell_anchorsc                 C   s   dd t | j| jD S )Nc                 S   s    g | ]\}}t |t | qS r   r    )r   r   ar   r   r   r   P        z<AnchorGenerator.num_anchors_per_location.<locals>.<listcomp>)r#   r!   r"   r   r   r   r   num_anchors_per_locationO   s   z(AnchorGenerator.num_anchors_per_location
grid_sizesstridesc              	   C   s  g }| j }t|d ud tt|t|  kot|kn  d t|||D ]\\}}}|\}}	|\}
}|j}tjd|	tj|d| }tjd|tj|d|
 }tj||dd\}}|	d}|	d}tj
||||fdd	}||ddd
|ddd
 	dd
 q)|S )Nzcell_anchors should not be NonezAnchors should be Tuple[Tuple[int]] because each feature map could potentially have different sizes and aspect ratios. There needs to be a match between the number of feature maps passed and the number of sizes / aspect ratios specified.r   r+   ijindexingr,   r   r-      )r	   r0   _assertr    r#   r)   arangeint32meshgridreshaper4   appendr3   )r   rD   rE   anchorsr	   r   strider:   grid_height
grid_widthstride_heightstride_widthr)   shifts_xshifts_yshift_yshift_xshiftsr   r   r   grid_anchorsT   s&   "

,zAnchorGenerator.grid_anchors
image_listfeature_mapsc           
         s   dd |D }|j jdd  |d j|d j}  fdd|D }| |  | ||}g }tt|jD ]}dd |D }	|	|	 q9dd |D }|S )Nc                 S      g | ]	}|j d d qS Nshaper   feature_mapr   r   r   r   t   r>   z+AnchorGenerator.forward.<locals>.<listcomp>r`   r   c                    sT   g | ]&}t jd t j dd |d  t jd t j dd |d  gqS )r   r+   r   r   )r0   emptyint64fill_)r   gr)   
image_sizer   r   r   w   s    ""c                 S   s   g | ]}|qS r   r   )r   anchors_per_feature_mapr   r   r   r      s    c                 S   s   g | ]}t |qS r   )r0   cat)r   anchors_per_imager   r   r   r      s    )
tensorsrb   r(   r)   r?   r[   ranger    image_sizesrO   )
r   r\   r]   rD   r(   rE   anchors_over_all_feature_mapsrP   _anchors_in_imager   ri   r   forwards   s   zAnchorGenerator.forward)r
   r   )__name__
__module____qualname____doc__r   r0   r   __annotations__r   float32r)   intfloatr(   r   r?   rC   r[   r   rt   __classcell__r   r   r$   r   r   
   s0    

*&r   c                       s   e Zd ZdZ					d!deee  deded	eee  d
eee  def fddZ	e
je
dfdede
jde
jdee fddZdee fddZe
jfdeee  dee de
jdefddZdefddZdedee dee fdd Z  ZS )"DefaultBoxGeneratora  
    This module generates the default boxes of SSD for a set of feature maps and image sizes.

    Args:
        aspect_ratios (List[List[int]]): A list with all the aspect ratios used in each feature map.
        min_ratio (float): The minimum scale :math:`	ext{s}_{	ext{min}}` of the default boxes used in the estimation
            of the scales of each feature map. It is used only if the ``scales`` parameter is not provided.
        max_ratio (float): The maximum scale :math:`	ext{s}_{	ext{max}}`  of the default boxes used in the estimation
            of the scales of each feature map. It is used only if the ``scales`` parameter is not provided.
        scales (List[float]], optional): The scales of the default boxes. If not provided it will be estimated using
            the ``min_ratio`` and ``max_ratio`` parameters.
        steps (List[int]], optional): It's a hyper-parameter that affects the tiling of default boxes. If not provided
            it will be estimated from the data.
        clip (bool): Whether the standardized values of default boxes should be clipped between 0 and 1. The clipping
            is applied while the boxes are encoded in format ``(cx, cy, w, h)``.
    333333??NTr"   	min_ratio	max_ratior'   stepsclipc                    s   t    |d urt|t|krtd|| _|| _|| _t||d u rIdkrC|   fddtD | _| j	d n	 |g| _n|| _| 
| _d S )Nz3aspect_ratios and steps should have the same lengthr   c                    s    g | ]} | d    qS )r   r   )r   kr   num_outputsrange_ratior   r   r      rB   z0DefaultBoxGenerator.__init__.<locals>.<listcomp>r   )r   r   r    
ValueErrorr"   r   r   ro   r'   rO   _generate_wh_pairs	_wh_pairs)r   r"   r   r   r'   r   r   r$   r   r   r      s   
	zDefaultBoxGenerator.__init__r&   r   r(   r)   r*   c                 C   s   g }t |D ]O}| j| }t| j| | j|d   }||g||gg}| j| D ] }	t|	}
| j| |
 }| j| |
 }|||g||gg q)|tj|||d q|S )Nr   r+   )	ro   r'   mathr2   r"   extendrO   r0   r1   )r   r   r(   r)   r   r   s_k	s_prime_kwh_pairsarsq_arwhr   r   r   r      s   

z&DefaultBoxGenerator._generate_wh_pairsc                 C   s   dd | j D S )Nc                 S   s   g | ]
}d d t |  qS )r/   r@   )r   rr   r   r   r      s    z@DefaultBoxGenerator.num_anchors_per_location.<locals>.<listcomp>)r"   r   r   r   r   rC      s   z,DefaultBoxGenerator.num_anchors_per_locationrD   rj   c                 C   sD  g }t |D ]\}}| jd ur"|d | j|  }|d | j|  }n|\}}td|d d | j|d}	td|d d | j|d}
tj|
|	dd\}}|d}|d}tj||ft| j	|  dddd	}| j
r{| j	| jddd
n| j	| }||d |d  d}tj||fdd}|| qtj|ddS )Nr   r   r   r(   rF   rG   r,   r-   r/   )minmax)	enumerater   r0   rK   r;   rM   rN   r4   r    r   r   clamprepeatrl   rO   )r   rD   rj   r(   default_boxesr   f_kx_f_ky_f_krV   rW   rX   rY   rZ   _wh_pairr   default_boxr   r   r   _grid_default_boxes   s"   
  

($z'DefaultBoxGenerator._grid_default_boxesc              
   C   s2   | j j d| j d| j d| j d| j d
}|S )Nz(aspect_ratios=z, clip=z	, scales=z, steps=))r%   ru   r"   r   r'   r   )r   r   r   r   r   __repr__   s   
zDefaultBoxGenerator.__repr__r\   r]   c              
   C   s   dd |D }|j jdd  }|d j|d j}}| j|||d}||}g }tj|d |d g|jd}	|jD ]=}
|}t	|d d d df d	|d d dd f   |	 |d d d df d	|d d dd f   |	 gd
}|
| q:|S )Nc                 S   r^   r_   ra   rc   r   r   r   r      r>   z/DefaultBoxGenerator.forward.<locals>.<listcomp>r`   r   r   r   )r)   r/   r   r,   )rn   rb   r(   r)   r   r;   r0   tensorrp   rl   rO   )r   r\   r]   rD   rj   r(   r)   r   dboxesx_y_sizerr   dboxes_in_imager   r   r   rt      s"   

..zDefaultBoxGenerator.forward)r   r   NNT)ru   rv   rw   rx   r   r{   r|   r   boolr   r0   rz   r)   r(   r   r   rC   r   strr   r   rt   r}   r   r   r$   r   r~      sV    





&r~   )r   typingr   r   r0   r   r   r\   r   Moduler   r~   r   r   r   r   <module>   s    ~