o
    Vh`.                     @   s   d dl Z d dlmZ d dlmZ d dlmZ d dlZd dlZd dl	m
Z
 d dlmZmZ d dlmZ d dlmZ d(d
dZd)ddZd*ddZd+ddZd,ddZd-ddZd.d d!Zd.d"d#Zed$krred%d&d' ed%d&d' dS dS )/    N)glob)ceil)Path)Image)	exif_sizeimg2label_paths)TQDM)check_requirementsư>c              	      s  t d ddlm  | ddd} tj| dd}tj| dd}tj||gdd}t|d	d	d	d	df d
d	df }t	|d	d	d	dd	f d
dd	f }t
|| dtj}|d |d  }	fddtdD \}
}}}tj|
||||||
|gddddd} fdd| D } fdd|D }t|	j}tt|	 D ]}||d  ||d  j||< qtjdd |D tjd}|d }t
||tj}|| }|jdkr|d }|S )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].
    shapelyr   Polygon      axisN.).r   ).   c                 3   s    | ]	} d |f V  qdS .N .0i)bbox2r   O/var/www/vscode/kcb/lib/python3.10/site-packages/ultralytics/data/split_dota.py	<genexpr>.   s    zbbox_iof.<locals>.<genexpr>c                       g | ]} |qS r   r   r   pr   r   r   
<listcomp>1       zbbox_iof.<locals>.<listcomp>c                    r   r   r   r   r   r   r   r    2   r!   c                 S   s   g | ]}|j qS r   )arear   r   r   r   r    6   s    dtyper   r   )r	   shapely.geometryr   reshapenpminmaxconcatenatemaximumminimumclipinfrangestackzerosshapezipnonzerointersectionr"   arrayfloat32ndim)polygon1r   epslt_pointrb_pointbbox1ltrbwh
h_overlapslefttoprightbottompolygon2	sg_polys1	sg_polys2overlapsr   unionsoutputsr   )r   r   r   bbox_iof   s0   **("
rL   trainc              	   C   s   |dv sJ d| dt | d | }| s J d| dttt | d | d }t|}g }t||D ]D\}}tt|\}}	t|dd	}
d
d |
	 
  D }tj|tjd}W d   n1 slw   Y  |t|	|f||d q9|S )a  
    Load DOTA dataset.

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

    Returns:
        (List[Dict]): List of annotation dictionaries containing image information.

    Notes:
        The directory structure assumed for the DOTA dataset:
            - data_root
                - images
                    - train
                    - val
                - labels
                    - train
                    - val
    >   valrM   z$Split must be 'train' or 'val', not .imagesCan't find , please check your data root.*utf-8encodingc                 S   s   g | ]
}t |r| qS r   )lensplit)r   xr   r   r   r    ^       z"load_yolo_dota.<locals>.<listcomp>r#   N)ori_sizelabelfilepath)r   existsr   strr   r3   r   r   openreadstrip
splitlinesr'   r6   r7   appenddict)	data_rootrX   im_dirim_fileslb_filesannosim_filelb_filewhflbr   r   r   load_yolo_dota@   s   rq         333333?{Gz?c                    sv  | \}}g }t ||D ]\}}	||	ksJ d| d|	 d||	  ||kr(dn	t||   d }
 fddt|
D }t|dkrQ|d | |krQ|| |d< ||krWdn	t||   d } fddt|D }t|dkr|d | |kr|| |d< tjtt||tj	d	}|| }|
tj||gdd
 qtj|dd
}| }t|dddddf d||dddddf< t|dddddf d||dddddf< |dddf |dddf  |dddf |dddf   }|dddf |dddf  |dddf |dddf   }|| }||k s5| }d|t|| |k < |||k S )a  
    Get the coordinates of windows.

    Args:
        im_size (tuple): Original image size, (h, w).
        crop_sizes (List[int]): Crop size of windows.
        gaps (List[int]): Gap between crops.
        im_rate_thr (float): Threshold of windows areas divided by image areas.
        eps (float): 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   c                       g | ]} | qS r   r   r   stepr   r   r    y   r!   zget_windows.<locals>.<listcomp>r   c                    rz   r   r   r   r{   r   r   r    ~   r!   r#   r   r   Nr      )r3   r   r/   rW   r'   r6   list	itertoolsproductint64rd   r*   copyr-   anyr)   abs)im_size
crop_sizesgapsim_rate_thrr:   rn   rm   windows	crop_sizegapxnxsynysstartstop
im_in_winsim_areas	win_areasim_ratesmax_rater   r{   r   get_windowsd   s6     22@@r   ffffff?c                    s   | d \}}| d t rHdddddf  |9  < dddddf  |9  < tddddf | fddtt |D S dd tt |D S )	zGet objects for each window.r[   r\   Nr   r   c                    s$   g | ]}d d |f  k qS )Nr   r   iof_thriofsr\   r   r   r       s   $ z"get_window_obj.<locals>.<listcomp>c                 S   s   g | ]
}t jd t jdqS ))r   	   r#   )r'   r1   r7   )r   _r   r   r   r       rZ   )rW   rL   r/   )annor   r   rn   rm   r   r   r   get_window_obj   s   r   Tc              
   C   s  t | d }t| d j}t|D ]\}}	|	 \}
}}}| d||
  d|
 d| }||||
|f }|jdd \}}|| }t|sJ|rYt t	t|| d | t|r|dddddf  |
8  < |dddddf  |8  < |dddddf  |  < |dddddf  |  < t
t|| d d	d
d*}|D ]}dd |dd D }|t|d  dd| d qW d   n1 sw   Y  qdS )a  
    Crop images and save new labels.

    Args:
        anno (dict): Annotation dict, including `filepath`, `label`, `ori_size` as its keys.
        windows (np.ndarray): Array of windows coordinates with shape (n, 4).
        window_objs (list): 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): Whether to include background images without labels.

    Notes:
        The directory structure assumed for the DOTA dataset:
            - data_root
                - images
                    - train
                    - val
                - labels
                    - train
                    - val
    r]   _____Nr   .jpgr   z.txtrm   rT   rU   c                 S   s   g | ]}|d qS )z.6gr   )r   coordr   r   r   r       r!   z!crop_and_save.<locals>.<listcomp>r   rx   
)cv2imreadr   stem	enumeratetolistr2   rW   imwriter_   r`   writeintjoin)r   r   window_objsrg   lb_dirallow_background_imagesimnamer   windowx_starty_startx_stopy_stopnew_namepatch_imphpwr\   ro   rp   formatted_coordsr   r   r   crop_and_save   s.   &r   c                 C   s   t |d | }|jddd t |d | }|jddd t| |d}t|t||dD ]}t|d ||}	t||	}
t||	|
t|t| q-dS )	a  
    Split both images and labels.

    Args:
        data_root (str): Root directory of the dataset.
        save_dir (str): Directory to save the split dataset.
        split (str): The split data set, could be `train` or `val`.
        crop_sizes (tuple): Tuple of crop sizes.
        gaps (tuple): 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
    rP   Tparentsexist_oklabels)rX   totaldescr[   N)	r   mkdirrq   r   rW   r   r   r   r_   )rf   save_dirrX   r   r   rg   r   rj   r   r   r   r   r   r   split_images_and_labels   s   
r   rs   ru   g      ?c           	      C   sV   g g }}|D ]}| t||  | t||  qdD ]
}t| |||| qdS )a  
    Split train and val set of DOTA.

    Args:
        data_root (str): Root directory of the dataset.
        save_dir (str): Directory to save the split dataset.
        crop_size (int): Base crop size.
        gap (int): Base gap between crops.
        rates (tuple): 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
    )rM   rN   N)rd   r   r   )	rf   r   r   r   ratesr   r   rrX   r   r   r   split_trainval   s   
r   c              	   C   sH  g g }}|D ]}| t||  | t||  qt|d d }|jddd t| d d }| s?J d| dtt|d }	t|	t|	ddD ]Q}
t	t
|
\}}t||f||d	}t|
}t|
j}|D ]0}| \}}}}| d
||  d
| d| }|||||f }tt|| d | qpqPdS )aj  
    Split test set of DOTA, 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): Base crop size.
        gap (int): Base gap between crops.
        rates (tuple): 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
    rP   testTr   rQ   rR   rS   r   )r   r   r   r   r   N)rd   r   r   r   r^   r   r_   r   rW   r   r   r`   r   r   r   r   r   r   )rf   r   r   r   r   r   r   r   rg   rh   rk   rm   rn   r   r   r   r   r   r   r   r   r   r   r   r   r   
split_test  s*   


r   __main__DOTAv2zDOTAv2-split)rf   r   )r
   )rM   )rr   rt   rv   rw   )r   )T)rM   rr   rt   )rs   ru   r   )r   r   mathr   pathlibr   r   numpyr'   PILr   ultralytics.data.utilsr   r   ultralytics.utilsr   ultralytics.utils.checksr	   rL   rq   r   r   r   r   r   r   __name__r   r   r   r   <module>   s,   

/
$
/

-
%
%+