o
    Ďii                    @  s@  d dl mZ d dlZd dlZd dlZd dl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 d dlmZmZ d dlmZ d dlZd d	lmZ d d
lmZ d dlmZmZmZ d dlmZmZm Z  G dd dZ!G dd dZ"G dd de"Z#G dd de"Z$G dd dZ%G dd de%Z&G dd dZ'G dd dZ(	dgddZ)	dhd d!Z*did&d'Z+djd,d-Z,dkdld1d2Z-dmd4d5Z.dnd8d9Z/dod;d<Z0dpd>d?Z1dpd@dAZ2	B	B	C	CdqdrdIdJZ3eG dKdL dLZ4dMdN Z5G dOdP dPZ6dkdsdUdVZ7			W	 	dtdud^d_Z8			W	 	dtdud`daZ9	dvdwdcddZ:	dvdwdedfZ;dS )x    )annotationsN)Counterdefaultdict)	dataclass)Pool)Path)LockThread)Literal)tqdm)logger)is_colab	load_json	save_json)ShapelyAnnotationboxget_shapely_multipolygonc                   @  s<   e Zd ZdZddd	d
Zedd Zedd Zdd Z	dS )CocoCategoryzCOCO formatted category.r   Nidintname
str | Nonesupercategoryc                 C  s(   t || _|| _|r|| _d S || _d S N)r   r   r   r   )selfr   r   r    r   K/home/jeff/fluffinator/venv/lib/python3.10/site-packages/sahi/utils/coco.py__init__   s   
zCocoCategory.__init__c                 C  s.   | |d |d d|v r|d dS |d dS )zCreates CocoCategory object using coco category.

        Args:
            category: Dict
                {"supercategory": "person", "id": 1, "name": "person"},
        r   r   r   r   r   r   r   )clscategoryr   r   r   from_coco_category    s   zCocoCategory.from_coco_categoryc                 C  s   | j | j| jdS )Nr   r   r   r   r   r   json.   s   zCocoCategory.jsonc                 C  s   d| j  d| j d| j dS )NzCocoCategory<
    id: ,
    name: z,
    supercategory: >r   r"   r   r   r   __repr__6   s   zCocoCategory.__repr__)r   NN)r   r   r   r   r   r   )
__name__
__module____qualname____doc__r   classmethodr!   propertyr#   r&   r   r   r   r   r      s    

r   c                   @  s  e Zd ZdZed5ddZed5ddZed6d7ddZed8ddZ					d9d:ddZ	d;ddZ
edd Zed d! Zed"d# Zed$d% Zejd&d% Zed'd( Zejd)d( Zed*d+ Zejd,d+ Zed-d. Zed/d0 Zd1d2 Zd3d4 ZdS )<CocoAnnotationzCOCO formatted annotation.r   c                 C     | ||||dS )ar  Creates CocoAnnotation object using coco segmentation.

        Args:
            segmentation: List[List]
                [[1, 1, 325, 125, 250, 200, 5, 200]]
            category_id: int
                Category id of the annotation
            category_name: str
                Category name of the annotation
            iscrowd: int
                0 or 1
        )segmentationcategory_idcategory_nameiscrowdr   )r   r/   r0   r1   r2   r   r   r   from_coco_segmentation@      z%CocoAnnotation.from_coco_segmentationc                 C  r.   )aS  Creates CocoAnnotation object using coco bbox.

        Args:
            bbox: List
                [xmin, ymin, width, height]
            category_id: int
                Category id of the annotation
            category_name: str
                Category name of the annotation
            iscrowd: int
                0 or 1
        bboxr0   r1   r2   r   )r   r6   r0   r1   r2   r   r   r   from_coco_bboxU   r4   zCocoAnnotation.from_coco_bboxNannotation_dictdictr1   r   c                 C  sz   | drt|d trd}td|d  d nd}| dr2|d r2|s2| |d |d |dS | |d	 |d |d
S )a|  Creates CocoAnnotation object from category name and COCO formatted annotation dict (with fields "bbox",
        "segmentation", "category_id").

        Args:
            category_name: str
                Category name of the annotation
            annotation_dict: dict
                COCO formatted annotation dict (with fields "bbox", "segmentation", "category_id")
        r/   TzSegmentation annotation for id r   z; is skipped since RLE segmentation format is not supported.Fr0   )r/   r0   r1   r6   )r6   r0   r1   )__contains__
isinstancer9   r   warning)r   r8   r1   has_rle_segmentationr   r   r   from_coco_annotation_dictj   s,   z(CocoAnnotation.from_coco_annotation_dictshapely_annotationr   r0   r   strr2   c                 C  s(   | g d|||d}|  |_||_|S )a'  Creates CocoAnnotation object from ShapelyAnnotation object.

        Args:
            shapely_annotation (ShapelyAnnotation)
            category_id (int): Category id of the annotation
            category_name (str): Category name of the annotation
            iscrowd (int): 0 or 1
        )r   r   r   r   r5   )to_coco_segmentation_segmentation_shapely_annotation)r   r?   r0   r1   r2   coco_annotationr   r   r   from_shapely_annotation   s   
z&CocoAnnotation.from_shapely_annotationr6   list[int] | Nonec                 C  sn   |du r|du rt d|| _|| _|| _|| _|| _| jr&tj| jd}n|s,tdtj	|d}|| _
dS )a  Creates coco annotation object using bbox or segmentation.

        Args:
            segmentation: List[List]
                [[1, 1, 325, 125, 250, 200, 5, 200]]
            bbox: List
                [xmin, ymin, width, height]
            category_id: int
                Category id of the annotation
            category_name: str
                Category name of the annotation
            image_id: int
                Image ID of the annotation
            iscrowd: int
                0 or 1
        Nz"you must provide a bbox or polygon)r/   zCoco bounding box not set)r6   )
ValueErrorrB   _category_id_category_name	_image_id_iscrowdr   r3   	TypeErrorr7   rC   )r   r0   r1   r/   r6   image_idr2   r?   r   r   r   r      s   
zCocoAnnotation.__init__
slice_bbox	list[int]c                 C  sF   t |d |d |d |d }| j|}tj|| j| jpd| jdS )Nr             )r0   r1   r2   )r   rC   get_intersectionr-   rE   r0   r1   r2   )r   rN   shapely_polygonintersection_shapely_annotationr   r   r   get_sliced_coco_annotation   s   z)CocoAnnotation.get_sliced_coco_annotationc                 C  s   | j jS )zDReturns area of annotation polygon (or bbox if no polygon available))rC   arear"   r   r   r   rX      s   zCocoAnnotation.areac                 C  s
   | j  S )zLReturns coco formatted bbox of the annotation as [xmin, ymin, width, height])rC   to_xywhr"   r   r   r   r6      s   
zCocoAnnotation.bboxc                 C  s   | j r| j S g S )z]Returns coco formatted segmentation of the annotation as [[1, 1, 325, 125, 250, 200, 5, 200]])rB   rC   rA   r"   r   r   r   r/      s   
zCocoAnnotation.segmentationc                 C     | j S )z-Returns category id of the annotation as int.)rH   r"   r   r   r   r0         zCocoAnnotation.category_idc                 C     t |ts	td|| _d S )Nzcategory_id must be an integer)r;   r   	ExceptionrH   r   ir   r   r   r0         

c                 C  rZ   )z*Returns image id of the annotation as int.)rJ   r"   r   r   r   rM      r[   zCocoAnnotation.image_idc                 C  r\   )Nzimage_id must be an integer)r;   r   r]   rJ   r^   r   r   r   rM      r`   c                 C  rZ   )z/Returns category name of the annotation as str.)rI   r"   r   r   r   r1     r[   zCocoAnnotation.category_namec                 C  r\   )Nzcategory_name must be a string)r;   r@   r]   rI   )r   nr   r   r   r1   
  r`   c                 C  rZ   )z'Returns iscrowd info of the annotation.)rK   r"   r   r   r   r2     r[   zCocoAnnotation.iscrowdc                 C     | j | j| j| j| j| jdS )NrM   r6   r0   r/   r2   rX   rc   r"   r   r   r   r#        zCocoAnnotation.jsonc                 C  s   t jdtdd | jS Nz-Use json property instead of serialize methodrQ   )
stacklevel)warningswarnDeprecationWarningr#   r"   r   r   r   	serialize   s   zCocoAnnotation.serializec                 C  s>   d| j  d| j d| j d| j d| j d| j d| j dS )	NzCocoAnnotation<
    image_id: ,
    bbox: ,
    segmentation: ,
    category_id: ,
    category_name: ,
    iscrowd: ,
    area: r%   )rM   r6   r/   r0   r1   r2   rX   r"   r   r   r   r&   $  s   zCocoAnnotation.__repr__)r   r   )r8   r9   r1   r   )r?   r   r0   r   r1   r@   r2   r   )NNNNr   )r0   r   r1   r   r6   rF   )rN   rO   )r'   r(   r)   r*   r+   r3   r7   r>   rE   r   rW   r,   rX   r6   r/   r0   setterrM   r1   r2   r#   rj   r&   r   r   r   r   r-   =   sR    $
*












r-   c                      sx   e Zd ZdZedddZedddZeddd	Z				
			dd fddZe	dd Z
dd Zdd Z  ZS )CocoPredictionz.Class for handling predictions in coco format.r   Nc                 C     | ||||||dS )a  Creates CocoAnnotation object using coco segmentation.

        Args:
            segmentation: List[List]
                [[1, 1, 325, 125, 250, 200, 5, 200]]
            category_id: int
                Category id of the annotation
            category_name: str
                Category name of the annotation
            score: float
                Prediction score between 0 and 1
            iscrowd: int
                0 or 1
        )r/   r0   r1   scorer2   rM   r   )r   r/   r0   r1   rt   r2   rM   r   r   r   r3   2     z%CocoPrediction.from_coco_segmentationc                 C  rs   )a  Creates CocoAnnotation object using coco bbox.

        Args:
            bbox: List
                [xmin, ymin, width, height]
            category_id: int
                Category id of the annotation
            category_name: str
                Category name of the annotation
            score: float
                Prediction score between 0 and 1
            iscrowd: int
                0 or 1
        )r6   r0   r1   rt   r2   rM   r   )r   r6   r0   r1   rt   r2   rM   r   r   r   r7   K  ru   zCocoPrediction.from_coco_bboxc                 C  s:   |d r| |d |d |||dS | |d |d ||dS )a  Creates CocoAnnotation object from category name and COCO formatted annotation dict (with fields "bbox",
        "segmentation", "category_id").

        Args:
            category_name: str
                Category name of the annotation
            annotation_dict: dict
                COCO formatted annotation dict (with fields "bbox", "segmentation", "category_id")
            score: float
                Prediction score between 0 and 1
        r/   r0   )r/   r0   r1   rt   rM   r6   r6   r0   r1   rM   r   )r   r1   r8   rt   rM   r   r   r   r>   d  s   z(CocoPrediction.from_coco_annotation_dictrS   r0   r   r1   r@   c                   s"   || _ t j||||||d dS )a  

        Args:
            segmentation: List[List]
                [[1, 1, 325, 125, 250, 200, 5, 200]]
            bbox: List
                [xmin, ymin, width, height]
            category_id: int
                Category id of the annotation
            category_name: str
                Category name of the annotation
            image_id: int
                Image ID of the annotation
            score: float
                Prediction score between 0 and 1
            iscrowd: int
                0 or 1
        )r/   r6   r0   r1   rM   r2   N)rt   superr   )r   r/   r6   r0   r1   rM   rt   r2   	__class__r   r   r     s   
zCocoPrediction.__init__c              	   C  s&   | j | j| j| j| j| j| j| jdS )NrM   r6   rt   r0   r1   r/   r2   rX   rz   r"   r   r   r   r#     s   zCocoPrediction.jsonc                 C  s   t jdtdd d S re   )rg   rh   ri   r"   r   r   r   rj     s   zCocoPrediction.serializec                 C  sF   d| j  d| j d| j d| j d| j d| j d| j d| j d	S )
NzCocoPrediction<
    image_id: rk   rl   z,
    score: rm   rn   ro   rp   r%   )rM   r6   r/   rt   r0   r1   r2   rX   r"   r   r   r   r&     s"   zCocoPrediction.__repr__)r   Nr   )NNr   rS   NNr   )r0   r   r1   r@   )r'   r(   r)   r*   r+   r3   r7   r>   r   r,   r#   rj   r&   __classcell__r   r   rx   r   rr   /  s(    &
rr   c                      s@   e Zd ZdZ				dd fd
dZedd Zdd Z  ZS )CocoVidAnnotationzCOCOVid formatted annotation.

    https://github.com/open-mmlab/mmtracking/blob/master/docs/tutorials/customize_dataset.md#the-cocovid-annotation-file
    Nr   r0   r   r1   r@   r6   rO   c                   s&   t  j|||||d || _|| _dS )a  
        Args:
            bbox: List
                [xmin, ymin, width, height]
            category_id: int
                Category id of the annotation
            category_name: str
                Category name of the annotation
            image_id: int
                Image ID of the annotation
            instance_id: int
                Used for tracking
            iscrowd: int
                0 or 1
            id: int
                Annotation id
        )r6   r0   r1   rM   r2   N)rw   r   instance_idr   )r   r0   r1   r6   rM   r}   r2   r   rx   r   r   r     s   
zCocoVidAnnotation.__init__c              
   C  s*   | j | j| j| j| j| j| j| j| jd	S )N	r   rM   r6   r/   r0   r1   r}   r2   rX   r~   r"   r   r   r   r#     s   zCocoVidAnnotation.jsonc                 C  sN   d| j  d| j d| j d| j d| j d| j d| j d| j d	| j d
S )NzCocoAnnotation<
    id: z,
    image_id: rk   rl   rm   rn   z,
    instance_id: ro   rp   r%   r~   r"   r   r   r   r&     s&   	zCocoVidAnnotation.__repr__)NNr   N)r0   r   r1   r@   r6   rO   )	r'   r(   r)   r*   r   r,   r#   r&   r{   r   r   rx   r   r|     s    
%
r|   c                   @  sH   e Zd Zedd ZddddZdd Zdd Zedd Z	dd Z
dS )	CocoImagec                 C  s    | |d |d |d |d dS )a  Creates CocoImage object from COCO formatted image dict (with fields "id", "file_name", "height" and
        "weight").

        Args:
            image_dict: dict
                COCO formatted image dict (with fields "id", "file_name", "height" and "weight")
        r   	file_nameheightwidthr   r   r   r   r   )r   
image_dictr   r   r   from_coco_image_dict
  s   	zCocoImage.from_coco_image_dictNr   r@   r   r   r   r   
int | Nonec                 C  s<   |rt |n|| _|| _t || _t || _g | _g | _dS )a  Creates CocoImage object.

        Args:
            id : int
                Image id
            file_name : str
                Image path
            height : int
                Image height in pixels
            width : int
                Image width in pixels
        N)r   r   r   r   r   r   predictions)r   r   r   r   r   r   r   r   r     s   


zCocoImage.__init__c                 C  "   t |ts	td| j| dS )zYAdds annotation to this CocoImage instance.

        annotation : CocoAnnotation
        z,annotation must be a CocoAnnotation instanceN)r;   r-   rL   r   appendr   
annotationr   r   r   add_annotation.     
zCocoImage.add_annotationc                 C  r   )zYAdds prediction to this CocoImage instance.

        prediction : CocoPrediction
        z,prediction must be a CocoPrediction instanceN)r;   rr   rL   r   r   )r   
predictionr   r   r   add_prediction8  r   zCocoImage.add_predictionc                 C  s   | j | j| j| jdS )Nr   r   r"   r   r   r   r#   B  s
   zCocoImage.jsonc              	   C  s&   d| j  d| j d| j d| j d	S )NzCocoImage<
    id: z,
    file_name: ,
    height: ,
    width: zO,
    annotations: List[CocoAnnotation],
    predictions: List[CocoPrediction]>r   r"   r   r   r   r&   K  s   zCocoImage.__repr__r   )r   r@   r   r   r   r   r   r   )r'   r(   r)   r+   r   r   r   r   r,   r#   r&   r   r   r   r   r   	  s    



r   c                      sR   e Zd ZdZ			d fdd	ZedddZdd Zed	d
 Z	dd Z
  ZS )CocoVidImagezCOCOVid formatted image.

    https://github.com/open-mmlab/mmtracking/blob/master/docs/tutorials/customize_dataset.md#the-cocovid-annotation-file
    Nc                   s$   t  j||||d || _|| _dS )a  Creates CocoVidImage object.

        Args:
            id: int
                Image id
            file_name: str
                Image path
            height: int
                Image height in pixels
            width: int
                Image width in pixels
            frame_id: int
                0-indexed frame id
            video_id: int
                Video id
        r   r   r   r   N)rw   r   frame_idvideo_id)r   r   r   r   r   r   r   rx   r   r   r   [  s   
zCocoVidImage.__init__c                 C  s   | |j |j|j|j||dS )zCreates CocoVidImage object using CocoImage object.

        Args:
            coco_image: CocoImage
            frame_id: int
                0-indexed frame id
            video_id: int
                Video id
        r   r   r   r   r   r   r   )r   
coco_imager   r   r   r   r   from_coco_imagex  s   zCocoVidImage.from_coco_imagec                 C  r   )zc
        Adds annotation to this CocoImage instance
        annotation : CocoVidAnnotation
        z/annotation must be a CocoVidAnnotation instanceN)r;   r|   rL   r   r   r   r   r   r   r     r   zCocoVidImage.add_annotationc                 C  rb   )Nr   r   r"   r   r   r   r#     rd   zCocoVidImage.jsonc                 C  s6   d| j  d| j d| j d| j d| j d| j dS )NzCocoVidImage<
    file_name: r   r   z
,
    id: z,
    video_id: z,
    frame_id: z+,
    annotations: List[CocoVidAnnotation]>r   r"   r   r   r   r&     s   zCocoVidImage.__repr__)NNNNN)r'   r(   r)   r*   r   r+   r   r   r,   r#   r&   r{   r   r   rx   r   r   U  s    



r   c                   @  sH   e Zd ZdZ				ddddZdd Zdd Zedd Zdd Z	dS )	CocoVideozCOCO formatted video.

    https://github.com/open-mmlab/mmtracking/blob/master/docs/tutorials/customize_dataset.md#the-cocovid-annotation-file
    Nr   r@   r   r   fpsfloat | Noner   r   c                 C  s(   || _ || _|| _|| _|| _g | _dS )a<  Creates CocoVideo object.

        Args:
            name: str
                Video name
            id: int
                Video id
            fps: float
                Video fps
            height: int
                Video height in pixels
            width: int
                Video width in pixels
        N)r   r   r   r   r   images)r   r   r   r   r   r   r   r   r   r     s   
zCocoVideo.__init__c                 C  s(   t |ts	td| jt| dS )zb
        Adds image to this CocoVideo instance
        Args:
            image: CocoImage
        z"image must be a CocoImage instanceN)r;   r   rL   r   r   r   r   r   imager   r   r   	add_image  s   
zCocoVideo.add_imagec                 C  r   )zs
        Adds CocoVidImage to this CocoVideo instance
        Args:
            cocovidimage: CocoVidImage
        z,cocovidimage must be a CocoVidImage instanceN)r;   r   rL   r   r   )r   cocovidimager   r   r   add_cocovidimage     
zCocoVideo.add_cocovidimagec                 C  s   | j | j| j| j| jdS )Nr   r   r   r   r   r   r"   r   r   r   r#     s   zCocoVideo.jsonc                 C  s.   d| j  d| j d| j d| j d| j dS )NzCocoVideo<
    id: r$   z,
    fps: r   r   z!,
    images: List[CocoVidImage]>)r   r   r   r   r   r"   r   r   r   r&     s   zCocoVideo.__repr__)NNNN)
r   r@   r   r   r   r   r   r   r   r   )
r'   r(   r)   r*   r   r   r   r,   r#   r&   r   r   r   r   r     s    
	r   c                   @  s  e Zd Z						dQdRddZdd Zdd Zdd ZdSdTddZdUddZe							dVdWd%d&Z
ed'd( Zed)d* Zed+d, Zed-d. Zed/d0 Zd1d2 ZdXd5d6Z	7	4		dYdZd?d@Z	7	4		dYdZdAdBZd[d\dGdHZd[d]dJdKZd4edLdfdMdNZdOdP ZdS )^CocoNFautor   r   	image_dirremapping_dictdict[int, int] | Noneignore_negative_samplesboolclip_bboxes_to_img_dimsimage_id_settingLiteral['auto', 'manual']c                 C  sJ   |dvrt d|| _|| _|| _|| _g | _g | _d| _|| _|| _	dS )a  Creates Coco object.

        Args:
            name: str
                Name of the Coco dataset, it determines exported json name.
            image_dir: str
                Base file directory that contains dataset images. Required for dataset merging.
            remapping_dict: dict
                {1:0, 2:1} maps category id 1 to 0 and category id 2 to 1
            ignore_negative_samples: bool
                If True ignores images without annotations in all operations.
            image_id_setting: str
                how to assign image ids while exporting can be
                auto -> will assign id from scratch (<CocoImage>.id will be ignored)
                manual -> you will need to provide image ids in <CocoImage> instances (<CocoImage>.id can not be None)
        r   manualz2image_id_setting must be either 'auto' or 'manual'N)
rG   r   r   r   r   
categoriesr   _statsr   r   )r   r   r   r   r   r   r   r   r   r   r     s   
zCoco.__init__c                 C  V   |D ]&}| j dur | j  D ]}|d |kr| j | }||d< q| t| qdS a5  Creates CocoCategory object using coco category list.

        Args:
            coco_category_list: List[Dict]
                [
                    {"supercategory": "person", "id": 1, "name": "person"},
                    {"supercategory": "vehicle", "id": 2, "name": "bicycle"}
                ]
        Nr   r   keysadd_categoryr   r!   r   coco_category_listcoco_category	source_id	target_idr   r   r   &add_categories_from_coco_category_list     

z+Coco.add_categories_from_coco_category_listc                 C  r   )z_Adds category to this Coco instance.

        Args:
            category: CocoCategory
        (category must be a CocoCategory instanceNr;   r   rL   r   r   r   r    r   r   r   r   3  s   
zCoco.add_categoryc                 C  s,   | j dkr|jdu rtd| j| dS )zVAdds image to this Coco instance.

        Args:
            image: CocoImage
        r   Nz=image id should be manually set for image_id_setting='manual')r   r   rG   r   r   r   r   r   r   r   ?  s   zCoco.add_imagedesired_name2iddict[str, int]update_image_filenamesc                 C  sJ  i }t | j| j| j| jd}| jD ]!}|j}|j}|s!td q||	 v r.|| ||< qd||< q|	 D ]}t
|| ||d}	||	 q7t| jD ]P}
t|
j}tj|
j|
jkrbdnd}|r|s| jsqtd ntttj| j|
j |_|
jD ]}|j}|| }|dur||_|| q|| qN|j| _dS )ax  Rearranges category mapping of given COCO object based on given desired_name2id. Can also be used to filter
        some of the categories.

        Args:
            desired_name2id: dict
                {"big_vehicle": 1, "car": 2, "human": 3}
            update_image_filenames: bool
                If True, updates coco image file_names with absolute file paths.
        r   r   r   r   z.no category name provided to update categoriesNr   TFzimage directory not set)r   r   r   r   r   r   r   r   r<   r   r   r   copydeepcopyr   r   r   r#   ospathabspathr   errorr@   r   r   r0   r   r   __dict__)r   r   r   currentid2desiredid_mappingupdated_cocor   current_category_idcurrent_category_namer   updated_coco_categoryr   updated_coco_imagefile_name_is_abspathrD   desired_category_idr   r   r   update_categoriesJ  sF   




zCoco.update_categoriesrP   c           	      C  s   | j du s
|j du rtd|r|std | }|}d}|du rEi }||fD ]}t|j}|D ]}|d |vrC|||d < |d7 }q0q0q&||fD ]	}|j|dd qI|j|j |j| _|j	| _	|rltd	| j dS dS )
ag  Combines the images/annotations/categories of given coco object with current one.

        Args:
            coco : sahi.utils.coco.Coco instance
                A COCO dataset object
            desired_name2id : dict
                {"human": 1, "car": 2, "big_vehicle": 3}
            verbose: bool
                If True, merging info is printed
        Nz)image_dir should be provided for merging.='desired_name2id' is not specified, combining all categories.r   r   rP   T)r   r   Categories are formed as:
)
r   rG   printr   r   json_categoriesr   r   extendr   )	r   cocor   verbosecoco1coco2category_indtemp_categoriestemp_categoryr   r   r   merge  s:   
z
Coco.merge
   coco_dict_or_path
dict | strdict | Noneuse_threadsnum_threadsr   c              
     s  | ||||d}t |ttfvrtdt|trt|}	n|}	t|	d }
||	d  t|	}|j	 t
 }t } fdd}|
| }|du rt|D ]#}|| }|| }||
kr\|
}t||||	d ||||fd}|  qLt }t D ]
}||ur|  qxnXt|	d d	D ]P}t|}|d
 }||v rtd| d q|| || }|D ]'}|jdur|j|d  }||d< n|d } | }tj||d}|| q|| q|r| }|S )a>  Creates coco object from COCO formatted dict or COCO dataset file path.

        Args:
            coco_dict_or_path: dict/str or List[dict/str]
                COCO formatted dict or COCO dataset file path
                List of COCO formatted dict or COCO dataset file path
            image_dir: str
                Base file directory that contains dataset images. Required for merging and yolov5 conversion.
            remapping_dict: dict
                {1:0, 2:1} maps category id 1 to 0 and category id 2 to 1
            ignore_negative_samples: bool
                If True ignores images without annotations in all operations.
            clip_bboxes_to_img_dims: bool = False
                Limits bounding boxes to image dimensions.
            use_threads: bool = False
                Use threads when processing the json image list, defaults to False
            num_threads: int = 10
                Slice the image list to given number of chunks, defaults to 10

        Properties:
            images: list of CocoImage
            category_mapping: dict
        )r   r   r   r   z)coco_dict_or_path should be a dict or strr   r   c                   s   t || | d|  d| D ]X}t|}|d }	|	|v r'td|	 d q|  ||	 |  ||	 }
|
D ]'}|jd urM|j|d  }||d< n|d } | }tj	||d}|
| q:|| qd S )Nz!Loading coco annotations between z and r   duplicate image_id: , will be ignored.r0   r1   r8   )r   r   r   r   acquireaddreleaser   r-   r>   r   r   )startfinish
image_list_image_id_set_image_id_to_annotation_list_cocolockcoco_image_dictr   rM   annotation_listcoco_annotation_dictr0   r1   rD   category_mappingr   r   fill_image_id_set  s0   



z6Coco.from_coco_dict_or_path.<locals>.fill_image_id_setT)targetargszLoading coco annotationsr   r   r   Nr0   r   )typer@   r9   rL   r;   r   lenr   "get_imageid2annotationlist_mappingr   setr   ranger	   r   	threadingcurrentThread	enumeratejoinr   r   r   r   r   r   r-   r>   r   r   get_coco_with_clipped_bboxes)r   r   r   r   r   r   r   r   r   	coco_dict	dict_sizeimage_id_to_annotation_listimage_id_setr   r   
chunk_sizer_   r   r   tmain_threadr   r   rM   r   r   r0   r1   rD   r   r   r   from_coco_dict_or_path  st   #

"




zCoco.from_coco_dict_or_pathc                 C      g }| j D ]}||j q|S r   r   r   r#   r   r   r    r   r   r   r   O     
zCoco.json_categoriesc                 C      i }| j D ]}|j||j< q|S r   r   r   r   r   r   r    r   r   r   r   V  r  zCoco.category_mappingc                 C  s   t | j| j| j| jdS )N)r   r   r   r   )create_coco_dictr   r   r   r   r"   r   r   r   r#   ]  s   z	Coco.jsonc                 C  s   t | j| j| jdS )N)r   r   r   )create_coco_prediction_arrayr   r   r   r"   r   r   r   prediction_arrayf  s
   zCoco.prediction_arrayc                 C  s   | j s|   | j S r   )r   calculate_statsr"   r   r   r   statsn  s   z
Coco.statsc                 C  s  d}t | j}d}t | j}dd | jD }dd | jD }t|}t|}t|}	t|}
td}d}d}d}d}| jD ]p}i }|jD ];}|j}||7 }||j  d7  < d||j< ||kre|}||k rk|}||
|j krw||
|j< ||	|j k r||	|j< qHt |jdkr|d7 }|t |j7 }t	t
|t
| }t |j}||kr|}||k r|}qA|| dkr|||  }|| }nd}d}|||||||||||||	|
d| _d	S )
z=Iterates over all annotations and calculates total number of.r   c                 S  s   i | ]}|d  dqS )r   r   r   .0r    r   r   r   
<dictcomp>{      z(Coco.calculate_stats.<locals>.<dictcomp>c                 S  s   i | ]	}|d  t dqS )r   inf)floatr  r   r   r   r  |      r   g    _BrP   )
num_imagesnum_annotationsnum_categoriesnum_negative_imagesnum_images_per_categorynum_annotations_per_categorymin_num_annotations_in_imagemax_num_annotations_in_imageavg_num_annotations_in_imagemin_annotation_areamax_annotation_areaavg_annotation_area min_annotation_area_per_category max_annotation_area_per_categoryN)r   r   r   r   r   r!  r   rX   r1   r9   r   r   )r   r$  r#  r&  r%  category_name_to_zerocategory_name_to_infr'  r(  r/  r0  r)  r*  total_annotation_arear,  r-  r   image_contains_categoryr   annotation_areanum_annotations_in_imager+  r.  r   r   r   r  t  sz   












zCoco.calculate_stats?r   c           
      C  s   t | j}t| j}t| t| t|| }|d| }||d }t| j	r.| j	nd| j
d}||_| j|_t| j	rB| j	nd| j
d}	||	_| j|	_||	dS )a  Split images into train-val and returns them as sahi.utils.coco.Coco objects.

        Args:
            train_split_rate: float
            numpy_seed: int
                random seed. Actually, this doesn't use numpy, but the random package
                from the standard library, but it is called numpy for compatibility.

        Returns:
            result : dict
                {
                    "train_coco": "",
                    "val_coco": "",
                }
        Nsplit_train)r   r   	split_val)
train_cocoval_coco)r   r   r   r   randomseedshuffler   r   r   r   r   )
r   train_split_rate
numpy_seedr#  shuffled_images	num_traintrain_images
val_imagesr:  r;  r   r   r   split_coco_as_train_val  s&   


zCoco.split_coco_as_train_val      ?
output_dir
str | Pathr?  r!  r@  mpdisable_symlinkc                 C  s$   t dt | j|||||d dS )znDeprecated.

        Please use export_as_yolo instead. Calls export_as_yolo with the same arguments.
        zBexport_as_yolov5 is deprecated. Please use export_as_yolo instead.)rG  r?  r@  rI  rJ  N)rg   rh   ri   export_as_yolo)r   rG  r?  r@  rI  rJ  r   r   r   export_as_yolov5  s   
zCoco.export_as_yolov5c                 C  s  zddl }W n ty   tdw d|k r|dk rd}n|dkr$d}n|dkr+d}ntd|dkrC| j||d	}|d
 }	|d }
n|dkrL| }	d}
n|dkrTd}	| }
d}d}|dv rmttj|d }|jddd |dv rttj|d }|jddd |dv rt	||	| j
||d |dv rt	||
| j
||d t|t|t| jt| j d}tt|d }t|d}|j||dd W d   dS 1 sw   Y  dS )a'  Exports current COCO dataset in ultralytics/yolo format. Creates train val folders with image symlinks and
        txt files and a data yaml file.

        Args:
            output_dir: str
                Export directory.
            train_split_rate: float
                If given 1, will be exported as train split.
                If given 0, will be exported as val split.
                If in between 0-1, both train/val splits will be calculated and exported.
            numpy_seed: int
                To fix the numpy seed.
            mp: bool
                If True, multiprocess mode is on.
                Should be called in 'if __name__ == __main__:' block.
            disable_symlink: bool
                If True, symlinks will not be created. Instead, images will be copied.
        r   NzVPlease run "pip install -U pyyaml" to install yaml first for yolo formatted exporting.rP   TRAINVALVALTRAIN#train_split_rate cannot be <0 or >1r?  r@  r:  r;  rS   )rM  rO  train/Tparentsexist_ok)rM  rN  val/rG  r   r   rI  rJ  trainvalncnamesdata.ymlwdefault_flow_style)yamlImportErrorrG   rE  r   r   r   r   mkdir,export_yolo_images_and_txts_from_coco_objectr   r@   r   r   listvaluesopendump)r   rG  r?  r@  rI  rJ  ra  
split_moderesultr:  r;  	train_dirval_dirdata	yaml_pathoutfiler   r   r   rK    st   

"zCoco.export_as_yolorQ   subsample_ratior0   r   c                 C  sX  t | j| j| j| jd}|| j |durg }| jD ]/}tt	}|j
D ]}d||j< q$|| r3d}n|dkrAt|j
dkrAd}nd}|rJ|| qg }	| jD ]/}tt	}|j
D ]}d||j< qY|| rhd}n|dkrvt|j
dkrvd}nd}|r|	| qP|r|}
tt|	D ]	}||	|  qn| j}
tdt|
|D ]	}||
|  q|S )a  Subsamples images with subsample_ratio and returns as sahi.utils.coco.Coco object.

        Args:
            subsample_ratio: int
                10 means take every 10th image with its annotations
            category_id: int
                subsample only images containing given category_id, if -1 then subsamples negative samples
        Returns:
            subsampled_coco: sahi.utils.coco.Coco
        r   NrP   Tr   F)r   r   r   r   r   r   r   r   r   r   r   r0   r   r   r  r   )r   rp  r0   subsampled_cocoimages_that_contain_categoryr   category_id_to_containsr   add_this_image#images_that_doesnt_contain_categoryselected_images	image_indr   r   r   get_subsampled_coco]  sV   





zCoco.get_subsampled_cocoupsample_ratioc           	      C  s   t | j| j| j| jd}|| j t|D ]P}tt| j	D ]F}|durYt
t}| j	| jD ]}d||j< q/|| r>d}n|dkrOt| j	| jdkrOd}n|dkrVd}nd}nd}|re|| j	|  qq|S )a  Upsamples images with upsample_ratio and returns as sahi.utils.coco.Coco object.

        Args:
            upsample_ratio: int
                10 means copy each sample 10 times
            category_id: int
                upsample only images containing given category_id, if -1 then upsamples negative samples
        Returns:
            upsampled_coco: sahi.utils.coco.Coco
        r   NrP   Trq  r   F)r   r   r   r   r   r   r   r  r   r   r   r   r   r0   r   )	r   rz  r0   upsampled_cocoindrx  rt  r   ru  r   r   r   get_upsampled_coco  s4   zCoco.get_upsampled_cocor   c           
      C  s   t | j| j| j| jd}|| j | jD ]B}d}|jD ]3}|durC|j	|
 v rC||j	 d }||j	 d }	|j|k sA|j|	krCd}|j|k sM|j|krOd}q|rW|| q|S )a  Filters annotation areas with given min and max values and returns remaining images as sahi.utils.coco.Coco
        object.

        Args:
            min: int
                minimum allowed area
            max_val: int
                maximum allowed area
            intervals_per_category: dict of dicts
                {
                    "human": {"min": 20, "max": 10000},
                    "vehicle": {"min": 50, "max": 15000},
                }
        Returns:
            area_filtered_coco: sahi.utils.coco.Coco
        r   TNminmaxF)r   r   r   r   r   r   r   r   r   r1   r   rX   r   )
r   r~  max_valintervals_per_categoryarea_filtered_cocor   is_valid_imager   category_based_mincategory_based_maxr   r   r   get_area_filtered_coco  s,   


zCoco.get_area_filtered_cococ                 C  s   ddl m} t| j| j| j| jd}|| j | j	D ]F}dd|j
|jg}t|j|j|j
|jd}|jD ]'}|j}|||dr[||}t|j}	t|	|j|j|jd}
||
 q4q4|| q|S )z6Limits overflowing bounding boxes to image dimensions.r   )annotation_inside_slicer   r   )r   rN   rv   )sahi.slicingr  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r#   rW   r   rY   rC   r-   r0   r1   rM   r   r   )r   r  r   coco_imgimg_dimsr   coco_annann_dictshapely_annr6   coco_ann_from_shapelyr   r   r   r    s8   


z!Coco.get_coco_with_clipped_bboxes)NNNFFr   )r   r   r   r   r   r   r   r   r   r   r   r   )F)r   r   r   r   NrP   )NNFFFr   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r7  r   )rF  r   FF)
rG  rH  r?  r!  r@  r   rI  r   rJ  r   )rQ   N)rp  r   r0   r   )rz  r   r0   r   )r'   r(   r)   r   r   r   r   r   r   r+   r  r,   r   r   r#   r  r  r  rE  rL  rK  ry  r}  r!  r  r  r   r   r   r   r     s`    %
=0 





G._C,'r   Fc                   s   t d t rst d d|rDtdd"} fdd jD }|tt|t	|d W d	   d	S 1 s=w   Y  d	S t jD ]}t| j
 qId	S )
aW  Creates image symlinks and annotation txts in yolo format from coco dataset.

    Args:
        output_dir: str
            Export directory.
        coco: sahi.utils.coco.Coco
            Initialized Coco object that contains images and categories.
        ignore_negative_samples: bool
            If True ignores images without annotations in all operations.
        mp: bool
            If True, multiprocess mode is on.
            Should be called in 'if __name__ == __main__:' block.
        disable_symlink: bool
            If True, symlinks are not created. Instead images are copied.
    z:generating image symlinks and annotation files for yolo...z2symlink is not supported in colab, disabling it...T0   )	processesc                   s   g | ]
}| j fqS r   r   )r  r   r   rJ  r   rG  r   r   
<listcomp>/  s    z@export_yolo_images_and_txts_from_coco_object.<locals>.<listcomp>)totalN)r   infor   r<   r   r   starmap.export_single_yolo_image_and_corresponding_txtr   r   r   )rG  r   r   rI  rJ  poolr   r   r   r  r   rd    s&   


"
rd  c              	   C  s  d}| j D ]}t|jdkrd} nq|rdS t| j dkr"|r"dS t| jjdkr5td| j d dS t| jjd	v rHtd
| j d dS t| j rWtj	
| j}n|du r_tdtj	
tt|| j }tt|t| jj }t|}	d}
t|	 rt|j}t|j}t|j}|d t|
 }t|||  }	|
d7 }
t|	 s|rddl}|||	 nt||	 | j}| j}d| }d| }t|	j}|	|d}| j }t|d^}|D ]R}|jd |jd d  }|jd |jd d  }|jd }|jd }|| }|| }|| }|| }|j}||||f}|t|d ddd |D  d  qW d   dS 1 sDw   Y  dS )a?  Generates YOLO formatted image symlink and annotation txt file.

    Args:
        coco_image: sahi.utils.coco.CocoImage
        coco_image_dir: str
        output_dir: str
            Export directory.
        ignore_negative_samples: bool
            If True ignores images without annotations in all operations.
    F   TNr   rS   z(image file has no suffix, skipping it: '').txtz/image file has incorrect suffix, skipping it: 'zAYou have to specify image_dir of Coco object for yolo conversion.rQ   _rP   rF  r  r^  g       @rR    c                 S  s   g | ]}t |qS r   )r@   )r  valuer   r   r   r        zBexport_single_yolo_image_and_corresponding_txt.<locals>.<listcomp>
)r   r   r6   r   r   suffixr   is_filer   r   r   rG   r@   r   r   r   parentstemshutilsymlinkr   r   replacerg  r0   writer  )r   coco_image_dirrG  r   rJ  contains_invalid_annotationsrD   coco_image_pathyolo_image_path_tempyolo_image_pathname_increment
parent_dirfilename
filesuffixr  r   r   dwdhimage_file_suffixyolo_annotation_pathr   ro  r   x_centery_center
bbox_widthbbox_heightr0   	yolo_bboxr   r   r   r  >  st   







,$r  r   r9   r  returnc                 C  s   t |}g g g d}i }|d D ]}|d }|d }||  v r(| | ||< qd||< q|d D ]}|d }|| }	|	dkrJ|	|d< |d | q1g }
|  D ]}i }| |d< |d< | | |d< |
| qQ|
|d< |d	 |d	< |S )
a  Rearranges category mapping of given COCO dictionary based on given category_mapping. Can also be used to filter
    some of the categories.

    Arguments:
    ---------
        desired_name2id : dict
            {"big_vehicle": 1, "car": 2, "human": 3}
        coco_dict : dict
            COCO formatted dictionary.
    Returns:
    ---------
        coco_target : dict
            COCO dict with updated/filtered categories.
    r   r   r   r   r   r   rq  r   r0   r   r   )r   r   r   r   )r   r  coco_sourcecoco_targetr   r    r   r   r   r   r   r   r   r   r   r     s2   

r   	coco_pathr@   	save_pathNonec                 C  s    t |}t| |}t|| dS )aD  Rearranges category mapping of a COCO dictionary in coco_path based on given category_mapping. Can also be used
    to filter some of the categories.

    Arguments:
    ---------
        desired_name2id : dict
            {"human": 1, "car": 2, "big_vehicle": 3}
        coco_path : str
            "dirname/coco.json"
    N)r   r   r   )r   r  r  r  r  r   r   r   update_categories_from_file  s   
r  
coco_dict1
coco_dict2r   c           
      C  s  t | }t |}|durt||}t||}|d |d kr.dd |d D }t||}tdd | d D  }tdd | d	 D  }|}|d D ]}|d
  |d 7  < |d | qP|d	 D ]}	|	d  |d 7  < |	d
  |d 7  < |d	 |	 qh|S )a  Combines 2 coco formatted annotations dicts, and returns the combined coco dict.

    Arguments:
    ---------
        coco_dict1 : dict
            First coco dictionary.
        coco_dict2 : dict
            Second coco dictionary.
        desired_name2id : dict
            {"human": 1, "car": 2, "big_vehicle": 3}
    Returns:
    ---------
        merged_coco_dict : dict
            Merged COCO dict.
    Nr   c                 S  s   i | ]	}|d  |d qS )r   r   r   r  r   r   r   r    r"  zmerge.<locals>.<dictcomp>c                 S     g | ]}|d  qS r   r   )r  r   r   r   r   r    r  zmerge.<locals>.<listcomp>r   c                 S  r  r  r   )r  r   r   r   r   r    r  r   r   rP   rM   )r   r   r   nparrayr  r   )
r  r  r   temp_coco_dict1temp_coco_dict2max_image_idmax_annotation_idmerged_coco_dictr   r   r   r   r   r     s&   




r   rP   c                 C  s   |r|st d |du r2i }d}| D ]}t|d }|D ]}|d |vr0|||d < |d7 }qqqt| D ]\}}|dkrDt|}q6t|||}q6|rTt d|d  |S )a  Combines a list of coco formatted annotations dicts, and returns the combined coco dict.

    Arguments:
    ---------
        coco_dict_list: list of dict
            A list of coco dicts
        desired_name2id: dict
            {"human": 1, "car": 2, "big_vehicle": 3}
        verbose: bool
            If True, merging info is printed
    Returns:
    ---------
        merged_coco_dict: dict
            Merged COCO dict.
    r   Nr   r   r   rP   r   )r   r   r   r  r   )coco_dict_listr   r   r|  r  r   r   r  r   r   r   merge_from_list  s0   
r  
coco_path1
coco_path2c                 C  s(   t | }t |}t||}t|| dS )aJ  Combines 2 coco formatted annotations files given their paths, and saves the combined file to save_path.

    Arguments:
    ---------
        coco_path1 : str
            Path for the first coco file.
        coco_path2 : str
            Path for the second coco file.
        save_path : str
            "dirname/coco.json"
    N)r   r   r   )r  r  r  r  r  r  r   r   r   merge_from_fileH  s   
r  dict[int, list[CocoAnnotation]]c                 C  s:   t t}td | d D ]}|d }|| | q|S )a  Get image_id to annotationlist mapping for faster indexing.

    Arguments
    ---------
        coco_dict : dict
            coco dict with fields "images", "annotations", "categories"
    Returns
    -------
        image_id_to_annotation_list : dict
        {
            1: [CocoAnnotation, CocoAnnotation, CocoAnnotation],
            2: [CocoAnnotation]
        }

        where
        CocoAnnotation = {
            'area': 2795520,
            'bbox': [491.0, 1035.0, 153.0, 182.0],
            'category_id': 1,
            'id': 1,
            'image_id': 1,
            'iscrowd': 0,
            'segmentation': [[491.0, 1035.0, 644.0, 1035.0, 644.0, 1217.0, 491.0, 1217.0]]
        }
    z$indexing coco dataset annotations...r   rM   )r   re  r   debugr   )r  r
  r   rM   r   r   r   r   `  s   
r   r   c              
   C  s   |dvrt dd}d}tg g |d}| D ]Z}|j}t|}	|r%|	dkr%q|dkr0|}
|d7 }n|dkr@|jdu r=t d	|j}
|j|j|
|jd
}|d | |D ]}d|
|j	|j
|j||jd}|d | |d7 }qSq|S )a  Creates COCO dict with fields "images", "annotations", "categories".

    Arguments
    ---------
        images : List of CocoImage containing a list of CocoAnnotation
        categories : List of Dict
            COCO categories
        ignore_negative_samples : Bool
            If True, images without annotations are ignored
        image_id_setting: str
            how to assign image ids while exporting can be
                auto --> will assign id from scratch (<CocoImage>.id will be ignored)
                manual --> you will need to provide image ids in <CocoImage> instances (<CocoImage>.id can not be None)
    Returns
    -------
        coco_dict : Dict
            COCO dict with fields "images", "annotations", "categories"
    r   6'image_id_setting' should be one of ['auto', 'manual']rP   r  r   r   r   NH'coco_image.id' should be set manually when image_id_setting == 'manual')r   r   r   r   r   )r2   rM   r6   r/   r0   r   rX   r   )rG   r9   r   r   r   r   r   r   r   r6   r/   r0   rX   )r   r   r   r   image_indexannotation_idr  r   coco_annotationsr$  rM   	out_imagerD   out_annotationr   r   r   r    sH   

	
r  c                 C  s   |dvrt dd}d}g }| D ]N}|j}t|}|r |dkr q|dkr+|}	|d7 }n|dkr;|jdu r8t d|j}	t|D ]\}
}||	|j|j|j|j|j	|j
d	}|| |d7 }q?q|S )
a  Creates COCO prediction array which is list of predictions.

    Arguments
    ---------
        images : List of CocoImage containing a list of CocoAnnotation
        ignore_negative_samples : Bool
            If True, images without predictions are ignored
        image_id_setting: str
            how to assign image ids while exporting can be
                auto --> will assign id from scratch (<CocoImage>.id will be ignored)
                manual --> you will need to provide image ids in <CocoImage> instances (<CocoImage>.id can not be None)
    Returns
    -------
        coco_prediction_array : List
            COCO predictions array
    r   r  rP   r   r   r   Nr  )r   rM   r6   rt   r0   r/   r2   rX   )rG   r   r   r   r  r6   rt   r0   r/   r2   rX   r   )r   r   r   r  prediction_idpredictions_arrayr   coco_predictionsnum_predictionsrM   prediction_indexcoco_predictionout_predictionr   r   r   r    s>   




r  rS   Tsource_coco_pathtarget_coco_pathadd_bboxr   add_areac              
     s   t | }t|}|d }t|D ]c\}}|rdg   fdd|d D  tt ddd t ddd t ddd t ddd g\}}	}
}||	|
| ||	 f\}}}}||||g|| d	< |rtt|d d
}|j|| d< q||d< t	|| |S )zTakes single coco dataset file path, calculates and fills bbox and area fields of the annotations and exports the
    updated coco dict.

    Returns:
    coco_dict : dict
        Updated coco dict
    r   c                   s   g | ]}  |qS r   )r   )r  coco_polygoncoco_polygonsr   r   r  "  r  z-add_bbox_and_area_to_coco.<locals>.<listcomp>r/   r   NrQ   rP   r6   )coco_segmentationrX   )
r   r   r   r  re  r~  r  r   rX   r   )r  r  r  r  r  r   r|  r   minxminymaxxmaxyxyr   r   shapely_multipolygonr   r  r   add_bbox_and_area_to_coco  s6   
	
r  c                   @  s2   e Zd ZU dZded< ded< dd Zdd	 Zd
S )DatasetClassCountszDStores the number of images that include each category in a dataset.r9   countsr   total_imagesc                   s    fdd j  D S )z>Calculates the frequency of images that contain each category.c                   s   i | ]
\}}|| j  qS r   )r  )r  cidcountr"   r   r   r  F  s    z2DatasetClassCounts.frequencies.<locals>.<dictcomp>)r  itemsr"   r   r"   r   frequenciesD  s   zDatasetClassCounts.frequenciesc                 C  sx   | j |j  }t|j t| j  }i }| j D ]\}}||j|d ||< q|D ]	}|j| ||< q-t||S )Nr   )r  r  r  r   r  getr  )r   or  exclusive_keysr  kvr   r   r   __add__H  s   
zDatasetClassCounts.__add__N)r'   r(   r)   r*   __annotations__r  r   r   r   r   r   r  =  s   
 r  c           
      C  s   t dd }t| }|d D ]}|d }|d }|| | d || |< qt t}| D ]\}}| D ]\}}|dkrE|| d ||< q5q-t|}t| }	t||	S )zReads a coco dataset file and returns an DatasetClassCounts object
     that stores the number of images that include each category in a dataset
    Returns: DatasetClassCounts object
    coco_file_path : str
        path to coco dataset file
    c                   S  s   t tS r   )r   r   r   r   r   r   <lambda>[  s    z,count_images_with_category.<locals>.<lambda>r   rM   r0   rP   r   )r   r   r   r  r9   r   r   r  )
coco_file_pathimage_id_2_category_2_countr   r   rM   r  category_2_countimage_category_2_countr  r  r   r   r   count_images_with_categoryS  s    
r  c                   @  sV   e Zd ZdddZdd Zddd	Zed
d Zedd ZdddZ	edd Z
dS )CocoVidNc                 C  s   || _ || _g | _g | _dS )zCreates CocoVid object.

        Args:
            name: str
                Name of the CocoVid dataset, it determines exported json name.
            remapping_dict: dict
                {1:0, 2:1} maps category id 1 to 0 and category id 2 to 1
        N)r   r   r   videos)r   r   r   r   r   r   r   n  s   	
zCocoVid.__init__c                 C  r   r   r   r   r   r   r   r   |  r   z.CocoVid.add_categories_from_coco_category_listr    r   c                 C  r   )zbAdds category to this CocoVid instance.

        Args:
            category: CocoCategory
        r   Nr   r   r   r   r   r     r   zCocoVid.add_categoryc                 C  r  r   r  r  r   r   r   r     r  zCocoVid.json_categoriesc                 C  r  r   r  r  r   r   r   r     r  zCocoVid.category_mappingvideor   c                 C  r   )zYAdds video to this CocoVid instance.

        Args:
            video: CocoVideo
        z"video must be a CocoVideo instanceN)r;   r   rL   r	  r   )r   r
  r   r   r   	add_video  r   zCocoVid.add_videoc                 C  s  g g g | j d}d}d}d}d}| jD ]n}||_|d |j d}t }|jD ]K}	||	_||	_|j|	_|d |	j |	j	D ]%}
|
|
j |
 j|7  _||
_|	j|
_|d |
j t|d }q?t|d }t|d }q(t|d }|t|7 }q|S )N)r	  r   r   r   rP   r	  r   r   r   )r   r	  r   r   r#   r  r   r   r   r   r   r}   rM   r   r   r   )r   r  r  rM   r   global_instance_id
coco_videor   instance_id_setcocovid_imagecocovid_annotationr   r   r   r#     s>   


zCocoVid.jsonr   )r    r   )r
  r   )r'   r(   r)   r   r   r   r,   r   r   r  r#   r   r   r   r   r  m  s    




r  result_list_or_path
list | strdataset_dict_or_pathdict | str | Nonec           
      C  sp  t | tr
t| }nt | tr| }ntd|durKt |tr$t|}nt |tr,|}ntdi }i }|d D ]}|d ||d < |d ||d < q8g }|D ]f}|d }	|	s\td	 qO|	d
 d
k st|	d d
k st|	d d
k st|	d d
k r|td|	  qO|dur|	d ||d  ks|	d ||d  ks|	d
 ||d  ks|	d ||d  krtd|	  qO|| qO|S )a  
    Removes invalid predictions from coco result such as:
        - negative bbox value
        - extreme bbox value

    Args:
        result_list_or_path: path or list for coco result json
        dataset_dict_or_path (optional): path or dict for coco dataset json
    z(incorrect type for "result_list_or_path"Nz!incorrect type for "dataset_dict"r   r   r   r   r6   z+ignoring invalid prediction with empty bboxr   rP   rQ   rR   z'ignoring invalid prediction with bbox: rM   )r;   r@   r   re  rL   r9   r   r   )
r  r  result_listdataset_dictimage_id_to_heightimage_id_to_widthr   fixed_result_listcoco_resultr6   r   r   r   remove_invalid_coco_results  sD   





0r  r7  rG  r:  Coco | Noner;  r?  r!  c                 C  s$   t dt t| |||||d dS )zpDeprecated.

    Please use export_coco_as_yolo instead. Calls export_coco_as_yolo with the same arguments.
    zLexport_coco_as_yolov5 is deprecated. Please use export_coco_as_yolo instead.rG  r:  r;  r?  r@  rJ  N)rg   rh   ri   export_coco_as_yolor  r   r   r   export_coco_as_yolov5	  s   
r  c                 C  s  zddl }W n ty   tdw |r|sd}n|r |r d}ntd|r8d|  k r3dk s8td td|rI|j||d	}|d
 }|d }ttj| d }	|	jddd ttj| d }
|
jddd t	|	||j
d|d |s{J dt	|
||j
d|d t|	ddt|
ddt|jt|j d}tt| d }t|d}|j||dd W d   |S 1 sw   Y  |S )a  Exports current COCO dataset in ultralytics/YOLO format. Creates train val folders with image symlinks and txt
    files and a data yaml file.

    Args:
        output_dir: str
            Export directory.
        train_coco: Coco
            coco object for training
        val_coco: Coco
            coco object for val
        train_split_rate: float
            train split rate between 0 and 1. will be used when val_coco is None.
        numpy_seed: int
            To fix the numpy seed.
        disable_symlink: bool
            If True, copy images instead of creating symlinks.

    Returns:
        yaml_path: str
            Path for the exported YOLO data.yml
    r   NVPlease run "pip install -U pyyaml" to install yaml first for YOLO formatted exporting.TFz 'train_coco' have to be providedrP   rP  rQ  r:  r;  rR  rS  rV  rW  zValidation Coco object not set\/rX  r]  r^  r_  )ra  rb  rG   rE  r   r   r   r   rc  rd  r   r@   r  r   r   re  rf  rg  rh  )rG  r:  r;  r?  r@  rJ  ra  ri  rj  rk  rl  rm  rn  ro  r   r   r   r  3	  sh   

r  yml_pathc                 C  s"   t dt t| ||||d dS )zDeprecated.

    Please use export_coco_as_yolo_via_yml instead. Calls export_coco_as_yolo_via_yml with the same arguments.
    z\export_coco_as_yolov5_via_yml is deprecated. Please use export_coco_as_yolo_via_yml instead.r#  rG  r?  r@  rJ  N)rg   rh   ri   export_coco_as_yolo_via_ymlr$  r   r   r   export_coco_as_yolov5_via_yml	  s   
r&  c                 C  s   zddl }W n ty   tdw t| }||}W d   n1 s&w   Y  |d rF|d s:t|  dtj|d |d d}nd}|d rc|d	 sWt|  d
tj|d |d	 d}	nd}	t|||	|||d}
|
S )a&  Exports current COCO dataset in ultralytics/YOLO format. Creates train val folders with image symlinks and txt
    files and a data yaml file. Uses a yml file as input.

    Args:
        yml_path: str
            file should contain these fields:
                train_json_path: str
                train_image_dir: str
                val_json_path: str
                val_image_dir: str
        output_dir: str
            Export directory.
        train_split_rate: float
            train split rate between 0 and 1. will be used when val_json_path is None.
        numpy_seed: int
            To fix the numpy seed.
        disable_symlink: bool
            If True, copy images instead of creating symlinks.

    Returns:
        yaml_path: str
            Path for the exported YOLO data.yml
    r   Nr   train_json_pathtrain_image_dirz is missing `train_image_dir`r  val_json_pathval_image_dirz is missing `val_image_dir`r  )ra  rb  rg  	safe_loadrG   r   r  r  )r#  rG  r?  r@  rJ  ra  streamconfig_dictr:  r;  rn  r   r   r   r%  	  s:   
	r%  )FFF)FF)r   r9   r  r9   r  r9   )r   r9   r  r@   r  r@   r  r  r   )r  r9   r  r9   r   r   r  r9   r  )r  r@   r  r@   r  r@   )r  r9   r  r  )Fr   )rS   rS   TT)
r  r@   r  r@   r  r   r  r   r  r9   )r  r  r  r  )NNr7  r   F)rG  r@   r:  r  r;  r  r?  r!  )r7  r   F)r#  r@   rG  r@   r?  r!  )<
__future__r   r   r   r<  r  rg   collectionsr   r   dataclassesr   multiprocessingr   pathlibr   r   r	   typingr
   numpyr  r   sahi.loggerr   sahi.utils.filer   r   r   sahi.utils.shapelyr   r   r   r   r-   rr   r|   r   r   r   r   rd  r  r   r  r   r  r  r   r  r  r  r  r  r  r  r  r  r&  r%  r   r   r   r   <module>   s   % s FLWM      $
)

V
=
1
1

#
JA0s;]