class_docstr: Implementation of the ShapeShifter attack. This is a robust physical adversarial attack on Faster R-CNN object
  detector and is developed in TensorFlow.
  
  | Paper link: https://arxiv.org/abs/1804.05810
class_docstr_tok: ["Implementation","of","the","ShapeShifter","attack",".","This","is","a","robust","physical","adversarial","attack","on","Faster","R-CNN","object","detector","and","is","developed","in","TensorFlow",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1804.05810"]
docstr: Build the TensorFlow graph for the attack.
  
  :param initial_shape: Image/texture shape.
  :param custom_loss: Custom loss function from users.
  :param rendering_function: A rendering function to use textures as input.
  :return: A tuple of tensors.
docstr_tok: ["Build","the","TensorFlow","graph","for","the","attack",".",":","param","initial_shape",":","Image\/texture","shape",".",":","param","custom_loss",":","Custom","loss","function","from","users",".",":","param","rendering_function",":","A","rendering","function","to","use","textures","as","input",".",":","return",":","A","tuple","of","tensors","."]
code: def _build_graph(
      self,
      initial_shape: Tuple[int, ...],
      custom_loss: Optional["Tensor"] = None,
      rendering_function: Optional["Callable"] = None,
  ) -> Tuple["Tensor", ...]:
      """
      Build the TensorFlow graph for the attack.
  
      :param initial_shape: Image/texture shape.
      :param custom_loss: Custom loss function from users.
      :param rendering_function: A rendering function to use textures as input.
      :return: A tuple of tensors.
      """
      import tensorflow as tf
  
      # Create a placeholder to pass input image/texture
      initial_input = tf.placeholder(
          dtype=tf.float32, shape=initial_shape, name="initial_input"
      )
  
      # Create adversarial image
      project_texture_op = None
  
      if self.texture_as_input:
          # Create a placeholder to pass input texture mask
          mask_input = tf.placeholder(
              dtype=tf.float32, shape=initial_shape, name="mask_input"
          )
  
          # Create texture variable
          if self.use_spectral:
              initial_value = np.zeros(
                  (
                      2,
                      initial_shape[0],
                      initial_shape[3],
                      initial_shape[1],
                      int(np.ceil(initial_shape[2] / 2) + 1),
                  )
              )
  
              current_texture_variable = tf.Variable(
                  initial_value=initial_value,
                  dtype=tf.float32,
                  name="current_texture_variable",
              )
  
              current_texture = current_texture_variable
              current_texture = tf.complex(
                  current_texture[0], current_texture[1]
              )
              current_texture = tf.map_fn(
                  tf.spectral.irfft2d, current_texture, dtype=tf.float32
              )
              current_texture = tf.transpose(
                  current_texture, (0, 2, 3, 1)
              )
  
          else:
              initial_value = np.zeros(
                  (
                      initial_shape[0],
                      initial_shape[1],
                      initial_shape[2],
                      initial_shape[3],
                  )
              )
  
              current_texture_variable = tf.Variable(
                  initial_value=initial_value,
                  dtype=tf.float32,
                  name="current_texture_variable",
              )
  
              current_texture = current_texture_variable
  
          # Invert texture for projection
          project_texture = (
              initial_input * (1.0 - mask_input)
              + current_texture * mask_input
          )
  
          if self.soft_clip:
              project_texture = tf.nn.sigmoid(project_texture)
          else:
              project_texture = tf.clip_by_value(
                  project_texture, 0.0, 1.0
              )
  
          if self.use_spectral:
              project_texture = tf.transpose(
                  project_texture, (0, 3, 1, 2)
              )
              project_texture = tf.map_fn(
                  tf.spectral.rfft2d,
                  project_texture,
                  dtype=tf.complex64,
              )
              project_texture = tf.stack(
                  [tf.real(project_texture), tf.imag(project_texture)]
              )
  
          # Update texture variable
          project_texture_op = tf.assign(
              current_texture_variable,
              project_texture,
              name="project_texture_op",
          )
  
          # Create a placeholder to pass the background
          background_phd = tf.placeholder(
              dtype=tf.float32,
              shape=initial_input.shape.as_list(),
              name="background_phd",
          )
  
          # Create a placeholder to pass the image frame
          image_frame_phd = tf.placeholder(
              dtype=tf.float32,
              shape=[initial_shape[0], None, None, 4],
              name="image_frame_phd",
          )
  
          # Create adversarial image
          if rendering_function is not None:
              current_image = rendering_function(
                  background_phd, image_frame_phd, current_texture
              )
          else:  # pragma: no cover
              ValueError("Callable rendering_function is None.")
  
      else:
          # Create image variable
          current_image_variable = tf.Variable(
              initial_value=np.zeros(initial_input.shape.as_list()),
              dtype=tf.float32,
              name="current_image_variable",
          )
  
          # Create a placeholder to pass random transformation
          random_transformation_phd = tf.placeholder(
              dtype=tf.float32,
              shape=initial_input.shape.as_list(),
              name="random_transformation_phd",
          )
  
          # Update current image
          current_image = (
              current_image_variable + random_transformation_phd
          )
          current_image = (tf.tanh(current_image) + 1) / 2
          current_image = tf.identity(
              current_image, name="current_image"
          )
  
      # Assign current image to the input of the object detector
      current_image_assign_to_input_image_op = tf.assign(
          ref=self.estimator.input_images,
          value=current_image,
          name="current_image_assign_to_input_image_op",
      )
  
      # Create attack loss
      if self.texture_as_input:
          total_loss = self._create_attack_loss(
              initial_input=initial_input,
              current_value=current_texture,
              custom_loss=custom_loss,
          )
      else:
          total_loss = self._create_attack_loss(
              initial_input=initial_input,
              current_value=current_image,
              custom_loss=custom_loss,
          )
  
      # Create optimizer
      optimizer = self._create_optimizer()
  
      # Create gradients
      if self.texture_as_input:
          gradients = optimizer.compute_gradients(
              total_loss, var_list=[current_texture_variable]
          )[0][0]
      else:
          gradients = optimizer.compute_gradients(
              total_loss, var_list=[current_image_variable]
          )[0][0]
  
      # Create variables to store gradients
      if self.texture_as_input:
          sum_gradients = tf.Variable(  # pylint: disable=E1123
              initial_value=np.zeros(
                  current_texture_variable.shape.as_list()
              ),
              trainable=False,
              name="sum_gradients",
              dtype=tf.float32,
              collections=[
                  tf.GraphKeys.GLOBAL_VARIABLES,
                  tf.GraphKeys.LOCAL_VARIABLES,
              ],
          )
  
      else:
          sum_gradients = tf.Variable(  # pylint: disable=E1123
              initial_value=np.zeros(
                  current_image_variable.shape.as_list()
              ),
              trainable=False,
              name="sum_gradients",
              dtype=tf.float32,
              collections=[
                  tf.GraphKeys.GLOBAL_VARIABLES,
                  tf.GraphKeys.LOCAL_VARIABLES,
              ],
          )
  
      num_gradients = tf.Variable(  # pylint: disable=E1123
          initial_value=0.0,
          trainable=False,
          name="count_gradients",
          collections=[
              tf.GraphKeys.GLOBAL_VARIABLES,
              tf.GraphKeys.LOCAL_VARIABLES,
          ],
      )
  
      # Accumulate gradients
      accumulated_sum_gradients = tf.assign_add(
          sum_gradients, gradients
      )
      accumulated_num_gradients = tf.assign_add(num_gradients, 1.0)
  
      # Final gradients
      final_gradients = tf.div(
          accumulated_sum_gradients,
          tf.maximum(accumulated_num_gradients, 1.0),
          name="final_gradients",
      )
  
      if self.sign_gradients:
          final_gradients = tf.sign(final_gradients)
  
      # Create accumulated gradients operator
      accumulated_gradients_op = tf.group(
          [accumulated_sum_gradients, accumulated_num_gradients],
          name="accumulated_gradients_op",
      )
  
      # Create final attack optimization operator and return
      if self.texture_as_input:
          # Create final attack optimization operator
          final_attack_optimization_op = optimizer.apply_gradients(
              grads_and_vars=[
                  (final_gradients, current_texture_variable)
              ],
              name="final_attack_optimization_op",
          )
  
          return (
              project_texture_op,
              current_image_assign_to_input_image_op,
              accumulated_gradients_op,
              final_attack_optimization_op,
              current_texture_variable,
              current_texture,
          )
  
      # Create final attack optimization operator
      final_attack_optimization_op = optimizer.apply_gradients(
          grads_and_vars=[(final_gradients, current_image_variable)],
          name="final_attack_optimization_op",
      )
  
      return (
          project_texture_op,
          current_image_assign_to_input_image_op,
          accumulated_gradients_op,
          final_attack_optimization_op,
          current_image_variable,
          current_image,
      )
  
file_path: adversarial-robustness-toolbox/art/attacks/evasion/shapeshifter.py
imports: import logging
  from typing import List, Dict, Optional, Tuple, TYPE_CHECKING
  import numpy
  from art.attacks.attack import EvasionAttack
  from art.estimators.object_detection.tensorflow_faster_rcnn import TensorFlowFasterRCNN
label_desc: Use image node_id 4 for calling the ShapeShifter obj's underlying member method code with example usage: obj._build_graph(initial_shape, custom_loss, rendering_function) and returns: project_texture_op,  current_image_assign_to_input_image_op,  accumulated_gradients_op,  final_attack_optimization_op,  current_image_variable,  current_image, project_texture_op,  current_image_assign_to_input_image_op,  accumulated_gradients_op,  final_attack_optimization_op,  current_texture_variable,  current_texture