
    ^j                    \    d dl mZ d dlZd dlZd dlZd dlmZ d dlZd dl	m
Z
  G d d      Zy)    )annotationsN)Any)
Detectionsc                      e Zd ZdZdddZddZ	 	 	 	 	 	 	 	 ddZddZedd       Z	ddZ
edd       Ze	 d	 	 	 	 	 dd
       Z	 d	 	 	 	 	 ddZy	)JSONSinka  
    A utility class for saving detection data to a JSON file. This class is designed to
    efficiently serialize detection objects into a JSON format, allowing for the
    inclusion of bounding box coordinates and additional attributes like `confidence`,
    `class_id`, and `tracker_id`.

    !!! tip

        JSONSink allows passing custom data alongside detection fields, providing
        flexibility for logging various types of information.
        When a list or tuple value in custom_data (or detections.data) has the
        same length as the detection count, each element is written to the
        corresponding detection row; any other value is broadcast to all rows.
        NumPy scalars (e.g. ``np.int64``, ``np.float32``) are serialized as
        JSON numbers; NumPy arrays are serialized as JSON arrays.

    Args:
        file_name: The name of the JSON file where the detections will be stored.
            Defaults to 'output.json'.

    Example:
        ```python
        import supervision as sv
        from ultralytics import YOLO

        model = YOLO("<SOURCE_MODEL_PATH>")
        json_sink = sv.JSONSink(<RESULT_JSON_FILE_PATH>)
        frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")

        with json_sink as sink:
            for frame in frames_generator:
                result = model(frame)[0]
                detections = sv.Detections.from_ultralytics(result)
                sink.append(detections, custom_data={"<CUSTOM_LABEL>":"<CUSTOM_DATA>"})
        ```
    c                .    || _         d| _        g | _        y)zt
        Initialize the JSONSink instance.

        Args:
            file_name: The name of the JSON file.
        N)	file_namefiledata)selfr	   s     p/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/detection/tools/json_sink.py__init__zJSONSink.__init__3   s     #-1	*,	    c                &    | j                          | S N)openr   s    r   	__enter__zJSONSink.__enter__>   s    		r   c                $    | j                          y r   )write_and_close)r   exc_typeexc_valexc_tbs       r   __exit__zJSONSink.__exit__B   s     	r   c                    t         j                  j                  | j                        }|r4t         j                  j	                  |      st        j
                  |       t        | j                  d      | _        y)z1
        Open the JSON file for writing.
        wN)ospathdirnamer	   existsmakedirsr   r
   )r   parent_directorys     r   r   zJSONSink.openJ   sM     77??4>>:BGGNN3C$DKK()-	r   c                    t        | t        j                        r| j                         S t        | t        j                        r| j                         S t        dt        |       j                   d      )a  Return a JSON-serializable equivalent of a NumPy scalar or array.

        Called as the ``default`` hook by :func:`json.dump`. Converts
        :class:`numpy.generic` scalars via ``.item()`` and
        :class:`numpy.ndarray` instances via ``.tolist()``.

        Args:
            value: Object the standard JSON encoder could not serialize.

        Returns:
            A Python scalar or nested list equivalent of ``value``.

        Raises:
            TypeError: If ``value`` is neither a NumPy scalar nor an ndarray.
        zObject of type z is not JSON serializable)	
isinstancenpgenericitemndarraytolist	TypeErrortype__name__)values    r   _json_defaultzJSONSink._json_defaultT   s]    " eRZZ(::<eRZZ(<<>!d5k2233LM
 	
r   c                   | j                   rW	 t        j                  | j                  | j                   dt        j
                         | j                   j                          yy# | j                   j                          w xY w)z0
        Write and close the JSON file.
           )indentdefaultN)r
   jsondumpr   r   r.   closer   s    r   r   zJSONSink.write_and_closem   sZ     99"		IItyyH<R<R 		!  		!s   ;A% %Bc                    t        | t        j                        r| j                  dk(  r| S | |   S t        | t        t
        f      rt        |       |k(  r| |   S | S )a{  
        Return the i-th element when the value stores per-detection data.

        Dispatch rules:
            - np.ndarray with ndim == 0: return as-is for broadcasting
            - np.ndarray with ndim >= 1: return value[i]
            - list or tuple with len equal to n: return value[i]
            - any other type: return as-is for broadcasting

        Args:
            value: Custom-data field value.
            i: Zero-based detection index.
            n: Total number of detections.

        Returns:
            Element at position i if value is a per-detection sequence,
            otherwise value unchanged.
        r   )r$   r%   r(   ndimlisttuplelen)r-   ins      r   _slice_valuezJSONSink._slice_valuey   sQ    ( eRZZ(!JJ!O59q9edE]+E
a8Or   Nc                   g }t        | j                        }t        |      D ]  }t        | j                  |   d         t        | j                  |   d         t        | j                  |   d         t        | j                  |   d         | j                  dnt        | j                  |         | j                  dnt        | j                  |         | j                  dnt        | j                  |         d}t        | d      rE| j                  j                         D ](  \  }}t        t        j                  |||            ||<   * |rY|j                         D ]F  \  }}t        j                  |||      }t        |t        j                         rt        |      n|||<   H |j#                  |        |S )aK  
        Convert detections and optional custom data into per-detection rows.

        Builds one dictionary per detection containing bounding box coordinates,
        detection attributes, and any values from ``detections.data`` or
        ``custom_data``. List and tuple values in ``custom_data`` with length
        equal to ``len(detections.xyxy)`` are sliced one element per row; all
        other values are broadcast to every row.

        Args:
            detections: Detection data to serialize into row dictionaries.
            custom_data: Optional extra fields to include in each row.

        Returns:
            A list of dictionaries, one per detection, containing ``xyxy``
            coordinates, ``class_id``, ``confidence``, ``tracker_id``, and any
            values from ``detections.data`` or ``custom_data``.
        r             )x_miny_minx_maxy_maxclass_id
confidence
tracker_idr   )r:   xyxyrangefloatrG   intrH   rI   hasattrr   itemsstrr   r=   r$   r%   r(   append)	
detectionscustom_dataparsed_rowsr<   r;   rowkeyr-   vs	            r   parse_detection_datazJSONSink.parse_detection_data   s   , 
 q 	$Azq1!45zq1!45zq1!45zq1!45&&. ,,Q/0((0 !:0034((0 !..q12C  z6*",//"7"7"9 GJC"8#8#81#EFCHG "-"3"3"5 NJC --eQ:A)3E2::)Fs1vACHN s#5	$6 r   c                f    t         j                  ||      }| j                  j                  |       y)a  
        Append detection data to the JSON file.

        Args:
            detections: The detection data.
            custom_data: Custom data to include. Scalars, dictionaries, and
                other non-sequence values are broadcast to every detection in
                this batch. NumPy arrays, lists, and tuples with length equal
                to ``len(detections)`` are sliced per detection; other lists
                and tuples are broadcast unchanged.
        N)r   rX   r   extend)r   rR   rS   rT   s       r   rQ   zJSONSink.append   s(     33JL		%r   )zoutput.json)r	   rP   returnNone)r[   r   )r   ztype | Noner   zException | Noner   z
Any | Noner[   r\   )r[   r\   )r-   r   r[   r   )r-   r   r;   rM   r<   rM   r[   r   r   )rR   r   rS   dict[str, Any] | Noner[   zlist[dict[str, Any]])rR   r   rS   r]   r[   r\   )r,   
__module____qualname____doc__r   r   r   r   staticmethodr.   r   r=   rX   rQ    r   r   r   r      s    #J	- " 	
 
. 
 
0
"  2 EI22-B2	2 2j LP&$&3H&	&r   r   )
__future__r   ior3   r   typingr   numpyr%   supervision.detection.corer   r   rb   r   r   <module>rh      s&    " 	  	   1J& J&r   