o
    0j                     @   sf  d dl mZmZmZmZmZ d dlZd dlmZ ddl	m
Z
mZmZ ddlmZ ddlmZ d	d
lmZ d	dlmZ edrBd dlZee Zeeef Zejddde
dG dd deZejG dd deZejG dd deZejG dd dZejG dd dZ ejG dd dZ!ejG dd dZ"dee dedee fd d!Z#d"ed#edefd$d%Z$ed	&	'dGd(ed)eeeeef ef d*ed+ed,eeef d-e%fd.d/Z&eje
dG d0d1 d1Z'd2ed3ee( d4eeef defd5d6Z)d2ed3ee( d4eeef defd7d8Z*dHd9d:Z+d;d< Z,dId?d@Z-dAdB Z.dJdCdDZ/ejG dEdF dFZ0dS )K    )ListOptionalSequenceTupleUnionN)ndarray   )class_requires_depsfunction_requires_depsis_dep_available   )	ReadImage)	benchmark   )	Normalize)Resizezopencv-contrib-pythonT)nameZis_read_operationc                   @   s<   e Zd ZdZdeeeeef  dee fddZ	dd Z
dS )	r   z9Reads images from a list of raw image data or file paths.raw_imgsreturnc                 C   s   g }|D ]`}t  }t|tr||d< t|t r8d|v r |d }nd|v r-|d }||d< ntd|| |}| |\}}||d< ||d< |jd |jd g|d< |jd |jd g|d< || q|S )	ak  Processes the input list of raw image data or file paths and returns a list of dictionaries containing image information.

        Args:
            raw_imgs (List[Union[ndarray, str]]): A list of raw image data (numpy ndarrays) or file paths (strings).

        Returns:
            List[dict]: A list of dictionaries, each containing image information.
        Zimg_pathimgz@When raw_img is dict, must have one of keys ['img', 'img_path'].ori_img   r   img_sizeori_img_size)dict
isinstancestr
ValueErrorupdatereadshapeappend)selfr   Z	out_datasZraw_imgdataZsrc_imgr   r    r$   u/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddlex/inference/models/object_detection/processors.py__call__&   s.   	




zReadImage.__call__c                 C   s   t |tjr|}| jdkrt|tj}||fS t |trI| j	|}|d u r.t
d| |}| jdkrE|jdkr>tdt|tj}||fS tdt|j d)NRGBzImage read Error: r   zArray is not 3-dimensional.zReadImage only supports the following types:
1. str, indicating a image file path or a directory containing image files.
2. numpy.ndarray.
However, got type: .)r   npr   formatcv2cvtColorZCOLOR_BGR2RGBr   Z_img_readerr   	ExceptionndimRuntimeError	TypeErrortype__name__)r"   r   r   Zblobr$   r$   r%   r   J   s(   



zReadImage.readN)r2   
__module____qualname____doc__r   r   r   r   r   r&   r   r$   r$   r$   r%   r   !   s    $$r   c                   @   &   e Zd Zdee dee fddZdS )r   datasr   c                 C   s   |D ]C}|d }d|vr|j d |j d g|d< |d }| |}||d< |j d |j d g}||d< |d |d  |d |d  g|d< q|S )a<  
        Args:
            datas (List[dict]): A list of dictionaries, each containing image data with key 'img'.

        Returns:
            List[dict]: A list of dictionaries with updated image data, including resized images,
                original image sizes, resized image sizes, and scale factors.
        r   r   r   r   r   scale_factors)r    resize)r"   r7   r#   r   r   r   r   r$   r$   r%   r&   g   s   	

zResize.__call__Nr2   r3   r4   r   r   r&   r$   r$   r$   r%   r   e       r   c                   @   r6   )r   r7   r   c                 C       |D ]}|  |d |d< q|S )zNormalizes images in a list of dictionaries. Iterates over each dictionary,
        applies normalization to the 'img' key, and returns the modified list.
        r   )Znormr"   r7   r#   r$   r$   r%   r&      s   zNormalize.__call__Nr:   r$   r$   r$   r%   r      r;   r   c                   @   s*   e Zd ZdZdee dee fddZdS )
ToCHWImagezAConverts images in a list of dictionaries from HWC to CHW format.r7   r   c                 C   s    |D ]}|d  d|d< q|S )aZ  Converts the image data in the list of dictionaries from HWC to CHW format in-place.

        Args:
            datas (List[dict]): A list of dictionaries, each containing an image tensor in 'img' key with HWC format.

        Returns:
            List[dict]: The same list of dictionaries with the image tensors converted to CHW format.
        r   )r   r   r   )Z	transposer=   r$   r$   r%   r&      s   	zToCHWImage.__call__N)r2   r3   r4   r5   r   r   r&   r$   r$   r$   r%   r>      s    r>   c                	   @   sj   e Zd ZdZddeee  fddZej	fde
e dedejd	ejfd
dZde
e d	ee fddZdS )ToBatchz
    Class for batch processing of data dictionaries.

    Args:
        ordered_required_keys (Optional[Tuple[str]]): A tuple of keys that need to be present in the input data dictionaries in a specific order.
    Nordered_required_keysc                 C   s
   || _ d S Nr@   )r"   r@   r$   r$   r%   __init__   s   
zToBatch.__init__r7   keydtyper   c                    s    dkr fdd|D }t j|ddj|ddS  dkr2 fd	d|D }t j|ddj|ddS t j fd
d|D ddj|ddS )a  
        Apply batch processing to a list of data dictionaries.

        Args:
            datas (List[dict]): A list of data dictionaries to process.
            key (str): The key in the data dictionaries to extract and batch.
            dtype (np.dtype): The desired data type of the output array (default is np.float32).

        Returns:
            np.ndarray: A numpy array containing the batched data.

        Raises:
            KeyError: If the specified key is not found in any of the data dictionaries.
        r   c                    s   g | ]}|  d d d qS )Nr$   .0r#   rD   r$   r%   
<listcomp>   s    z!ToBatch.apply.<locals>.<listcomp>r   )ZaxisF)rE   copyr8   c                    s&   g | ]}|  d d gddd qS )      ?NrF   )getrG   rI   r$   r%   rJ      s   & c                    s   g | ]}|  qS r$   r$   rG   rI   r$   r%   rJ      s    )r)   stackastype)r"   r7   rD   rE   Z	img_sizesr8   r$   rI   r%   apply   s   zToBatch.applyc                    s    fddj D S )Nc                    s   g | ]}  |qS r$   rP   )rH   rD   r7   r"   r$   r%   rJ      s    z$ToBatch.__call__.<locals>.<listcomp>rB   )r"   r7   r$   rR   r%   r&      s   zToBatch.__call__rA   )r2   r3   r4   r5   r   r   r   rC   r)   float32r   r   rE   r   rP   r   r&   r$   r$   r$   r%   r?      s    
 r?   c                       sn   e Zd ZdZg dfdee deeeef  f fddZde	de	fd	d
Z
dee dee fddZ  ZS )DetPadz
    Pad image to a specified size.
    Args:
        size (list[int]): image target size
        fill_value (list[float]): rgb value of pad area, default (114.0, 114.0, 114.0)
    )     \@rU   rU   size
fill_valuec                    s,   t    t|tr||g}|| _|| _d S rA   )superrC   r   intrV   rW   )r"   rV   rW   	__class__r$   r%   rC      s
   


zDetPad.__init__r   r   c                 C   s   |}|j d d \}}| j\}}||kr||kr|S tj||dftjd}|tj| jtjd9 }|tj|d|d|d d f< |S )Nr   r   rE   r   )r    rV   r)   onesrS   arrayrW   rO   )r"   r   imim_him_whwZcanvasr$   r$   r%   rP      s   
"zDetPad.applyr7   c                 C   r<   Nr   rQ   r=   r$   r$   r%   r&         zDetPad.__call__)r2   r3   r4   r5   r   rY   r   floatrC   r   rP   r   r&   __classcell__r$   r$   rZ   r%   rT      s    
"rT   c                       sP   e Zd ZdZddef fddZdefddZd	ee	 d
ee	 fddZ
  ZS )	PadStridezpadding image for model with FPN , instead PadBatch(pad_to_stride, pad_gt) in original config
    Args:
        stride (bool): model with FPN need image shape % stride == 0
    r   stridec                    s   t    || _d S rA   )rX   rC   coarsest_stride)r"   ri   rZ   r$   r%   rC      s   

zPadStride.__init__r   c           
      C   s   |}| j }|dkr|S |j\}}}ttt|| | }ttt|| | }tj|||ftjd}	||	ddd|d|f< |	S )z
        Args:
            im (np.ndarray): image (np.ndarray)
        Returns:
            im (np.ndarray):  processed image (np.ndarray)
        r   r\   N)rj   r    rY   r)   ceilrf   zerosrS   )
r"   r   r_   rj   Zim_cr`   ra   Zpad_hZpad_wZ
padding_imr$   r$   r%   rP     s   zPadStride.applyr7   r   c                 C   r<   rd   rQ   r=   r$   r$   r%   r&     re   zPadStride.__call__)r   )r2   r3   r4   r5   rY   rC   r   rP   r   r   r&   rg   r$   r$   rZ   r%   rh      s
    "rh   pt	angle_radr   c                 C   sb   t | dksJ t|t|}}| d | | d |  }| d | | d |  }||g}|S )zRotate a point by an angle.
    Args:
        pt (list[float]): 2 dimensional point to be rotated
        angle_rad (float): rotation angle by radian
    Returns:
        list[float]: Rotated point.
    r   r   r   )lenr)   sincos)rm   rn   ZsncsZnew_xZnew_yZ
rotated_ptr$   r$   r%   rotate_point  s   rs   abc                 C   sN   t | dksJ t |dksJ | | }|tj|d  |d gtjd }|S )a  To calculate the affine matrix, three pairs of points are required. This
    function is used to get the 3rd point, given 2D points a & b.
    The 3rd point is defined by rotating vector `a - b` by 90 degrees
    anticlockwise, using b as the rotation center.
    Args:
        a (np.ndarray): point(x,y)
        b (np.ndarray): point(x,y)
    Returns:
        np.ndarray: The 3rd point.
    r   r   r   r\   )ro   r)   r^   rS   )rt   ru   	directionZthird_ptr$   r$   r%   _get_3rd_point+  s
   "rw           ry   Fcenter
input_sizerotoutput_sizeshiftinvc                 C   s  t | dksJ t |dksJ t |dksJ t|ttfs)tj||gtjd}|}t|}|d }|d }|d }	tj| d }
td|d g|
}td|d g}tj	dtjd}| ||  |dd	d	f< | | ||  |dd	d	f< t
|dd	d	f |dd	d	f |dd	d	f< tj	dtjd}|d
 |	d
 g|dd	d	f< t|d
 |	d
 g| |dd	d	f< t
|dd	d	f |dd	d	f |dd	d	f< |rtt|t|}|S tt|t|}|S )a  Get the affine transform matrix, given the center/scale/rot/output_size.
    Args:
        center (np.ndarray[2, ]): Center of the bounding box (x, y).
        input_size (np.ndarray[2, ]): Scale of the bounding box
            wrt [width, height].
        rot (float): Rotation angle (degree).
        output_size (np.ndarray[2, ]): Size of the destination heatmaps.
        shift (0-100%): Shift translation ratio wrt the width/height.
            Default (0., 0.).
        inv (bool): Option to inverse the affine transform direction.
            (inv=False: src->dst or inv=True: dst->src)
    Returns:
        np.ndarray: The transform matrix.
    r   r\   r   r      ry   g      )r   r   N      ?)ro   r   r   listr)   r^   rS   pirs   rl   rw   r+   ZgetAffineTransform)rz   r{   r|   r}   r~   r   Z	scale_tmpZsrc_wZdst_wZdst_hZrot_radsrc_dirZdst_dirsrcdstZtransr$   r$   r%   get_affine_transform>  s4   
.&.r   c                       sX   e Zd ZdZ							d fdd		Zd
efddZdee dee fddZ	  Z
S )
WarpAffineaL  Apply warp affine transformation to the image based on the given parameters.

    Args:
        keep_res (bool): Whether to keep the original resolution aspect ratio during transformation.
        pad (int): Padding value used when keep_res is True.
        input_h (int): Target height for the input image when keep_res is False.
        input_w (int): Target width for the input image when keep_res is False.
        scale (float): Scale factor for resizing.
        shift (float): Shift factor for transformation.
        down_ratio (int): Downsampling ratio for the output image.
    F      皙?皙?r   c                    s8   t    || _|| _|| _|| _|| _|| _|| _d S rA   )	rX   rC   keep_respadinput_hinput_wscaler~   
down_ratio)r"   r   r   r   r   r   r~   r   rZ   r$   r%   rC     s   


zWarpAffine.__init__r   c                 C   s  t |t j}|jd d \}}| jr:|| jB d }|| jB d }tj||gtjd}tj|d |d gtjd}nt	||d }| j
| j}}tj|d |d gtjd}t||d||g}t |||f}t j||||ft jd}	| js|| j }
|| j }t||d||
g |	S )Nr   r   r\   rL   g       @r   )flags)r+   r,   ZCOLOR_RGB2BGRr    r   r   r)   r^   rS   maxr   r   r   r9   Z
warpAffineZINTER_LINEARr   )r"   r   rb   rc   r   r   scZtrans_inputinpZout_hZout_wr$   r$   r%   rP     s(   

zWarpAffine.applyr7   r   c                 C   sH   |D ]}|d }d|vr|j d |j d g|d< | |}||d< q|S )Nr   r   r   r   )r    rP   )r"   r7   r#   r   r   r$   r$   r%   r&     s   

zWarpAffine.__call__)Fr   r   r   r   r   r   )r2   r3   r4   r5   rC   r   rP   r   r   r&   rg   r$   r$   rZ   r%   r   w  s    " r   boxeslabelsr   c              
   C   s   g }|\}}| D ]E}|dd \}}}	}
t d|}t d|}t||	}	t||
}
|	|ks0|
|kr1q|t|d |t|d  t|d |||	|
gd q|S )a   
    Restructure the given bounding boxes and labels based on the image size.

    Args:
        boxes (ndarray): A 2D array of bounding boxes with each box represented as [cls_id, score, xmin, ymin, xmax, ymax].
        labels (List[str]): A list of class labels corresponding to the class ids.
        img_size (Tuple[int, int]): A tuple representing the width and height of the image.

    Returns:
        Boxes: A list of dictionaries, each containing 'cls_id', 'label', 'score', and 'coordinate' keys.
    r   Nr   r   Zcls_idlabelscoreZ
coordinate)r   minr!   rY   rf   )r   r   r   box_listrc   rb   boxxminyminxmaxymaxr$   r$   r%   restructured_boxes  s$   






	r   c                 C   s  g }|\}}| j d dksJ d| D ]p}|dd \}}}	}
}}}}ttd||}ttd||}ttd|	|}	ttd|
|}
ttd||}ttd||}ttd||}ttd||}|t|d |t|d  t|d |||	|
||||gd q|S )a  
    Restructure the given rotated bounding boxes and labels based on the image size.

    Args:
        boxes (ndarray): A 2D array of rotated bounding boxes with each box represented as [cls_id, score, x1, y1, x2, y2, x3, y3, x4, y4].
        labels (List[str]): A list of class labels corresponding to the class ids.
        img_size (Tuple[int, int]): A tuple representing the width and height of the image.

    Returns:
        Boxes: A list of dictionaries, each containing 'cls_id', 'label', 'score', and 'coordinate' keys.
    r   
   z,The shape of rotated boxes should be [N, 10]r   Nr   r   )r    r   r   r!   rY   rf   )r   r   r   r   rc   rb   r   x1y1x2y2Zx3Zy3Zx4Zy4r$   r$   r%   restructured_rotated_boxes  s*   

	r   c              	   C   s  |du r| S t |trng }| D ]Y}|\}}}}}}	||v rc|| \}
}|| }|	| }||
 }|| }||d  }||d  }||d  }||d  }||d  }||d  }|||||||g q|| qt|S | dddf | dddf  }| dddf | dddf  }||d  }||d  }| dddf |d  }| dddf |d  }||d  }||d  }||d  }||d  }t| dddf | dddf ||||f}|S )a]  
    Expand bounding boxes from (x1, y1, x2, y2) format using an unclipping ratio.

    Parameters:
    - boxes: np.ndarray of shape (N, 4), where each row is (x1, y1, x2, y2).
    - unclip_ratio: tuple of (width_ratio, height_ratio), optional.

    Returns:
    - expanded_boxes: np.ndarray of shape (N, 4), where each row is (x1, y1, x2, y2).
    Nr   r      r   r   r   )r   r   r!   r)   r^   Zcolumn_stack)r   Zunclip_ratioZexpanded_boxesr   Zclass_idr   r   r   r   r   Zwidth_ratioZheight_ratiowidthheightZnew_wZnew_hZcenter_xZcenter_yZnew_x1Znew_y1Znew_x2Znew_y2widthsZheightsr$   r$   r%   unclip_boxes  sF   

  &r   c                 C   s   | \}}}}|\}}}}	t ||}
t ||}t||}t||	}t d||
 d t d|| d  }|| d || d  }|| d |	| d  }|t|| |  }|S )z@Compute the Intersection over Union (IoU) of two bounding boxes.r   r   )r   r   rf   )box1box2r   r   r   r   x1_py1_px2_py2_pZx1_iZy1_iZx2_iZy2_iZ
inter_area	box1_areaZ	box2_area	iou_valuer$   r$   r%   iouM  s   



$r   333333?ffffff?c                 C   s   | dddf }t |ddd }g }t|dkrn|d }| | }|d }|d  |dd }	|| |dd }g }
|D ]&}| | }|d }|dd }t|	|}||krZ|n|}||k re|
| q?|
}t|dks|S )zcPerform Non-Maximum Suppression (NMS) with different IoU thresholds for same and different classes.Nr   rF   r   r   )r)   argsortro   r!   r   )r   iou_sameiou_diffZscoresindicesZselected_boxescurrentZcurrent_boxZcurrent_classZcurrent_coordsZfiltered_indicesir   Z	box_classZ
box_coordsr   	thresholdr$   r$   r%   nmse  s0   


r   c                 C   s   | \}}}}}}|\}}}}}	}
|| ||  }t ||}t ||}t||	}t||
}t d|| }t d|| }|| }|dkrF|| nd}|dkS )z'Check if box1 is contained within box2.r   g?)r   r   )r   r   _r   r   r   r   r   r   r   r   r   Zxi1Zyi1Zxi2Zyi2Zinter_widthZinter_heightZintersect_arear   r$   r$   r%   is_contained  s   



r   c           	      C   s$  t | }tj|td}tj|td}t|D ]w}t|D ]p}||kr#q|dur8| | d |kr8| | d |kr8q|dur{|dur{|dkr]| | d |kr]t| | | | r]d||< d||< |dkrz| | d |krzt| | | | rzd||< d||< qt| | | | rd||< d||< qq||fS )z,Check containment relationships among boxes.r\   Nr   larger   small)ro   r)   rl   rY   ranger   )	r   formula_indexcategory_indexmodencontains_othercontained_by_otherr   jr$   r$   r%   check_containment  s4    r   c                       s   e Zd ZdZddeee  ddf fddZdede	e
e
f d	eeef d
ee deeee	eef ef  deeeef  defddZ				ddee dee d	eeeef  d
ee deeee	eef f  dee dee fddZ  ZS )DetPostProcesszSave Result Transform

    This class is responsible for post-processing detection results, including
    thresholding, non-maximum suppression (NMS), and restructuring the boxes
    based on the input type (normal or rotated object detection).
    Nr   r   c                    s   t    || _dS )a  Initialize the DetPostProcess class.

        Args:
            threshold (float, optional): The threshold to apply to the detection scores. Defaults to 0.5.
            labels (Optional[List[str]], optional): The list of labels for the detection categories. Defaults to None.
            layout_postprocess (bool, optional): Whether to apply layout post-processing. Defaults to False.
        N)rX   rC   r   )r"   r   rZ   r$   r%   rC     s   

zDetPostProcess.__init__r   r   r   
layout_nmslayout_unclip_ratiolayout_merge_bboxes_modec           "      C   s,  t |tr"|dddf |k|dddf dk@ }||ddf }nPt |trrg }t|dddf D ]1}	||dddf |	k }
|t|	d}|
dddf |k|
dddf dk@ }||
|  q4|rmt|nt	g }|rt
|ddddf ddd	}t	|| }d
}|rt|dkr|jd dv r|d |d krd}nd}d| jv r| jdnd}|d |d  }g }|D ]E}|dd \}}}}}}||krtd|}td|}t|d |}t|d |}|| ||  }||| kr|| q|| qt|dkr|}t	|}|rd| jv r'| jdnd}t |trl|dv s;J d| |dkrAnt|ddddf |\}}|dkr\||dk }n|dkrk||dk|dkB  }npt |trtjt|td}| D ]X\}}|dv sJ d| |dkrq|dkrt|ddddf |||d\}}||dkM }q|dkrt|ddddf |||d\}}||dk|dkB M }q|| }|jdkrg S |jd dkrt|dddf  |dddf f} ||  }!|!ddddf }|jd dkr/t|dddf } ||  }!|!ddddf }|rgt |tr=||f}n%t |ttfrQt|dksPJ dnt |trXn
tdt| dt||}|jd dkry	 t|| j|}|S |jd dkr	 t|| j|}|S 	 td|jd  )a	  Apply post-processing to the detection boxes.

        Args:
            boxes (ndarray): The input detection boxes with scores.
            img_size (tuple): The original image size.

        Returns:
            Boxes: The post-processed detection boxes.
        Nr   r   rF   r      r   g\(\?)r   r   T)r         g=
ףp=?g(\?imageZformula)unionr   r   z\The value of `layout_merge_bboxes_mode` must be one of ['union', 'large', 'small'], but got r   r   r   r\   )r   r   r   r   z0The length of `layout_unclip_ratio` should be 2.zqThe type of `layout_unclip_ratio` must be float, Tuple[float, float] or  Dict[int, Tuple[float, float]], but got r(   r   z1The shape of boxes should be 6 or 10, instead of ) r   rf   r   r)   uniquerM   rY   r!   Zvstackr^   r   ro   r    r   indexr   r   r   r   r]   boolitemsrV   Zlexsortr   tupler   r   r1   r   r   r   )"r"   r   r   r   r   r   r   Zexpect_boxesZcategory_filtered_boxesZcat_idZcategory_boxesZcategory_thresholdZselected_indicesZfilter_large_imageZ
area_thresZimage_indexZimg_areaZfiltered_boxesr   Zlabel_indexr   r   r   r   r   Zbox_arear   r   r   Z	keep_maskr   Zlayout_modeZ
sorted_idxZsorted_boxesr$   r$   r%   rP     s  
(
$













(

	zDetPostProcess.applybatch_outputsr7   c              	   C   sB   g }t ||D ]\}}	| |	d |d ||||}
||
 q|S )a  Apply the post-processing to a batch of outputs.

        Args:
            batch_outputs (List[dict]): The list of detection outputs.
            datas (List[dict]): The list of input data.

        Returns:
            List[Boxes]: The list of post-processed detection boxes.
        r   r   )ziprP   r!   )r"   r   r7   r   r   r   r   Zoutputsr#   outputr   r$   r$   r%   r&   r  s   zDetPostProcess.__call__rA   )NNNN)r2   r3   r4   r5   r   r   r   rC   r   r   rY   r   rf   r   r   BoxesrP   r&   rg   r$   r$   rZ   r%   r     sL     


 /r   )rx   FrA   )r   r   )NNN)1typingr   r   r   r   r   numpyr)   r   Z
utils.depsr	   r
   r   Zcommon.readerr   ZCommonReadImageZutils.benchmarkr   commonr   ZCommonNormalizer   ZCommonResizer+   r   r   rY   rf   NumberZtimeit_with_optionsZtimeitr>   r?   rT   rh   rs   rw   r   r   r   r   r   r   r   r   r   r   r   r   r$   r$   r$   r%   <module>   s   B
/%"
8M

%


(:
"
