class_docstr: Class that generates noisy augmentations of input images.
  
  Args:
      anomaly_source_path (str | None): Path to a folder of images that will be used as source of the anomalous
      noise. If not specified, random noise will be used instead.
      p_anomalous (float): Probability that the anomalous perturbation will be applied to a given image.
      beta (float): Parameter that determines the opacity of the noise mask.
class_docstr_tok: ["Class","that","generates","noisy","augmentations","of","input","images",".","Args",":","anomaly_source_path","(","str","|","None",")",":","Path","to","a","folder","of","images","that","will","be","used","as","source","of","the","anomalous","noise",".","If","not","specified",",","random","noise","will","be","used","instead",".","p_anomalous","(","float",")",":","Probability","that","the","anomalous","perturbation","will","be","applied","to","a","given","image",".","beta","(","float",")",":","Parameter","that","determines","the","opacity","of","the","noise","mask","."]
docstr: Generate an image containing a random anomalous perturbation using a source image.
  
  Args:
      height (int): height of the generated image.
      width: (int): width of the generated image.
      anomaly_source_path (str | None): Path to an image file. If not provided, random noise will be used
      instead.
  
  Returns:
      Image containing a random anomalous perturbation, and the corresponding ground truth anomaly mask.
docstr_tok: ["Generate","an","image","containing","a","random","anomalous","perturbation","using","a","source","image",".","Args",":","height","(","int",")",":","height","of","the","generated","image",".","width",":","(","int",")",":","width","of","the","generated","image",".","anomaly_source_path","(","str","|","None",")",":","Path","to","an","image","file",".","If","not","provided",",","random","noise","will","be","used","instead",".","Returns",":","Image","containing","a","random","anomalous","perturbation",",","and","the","corresponding","ground","truth","anomaly","mask","."]
code: def generate_perturbation(
      self, height: int, width: int, anomaly_source_path: str | None
  ) -> tuple[np.ndarray, np.ndarray]:
      """Generate an image containing a random anomalous perturbation using a source image.
  
      Args:
          height (int): height of the generated image.
          width: (int): width of the generated image.
          anomaly_source_path (str | None): Path to an image file. If not provided, random noise will be used
          instead.
  
      Returns:
          Image containing a random anomalous perturbation, and the corresponding ground truth anomaly mask.
      """
      # Generate random perlin noise
      perlin_scale = 6
      min_perlin_scale = 0
  
      perlin_scalex = 2 ** random.randint(
          min_perlin_scale, perlin_scale
      )  # nosec: B311
      perlin_scaley = 2 ** random.randint(
          min_perlin_scale, perlin_scale
      )  # nosec: B311
  
      perlin_noise = random_2d_perlin(
          (nextpow2(height), nextpow2(width)),
          (perlin_scalex, perlin_scaley),
      )[:height, :width]
      perlin_noise = self.rot(image=perlin_noise)
  
      # Create mask from perlin noise
      mask = np.where(
          perlin_noise > 0.5,
          np.ones_like(perlin_noise),
          np.zeros_like(perlin_noise),
      )
      mask = np.expand_dims(mask, axis=2).astype(np.float32)
  
      # Load anomaly source image
      if anomaly_source_path:
          anomaly_source_img = cv2.imread(anomaly_source_path)
          anomaly_source_img = cv2.resize(
              anomaly_source_img, dsize=(width, height)
          )
      else:  # if no anomaly source is specified, we use the perlin noise as anomalous source
          anomaly_source_img = np.expand_dims(perlin_noise, 2).repeat(
              3, 2
          )
          anomaly_source_img = (anomaly_source_img * 255).astype(
              np.uint8
          )
  
      # Augment anomaly source image
      aug = self.rand_augmenter()
      anomaly_img_augmented = aug(image=anomaly_source_img)
  
      # Create anomalous perturbation that we will apply to the image
      perturbation = (
          anomaly_img_augmented.astype(np.float32) * mask / 255.0
      )
  
      return perturbation, mask
  
file_path: anomalib/src/anomalib/data/utils/augmenter.py
imports: from __future__ import annotations
  import glob
  import math
  import random
  import cv2
  import imgaug.augmenters
  import numpy
  import torch
  from torch import Tensor
  from torchvision.datasets.folder import IMG_EXTENSIONS
  from anomalib.data.utils.generators.perlin import random_2d_perlin
label_desc: Use image node_id 3 for calling the Augmenter obj's underlying member method code with example usage: obj.generate_perturbation(height, width, anomaly_source_path) and returns: perturbation,  mask