o
    oi+                  	   @   s8  d dl mZ d dlmZmZmZmZ d dlZd dlmZ d dl	m
Z d dlmZ d&ded	ed
efddZdee d
efddZded
efddZded
efddZd'ded	eded
efddZG dd dejZd(dedee ded
efddZd ed!ef d
ed!ef fd"d#Zd ed!ef d
ed!ef fd$d%ZdS ))    )wraps)AnyCallableListOptionalN)nn)
functional)TensorTimagekeepdimreturnc                 C   s   t | jdkst | jdk rtd| j}t| }t |dkr&|d}n&t |dkr4|ddd}nt |dkrE|dddd}d}ntd| |sS|dS |S )	a  Convert a numpy image to a PyTorch 4d tensor image.

    Args:
        image: image of the form :math:`(H, W, C)`, :math:`(H, W)` or
            :math:`(B, H, W, C)`.
        keepdim: If ``False`` unsqueeze the input image to match the shape
            :math:`(B, H, W, C)`.

    Returns:
        tensor of the form :math:`(B, C, H, W)` if keepdim is ``False``,
            :math:`(C, H, W)` otherwise.

    Example:
        >>> img = np.ones((3, 3))
        >>> image_to_tensor(img).shape
        torch.Size([1, 3, 3])

        >>> img = np.ones((4, 4, 1))
        >>> image_to_tensor(img).shape
        torch.Size([1, 4, 4])

        >>> img = np.ones((4, 4, 3))
        >>> image_to_tensor(img, keepdim=False).shape
        torch.Size([1, 3, 4, 4])

          z9Input size must be a two, three or four dimensional arrayr         Tz Cannot process image with shape )lenshape
ValueErrortorch
from_numpy	unsqueezepermute)r
   r   input_shapetensor r   F/home/ubuntu/.local/lib/python3.10/site-packages/kornia/utils/image.pyimage_to_tensor   s   
r   imagesc                    s   | st dg }| D ]}t|st|}|| q
|d j t dkr+t dt fdd|D r:t dtj|dd	ddd	d
S )a  Convert a list of numpy images to a PyTorch 4d tensor image.

    Args:
        images: list of images, each of the form :math:`(H, W, C)`.
        Image shapes must be consistent

    Returns:
        tensor of the form :math:`(B, C, H, W)`.

    Example:
        >>> imgs = [np.ones((4, 4, 1)), np.zeros((4, 4, 1))]
        >>> image_list_to_tensor(imgs).shape
        torch.Size([2, 1, 4, 4])

    zInput list of images is emptyr   r   z$Each image must have shape (H, W, C)c                 3   s    | ]}|j  kV  qd S Nr   ).0imgr   r   r   	<genexpr>i   s    z'image_list_to_tensor.<locals>.<genexpr>z#All images must have the same shapedimr   r   )
r   r   	is_tensor	as_tensorappendr   r   anystackr   )r   images_tr!   r   r   r   image_list_to_tensorM   s   


r+   r   c                 C   s   t | tstdt|  t| jdk rtd| j t| jdkr)| d} t| jdkr5| d} t| jdkrM| d| jd | jd	 | jd } | S )
zConvert a PyTorch tensor image to BCHW format.

    Args:
        tensor (torch.Tensor): image of the form :math:`(*, H, W)`.

    Returns:
        input tensor of the form :math:`(B, C, H, W)`.

     Input type is not a Tensor. Got r   z@Input size must be a two, three or four dimensional tensor. Got r   r   r   	
isinstancer	   	TypeErrortyper   r   r   r   viewr   r   r   r   _to_bchwp   s   



"r6   c                 C   s   t | tstdt|  t| jdk rtd| j t| jdkr)| d} t| jdkr5| d} t| jdkrQ| d| jd | jd	 | jd
 | jd } | S )zConvert a PyTorch tensor image to BCDHW format.

    Args:
        tensor (torch.Tensor): image of the form :math:`(*, D, H, W)`.

    Returns:
        input tensor of the form :math:`(B, C, D, H, W)`.

    r,   r   zAInput size must be a three, four or five dimensional tensor. Got r   r      r-   r.   r/   r0   r5   r   r   r   	_to_bcdhw   s   



*r9   Fforce_contiguousc                 C   s  t | tstdt|  t| jdkst| jdk r td| j}|   }t|dkr0nGt|dkrI|d dkrA|	 }n6|
ddd}n.t|dkrp|
dddd}|d dkrd|sd|	d}|d dkro|	d}ntd	| |r}| }| S )
a  Convert a PyTorch tensor image to a numpy image.

    In case the tensor is in the GPU, it will be copied back to CPU.

    Args:
        tensor: image of the form :math:`(H, W)`, :math:`(C, H, W)` or
            :math:`(B, C, H, W)`.
        keepdim: If ``False`` squeeze the input image to match the shape
            :math:`(H, W, C)` or :math:`(H, W)`.
        force_contiguous: If ``True`` call `contiguous` to the tensor before

    Returns:
        image of the form :math:`(H, W)`, :math:`(H, W, C)` or :math:`(B, H, W, C)`.

    Example:
        >>> img = torch.ones(1, 3, 3)
        >>> tensor_to_image(img).shape
        (3, 3)

        >>> img = torch.ones(3, 4, 4)
        >>> tensor_to_image(img).shape
        (4, 4, 3)

    r,   r   r   z:Input size must be a two, three or four dimensional tensorr   r   r   r-   z!Cannot process tensor with shape )r1   r	   r2   r3   r   r   r   cpudetachsqueezer   
contiguousnumpy)r   r   r:   r   r
   r   r   r   tensor_to_image   s.   



r@   c                       s>   e Zd ZdZddeddf fddZdedefd	d
Z  Z	S )ImageToTensorzConverts a numpy image to a PyTorch 4d tensor image.

    Args:
        keepdim: If ``False`` unsqueeze the input image to match the shape :math:`(B, H, W, C)`.

    Fr   r   Nc                    s   t    || _d S r   )super__init__r   )selfr   	__class__r   r   rC      s   

zImageToTensor.__init__xc                 C   s   t || jdS )N)r   )r   r   )rD   rG   r   r   r   forward   s   zImageToTensor.forward)F)
__name__
__module____qualname____doc__boolrC   r   r	   rH   __classcell__r   r   rE   r   rA      s    rA   r   n_rowpaddingc                 C   s>  t | tjs
td| j\}}}}|du r&tttj|tjd	 
 }|| d | }|| }|| }	t| d|d|f}
|| }||kratj|| |||	f| j| jd}tj|
|fdd}
|
 }
|
|||||	}|ddd	dd
 }|||| ||	 }|| | }||	 | }|ddd|d|f }|S )a?  Convert a batched tensor to one image with padding in between.

    Args:
        tensor: A batched tensor of shape (B, C, H, W).
        n_row: Number of images displayed in each row of the grid.
        padding: The amount of padding to add between images.

    Returns:
        Tensor: The combined image grid.

    z&Input tensor must be a PyTorch tensor.N)dtyper   r   )rQ   devicer#   r   r   r   )r1   r   r	   r2   r   intsqrtr   float32ceilitemFpadzerosrQ   rR   catr>   r4   r   )r   rO   rP   BCHWn_colpadded_Hpadded_Wtensor_paddedtotal	pad_tilesgridcombined
combined_H
combined_Wr   r   r   	make_grid   s*   " rj   f.c              	      *   t  dtdtdtdtf fdd}|S )zApply `f` to an image of arbitrary leading dimensions `(*, C, H, W)`.

    It works by first viewing the image as `(B, C, H, W)`, applying the function and re-viewing the image as original
    shape.
    inputargskwargsr   c                    s   t | tstdt|  | j dkrtd| j}t| }  | g|R i |}t|dkr5|d }t|dkr?|d }t|dkrU|j	|d d |jdd    }|S )	N&Input input type is not a Tensor. Got r   "Invalid input tensor, it is empty.r   r   r   r   r   r.   )
r1   r	   r2   r3   r   numelr   r6   r   r4   rm   rn   ro   r   outputrk   r   r   _wrapper-  s   
 z*perform_keep_shape_image.<locals>._wrapperr   r	   r   rk   rw   r   rv   r   perform_keep_shape_image&      rz   c              	      rl   )zApply `f` to an image of arbitrary leading dimensions `(*, C, D, H, W)`.

    It works by first viewing the image as `(B, C, D, H, W)`, applying the function and re-viewing the image as original
    shape.
    rm   rn   ro   r   c                    s   t | tstdt|  |  dkrtd| j}t| }  | g|R i |}t|dkr4|d }t|dkr>|d }t|dkrT|j	|d d |jdd    }|S )	Nrp   r   rq   r   r   rr   r7   r8   )
r1   r	   r2   r3   rs   r   r   r9   r   r4   rt   rv   r   r   rw   M  s   
 z*perform_keep_shape_video.<locals>._wrapperrx   ry   r   rv   r   perform_keep_shape_videoF  r{   r|   )T)FF)Nr   )	functoolsr   typingr   r   r   r   r   r   torch.nnr   rX   kornia.corer	   rM   r   r+   r6   r9   r@   ModulerA   rS   rj   rz   r|   r   r   r   r   <module>   s   1#= "1& 