class_docstr: Implementation of the DPatch attack.
  
  | Paper link: https://arxiv.org/abs/1806.02299v4
class_docstr_tok: ["Implementation","of","the","DPatch","attack",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1806.02299v4"]
docstr: Generate DPatch.
  
  :param x: Sample images.
  :param y: True labels of type `List[Dict[np.ndarray]]` for untargeted attack, one dictionary per input image.
            The keys and values of the dictionary are:
  
            - boxes [N, 4]: the boxes in [x1, y1, x2, y2] format, with 0 <= x1 < x2 <= W and 0 <= y1 < y2 <= H.
            - labels [N]: the labels for each image
            - scores [N]: the scores or each prediction.
  :param target_label: The target label of the DPatch attack.
  :param mask: An 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`
  :return: Adversarial patch.
docstr_tok: ["Generate","DPatch",".",":","param","x",":","Sample","images",".",":","param","y",":","True","labels","of","type","`","List","[","Dict","[","np.ndarray","]","]","`","for","untargeted","attack",",","one","dictionary","per","input","image",".","The","keys","and","values","of","the","dictionary","are",":","-","boxes","[","N",",","4","]",":","the","boxes","in","[","x1",",","y1",",","x2",",","y2","]","format",",","with","0","<","=","x1","<","x2","<","=","W","and","0","<","=","y1","<","y2","<","=","H.","-","labels","[","N","]",":","the","labels","for","each","image","-","scores","[","N","]",":","the","scores","or","each","prediction",".",":","param","target_label",":","The","target","label","of","the","DPatch","attack",".",":","param","mask",":","An","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","`",":","return",":","Adversarial","patch","."]
code: def generate(  # pylint: disable=W0221
      self,
      x: np.ndarray,
      y: Optional[np.ndarray] = None,
      target_label: Optional[Union[int, List[int], np.ndarray]] = None,
      **kwargs,
  ) -> np.ndarray:
      """
      Generate DPatch.
  
      :param x: Sample images.
      :param y: True labels of type `List[Dict[np.ndarray]]` for untargeted attack, one dictionary per input image.
                The keys and values of the dictionary are:
  
                - boxes [N, 4]: the boxes in [x1, y1, x2, y2] format, with 0 <= x1 < x2 <= W and 0 <= y1 < y2 <= H.
                - labels [N]: the labels for each image
                - scores [N]: the scores or each prediction.
      :param target_label: The target label of the DPatch attack.
      :param mask: An 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`
      :return: Adversarial patch.
      """
      mask = kwargs.get("mask")
      if mask is not None:
          mask = mask.copy()
      if mask is not None and (  # pragma: no cover
          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."
          )
  
      channel_index = 1 if self.estimator.channels_first else x.ndim - 1
      if x.shape[channel_index] != self.patch_shape[channel_index - 1]:
          raise ValueError(
              "The color channel index of the images and the patch have to be identical."
          )
      if x.ndim != 4:  # pragma: no cover
          raise ValueError(
              "The adversarial patch can only be applied to images."
          )
      if target_label is not None:
          if isinstance(target_label, int):
              self.target_label = [target_label] * x.shape[0]
          elif isinstance(target_label, np.ndarray):
              if target_label.shape not in (
                  (x.shape[0], 1),
                  (x.shape[0],),
              ):  # pragma: no cover
                  raise ValueError(
                      "The target_label has to be a 1-dimensional array."
                  )
              self.target_label = target_label.tolist()
          else:
              if not len(target_label) == x.shape[0] or not isinstance(
                  target_label, list
              ):  # pragma: no cover
                  raise ValueError(
                      "The target_label as list of integers needs to of length number of images in `x`."
                  )
              self.target_label = target_label
  
      patched_images, transforms = self._augment_images_with_patch(
          x,
          self._patch,
          random_location=True,
          channels_first=self.estimator.channels_first,
          mask=mask,
          transforms=None,
      )
      patch_target: List[Dict[str, np.ndarray]] = []
  
      if self.target_label and y is None:
          for i_image in range(patched_images.shape[0]):
              if isinstance(self.target_label, int):
                  t_l = self.target_label
              else:
                  t_l = self.target_label[i_image]
  
              i_x_1 = transforms[i_image]["i_x_1"]
              i_x_2 = transforms[i_image]["i_x_2"]
              i_y_1 = transforms[i_image]["i_y_1"]
              i_y_2 = transforms[i_image]["i_y_2"]
  
              target_dict = {}
              target_dict["boxes"] = np.asarray(
                  [[i_x_1, i_y_1, i_x_2, i_y_2]]
              )
              target_dict["labels"] = np.asarray(
                  [
                      t_l,
                  ]
              )
              target_dict["scores"] = np.asarray(
                  [
                      1.0,
                  ]
              )
  
              patch_target.append(target_dict)
  
      else:
          predictions = (
              y
              if y is not None
              else self.estimator.predict(
                  x=patched_images, standardise_output=True
              )
          )
  
          for i_image in range(patched_images.shape[0]):
              target_dict = {}
              target_dict["boxes"] = predictions[i_image]["boxes"]
              target_dict["labels"] = predictions[i_image]["labels"]
              target_dict["scores"] = predictions[i_image]["scores"]
  
              patch_target.append(target_dict)
  
      for i_step in trange(
          self.max_iter,
          desc="DPatch iteration",
          disable=not self.verbose,
      ):
          if i_step == 0 or (i_step + 1) % 100 == 0:
              logger.info("Training Step: %i", i_step + 1)
  
          num_batches = 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 = min(
                  (i_batch + 1) * self.batch_size,
                  patched_images.shape[0],
              )
  
              gradients = self.estimator.loss_gradient(
                  x=patched_images[i_batch_start:i_batch_end],
                  y=patch_target[i_batch_start:i_batch_end],
                  standardise_output=True,
              )
  
              for i_image in range(gradients.shape[0]):
                  i_x_1 = transforms[i_batch_start + i_image]["i_x_1"]
                  i_x_2 = transforms[i_batch_start + i_image]["i_x_2"]
                  i_y_1 = transforms[i_batch_start + i_image]["i_y_1"]
                  i_y_2 = transforms[i_batch_start + i_image]["i_y_2"]
  
                  if self.estimator.channels_first:
                      patch_gradients_i = gradients[
                          i_image, :, i_x_1:i_x_2, i_y_1:i_y_2
                      ]
                  else:
                      patch_gradients_i = gradients[
                          i_image, i_x_1:i_x_2, i_y_1:i_y_2, :
                      ]
  
                  patch_gradients = patch_gradients + patch_gradients_i
  
          if self.target_label:
              self._patch = (
                  self._patch
                  - np.sign(patch_gradients) * self.learning_rate
              )
          else:
              self._patch = (
                  self._patch
                  + np.sign(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],
              )
  
          patched_images, _ = self._augment_images_with_patch(
              x,
              self._patch,
              random_location=False,
              channels_first=self.estimator.channels_first,
              mask=None,
              transforms=transforms,
          )
  
      return self._patch
  
file_path: adversarial-robustness-toolbox/art/attacks/evasion/dpatch.py
imports: import logging
  import math
  import random
  from typing import Dict, List, Optional, Tuple, Union, TYPE_CHECKING
  import numpy
  from tqdm.auto import trange
  from art.attacks.attack import EvasionAttack
  from art.estimators.estimator import BaseEstimator, LossGradientsMixin
  from art.estimators.object_detection.object_detector import ObjectDetectorMixin
  from art import config
label_desc: Use image node_id 2 for calling the DPatch obj's underlying member method code with example usage: obj.generate(x, y, target_label) and returns: self