def random_patch_gaussian(image,
                          min_patch_size=1,
                          max_patch_size=250,
                          min_gaussian_stddev=0.0,
                          max_gaussian_stddev=1.0,
                          random_coef=0.0,
                          seed=None,
                          preprocess_vars_cache=None):
  """Randomly applies gaussian noise to a random patch on the image.

  The gaussian noise is applied to the image with values scaled to the range
  [0.0, 1.0]. The result of applying gaussian noise to the scaled image is
  clipped to be within the range [0.0, 1.0], equivalent to the range
  [0.0, 255.0] after rescaling the image back.

  See "Improving Robustness Without Sacrificing Accuracy with Patch Gaussian
  Augmentation " by Lopes et al., 2019, for further details.
  https://arxiv.org/abs/1906.02611

  Args:
    image: Rank 3 float32 tensor with shape [height, width, channels] and
      values in the range [0.0, 255.0].
    min_patch_size: Integer. An inclusive lower bound for the patch size.
    max_patch_size:  Integer. An exclusive upper bound for the patch size.
    min_gaussian_stddev: Float. An inclusive lower bound for the standard
      deviation of the gaussian noise.
    max_gaussian_stddev: Float. An exclusive upper bound for the standard
      deviation of the gaussian noise.
    random_coef: Float. Random coefficient that defines the chance of getting
      the original image. If random_coef is 0.0, we will always apply
      downscaling, and if it is 1.0, we will always get the original image.
    seed: (optional) Integer. Random seed.
    preprocess_vars_cache: (optional) PreprocessorCache object that records
      previously performed augmentations. Updated in-place. If this function is
      called multiple times with the same non-null cache, it will perform
      deterministically.

  Returns:
    Rank 3 float32 tensor with same shape as the input image and with gaussian
    noise applied within a random patch.

  Raises:
    ValueError: If min_patch_size is < 1.
  """
  if min_patch_size < 1:
    raise ValueError('Minimum patch size must be >= 1.')

  get_or_create_rand_vars_fn = functools.partial(
      _get_or_create_preprocess_rand_vars,
      function_id=preprocessor_cache.PreprocessorCache.PATCH_GAUSSIAN,
      preprocess_vars_cache=preprocess_vars_cache)

  def _apply_patch_gaussian(image):
    """Applies a patch gaussian with random size, location, and stddev."""
    patch_size = get_or_create_rand_vars_fn(
        functools.partial(
            tf.random_uniform, [],
            minval=min_patch_size,
            maxval=max_patch_size,
            dtype=tf.int32,
            seed=seed),
        key='patch_size')
    gaussian_stddev = get_or_create_rand_vars_fn(
        functools.partial(
            tf.random_uniform, [],
            minval=min_gaussian_stddev,
            maxval=max_gaussian_stddev,
            dtype=tf.float32,
            seed=seed),
        key='gaussian_stddev')

    image_shape = tf.shape(image)
    y = get_or_create_rand_vars_fn(
        functools.partial(
            tf.random_uniform, [],
            minval=0,
            maxval=image_shape[0],
            dtype=tf.int32,
            seed=seed),
        key='y')
    x = get_or_create_rand_vars_fn(
        functools.partial(
            tf.random_uniform, [],
            minval=0,
            maxval=image_shape[1],
            dtype=tf.int32,
            seed=seed),
        key='x')
    gaussian = get_or_create_rand_vars_fn(
        functools.partial(
            tf.random.normal,
            image_shape,
            stddev=gaussian_stddev,
            dtype=tf.float32,
            seed=seed),
        key='gaussian')

    scaled_image = image / 255.0
    image_plus_gaussian = tf.clip_by_value(scaled_image + gaussian, 0.0, 1.0)
    patch_mask = patch_ops.get_patch_mask(y, x, patch_size, image_shape)
    patch_mask = tf.expand_dims(patch_mask, -1)
    patch_mask = tf.tile(patch_mask, [1, 1, image_shape[2]])
    patched_image = tf.where(patch_mask, image_plus_gaussian, scaled_image)
    return patched_image * 255.0

  with tf.name_scope('RandomPatchGaussian', values=[image]):
    image = tf.cast(image, tf.float32)
    patch_gaussian_random = get_or_create_rand_vars_fn(
        functools.partial(tf.random_uniform, [], seed=seed))
    do_patch_gaussian = tf.greater_equal(patch_gaussian_random, random_coef)
    image = tf.cond(do_patch_gaussian,
                    lambda: _apply_patch_gaussian(image),
                    lambda: image)
  return image
Randomly applies gaussian noise to a random patch on the image.

  The gaussian noise is applied to the image with values scaled to the range
  [0.0, 1.0]. The result of applying gaussian noise to the scaled image is
  clipped to be within the range [0.0, 1.0], equivalent to the range
  [0.0, 255.0] after rescaling the image back.

  See "Improving Robustness Without Sacrificing Accuracy with Patch Gaussian
  Augmentation " by Lopes et al., 2019, for further details.
  https://arxiv.org/abs/1906.02611

  Args:
    image: Rank 3 float32 tensor with shape [height, width, channels] and
      values in the range [0.0, 255.0].
    min_patch_size: Integer. An inclusive lower bound for the patch size.
    max_patch_size:  Integer. An exclusive upper bound for the patch size.
    min_gaussian_stddev: Float. An inclusive lower bound for the standard
      deviation of the gaussian noise.
    max_gaussian_stddev: Float. An exclusive upper bound for the standard
      deviation of the gaussian noise.
    random_coef: Float. Random coefficient that defines the chance of getting
      the original image. If random_coef is 0.0, we will always apply
      downscaling, and if it is 1.0, we will always get the original image.
    seed: (optional) Integer. Random seed.
    preprocess_vars_cache: (optional) PreprocessorCache object that records
      previously performed augmentations. Updated in-place. If this function is
      called multiple times with the same non-null cache, it will perform
      deterministically.

  Returns:
    Rank 3 float32 tensor with same shape as the input image and with gaussian
    noise applied within a random patch.

  Raises:
    ValueError: If min_patch_size is < 1.
  
inference_api/src/main/object_detection/core/preprocessor.py