code: def elastic_transform(
      x: np.ndarray,
      mult_dxdy: float,
      sigma: float,
      rnd_rng: float,
      xrange: tuple = None,
  ) -> np.ndarray:
      """
      Apply elastic transformation to instance.
  
      Parameters
      ----------
      x
          Instance to be perturbed.
      mult_dxdy
          Multiplier for the Gaussian noise in x and y directions.
      sigma
          Standard deviation determining the strength of the Gaussian perturbation.
      rnd_rng
          Range for random uniform noise.
      xrange
          Tuple with min and max data range.
  
      Returns
      -------
      Perturbed instance.
      """
      x, scale_back = scale_minmax(x, xrange)
      shape = x.shape
      shape_size = shape[:2]
  
      mult_dxdy *= shape[0]
      sigma *= shape[0]
      rnd_rng *= shape[0]
  
      # random affine
      center_square = np.asarray(shape_size, dtype=np.float32) // 2
      square_size = min(shape_size) // 3
      pts1 = np.asarray(
          [
              center_square + square_size,
              [
                  center_square[0] + square_size,
                  center_square[1] - square_size,
              ],
              center_square - square_size,
          ],
          dtype=np.float32,
      )
      pts2 = pts1 + np.random.uniform(
          -rnd_rng, rnd_rng, size=pts1.shape
      ).astype(np.float32)
      M = cv2.getAffineTransform(pts1, pts2)
      image = cv2.warpAffine(
          x, M, shape_size[::-1], borderMode=cv2.BORDER_REFLECT_101
      )
      dx = (
          gaussian(
              np.random.uniform(-1, 1, size=shape_size),
              sigma,
              mode="reflect",
              truncate=3,
          )
          * mult_dxdy
      ).astype(np.float32)
      dy = (
          gaussian(
              np.random.uniform(-1, 1, size=shape_size),
              sigma,
              mode="reflect",
              truncate=3,
          )
          * mult_dxdy
      ).astype(np.float32)
      dx, dy = dx[..., np.newaxis], dy[..., np.newaxis]
      x, y, z = np.meshgrid(
          np.arange(shape[1]), np.arange(shape[0]), np.arange(shape[2])
      )
      indices = (
          np.reshape(y + dy, (-1, 1)),
          np.reshape(x + dx, (-1, 1)),
          np.reshape(z, (-1, 1)),
      )
      x_et = map_coordinates(
          image, indices, order=1, mode="reflect"
      ).reshape(shape)
      if scale_back:
          x_et = x_et * (xrange[1] - xrange[0]) + xrange[0]
      if isinstance(xrange, tuple):
          return np.clip(x_et, xrange[0], xrange[1])
      else:
          return x_et
  
imports: import random
  from io import BytesIO
  from typing import List, Tuple, Union
  import cv2
  import numpy
  import skimage
  from alibi_detect.utils.data import Bunch
  from alibi_detect.utils.discretizer import Discretizer
  from alibi_detect.utils.distance import abdm, multidim_scaling
  from alibi_detect.utils.mapping import ohe2ord
  from PIL import Image
  from scipy.ndimage import zoom
  from scipy.ndimage.interpolation import map_coordinates
  from skimage.filters import gaussian
label_desc: Use image node_id 23 for calling a global function with example usage: elastic_transform(x, mult_dxdy, sigma, rnd_rng, xrange) and returns: np, x_et