o
    Ďia                     @  s  d dl mZ d dlZd dlZd dlmZ 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 d d	lmZ d d
lmZmZmZmZmZ d dlmZmZ d dlmZ d dlmZm Z  d dl!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( d dl)m*Z*m+Z+m,Z,m-Z-m.Z. d dl/m0Z0 eeeedZ1dZ2dd Z3d d gddd ddfdpd!d"Z4				#	#	$	%	&	'	(	)		$				dqdrd<d=Z5d>d? Z6dsdAdBZ7		C			D					(	(		E	E	#	#	%	&	'	(	(	(	 	(	(		F	G				(	(	H	)	(	(		dtdudhdiZ8	j			D				k	k	(	(		l	l	#	#	%	&	'	(	)		dvdwdndoZ9dS )x    )annotationsN)	Generator)
cmp_to_key)Image)tqdm)AutoDetectionModel)logger)DetectionModel)GreedyNMMPostprocessLSNMSPostprocessNMMPostprocessNMSPostprocessPostprocessPredictions)ObjectPredictionPredictionResult)slice_image)Coco	CocoImage)IMAGE_EXTENSIONSVIDEO_EXTENSIONScrop_object_predictionscv2get_video_readerread_image_as_pilvisualize_object_predictions)Pathincrement_path
list_files	save_jsonsave_pickle)check_requirements)	GREEDYNMMNMMNMSLSNMSg?c                   s    fdd| D S )Nc                   s0   g | ]}|j jp
g vr|j j pg vr|qS  )categorynameid).0obj_predexclude_classes_by_idexclude_classes_by_namer%   H/home/jeff/fluffinator/venv/lib/python3.10/site-packages/sahi/predict.py
<listcomp>0   s    z&filter_predictions.<locals>.<listcomp>r%   )object_prediction_listr-   r,   r%   r+   r.   filter_predictions/   s   r1   shift_amountlistpostprocessPostprocessPredictions | Noneverboseintr-   list[str] | Noner,   list[int] | Nonereturnr   c                 C  s   t  }t| }	t }
|t|	 t |
 }||d< |du r'|	j|	jg}t }
|j||d |j	}t
|||}|durC||}t |
 }||d< |dkrYtd|d d t| ||dS )	a  Function for performing prediction for given image using given detection_model.

    Arguments:
        image: str or np.ndarray
            Location of image or numpy image matrix to slice
        detection_model: model.DetectionMode
        shift_amount: List
            To shift the box and mask predictions from sliced image to full
            sized image, should be in the form of [shift_x, shift_y]
        full_shape: List
            Size of the full image, should be in the form of [height, width]
        postprocess: sahi.postprocess.combine.PostprocessPredictions
        verbose: int
            0: no print (default)
            1: print prediction duration
        exclude_classes_by_name: Optional[List[str]]
            None: if no classes are excluded
            List[str]: set of classes to exclude using its/their class label name/s
        exclude_classes_by_id: Optional[List[int]]
            None: if no classes are excluded
            List[int]: set of classes to exclude using one or more IDs
    Returns:
        A dict with fields:
            object_prediction_list: a list of ObjectPrediction
            durations_in_seconds: a dict containing elapsed times for profiling
    
predictionN)r2   
full_shaper4      Prediction performed inseconds.imager0   durations_in_seconds)dictr   timeperform_inferencenpascontiguousarrayheightwidthconvert_original_predictionsr0   r1   printr   )rA   detection_modelr2   r<   r4   r6   r-   r,   rB   image_as_pil
time_starttime_endr0   r%   r%   r.   get_prediction8   s8   $rP   皙?Tr!   IOS      ?Fr=   slice_height
int | Noneslice_widthoverlap_height_ratiofloatoverlap_width_ratioperform_standard_predboolpostprocess_typestrpostprocess_match_metricpostprocess_match_thresholdpostprocess_class_agnosticmerge_buffer_lengthauto_slice_resolutionslice_export_prefix
str | None	slice_dirc           %   
   C  s|  t  }d}t }t| |||||||d}ddlm} t|}t | }||d< t||r3|jr3d}|t	 vrGt
dtt	  d| t| }||	||
d	}d}t }t|| }|dksf|d
krotd| d g }t|D ]`}g }g } t|D ]}!||j|| |!   | |j|| |!   qt|d || d |j|jg||d}"|"jD ]}#|#r||#  q|durt||krt }$||}|t |$ 7 }qu|dkr|rt| |ddg|j|jgd||d}"||"j t|dkr
t }$||}|t |$ 7 }t | }|| |d< ||d< |d
kr7td|d d td|d d td|d d t| ||dS )au  Function for slice image + get predicion for each slice + combine predictions in full image.

    Args:
        image: str or np.ndarray
            Location of image or numpy image matrix to slice
        detection_model: model.DetectionModel
        slice_height: int
            Height of each slice.  Defaults to ``None``.
        slice_width: int
            Width of each slice.  Defaults to ``None``.
        overlap_height_ratio: float
            Fractional overlap in height of each window (e.g. an overlap of 0.2 for a window
            of size 512 yields an overlap of 102 pixels).
            Default to ``0.2``.
        overlap_width_ratio: float
            Fractional overlap in width of each window (e.g. an overlap of 0.2 for a window
            of size 512 yields an overlap of 102 pixels).
            Default to ``0.2``.
        perform_standard_pred: bool
            Perform a standard prediction on top of sliced predictions to increase large object
            detection accuracy. Default: True.
        postprocess_type: str
            Type of the postprocess to be used after sliced inference while merging/eliminating predictions.
            Options are 'NMM', 'GREEDYNMM' or 'NMS'. Default is 'GREEDYNMM'.
        postprocess_match_metric: str
            Metric to be used during object prediction matching after sliced prediction.
            'IOU' for intersection over union, 'IOS' for intersection over smaller area.
        postprocess_match_threshold: float
            Sliced predictions having higher iou than postprocess_match_threshold will be
            postprocessed after sliced prediction.
        postprocess_class_agnostic: bool
            If True, postprocess will ignore category ids.
        verbose: int
            0: no print
            1: print number of slices (default)
            2: print number of slices and slice/prediction durations
        merge_buffer_length: int
            The length of buffer for slices to be used during sliced prediction, which is suitable for low memory.
            It may affect the AP if it is specified. The higher the amount, the closer results to the non-buffered.
            scenario. See [the discussion](https://github.com/obss/sahi/pull/445).
        auto_slice_resolution: bool
            if slice parameters (slice_height, slice_width) are not given,
            it enables automatically calculate these params from image resolution and orientation.
        slice_export_prefix: str
            Prefix for the exported slices. Defaults to None.
        slice_dir: str
            Directory to save the slices. Defaults to None.
        exclude_classes_by_name: Optional[List[str]]
            None: if no classes are excluded
            List[str]: set of classes to exclude using its/their class label name/s
        exclude_classes_by_id: Optional[List[int]]
            None: if no classes are excluded
            List[int]: set of classes to exclude using one or more IDs
    Returns:
        A Dict with fields:
            object_prediction_list: a list of sahi.prediction.ObjectPrediction
            durations_in_seconds: a dict containing elapsed times for profiling
    r=   )rA   output_file_name
output_dirrT   rV   rW   rY   rb   r   )UltralyticsDetectionModelslicer#   z"postprocess_type should be one of z but given as )match_thresholdmatch_metricclass_agnostic   zPerforming prediction on z slices.)rA   rL   r2   r<   r-   r,   N)rA   rL   r2   r<   r4   r-   r,   r;   r4   Slicing performed inr?   r>   zPostprocessing performed inr@   )rC   rD   r   sahi.models.ultralyticsrh   len
isinstanceis_obbPOSTPROCESS_NAME_TO_CLASSkeys
ValueErrorr3   r7   r   writerangeappendimagesstarting_pixelsrP   original_image_heightoriginal_image_widthr0   get_shifted_object_predictionextendrK   r   )%rA   rL   rT   rV   rW   rY   rZ   r\   r^   r_   r`   r6   ra   rb   rc   re   r-   r,   rB   	num_batchrN   slice_image_resultrh   
num_slicesrO   postprocess_constructorr4   postprocess_time	num_groupr0   	group_ind
image_listshift_amount_list	image_indprediction_resultobject_predictionpostprocess_time_startr%   r%   r.   get_sliced_prediction   s   P


r   c                 C  s@   | }|}t |d |d  |kr|d |d  S |d |d  S )a)  
    a, b  - function receives two bounding bboxes

    thresh - the threshold takes into account how far two bounding bboxes differ in
    Y where thresh is the threshold we set for the
    minimum allowable difference in height between adjacent bboxes
    and sorts them by the X coordinate
    r=   r   )abs)abthreshbbox_abbox_br%   r%   r.   	bbox_sortT  s
   
r   resultc                   s   g }|   }|D ]}|d }|d }|d }|d }|d }	|||||	f qt|t fddd}
tt|d D ]}|
t|| d || d	< q<|S )
Nbboxr   r=   rm      c                   s   t | | S )N)r   )r   r   r   r%   r.   <lambda>r  s    z agg_prediction.<locals>.<lambda>)keyimage_id)to_coco_annotationsrx   sortedr   rw   rp   indextuple)r   r   
coord_listresanncurrent_bboxxywhcntspredr%   r   r.   agg_predictiong  s    r   ultralytics      ?   runs/predictexppngrL   DetectionModel | None
model_type
model_pathmodel_config_pathmodel_confidence_thresholdmodel_devicemodel_category_mappingdict | Nonemodel_category_remappingsourceno_standard_predictionno_sliced_prediction
image_sizenovisual
view_videoframe_skip_intervalexport_pickleexport_cropdataset_json_pathprojectr'   visual_bbox_thicknessvisual_text_sizefloat | Nonevisual_text_thicknessvisual_hide_labelsvisual_hide_confvisual_export_formatreturn_dictforce_postprocess_typec'           P        s  |	r|
rt d|$s|tk r|dkrtd| d d}d}t }(ttt|| dd})|)d }*|)d	 }+|)d
 },|)d }-|rH|sH|sH|durO|)jddd d}.d}/|ri rit	|}0 fdd|0j
D }1g }2n: rytj ryt t|"d}1n* rt jtv rd}.t t|)|| |\}3}4}5}/|3}1n r g}1ntd dS t }6| du rtjd;|||||||d|d	|'} |   t |6 }7|7|(d< d|(d< d|(d< |.rdnd}8tt|1d|8 |/dD ]\}9}: r|.rt j};|;d t|9 }<n:t|:tjrtd r1tj r1tt|:tt d }<|<d tj kr.|<dd n|<}<nt|:j!}<t|<j}=t"|:}>|
smt#|>| |||||	 |||||"rTdnd|%|&d }?|?j$}@|?j%rl|(d  |?j%d 7  < nt&|>| ddgddd|%|&d!}?|?j$}@|(d  |?j%d 7  < |"rt'd"(|?j%d d#  |r|.du rt)d$|@D ]}A|A* }B|0j
|9 j+|B_,|Bj-}C|Cd% r|2.|C q|s|0j
|9 }Dg }E|Dj/D ]}F|Fj-}G|Fj0}H|Dj1|Dj2g}It3j4|G|H|Id&}J|E.|J qt|,t|<j5 }Kd'}Lt6t78|>|E||||L|| dddd(}Md)}Lt6|Md* |@||||L|| |K|=|!d(}Nt }6|r9t|*t|<j5 }Kt9t78|>|@|K|=|!d+ |rOt|-t|<j5 |=d,  }Ot:|@|Od- |rU|rt|+t|<j5 }Kt6t78|>|@||||| |.sn|Knd|=|!d.
}M|s|.r|4du rtd/|4't;<|Md* t;j= |rt;>d0|5|Md*  t;?d t |6 }7|7|(d1< q|rt|)d2 }Ot@|2|O |r|s|s|durtAd3|)  |"d4krtAd5|(d d6 tAd7|(d d6 tAd8|(d d6 |stAd9|(d1 d6 |#rd:|)iS dS )<az  Performs prediction for all present images in given folder.

    Args:
        detection_model: sahi.model.DetectionModel
            Optionally provide custom DetectionModel to be used for inference. When provided,
            model_type, model_path, config_path, model_device, model_category_mapping, image_size
            params will be ignored
        model_type: str
            mmdet for 'MmdetDetectionModel', 'yolov5' for 'Yolov5DetectionModel'.
        model_path: str
            Path for the model weight
        model_config_path: str
            Path for the detection model config file
        model_confidence_threshold: float
            All predictions with score < model_confidence_threshold will be discarded.
        model_device: str
            Torch device, "cpu" or "cuda"
        model_category_mapping: dict
            Mapping from category id (str) to category name (str) e.g. {"1": "pedestrian"}
        model_category_remapping: dict: str to int
            Remap category ids after performing inference
        source: str
            Folder directory that contains images or path of the image to be predicted. Also video to be predicted.
        no_standard_prediction: bool
            Dont perform standard prediction. Default: False.
        no_sliced_prediction: bool
            Dont perform sliced prediction. Default: False.
        image_size: int
            Input image size for each inference (image is scaled by preserving asp. rat.).
        slice_height: int
            Height of each slice.  Defaults to ``512``.
        slice_width: int
            Width of each slice.  Defaults to ``512``.
        overlap_height_ratio: float
            Fractional overlap in height of each window (e.g. an overlap of 0.2 for a window
            of size 512 yields an overlap of 102 pixels).
            Default to ``0.2``.
        overlap_width_ratio: float
            Fractional overlap in width of each window (e.g. an overlap of 0.2 for a window
            of size 512 yields an overlap of 102 pixels).
            Default to ``0.2``.
        postprocess_type: str
            Type of the postprocess to be used after sliced inference while merging/eliminating predictions.
            Options are 'NMM', 'GREEDYNMM', 'LSNMS' or 'NMS'. Default is 'GREEDYNMM'.
        postprocess_match_metric: str
            Metric to be used during object prediction matching after sliced prediction.
            'IOU' for intersection over union, 'IOS' for intersection over smaller area.
        postprocess_match_threshold: float
            Sliced predictions having higher iou than postprocess_match_threshold will be
            postprocessed after sliced prediction.
        postprocess_class_agnostic: bool
            If True, postprocess will ignore category ids.
        novisual: bool
            Dont export predicted video/image visuals.
        view_video: bool
            View result of prediction during video inference.
        frame_skip_interval: int
            If view_video or export_visual is slow, you can process one frames of 3(for exp: --frame_skip_interval=3).
        export_pickle: bool
            Export predictions as .pickle
        export_crop: bool
            Export predictions as cropped images.
        dataset_json_path: str
            If coco file path is provided, detection results will be exported in coco json format.
        project: str
            Save results to project/name.
        name: str
            Save results to project/name.
        visual_bbox_thickness: int
        visual_text_size: float
        visual_text_thickness: int
        visual_hide_labels: bool
        visual_hide_conf: bool
        visual_export_format: str
            Can be specified as 'jpg' or 'png'
        verbose: int
            0: no print
            1: print slice/prediction durations, number of slices
            2: print model loading/file exporting durations
        return_dict: bool
            If True, returns a dict with 'export_dir' field.
        force_postprocess_type: bool
            If True, auto postprocess check will e disabled
        exclude_classes_by_name: Optional[List[str]]
            None: if no classes are excluded
            List[str]: set of classes to exclude using its/their class label name/s
        exclude_classes_by_id: Optional[List[int]]
            None: if no classes are excluded
            List[int]: set of classes to exclude using one or more IDs
    zT'no_standard_prediction' and 'no_sliced_prediction' cannot be True at the same time.r#   zPSwitching postprocess type/metric to NMS/IOU since confidence threshold is low (z).IOUF)exist_okcropsvisualsvisuals_with_gtpicklesNT)parentsr   c                   s"   g | ]}t t t|j qS r%   )r]   r   	file_name)r)   
coco_imager   r%   r.   r/     s   " zpredict.<locals>.<listcomp>)	directorycontainsr6   z(No valid input given to predict function	r   r   config_pathconfidence_thresholddevicecategory_mappingcategory_remappingload_at_initr   
model_loadr   r;   ri   zvideo framesry   zPerforming inference on )total_frame_z:Source is not a video, but image is still an Image object r=   )rA   rL   rT   rV   rW   rY   rZ   r\   r^   r_   r`   r6   r-   r,   rA   rL   r2   r<   r4   r6   r-   r,   zPrediction time is: {:.2f} msi  z?Video input type not supported with coco formatted dataset jsonr   )annotation_dictcategory_namer<   )r      r   )
r0   rect_th	text_sizetext_thcolorhide_labels	hide_confrg   r   export_format)r   r   r   rA   )rA   r0   rg   r   r   z.pickle)data	save_path)	r0   r   r   r   r   r   rg   r   r   z(Output video writer could not be createdzPrediction of export_fileszresult.jsonz0Prediction results are successfully exported to rm   Model loaded inr?   rn   r>   zExporting performed in
export_dirr%   )Bru   LOW_MODEL_CONFIDENCEr   warningrC   r   r   mkdirr   from_coco_dict_or_pathry   ospathisdirr   r   suffixr   r   r]   errorrD   r   from_pretrained
load_model	enumerater   stemrq   r   RuntimeErrorsplitsepr'   r   r   r0   rB   rP   rv   formatNotImplementedErrorto_coco_predictionr(   r   jsonrx   r   r   rH   rI   r   from_coco_annotation_dictparentr   rF   rG   r   r   r   cvtColorCOLOR_RGB2BGRimshowwaitKeyr   rK   )PrL   r   r   r   r   r   r   r   r   r   r   r   rT   rV   rW   rY   r\   r^   r_   r`   r   r   r   r   r   r   r   r'   r   r   r   r   r   r   r6   r   r   r-   r,   kwargsrB   save_dircrop_dir
visual_dirvisual_with_gt_dir
pickle_dirsource_is_video
num_framescocoimage_iterator	coco_jsonread_video_frameoutput_video_writervideo_file_namerN   rO   input_type_strind
image_path
video_namerelative_filepathfilename_without_extensionrM   r   r0   r   coco_predictioncoco_prediction_jsonr   object_prediction_gt_listcoco_annotationcoco_annotation_dictr   r<   object_prediction_gtrg   r   r   _r   r%   r   r.   predicty  s   



"












r)  mmdet    	image_dirc           &      C  s  t dg ddlm}m} |	r|
rtdt }|||}t }tj| ||||||d|d	}|	  t | }||d< d|d< d|d	< |
 Y}||D ]L}|
srt|j||||||	 |||||||d
} |d	  | jd	 7  < nt|j|ddgddd||d} |d  | jd 7  < |j|  d|| < |  qNW d   n1 sw   Y  |dkrtd|d d td|d	 d td|d d | }!||!_|j| dd|dd}"|d}#t|#|#jdddd }$|"j|$d |d}%|%jddd|!_	 td q)a  Performs prediction for all present images in given folder.

    Args:
        model_type: str
            mmdet for 'MmdetDetectionModel', 'yolov5' for 'Yolov5DetectionModel'.
        model_path: str
            Path for the model weight
        model_config_path: str
            Path for the detection model config file
        model_confidence_threshold: float
            All predictions with score < model_confidence_threshold will be discarded.
        model_device: str
            Torch device, "cpu" or "cuda"
        model_category_mapping: dict
            Mapping from category id (str) to category name (str) e.g. {"1": "pedestrian"}
        model_category_remapping: dict: str to int
            Remap category ids after performing inference
        dataset_json_path: str
            If coco file path is provided, detection results will be exported in coco json format.
        image_dir: str
            Folder directory that contains images or path of the image to be predicted.
        no_standard_prediction: bool
            Dont perform standard prediction. Default: False.
        no_sliced_prediction: bool
            Dont perform sliced prediction. Default: False.
        image_size: int
            Input image size for each inference (image is scaled by preserving asp. rat.).
        slice_height: int
            Height of each slice.  Defaults to ``256``.
        slice_width: int
            Width of each slice.  Defaults to ``256``.
        overlap_height_ratio: float
            Fractional overlap in height of each window (e.g. an overlap of 0.2 for a window
            of size 256 yields an overlap of 51 pixels).
            Default to ``0.2``.
        overlap_width_ratio: float
            Fractional overlap in width of each window (e.g. an overlap of 0.2 for a window
            of size 256 yields an overlap of 51 pixels).
            Default to ``0.2``.
        postprocess_type: str
            Type of the postprocess to be used after sliced inference while merging/eliminating predictions.
            Options are 'NMM', 'GREEDYNMM' or 'NMS'. Default is 'GREEDYNMM'.
        postprocess_match_metric: str
            Metric to be used during object prediction matching after sliced prediction.
            'IOU' for intersection over union, 'IOS' for intersection over smaller area.
        postprocess_match_metric: str
            Metric to be used during object prediction matching after sliced prediction.
            'IOU' for intersection over union, 'IOS' for intersection over smaller area.
        postprocess_match_threshold: float
            Sliced predictions having higher iou than postprocess_match_threshold will be
            postprocessed after sliced prediction.
        postprocess_class_agnostic: bool
            If True, postprocess will ignore category ids.
        verbose: int
            0: no print
            1: print slice/prediction durations, number of slices, model loading/file exporting durations
        exclude_classes_by_name: Optional[List[str]]
            None: if no classes are excluded
            List[str]: set of classes to exclude using its/their class label name/s
        exclude_classes_by_id: Optional[List[int]]
            None: if no classes are excluded
            List[int]: set of classes to exclude using one or more IDs
    fiftyoner   )&create_fiftyone_dataset_from_coco_filefozN'no_standard_pred' and 'no_sliced_prediction' cannot be True at the same time.Fr   r   r;   ri   )rA   rL   rT   rV   rW   rY   rZ   r\   r_   r^   r`   r6   r-   r,   Nr   )
detectionsr=   r   r?   rn   r>   ground_truthevalT)gt_fieldeval_keyioucompute_mAPzground_truth.detections.label)r   reverse
   )classeseval_fp)r8  r   )r    sahi.utils.fiftyoner/  r0  ru   rC   rD   r   r   r   ProgressBarr   filepathrB   rP   
Detectionsto_fiftyone_detectionssaverK   
launch_appdatasetevaluate_detectionscount_valuesr   getprint_reportload_evaluation_viewsort_byviewsleep)&r   r   r   r   r   r   r   r   r-  r   r   r   rT   rV   rW   rY   r\   r^   r_   r`   r6   r-   r,   r/  r0  rB   rC  rN   rL   rO   pbsampler   sessionresultscountsclasses_top10	eval_viewr%   r%   r.   predict_fiftyone  s   
X



)


rS  )r2   r3   r4   r5   r6   r7   r-   r8   r,   r9   r:   r   )NNNrQ   rQ   Tr!   rR   rS   Fr=   NTNNNN)"rT   rU   rV   rU   rW   rX   rY   rX   rZ   r[   r\   r]   r^   r]   r_   rX   r`   r[   r6   r7   ra   rU   rb   r[   rc   rd   re   rd   r-   r8   r,   r9   r:   r   )r   r   )'Nr   NNr   NNNNFFNr   r   rQ   rQ   r!   rR   rS   FFFr   FFNr   r   NNNFFr   r=   FFNN)NrL   r   r   r]   r   rd   r   rd   r   rX   r   rd   r   r   r   r   r   rd   r   r[   r   r[   r   rU   rT   r7   rV   r7   rW   rX   rY   rX   r\   r]   r^   r]   r_   rX   r`   r[   r   r[   r   r[   r   r7   r   r[   r   r[   r   rd   r   r]   r'   r]   r   rU   r   r   r   rU   r   r[   r   r[   r   r]   r6   r7   r   r[   r   r[   r-   r8   r,   r9   )r*  NNr   NNNr+  r+  FFNr,  r,  rQ   rQ   r!   rR   rS   Fr=   NN).r   r]   r   rd   r   rd   r   rX   r   rd   r   r   r   r   r   r]   r-  r]   r   r[   r   r[   r   rU   rT   r7   rV   r7   rW   rX   rY   rX   r\   r]   r^   r]   r_   rX   r`   r[   r6   r7   r-   r8   r,   r9   ):
__future__r   r   rD   collections.abcr   	functoolsr   numpyrF   PILr   r   sahi.auto_modelr   sahi.loggerr   sahi.models.baser	   sahi.postprocess.combiner
   r   r   r   r   sahi.predictionr   r   sahi.slicingr   sahi.utils.cocor   r   sahi.utils.cvr   r   r   r   r   r   r   sahi.utils.filer   r   r   r   r   sahi.utils.import_utilsr    rs   r   r1   rP   r   r   r   r)  rS  r%   r%   r%   r.   <module>   s    $	P O
   