o
    Ďim                     @  s  d dl mZ d dlZd dl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Zd dlZd dlmZmZ d dlmZ d dlmZ dd	gZg d
Zee Zg dZG dd dZ			dcddddZdedfddZdgd!d"Zdhd$d%Zdidjd*d+Zd,d- Zdkd0d1Z 		dldmd9d:Z!								dndodIdJZ"									dpdqdLdMZ#drdPdQZ$dsdUdVZ%dtdXdYZ&dZd[ Z'dud]d^Z(dvd_d`Z)dvdadbZ*dS )w    )annotationsN)	Generator)BytesIO)ImageImageOps)logger)Pathz.jpgz.jpeg).pngz.tifz.tiffz.bmp)z.mp4z.mkvz.flvz.aviz.tsz.mpgz.movwmvc                   @  s,   e Zd Zdd ZddddZedd	 Zd
S )Colorsc                   s,   d} fdd|  D  _t j _d S )NzFF3838 2C99A8 FF701F 6473FF CFD231 48F90A 92CC17 3DDB86 1A9334 00D4BB FF9D97 00C2FF 344593 FFB21D 0018EC 8438FF 520085 CB38FF FF95C8 FF37C7c                   s   g | ]
}  d | qS )#)
hex_to_rgb).0cself I/home/jeff/fluffinator/venv/lib/python3.10/site-packages/sahi/utils/cv.py
<listcomp>   s    z#Colors.__init__.<locals>.<listcomp>)splitpalettelenn)r   
hex_colorsr   r   r   __init__   s   zColors.__init__Fbgrboolc                 C  s2   | j t|| j  }|r|d |d |d fS |S )a6  Convert an index to a color code.

        Args:
            ind (int): The index to convert.
            bgr (bool, optional): Whether to return the color code in BGR format. Defaults to False.

        Returns:
            tuple: The color code in RGB or BGR format, depending on the value of `bgr`.
              r   )r   intr   )r   indr   color_codesr   r   r   __call__"   s   
zColors.__call__c                 C  s:   g }dD ]}| t| d| d| d  d qt|S )zConverts a hexadecimal color code to RGB format.

        Args:
            hex_code (str): The hexadecimal color code to convert.

        Returns:
            tuple: A tuple representing the RGB values in the order (R, G, B).
        )r   r      r   r      )appendr   tuple)hex_codergbir   r   r   r   /   s   
&zColors.hex_to_rgbN)F)r   r   )__name__
__module____qualname__r   r"   staticmethodr   r   r   r   r   r      s
    	r    prediction_visualpngimage
np.ndarray
output_dirstr	file_nameexport_formatc              	   C  s   t |jddd t|D ]S\}}| }|j }|jj}t| t	|d t	|d t	|d t	|d ddf }	t
j||d t| d	 t| d
 | }
t|
t|	tj qdS )au  Crops bounding boxes over the source image and exports it to the output folder.

    Args:
        image (np.ndarray): The source image to crop bounding boxes from.
        object_prediction_list: A list of object predictions.
        output_dir (str): The directory where the resulting visualizations will be exported. Defaults to an empty string.
        file_name (str): The name of the exported file. The exported file will be saved as `output_dir + file_name + ".png"`. Defaults to "prediction_visual".
        export_format (str): The format of the exported file. Can be specified as 'jpg' or 'png'. Defaults to "png".
    Tparentsexist_okr      r   r   N_box_class.)r   mkdir	enumeratedeepcopybboxto_xyxycategoryidcopyr   ospathjoinr4   cv2imwritecvtColorCOLOR_RGB2BGR)r1   object_prediction_listr3   r5   r6   r    object_predictionrA   category_idcropped_img	save_pathr   r   r   crop_object_predictions?   s&   
"rR   jpgF	extension	grayscaler   c                 C  sP   t | }tj| \}}|rt |t j}|d }|d | }t || dS )aZ  Reads an image from the given path and saves it with the specified extension.

    Args:
        read_path (str): The path to the image file.
        extension (str, optional): The desired file extension for the saved image. Defaults to "jpg".
        grayscale (bool, optional): Whether to convert the image to grayscale. Defaults to False.
    _grayr=   N)rI   imreadrF   rG   splitextrK   COLOR_BGR2GRAYrJ   )	read_pathrT   rU   r1   pre_rQ   r   r   r   convert_image_toh   s   
r]   
image_pathc                 C  s   d}zt | d}t |t j}W ||fS  tyR } z2td| d zddl}W n ty6   tdw |j	j| dd	
tj}d}W Y d}~||fS d}~ww )
a  Reads a large image from the specified image path.

    Args:
        image_path (str): The path to the image file.

    Returns:
        tuple: A tuple containing the image data and a flag indicating whether cv2 was used to read the image.
            The image data is a numpy array representing the image in RGB format.
            The flag is True if cv2 was used, False otherwise.
    Tr   z'OpenCV failed reading image with error , trying skimage insteadr   Nz`Please run "pip install -U scikit-image" to install scikit-image first for large image handling.F)as_grey)rI   rW   rK   COLOR_BGR2RGB	Exceptionr   error
skimage.ioImportErrorioastypenpuint8)r^   use_cv2img_cv2image0eskimager   r   r   read_large_imagey   s&   ro   returnc                 C  s   t | }t |t j}|S )zLoads image as a numpy array from the given path.

    Args:
        image_path (str): The path to the image file.

    Returns:
        numpy.ndarray: The loaded image as a numpy array.
    )rI   rW   rK   ra   )r^   r1   r   r   r   
read_image   s   

rq   TImage.Image | str | np.ndarrayexif_fixImage.Imagec                 C  s  dt _t| t j r| }|S t| trz(t t| dr&ttj| ddj	n| 
d}|r8tj|dd W |S W |S  ty } zrtd| d zd	dl}W n ty\   td
w |j| tj}t|jdkrvt j|dd}n)|jd dkrt j|dd}n!|jd dkrt j|dd}ntd|jd  dW Y d}~|S W Y d}~|S W Y d}~|S d}~ww t| tjr| jd	 dk r| dddddddf } t | }|S td)a  Loads an image as PIL.Image.Image.

    Args:
        image (Union[Image.Image, str, np.ndarray]): The image to be loaded. It can be an image path or URL (str),
            a numpy image (np.ndarray), or a PIL.Image object.
        exif_fix (bool, optional): Whether to apply an EXIF fix to the image. Defaults to False.

    Returns:
        PIL.Image.Image: The loaded image as a PIL.Image object.
    NhttpT)streamRGB)in_placez$PIL failed reading image with error r_   r   zNPlease run 'pip install -U scikit-image imagecodecs' for large image handling.r   1)moder#   RGBAr:   zimage with shape: z is not supported.   z-read image with 'pillow' using 'Image.open()')r   MAX_IMAGE_PIXELS
isinstancer4   open
startswithr   requestsgetcontentconvertr   exif_transposerb   r   rc   rd   re   rf   rW   rg   rh   ri   r   shape	fromarray	TypeErrorndarray)r1   rs   	image_pilrm   rn   image_skr   r   r   read_image_as_pil   sZ   
$


	
r   c                  C  sV   g dg dg dg dg dg dg dg dg d	g d
g dg} | t dd S )zSelects a random color from a predefined list of colors.

    Returns:
        list: A list representing the RGB values of the selected color.
    )r      r   )r   r   r   )r   r   r   )r   r   r   )r   r   r   )r   r   r   )P   F      )   r      )      2   )r      r   )r   r   r   r   
   )random	randrange)colorsr   r   r   select_random_color   s   r   colortuple[int, int, int]c                 C  sp   t | t j}t | t j}t | t j}|\|| dk< || dk< || dk< t j|||gdd}|S )a  Applies color mask to given input image.

    Args:
        image (np.ndarray): The input image to apply the color mask to.
        color (tuple): The RGB color tuple to use for the mask.

    Returns:
        np.ndarray: The resulting image with the applied color mask.
    r   r   axis)rh   
zeros_likerg   ri   stack)r1   r   rgbcolored_maskr   r   r   apply_color_mask   s   
"r   sourcesave_dirframe_skip_intervalr   export_visualview_visual?tuple[Generator[Image.Image], cv2.VideoWriter | None, str, int]c                   s   t j|  t| }t|tj}r||d  }t|}d	 fdd}|re|dkr8|tj}|| }n|tj}t|tj	}	t|tj
}
|	|
f}tjd }tt j| |||}nd}|||| |fS )
a  Creates OpenCV video capture object from given video file path.

    Args:
        source: Video file path
        save_dir: Video export directory
        frame_skip_interval: Frame skip interval
        export_visual: Set True if you want to export visuals
        view_visual: Set True if you want to render visual

    Returns:
        iterator: Pillow Image
        video_writer: cv2.VideoWriter
        video_file_name: video name with extension
    r   rp   Generator[Image.Image]c                 3  s|   rd }t |t j tjdtjd}t || | jr| t j	}| 
t j	||  t d}| t j	}|dkrEtd t  |dkrM|d7 }|dkrU|d8 }|d	kr]|d7 }|d
kre|d8 }| 
t j	| |  \}}|sztd d S tt |t jV  | js d S d S | jr| t j	}| 
t j	||  |  \}}|std d S tt |t jV  | jsd S d S )NzPrediction of )i  i  r:   )dtype      z>
===========================Closing===========================d   a   g   f   zD
=========================== Video Ended ===========================)rI   namedWindowWINDOW_AUTOSIZErh   zerosri   imshowisOpenedr   CAP_PROP_POS_FRAMESsetwaitKeyprintexitreadr   r   rK   ra   )video_capturer   window_namedefault_image	frame_numkretframevideo_file_namer   r   r   read_video_frame  sP   

z*get_video_reader.<locals>.read_video_framer   mp4vN)rp   r   )rF   rG   basenamerI   VideoCapturer   r   CAP_PROP_FRAME_COUNTCAP_PROP_FPSCAP_PROP_FRAME_WIDTHCAP_PROP_FRAME_HEIGHTVideoWriter_fourccVideoWriterrH   )r   r   r   r   r   r   
num_framesr   fpswhsizefourccvideo_writerr   r   r   get_video_reader   s(   
.
r   boxes
list[list]classes	list[str]maskslist[np.ndarray] | Nonerect_th
int | None	text_sizefloat | Nonetext_thtuple | Nonehide_labels
str | Nonec              
   C  s~  t   }t| } |du rt }nd}|p"ttt| jd d d}|p+t|d d}|p1|d }|dur@|du r@t	d n#|durc|durc|D ]}t|}t
t||}t| d|dd} qJtt|D ]}t|| }|| }|dur||}n|dur|}nt	d	 qit|d t|d gt|d t|d g}}tj| ||||d
 |s| }tj|d||dd \}}|d | d dk}|d | |r|d | d n|d | d f}t| |||pddtj tj| ||d |r|d d n|d | d fd|d|d qi|	r4t|	jddd tj|	|
p%dd }t|t| tj t   | }| |dS )a  Visualizes prediction classes, bounding boxes over the source image and exports it to output folder.

    Args:
        image (np.ndarray): The source image.
        boxes (List[List]): List of bounding boxes coordinates.
        classes (List[str]): List of class labels corresponding to each bounding box.
        masks (Optional[List[np.ndarray]], optional): List of masks corresponding to each bounding box. Defaults to None.
        rect_th (int, optional): Thickness of the bounding box rectangle. Defaults to None.
        text_size (float, optional): Size of the text for class labels. Defaults to None.
        text_th (int, optional): Thickness of the text for class labels. Defaults to None.
        color (tuple, optional): Color of the bounding box and text. Defaults to None.
        hide_labels (bool, optional): Whether to hide the class labels. Defaults to False.
        output_dir (Optional[str], optional): Output directory to save the visualization. Defaults to None.
        file_name (Optional[str], optional): File name for the saved visualization. Defaults to "prediction_visual".

    Returns:
        dict: A dictionary containing the visualized image and the elapsed time for the visualization process.
    Nr   ~jth?r   r:   z%Cannot add mask, no color tuple given333333?r   zcolor cannot be definedr   	thickness	fontScaler   r   r   r   r}   r   r   r   r   Tr7   unknownr	   r1   elapsed_time)timerE   r@   r   maxroundsumr   r   rc   r   rh   squeezerI   addWeightedranger   r   	rectanglegetTextSizeLINE_AAputTextr   r>   rF   rG   rH   rJ   rK   rL   )r1   r   r   r   r   r   r   r   r   r3   r5   r   r   maskrgb_mask
box_indiceboxclass_mycolorpoint1point2label	box_width
box_heightoutsiderQ   r   r   r   visualize_predictionc  sp    
 


20(	
r  	hide_confc              
   C  s  t   }t| } |du rt }nd}|p"ttt| jd d d}|p+t|d d}|p1|d }|D ]r}| }|jj	 }|sL|d|j
jd7 }|durV||jj}|jdu}d}|r|jj}t|dkrtt|d	 d
krtd}|rt|dtj}tj| |gd|pd|d |s||dddddf   d	 }tj|d	||dd	 \}}|d | d d	k}|d	 |r|d | d n|d d f}|d	 | |d f}tj| |||pddtjd tj| ||d	 |r|d d n|d | d fd	|d|d nt|jj|pd}t| d|dd	} |s|j  }t!|d	 t!|d ft!|d t!|d f}}tj| |||pCd|d |stj|d	||dd	 \}}|d | d d	k}|d	 | |rq|d | d n|d | d f}t| |||pddtj tj| ||d	 |r|d d n|d | d fd	|d|d q4|durt"|j#ddd t$t"||	pdd |
pd  }t%|t&| tj' t   | }| |dS )a  Visualizes prediction category names, bounding boxes over the source image and exports it to output folder.

    Args:
        object_prediction_list: a list of prediction.ObjectPrediction
        rect_th: rectangle thickness
        text_size: size of the category name over box
        text_th: text thickness
        color: annotation color in the form: (0, 255, 0)
        hide_labels: hide labels
        hide_conf: hide confidence
        output_dir: directory for resulting visualization to be exported
        file_name: exported file will be saved as: output_dir+file_name+".png"
        export_format: can be specified as 'jpg' or 'png'
    Nr   r   r   r:    z.2fFr      T)r}   r   r   r   )isClosedr   r   r   r}   )r   lineTyper   r   r   r   r7   r.   r=   r   )(r   rE   r@   r   r   r   r   r   rC   namescorevaluerD   r  segmentationr   rh   arrayreshaperg   int32rI   	polylinesargmaxr   r   r   r   r   	bool_maskr   rA   rB   r   r   r>   r4   rJ   rK   rL   )r1   rM   r   r   r   r   r   r  r3   r5   r6   r   r   rN   r	  has_maskis_obb_predr  pointslowest_pointr
  r  r  text_bg_point1text_bg_point2r  rA   r  r  rQ   r   r   r   visualize_object_predictions  s   
 


"&
22(
$
r#  r  list[list[float]]c              	   C  s   t | }|t j}tj|ddddtjdd}tj|tjtj	dd}t
|dkr-|d n|d }g }|D ]}|  }t
|dkrH|| q5|S )	z
    Convert boolean mask to coco segmentation format
    [
        [x1, y1, x2, y2, x3, y3, ...],
        [x1, y1, x2, y2, x3, y3, ...],
        ...
    ]
    r   r   )r  )r}   r}   )offsetr   r      )rh   r   rg   ri   rI   copyMakeBorderBORDER_CONSTANTfindContours	RETR_LISTCHAIN_APPROX_SIMPLEr   flattentolistr%   )r  r  polygonscoco_segmentationpolygonr  r   r   r   $get_coco_segmentation_from_bool_mask]  s   


r1  r/  widthheightc                 C  s<   ||g}dd | D }t |}t||d}|t |S )a?  Convert coco segmentation to 2D boolean mask of given height and width.

    Parameters:
    - coco_segmentation: list of points representing the coco segmentation
    - width: width of the boolean mask
    - height: height of the boolean mask

    Returns:
    - bool_mask: 2D boolean mask of size (height, width)
    c                 S  s(   g | ]}t |d d tqS )r}   r   )rh   r  r  r   rg   r   )r   pointr   r   r   r     s   ( z8get_bool_mask_from_coco_segmentation.<locals>.<listcomp>)g      ?)rh   r   rI   fillPolyrg   r   )r/  r2  r3  r   r  r  r   r   r   $get_bool_mask_from_coco_segmentationv  s   

r6  list[int] | Nonec           	      C  s   t j| dd}t j| dd}t |rt |sdS t |d ddg \}}t |d ddg \}}|| }|| }|dksD|dkrFdS ||||gS )a  Generate VOC bounding box [xmin, ymin, xmax, ymax] from given boolean mask.

    Args:
        bool_mask (np.ndarray): 2D boolean mask.

    Returns:
        Optional[List[int]]: VOC bounding box [xmin, ymin, xmax, ymax] or None if no bounding box is found.
    r   r   r   Nr}   )rh   anywhere)	r  rowscolsyminymaxxminxmaxr2  r3  r   r   r   get_bbox_from_bool_mask  s   	r@  c                 C  s   g }g }| D ]}| |ddd  | |ddd  qt|dks)t|dkr+dS t|}t|}t|}t|}||||gS )zIGenerate voc box ([xmin, ymin, xmax, ymax]) from given coco segmentation.Nr   r   r   )extendr   minr   )r/  xsyssegmr>  r?  r<  r=  r   r   r   get_bbox_from_coco_segmentation  s   rF  
obb_pointsc                 C  s8   |  d }g }g ||d |d }|| |S )a  Convert OBB (Oriented Bounding Box) points to COCO polygon format.

    Args:
        obb_points: np.ndarray
            OBB points tensor from ultralytics.engine.results.OBB
            Shape: (4, 2) containing 4 points with (x,y) coordinates each

    Returns:
        List[List[float]]: Polygon points in COCO format
            [[x1, y1, x2, y2, x3, y3, x4, y4], [...], ...]
    r}   r   r   )r  r-  r%   )rG  r  r.  closed_polygonr   r   r   %get_coco_segmentation_from_obb_points  s
   
rI  c                 C  s   | t |  S )zNormalizes numpy image.)rh   r   )r1   r   r   r   normalize_numpy_image  s   rJ  c                 C  sD   ddl }t| tj} td| \}}|jj|d}|j| dS )zDisplays numpy image in notebook.

    If input image is in range 0..1, please first multiply img by 255
    Assumes image is ndarray of shape [height, width, channels] where channels can be 1, 3 or 4
    r   Nr	   )data)IPythonrI   rK   rL   imencodedisplayr   )r1   rL  r\   r   r)   r   r   r   ipython_display  s
   rO  )r.   r/   r0   )r1   r2   r3   r4   r5   r4   r6   r4   )rS   F)rT   r4   rU   r   )r^   r4   )r^   r4   rp   r2   )T)r1   rr   rs   r   rp   rt   )r1   r2   r   r   )FF)r   r4   r   r4   r   r   r   r   r   r   rp   r   )NNNNNFNr/   )r1   r2   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r3   r   r5   r   )	NNNNFFNr/   r0   )r1   r2   r   r   r   r   r   r   r   r   r   r   r  r   r3   r   r5   r   r6   r   )r  r2   rp   r$  )r/  r$  r2  r   r3  r   rp   r2   )r  r2   rp   r7  )rG  r2   rp   r$  )r1   r2   )+
__future__r   rE   rF   r   r   collections.abcr   rf   r   rI   numpyrh   r   PILr   r   sahi.loggerr   sahi.utils.filer   IMAGE_EXTENSIONS_LOSSYIMAGE_EXTENSIONS_LOSSLESSIMAGE_EXTENSIONSVIDEO_EXTENSIONSr   rR   r]   ro   rq   r   r   r   r   r  r#  r1  r6  r@  rF  rI  rJ  rO  r   r   r   r   <module>   st    *)

0
gu 
	



