o
    ‹ÄŽiY  ã                   @  s  d dl mZ 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 d dlmZ d dlmZ d)d*dd„Z			
d)d+dd„Z			
d)d,dd„Z			
d)d-dd„Z			
d)d-dd„Z			
d)d-dd„ZG dd „ d ƒZG d!d"„ d"eƒZG d#d$„ d$eƒZG d%d&„ d&eƒZG d'd(„ d(eƒZdS ).é    )ÚannotationsN)Úbox)ÚSTRtree)Úlogger)ÚObjectPredictionListÚ	has_matchÚmerge_object_prediction_pair)ÚObjectPrediction)Úcheck_requirementsÚIOUç      à?Úpredictionsútorch.tensorÚmatch_metricÚstrÚmatch_thresholdÚfloatc           
      C  s¤   | dd…df   ¡ }| dd…df   ¡ }tj|tjd}t |¡D ]}t ||k¡d }t| | ||ƒ}d||| < q!t |¡d }	|	||	 jddd   ¡ }	|	S )	a°  Apply non-maximum suppression to avoid detecting too many overlapping bounding boxes for a given object.

    Args:
        predictions: (tensor) The location preds for the image
            along with the class predscores, Shape: [num_boxes,5].
        match_metric: (str) IOU or IOS
        match_threshold: (float) The overlap thresh for
            match metric.
    Returns:
        A list of filtered indexes, Shape: [ ,]
    Né   é   )Údtyper   T©Ú
descendingé   )	ÚsqueezeÚtorchÚ
zeros_likeÚboolÚuniqueÚwhereÚnmsÚsortÚtolist)
r   r   r   ÚscoresÚcategory_idsÚ	keep_maskÚcategory_idÚcurr_indicesÚcurr_keep_indicesÚkeep_indices© r)   úT/home/jeff/fluffinator/venv/lib/python3.10/site-packages/sahi/postprocess/combine.pyÚbatched_nms   s   r+   útorch.Tensorc              	   C  sD  | dd…df }| dd…df }| dd…df }| dd…df }| dd…df }|| ||  }g }	t t| ƒƒD ]}
|	 t||
  ¡ ||
  ¡ ||
  ¡ ||
  ¡ ƒ¡ q8tj|dd ¡ }t|	ƒ}g }t	ƒ }|D ]¶}||v rpqi| |¡ |	| }||  ¡ }| 
|¡}|D ]˜}||ks||v r‘q†|| || kršq†|| || krÓ||  ¡ ||  ¡ ||  ¡ ||  ¡ f}||  ¡ ||  ¡ ||  ¡ ||  ¡ f}||krÓq†|	| }| |¡j}|d	krö|||  ¡  | }|dkró|| nd}n|d
krt|||  ¡ ƒ}|dkr|| nd}ntdƒ‚||kr| |¡ q†qi|S )a’  
    Optimized non-maximum suppression for axis-aligned bounding boxes using STRTree.

    Args:
        predictions: (tensor) The location preds for the image along with the class
            predscores, Shape: [num_boxes,5].
        match_metric: (str) IOU or IOS
        match_threshold: (float) The overlap thresh for match metric.

    Returns:
        A list of filtered indexes, Shape: [ ,]
    Nr   r   é   é   r   Tr   r   ÚIOSúInvalid match_metric)ÚrangeÚlenÚappendr   Úitemr   Úargsortr!   r   ÚsetÚqueryÚintersectionÚareaÚminÚ
ValueErrorÚadd)r   r   r   Úx1Úy1Úx2Úy2r"   ÚareasÚboxesÚiÚsorted_idxsÚtreeÚkeepÚ
suppressedÚcurrent_idxÚcurrent_boxÚcurrent_areaÚcandidate_idxsÚcandidate_idxÚcurrent_coordsÚcandidate_coordsÚcandidate_boxr8   ÚunionÚmetricÚsmallerr)   r)   r*   r   '   sv   



üÿ






ü



ü


€Ô.r   Úobject_predictions_as_tensorc                   óŠ   | dd…df   ¡ }i }t |¡D ]1}t ||k¡d }t| | ||ƒ}| ¡ ‰ | ¡ D ]\}}	ˆ | }
‡ fdd„|	D ƒ}|||
< q,q|S )a@  Apply greedy version of non-maximum merging per category to avoid detecting too many overlapping bounding boxes
    for a given object.

    Args:
        object_predictions_as_tensor: (tensor) The location preds for the image
            along with the class predscores, Shape: [num_boxes,5].
        match_metric: (str) IOU or IOS
        match_threshold: (float) The overlap thresh for
            match metric.
    Returns:
        keep_to_merge_list: (Dict[int:List[int]]) mapping from prediction indices
        to keep to a list of prediction indices to be merged.
    Nr   r   c                   ó   g | ]}ˆ | ‘qS r)   r)   ©Ú.0Úcurr_merge_ind©Úcurr_indices_listr)   r*   Ú
<listcomp>®   ó    z&batched_greedy_nmm.<locals>.<listcomp>)r   r   r   r   Ú
greedy_nmmr!   Úitems©rS   r   r   r#   Úkeep_to_merge_listr%   r&   Úcurr_keep_to_merge_listÚ	curr_keepÚcurr_merge_listrF   Ú
merge_listr)   rY   r*   Úbatched_greedy_nmm”   s   
ýre   c              	   C  s^  | dd…df }| dd…df }| dd…df }| dd…df }| dd…df }|| ||  }g }	t t| ƒƒD ]}
|	 t||
  ¡ ||
  ¡ ||
  ¡ ||
  ¡ ƒ¡ q8tj|dd ¡ }t|	ƒ}i }t	ƒ }|D ]Ã}||v rpqi|	| }||  ¡ }| 
|¡}g }|D ]}||ks||v rŽqƒ|| || kr—qƒ|| || krÐ||  ¡ ||  ¡ ||  ¡ ||  ¡ f}||  ¡ ||  ¡ ||  ¡ ||  ¡ f}||krÐqƒ|	| }| |¡j}|d	kró|||  ¡  | }|dkrð|| nd}n|d
krt|||  ¡ ƒ}|dkr
|| nd}ntdƒ‚||kr | |¡ | |¡ qƒdd„ |D ƒ|t|ƒ< qi|S )a  
    Optimized greedy non-maximum merging for axis-aligned bounding boxes using STRTree.

    Args:
        object_predictions_as_tensor: (tensor) The location preds for the image
            along with the class predscores, Shape: [num_boxes,5].
        match_metric: (str) IOU or IOS
        match_threshold: (float) The overlap thresh for match metric.
    Returns:
        keep_to_merge_list: (dict[int, list[int]]) mapping from prediction indices
        to keep to a list of prediction indices to be merged.
    Nr   r   r-   r.   r   Tr   r   r/   r0   c                 S  s   g | ]}t |ƒ‘qS r)   )Úint)rW   Úidxr)   r)   r*   r[     r\   zgreedy_nmm.<locals>.<listcomp>)r1   r2   r3   r   r4   r   r5   r!   r   r6   r7   r8   r9   r:   r;   r<   rf   )rS   r   r   r=   r>   r?   r@   r"   rA   rB   rC   rD   rE   r`   rG   rH   rI   rJ   rK   rd   rL   rM   rN   rO   r8   rP   rQ   rR   r)   r)   r*   r]   ³   sx   



üÿ





ü



ü



€r]   c                   rT   )a*  Apply non-maximum merging per category to avoid detecting too many overlapping bounding boxes for a given object.

    Args:
        object_predictions_as_tensor: (tensor) The location preds for the image
            along with the class predscores, Shape: [num_boxes,5].
        match_metric: (str) IOU or IOS
        match_threshold: (float) The overlap thresh for
            match metric.
    Returns:
        keep_to_merge_list: (Dict[int:List[int]]) mapping from prediction indices
        to keep to a list of prediction indices to be merged.
    Nr   r   c                   rU   r)   r)   rV   rY   r)   r*   r[   ;  r\   zbatched_nmm.<locals>.<listcomp>)r   r   r   r   Únmmr!   r^   r_   r)   rY   r*   Úbatched_nmm"  s   
ýri   c               	   C  sÜ  | dd…df }| dd…df }| dd…df }| dd…df }| dd…df }|| ||  }g }	t t| ƒƒD ]}
|	 t||
  ¡ ||
  ¡ ||
  ¡ ||
  ¡ ƒ¡ q8tj|dd ¡ }t|	ƒ}i }i }|D ]}|	| }||  ¡ }| 	|¡}g }|D ]”}||kr…q~|| || krŽq~|| || krÇ||  ¡ ||  ¡ ||  ¡ ||  ¡ f}||  ¡ ||  ¡ ||  ¡ ||  ¡ f}||krÇq~|	| }| 
|¡j}|d	krê|||  ¡  | }|dkrç|| nd}n|d
krt|||  ¡ ƒ}|dkr|| nd}ntdƒ‚||kr| |¡ q~t|ƒ}||vr;g ||< |D ]}t|ƒ}||vr8||  |¡ |||< q"qh|| }|D ])}t|ƒ}|| |g ¡vri||vri||vr^g ||< ||  |¡ |||< qAqh|S )a  Apply non-maximum merging to avoid detecting too many overlapping bounding boxes for a given object.

    Args:
        object_predictions_as_tensor: (tensor) The location preds for the image
            along with the class predscores, Shape: [num_boxes,5].
        match_metric: (str) IOU or IOS
        match_threshold: (float) The overlap thresh for match metric.
    Returns:
        keep_to_merge_list: (Dict[int:List[int]]) mapping from prediction indices
        to keep to a list of prediction indices to be merged.
    Nr   r   r-   r.   r   Tr   r   r/   r0   )r1   r2   r3   r   r4   r   r5   r!   r   r7   r8   r9   r:   r;   rf   Úget) rS   r   r   r=   r>   r?   r@   r"   rA   rB   rC   rD   rE   r`   Úmerge_to_keeprH   rI   rJ   rK   Úmatched_box_indicesrL   rM   rN   rO   r8   rP   rQ   rR   Úcurrent_idx_nativeÚmatched_box_idxÚmatched_box_idx_nativeÚkeep_idxr)   r)   r*   rh   @  sš   



üÿ






ü



ü


€

€ü

€÷rh   c                   @  s,   e Zd ZdZ			dddd„Zddd„ZdS )ÚPostprocessPredictionszJUtilities for calculating IOU/IOS based match for given ObjectPredictions.r   r   Tr   r   r   r   Úclass_agnosticr   c                 C  s    || _ || _|| _tdgƒ d S )Nr   )r   rr   r   r
   )Úselfr   r   rr   r)   r)   r*   Ú__init__Ä  s   zPostprocessPredictions.__init__r   úlist[ObjectPrediction]c                 C  s   t ƒ ‚)N)ÚNotImplementedError)rs   r   r)   r)   r*   Ú__call__Ð  s   zPostprocessPredictions.__call__N)r   r   T)r   r   r   r   rr   r   )r   ru   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__rt   rw   r)   r)   r)   r*   rq   Á  s    ürq   c                   @  ó   e Zd Zddd„ZdS )ÚNMSPostprocessÚobject_predictionsru   c                 C  s\   t |ƒ}| ¡ }| jrt|| j| jd}n	t|| j| jd}||  ¡ }t|t	ƒs,|g}|S ©N)r   r   )
r   Útotensorrr   r   r   r   r+   r!   Ú
isinstanceÚlist)rs   r~   Úobject_prediction_listÚobject_predictions_as_torchrF   Úselected_object_predictionsr)   r)   r*   rw   Õ  s   
ÿ
ÿ
zNMSPostprocess.__call__N©r~   ru   ©rx   ry   rz   rw   r)   r)   r)   r*   r}   Ô  ó    r}   c                   @  r|   )ÚNMMPostprocessr~   ru   c           	      C  ó²   t |ƒ}| ¡ }| jrt|| j| jd}n	t|| j| jd}g }| ¡ D ]2\}}|D ]"}t||  	¡ ||  	¡ | j| jƒrLt
||  	¡ ||  	¡ ƒ||< q*| ||  	¡ ¡ q$|S r   )r   r€   rr   rh   r   r   ri   r^   r   r!   r   r3   ©	rs   r~   rƒ   r„   r`   r…   Úkeep_indÚmerge_ind_listÚ	merge_indr)   r)   r*   rw   ì  ó8   ýý

üÿ€zNMMPostprocess.__call__Nr†   r‡   r)   r)   r)   r*   r‰   ë  rˆ   r‰   c                   @  r|   )ÚGreedyNMMPostprocessr~   ru   c           	      C  rŠ   r   )r   r€   rr   r]   r   r   re   r^   r   r!   r   r3   r‹   r)   r)   r*   rw     r   zGreedyNMMPostprocess.__call__Nr†   r‡   r)   r)   r)   r*   r     rˆ   r   c                   @  r|   )ÚLSNMSPostprocessr~   ru   c           
      C  sÔ   zddl m} W n ty   tdƒ‚w | jdkr"td| j› dƒ t d¡ t|ƒ}| ¡ }|d d …d d…f }|d d …df }|d d …d	f  	d
¡}|||| j
| jrVd n|d}||  ¡ }	t|	tƒsh|	g}	|	S )Nr   )r   zPPlease run "pip install lsnms>0.3.1" to install lsnms first for lsnms utilities.r/   zmatch_metric=z& is not supported for LSNMSPostprocessz<LSNMSPostprocess is experimental and not recommended to use.r   r   Úuint8)Úiou_thresholdÚ	class_ids)Úlsnmsr   ÚModuleNotFoundErrorr   rv   r   Úwarningr   ÚtonumpyÚastyper   rr   r!   r   r‚   )
rs   r~   r   rƒ   Úobject_predictions_as_numpyrB   r"   r”   rF   r…   r)   r)   r*   rw   7  s,   ÿÿ

ÿ
zLSNMSPostprocess.__call__Nr†   r‡   r)   r)   r)   r*   r‘   5  s    r‘   )r   r   )r   r   r   r   r   r   )r   r,   r   r   r   r   )rS   r   r   r   r   r   )rS   r,   r   r   r   r   )Ú
__future__r   r   Úshapely.geometryr   Úshapely.strtreer   Úsahi.loggerr   Úsahi.postprocess.utilsr   r   r   Úsahi.predictionr	   Úsahi.utils.import_utilsr
   r+   r   re   r]   ri   rh   rq   r}   r‰   r   r‘   r)   r)   r)   r*   Ú<module>   s<    ýoý!ýqý ý %%