
    hn2                       S SK Jr  S SKrS SKJr  S SKJr  S SKJr  S SKJ	r	  S SK
r
S SKrS SKJr  S SKJrJr  S S	KJr  S S
KJr  SSS jjrSSS jjr    S           SS jjrSSS jjr S             S S jjr   S!           S"S jjr S#           S$S jjr S#           S$S jjr\S:X  a  \" SSS9  \" SSS9  gg)%    )annotationsN)glob)ceil)Path)Any)Image)	exif_sizeimg2label_paths)TQDM)check_requirementsc           
       ^ [        S5        SSKJn  U R                  SSS5      n [        R
                  " U SS9n[        R                  " U SS9n[        R                  " XE/SS9n[        R                  " US	S	2S	S	S24   TS
S	S24   5      n[        R                  " US	S	2S	SS	24   TS
SS	24   5      n[        R                  " X-
  S[        R                  5      n	U	S   U	S   -  n
U4S j[        S5       5       u  pp[        R                  " XXXX/SS9R                  SSS5      nU  Vs/ s H  nU" U5      PM     nnU Vs/ s H  nU" U5      PM     nn[        R                  " U
R                  5      n[!        [        R"                  " U
5      6  H-  nUUS      R%                  UUS      5      R&                  UU'   M/     [        R(                  " U Vs/ s H  nUR&                  PM     sn[        R*                  S9nUS   n[        R                  " UU[        R                  5      nUU-  nUR,                  S:X  a  US   nU$ s  snf s  snf s  snf )a  
Calculate Intersection over Foreground (IoF) between polygons and bounding boxes.

Args:
    polygon1 (np.ndarray): Polygon coordinates with shape (N, 8).
    bbox2 (np.ndarray): Bounding boxes with shape (N, 4).
    eps (float, optional): Small value to prevent division by zero.

Returns:
    (np.ndarray): IoF scores with shape (N, 1) or (N, M) if bbox2 is (M, 4).

Notes:
    Polygon format: [x1, y1, x2, y2, x3, y3, x4, y4].
    Bounding box format: [x_min, y_min, x_max, y_max].
zshapely>=2.0.0r   )Polygon      axisN.).r   ).   c              3  2   >#    U  H  nTS U4   v   M     g7f.N ).0ibbox2s     U/home/james-whalen/.local/lib/python3.13/site-packages/ultralytics/data/split_dota.py	<genexpr>bbox_iof.<locals>.<genexpr>1   s     @x!c1fxs   dtyper   r   )r   shapely.geometryr   reshapenpminmaxconcatenatemaximumminimumclipinfrangestackzerosshapezipnonzerointersectionareaarrayfloat32ndim)polygon1r   epsr   lt_pointrb_pointbbox1ltrbwh
h_overlapslefttoprightbottompolygon2p	sg_polys1	sg_polys2overlapsunionsoutputss    `                    r   bbox_iofrJ      s     '((Aq)HvvhR(HvvhR(HNNH/b9E	E!T2A2+&c2A2g	7B	E!T12+&c12g	7B	!RVV	$BFbj(J@uQx@DuxxEtLSUV^^_acdfghH%-.XXI.%-.XXI.xx
(()H"**Z()!o229QrU3CDII *XXy1y!qvvy1DFIFWWVS"&&)FG||q)$N /. 2s   /IIIc           	        US;   d   SU S35       e[        U 5      S-  U-  nUR                  5       (       d   SU S35       e[        [        [        U 5      S-  U-  S-  5      5      n[	        U5      n/ n[        X45       H  u  pg[        [        R                  " U5      5      u  p[        USS	9 n
U
R                  5       R                  5       R                  5        Vs/ s H%  n[        U5      (       d  M  UR                  5       PM'     nn[        R                  " U[        R                   S
9nSSS5        UR#                  [%        X4WUS95        M     U$ s  snf ! , (       d  f       N4= f)a  
Load DOTA dataset annotations and image information.

Args:
    data_root (str): Data root directory.
    split (str, optional): The split data set, could be 'train' or 'val'.

Returns:
    (list[dict[str, Any]]): List of annotation dictionaries containing image information.

Notes:
    The directory structure assumed for the DOTA dataset:
        - data_root
            - images
                - train
                - val
            - labels
                - train
                - val
>   valtrainz$Split must be 'train' or 'val', not .imagesCan't find , please check your data root.*utf-8encodingr   N)ori_sizelabelfilepath)r   existsr   strr
   r/   r	   r   openreadstrip
splitlineslensplitr#   r3   r4   appenddict)	data_rootr`   im_dirim_fileslb_filesannosim_filelb_filewhfxlbs                r   load_yolo_dotaro   C   s;   * $$U(LUGST&UU$)_x'%/F==??Pk&1OPP?CY(2U:S@ABHx(HE3G,-'G,%&VVX^^%5%@%@%BM%Bc!f)!'')%BBM"BJJ/B - 	TA6gFG 4 L N -,s$   1/E E8E%EE
E-	c           	        U u  pV/ n[        X5       GH:  u  pX:  d   SU SU	 S35       eX-
  n
Xh::  a  SO[        Xh-
  U
-  S-   5      n[        U5       Vs/ s H  oU-  PM	     nn[        U5      S:  a  US   U-   U:  a  Xh-
  US'   XX::  a  SO[        XX-
  U
-  S-   5      n[        U5       Vs/ s H  oU-  PM	     nn[        U5      S:  a  US   U-   U:  a  XX-
  US'   [        R
                  " [        [        R                  " X5      5      [        R                  S9nUU-   nUR                  [        R                  " UU/SS95        GM=     [        R                  " USS9nUR                  5       n[        R                  " US	S	2SS	S
24   SU5      US	S	2SS	S
24'   [        R                  " US	S	2SS	S
24   SU5      US	S	2SS	S
24'   US	S	2S
4   US	S	2S4   -
  US	S	2S4   US	S	2S4   -
  -  nUS	S	2S
4   US	S	2S4   -
  US	S	2S4   US	S	2S4   -
  -  nUU-  nUU:  R                  5       (       d$  UR                  5       nSU[!        UU-
  5      U:  '   UUU:     $ s  snf s  snf )a  
Get the coordinates of sliding windows for image cropping.

Args:
    im_size (tuple[int, int]): Original image size, (H, W).
    crop_sizes (tuple[int, ...], optional): Crop size of windows.
    gaps (tuple[int, ...], optional): Gap between crops.
    im_rate_thr (float, optional): Threshold of windows areas divided by image areas.
    eps (float, optional): Epsilon value for math operations.

Returns:
    (np.ndarray): Array of window coordinates with shape (N, 4) where each row is [x_start, y_start, x_stop, y_stop].
zinvalid crop_size gap pair [ ]r   r   r   r   r   Nr      )r/   r   r+   r_   r#   r3   list	itertoolsproductint64ra   r&   copyr)   anyr%   abs)im_size
crop_sizesgapsim_rate_thrr7   rk   rj   windows	crop_sizegapstepxnr   xsynysstartstop
im_in_winsim_areas	win_areasim_ratesmax_rates                          r   get_windowsr   g   s   ( DAGj/	Q">yk3%q QQ.QdAMT+AA+E&F %b	*	1Qh	*r7Q;2b6I-1]BrF.QdAMT+AA+E&F %b	*	1Qh	*r7Q;2b6I-1]BrFi//78Iy r~~udm!<=! 0" nnW1-GJ''*Q1W"5q!<Jq!$Q$w''*Q1W"5q!<Jq!$Q$w1a4 :ad#33
1a48H:VWYZVZK[8[\HAA.71a4=71a4=3PQI)#H{"''))<<>34X()C/08k)**/ +
 +s   I%/I*c                   U S   u  p4U S   n[        U5      (       an  USS2SSS24==   U-  ss'   USS2SSS24==   U-  ss'   [        USS2SS24   U5      n[        [        U5      5       Vs/ s H  ouUSS2U4   U:     PM     sn$ [        [        U5      5       Vs/ s H&  n[        R                  " S[        R
                  S9PM(     sn$ s  snf s  snf )z3Get objects for each window based on IoF threshold.rV   rW   Nr   r   )r   	   r   )r_   rJ   r+   r#   r-   r4   )	annor   iof_thrrk   rj   rW   iofsr   _s	            r   get_window_objr      s    
DAME
5zzaAg!aAg!aeg.8=c'l8KL8K1tAqDzW,-8KLL<A#g,<OP<Oqrzz2<OPP MPs   0C!-Cc           
     ~   [         R                  " U S   5      n[        U S   5      R                  n[	        U5       GHd  u  pU	R                  5       u  ppU SX-
   SU
 SU 3nXkU2X24   nUR                  SS u  nnX(   n[        U5      (       d  U(       a/  [         R                  " [        [        U5      U S3-  5      U5        [        U5      (       d  M  USS2SSS24==   U
-  ss'   USS2SSS24==   U-  ss'   USS2SSS24==   U-  ss'   USS2SSS24==   U-  ss'   [        [        U5      U S3-  S	S
S9 nU HL  nUSS  Vs/ s H  nUS PM	     nnUR                  [        US   5       SSR                  U5       S35        MN     SSS5        GMg     gs  snf ! , (       d  f       GM  = f)a  
Crop images and save new labels for each window.

Args:
    anno (dict[str, Any]): Annotation dict, including 'filepath', 'label', 'ori_size' as its keys.
    windows (np.ndarray): Array of windows coordinates with shape (N, 4).
    window_objs (list[np.ndarray]): A list of labels inside each window.
    im_dir (str): The output directory path of images.
    lb_dir (str): The output directory path of labels.
    allow_background_images (bool, optional): Whether to include background images without labels.

Notes:
    The directory structure assumed for the DOTA dataset:
        - data_root
            - images
                - train
                - val
            - labels
                - train
                - val
rX   _____Nr   .jpgr   z.txtrj   rS   rT   z.6gr   rq   
)cv2imreadr   stem	enumeratetolistr.   r_   imwriterZ   r[   writeintjoin)r   r   window_objsrd   lb_dirallow_background_imagesimnamer   windowx_starty_startx_stopy_stopnew_namepatch_imphpwrW   rl   rn   coordformatted_coordss                          r   crop_and_saver      s   : 
D$	%BZ !&&Dw'	+1==?(&V2f./r'#gYGfngn45#Bu::0KKDLhZt+<<=xHu::!QTT'Ng%N!QTT'Ng%N!QTT'Nb N!QTT'Nb Nd6lz%66gNRSBDFqrF'KF55+F$'KGGs2a5zl!CHH5E,F+GrJK   ON (" (L ONs   F,F'
!8F,'F,,
F<	c           
     D   [        U5      S-  U-  nUR                  SSS9  [        U5      S-  U-  nUR                  SSS9  [        XS9n[        U[	        U5      US9 H=  n[        US   X45      n	[        X5      n
[        XU
[        U5      [        U5      5        M?     g)	a  
Split both images and labels for a given dataset split.

Args:
    data_root (str): Root directory of the dataset.
    save_dir (str): Directory to save the split dataset.
    split (str, optional): The split data set, could be 'train' or 'val'.
    crop_sizes (tuple[int, ...], optional): Tuple of crop sizes.
    gaps (tuple[int, ...], optional): Tuple of gaps between crops.

Notes:
    The directory structure assumed for the DOTA dataset:
        - data_root
            - images
                - split
            - labels
                - split
    and the output directory structure is:
        - save_dir
            - images
                - split
            - labels
                - split
rO   Tparentsexist_oklabels)r`   totaldescrV   N)	r   mkdirro   r   r_   r   r   r   rZ   )rc   save_dirr`   r|   r}   rd   r   rg   r   r   r   s              r   split_images_and_labelsr      s    > (^h&.F
LLL-(^h&.F
LLL-92EU#e*59d:.
A$T3d[#f+s6{K :    c                    / / peU H;  nUR                  [        X'-  5      5        UR                  [        X7-  5      5        M=     S H  n[        XXU5        M     g)a	  
Split train and val sets of DOTA dataset with multiple scaling rates.

Args:
    data_root (str): Root directory of the dataset.
    save_dir (str): Directory to save the split dataset.
    crop_size (int, optional): Base crop size.
    gap (int, optional): Base gap between crops.
    rates (tuple[float, ...], optional): Scaling rates for crop_size and gap.

Notes:
    The directory structure assumed for the DOTA dataset:
        - data_root
            - images
                - train
                - val
            - labels
                - train
                - val
    and the output directory structure is:
        - save_dir
            - images
                - train
                - val
            - labels
                - train
                - val
>   rL   rM   N)ra   r   r   )	rc   r   r   r   ratesr|   r}   rr`   s	            r   split_trainvalr   	  sT    > 2#im,-CL!  "	UM "r   c           	         / / peU H;  nUR                  [        X'-  5      5        UR                  [        X7-  5      5        M=     [        U5      S-  S-  nUR                  SSS9  [        U 5      S-  S-  nUR	                  5       (       d   SU S35       e[        [        US-  5      5      n	[        U	[        U	5      SS9 H  n
[        [        R                  " U
5      5      u  p[        X4XVS	9n[        R                  " U
5      n[        U
5      R                  nU HY  nUR!                  5       u  nnnnU S
UU-
   S
U SU 3nUUU2UU24   n[        R"                  " [        UU S3-  5      U5        M[     M     g)aX  
Split test set of DOTA dataset, labels are not included within this set.

Args:
    data_root (str): Root directory of the dataset.
    save_dir (str): Directory to save the split dataset.
    crop_size (int, optional): Base crop size.
    gap (int, optional): Base gap between crops.
    rates (tuple[float, ...], optional): Scaling rates for crop_size and gap.

Notes:
    The directory structure assumed for the DOTA dataset:
        - data_root
            - images
                - test
    and the output directory structure is:
        - save_dir
            - images
                - test
rO   testTr   rP   rQ   rR   r   )r|   r}   r   r   r   N)ra   r   r   r   rY   r   rZ   r   r_   r	   r   r[   r   r   r   r   r   r   )rc   r   r   r   r   r|   r}   r   rd   re   rh   rj   rk   r   r   r   r   r   r   r   r   r   r   s                          r   
split_testr   0  st   . 2#im,-CL!  H~(61HNN4$N/)_x'&0F==??Pk&1OPP?C%&HHFCG,-qfGZZ G}!!F/5}},GWffr&7"2!32gYc'KH'&.'&.89HKKH(4'8898D	  Dr   __main__DOTAv2zDOTAv2-split)rc   r   )gư>)r6   
np.ndarrayr   r   r7   floatreturnr   )rM   )rc   rZ   r`   rZ   r   zlist[dict[str, Any]])      g333333?g{Gz?)r{   ztuple[int, int]r|   tuple[int, ...]r}   r   r~   r   r7   r   r   r   )gffffff?)r   dict[str, Any]r   r   r   r   r   list[np.ndarray])T)r   r   r   r   r   r   rd   rZ   r   rZ   r   boolr   None)rM   r   r   )rc   rZ   r   rZ   r`   rZ   r|   r   r}   r   r   r   )r   r   )g      ?)rc   rZ   r   rZ   r   r   r   r   r   ztuple[float, ...]r   r   )
__future__r   ru   r   mathr   pathlibr   typingr   r   numpyr#   PILr   ultralytics.data.utilsr	   r
   ultralytics.utilsr   ultralytics.utils.checksr   rJ   ro   r   r   r   r   r   r   __name__r   r   r   <module>r      s   #      
   = " 7,^!L #*"2+2+2+ 2+ 	2+
 
2+ 2+jQ( %)1L
1L1L "1L 	1L
 1L "1L 
1Ln ")"(L(L(L (L  	(L
 (L 
(LX fl$N$N!$N.1$N?B$NQb$N	$NP fl*E*E!*E.1*E?B*EQb*E	*EZ zX?N; r   