o
    Vhso                     @   s:  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m	Z	 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mZmZ d dlmZmZmZmZ d d	lmZ d d
lmZ eG dd dZ G dd dZ!G dd dZ"G dd dZ#G dd dZ$G dd dZ%dd Z&dddZ'e!e$e#e"fZ(dS )    N)	dataclass)Path)Thread)urlparse)Image)FORMATS_HELP_MSGIMG_FORMATSVID_FORMATS)IS_COLAB	IS_KAGGLELOGGERops)check_requirements)imreadc                   @   sB   e Zd ZU dZdZeed< dZeed< dZeed< dZ	eed< dS )SourceTypesa  
    Class to represent various types of input sources for predictions.

    This class uses dataclass to define boolean flags for different types of input sources that can be used for
    making predictions with YOLO models.

    Attributes:
        stream (bool): Flag indicating if the input source is a video stream.
        screenshot (bool): Flag indicating if the input source is a screenshot.
        from_img (bool): Flag indicating if the input source is an image file.
        tensor (bool): Flag indicating if the input source is a tensor.

    Examples:
        >>> source_types = SourceTypes(stream=True, screenshot=False, from_img=False)
        >>> print(source_types.stream)
        True
        >>> print(source_types.from_img)
        False
    Fstream
screenshotfrom_imgtensorN)
__name__
__module____qualname____doc__r   bool__annotations__r   r   r    r   r   L/var/www/vscode/kcb/lib/python3.10/site-packages/ultralytics/data/loaders.pyr      s   
 r   c                   @   sB   e Zd ZdZdddZdd Zd	d
 Zdd Zdd Zdd Z	dS )LoadStreamsa  
    Stream Loader for various types of video streams.

    Supports RTSP, RTMP, HTTP, and TCP streams. This class handles the loading and processing of multiple video
    streams simultaneously, making it suitable for real-time video analysis tasks.

    Attributes:
        sources (List[str]): The source input paths or URLs for the video streams.
        vid_stride (int): Video frame-rate stride.
        buffer (bool): Whether to buffer input streams.
        running (bool): Flag to indicate if the streaming thread is running.
        mode (str): Set to 'stream' indicating real-time capture.
        imgs (List[List[np.ndarray]]): List of image frames for each stream.
        fps (List[float]): List of FPS for each stream.
        frames (List[int]): List of total frames for each stream.
        threads (List[Thread]): List of threads for each stream.
        shape (List[Tuple[int, int, int]]): List of shapes for each stream.
        caps (List[cv2.VideoCapture]): List of cv2.VideoCapture objects for each stream.
        bs (int): Batch size for processing.

    Methods:
        update: Read stream frames in daemon thread.
        close: Close stream loader and release resources.
        __iter__: Returns an iterator object for the class.
        __next__: Returns source paths, transformed, and original images for processing.
        __len__: Return the length of the sources object.

    Examples:
        >>> stream_loader = LoadStreams("rtsp://example.com/stream1.mp4")
        >>> for sources, imgs, _ in stream_loader:
        ...     # Process the images
        ...     pass
        >>> stream_loader.close()

    Notes:
        - The class uses threading to efficiently load frames from multiple streams simultaneously.
        - It automatically handles YouTube links, converting them to the best available stream URL.
        - The class implements a buffer system to manage frame storage and retrieval.
    file.streams   Fc                 C   s  dt jj_|| _d| _d| _|| _tj	
|rt|  n|g}t|}|| _dg| | _dg| | _dg| | _dg| | _dd t|D | _dd t|D | _dd |D | _t|D ]\}}|d	  d
| d| d}t|jdv r}t|}| rt|n|}|dkrtstrt dt!"|| j|< | j| # st$| d| t%| j| &t!j'}t%| j| &t!j(}	| j| &t!j)}
t*t%| j| &t!j+dpt,d| j|< t*t-.|
r|
ndd dpd| j|< | j| / \}}|r|du rt$| d| | j| 0| |j| j|< t1| j2|| j| |gdd| j|< t34| d| j|  d| d|	 d| j| dd
 | j| 5  qat34d dS )zUInitialize stream loader for multiple video sources, supporting various stream types.Tr   r   Nc                 S      g | ]}g qS r   r   .0_r   r   r   
<listcomp>l       z(LoadStreams.__init__.<locals>.<listcomp>c                 S   r    r   r   r!   r   r   r   r$   m   r%   c                 S   s    g | ]}t |tjd qS )r#   )r   	clean_strreplaceossepr"   xr   r   r   r$   n   s     r   /: z... >   youtu.beyoutube.comwww.youtube.comzm'source=0' webcam not supported in Colab and Kaggle notebooks. Try running 'source=0' in a local environment.zFailed to open infd      zFailed to read images from )targetargsdaemonu   Success ✅ (z frames of shape r+   z at z.2fz FPS) )6torchbackendscudnn	benchmarkbufferrunningmode
vid_strider(   pathisfiler   	read_textrsplitlenbsfpsframesthreadscapsrangeimgsshapesources	enumerater   hostnameget_best_youtube_url	isnumericevalr
   r   NotImplementedErrorcv2VideoCaptureisOpenedConnectionErrorintgetCAP_PROP_FRAME_WIDTHCAP_PROP_FRAME_HEIGHTCAP_PROP_FPSmaxCAP_PROP_FRAME_COUNTfloatmathisfinitereadappendr   updater   infostart)selfrM   r?   r<   nisstwhrF   successimr   r   r   __init__]   sV   
"
&"6zLoadStreams.__init__c                 C   s   d| j | }}| jrq| rs||d k rut| j| dk r]|d7 }|  || j dkr\| \}}|sJtj	| j
| tjd}td || | jrV| j| | n|g| j|< ntd | jrw| ry||d k sdS dS dS dS dS dS )z<Read stream frames in daemon thread and update image buffer.r   r   r3   dtypezBVideo stream unresponsive, please check your IP camera connection.g{Gz?N)rG   r=   rV   rD   rK   grabr?   retrievenpzerosrL   uint8r   warningopenr<   rc   timesleep)rg   ri   capr   rh   frn   ro   r   r   r   rd      s"   


2zLoadStreams.updatec                 C   s~   d| _ | jD ]}| r|jdd q| jD ]"}z|  W q ty8 } ztd|  W Y d}~qd}~ww t	
  dS )zNTerminates stream loader, stops threads, and releases video capture resources.F   )timeoutz'Could not release VideoCapture object: N)r=   rH   is_alivejoinrI   release	Exceptionr   rx   rT   destroyAllWindows)rg   threadr|   er   r   r   close   s   

zLoadStreams.closec                 C   
   d| _ | S )zCIterates through YOLO image feed and re-opens unresponsive streams.countrg   r   r   r   __iter__      zLoadStreams.__iter__c                 C   s   |  j d7  _ g }t| jD ]\\}}|sE| j|  r$tdtdkr*|   t	t
dt| j  | j| }|sCtd|  |r| jrQ||d q||rZ|dn
tj| j| tjd |  q| j|dg| j fS )zLReturns the next batch of frames from multiple video streams for processing.r   qzWaiting for stream r   r   rq   r7   )r   rN   rK   rH   r   rT   waitKeyordr   StopIterationrz   r{   minrF   r   rx   r<   rc   popru   rv   rL   rw   clearrM   rE   )rg   imagesri   r+   r   r   r   __next__   s"    

*
zLoadStreams.__next__c                 C      | j S )z=Return the number of video streams in the LoadStreams object.rE   r   r   r   r   __len__      zLoadStreams.__len__N)r   r   F)
r   r   r   r   rp   rd   r   r   r   r   r   r   r   r   r   4   s    
(3r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	LoadScreenshotsa  
    Ultralytics screenshot dataloader for capturing and processing screen images.

    This class manages the loading of screenshot images for processing with YOLO. It is suitable for use with
    `yolo predict source=screen`.

    Attributes:
        source (str): The source input indicating which screen to capture.
        screen (int): The screen number to capture.
        left (int): The left coordinate for screen capture area.
        top (int): The top coordinate for screen capture area.
        width (int): The width of the screen capture area.
        height (int): The height of the screen capture area.
        mode (str): Set to 'stream' indicating real-time capture.
        frame (int): Counter for captured frames.
        sct (mss.mss): Screen capture object from `mss` library.
        bs (int): Batch size, set to 1.
        fps (int): Frames per second, set to 30.
        monitor (Dict[str, int]): Monitor configuration details.

    Methods:
        __iter__: Returns an iterator object.
        __next__: Captures the next screenshot and returns it.

    Examples:
        >>> loader = LoadScreenshots("0 100 100 640 480")  # screen 0, top-left (100,100), 640x480
        >>> for source, im, im0s, vid_cap, s in loader:
        ...     print(f"Captured frame: {im.shape}")
    c           	      C   s6  t d ddl}| ^}}d\| _}}}}t|dkr$t|d | _n%t|dkr6dd |D \}}}}nt|d	krId
d |D \| _}}}}d| _d| _| | _d| _	d| _
| jj| j }|du ri|d n|d | | _|du rx|d n|d | | _|p|d | _|p|d | _| j| j| j| jd| _dS )zJInitialize screenshot capture with specified screen and region parameters.mssr   N)r   NNNNr      c                 s       | ]}t |V  qd S NrX   r*   r   r   r   	<genexpr>       z+LoadScreenshots.__init__.<locals>.<genexpr>r~   c                 s   r   r   r   r*   r   r   r   r     r   r   r3   topleftwidthheight)r   r   r   r   )r   r   splitscreenrD   rX   r>   framesctrE   rF   monitorsr   r   r   r   monitor)	rg   sourcer   paramsr   r   r   r   r   r   r   r   rp      s*   
zLoadScreenshots.__init__c                 C   s   | S )zTYields the next screenshot image from the specified screen or region for processing.r   r   r   r   r   r     s   zLoadScreenshots.__iter__c                 C   s|   t | j| jddddddf }d| j d| j d| j d| j d| j	 d}|  j
d7  _
t| jg|g|gfS )zPCaptures and returns the next screenshot as a numpy array using the mss library.N   zscreen z	 (LTWH): ,r-   r   )ru   asarrayr   rs   r   r   r   r   r   r   r   str)rg   im0rj   r   r   r   r     s   *.zLoadScreenshots.__next__N)r   r   r   r   rp   r   r   r   r   r   r   r      s
    r   c                   @   s:   e Zd ZdZdddZdd Zdd Zd	d
 Zdd ZdS )LoadImagesAndVideosa  
    A class for loading and processing images and videos for YOLO object detection.

    This class manages the loading and pre-processing of image and video data from various sources, including
    single image files, video files, and lists of image and video paths.

    Attributes:
        files (List[str]): List of image and video file paths.
        nf (int): Total number of files (images and videos).
        video_flag (List[bool]): Flags indicating whether a file is a video (True) or an image (False).
        mode (str): Current mode, 'image' or 'video'.
        vid_stride (int): Stride for video frame-rate.
        bs (int): Batch size.
        cap (cv2.VideoCapture): Video capture object for OpenCV.
        frame (int): Frame counter for video.
        frames (int): Total number of frames in the video.
        count (int): Counter for iteration, initialized at 0 during __iter__().
        ni (int): Number of images.

    Methods:
        __init__: Initialize the LoadImagesAndVideos object.
        __iter__: Returns an iterator object for VideoStream or ImageFolder.
        __next__: Returns the next batch of images or video frames along with their paths and metadata.
        _new_video: Creates a new video capture object for the given path.
        __len__: Returns the number of batches in the object.

    Examples:
        >>> loader = LoadImagesAndVideos("path/to/data", batch=32, vid_stride=1)
        >>> for paths, imgs, info in loader:
        ...     # Process batch of images or video frames
        ...     pass

    Notes:
        - Supports various image formats including HEIC.
        - Handles both local files and directories.
        - Can read from a text file containing paths to images and videos.
    r   c              
   C   s  d}t |trt|jdkrt|j}t|  }g }t |ttfr(t	|n|gD ]W}tt|
 }d|v rF|t	tj|dd q+tj|r\|t	ttj|d q+tj|rh|| q+|r|||  r||t|| 
  q+t| dg g }}	|D ]}
|
dd	  }|tv r||
 q|tv r|	|
 qt|t|	}}||	 | _|| | _|| _d
g| dg|  | _|dkrdnd| _|| _|| _ t!|	r| "|	d  nd| _#| jdkrtd| dt$ dS )zNInitialize dataloader for images and videos, supporting various input formats.Nz.txt*T)	recursivez*.*z does not exist.r   Fr   videoimagezNo images or videos found in z. )%
isinstancer   r   suffixparentrB   
splitlineslisttuplesortedabsoluteextendglobr(   r@   isdirr   rA   rc   is_fileFileNotFoundErrorr   lowerr   r	   rD   filesnfni
video_flagr>   r?   rE   any
_new_videor|   r   )rg   r@   batchr?   r   r   par   videosr}   r   r   nvr   r   r   rp   D  sL   
  




zLoadImagesAndVideos.__init__c                 C   r   )zPIterates through image/video files, yielding source paths, images, and metadata.r   r   r   r   r   r   r   p  r   zLoadImagesAndVideos.__iter__c           
      C   sx  g g g }}}t || jk r7| j| jkr|r|||fS t| j| j }| j| j rd| _| jr6| j	 s;| 
| d}t| jD ]}| j }|sM nqB|r| j \}}|r|  jd7  _|| || |d| jd  d| j d| j d| j d| d | j| jkr|  jd7  _| j  n|  jd7  _| jr| j  | j| jk r| 
| j| j  nyd	| _|d
d  dkrtd ddlm} |  t|}	tt|	tj}W d   n1 sw   Y  nt|}|du rt !d|  n|| || |d| jd  d| j d| d |  jd7  _| j| j"kr0nt || jk s|||fS )zOReturns the next batch of images or video frames with their paths and metadata.r   Fr   zvideo r,   z (frame z) r-   r   r   r   heiczpillow-heifr   )register_heif_openerNzImage Read Error zimage  )#rD   rE   r   r   r   r   r   r>   r|   rV   r   rJ   r?   rs   rt   r   rc   rG   r   r   r   r   pillow_heifr   r   ry   rT   cvtColorru   r   COLOR_RGB2BGRr   r   rx   r   )
rg   pathsrK   re   r@   rn   r#   r   r   imgr   r   r   r   u  sl   




6




&
<zLoadImagesAndVideos.__next__c                 C   s\   d| _ t|| _t| jtj| _| j st	d| t| jtj
| j | _dS )z_Creates a new video capture object for the given path and initializes video-related attributes.r   zFailed to open video N)r   rT   rU   r|   rX   rY   r\   rF   rV   r   r^   r?   rG   )rg   r@   r   r   r   r     s   
zLoadImagesAndVideos._new_videoc                 C   s   t | j| j S )z?Returns the number of files (images and videos) in the dataset.)r`   ceilr   rE   r   r   r   r   r     s   zLoadImagesAndVideos.__len__N)r   r   )	r   r   r   r   rp   r   r   r   r   r   r   r   r   r     s    
&,A	r   c                   @   s<   e Zd ZdZdd Zedd Zdd Zdd	 Zd
d Z	dS )LoadPilAndNumpya3  
    Load images from PIL and Numpy arrays for batch processing.

    This class manages loading and pre-processing of image data from both PIL and Numpy formats. It performs basic
    validation and format conversion to ensure that the images are in the required format for downstream processing.

    Attributes:
        paths (List[str]): List of image paths or autogenerated filenames.
        im0 (List[np.ndarray]): List of images stored as Numpy arrays.
        mode (str): Type of data being processed, set to 'image'.
        bs (int): Batch size, equivalent to the length of `im0`.

    Methods:
        _single_check: Validate and format a single image to a Numpy array.

    Examples:
        >>> from PIL import Image
        >>> import numpy as np
        >>> pil_img = Image.new("RGB", (100, 100))
        >>> np_img = np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)
        >>> loader = LoadPilAndNumpy([pil_img, np_img])
        >>> paths, images, _ = next(iter(loader))
        >>> print(f"Loaded {len(images)} images")
        Loaded 2 images
    c                    sN   t |ts|g}dd t|D  _ fdd|D  _d _t j _dS )zZInitializes a loader for PIL and Numpy images, converting inputs to a standardized format.c                 S   s(   g | ]\}}t |d dpd| dqS )filenamer7   r   .jpggetattrr"   ri   ro   r   r   r   r$     s   ( z,LoadPilAndNumpy.__init__.<locals>.<listcomp>c                    s   g | ]}  |qS r   )_single_check)r"   ro   r   r   r   r$     s    r   N)r   r   rN   r   r   r>   rD   rE   rg   r   r   r   r   rp     s   
zLoadPilAndNumpy.__init__c                 C   st   t | tjtjfsJ dt|  t | tjr8| jdkr"| d} t| dddddddf } t| } | S )zVValidate and format an image to numpy array, ensuring RGB order and contiguous memory.z,Expected PIL/np.ndarray image type, but got RGBNr   )	r   r   ru   ndarraytyper>   convertr   ascontiguousarray)ro   r   r   r   r     s   $

"
zLoadPilAndNumpy._single_checkc                 C   s
   t | jS )zTReturns the length of the 'im0' attribute, representing the number of loaded images.)rD   r   r   r   r   r   r     s   
zLoadPilAndNumpy.__len__c                 C   2   | j dkrt|  j d7  _ | j| jdg| j fS )zEReturns the next batch of images, paths, and metadata for processing.r   r7   r   r   r   r   rE   r   r   r   r   r        
zLoadPilAndNumpy.__next__c                 C   r   )z[Iterates through PIL/numpy images, yielding paths, raw images, and metadata for processing.r   r   r   r   r   r   r     r   zLoadPilAndNumpy.__iter__N)
r   r   r   r   rp   staticmethodr   r   r   r   r   r   r   r   r     s    


r   c                   @   s@   e Zd ZdZdddZedddZd	d
 Zdd Zdd Z	dS )
LoadTensoraf  
    A class for loading and processing tensor data for object detection tasks.

    This class handles the loading and pre-processing of image data from PyTorch tensors, preparing them for
    further processing in object detection pipelines.

    Attributes:
        im0 (torch.Tensor): The input tensor containing the image(s) with shape (B, C, H, W).
        bs (int): Batch size, inferred from the shape of `im0`.
        mode (str): Current processing mode, set to 'image'.
        paths (List[str]): List of image paths or auto-generated filenames.

    Methods:
        _single_check: Validates and formats an input tensor.

    Examples:
        >>> import torch
        >>> tensor = torch.rand(1, 3, 640, 640)
        >>> loader = LoadTensor(tensor)
        >>> paths, images, info = next(iter(loader))
        >>> print(f"Processed {len(images)} images")
    returnNc                 C   s8   |  || _| jjd | _d| _dd t|D | _dS )zDInitialize LoadTensor object for processing torch.Tensor image data.r   r   c                 S   s$   g | ]\}}t |d d| dqS )r   r   r   r   r   r   r   r   r$   "  s   $ z'LoadTensor.__init__.<locals>.<listcomp>N)r   r   rL   rE   r>   rN   r   r   r   r   r   rp     s   zLoadTensor.__init__    c                 C   s   d| dt | j d}t| jdkr(t| jdkrt|t| | d} | jd | s6| jd | r:t||  dt	| j
j krXtd	|   d
 |  d } | S )zVValidates and formats a single image tensor, ensuring correct shape and normalization.zRtorch.Tensor inputs should be BCHW i.e. shape(1, 3, 640, 640) divisible by stride z. Input shapez is incompatible.r   r   r      g      ?zBtorch.Tensor inputs should be normalized 0.0-1.0 but max value is z. Dividing input by 255.g     o@)r   rL   rD   
ValueErrorr   rx   	unsqueezer]   r8   finforr   epsr_   )ro   striderj   r   r   r   r   $  s&   

zLoadTensor._single_checkc                 C   r   )zBYields an iterator object for iterating through tensor image data.r   r   r   r   r   r   r   :  r   zLoadTensor.__iter__c                 C   r   )zCYields the next batch of tensor images and metadata for processing.r   r7   r   r   r   r   r   r   ?  r   zLoadTensor.__next__c                 C   r   )z+Returns the batch size of the tensor input.r   r   r   r   r   r   F  r   zLoadTensor.__len__)r   N)r   )
r   r   r   r   rp   r   r   r   r   r   r   r   r   r   r     s    
r   c              	   C   s   g }| D ]:}t |ttfr%|tt|dr tj|ddj	n| qt |tjt
jfr4|| qtdt|j d|S )z^Merges a list of sources into a list of numpy arrays or PIL images for Ultralytics prediction.httpT)r   ztype z is not a supported Ultralytics prediction source type. 
See https://docs.ultralytics.com/modes/predict for supported source types.)r   r   r   rc   r   ry   
startswithrequestsrY   rawru   r   	TypeErrorr   r   )r   r   ro   r   r   r   autocast_listK  s   0r   pytubec                 C   sn  |dkr;t d ddlm} || jjddd}t|dd	 dd
}|D ]}|jr8t|jdd dkr8|j  S q#dS |dkrQt d ddl	}|
| jddjS |dkrt d ddl}|ddi}|j| dd}W d   n1 svw   Y  t|dg D ]1}	|	dpddkp|	dpddk}
|
r|	d dkr|	d dkr|	d dkr|	d  S qdS dS )a  
    Retrieves the URL of the best quality MP4 video stream from a given YouTube video.

    Args:
        url (str): The URL of the YouTube video.
        method (str): The method to use for extracting video info. Options are "pytube", "pafy", and "yt-dlp".
            Defaults to "pytube".

    Returns:
        (str | None): The URL of the best quality MP4 video stream, or None if no suitable stream is found.

    Examples:
        >>> url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
        >>> best_url = get_best_youtube_url(url)
        >>> print(best_url)
        https://rr4---sn-q4flrnek.googlevideo.com/videoplayback?expire=...

    Notes:
        - Requires additional libraries based on the chosen method: pytubefix, pafy, or yt-dlp.
        - The function prioritizes streams with at least 1080p resolution when available.
        - For the "yt-dlp" method, it looks for formats with video codec, no audio, and *.mp4 extension.
    r   zpytubefix>=6.5.2r   )YouTubemp4T)file_extension
only_videoc                 S   r   r   )
resolution)rj   r   r   r   <lambda>y  s    z&get_best_youtube_url.<locals>.<lambda>)keyreverseNr   i8  pafy)r  zyoutube_dl==2020.12.2)preftypezyt-dlpquietF)downloadformatsr   i  r   vcodecnoneacodecexturl)r   	pytubefixr   streamsfilterr   r  rX   r  r  newgetbestvideoyt_dlp	YoutubeDLextract_inforeversedrY   )r  methodr   r  r   r  r  ydl	info_dictr}   	good_sizer   r   r   rP   \  s6   
$(rP   )r   ))r   r`   r(   rz   dataclassesr   pathlibr   	threadingr   urllib.parser   rT   numpyru   r   r8   PILr   ultralytics.data.utilsr   r   r	   ultralytics.utilsr
   r   r   r   ultralytics.utils.checksr   ultralytics.utils.patchesr   r   r   r   r   r   r   r   rP   LOADERSr   r   r   r   <module>   s:    #G (AF
6