
    ^j|G                       d dl mZ d dlZd dlZd dlmZ d dlmZm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mZ d d	lmZmZ d d
lmZmZmZmZmZ erd dlmZ ddZ ddZ!ddZ"	 	 	 	 	 	 ddZ#ddZ$ddZ%ddZ&	 d	 	 	 	 	 	 	 	 	 d dZ'	 	 d!	 	 	 	 	 	 	 	 	 	 	 d"dZ(	 d#	 	 	 	 	 	 	 	 	 d$dZ)	 	 	 	 d%	 	 	 	 	 	 	 	 	 	 	 	 	 d&dZ*	 	 	 	 d%	 	 	 	 	 	 	 	 	 	 	 	 	 d'dZ+d(dZ,y))    )annotationsN)Path)TYPE_CHECKINGAny)Image)ORIENTED_BOX_COORDINATES)approximate_mask_with_polygons)
Detections)polygon_to_maskpolygon_to_xyxy)list_files_with_extensionsread_txt_fileread_yaml_filesave_text_filesave_yaml_file)DetectionDatasetc           	     "   | \  }}}}t        j                  t        |      t        |      dz  z
  t        |      t        |      dz  z
  t        |      t        |      dz  z   t        |      t        |      dz  z   gt         j                        S )N   dtype)nparrayfloatfloat32)valuesx_centery_centerwidthheights        k/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/dataset/formats/yolo.py
_parse_boxr!      s    (.%Hhv88(OeElQ..(OeFma//(OeElQ..(OeFma//		
 jj     c                t    t        j                  | d   | d   g| d   | d   g| d   | d   g| d   | d   gg      S )Nr      r      )r   r   boxs    r    _box_to_polygonr(   )   sS    88
a&#a&	CFCF+c!fc!f-=AA?OP r"   c                l    t        j                  | t         j                        j                  dd      S )Nr   r   )r   r   r   reshaper   s    r    _parse_polygonr-   /   s$    88F"**-55b!<<r"   c           
         t        j                  | D cg c]?  }t        t        j                  |      j	                  t         j
                        |      A c}t              S c c}w )N)polygonresolution_whr   )r   r   r   roundastypeint32bool)polygonsr0   r/   s      r    _polygons_to_masksr6   3   s\     88 $	

 	 )00:+	
 	 		
s   AA%c           	     r    t        | D cg c]  }t        |j                               dkD    c}      S c c}w )N   )anylensplit)lineslines     r    _with_seg_maskr>   B   s+    %8$DJJL!A%8998s   #4c           	     t   t        |       }t        |t              s%t        d|  dt	        |      j
                   d      |j                  d      }t        |t              rt        |j                               }dd}|D cg c]
  } ||       }}t        |      rjt        |      s_t        ||      D cg c]
  \  }}|s	| c}}dd }t        ||      D cg c]
  \  }}|r	| c}}dd }	t        d	|  d
| d|	 d      t        |      rt        |d       }
nt        |t              }
|
D cg c]  }t        ||          c}S t        |t              r|D cg c]  }t        |       c}S t        d|  dt	        |      j
                   d      c c}w c c}}w c c}}w c c}w c c}w )a  Return class names from a YOLO data.yaml file ordered by class index.

    Supports list and dict forms of the ``names`` field. Dict keys that are
    all int-like (plain ints or digit strings) are sorted numerically so
    class index 10 follows index 9. All-non-numeric keys are sorted
    lexicographically. Mixed numeric/non-numeric keys raise ``ValueError``.
    Boolean YAML keys (``true``/``false``) are excluded from numeric sorting
    because ``bool`` is a subclass of ``int`` in Python.

    Args:
        file_path: Path to the data.yaml file.

    Returns:
        Class names in class-index order.

    Raises:
        ValueError: If the YAML root is not a mapping, if ``names`` is
            neither a list nor a dict, or if the dict has mixed key types.
    	file_pathz"Expected mapping in data.yaml at 'z', got .namesc                    t        | t              ryt        | t              ryt        | t              r | j	                         }|j                         S y)NFT)
isinstancer4   intstrstripisdigit)keystrippeds     r    _is_int_likez*_extract_class_names.<locals>._is_int_liked   sC    #t$#s##s#99;''))r"   Nr%   z'Expected 'names' dict in data.yaml at 'zI' to have either all numeric or all non-numeric keys, got a mix: numeric z and non-numeric z keys.c                    t        |       S N)rF   )ks    r    <lambda>z&_extract_class_names.<locals>.<lambda>y   s
    SV r"   )rJ   z7Expected 'names' to be a list or dict in data.yaml at ')rJ   r   returnr4   )r   rE   dict
ValueErrortype__name__getlistkeysr9   allzipsortedrG   )rA   datarC   rX   rL   rO   int_likeilmixed_numericmixed_othersorted_keysrJ   names                r    _extract_class_namesrc   F   s   ( *I>DdD!0 <J''(+
 	
 HHWE%EJJL!		 .22LO22x=X,/h,?F51b2QFrJM*-dH*=HBR1H!LK9) E(/):;-vO 
 x= +;<K 3/K+67CE#J77%&+,dD	,,
	;gd5k2231	6 ! 3FH 8,s*   F:
F$F$
F**F*9F0%F5c                P    t         j                  j                  |       \  }}|dz   S )N.txt)ospathsplitext)
image_name	base_name_s      r    _image_name_to_annotation_namerl      s%    77##J/LIqvr"   c                   t        |       dk(  rt        j                         S g g g g f\  }}}}|\  }}	| D ]  }
|
j                         }|j	                  t        |d                t        |      dk(  r?t        |dd        }|j	                  |       |sa|j	                  t        |             }t        |      dkD  st        |dd        }|j	                  t        |             |r'|j	                  t        j                  |dd               |s|j	                  |        t        j                  |t
              }t        j                  |t        j                        }|t        j                  ||	||	gt        j                        z  }i }|rkt        j                  |t        j                        }|j                  dd	d
      }|t        j                  ||	gt        j                        z  }||t        <   |st        |||      S |D cg c]*  }|t        j                  |t        j                        z  , }}t        ||      }t        ||||      S c c}w )Nr   r8   r$   r,   r&   r/   r   r*      r   )class_idxyxyr\   )r5   r0   )rp   rq   r\   mask)r:   r
   emptyr;   appendrF   r!   r(   r-   r   r   r   r   r+   r   r6   )r<   r0   
with_masksis_obbrp   relative_xyxyrelative_polygonrelative_xyxyxyxywhr=   r   r'   r/   rq   r\   xyxyxyxyr5   rr   s                      r    yolo_annotations_to_detectionsr}      s    5zQ!!CEr2r>@Hm-/@DAq 1F1I'v;!F12J/C  % ''C(@A[1_$F12J7G  !AB!((&*)=> ''01  xx,HHH]"**=M288Q1aL

CCDDHH%6bjjI$,,RA6BHHaV2::66)1%&8$TBB ( 	"((=

;;H  x}MDxdDIIs   /I&c                   |r|rt        j                  dt        d       t        | g d      D cg c]  }t	        |       }}t        |      }i }|D ]  }	t        |	      j                  }
t        j                  j                  ||
 d      }t        j                  j                  |      st        j                         ||	<   rt        j                  |	      }t!        |d	      }|j"                  \  }}||f}|j$                  d
vrt'        d|	 d|j$                   d      | xr |xs t)        |      }t+        ||||      }|||	<    |||fS c c}w )aM  
    Loads YOLO annotations and returns class names, images,
        and their corresponding detections.

    Args:
        images_directory_path: The path to the directory containing the images.
        annotations_directory_path: The path to the directory
            containing the YOLO annotation files.
        data_yaml_path: The path to the data
            YAML file containing class information.
        force_masks: If True, forces masks to be loaded
            for all annotations, regardless of whether they are present.
            This parameter has no effect when `is_obb=True`; mask generation
            is always disabled for OBB annotations.
        is_obb: If True, loads the annotations in OBB format.
            OBB annotations are defined as `[class_id, x, y, x, y, x, y, x, y]`,
            where pairs of [x, y] are box corners.

    Returns:
        A tuple containing a list of class names, a dictionary with
            image names as keys and images as values, and a dictionary
            with image names as keys and corresponding Detections instances as values.
    zl`force_masks=True` has no effect when `is_obb=True`; mask generation is always disabled for OBB annotations.r   
stacklevel)	bmpdngjpgjpegmpopngtiftiffwebp)	directory
extensionsr@   re   T)rA   
skip_empty)RGBLz9Images must be 'RGB' or 'grayscale',                 but z
 mode is 'z'.)r<   )r<   r0   ru   rv   )warningswarnUserWarningr   rG   rc   r   stemrf   rg   joinexistsr
   rs   r   openr   sizemoderS   r>   r}   )images_directory_pathannotations_directory_pathdata_yaml_pathforce_masksrv   rg   image_pathsclassesr   
image_path
image_stemannotation_pathimager<   rz   r{   r0   ru   
annotations                      r    load_yolo_annotationsr      sy   < +F		
 /+

 	D	K $ #^<GK! -
*%**
'',,'Aj\QUCVWww~~o.&0&6&6&8K
# 

:&DIzz1A::\)L
5::,b: 
  ZP[%ON4O
3'!	

 #-J3-4 K,,_s   Ec           
        |\  }}}|j| t        j                  ||||gt         j                        z  }|\  }}	}
}||
z   dz  }|	|z   dz  }|
|z
  }||	z
  }t        |       d|dd|dd|dd|d	S |t        j                  ||gt         j                        z  }|j	                  d      }dj                  |D cg c]  }|d c}      }t        |       d| S c c}w )Nr   r    z.5fr*   )r   r   r   rF   r+   r   )rq   rp   image_shaper/   r{   rz   rk   xyxy_relativex_miny_minx_maxy_maxr   r   r   r   polygon_relativevaluepolygon_parseds                      r    object_to_yolor     s    GAq!rxxAq!BJJGG%2"ueUEMQ&EMQ&h-(3q#ac{!FSV<XX"RXXq!fBJJ%GG+33B7?O"PeeC[>"PQh-.!122 #Qs   =Cc                l   |r:t        |       dkD  r,t        | j                  vrt        dt         dt         d      |r0| j                  $t        j                  dt         dt        d       g }| D ]=  \  }}}	}
}	}|
t        d	      t        |
t        t        j                  f      st        d
t        |
      d      t        |
      }|r|t        j                  |t           t        j                        }|j                  dk7  r t        d|j                   dt         d      t!        ||||      }|j#                  |       |Dt%        ||||      }|D ].  }t'        |      }t!        ||||      }|j#                  |       0 t!        |||      }|j#                  |       @ |S )a$  Convert detections to YOLO annotation lines.

    Args:
        detections: The detections to serialize. Each detection must have a
            valid integer ``class_id``. When ``is_obb=True``, each non-empty
            detection must also carry ``detections.data['xyxyxyxy']`` with
            shape ``(N, 4, 2)``.
        image_shape: The ``(height, width, channels)`` shape of the source
            image, used to normalize coordinates to ``[0, 1]``.
        min_image_area_percentage: Minimum detection area as a fraction of the
            image area; smaller detections are omitted. Ignored when
            ``is_obb=True``.
        max_image_area_percentage: Maximum detection area as a fraction of the
            image area; larger detections are omitted. Ignored when
            ``is_obb=True``.
        approximation_percentage: Fraction of polygon points removed during
            contour approximation when saving mask annotations. Ignored when
            ``is_obb=True``.
        is_obb: If ``True``, serializes oriented bounding-box corners from
            ``detections.data['xyxyxyxy']`` as a 9-token YOLO OBB line
            ``class_id x1 y1 x2 y2 x3 y3 x4 y4``. Mask data is ignored.

    Returns:
        A list of YOLO annotation strings, one per detection (or one per
        polygon for instance-segmentation annotations).

    Raises:
        ValueError: If any detection has ``class_id=None`` or a non-integer
            ``class_id``.
        ValueError: If ``is_obb=True`` and any non-empty detection is missing
            ``'xyxyxyxy'`` in ``detections.data``.

    Examples:
        >>> import numpy as np
        >>> from supervision.detection.core import Detections
        >>> from supervision.dataset.formats.yolo import detections_to_yolo_annotations
        >>> detections = Detections(
        ...     xyxy=np.array([[10, 10, 90, 90]], dtype=np.float32),
        ...     class_id=np.array([0]),
        ... )
        >>> detections_to_yolo_annotations(detections, image_shape=(100, 100, 3))
        ['0 0.50000 0.50000 0.80000 0.80000']
    r   z`is_obb=True` requires `'z'` in `detections.data` with shape (N, 4, 2). Load OBB datasets via `DetectionDataset.from_yolo(..., is_obb=True)` or set `detections.data['z'']` (shape (N, 4, 2)) before exporting.zo`detections.mask` is ignored when `is_obb=True`; OBB annotations use corner coordinates from `detections.data['z']`.r   r   z*Class ID is required for YOLO annotations.z<Detections class_id must be an integer for YOLO export, got rB   r   )ro   r   z8OBB data for each detection must have shape (4, 2), got z. Ensure `detections.data['z)']` has shape (N, 4, 2) before exporting.)rq   rp   r   r/   )rr   min_image_area_percentagemax_image_area_percentageapproximation_percentagern   )rq   rp   r   )r:   r   r\   rS   rr   r   r   r   rE   rF   r   integerrT   asarrayr   shaper   rt   r	   r   )
detectionsr   r   r   r   rv   r   rq   rr   rk   rp   r\   class_id_intcornersnext_objectr5   r/   s                    r    detections_to_yolo_annotationsr   (  s   h 	
Oa$JOO;'(@'A B! ": : ;22
 	
 *//-!!9 :$@ 	
 J,6 0+(dAxDIJJ(S"**$56H~(+  8}jj&>!?rzzRG}}& "==/ *))A(B C88  )%'	K k*5*C*C)A	H $ /&w7,) +#	 !!+./ )LkK k*a0+b r"   c           	     $   t        |      j                  dd       | D ]o  \  }}}t        |      j                  }	t        |	      }
t        j
                  j                  ||
      }t        ||j                  ||||      }t        ||       q y)aQ  Save dataset annotations in YOLO format.

    Args:
        dataset: The dataset whose annotations are saved.
        annotations_directory_path: Path to the directory where annotation
            ``.txt`` files are written; created automatically if absent.
        min_image_area_percentage: Minimum detection area as a fraction of the
            image area; smaller detections are omitted. Ignored when
            ``is_obb=True``.
        max_image_area_percentage: Maximum detection area as a fraction of the
            image area; larger detections are omitted. Ignored when
            ``is_obb=True``.
        approximation_percentage: Fraction of polygon points removed during
            contour approximation when saving mask annotations. Ignored when
            ``is_obb=True``.
        is_obb: If ``True``, writes oriented bounding-box annotations using
            the 9-token format ``class_id x1 y1 x2 y2 x3 y3 x4 y4``. Each
            non-empty detection must carry ``detections.data['xyxyxyxy']``
            with shape ``(N, 4, 2)``.

    Examples:
        >>> from supervision.dataset.core import DetectionDataset
        >>> from supervision.dataset.formats.yolo import save_yolo_annotations
        >>> dataset = DetectionDataset(classes=["cat"], images={}, annotations={})
        >>> save_yolo_annotations(dataset, "/tmp/labels")
    Tparentsexist_ok)ri   )r   r   r   r   r   rv   )r<   rA   N)
r   mkdirrb   rl   rf   rg   r   r   r   r   )datasetr   r   r   r   rv   r   r   r   ri   yolo_annotations_nameyolo_annotations_pathr<   s                r    save_yolo_annotationsr     s    D 		#$**4$*G)0 E%
E:*%**
 >* U "&(=!
 /!&?&?%=
 	U.CDEr"   c                    t        |      |d}t        |       j                  j                  dd       t	        ||        y )N)ncrC   Tr   )r\   rA   )r:   r   parentr   r   )r   r   r\   s      r    save_data_yamlr     s8    g,1D%%dT%B7r"   )r   	list[str]rQ   npt.NDArray[np.float32])r'   r   rQ   r   )r5   zlist[npt.NDArray[np.number]]r0   tuple[int, int]rQ   znpt.NDArray[np.bool_])r<   r   rQ   r4   )rA   rG   rQ   r   )ri   rG   rQ   rG   )F)
r<   r   r0   r   ru   r4   rv   r4   rQ   r
   )FF)r   rG   r   rG   r   rG   r   r4   rv   r4   rQ   z2tuple[list[str], list[str], dict[str, Detections]]rN   )
rq   znpt.NDArray[np.number]rp   rF   r   tuple[int, int, int]r/   znpt.NDArray[np.number] | NonerQ   rG   )g        g      ?g      ?F)r   r
   r   r   r   r   r   r   r   r   rv   r4   rQ   r   )r   r   r   rG   r   r   r   r   r   r   rv   r4   rQ   None)r   rG   r   r   rQ   r   )-
__future__r   rf   r   pathlibr   typingr   r   numpyr   numpy.typingnptPILr   supervision.configr   supervision.dataset.utilsr	   supervision.detection.corer
   &supervision.detection.utils.convertersr   r   supervision.utils.filer   r   r   r   r   supervision.dataset.corer   r!   r(   r-   r6   r>   rc   rl   r}   r   r   r   r   r    r"   r    <module>r      s   " 	   %    7 D 1 S  9
=*;J:<~ 	.J.J".J .J 	.J
 .Jj T-T- #T- T- 	T-
 T- 8T-v .2	3
 33 &3 +	3
 	32 (+'*&*{{%{  %{  %	{
 ${ { {B (+'*&*1E1E #1E  %1E  %	1E
 $1E 1E 
1Eh8r"   