Ë
    ¼Ó^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   € ô Ÿ7™7Ÿ?™?¨4¯>©>Ó:ÐÙ¤B§G¡G§N¡NÐ3CÔ$DÜ�K‰KÐ(Ô)ä˜Ÿ™¨Ó-ˆ�	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]   € ô" �eœRŸZ™ZÔ(Ø—:‘:“<ÐÜ�eœRŸZ™ZÔ(Ø—<‘<“>Ð!ÜØœd 5›k×2Ñ2Ð3Ð3LÐ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   € ð �9Š9ð"Ü—	‘	Ø—I‘I˜tŸy™y°¼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   € ô( �eœRŸZ™ZÔ(Ø!ŸJ™J¨!šO�5Ð9°°q±Ð9Ü�eœd¤E˜]Ô+´°E³
¸a²Ø˜‘8ˆOØˆ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ô  �z 6Ô*Ø",§/¡/×"7Ñ"7Ó"9ò G‘J�C˜Ü"¤8×#8Ñ#8¸ÀÀ1Ó#EÓF�C˜’HðGñ Ø"-×"3Ñ"3Ó"5ò N‘J�C˜Ü ×-Ñ-¨e°Q¸Ó:�AÜ)3°E¼2¿:¹:Ô)Fœs 1œvÈA�C˜’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Ñ3°JÀÓ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   