class_docstr: Implementation of the white-box PyTorch GRAPHITE attack from Feng et al. (2022). This is a physical attack
  that generates robust physical perturbations that can be applied as stickers.
  
  | Paper link: https://arxiv.org/abs/2002.07088
  | Original github link: https://github.com/ryan-feng/GRAPHITE
class_docstr_tok: ["Implementation","of","the","white-box","PyTorch","GRAPHITE","attack","from","Feng","et","al",".","(","2022",")",".","This","is","a","physical","attack","that","generates","robust","physical","perturbations","that","can","be","applied","as","stickers",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/2002.07088","|","Original","github","link",":","https",":","\/\/github.com\/ryan-feng\/GRAPHITE"]
docstr: Generate adversarial samples and return them in an array.
  
  :param x: An array with the original inputs to be attacked.
  :param y: Target values (class labels) one-hot-encoded of shape `(nb_samples, nb_classes)` or indices of shape
            (nb_samples,).
  :param mask: An array with a mask broadcastable to input `x` defining where to apply adversarial perturbations.
               Shape needs to be broadcastable to the shape of x and can also be of the same shape as `x`. Any
               features for which the mask is zero will not be adversarially perturbed.
  :param pts: Optional points to consider when cropping the perspective transform.
              An array of points in [x, y, scale] with shape [num points, 3, 1].
  :param obj_width: The estimated object width (inches) for perspective transform. 30 by default.
  :param focal: The estimated focal length (ft) for perspective transform. 3 by default.
  :return: An array holding the adversarial examples.
docstr_tok: ["Generate","adversarial","samples","and","return","them","in","an","array",".",":","param","x",":","An","array","with","the","original","inputs","to","be","attacked",".",":","param","y",":","Target","values","(","class","labels",")","one-hot-encoded","of","shape","`","(","nb_samples",",","nb_classes",")","`","or","indices","of","shape","(","nb_samples",",",")",".",":","param","mask",":","An","array","with","a","mask","broadcastable","to","input","`","x","`","defining","where","to","apply","adversarial","perturbations",".","Shape","needs","to","be","broadcastable","to","the","shape","of","x","and","can","also","be","of","the","same","shape","as","`","x","`",".","Any","features","for","which","the","mask","is","zero","will","not","be","adversarially","perturbed",".",":","param","pts",":","Optional","points","to","consider","when","cropping","the","perspective","transform",".","An","array","of","points","in","[","x",",","y",",","scale","]","with","shape","[","num","points",",","3",",","1","]",".",":","param","obj_width",":","The","estimated","object","width","(","inches",")","for","perspective","transform",".","30","by","default",".",":","param","focal",":","The","estimated","focal","length","(","ft",")","for","perspective","transform",".","3","by","default",".",":","return",":","An","array","holding","the","adversarial","examples","."]
code: def generate(
      self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs
  ) -> np.ndarray:
      """
      Generate adversarial samples and return them in an array.
  
      :param x: An array with the original inputs to be attacked.
      :param y: Target values (class labels) one-hot-encoded of shape `(nb_samples, nb_classes)` or indices of shape
                (nb_samples,).
      :param mask: An array with a mask broadcastable to input `x` defining where to apply adversarial perturbations.
                   Shape needs to be broadcastable to the shape of x and can also be of the same shape as `x`. Any
                   features for which the mask is zero will not be adversarially perturbed.
      :param pts: Optional points to consider when cropping the perspective transform.
                  An array of points in [x, y, scale] with shape [num points, 3, 1].
      :param obj_width: The estimated object width (inches) for perspective transform. 30 by default.
      :param focal: The estimated focal length (ft) for perspective transform. 3 by default.
      :return: An array holding the adversarial examples.
      """
      mask = kwargs.get("mask")
      obj_width = (
          kwargs.get("obj_width") if "obj_width" in kwargs else 30
      )
      focal = kwargs.get("focal") if "focal" in kwargs else 3
      pts = kwargs.get("pts") if "pts" in kwargs else None
  
      if y is None:
          raise ValueError("Target labels `y` need to be provided.")
  
      y = check_and_transform_label_format(y, self.estimator.nb_classes)
  
      if (
          self.estimator.nb_classes == 2 and y.shape[1] == 1
      ):  # pragma: no cover
          raise ValueError(
              "This attack has not yet been tested for binary classification with a single output classifier."
          )
  
      if not isinstance(obj_width, int) and not isinstance(
          obj_width, float
      ):
          raise ValueError("obj_width must be int or float")
      obj_width = float(obj_width)
  
      if not isinstance(focal, int) and not isinstance(focal, float):
          raise ValueError("focal must be int or float")
      focal = float(focal)
  
      # Check the mask
      if mask is not None:
          if len(mask.shape) == len(x.shape):
              mask = mask.astype(ART_NUMPY_DTYPE)
          else:
              mask = np.array(
                  [mask.astype(ART_NUMPY_DTYPE)] * x.shape[0]
              )
      else:
          mask = np.ones((x.shape))
  
      # Get clip_min and clip_max from the classifier or infer them from data
      if self.estimator.clip_values is not None:
          clip_min, clip_max = self.estimator.clip_values
      else:
          clip_min, clip_max = np.min(x), np.max(x)
  
      # Some initial setups
      x_adv = x.astype(ART_NUMPY_DTYPE)
  
      if not self.estimator.channels_first:
          x = np.transpose(x, (0, 3, 1, 2))
          x_adv = np.transpose(x_adv, (0, 3, 1, 2))
          mask = np.transpose(mask, (0, 3, 1, 2))
  
      y_pred = self.estimator.predict(
          np.transpose(
              convert_to_network(
                  np.transpose(x_adv[0], (1, 2, 0)),
                  self.net_size,
                  clip_min,
                  clip_max,
              )[np.newaxis, :, :, :],
              (0, 3, 1, 2),
          )
      )
      if is_probability(y_pred):
          self.use_logits = False
      else:
          self.use_logits = True
  
      # Generate the adversarial samples
      for i in range(x_adv.shape[0]):
          x_adv[i] = self._perturb(
              x=x_adv[i],
              y=y[i],
              mask=mask[i],
              obj_width=obj_width,
              focal=focal,
              clip_min=clip_min,
              clip_max=clip_max,
              pts=pts,
          )
  
      y = np.argmax(y, axis=1)
      y = to_categorical(y, self.estimator.nb_classes)  # type: ignore
  
      # COMPUTE SUCCESS RATE
      x_copy = np.zeros(
          (x.shape[0], self.net_size[1], self.net_size[0], x.shape[1])
      )
      x_adv_copy = np.zeros(
          (
              x_adv.shape[0],
              self.net_size[1],
              self.net_size[0],
              x_adv.shape[1],
          )
      )
      x_copy_trans = np.transpose(x, (0, 2, 3, 1))
      x_adv_copy_trans = np.transpose(x_adv, (0, 2, 3, 1))
      for i in range(x_copy.shape[0]):
          x_copy[i] = convert_to_network(
              x_copy_trans[i], self.net_size, clip_min, clip_max
          )
          x_adv_copy[i] = convert_to_network(
              x_adv_copy_trans[i], self.net_size, clip_min, clip_max
          )
  
      if self.estimator.channels_first:
          x_copy = np.transpose(x_copy, (0, 3, 1, 2))
          x_adv_copy = np.transpose(x_adv_copy, (0, 3, 1, 2))
  
      logger.info(
          "Success rate of GRAPHITE white-box attack: %.2f%%",
          100
          * compute_success(
              self.estimator,
              x_copy.astype(np.float32),
              y,
              x_adv_copy.astype(np.float32),
              self.targeted,
              batch_size=self.batch_size,
          ),
      )
  
      if not self.estimator.channels_first:
          x_adv = np.transpose(x_adv, (0, 2, 3, 1))
  
      return x_adv
  
file_path: adversarial-robustness-toolbox/art/attacks/evasion/graphite/graphite_whitebox_pytorch.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, Tuple, Union, TYPE_CHECKING, List
  import numpy
  from art.config import ART_NUMPY_DTYPE
  from art.attacks.attack import EvasionAttack
  from art.estimators.estimator import BaseEstimator
  from art.estimators.classification import ClassifierMixin
  from art.utils import compute_success, to_categorical, check_and_transform_label_format, is_probability
  from art.attacks.evasion.graphite.utils import convert_to_network, get_transform_params, transform_wb
label_desc: Use image node_id 2 for calling the GRAPHITEWhiteboxPyTorch obj's underlying member method code with example usage: obj.generate(x, y) and returns: x_adv