code: def slice_image(
      image: Union[str, Image.Image],
      coco_annotation_list: Optional[List[CocoAnnotation]] = None,
      output_file_name: Optional[str] = None,
      output_dir: Optional[str] = None,
      slice_height: Optional[int] = None,
      slice_width: Optional[int] = None,
      overlap_height_ratio: float = 0.2,
      overlap_width_ratio: float = 0.2,
      auto_slice_resolution: bool = True,
      min_area_ratio: float = 0.1,
      out_ext: Optional[str] = None,
      verbose: bool = False,
  ) -> SliceImageResult:
      """Slice a large image into smaller windows. If output_file_name is given export
      sliced images.
  
      Args:
          image (str or PIL.Image): File path of image or Pillow Image to be sliced.
          coco_annotation_list (List[CocoAnnotation], optional): List of CocoAnnotation objects.
          output_file_name (str, optional): Root name of output files (coordinates will
              be appended to this)
          output_dir (str, optional): Output directory
          slice_height (int, optional): Height of each slice. Default None.
          slice_width (int, optional): Width of each slice. Default None.
          overlap_height_ratio (float): Fractional overlap in height of each
              slice (e.g. an overlap of 0.2 for a slice of size 100 yields an
              overlap of 20 pixels). Default 0.2.
          overlap_width_ratio (float): Fractional overlap in width of each
              slice (e.g. an overlap of 0.2 for a slice of size 100 yields an
              overlap of 20 pixels). Default 0.2.
          auto_slice_resolution (bool): if not set slice parameters such as slice_height and slice_width,
              it enables automatically calculate these params from image resolution and orientation.
          min_area_ratio (float): If the cropped annotation area to original annotation
              ratio is smaller than this value, the annotation is filtered out. Default 0.1.
          out_ext (str, optional): Extension of saved images. Default is the
              original suffix for lossless image formats and png for lossy formats ('.jpg','.jpeg').
          verbose (bool, optional): Switch to print relevant values to screen.
              Default 'False'.
  
      Returns:
          sliced_image_result: SliceImageResult:
                                  sliced_image_list: list of SlicedImage
                                  image_dir: str
                                      Directory of the sliced image exports.
                                  original_image_size: list of int
                                      Size of the unsliced original image in [height, width]
          num_total_invalid_segmentation: int
              Number of invalid segmentation annotations.
      """
  
      # define verboseprint
      verboselog = logger.info if verbose else lambda *a, **k: None
  
      def _export_single_slice(
          image: np.ndarray, output_dir: str, slice_file_name: str
      ):
          image_pil = read_image_as_pil(image)
          slice_file_path = str(Path(output_dir) / slice_file_name)
          # export sliced image
          image_pil.save(slice_file_path, quality="keep")
          image_pil.close()  # to fix https://github.com/obss/sahi/issues/565
          verboselog("sliced image path: " + slice_file_path)
  
      # create outdir if not present
      if output_dir is not None:
          Path(output_dir).mkdir(parents=True, exist_ok=True)
  
      # read image
      image_pil = read_image_as_pil(image)
      verboselog("image.shape: " + str(image_pil.size))
  
      image_width, image_height = image_pil.size
      if not (image_width != 0 and image_height != 0):
          raise RuntimeError(
              f"invalid image size: {image_pil.size} for 'slice_image'."
          )
      slice_bboxes = get_slice_bboxes(
          image_height=image_height,
          image_width=image_width,
          auto_slice_resolution=auto_slice_resolution,
          slice_height=slice_height,
          slice_width=slice_width,
          overlap_height_ratio=overlap_height_ratio,
          overlap_width_ratio=overlap_width_ratio,
      )
  
      n_ims = 0
  
      # init images and annotations lists
      sliced_image_result = SliceImageResult(
          original_image_size=[image_height, image_width],
          image_dir=output_dir,
      )
  
      image_pil_arr = np.asarray(image_pil)
      # iterate over slices
      for slice_bbox in slice_bboxes:
          n_ims += 1
  
          # extract image
          tlx = slice_bbox[0]
          tly = slice_bbox[1]
          brx = slice_bbox[2]
          bry = slice_bbox[3]
          image_pil_slice = image_pil_arr[tly:bry, tlx:brx]
  
          # set image file suffixes
          slice_suffixes = "_".join(map(str, slice_bbox))
          if out_ext:
              suffix = out_ext
          elif hasattr(image_pil, "filename"):
              suffix = Path(getattr(image_pil, "filename")).suffix
              if suffix in IMAGE_EXTENSIONS_LOSSY:
                  suffix = ".png"
              elif suffix in IMAGE_EXTENSIONS_LOSSLESS:
                  suffix = Path(image_pil.filename).suffix
          else:
              suffix = ".png"
  
          # set image file name and path
          slice_file_name = (
              f"{output_file_name}_{slice_suffixes}{suffix}"
          )
  
          # create coco image
          slice_width = slice_bbox[2] - slice_bbox[0]
          slice_height = slice_bbox[3] - slice_bbox[1]
          coco_image = CocoImage(
              file_name=slice_file_name,
              height=slice_height,
              width=slice_width,
          )
  
          # append coco annotations (if present) to coco image
          if coco_annotation_list is not None:
              for sliced_coco_annotation in process_coco_annotations(
                  coco_annotation_list, slice_bbox, min_area_ratio
              ):
                  coco_image.add_annotation(sliced_coco_annotation)
  
          # create sliced image and append to sliced_image_result
          sliced_image = SlicedImage(
              image=image_pil_slice,
              coco_image=coco_image,
              starting_pixel=[slice_bbox[0], slice_bbox[1]],
          )
          sliced_image_result.add_sliced_image(sliced_image)
  
      # export slices if output directory is provided
      if output_file_name and output_dir:
          conc_exec = concurrent.futures.ThreadPoolExecutor(
              max_workers=MAX_WORKERS
          )
          conc_exec.map(
              _export_single_slice,
              sliced_image_result.images,
              [output_dir] * len(sliced_image_result),
              sliced_image_result.filenames,
          )
  
      verboselog(
          "Num slices: "
          + str(n_ims)
          + " slice_height: "
          + str(slice_height)
          + " slice_width: "
          + str(slice_width)
      )
  
      return sliced_image_result
  
imports: import concurrent.futures
  import logging
  import os
  import time
  from pathlib import Path
  from typing import Dict, List, Optional, Sequence, Tuple, Union
  import numpy
  from PIL import Image
  from shapely.errors import TopologicalError
  from tqdm import tqdm
  from sahi.annotation import BoundingBox, Mask
  from sahi.utils.coco import Coco, CocoAnnotation, CocoImage, create_coco_dict
  from sahi.utils.cv import IMAGE_EXTENSIONS_LOSSLESS, IMAGE_EXTENSIONS_LOSSY, read_image_as_pil
  from sahi.utils.file import load_json, save_json
label_desc: Use image node_id 4 for calling a global function with example usage: slice_image(image, coco_annotation_list, output_file_name, output_dir, slice_height, slice_width, overlap_height_ratio, overlap_width_ratio, auto_slice_resolution, min_area_ratio, out_ext, verbose) and returns: sliced_image_result