class_docstr: Implementation of the adversarial patch attack for square and rectangular images and videos in Numpy.
  
  | Paper link: https://arxiv.org/abs/1712.09665
class_docstr_tok: ["Implementation","of","the","adversarial","patch","attack","for","square","and","rectangular","images","and","videos","in","Numpy",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1712.09665"]
docstr: Generate an adversarial patch and return the patch and its mask in arrays.
  
  :param x: An array with the original input images of shape NHWC or NCHW or input videos of shape NFHWC or NFCHW.
  :param y: An array with the original true labels.
  :param mask: A boolean array of shape equal to the shape of a single samples (1, H, W) or the shape of `x`
               (N, H, W) without their channel dimensions. Any features for which the mask is True can be the
               center location of the patch during sampling.
  :type mask: `np.ndarray`
  :param reset_patch: If `True` reset patch to initial values of mean of minimal and maximal clip value, else if
                      `False` (default) restart from previous patch values created by previous call to `generate`
                      or mean of minimal and maximal clip value if first call to `generate`.
  :type reset_patch: bool
  :return: An array with adversarial patch and an array of the patch mask.
docstr_tok: ["Generate","an","adversarial","patch","and","return","the","patch","and","its","mask","in","arrays",".",":","param","x",":","An","array","with","the","original","input","images","of","shape","NHWC","or","NCHW","or","input","videos","of","shape","NFHWC","or","NFCHW",".",":","param","y",":","An","array","with","the","original","true","labels",".",":","param","mask",":","A","boolean","array","of","shape","equal","to","the","shape","of","a","single","samples","(","1",",","H",",","W",")","or","the","shape","of","`","x","`","(","N",",","H",",","W",")","without","their","channel","dimensions",".","Any","features","for","which","the","mask","is","True","can","be","the","center","location","of","the","patch","during","sampling",".",":","type","mask",":","`","np.ndarray","`",":","param","reset_patch",":","If","`","True","`","reset","patch","to","initial","values","of","mean","of","minimal","and","maximal","clip","value",",","else","if","`","False","`","(","default",")","restart","from","previous","patch","values","created","by","previous","call","to","`","generate","`","or","mean","of","minimal","and","maximal","clip","value","if","first","call","to","`","generate","`",".",":","type","reset_patch",":","bool",":","return",":","An","array","with","adversarial","patch","and","an","array","of","the","patch","mask","."]
code: def generate(  # type: ignore
      self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs
  ) -> Tuple[np.ndarray, np.ndarray]:
      """
      Generate an adversarial patch and return the patch and its mask in arrays.
  
      :param x: An array with the original input images of shape NHWC or NCHW or input videos of shape NFHWC or NFCHW.
      :param y: An array with the original true labels.
      :param mask: A boolean array of shape equal to the shape of a single samples (1, H, W) or the shape of `x`
                   (N, H, W) without their channel dimensions. Any features for which the mask is True can be the
                   center location of the patch during sampling.
      :type mask: `np.ndarray`
      :param reset_patch: If `True` reset patch to initial values of mean of minimal and maximal clip value, else if
                          `False` (default) restart from previous patch values created by previous call to `generate`
                          or mean of minimal and maximal clip value if first call to `generate`.
      :type reset_patch: bool
      :return: An array with adversarial patch and an array of the patch mask.
      """
      logger.info("Creating adversarial patch.")
  
      test_input_shape = list(self.estimator.input_shape)
  
      for i, size in enumerate(self.estimator.input_shape):
          if size is None or size != x.shape[i + 1]:
              test_input_shape[i] = x.shape[i + 1]
  
      self.input_shape = tuple(test_input_shape)
  
      mask = kwargs.get("mask")
      if mask is not None:
          mask = mask.copy()
      if mask is not None and (
          (mask.dtype != bool)
          or not (mask.shape[0] == 1 or mask.shape[0] == x.shape[0])
          or not (
              (
                  mask.shape[1] == x.shape[1]
                  and mask.shape[2] == x.shape[2]
              )
              or (
                  mask.shape[1] == x.shape[2]
                  and mask.shape[2] == x.shape[3]
              )
          )
      ):
          raise ValueError(
              "The shape of `mask` has to be equal to the shape of a single samples (1, H, W) or the"
              "shape of `x` (N, H, W) without their channel dimensions."
          )
  
      if len(x.shape) == 2:
          raise ValueError(
              "Feature vectors detected. The adversarial patch can only be applied to data with spatial "
              "dimensions."
          )
  
      if kwargs.get("reset_patch"):
          self.reset_patch(self.mean_value)
  
      if y is not None:
          y_target = check_and_transform_label_format(
              labels=y, nb_classes=self.estimator.nb_classes
          )
      else:
          raise ValueError("Labels `y` cannot be `None`.")
  
      for _ in trange(
          self.max_iter,
          desc="Adversarial Patch Numpy",
          disable=not self.verbose,
      ):
          (
              patched_images,
              patch_mask_transformed,
              transforms,
          ) = self._augment_images_with_random_patch(
              x, self.patch, mask=mask
          )
  
          num_batches = int(math.ceil(x.shape[0] / self.batch_size))
          patch_gradients = np.zeros_like(self.patch)
  
          for i_batch in range(num_batches):
              i_batch_start = i_batch * self.batch_size
              i_batch_end = (i_batch + 1) * self.batch_size
  
              gradients = self.estimator.loss_gradient(
                  patched_images[i_batch_start:i_batch_end],
                  y_target[i_batch_start:i_batch_end],
              )
  
              for i_image in range(gradients.shape[0]):
                  patch_gradients_i = self._reverse_transformation(
                      gradients[i_image, :, :, :],
                      patch_mask_transformed[i_image, :, :, :],
                      transforms[i_image],
                  )
                  if self.nb_dims == 4:
                      patch_gradients_i = np.mean(
                          patch_gradients_i, axis=0
                      )
                  patch_gradients += patch_gradients_i
  
          # patch_gradients = patch_gradients / (num_batches * self.batch_size)
          self.patch -= patch_gradients * self.learning_rate
          if self.estimator.clip_values is not None:
              self.patch = np.clip(
                  self.patch,
                  a_min=self.estimator.clip_values[0],
                  a_max=self.estimator.clip_values[1],
              )
          else:
              raise ValueError(
                  "Clip values of estimator cannot be None."
              )
  
      return self.patch, self._get_circular_patch_mask()
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  import math
  from typing import Optional, Union, Tuple, TYPE_CHECKING
  import random
  import numpy
  from scipy.ndimage import rotate, shift, zoom
  from tqdm.auto import trange
  from art.attacks.attack import EvasionAttack
  from art.attacks.evasion.adversarial_patch.utils import insert_transformed_patch
  from art.estimators.estimator import BaseEstimator, NeuralNetworkMixin
  from art.estimators.classification.classifier import ClassifierMixin
  from art.utils import check_and_transform_label_format
label_desc: Use image node_id 2 for calling the AdversarialPatchNumpy obj's underlying member method code with example usage: obj.generate(x, y) and returns: self,  self