o
    oiM?                     @   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+d	ejd
eeef dedeejejf fddZdejdeeef dejfddZdejdedejfddZ	d,dejdedededejf
ddZdejd ejdejfd!d"Zdejd ejdejfd#d$Ze		%	d-d&ejd'ed
eeef d(edejf
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  }|r3||d r&dnd7 }||d r0dnd7 }||d  | }||d  | }	||j d ksQ|	|j d krUtd|dks]|	dkritj|d|	d|gdd	}|j d
 }
|d|
|
d||d||d }|j d |d krt	|j d |d krt	||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 sizereflect)mode   )
shapemathceil
ValueErrorFpadunfoldsqueeze
contiguousAssertionError)r   r	   r
   batchhwkernel_vertkernel_horzpad_vertpad_horzctiles r(   O/home/ubuntu/.local/lib/python3.10/site-packages/kornia/enhance/equalization.py_compute_tiles    s2   


r*   padded_imgs	tile_sizec                 C   s   |   dkr
td| jd |d  dkrtd| jd |d  dkr(td|d d }|d d }| jd	 }| d||d||d
||d }|jd	 |krXt|jd |d d kret|jd |d d krrt|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,   interp_kernel_vertinterp_kernel_horzr&   interp_tilesr(   r(   r)   _compute_interpolation_tilesZ   s,   


r2   r'   binsc                 C   s   t | |dddS )Nr   r   r3   minmaxr   )r'   r3   r(   r(   r)   	_my_histc   s   r7            D@
tiles_x_imnum_binsclipdiffc              	      s  |   dkr
td| j\}}}}}}	||	 }
| d|
}|sBtj r1t fdd|D }n*ttt	t
| gt| }ntjdd |jd}t||td	 }||
9 }|d
krt||
   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   r4   r   ).0tiler;   r(   r)   
<listcomp>   s    z!_compute_luts.<locals>.<listcomp>r   r   )devicegMbP?g        )r6   N)r.   r   r   viewtorchjitis_scriptingstacklistmapr7   lenlinspacerC   r   tensorr   r6   clamp_sum	remainderdiv	transposearangerepeatcumsumclampfloor)r:   r;   r<   r=   bghgwr&   thtwpixelsr'   histosr3   max_valclippedresidualredistv_range	mat_range	lut_scalelutsr(   rA   r)   _compute_luts   s:   
"rg   r1   rf   c                 C   s8  |   dkr
td|  dkrtd| j\}}}}}}tjddtjd}|dkrRt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rt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)

    r>   interp_tiles tensor must be 6D.   luts tensor must be 5D.r   r-   )dtyper   r   trunc)rounding_mode)r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   r   rk   rC   N)r.   r   r   rE   emptylongrS   rD   rQ   rM   fullrk   rC   r6   rT   permute)r1   rf   num_imgsrY   rZ   r&   _j_idxsj_floori_idxsi_floorluts_x_interp_tilesr(   r(   r)   	_map_luts   s6   &"&"^PPPP> rz   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)

    r>   rh   ri   rj      r   r   r   r-   r   r   rn   g       @Nr   r   g     o@)r.   r   rz   r   rp   flatten	unsqueezeexpandrE   gathertoreshape
zeros_likerS   rk   rC   rQ   rR   r   rT   unbindaddcmulsubr   )r1   rf   mapped_lutsrs   rY   rZ   r&   r[   r\   flatten_interp_tilespreinterp_tiles_equalizedtiles_equalizedihiwtiwtihtltrblbrtrX   rt   leftrightr(   r(   r)   _compute_equalized_tiles   sR   

.(,J$.(2$((,
r      r   input
clip_limitslow_and_differentiablec                 C   sJ  t |tstdt| t |tstdt| t|dkr+tdt| t |d ts9t |d tr=td|d dksI|d dkrPt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r|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   )r<   r=   r   r-   ri   N.)
isinstancefloat	TypeErrortypetuplerK   r   r*   r   r2   rg   r   rr   
reshape_asr.   r   )r   r   r	   r   r   
hist_tiles
img_paddedr,   r1   rf   equalized_tileseq_imgsr    r!   r(   r(   r)   equalize_claheK  s0   
"



r   )F)r8   r9   F)r9   r   F)__doc__r   typingr   rE   torch.nn.functionalnn
functionalr   kornia.utils.helpersr   kornia.utils.imager   r   Tensorintboolr*   r2   r7   r   rg   rz   r   r   r(   r(   r(   r)   <module>   sb   

":/
68P
