code: def combine_tensor_patches(
      patches: Tensor,
      original_size: Union[int, Tuple[int, int]],
      window_size: Union[int, Tuple[int, int]],
      stride: Union[int, Tuple[int, int]],
      unpadding: Union[int, Tuple[int, int]] = 0,
      eps: float = 1e-8,
  ) -> Tensor:
      r"""Restore input from patches.
  
      See :class:`~kornia.contrib.CombineTensorPatches` for details.
  
      Args:
          patches: patched tensor with shape :math:`(B, N, C, H_{out}, W_{out})`.
          original_size: the size of the original tensor and the output patch size.
          window_size: the size of the sliding window used while extracting patches.
          stride: stride of the sliding window.
          unpadding: remove the padding added to both side of the input.
  
      Return:
          The combined patches in an image tensor with shape :math:`(B, C, H, W)`.
  
      Example:
          >>> out = extract_tensor_patches(torch.arange(16).view(1, 1, 4, 4), window_size=(2, 2), stride=(2, 2))
          >>> combine_tensor_patches(out, original_size=(4, 4), window_size=(2, 2), stride=(2, 2))
          tensor([[[[ 0,  1,  2,  3],
                    [ 4,  5,  6,  7],
                    [ 8,  9, 10, 11],
                    [12, 13, 14, 15]]]])
  
      .. note::
          This function is supposed to be used in conjunction with :func:`extract_tensor_patches`.
      """
  
      if patches.ndim != 5:
          raise ValueError(
              f"Invalid input shape, we expect BxNxCxHxW. Got: {patches.shape}"
          )
  
      original_size = cast(Tuple[int, int], _pair(original_size))
      window_size = cast(Tuple[int, int], _pair(window_size))
      stride = cast(Tuple[int, int], _pair(stride))
      unpadding = cast(Tuple[int, int], _pair(unpadding))
  
      if len(unpadding) != 2:
          raise AssertionError(
              "Unpadding must be either an int or a tuple of two ints"
          )
  
      ones = torch.ones(
          patches.shape[0],
          patches.shape[2],
          original_size[0],
          original_size[1],
          device=patches.device,
          dtype=patches.dtype,
      )
      patches = patches.permute(0, 2, 3, 4, 1)
      patches = patches.reshape(patches.shape[0], -1, patches.shape[-1])
      int_flag = 0
      if not torch.is_floating_point(patches):
          int_flag = 1
          dtype = patches.dtype
          patches = patches.float()
          ones = ones.float()
  
      # Calculate normalization map
      unfold_ones = F.unfold(
          ones,
          kernel_size=window_size,
          stride=stride,
          padding=unpadding,
      )
      norm_map = F.fold(
          input=unfold_ones,
          output_size=original_size,
          kernel_size=window_size,
          stride=stride,
          padding=unpadding,
      )
  
      # Restored tensor
      saturated_restored_tensor = F.fold(
          input=patches,
          output_size=original_size,
          kernel_size=window_size,
          stride=stride,
          padding=unpadding,
      )
  
      # Remove satuation effect due to multiple summations
      restored_tensor = saturated_restored_tensor / (norm_map + eps)
      if int_flag:
          restored_tensor = restored_tensor.to(dtype)
      return restored_tensor
  
file_path: kornia/kornia/contrib/extract_patches.py
imports: import math
  from typing import Optional, Tuple, Union, cast
  import torch
  import torch.nn.functional
  from torch.nn.modules.utils import _pair
  from kornia.core import Module, Tensor, pad
label_desc: Use image node_id 2 for calling a global function with example usage: combine_tensor_patches(patches, original_size, window_size, stride, unpadding, eps) and returns: restored_tensor