code: def create_shadow_mask(
      target_shape: Tuple[int, int],
      min_base_width=0.3,
      max_tip_width=0.5,
      max_tip_height=0.3,
  ) -> np.ndarray:
      """Creates a random shadow mask
  
      Args:
      ----
          target_shape: the target shape (H, W)
          min_base_width: the relative minimum shadow base width
          max_tip_width: the relative maximum shadow tip width
          max_tip_height: the relative maximum shadow tip height
  
      Returns:
      -------
          a numpy ndarray of shape (H, W, 1) with values in the range [0, 1]
      """
      # Default base is top
      _params = np.random.rand(6)
      base_width = min_base_width + (1 - min_base_width) * _params[0]
      base_center = base_width / 2 + (1 - base_width) * _params[1]
      # Ensure tip width is smaller for shadow consistency
      tip_width = min(
          _params[2] * base_width * target_shape[0] / target_shape[1],
          max_tip_width,
      )
      tip_center = tip_width / 2 + (1 - tip_width) * _params[3]
      tip_height = _params[4] * max_tip_height
      tip_mid = tip_height / 2 + (1 - tip_height) * _params[5]
      _order = tip_center < base_center
      contour: np.ndarray = np.array(
          [
              [base_center - base_width / 2, 0],
              [base_center + base_width / 2, 0],
              [
                  tip_center + tip_width / 2,
                  tip_mid + tip_height / 2
                  if _order
                  else tip_mid - tip_height / 2,
              ],
              [
                  tip_center - tip_width / 2,
                  tip_mid - tip_height / 2
                  if _order
                  else tip_mid + tip_height / 2,
              ],
          ],
          dtype=np.float32,
      )
  
      # Convert to absolute coords
      abs_contour: np.ndarray = (
          np.stack(
              (
                  contour[:, 0] * target_shape[1],
                  contour[:, 1] * target_shape[0],
              ),
              axis=-1,
          )
          .round()
          .astype(np.int32)
      )
  
      # Direction
      _params = np.random.rand(1)
      rotated_contour = (
          rotate_abs_geoms(
              abs_contour[None, ...],
              360 * _params[0],
              target_shape,
              expand=False,
          )[0]
          .round()
          .astype(np.int32)
      )
      # Check approx quadrant
      quad_idx = int(_params[0] / 0.25)
      # Top-bot
      if quad_idx % 2 == 0:
          intensity_mask = np.repeat(
              np.arange(target_shape[0])[:, None],
              target_shape[1],
              axis=1,
          ) / (target_shape[0] - 1)
          if quad_idx == 0:
              intensity_mask = 1 - intensity_mask
      # Left - right
      else:
          intensity_mask = np.repeat(
              np.arange(target_shape[1])[None, :],
              target_shape[0],
              axis=0,
          ) / (target_shape[1] - 1)
          if quad_idx == 1:
              intensity_mask = 1 - intensity_mask
  
      # Expand base
      final_contour = rotated_contour.copy()
      final_contour[0] = expand_line(
          final_contour[[0, 3]], target_shape
      )
      final_contour[1] = expand_line(
          final_contour[[1, 2]], target_shape
      )
      # If both base are not on the same side, add a point
      if not np.any(final_contour[0] == final_contour[1]):
          corner_x = (
              0
              if max(final_contour[0, 0], final_contour[1, 0])
              < target_shape[1]
              else target_shape[1]
          )
          corner_y = (
              0
              if max(final_contour[0, 1], final_contour[1, 1])
              < target_shape[0]
              else target_shape[0]
          )
          corner: np.ndarray = np.array([corner_x, corner_y])
          final_contour = np.concatenate(
              (final_contour[:1], corner[None, ...], final_contour[1:]),
              axis=0,
          )
  
      # Direction & rotate
      mask: np.ndarray = np.zeros((*target_shape, 1), dtype=np.uint8)
      mask = cv2.fillPoly(
          mask, [final_contour], (255,), lineType=cv2.LINE_AA
      )[..., 0]
  
      return (mask / 255).astype(np.float32).clip(
          0, 1
      ) * intensity_mask.astype(np.float32)
  
imports: from typing import Tuple, Union
  import cv2
  import numpy
  from doctr.utils.geometry import rotate_abs_geoms
label_desc: Use image node_id 3 for calling a global function with example usage: create_shadow_mask(target_shape, min_base_width, max_tip_width, max_tip_height) and returns: unknown