code: def get_image_generator(
      height,
      width,
      font_groups,
      text_generator,
      font_size: typing.Union[int, typing.Tuple[int, int]] = 18,
      backgrounds: typing.List[typing.Union[str, np.ndarray]] = None,
      background_crop_mode="crop",
      rotationX: typing.Union[int, typing.Tuple[int, int]] = 0,
      rotationY: typing.Union[int, typing.Tuple[int, int]] = 0,
      rotationZ: typing.Union[int, typing.Tuple[int, int]] = 0,
      margin=0,
      use_ligatures=False,
      augmenter=None,
      draw_contour=False,
      draw_contour_text=False,
  ):
      """Create a generator for images containing text.
  
      Args:
          height: The height of the generated image
          width: The width of the generated image.
          font_groups: A dict mapping of { subalphabet: [path_to_font1, path_to_font2] }.
          text_generator: See get_text_generator
          font_size: The font size to use. Alternative, supply a tuple
              and the font size will be randomly selected between
              the two values.
          backgrounds: A list of paths to image backgrounds or actual images
              as numpy arrays with channels in RGB order.
          background_crop_mode: One of letterbox or crop, indicates
              how backgrounds will be resized to fit on the canvas.
          rotationX: The X-axis text rotation to use. Alternative, supply a tuple
              and the rotation will be randomly selected between
              the two values.
          rotationY: The Y-axis text rotation to use. Alternative, supply a tuple
              and the rotation will be randomly selected between
              the two values.
          rotationZ: The Z-axis text rotation to use. Alternative, supply a tuple
              and the rotation will be randomly selected between
              the two values.
          margin: The minimum margin around the edge of the image.
          use_ligatures: Whether to render ligatures (see `draw_text_image`)
          augmenter: An image augmenter to be applied to backgrounds
          draw_contour: Draw the permitted contour onto images (debugging only)
          draw_contour_text: Draw the permitted contour inside the text
              drawing function.
  
      Yields:
          Tuples of (image, lines) where image is the
          transparent text image and lines is a list of lines
          where each line itself is a list of (box, character) tuples and
          box is an array of points with shape (4, 2) providing the coordinates
          of the character box in clockwise order starting from the top left.
      """
      if backgrounds is None:
          backgrounds = [np.zeros((height, width, 3), dtype="uint8")]
      alphabet = "".join(font_groups.keys())
      assert len(set(alphabet)) == len(
          alphabet
      ), "Each character can appear in the subalphabet for only one font group."
      for text, background_index, current_font_groups in zip(
          text_generator,
          itertools.cycle(range(len(backgrounds))),
          zip(
              *[
                  itertools.cycle(
                      [
                          (subalphabet, font_filepath)
                          for font_filepath in font_group_filepaths
                      ]
                  )
                  for subalphabet, font_group_filepaths in font_groups.items()
              ]
          ),
      ):
          if background_index == 0:
              random.shuffle(backgrounds)
          current_font_groups = dict(current_font_groups)
          current_font_size = (
              np.random.randint(low=font_size[0], high=font_size[1])
              if isinstance(font_size, tuple)
              else font_size
          )
          current_rotation_X, current_rotation_Y, current_rotation_Z = [
              (
                  np.random.uniform(low=rotation[0], high=rotation[1])
                  if isinstance(rotation, tuple)
                  else rotation
              )
              * np.pi
              / 180
              for rotation in [rotationX, rotationY, rotationZ]
          ]
          current_background_filepath_or_array = backgrounds[
              background_index
          ]
          current_background = (
              tools.read(current_background_filepath_or_array)
              if isinstance(current_background_filepath_or_array, str)
              else current_background_filepath_or_array
          )
          if augmenter is not None:
              current_background = augmenter(
                  images=[current_background]
              )[0]
          if (
              current_background.shape[0] != height
              or current_background.shape[1] != width
          ):
              current_background = tools.fit(
                  current_background,
                  width=width,
                  height=height,
                  mode=background_crop_mode,
              )
          permitted_contour, isDark = get_maximum_uniform_contour(
              image=current_background,
              fontsize=current_font_size,
              margin=margin,
          )
          if permitted_contour is None:
              # We can't draw on this background. Boo!
              continue
          random_color_values = np.random.randint(
              low=0, high=50, size=3
          )
          text_color = (
              tuple(np.array([255, 255, 255]) - random_color_values)
              if isDark
              else tuple(random_color_values)
          )
          text_image, lines = draw_text_image(
              text=text,
              width=width,
              height=height,
              fontsize=current_font_size,
              fonts=current_font_groups,
              thetaX=current_rotation_X,
              thetaY=current_rotation_Y,
              thetaZ=current_rotation_Z,
              use_ligatures=use_ligatures,
              permitted_contour=permitted_contour,
              color=text_color,
              draw_contour=draw_contour_text,
          )
          alpha = text_image[..., -1:].astype("float32") / 255
          image = (
              alpha * text_image[..., :3]
              + (1 - alpha) * current_background
          ).astype("uint8")
          if draw_contour:
              image = cv2.drawContours(
                  image,
                  contours=[
                      permitted_contour.reshape((-1, 1, 2)).astype(
                          "int32"
                      )
                  ],
                  contourIdx=0,
                  color=(255, 0, 0),
                  thickness=int(width / 100),
              )
          yield image, lines
  
imports: import os
  import math
  import glob
  import typing
  import random
  import zipfile
  import string
  import itertools
  import cv2
  import tqdm
  import numpy
  import essential_generators
  import PIL.Image
  import PIL.ImageDraw
  import PIL.ImageFont
  import fontTools.ttLib
  from .None import tools
label_desc: Use image node_id 13 for calling a global function with example usage: get_image_generator(height, width, font_groups, text_generator, font_size, backgrounds, background_crop_mode, rotationX, rotationY, rotationZ, margin, use_ligatures, augmenter, draw_contour, draw_contour_text) without return types