code: def _rand_perlin_2d_np(
      shape, res, fade=lambda t: 6 * t**5 - 15 * t**4 + 10 * t**3
  ):
      """Generate a random image containing Perlin noise. Numpy version."""
      delta = (res[0] / shape[0], res[1] / shape[1])
      d = (shape[0] // res[0], shape[1] // res[1])
      grid = (
          np.mgrid[
              0 : res[0] : delta[0], 0 : res[1] : delta[1]
          ].transpose(1, 2, 0)
          % 1
      )
  
      angles = 2 * math.pi * np.random.rand(res[0] + 1, res[1] + 1)
      gradients = np.stack((np.cos(angles), np.sin(angles)), axis=-1)
  
      def tile_grads(slice1, slice2):
          return np.repeat(
              np.repeat(
                  gradients[
                      slice1[0] : slice1[1], slice2[0] : slice2[1]
                  ],
                  d[0],
                  axis=0,
              ),
              d[1],
              axis=1,
          )
  
      def dot(grad, shift):
          return (
              np.stack(
                  (
                      grid[: shape[0], : shape[1], 0] + shift[0],
                      grid[: shape[0], : shape[1], 1] + shift[1],
                  ),
                  axis=-1,
              )
              * grad[: shape[0], : shape[1]]
          ).sum(axis=-1)
  
      n00 = dot(tile_grads([0, -1], [0, -1]), [0, 0])
      n10 = dot(tile_grads([1, None], [0, -1]), [-1, 0])
      n01 = dot(tile_grads([0, -1], [1, None]), [0, -1])
      n11 = dot(tile_grads([1, None], [1, None]), [-1, -1])
      t = fade(grid[: shape[0], : shape[1]])
      return math.sqrt(2) * lerp_np(
          lerp_np(n00, n10, t[..., 0]),
          lerp_np(n01, n11, t[..., 0]),
          t[..., 1],
      )
  
file_path: anomalib/src/anomalib/data/utils/generators/perlin.py
imports: from __future__ import annotations
  import math
  import numpy
  import torch
  from torch import Tensor
label_desc: Use image node_id 5 for calling a global function with example usage: _rand_perlin_2d_np(shape, res, fade) and returns: unknown, np, unknown