a
    ^DfQ                     @   s|   d dl m  mZ d dlmZmZ d dlmZm	Z	m
Z
mZmZ ddlmZ eeeeef ZG dd deZG dd	 d	ZdS )
    N)Enumauto)AnyMappingOptionalTupleUnion   )ParsingErrorc                   @   s6   e Zd ZdZe Ze Ze Zee	d dddZ
dS )	BoxFormatac  
    The coordinate format of a `BoundingBox`, i.e. the order and defining coordinates.

    It can be one of:

    * `BoxFormat.LTRB`: [xmin, ymin, xmax, ymax],
    * `BoxFormat.LTWH`: [xmin, ymin, width, height],
    * `BoxFormat.XYWH`: [xmid, ymid, width, height].

    See the `BoundingBox` documentation for more detail on the coordinate format.
    )stringreturnc                 C   s>   |dkrt jS |dkrt jS |dkr*t jS td| ddS )zy
        Create a `BoxFormat` from a raw string.

        The raw string can be either "ltrb", "ltwh" or "xywh".
        ltrbltwhxywhzInvalid BoxFormat string ''N)r   LTRBLTWHXYWH
ValueError)clsr    r   _/nfs/NAS7/SABIOD/METHODE/ermites/ermites_venv/lib/python3.9/site-packages/globox/boundingbox.pyfrom_string%   s    zBoxFormat.from_stringN)__name__
__module____qualname____doc__r   r   r   r   classmethodstrr   r   r   r   r   r      s   r   c                	   @   sn  e Zd ZdZdZddeeeeeee ddddZe	ee dd	d
Z
e
jee ddd
Z
e	edddZe	edddZe	edddZe	edddZe	edddZe	edddZe	edddZe	edddZe	edddZdedd d!Ze	edd"d#Zd ed$d%d&Zd ed$d'd(Ze	edd)d*Ze	edd+d,Zeed-ed.d/d0Zeed-ed.d1d2Z eeed3d4d5Z!eeed3d6d7Z"e	edd8d9Z#e	edd:d;Z$e	edd<d=Z%e&de'j(d>dd?eeee ed- d d@dAdBZ)ee'j(d>ddd>dCeed- ee ed dDdEdFZ*ed>dGed-ed dHdIdJZ+eed-d dKdLdMZ,eed-d dKdNdOZ-eed-d dKdPdQZ.ee/j0d dRdSdTZ1ee2d dRdUdVZ3ee/j0d dRdWdXZ4edYdZd[e2eed d\d]d^Z5de'j(d>dd_d>d`ee6ee7eef f  e'ed- eeedadbdcZ8dd>ddd-ee6ee7eef f  eededfdgZ9ddhd-ee6ee7eef f  edidjdkZ:ddhd-ee6ee7eef f  edidldmZ;ddhd-ee6ee7eef f  edidndoZ<e2ddpdqZ=e/j0ddrdsZ>e/j0ddtduZ?dYdZd[eee2dvdwdxZ@dydz ZAedd{d|ZBdS )}BoundingBoxu  
    A rectangular bounding box with a label and an optional confidence score. Coordinates are
    absolute (i.e. in pixels) and stored internally in `BoxFormat.LTRB` format.

    Spatial layout:

    ```
        xmin   xmid   xmax
    ymin ╆╍╍╍╍╍╍┿╍╍╍╍╍╍┪
         ╏      ┆      ╏
    ymid ╂┄┄┄┄┄┄┼┄┄┄┄┄┄┨
         ╏      ┆      ╏
    ymax ┺╍╍╍╍╍╍┴╍╍╍╍╍╍┛
    ```
    label_xmin_ymin_xmax_ymax_confidenceN)
confidence)r"   xminyminxmaxymaxr(   r   c                C   sv   ||ksJ d||ks J d|durNd|  kr<dksNn J d| d|| _ || _|| _|| _|| _|| _dS )z
        Create a `BoundingBox` from the top-left and bottom-right corner coordinates.

        Use `BoundingBox.create()` to instantiate a `BoundingBox` from other
        coordinate formats.
        z#`xmax` must be greater than `xmin`.z#`ymax` must be greater than `ymin`.N              ?Confidence () should be in [0, 1].r!   )selfr"   r)   r*   r+   r,   r(   r   r   r   __init__I   s    

zBoundingBox.__init__)r   c                 C   s   | j S )zr
        The bounding box optional confidence score. If present, it is a `float`
        between 0 and 1.
        r'   r1   r   r   r   r(   h   s    zBoundingBox.confidencec                 C   s8   |d ur.d|  krdks.n J d| d|| _ d S )Nr-   r.   r/   r0   r3   )r1   r(   r   r   r   r(   p   s    

c                 C   s   | j S )zNThe `x` value in pixels of the bounding box top-left corner (horizontal axis).)r#   r4   r   r   r   r)   x   s    zBoundingBox.xminc                 C   s   | j S zLThe `y` value in pixels of the bounding box top-left corner (vertical axis).)r$   r4   r   r   r   r*   }   s    zBoundingBox.yminc                 C   s   | j S )zRThe `x` value in pixels of the bounding box bottom-right corner (horizontal axis).)r%   r4   r   r   r   r+      s    zBoundingBox.xmaxc                 C   s   | j S r5   )r&   r4   r   r   r   r,      s    zBoundingBox.ymaxc                 C   s   | j | j d S )zKThe `x` value in pixels of the bounding box center point (horizontal axis).       @)r#   r%   r4   r   r   r   xmid   s    zBoundingBox.xmidc                 C   s   | j | j d S )zIThe `y` value in pixels of the bounding box center point (vertical axis).r6   )r$   r&   r4   r   r   r   ymid   s    zBoundingBox.ymidc                 C   s   | j | j S )z!The bounding box width in pixels.)r%   r#   r4   r   r   r   width   s    zBoundingBox.widthc                 C   s   | j | j S )z"The bounding box height in pixels.)r&   r$   r4   r   r   r   height   s    zBoundingBox.heightc                 C   s   | j | j S )z'The area of the bounding box in pixels.)r9   r:   r4   r   r   r   area   s    zBoundingBox.areaztuple[float, float])range_r   c                 C   s"   |\}}|| j   ko|kS   S )z<Returns `True` if the bounding box area is in a given range.)r;   )r1   r<   Zlower_boundZupper_boundr   r   r   _area_in   s    zBoundingBox._area_inc                 C   s8   t | jt | j d }t | jt | j d }|| S )z*The bounding box PascalVOC area in pixels.r	   )intr%   r#   r&   r$   )r1   r9   r:   r   r   r   pascal_area   s    zBoundingBox.pascal_area)otherr   c                 C   s   t | j|j}t | j|j}t| j|j}t| j|j}||k sH||k rLdS || ||  }| j|j | }|dkrxdS || S )z=The Intersection over Union (IoU) between two bounding boxes.r-   r.   )maxr#   r$   minr%   r&   r;   r1   r@   r)   r*   r+   r,   intersectionunionr   r   r   iou   s    zBoundingBox.iouc                 C   s   t t| jt|j}t t| jt|j}tt| jt|j}tt| jt|j}||k sh||k rldS || d || d  }| j|j | }|dkrdS || S )zHThe Pascal VOC Intersection over Union (IoU) between two bounding boxes.r-   r	   r   r.   )rA   r>   r#   r$   rB   r%   r&   r?   rC   r   r   r   
pascal_iou   s    zBoundingBox.pascal_iouc                 C   s
   | j duS )zAReturn `True` if the bounding box confidence score is not `None`.Nr3   r4   r   r   r   is_detection   s    zBoundingBox.is_detectionc                 C   s
   | j du S )z=Return `True` if the bounding box confidence score is `None`.Nr3   r4   r   r   r   is_ground_truth   s    zBoundingBox.is_ground_truthztuple[int, int])coordssizer   c                 C   s0   | \}}}}|\}}|| || || || fS )aJ  
        Convert coordinates from relative (between 0 and 1) to absolute (pixels) form.

        The coordinates at indices 0 and 2 must be on the X-axis (horizontal) and the ones
        at indices 1 and 3 must be on the Y-axis (vertical).

        The image size should be a `(width, height)` tuple expressed in pixels.
        r   rJ   rK   abcdwhr   r   r   
rel_to_abs   s    
zBoundingBox.rel_to_absc                 C   s0   | \}}}}|\}}|| || || || fS )aJ  
        Convert coordinates from absolute (pixels) to relative (between 0 and 1) form.

        The coordinates at indices 0 and 2 must be on the X-axis (horizontal) and the ones
        at indices 1 and 3 must be on the Y-axis (vertical).

        The image size should be a `(width, height)` tuple expressed in pixels.
        r   rL   r   r   r   
abs_to_rel   s    
zBoundingBox.abs_to_rel)rJ   r   c                 C   s    | \}}}}|||| || fS )z
        Convert coordinates from `BoxFormat.LTWH` to `BoxFormat.LTRB` format.

        The coordinates can be either in relative (between 0 and 1) or absolute (pixels) form.
        r   )rJ   r)   r*   r9   r:   r   r   r   ltwh_to_ltrb   s    zBoundingBox.ltwh_to_ltrbc                 C   s:   | \}}}}|d |d  }}|| || || || fS )z
        Convert coordinates from `BoxFormat.XYWH` to `BoxFormat.LTRB` format.

        The coordinates can be either in relative (between 0 and 1)  or absolute (pixels) form.
           r   )rJ   r7   r8   r9   r:   Zw_hZh_hr   r   r   xywh_to_ltrb  s    zBoundingBox.xywh_to_ltrbc                 C   s   | j | j| j| jfS )zSThe bounding box coordinates in `BoxFormat.LTRB` format and absolute form (pixels).)r#   r$   r%   r&   r4   r   r   r   r     s    zBoundingBox.ltrbc                 C   s   | j | j| j| jfS )zSThe bounding box coordinates in `BoxFormat.LTWH` format and absolute form (pixels).)r#   r$   r9   r:   r4   r   r   r   r     s    zBoundingBox.ltwhc                 C   s   | j | j| j| jfS )zSThe bounding box coordinates in `BoxFormat.XYWH` format and absolute form (pixels).)r7   r8   r9   r:   r4   r   r   r   r     s    zBoundingBox.xywhF)r(   
box_formatrelative
image_size)r"   rJ   r(   rZ   r   c                C   s   |r |dusJ d|  ||}|tju r6| |}n2|tju rL| |}n|tju rXntd| d|\}}}	}
| ||||	|
|dS )z
        Create a `BoundingBox` from different coordinate formats.

        The image size should be provided if the coordinates are given in the relative form
        (values between 0 and 1).
        Nz9For relative coordinates `image_size` should be provided.Unknown BoxFormat 'z'.)r"   r)   r*   r+   r,   r(   )rS   r   r   rU   r   rW   r   r   )r   r"   rJ   r(   rX   rY   rZ   r)   r*   r+   r,   r   r   r   create   s,    


zBoundingBox.createrX   rY   rZ   	separator	conf_last)r   rZ   r^   r_   r   c          
      C   s   |   |}t|dkr(|^}}d }	n2t|dkrR|rF|^}}}	qZ|^}}	}ntdz&tdd |D }|	d ur~t|	}	W n ty   tdY n0 tj|||	|||dS )N      z$Syntax error in txt annotation file.c                 s   s   | ]}t |V  qd S Nfloat.0rO   r   r   r   	<genexpr>c      z'BoundingBox.from_txt.<locals>.<genexpr>)r"   rJ   r(   rX   rY   rZ   )	stripsplitlenr
   tuplerd   r   r    r\   )
r   rX   rY   rZ   r^   r_   valuesr"   rJ   r(   r   r   r   from_txtK  s.    
zBoundingBox.from_txt)r_   )r   rZ   r_   r   c                C   s   t j| tjd|d |dS )NTr]   )r    rn   r   r   )r   rZ   r_   r   r   r   	from_yolor  s    zBoundingBox.from_yolo)r   rZ   r   c                C   s   t j| |ddS )NFrZ   r_   r    ro   r   rZ   r   r   r   from_yolo_darknet  s    zBoundingBox.from_yolo_darknetc                C   s   t j| |ddS )NTrp   rq   rr   r   r   r   from_yolo_v5  s    zBoundingBox.from_yolo_v5c                C   s   t j| |dS )N)rZ   )r    rt   rr   r   r   r   from_yolo_v7  s    zBoundingBox.from_yolo_v7)noder   c                 C   s   |  d}| d}|d u s$|d u r,td| d| d| d| df\}}}}|d u sx|d u sx|d u sx|d u rtdztdd	 ||||fD }W n ty   tdY n0 tj|t|d
S )Nnamebndboxz*Syntax error in imagenet annotation formatr)   r*   r+   r,   c                 s   s   | ]}t |V  qd S rb   rc   re   r   r   r   rg     rh   z'BoundingBox.from_xml.<locals>.<genexpr>r"   rJ   )findtextfindr   rl   r
   r    r\   )rv   r"   box_nodeltrrN   rJ   r   r   r   from_xml  s     

 zBoundingBox.from_xmlc              	   C   sl   z>t | d }| d \\}}\}}tdd ||||fD }W n ttfy\   tdY n0 tj||dS )Nr"   pointsc                 s   s   | ]}t |V  qd S rb   rc   re   r   r   r   rg     rh   z+BoundingBox.from_labelme.<locals>.<genexpr>z(Syntax error in labelme annotation file.ry   )r   rl   r   KeyErrorr
   r    r\   )rv   r"   r)   r*   r+   r,   rJ   r   r   r   from_labelme  s    zBoundingBox.from_labelmec                 C   s   |  d}|  d|  d|  d|  df\}}}}|d u s^|d u s^|d u s^|d u s^|d u rftdztdd ||||fD }W n ty   tdY n0 tj||d	S )
Nr"   xtlytlxbrybrz%Syntax error in CVAT annotation file.c                 s   s   | ]}t |V  qd S rb   rc   re   r   r   r   rg     rh   z(BoundingBox.from_cvat.<locals>.<genexpr>ry   )getr
   rl   r   r    r\   )rv   r"   r}   r~   r   rN   rJ   r   r   r   	from_cvat  s    
,(zBoundingBox.from_cvatZlabel_idr(   )	label_keyconfidence_key)regionr   r   r   c                C   s   zJ| d }|| }| |}| d }|d |d  }}|d |d  }	}
W n tyd   tdY n0 tj||||	|
f|tjdS )	Nregion_attributesshape_attributesxyr9   r:   z)Syntax error in VIA JSON annotation file.)r"   rJ   r(   rX   )r   r   r
   r    r\   r   r   )r   r   r   Zregion_attrsr"   r(   Zshape_attrsr)   r*   r9   r:   r   r   r   from_via_json  s    

zBoundingBox.from_via_json label_to_idrX   rY   rZ   r^   r_   )r   rX   rZ   r^   r_   r   c          
      C   s  d|vsJ d|t ju r"| j}n4|t ju r4| j}n"|t ju rF| j}ntd| d|rv|d usjJ dt	||}| j
}|d ur|| }t|tr||vsJ d| d| d| jr|g|R }	n(|r|g|| jR }	n|| jg|R }	|d	d
 |	D S )N
zEThe newline character '\n' cannot be used as the separator character.r[   r   z:For relative coordinates, `image_size` should be provided.zThe box label 'z' contains the character 'a#  ' which is the same as the separtor character used for BoundingBox representation in TXT/YOLO format. This will corrupt the saved annotation file and likely make it unreadable. Use another character in the label name or `label_to_id` mapping, e.g. use and underscore instead of a whitespace.c                 s   s   | ]}| V  qd S rb   r   )rf   vr   r   r   rg     rh   z%BoundingBox.to_txt.<locals>.<genexpr>)r   r   r   r   r   r   r   r   r    rT   r"   
isinstancer   rI   r'   join)
r1   r   rX   rY   rZ   r^   r_   rJ   r"   liner   r   r   to_txt  s<    




zBoundingBox.to_txt)r   r_   )rZ   r   r_   r   c                C   s   | j |tjd|d|dS )NTr   r   )r   r   r   )r1   rZ   r   r_   r   r   r   to_yolo  s    zBoundingBox.to_yolo)r   )rZ   r   r   c                C   s   | j ||ddS )NFrZ   r   r_   r   r1   rZ   r   r   r   r   to_yolo_darknet#  s    zBoundingBox.to_yolo_darknetc                C   s   | j ||ddS )NTr   r   r   r   r   r   
to_yolo_v5-  s    zBoundingBox.to_yolo_v5c                C   s   | j ||dS )N)rZ   r   )r   r   r   r   r   
to_yolo_v77  s    zBoundingBox.to_yolo_v7c                 C   s(   | j \}}}}| j||g||ggddS )NZ	rectangle)r"   r   Z
shape_type)r   r"   )r1   r)   r*   r+   r,   r   r   r   
to_labelme?  s
    zBoundingBox.to_labelmec                 C   sP   t d}| jt |d_t |d}td| jD ]\}}| t ||_q2|S )Nobjectrw   rx   )r)   r*   r+   r,   )etElementr"   
SubElementtextzipr   )r1   Zobj_noder|   tagZcoordr   r   r   to_xmlH  s    
zBoundingBox.to_xmlc                 C   s2   | j \}}}}tjd| j| | | | ddS )NZbox)r"   r   r   r   r   )attrib)r   r   r   r"   )r1   r   r   r   r   r   r   r   to_cvatR  s    zBoundingBox.to_cvat)r   r   r   c                C   s^   ||ksJ d| d| dd| j | j| j| jd}|| ji}| jd urT| j||< ||dS )NzLabel key 'z' and confidence key 'z' should be different.Zrect)rw   r   r   r9   r:   )r   r   )r)   r*   r9   r:   r"   r(   )r1   r   r   r   r   r   r   r   to_via_json_  s     


zBoundingBox.to_via_jsonc                 C   sV   t |tst| j|jkoT| j|jkoT| j|jkoT| j|jkoT| j|jkoT| j|jkS rb   )	r   r    NotImplementedErrorr"   r)   r*   r+   r,   r(   )r1   r@   r   r   r   __eq__x  s    





zBoundingBox.__eq__c                 C   s6   d| j  d| j d| j d| j d| j d| j dS )NzBoundingBox(label: z, xmin: z, ymin: z, xmax: z, ymax: z, confidence: )r!   r4   r   r   r   __repr__  s    zBoundingBox.__repr__)Cr   r   r   r   	__slots__r   rd   r   r2   propertyr(   setterr)   r*   r+   r,   r7   r8   r9   r:   r;   boolr=   r>   r?   rF   rG   rH   rI   staticmethodCoordinatesrS   rT   rU   rW   r   r   r   r   r   r   r\   rn   ro   rs   rt   ru   r   r   r   dictr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    6   sJ  
	
*&
7	
r    )xml.etree.ElementTreeetreeElementTreer   enumr   r   typingr   r   r   r   r   errorsr
   rd   r   r   r    r   r   r   r   <module>   s   '