U
    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ee ee ejej
edd	d
Zejej
dddZee dddZeee  eee  ee dddZeee ee d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sN|ft| }| _| _ fddt||D  _	d S )Nr   c                 s   s   | ]}|fV  qd S )N ).0sr   r   [/var/www/html/venv/lib/python3.8/site-packages/torchvision/models/detection/anchor_utils.py	<genexpr>,   s     z+AnchorGenerator.__init__.<locals>.<genexpr>c                    s   g | ]\}}  ||qS r   )generate_anchors)r   sizeZ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(   Zh_ratiosZw_ratioswshsbase_anchorsr   r   r   r   :   s    
&&z AnchorGenerator.generate_anchorsr*   c                    s    fdd| j D | _ d S )Nc                    s   g | ]}|j  d qS )r*   )to)r   Zcell_anchorr(   r'   r   r   r   M   s     z4AnchorGenerator.set_cell_anchors.<locals>.<listcomp>)r	   )r   r'   r(   r   r9   r   set_cell_anchorsL   s    z AnchorGenerator.set_cell_anchorsr)   c                 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   s     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stridesr)   c              	   C   s  g }| j }t|d k	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
 qR|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Zindexingr+   r   r,      )r	   r/   Z_assertr   r"   r(   arangeZint32meshgridreshaper3   appendr2   )r   r?   r@   anchorsr	   r   Zstrider7   Zgrid_heightZ
grid_widthZstride_heightZstride_widthr(   shifts_xshifts_yshift_yshift_xshiftsr   r   r   grid_anchorsT   s&    "

,zAnchorGenerator.grid_anchors
image_listfeature_mapsr)   c           
         s   dd |D }|j jdd  |d j|d j }  fdd|D }| |  | ||}g }tt|jD ]}dd |D }	|	|	 qrdd |D }|S )Nc                 S   s   g | ]}|j d d qS Nshaper   Zfeature_mapr   r   r   r   t   s     z+AnchorGenerator.forward.<locals>.<listcomp>rS   r   c                    sT   g | ]L}t jd t j dd |d  t jd t j dd |d  gqS )r   r*   r   r   )r/   emptyZint64Zfill_)r   gr(   
image_sizer   r   r   w   s   ""c                 S   s   g | ]}|qS r   r   )r   Zanchors_per_feature_mapr   r   r   r      s     c                 S   s   g | ]}t |qS r   )r/   cat)r   Zanchors_per_imager   r   r   r      s     )
tensorsrU   r'   r(   r:   rN   ranger   image_sizesrG   )
r   rP   rQ   r?   r'   r@   Zanchors_over_all_feature_mapsrH   _Zanchors_in_imager   rY   r   forwards   s    zAnchorGenerator.forward)r
   r   )__name__
__module____qualname____doc__r   r/   r   __annotations__r   float32r(   intfloatr'   r   r:   r>   rN   r   r`   __classcell__r   r   r#   r   r   
   s(      &r   c                       s   e Zd ZdZdeee  eeeee  eee  ed fddZ	e
je
d	fee
je
jee d
ddZee dddZe
jfeee  ee e
jedddZedddZeee ee d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??NT)r!   	min_ratio	max_ratior&   stepsclipc                    s   t    |d k	r*t|t|kr*td|| _|| _|| _t||d krdkr|   fddtD | _| j	d q |g| _n|| _| 
| _d S )Nz3aspect_ratios and steps should have the same lengthr   c                    s    g | ]} | d    qS )r   r   )r   krm   num_outputsZrange_ratior   r   r      s     z0DefaultBoxGenerator.__init__.<locals>.<listcomp>r   )r   r   r   
ValueErrorr!   ro   rp   r]   r&   rG   _generate_wh_pairs	_wh_pairs)r   r!   rm   rn   r&   ro   rp   r#   rr   r   r      s    	
zDefaultBoxGenerator.__init__r%   )rs   r'   r(   r)   c                 C   s   g }t |D ]}| j| }t| j| | j|d   }||g||gg}| j| D ]@}	t|	}
| j| |
 }| j| |
 }|||g||gg qR|tj|||d q|S )Nr   r*   )	r]   r&   mathr1   r!   extendrG   r/   r0   )r   rs   r'   r(   rv   rq   Zs_kZ	s_prime_kwh_pairsarZsq_arwhr   r   r   ru      s    

z&DefaultBoxGenerator._generate_wh_pairsr;   c                 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   r>      s    z,DefaultBoxGenerator.num_anchors_per_location)r?   rZ   r'   r)   c                 C   sF  g }t |D ](\}}| jd k	rF|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'   rA   rB   r+   r,   r.   )minmax)	enumeratero   r/   rD   r8   rE   rF   r3   r   rv   rp   clamprepeatr[   rG   )r   r?   rZ   r'   default_boxesrq   Zf_kZx_f_kZy_f_krI   rJ   rK   rL   rM   Z_wh_pairry   Z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$   ra   r!   rp   r&   ro   )r   r   r   r   r   __repr__   s    ,zDefaultBoxGenerator.__repr__rO   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 ]z}
|}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
}|
| qt|S )Nc                 S   s   g | ]}|j d d qS rR   rT   rV   r   r   r   r      s     z/DefaultBoxGenerator.forward.<locals>.<listcomp>rS   r   r~   r   )r(   r.   r   r+   )r\   rU   r'   r(   r   r8   r/   Ztensorr^   r[   rG   )r   rP   rQ   r?   rZ   r'   r(   r   ZdboxesZx_y_sizer_   Zdboxes_in_imager   r   r   r`      s"    

..zDefaultBoxGenerator.forward)rk   rl   NNT)ra   rb   rc   rd   r   rg   rh   r   boolr   r/   rf   r(   r'   r   ru   r>   r   strr   r   r`   ri   r   r   r#   r   rj      s@        


   
  rj   )rw   typingr   r   r/   r   r   rP   r   Moduler   rj   r   r   r   r   <module>   s   ~