class_docstr: Implementation of a particular variation of the DPatch attack.
  It follows Lee & Kolter (2019) in using sign gradients with expectations over transformations.
  The particular transformations supported in this implementation are cropping, rotations by multiples of 90 degrees,
  and changes in the brightness of the image.
  
  | Paper link (original DPatch): https://arxiv.org/abs/1806.02299v4
  | Paper link (physical-world patch from Lee & Kolter): https://arxiv.org/abs/1906.11897
class_docstr_tok: ["Implementation","of","a","particular","variation","of","the","DPatch","attack",".","It","follows","Lee","&","Kolter","(","2019",")","in","using","sign","gradients","with","expectations","over","transformations",".","The","particular","transformations","supported","in","this","implementation","are","cropping",",","rotations","by","multiples","of","90","degrees",",","and","changes","in","the","brightness","of","the","image",".","|","Paper","link","(","original","DPatch",")",":","https",":","\/\/arxiv.org\/abs\/1806.02299v4","|","Paper","link","(","physical-world","patch","from","Lee","&","Kolter",")",":","https",":","\/\/arxiv.org\/abs\/1906.11897"]
docstr: Generate RobustDPatch.
  
  :param x: Sample images.
  :param y: Target labels for object detector.
  :return: Adversarial patch.
docstr_tok: ["Generate","RobustDPatch",".",":","param","x",":","Sample","images",".",":","param","y",":","Target","labels","for","object","detector",".",":","return",":","Adversarial","patch","."]
code: def generate(  # type: ignore
      self,
      x: np.ndarray,
      y: Optional[List[Dict[str, np.ndarray]]] = None,
      **kwargs,
  ) -> np.ndarray:
      """
      Generate RobustDPatch.
  
      :param x: Sample images.
      :param y: Target labels for object detector.
      :return: Adversarial patch.
      """
      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 y is None and self.targeted:
          raise ValueError(
              "The targeted version of RobustDPatch attack requires target labels provided to `y`."
          )
      if y is not None and not self.targeted:
          raise ValueError(
              "The RobustDPatch attack does not use target labels."
          )
      if x.ndim != 4:  # pragma: no cover
          raise ValueError(
              "The adversarial patch can only be applied to images."
          )
  
      # Check whether patch fits into the cropped images:
      if self.estimator.channels_first:
          image_height, image_width = x.shape[2:4]
      else:
          image_height, image_width = x.shape[1:3]
  
      if (
          not self.estimator.native_label_is_pytorch_format
          and y is not None
      ):
          from art.estimators.object_detection.utils import (
              convert_tf_to_pt,
          )
  
          y = convert_tf_to_pt(y=y, height=x.shape[1], width=x.shape[2])
  
      if y is not None:
          for i_image in range(x.shape[0]):
              y_i = y[i_image]["boxes"]
              for i_box in range(y_i.shape[0]):
                  x_1, y_1, x_2, y_2 = y_i[i_box]
                  if (  # pragma: no cover
                      x_1 < self.crop_range[1]
                      or y_1 < self.crop_range[0]
                      or x_2 > image_width - self.crop_range[1] + 1
                      or y_2 > image_height - self.crop_range[0] + 1
                  ):
                      raise ValueError(
                          "Cropping is intersecting with at least one box, reduce `crop_range`."
                      )
  
      if (  # pragma: no cover
          self.patch_location[0] + self.patch_shape[0]
          > image_height - self.crop_range[0]
          or self.patch_location[1] + self.patch_shape[1]
          > image_width - self.crop_range[1]
      ):
          raise ValueError(
              "The patch (partially) lies outside the cropped image."
          )
  
      for i_step in trange(
          self.max_iter,
          desc="RobustDPatch 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_old = np.zeros_like(self._patch)
  
          for e_step in range(self.sample_size):
              if e_step == 0 or (e_step + 1) % 100 == 0:
                  logger.info("EOT Step: %i", e_step + 1)
  
              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, x.shape[0]
                  )
  
                  if y is None:
                      y_batch = y
                  else:
                      y_batch = y[i_batch_start:i_batch_end]
  
                  # Sample and apply the random transformations:
                  (
                      patched_images,
                      patch_target,
                      transforms,
                  ) = self._augment_images_with_patch(
                      x[i_batch_start:i_batch_end],
                      y_batch,
                      self._patch,
                      channels_first=self.estimator.channels_first,
                  )
  
                  gradients = self.estimator.loss_gradient(
                      x=patched_images,
                      y=patch_target,
                      standardise_output=True,
                  )
  
                  gradients = self._untransform_gradients(
                      gradients,
                      transforms,
                      channels_first=self.estimator.channels_first,
                  )
  
                  patch_gradients = patch_gradients_old + np.sum(
                      gradients, axis=0
                  )
                  logger.debug(
                      "Gradient percentage diff: %f)",
                      np.mean(
                          np.sign(patch_gradients)
                          != np.sign(patch_gradients_old)
                      ),
                  )
  
                  patch_gradients_old = patch_gradients
  
          # Write summary
          if self.summary_writer is not None:  # pragma: no cover
              x_patched, y_patched, _ = self._augment_images_with_patch(
                  x,
                  y,
                  self._patch,
                  channels_first=self.estimator.channels_first,
              )
  
              self.summary_writer.update(
                  batch_id=0,
                  global_step=i_step,
                  grad=np.expand_dims(patch_gradients, axis=0),
                  patch=self._patch,
                  estimator=self.estimator,
                  x=x_patched,
                  y=y_patched,
                  targeted=self.targeted,
              )
  
          self._patch = (
              self._patch
              + np.sign(patch_gradients)
              * (1 - 2 * int(self.targeted))
              * 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],
              )
  
      if self.summary_writer is not None:
          self.summary_writer.reset()
  
      return self._patch
  
file_path: adversarial-robustness-toolbox/art/attacks/evasion/dpatch_robust.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
  from art.summary_writer import SummaryWriter
label_desc: Use image node_id 2 for calling the RobustDPatch obj's underlying member method code with example usage: obj.generate(x, y) and returns: self