o
    eb                     @  s  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
mZmZmZmZ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mZmZ d d
lmZmZmZ d dlm Z m!Z!m"Z"m#Z#m$Z$ d dl%m&Z& eG dd deZ'eG dd de'Z(eG dd de'Z)dS )    annotationsN)ABCabstractmethod)	dataclass)Path)DictIteratorListOptionalTuple)Classifications)load_coco_annotationssave_coco_annotations)detections_to_pascal_vocload_pascal_voc_annotations)load_yolo_annotationssave_data_yamlsave_yolo_annotations)build_class_index_mappingmap_detections_class_idmerge_class_listssave_dataset_imagestrain_test_split)
Detectionsc                   @  s,   e Zd ZedddZe	ddddZdS )BaseDatasetreturnintc                 C     d S N selfr    r    G/var/www/myenv/lib/python3.10/site-packages/supervision/dataset/core.py__len__&   s   zBaseDataset.__len__皙?NTshuffleboolTuple[BaseDataset, BaseDataset]c                 C  r   r   r    )r"   split_ratiorandom_stater&   r    r    r#   split*   s   zBaseDataset.splitr   r   r%   NT)r&   r'   r   r(   )__name__
__module____qualname__r   r$   r+   r    r    r    r#   r   $   s    r   c                   @  s   e Zd ZU dZded< ded< ded< d8d
dZd9ddZdd Z	d:d;ddZ					d<d=d#d$Z	e
	%d>d?d(d)Ze
	%d>d@d+d,Z						dAdBd-d.Ze
	%d>dCd0d1Z					d<dDd2d3Ze
dEd6d7ZdS )FDetectionDatasetaT  
    Dataclass containing information about object detection dataset.

    Attributes:
        classes (List[str]): List containing dataset class names.
        images (Dict[str, np.ndarray]): Dictionary mapping image name to image.
        annotations (Dict[str, Detections]): Dictionary mapping
            image name to annotations.
    	List[str]classesDict[str, np.ndarray]imageszDict[str, Detections]r   r   r   c                 C  
   t | jS )zv
        Return the number of images in the dataset.

        Returns:
            int: The number of images.
        lenr5   r!   r    r    r#   r$   A   s   
zDetectionDataset.__len__,Iterator[Tuple[str, np.ndarray, Detections]]c                 c  s0    | j  D ]\}}||| j|dfV  qdS )a   
        Iterate over the images and annotations in the dataset.

        Yields:
            Iterator[Tuple[str, np.ndarray, Detections]]:
                An iterator that yields tuples containing the image name,
                the image data, and its corresponding annotation.
        N)r5   itemsr   get)r"   
image_nameimager    r    r#   __iter__J   s   	zDetectionDataset.__iter__c                 C  sn   t |tsdS t| jt|jkrdS | jD ]}t| j| |j| s' dS | j| |j| ks4 dS qdS )NFT)
isinstancer1   setr3   r5   nparray_equalr   )r"   otherkeyr    r    r#   __eq__V   s   

zDetectionDataset.__eq__r%   NTr&   r'   )Tuple[DetectionDataset, DetectionDataset]c           	           t  j }t||||d\}}t j fdd|D  fdd|D d}t j fdd|D  fdd|D d}||fS )a  
        Splits the dataset into two parts (training and testing)
            using the provided split_ratio.

        Args:
            split_ratio (float, optional): The ratio of the training
                set to the entire dataset.
            random_state (int, optional): The seed for the random number generator.
                This is used for reproducibility.
            shuffle (bool, optional): Whether to shuffle the data before splitting.

        Returns:
            Tuple[DetectionDataset, DetectionDataset]: A tuple containing
                the training and testing datasets.

        Example:
            ```python
            >>> import supervision as sv

            >>> ds = sv.DetectionDataset(...)
            >>> train_ds, test_ds = ds.split(split_ratio=0.7,
            ...                              random_state=42, shuffle=True)
            >>> len(train_ds), len(test_ds)
            (700, 300)
            ```
        datatrain_ratior*   r&   c                      i | ]}| j | qS r    r5   .0namer!   r    r#   
<dictcomp>       z*DetectionDataset.split.<locals>.<dictcomp>c                   rK   r    r   rM   r!   r    r#   rP      rQ   r3   r5   r   c                   rK   r    rL   rM   r!   r    r#   rP      rQ   c                   rK   r    r   rM   r!   r    r#   rP      rQ   )listr5   keysr   r1   r3   	r"   r)   r*   r&   image_namestrain_names
test_namestrain_datasettest_datasetr    r!   r#   r+   e   s$   
zDetectionDataset.split              ?images_directory_pathOptional[str]annotations_directory_pathmin_image_area_percentagefloatmax_image_area_percentageapproximation_percentageNonec              
   C  s   |r	t || jd |rt|jddd | j D ]F\}}| j| }|r_t|j}	tj	||	 d}
t|j
}t|| j||j|||d}t|
d}|| W d   n1 sZw   Y  qdS )a  
        Exports the dataset to PASCAL VOC format. This method saves the images
        and their corresponding annotations in PASCAL VOC format.

        Args:
            images_directory_path (Optional[str]): The path to the directory
                where the images should be saved.
                If not provided, images will not be saved.
            annotations_directory_path (Optional[str]): The path to
                the directory where the annotations in PASCAL VOC format should be
                saved. If not provided, annotations will not be saved.
            min_image_area_percentage (float): The minimum percentage of
                detection area relative to
                the image area for a detection to be included.
                Argument is used only for segmentation datasets.
            max_image_area_percentage (float): The maximum percentage
                of detection area relative to
                the image area for a detection to be included.
                Argument is used only for segmentation datasets.
            approximation_percentage (float): The percentage of
                polygon points to be removed from the input polygon,
                in the range [0, 1). Argument is used only for segmentation datasets.
        r]   r5   T)parentsexist_okz.xml)
detectionsr3   filenameimage_shaper`   rb   rc   wN)r   r5   r   mkdirr:   r   stemospathjoinrO   r   r3   shapeopenwrite)r"   r]   r_   r`   rb   rc   
image_pathr=   rh   annotation_nameannotations_pathr<   pascal_voc_xmlfr    r    r#   as_pascal_voc   s8   




zDetectionDataset.as_pascal_vocFstrforce_masksc                 C  "   t |||d\}}}t|||dS )a  
        Creates a Dataset instance from PASCAL VOC formatted data.

        Args:
            images_directory_path (str): Path to the directory containing the images.
            annotations_directory_path (str): Path to the directory
                containing the PASCAL VOC XML annotations.
            force_masks (bool, optional): If True, forces masks to
                be loaded for all annotations, regardless of whether they are present.

        Returns:
            DetectionDataset: A DetectionDataset instance containing
                the loaded images and annotations.

        Example:
            ```python
            >>> import roboflow
            >>> from roboflow import Roboflow
            >>> import supervision as sv

            >>> roboflow.login()

            >>> rf = Roboflow()

            >>> project = rf.workspace(WORKSPACE_ID).project(PROJECT_ID)
            >>> dataset = project.version(PROJECT_VERSION).download("voc")

            >>> ds = sv.DetectionDataset.from_pascal_voc(
            ...     images_directory_path=f"{dataset.location}/train/images",
            ...     annotations_directory_path=f"{dataset.location}/train/labels"
            ... )

            >>> ds.classes
            ['dog', 'person']
            ```
        )r]   r_   r{   rR   )r   r1   )clsr]   r_   r{   r3   r5   r   r    r    r#   from_pascal_voc   s   ,z DetectionDataset.from_pascal_vocdata_yaml_pathc                 C  s$   t ||||d\}}}t|||dS )a  
        Creates a Dataset instance from YOLO formatted data.

        Args:
            images_directory_path (str): The path to the
                directory containing the images.
            annotations_directory_path (str): The path to the directory
                containing the YOLO annotation files.
            data_yaml_path (str): The path to the data
                YAML file containing class information.
            force_masks (bool, optional): If True, forces
                masks to be loaded for all annotations,
                regardless of whether they are present.

        Returns:
            DetectionDataset: A DetectionDataset instance
                containing the loaded images and annotations.

        Example:
            ```python
            >>> import roboflow
            >>> from roboflow import Roboflow
            >>> import supervision as sv

            >>> roboflow.login()

            >>> rf = Roboflow()

            >>> project = rf.workspace(WORKSPACE_ID).project(PROJECT_ID)
            >>> dataset = project.version(PROJECT_VERSION).download("yolov5")

            >>> ds = sv.DetectionDataset.from_yolo(
            ...     images_directory_path=f"{dataset.location}/train/images",
            ...     annotations_directory_path=f"{dataset.location}/train/labels",
            ...     data_yaml_path=f"{dataset.location}/data.yaml"
            ... )

            >>> ds.classes
            ['dog', 'person']
            ```
        )r]   r_   r   r{   rR   )r   r1   )r}   r]   r_   r   r{   r3   r5   r   r    r    r#   	from_yolo  s   1zDetectionDataset.from_yoloc                 C  sT   |durt || jd |durt|| j| j|||d |dur(t|| jd dS dS )a  
        Exports the dataset to YOLO format. This method saves the
        images and their corresponding annotations in YOLO format.

        Args:
            images_directory_path (Optional[str]): The path to the
                directory where the images should be saved.
                If not provided, images will not be saved.
            annotations_directory_path (Optional[str]): The path to the
                directory where the annotations in
                YOLO format should be saved. If not provided,
                annotations will not be saved.
            data_yaml_path (Optional[str]): The path where the data.yaml
                file should be saved.
                If not provided, the file will not be saved.
            min_image_area_percentage (float): The minimum percentage of
                detection area relative to
                the image area for a detection to be included.
                Argument is used only for segmentation datasets.
            max_image_area_percentage (float): The maximum percentage
                of detection area relative to
                the image area for a detection to be included.
                Argument is used only for segmentation datasets.
            approximation_percentage (float): The percentage of polygon points to
                be removed from the input polygon, in the range [0, 1).
                This is useful for simplifying the annotations.
                Argument is used only for segmentation datasets.
        Nre   )r_   r5   r   r`   rb   rc   )r   r3   )r   r5   r   r   r   r3   )r"   r]   r_   r   r`   rb   rc   r    r    r#   as_yolo@  s    %zDetectionDataset.as_yolorv   c                 C  r|   )a  
        Creates a Dataset instance from COCO formatted data.

        Args:
            images_directory_path (str): The path to the
                directory containing the images.
            annotations_path (str): The path to the json annotation files.
            force_masks (bool, optional): If True,
                forces masks to be loaded for all annotations,
                regardless of whether they are present.

        Returns:
            DetectionDataset: A DetectionDataset instance containing
                the loaded images and annotations.

        Example:
            ```python
            >>> import roboflow
            >>> from roboflow import Roboflow
            >>> import supervision as sv

            >>> roboflow.login()

            >>> rf = Roboflow()

            >>> project = rf.workspace(WORKSPACE_ID).project(PROJECT_ID)
            >>> dataset = project.version(PROJECT_VERSION).download("coco")

            >>> ds = sv.DetectionDataset.from_coco(
            ...     images_directory_path=f"{dataset.location}/train",
            ...     annotations_path=f"{dataset.location}/train/_annotations.coco.json",
            ... )

            >>> ds.classes
            ['dog', 'person']
            ```
        )r]   rv   r{   rR   )r   r1   )r}   r]   rv   r{   r3   r5   r   r    r    r#   	from_cocou  s   ,zDetectionDataset.from_cococ              	   C  sB   |durt || jd |durt|| j| j| j|||d dS dS )a  
        Exports the dataset to COCO format. This method saves the
        images and their corresponding annotations in COCO format.

        Args:
            images_directory_path (Optional[str]): The path to the directory
                where the images should be saved.
                If not provided, images will not be saved.
            annotations_path (Optional[str]): The path to COCO annotation file.
            min_image_area_percentage (float): The minimum percentage of
                detection area relative to
                the image area for a detection to be included.
                Argument is used only for segmentation datasets.
            max_image_area_percentage (float): The maximum percentage of
                detection area relative to
                the image area for a detection to be included.
                Argument is used only for segmentation datasets.
            approximation_percentage (float): The percentage of polygon points
                to be removed from the input polygon,
                in the range [0, 1). This is useful for simplifying the annotations.
                Argument is used only for segmentation datasets.
        Nre   )annotation_pathr5   r   r3   r`   rb   rc   )r   r5   r   r   r3   )r"   r]   rv   r`   rb   rc   r    r    r#   as_coco  s   
zDetectionDataset.as_cocodataset_listList[DetectionDataset]c                 C  s   i i }}dd |D }t |d}|D ])}t|j|d}|D ]\}}	}
||v r/td| d|	||< t||
d||< qq| |||dS )	a  
        Merge a list of `DetectionDataset` objects into a single
            `DetectionDataset` object.

        This method takes a list of `DetectionDataset` objects and combines
        their respective fields (`classes`, `images`,
        `annotations`) into a single `DetectionDataset` object.

        Args:
            dataset_list (List[DetectionDataset]): A list of `DetectionDataset`
                objects to merge.

        Returns:
            (DetectionDataset): A single `DetectionDataset` object containing
            the merged data from the input list.

        Example:
            ```python
            >>> import supervision as sv

            >>> ds_1 = sv.DetectionDataset(...)
            >>> len(ds_1)
            100
            >>> ds_1.classes
            ['dog', 'person']

            >>> ds_2 = sv.DetectionDataset(...)
            >>> len(ds_2)
            200
            >>> ds_2.classes
            ['cat']

            >>> ds_merged = sv.DetectionDataset.merge([ds_1, ds_2])
            >>> len(ds_merged)
            300
            >>> ds_merged.classes
            ['cat', 'dog', 'person']
            ```
        c                 S  s   g | ]}|j qS r    )r3   )rN   datasetr    r    r#   
<listcomp>  s    z*DetectionDataset.merge.<locals>.<listcomp>)class_lists)source_classestarget_classeszImage name z is not unique across datasets.)source_to_target_mappingrh   rR   )r   r   r3   
ValueErrorr   )r}   r   merged_imagesmerged_annotationsr   merged_classesr   class_index_mappingr<   r=   rh   r    r    r#   merge  s*   
)

zDetectionDataset.merger,   )r   r9   r-   )r&   r'   r   rF   )NNr[   r\   r[   )r]   r^   r_   r^   r`   ra   rb   ra   rc   ra   r   rd   )F)r]   rz   r_   rz   r{   r'   r   r1   )
r]   rz   r_   rz   r   rz   r{   r'   r   r1   )NNNr[   r\   r[   )r]   r^   r_   r^   r   r^   r`   ra   rb   ra   rc   ra   r   rd   )r]   rz   rv   rz   r{   r'   r   r1   )r]   r^   rv   r^   r`   ra   rb   ra   rc   ra   r   rd   )r   r   r   r1   )r.   r/   r0   __doc____annotations__r$   r>   rE   r+   ry   classmethodr~   r   r   r   r   r   r    r    r    r#   r1   1   sP   
 


	4<3:54-r1   c                   @  sZ   e Zd ZU dZded< ded< ded< dd
dZ	ddddZdddZedddZ	dS ) ClassificationDatasetaT  
    Dataclass containing information about a classification dataset.

    Attributes:
        classes (List[str]): List containing dataset class names.
        images (Dict[str, np.ndarray]): Dictionary mapping image name to image.
        annotations (Dict[str, Detections]): Dictionary mapping
            image name to annotations.
    r2   r3   r4   r5   zDict[str, Classifications]r   r   r   c                 C  r6   r   r7   r!   r    r    r#   r$   '  s   
zClassificationDataset.__len__r%   NTr&   r'   3Tuple[ClassificationDataset, ClassificationDataset]c           	        rG   )a  
        Splits the dataset into two parts (training and testing)
            using the provided split_ratio.

        Args:
            split_ratio (float, optional): The ratio of the training
                set to the entire dataset.
            random_state (int, optional): The seed for the
                random number generator. This is used for reproducibility.
            shuffle (bool, optional): Whether to shuffle the data before splitting.

        Returns:
            Tuple[ClassificationDataset, ClassificationDataset]: A tuple containing
            the training and testing datasets.

        Example:
            ```python
            >>> import supervision as sv

            >>> cd = sv.ClassificationDataset(...)
            >>> train_cd,test_cd = cd.split(split_ratio=0.7,
            ...                             random_state=42,shuffle=True)
            >>> len(train_cd), len(test_cd)
            (700, 300)
            ```
        rH   c                   rK   r    rL   rM   r!   r    r#   rP   Q  rQ   z/ClassificationDataset.split.<locals>.<dictcomp>c                   rK   r    r   rM   r!   r    r#   rP   R  rQ   rR   c                   rK   r    rL   rM   r!   r    r#   rP   V  rQ   c                   rK   r    r   rM   r!   r    r#   rP   W  rQ   )rS   r5   rT   r   r   r3   rU   r    r!   r#   r+   *  s$   
zClassificationDataset.splitroot_directory_pathrz   rd   c                 C  s   t j|dd | jD ]}t jt j||dd q
| jD ]7}| j| }| j| }t|j}|j	du r7|j
d n|dd d }| j| }t j|||}t|| qdS )z
        Saves the dataset as a multi-class folder structure.

        Args:
            root_directory_path (str): The path to the directory
                where the dataset will be saved.
        T)rg   Nr      )rn   makedirsr3   ro   rp   r5   r   r   rO   
confidenceclass_id	get_top_kcv2imwrite)r"   r   
class_namert   classificationr=   r<   r   r    r    r#   as_folder_structure[  s   







z)ClassificationDataset.as_folder_structurec           	      C  s   t |}tt|}i }i }|D ]0}||}t t j||D ]}tt j|||}t	|||< t
t|gd||< q"q| |||dS )a  
        Load data from a multiclass folder structure into a ClassificationDataset.

        Args:
            root_directory_path (str): The path to the dataset directory.

        Returns:
            ClassificationDataset: The dataset.

        Example:
            ```python
            >>> import roboflow
            >>> from roboflow import Roboflow
            >>> import supervision as sv

            >>> roboflow.login()

            >>> rf = Roboflow()

            >>> project = rf.workspace(WORKSPACE_ID).project(PROJECT_ID)
            >>> dataset = project.version(PROJECT_VERSION).download("folder")

            >>> cd = sv.ClassificationDataset.from_folder_structure(
            ...     root_directory_path=f"{dataset.location}/train"
            ... )
            ```
        )r   rR   )rn   listdirsortedr@   indexro   rp   rz   r   imreadr   rA   array)	r}   r   r3   r5   r   r   r   r=   rt   r    r    r#   from_folder_structureu  s$   


z+ClassificationDataset.from_folder_structurer,   r-   )r&   r'   r   r   )r   rz   r   rd   )r   rz   r   r   )
r.   r/   r0   r   r   r$   r+   r   r   r   r    r    r    r#   r     s   
 


1r   )*
__future__r   rn   abcr   r   dataclassesr   pathlibr   typingr   r	   r
   r   r   r   numpyrA   supervision.classification.corer    supervision.dataset.formats.cocor   r   &supervision.dataset.formats.pascal_vocr   r    supervision.dataset.formats.yolor   r   r   supervision.dataset.utilsr   r   r   r   r   supervision.detection.corer   r   r1   r   r    r    r    r#   <module>   s.       h