
    ^j                    t    d dl mZ d dlZd dlmZm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  G d d	      Zy)
    )annotationsN)defaultdictdeque)deepcopy)cast)
Detections)SupervisionWarningsc                  2    e Zd ZdZdddZd	dZd
dZddZy)DetectionsSmootheru
  
    A utility class for smoothing detections over multiple frames in video tracking.
    It maintains a history of detections for each track and provides smoothed
    predictions based on these histories.

    <video controls>
        <source
            src="https://media.roboflow.com/supervision-detection-smoothing.mp4"
            type="video/mp4">
    </video>

    !!! warning

        - `DetectionsSmoother` requires the `tracker_id` for each detection. Refer to
          [Roboflow Trackers](/latest/trackers/) for
          information on integrating tracking into your inference pipeline.
        - This class is not compatible with segmentation models.
        - When detections in a frame disagree on confidence presence — some tracks
          carry confidence scores and others do not — `confidence` is set to `None`
          for all smoothed detections in that frame.

    Example:
        ```pycon
        >>> import numpy as np
        >>> import supervision as sv
        >>> smoother = sv.DetectionsSmoother(length=3)
        >>> detections_1 = sv.Detections(
        ...     xyxy=np.array([[0, 0, 10, 10]]),
        ...     confidence=np.array([0.5]),
        ...     tracker_id=np.array([1])
        ... )
        >>> detections_2 = sv.Detections(
        ...     xyxy=np.array([[2, 2, 12, 12]]),
        ...     confidence=np.array([0.7]),
        ...     tracker_id=np.array([1])
        ... )
        >>> smoothed = smoother.update_with_detections(detections_1)
        >>> smoothed.xyxy
        array([[ 0.,  0., 10., 10.]])
        >>> smoothed = smoother.update_with_detections(detections_2)
        >>> smoothed.xyxy
        array([[ 1.,  1., 11., 11.]])
        >>> smoothed.confidence
        array([0.6])

        ```


        ```python
        import supervision as sv

        from ultralytics import YOLO

        video_info = sv.VideoInfo.from_video_path(video_path="<SOURCE_FILE_PATH>")
        frame_generator = sv.get_video_frames_generator(
            source_path="<SOURCE_FILE_PATH>")

        model = YOLO("<MODEL_PATH>")
        tracker = sv.ByteTrack(frame_rate=video_info.fps)
        smoother = sv.DetectionsSmoother()

        box_annotator = sv.BoxAnnotator()

        with sv.VideoSink("<TARGET_FILE_PATH>", video_info=video_info) as sink:
            for frame in frame_generator:
                result = model(frame)[0]
                detections = sv.Detections.from_ultralytics(result)
                detections = tracker.update_with_detections(detections)
                detections = smoother.update_with_detections(detections)

                annotated_frame = box_annotator.annotate(frame.copy(), detections)
                sink.write_frame(annotated_frame)
        ```
    c                ,    t        fd      | _        y)z
        Args:
            length: The maximum number of frames to consider for smoothing
                detections. Defaults to 5.
        c                     t               S )N)maxlen)r   )lengths   o/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/detection/tools/smoother.py<lambda>z-DetectionsSmoother.__init__.<locals>.<lambda>a   s    E(     N)r   tracks)selfr   s    `r   __init__zDetectionsSmoother.__init__Z   s     CN(C
r   c                   |j                   t        j                  dt               |S t	        t        |            D ]K  }|j                   |   }t        |      }| j                  |   j                  t        t        ||                M | j                  j                         D ]/  }||j                   vs| j                  |   j                  d       1 t        | j                  j                               D ]8  }t        | j                  |   D cg c]  }|du  c}      s,| j                  |= : | j                         S c c}w )z
        Updates the smoother with a new set of detections from a frame.

        Args:
            detections: The detections to add to the smoother.
        NzSmoothing skipped. DetectionsSmoother requires tracker_id. Refer to https://supervision.roboflow.com/latest/trackers for more information.)category)
tracker_idwarningswarnr	   rangelenintr   appendr   r   keyslistallget_smoothed_detections)r   
detectionsdetection_idxtracker_id_valuer   track_idds          r   update_with_detectionsz)DetectionsSmoother.update_with_detectionsd   s/      (MM -	 "3z?3 	XM)44]C-.JKK
#**4
J}<U+VW		X ((* 	3Hz444H%,,T2	3 T[[--/0 	*Ht{{8'<=!AI=>KK)	* ++-- >s   E
c                   | j                   j                  |d      }|y|D cg c]  }||	 }}t        |      dk(  ryt        |d         }t	        j
                  |D cg c]  }|j                   c}d      |_        |D cg c]  }|j                  |j                   }}|r1t	        j
                  t	        j                  |      d      |_        |S d|_        |S c c}w c c}w c c}w )aE  Return the smoothed `Detections` for a single track.

        Averages `xyxy` over all valid (non-`None`) frames in the track window.
        `confidence` is averaged only over frames that carry it; frames with
        `confidence=None` are excluded. Returns `None` when the track is unknown
        or its entire window is empty.

        Args:
            track_id: The tracker ID whose smoothed detection to retrieve.

        Returns:
            Smoothed `Detections` for the track, or `None` if the track is
            unknown or all frames in its window are empty.
        Nr   )axis)	r   getr   r   npmeanxyxy
confidencearray)r   r&   trackr'   validretconfidencess          r   	get_trackzDetectionsSmoother.get_track   s     $/=.3"Eq}1"E"Eu:?uQx 77E2qAFF2; .3Oall6Nq||OOCN+!6Q?
 UY
 #F
 3 Ps   C%C%"C*C/C/c                @   g }| j                   D ]'  }| j                  |      }||j                  |       ) |r t        d |D              r|D ]	  }d |_         t        j                  |      }t        |      dk(  r t        j                  g t              |_        |S )Nc              3  8   K   | ]  }|j                   d u   y w)N)r/   ).0r'   s     r   	<genexpr>z=DetectionsSmoother.get_smoothed_detections.<locals>.<genexpr>   s     %Wqalld&:%Ws   r   )dtype)r   r5   r   anyr/   r   merger   r,   r0   r   r   )r   tracked_detectionsr&   r1   r'   r#   s         r   r"   z*DetectionsSmoother.get_smoothed_detections   s     	1HNN8,E "))%0	1 #%WDV%W"W' $#$  %%&89
z?a$&HHRs$;J!r   N)   )r   r   returnNone)r#   r   r?   r   )r&   r   r?   zDetections | None)r?   r   )__name__
__module____qualname____doc__r   r(   r5   r"    r   r   r   r      s    IV
.BBr   r   )
__future__r   r   collectionsr   r   copyr   typingr   numpyr,   supervision.detection.corer   supervision.utils.internalr	   r   rE   r   r   <module>rM      s)    "  *    1 :j jr   