a
    d<                     @   s.  d Z ddlZddlmZ ddlZddlm  mZ ddl	m
Z
 ddlmZ ddlmZ d ejeeef eeejejf d	d
dZejeeef ejdddZejeejdddZd!ejeeeejdddZejejejdddZejejejdddZed"ejeeeef eejdddZdS )#zHIn this module several equalization methods are exposed: he, ahe, clahe.    N)Tuple_torch_histc_cast)perform_keep_shape_image   )	histogramF)imgs	grid_sizeeven_tile_sizereturnc                 C   s@  | }|j dd \}}t||d  }t||d  }|rf||d rLdnd7 }||d r`dnd7 }||d  | }||d  | }	||j d ks|	|j d krtd|dks|	dkrtj|d|	d|gdd	}|j d
 }
|d|
|
d||d||d }|j d |d kr t	|j d |d kr8t	||fS )a  Compute tiles on an image according to a grid size.

    Note that padding can be added to the image in order to crop properly the image.
    So, the grid_size (GH, GW) x tile_size (TH, TW) >= image_size (H, W)

    Args:
        imgs: batch of 2D images with shape (B, C, H, W) or (C, H, W).
        grid_size: number of tiles to be cropped in each direction (GH, GW)
        even_tile_size: Determine if the width and height of the tiles must be even.

    Returns:
        tensor with tiles (B, GH, GW, C, TH, TW). B = 1 in case of a single image is provided.
        tensor with the padded batch of 2D imageswith shape (B, C, H', W').
    Nr   r      zBCannot compute tiles on the image according to the given grid sizeZreflect)mode   )
shapemathceil
ValueErrorFpadunfoldsqueeze
contiguousAssertionError)r   r	   r
   batchhwZkernel_vertZkernel_horzZpad_vertZpad_horzctiles r#   d/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/enhance/equalization.py_compute_tiles   s6    
r%   )padded_imgs	tile_sizer   c                 C   s   |   dkrtd| jd |d  dkr2td| jd |d  dkrPtd|d d }|d d }| jd	 }| d||d||d
||d }|jd	 |krt|jd |d d krt|jd |d d krt|S )a  Compute interpolation tiles on a properly padded set of images.

    Note that images must be padded. So, the tile_size (TH, TW) * grid_size (GH, GW) = image_size (H, W)

    Args:
        padded_imgs: batch of 2D images with shape (B, C, H, W) already padded to extract tiles
                                    of size (TH, TW).
        tile_size: shape of the current tiles (TH, TW).

    Returns:
        tensor with the interpolation tiles (B, 2GH, 2GW, C, TH/2, TW/2).
       zImages Tensor must be 4D.r   r   z Images are not correctly padded.r   r   r   r   r   )dimr   r   r   r   r   )r&   r'   Zinterp_kernel_vertZinterp_kernel_horzr!   interp_tilesr#   r#   r$   _compute_interpolation_tilesH   s0    
r+   )r"   binsr   c                 C   s   t | |dddS )Nr   r   r,   minmaxr   )r"   r,   r#   r#   r$   	_my_histcv   s    r0            D@)
tiles_x_imnum_binsclipdiffr   c              	      s  |   dkrtd| j\}}}}}}	||	 }
| d|
}|stj rbt fdd|D }qttt	t
| gt| }n2tjdd |jd}t||td	 }||
9 }|d
krTt||
   d}|j|d |
|d }t| }||  }||d dd7 }tj |jd}||jd d}|||d ddk 7 } d |
 }t|d| }|d d }|s| }||||| f}|S )a  Compute luts for a batched set of tiles.

    Same approach as in OpenCV (https://github.com/opencv/opencv/blob/master/modules/imgproc/src/clahe.cpp)

    Args:
        tiles_x_im: set of tiles per image to apply the lut. (B, GH, GW, C, TH, TW)
        num_bins: number of bins. default: 256
        clip: threshold value for contrast limiting. If it is 0 then the clipping is disabled.
        diff: denote if the differentiable histagram will be used. Default: False

    Returns:
        Lut for each tile (B, GH, GW, C, 256).
       zTensor must be 6D.r   c                    s   g | ]}t | d ddqS )r   r   r-   r   ).0Ztiler4   r#   r$   
<listcomp>       z!_compute_luts.<locals>.<listcomp>r   r   )devicegMbP?g        )r/   N)r)   r   r   viewtorchZjitZis_scriptingstacklistmapr0   lenZlinspacer<   r   tensorr   r/   Zclamp_sum	remainderdiv	transposearangerepeatZcumsumclampfloor)r3   r4   r5   r6   bghgwr!   thtwZpixelsr"   Zhistosr,   Zmax_valZclippedZresidualZredistZv_rangeZ	mat_rangeZ	lut_scalelutsr#   r9   r$   _compute_lutsz   s:    
"
rR   )r*   rQ   r   c                 C   s:  |   dkrtd|  dkr(td| j\}}}}}}tjddtjd}|dkrtd	|d	 |d d	jdd
d}t	g dg dg|d d  }||7 }tjddtjd}	|dkrtd	|d	 |d d	jdd
d}
t	g dg dg|d d  }	|	|
7 }	tj
|||d||jd fd| j| jd}|ddddt|d d	 d	ddt|d d	 d	f |dddd|d	 dd|d	 df< |dd|dddf ddt|d d	 d	f |ddd	ddd|d	 df< |dd|dddf ddt|d d	 d	f |ddd	ddd|d	 d	f< |ddddt|d d	 d	|	dddf f |dddd|d	 d	ddf< |ddddt|d d	 d	|	ddd	f f |dddd|d	 d	dd	f< |dd|t|d d	d	d	d	dd|	t|d d	d	d	f |ddd	dd	dddf< |S )a  Assign the required luts to each tile.

    Args:
        interp_tiles: set of interpolation tiles. (B, 2GH, 2GW, C, TH/2, TW/2)
        luts: luts for each one of the original tiles. (B, GH, GW, C, 256)

    Returns:
         mapped luts (B, 2GH, 2GW, 4, C, 256)
    r7   interp_tiles tensor must be 6D.   luts tensor must be 5D.r   r(   )dtyper   r   trunc)Zrounding_mode)r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   r   rV   r<   N)r)   r   r   r>   emptylongrH   r=   rF   rC   fullrV   r<   r/   rI   permute)r*   rQ   num_imgsrM   rN   r!   _Zj_idxsZj_floorZi_idxsZi_floorZluts_x_interp_tilesr#   r#   r$   	_map_luts   s6    
&"
&"^PPPP> r_   c              	   C   s  |   dkrtd|  dkr(tdt| |}| j\}}}}}}| d  dd}	|	d|||d	||| }	t	|d|	
| |||d	|||}
t| }tjd
| d dd| j| jdd| d d ddd
| |}|d||d||}tjd
| d dd| j| jdd| d |d
| }|d||d||}||d
 d
 d
|||d
 d||d}||d
 d
 dddd}|
ddddddf d\}}}}t||t||}t||t||}t||t|||ddddddf< |
dddd|d dd|d df |dddd|d dd|d f< |
dddddf d
\}}}}t||dt|||dddddf< |
dddd|d f d
\}}}}t||dt|||dddd|d f< |
dddddf d
\}}}}t||t|||dddddf< |
dd|d ddf d
\}}}}t||t|||dd|d ddf< |dS )a.  Equalize the tiles.

    Args:
        interp_tiles: set of interpolation tiles, values must be in the range [0, 1].
          (B, 2GH, 2GW, C, TH/2, TW/2)
        luts: luts for each one of the original tiles. (B, GH, GW, C, 256)

    Returns:
        equalized tiles (B, 2GH, 2GW, C, TH/2, TW/2)
    r7   rS   rT   rU      r   r   r   r(   r   r   rX   g       @Nr   r   g     o@)r)   r   r_   r   rZ   flattenZ	unsqueezeexpandr>   ZgathertoZreshapeZ
zeros_likerH   rV   r<   rF   rG   r   rI   ZunbindZaddcmulsubr   )r*   rQ   Zmapped_lutsr]   rM   rN   r!   rO   rP   Zflatten_interp_tilesZpreinterp_tiles_equalizedZtiles_equalizedZihiwZtiwZtihtltrblbrtrL   r^   lrr#   r#   r$   _compute_equalized_tiles   sb    

 
 
.(,J$.(2$((,rm      ro   )input
clip_limitr	   slow_and_differentiabler   c                 C   sL  t |tstdt| t |ts8tdt| t|dkrVtdt| t |d tsrt |d trztd|d dks|d dkrtd| | }t||d	\}}|jd
 |jd f}t	||}t
|||d}	t||	}
|
dddddd|}|jd
d \}}|dd|d|f }|  | krH|d}|S )a  Apply clahe equalization on the input tensor.

    .. image:: _static/img/equalize_clahe.png

    NOTE: Lut computation uses the same approach as in OpenCV, in next versions this can change.

    Args:
        input: images tensor to equalize with values in the range [0, 1] and shape :math:`(*, C, H, W)`.
        clip_limit: threshold value for contrast limiting. If 0 clipping is disabled.
        grid_size: number of tiles to be cropped in each direction (GH, GW).
        slow_and_differentiable: flag to select implementation

    Returns:
        Equalized image or images with shape as the input.

    Examples:
        >>> img = torch.rand(1, 10, 20)
        >>> res = equalize_clahe(img)
        >>> res.shape
        torch.Size([1, 10, 20])

        >>> img = torch.rand(2, 3, 10, 20)
        >>> res = equalize_clahe(img)
        >>> res.shape
        torch.Size([2, 3, 10, 20])
    z(Input clip_limit type is not float. Got z'Input grid_size type is not Tuple. Got r   z4Input grid_size is not a Tuple with 2 elements. Got r   r   z=Input grid_size type is not valid, must be a Tuple[int, int].z/Input grid_size elements must be positive. Got Tr   r   )r5   r6   r   r(   rT   N.)
isinstancefloat	TypeErrortypetuplerB   r   r%   r   r+   rR   rm   r\   Z
reshape_asr)   r   )rp   rq   r	   rr   r   Z
hist_tilesZ
img_paddedr'   r*   rQ   Zequalized_tilesZeq_imgsr   r    r#   r#   r$   equalize_clahe5  s,    !




rx   )F)r1   r2   F)r2   rn   F)__doc__r   typingr   r>   Ztorch.nn.functionalnnZ
functionalr   Zkornia.utils.helpersr   Zkornia.utils.imager   r   ZTensorintboolr%   r+   r0   rt   rR   r_   rm   rx   r#   r#   r#   r$   <module>   s@    9. 
57O   
