o
    izK                     @   sV  d dl Z d dlmZ d dlmZ d dlmZ d dlmZm	Z	m
Z
mZmZmZ d dlZd dlZeG dd dZdd	 Zd
eej fddZG dd dZ	dZdejdee dejdejdedejfddZ	dZdejdee dee dedejf
ddZdejdejfddZdede
ee ddf fdd Zd!ejdee	eef  fd"d#Zd$e	eef dejfd%d&Zd!ejdejejffd'd(Z d!ejd)ejd*ejdejejffd+d,Z!d!ejdefd-d.Z"d/efd0d1Z#d!ejdee	eef  fd2d3Z$d$e	eef defd4d5Z%d6ejd7ed8edejfd9d:Z&d;edejfd<d=Z'd;ed>ed?edeej fd@dAZ(dBeedCf d>edDedeeee  ee f fdEdFZ)dejdee dejfdGdHZ*dIejdee dejfdJdKZ+d6ejdee dLedMedejf
dNdOZ,dPejdQedRedeeje-f fdSdTZ.dUe	eef de	eef fdVdWZ/d6ejdejfdXdYZ0dS )[    Ndeepcopy)	dataclass)product)AnyDict	Generator	ItemsViewListTuplec                   @   sB   e Zd ZU ejed< ejed< eed< eed< eed< dd ZdS )	RLEDataalt_lens_ntcounts_initbhwc                 C   s   | j S N)r   self r   R/home/ubuntu/.local/lib/python3.10/site-packages/torchao/_models/sam2/utils/amg.py__len__   s   zRLEData.__len__N)__name__
__module____qualname__torchTensor__annotations__intr   r   r   r   r   r      s   
 

r   c           	      C   s   |   }|  }| }||  }||  }dd t||D }t||j}t	|d|}||j}tj
j||dS )Nc                 S   s   g | ]\}}|t | qS r   )r   arange).0olr   r   r   
<listcomp>#   s    z)nt_index_select_dim_0.<locals>.<listcomp>r   lengths)valuesoffsetsdiffcpuzipr   cattodeviceindex_selectnestednested_tensor_from_jagged)	ntindexr&   r'   r%   offsets_indexlengths_indexindicesvalues_indexr   r   r   nt_index_select_dim_0   s   r7   ntsc                 C   sV   g }g }| D ]}| |  | |   qt|}t|}tjj||dS )Nr$   )appendr&   r'   r(   r   r+   r/   r0   )r8   
all_valuesall_lengthsr1   
new_valuesnew_lengthsr   r   r   nt_cat_dim_0*   s   

r>   c                   @   s   e Zd ZdZdddZdededdfdd	Zdeddfd
dZdedefddZ	de
eef fddZdejddfddZdddZdddZdS )MaskDataz
    A structure for storing masks and their related data in batched format.
    Implements basic filtering and concatenation.
    returnNc                 K   s@   |  D ]}t|ttjtjtfsJ dqtdi || _	d S )N=MaskData only supports list, numpy arrays, and torch tensors.r   )
r&   
isinstancelistnpndarrayr   r   r   dict_stats)r   kwargsvr   r   r   __init__<   s
   zMaskData.__init__keyitemc                 C   s,   t |ttjtjtfsJ d|| j|< d S )NrA   )rB   rC   rD   rE   r   r   r   rG   )r   rK   rL   r   r   r   __setitem__C   s   zMaskData.__setitem__c                 C   s   | j |= d S r   rG   r   rK   r   r   r   __delitem__I   s   zMaskData.__delitem__c                 C   s
   | j | S r   rN   rO   r   r   r   __getitem__L      
zMaskData.__getitem__c                 C   s
   | j  S r   )rG   itemsr   r   r   r   rS   O   rR   zMaskData.itemskeepc                    s   | j  D ]\}d u rd | j |< qttjr!  | j |< qttjr5   	  | j |< qtt
rO jtjkrO fddtD | j |< qtt
rafdd D | j |< qttrtj }t|j  |djjd| j |< qtd| dt dd S )	Nc                    s   g | ]
\}} | r|qS r   r   )r    ia)rT   r   r   r#   \       z#MaskData.filter.<locals>.<listcomp>c                    s   g | ]} | qS r   r   r    rU   )rI   r   r   r#   ^       r   r   r   r   r   r   MaskData key  has an unsupported type .)rG   rS   rB   r   r   rD   rE   detachr)   numpyrC   dtypebool	enumerater   r7   r   r   sizer   r   	TypeErrortype)r   rT   knew_alt_lens_ntr   )rT   rI   r   filterR   s,   

zMaskData.filter	new_statsc                 C   sZ  |  D ]\}}|| jvs| j| d u rt|| j|< qt|tjr2tj| j| |gdd| j|< qt|tjrHtj	| j| |gdd| j|< qt|t
rZ| j| t| | j|< qt|tr| j| j|jksjJ | j| j|jksuJ tt| j| j|jgt| j| j|jg| j| j|j |j|jd| j|< qtd| dt| dd S )Nr   dimaxisrZ   r[   r\   r]   )rS   rG   r   rB   r   r   r+   rD   rE   concatenaterC   r   r   r   r>   r   r   r   rd   re   )r   ri   rf   rI   r   r   r   r+   k   s.     


zMaskData.catc                 C   s>   | j  D ]\}}t|tjr|    | j |< qd S r   )	rG   rS   rB   r   r   floatr^   r)   r_   )r   rf   rI   r   r   r   to_numpy   s
   zMaskData.to_numpy)r@   N)ri   r?   r@   N)r   r   r   __doc__rJ   strr   rM   rP   rQ   r	   rS   r   r   rh   r+   rp   r   r   r   r   r?   6   s    

r?         4@boxescrop_boxcrop_box_torchorig_box_torchatolr@   c                 C   sf   t | | } tj| |dddf |dd}tj| |dddf |dd}t|| }tj|ddS )zNFilter masks at the edge of a crop, but not at the edge of the original image.Nr   )rx   rtol   rj   )uncrop_boxes_xyxyro   r   iscloselogical_andany)rt   ru   rv   rw   rx   near_crop_edgenear_image_edger   r   r   is_box_near_crop_edge_torch   s
   r   orig_boxc                 C   s8   t j|t j| jd}t j|t j| jd}t| ||||S )Nr`   r-   )r   	as_tensorro   r-   r   )rt   ru   r   rx   rv   rw   r   r   r   is_box_near_crop_edge   s
   
r   box_xyxyc                 C   s4   t | }|d |d  |d< |d |d  |d< |S )N   r      rz   r   )r   box_xywhr   r   r   box_xyxy_to_xywh   s   r   
batch_sizec                 '   s|    t  dkrt fdd D sJ dt  d  tt  d  dk }t|D ]fdd D V  q.d S )Nr   c                 3   s$    | ]}t |t  d  kV  qdS )r   N)len)r    rV   )argsr   r   	<genexpr>   s   " z!batch_iterator.<locals>.<genexpr>z8Batched iteration must have inputs of all the same size.c                    s$   g | ]}|   d    qS rz   r   )r    arg)r   r   r   r   r#      s   $ z"batch_iterator.<locals>.<listcomp>)r   allr   range)r   r   	n_batchesr   )r   r   r   r   batch_iterator   s   $(r   tensorc              
   C   s  | j \}}}| dddd} | ddddf | ddddf A }| }g }t|D ]\}||dddf |kdf }ttjdg|j|j	d|d tj|| g|j|j	dg}|dd |dd  }	| |df dkrrg ndg}
|

|	    |||g|
d q.|S )[
    Encodes masks to an uncompressed RLE, in the format expected by
    pycoco tools.
    r   r   rz   Nr   rc   counts)shapepermuteflattennonzeror   r   r+   r   r`   r-   extendr^   r)   tolistr9   )r   r   r   r   r(   change_indicesoutrU   cur_idxsbtw_idxsr   r   r   r   mask_to_rle_pytorch   s$   (r   rlec                 C   sh   | d \}}t j|| td}d}d}| d D ]}||||| < ||7 }|dN }q|||}| S )z/Compute a binary mask from an uncompressed RLE.rc   r`   r   Fr   T)rD   emptyra   reshape	transpose)r   r   r   maskidxparitycountr   r   r   rle_to_mask   s   
r   c                 C   s   | j \}}}| dddd} | ddddf | ddddf A }tjdt|jd}||ddd}tj	|||gdd}|S )	r   r   r   rz   Nr   )rz   rz   r   rj   )
r   r   r   r   onesra   r-   	expand_asnarrowr+   )r   r   r   r   r(   rV   r   r   r   _mask_to_rle_pytorch_2_0_0   s   (r   r(   r   c           
      C   s   |  dddd} |jdd}|d d df }| dkr#|}|}n|dd|dd }|ddd}t||g}|| }tjj	||d}| d d df dk}	||	fS )Nr   r   rz   rj   r$   )
r   r   sumnumelr   rc   r   r+   r/   r0   )
r   r(   r   alt_lensall_cur_idxall_cur_idx_0all_cur_idx_1all_btw_idxr   r   r   r   r   _mask_to_rle_pytorch_2_0_1   s   r   c           	      C   s   | j \}}}tjjd t| }W d    n1 sw   Y  tjjd% d}|| d d ks9J dtdd ||D }W d    n1 sPw   Y  tjjd t	| ||\}}W d    n1 sow   Y  t
|||||d	S )
Nz1mask_to_rle_pytorch_2: _mask_to_rle_pytorch_2_0_0zmask_to_rle_pytorch_2: nonzero   iz!Needed more chunks than expected.c                 S   s   g | ]}|  qS r   )r   )r    dr   r   r   r#     rY   z,_mask_to_rle_pytorch_2_0.<locals>.<listcomp>z1mask_to_rle_pytorch_2: _mask_to_rle_pytorch_2_0_1rZ   )r   r   autogradprofilerrecord_functionr   r   r+   chunkr   r   )	r   r   r   r   r(   
num_chunksr   r   r   r   r   r   _mask_to_rle_pytorch_2_0  s*   

r   rle_datac           
      C   s   t jjd_ g }| j  }| j }| }| }| j	 }d}t
t| j|D ]0\}}|||||   d d }||| 7 }|rIg ndg}	|	| || j| jg|	d q-W d    |S 1 siw   Y  |S )Nz(mask_to_rle_pytorch_2: Encode run lengthr   r   r   )r   r   r   r   r   r'   r(   r&   r   r   r*   r   r   r   r9   r   r   )
r   r   r   r   r   offsetrU   cir   r   r   r   r   _mask_to_rle_pytorch_2_1)  s*   



r   c                 C   s>   t jjd tt| W  d    S 1 sw   Y  d S )Nmask_to_rle_pytorch_2)r   r   r   r   r   r   )r   r   r   r   r   >  s   
$r   c                 C   s   t | d dd d S )Nr   rz   r   )r   )r   r   r   r   area_from_rleC  s   r   masksmask_thresholdthreshold_offsetc                 C   sP   | || kj dtjdj dtjd}| || kj dtjdj dtjd}|| S )z
    Computes the stability score for a batch of masks. The stability
    score is the IoU between the binary masks obtained by thresholding
    the predicted mask logits at high and low values.
    r   r   )r   r   int16int32)r   r   r   intersectionsunionsr   r   r   calculate_stability_scoreI  s   

r   
n_per_sidec                 C   st   dd|   }t |d| | }t |dddf | df}t |dddf d| f}t j||gdddd}|S )z;Generates a 2D grid of points evenly spaced in [0,1]x[0,1].rz   r   Nr   rl   )rD   linspacetilestackr   )r   r   points_one_sidepoints_xpoints_ypointsr   r   r   build_point_grid`  s   r   n_layersscale_per_layerc                 C   s8   g }t |d D ]}t| ||  }|t| q|S )z*Generates point grids for all crop layers.rz   )r   r   r9   r   )r   r   r   points_by_layerrU   n_pointsr   r   r   build_all_layer_point_gridsj  s
   r   im_size.overlap_ratioc                    s
  g g }}| \}}t ||}|dd||g |d dd }t|D ]\}	d|	d  }
t|| d|
  |||
|||
 fddt|
D } fddt|
D }t||D ] \}}||t | |t |  |g}|| ||	d  q_q$||fS )	zr
    Generates a list of crop boxes of different sizes. Each layer
    has (2**i)**2 boxes for the ith layer.
    r   c                 S   s   t t||d  |  | S )Nrz   )r   mathceil)orig_lenn_cropsoverlapr   r   r   crop_len  s   z%generate_crop_boxes.<locals>.crop_lenr   rz   c                       g | ]
}t   | qS r   r   rX   )crop_wr   r   r   r#     rW   z'generate_crop_boxes.<locals>.<listcomp>c                    r   r   r   rX   )crop_hr   r   r   r#     rW   )minr9   r   r   r   )r   r   r   
crop_boxes
layer_idxsim_him_w
short_sider   i_layern_crops_per_sidecrop_box_x0crop_box_y0x0y0boxr   )r   r   r   r   generate_crop_boxesu  s&   


 
r   c                 C   sT   |\}}}}t ||||gg }|j| jdd}t| jdkr&|d}| | S NT)r-   non_blockingr   rz   r   r   
pin_memoryr,   r-   r   r   	unsqueeze)rt   ru   r   r   _r   r   r   r   r{     s   
r{   r   c                 C   sP   |\}}}}t ||gg }|j| jdd}t| jdkr$|d}| | S r   r   )r   ru   r   r   r   r   r   r   r   uncrop_points  s   
r   orig_horig_wc                 C   sr   |\}}}}|dkr|dkr||kr||kr| S |||  |||  }}	||| ||	| f}
t jjj| |
ddS )Nr   )value)r   nn
functionalpad)r   ru   r   r  r   r   x1y1pad_xpad_yr  r   r   r   uncrop_masks  s    r
  r   area_threshmodec                    s   ddl }|dv s
J |dk}|| A tj}||d\}}}}	|dddf dd }
 fdd	t|
D }t|dkrA| d
fS dg| |scfdd	t|D tdkrctt	|
d gt
|} | dfS )z
    Removes small disconnected regions and holes in a mask. Returns the
    mask and an indicator of if the mask has been modified.
    r   N)holesislandsr  r   r   rz   c                    s    g | ]\}}| k r|d  qS r   r   )r    rU   s)r  r   r   r#     s     z(remove_small_regions.<locals>.<listcomp>Fc                    s   g | ]}| vr|qS r   r   rX   )fill_labelsr   r   r#     s    T)cv2astyperD   uint8connectedComponentsWithStatsrb   r   r   r   argmaxisin)r   r  r  r  correct_holesworking_maskn_labelsregionsstatsr   sizessmall_regionsr   )r  r  r   remove_small_regions  s    
r  uncompressed_rlec                 C   s<   ddl m} | d \}}|| ||}|d d|d< |S )Nr   )r   rc   r   zutf-8)pycocotoolsr   frPyObjectsdecode)r  
mask_utilsr   r   r   r   r   r   coco_encode_rle  s
   r$  c                 C   sp  | j }|dd \}}t|dkr| dd} n| d} tj| dd\}}|tj||jddddf  }tj|dd\}}|||   }tj|dd\}}tj| dd\}	}|	tj||	jddddf  }
tj|
dd\}}|
||	   }
tj|
dd\}}||k ||k B }tj	||||gdd}|| d }t|dkr|j
g |dd d	R  }|S |d }|S )
z
    Calculates boxes in XYXY format around masks. Return [0,0,0,0] for
    an empty mask. For input shape C1xC2x...xHxW, the output shape is C1xC2x...x4.
    Nr   r   r   rj   )r-      )r   r   r   r   r   maxr   r-   r   r   r   )r   r   r   r   	in_heightr   in_height_coordsbottom_edges	top_edgesin_widthin_width_coordsright_edges
left_edgesempty_filterr   r   r   r   batched_mask_to_box  s.   

  r2  )rs   )1r   copyr   dataclassesr   	itertoolsr   typingr   r   r   r	   r
   r   r_   rD   r   r   r7   r   r>   r?   r   ro   r   r   r   r   rr   r   rE   r   r   r   r   r   r   r   r   r   r   r   r{   r   r
  ra   r  r$  r2  r   r   r   r   <module>   s    Y


  	

 




%



"