docstr: :param image_shape: Shape of the source image (H, W)
  :param tile_size: Tile size (Scalar or tuple (H, W)
  :param tile_step: Step in pixels between tiles (Scalar or tuple (H, W))
  :param image_margin:
  :param weight: Fusion algorithm. 'mean' - avergaing
docstr_tok: [":","param","image_shape",":","Shape","of","the","source","image","(","H",",","W",")",":","param","tile_size",":","Tile","size","(","Scalar","or","tuple","(","H",",","W",")",":","param","tile_step",":","Step","in","pixels","between","tiles","(","Scalar","or","tuple","(","H",",","W",")",")",":","param","image_margin",":",":","param","weight",":","Fusion","algorithm",".","'mean","'","-","avergaing"]
code: def __init__(
      self,
      image_shape: Tuple[int, int],
      tile_size,
      tile_step=0,
      image_margin=0,
      weight="mean",
  ):
      """
  
      :param image_shape: Shape of the source image (H, W)
      :param tile_size: Tile size (Scalar or tuple (H, W)
      :param tile_step: Step in pixels between tiles (Scalar or tuple (H, W))
      :param image_margin:
      :param weight: Fusion algorithm. 'mean' - avergaing
      """
      self.image_height = image_shape[0]
      self.image_width = image_shape[1]
  
      if isinstance(tile_size, (np.ndarray, Sequence)):
          if len(tile_size) != 2:
              raise ValueError(
                  f"Tile size must have exactly 2 elements. Got: tile_size={tile_size}"
              )
          self.tile_size = int(tile_size[0]), int(tile_size[1])
      else:
          self.tile_size = int(tile_size), int(tile_size)
  
      if isinstance(tile_step, (np.ndarray, Sequence)):
          if len(tile_step) != 2:
              raise ValueError(
                  f"Tile size must have exactly 2 elements. Got: tile_step={tile_size}"
              )
          self.tile_step = int(tile_step[0]), int(tile_step[1])
      else:
          self.tile_step = int(tile_step), int(tile_step)
  
      weights = {"mean": self._mean, "pyramid": self._pyramid}
  
      self.weight = (
          weight
          if isinstance(weight, np.ndarray)
          else weights[weight](self.tile_size)
      )
  
      if self.tile_step[0] < 1 or self.tile_step[0] > self.tile_size[0]:
          raise ValueError()
      if self.tile_step[1] < 1 or self.tile_step[1] > self.tile_size[1]:
          raise ValueError()
  
      overlap = (
          self.tile_size[0] - self.tile_step[0],
          self.tile_size[1] - self.tile_step[1],
      )
  
      self.margin_left = 0
      self.margin_right = 0
      self.margin_top = 0
      self.margin_bottom = 0
  
      if image_margin == 0:
          # In case margin is not set, we compute it manually
  
          nw = max(
              1,
              math.ceil(
                  (self.image_width - overlap[1]) / self.tile_step[1]
              ),
          )
          nh = max(
              1,
              math.ceil(
                  (self.image_height - overlap[0]) / self.tile_step[0]
              ),
          )
  
          extra_w = self.tile_step[1] * nw - (
              self.image_width - overlap[1]
          )
          extra_h = self.tile_step[0] * nh - (
              self.image_height - overlap[0]
          )
  
          self.margin_left = extra_w // 2
          self.margin_right = extra_w - self.margin_left
          self.margin_top = extra_h // 2
          self.margin_bottom = extra_h - self.margin_top
  
      else:
          if isinstance(image_margin, Sequence):
              (
                  margin_left,
                  margin_right,
                  margin_top,
                  margin_bottom,
              ) = image_margin
          else:
              margin_left = (
                  margin_right
              ) = margin_top = margin_bottom = image_margin
  
          self.margin_left = margin_left
          self.margin_right = margin_right
          self.margin_top = margin_top
          self.margin_bottom = margin_bottom
  
      crops = []
      bbox_crops = []
  
      for y in range(
          0,
          self.image_height
          + self.margin_top
          + self.margin_bottom
          - self.tile_size[0]
          + 1,
          self.tile_step[0],
      ):
          for x in range(
              0,
              self.image_width
              + self.margin_left
              + self.margin_right
              - self.tile_size[1]
              + 1,
              self.tile_step[1],
          ):
              crops.append((x, y, self.tile_size[1], self.tile_size[0]))
              bbox_crops.append(
                  (
                      x - self.margin_left,
                      y - self.margin_top,
                      self.tile_size[1],
                      self.tile_size[0],
                  )
              )
  
      self.crops = np.array(crops)
      self.bbox_crops = np.array(bbox_crops)
  
imports: import dataclasses
  import math
  from typing import List, Iterable, Tuple, Union, Sequence
  import cv2
  import numpy
  import torch
label_desc: Use image node_id 1 to create a new ImageSlicer object  with example: obj = ImageSlicer(image_shape, tile_size, tile_step, image_margin, weight)