class_docstr: Implementation of the adversarial patch attack for square and rectangular images and videos in PyTorch.
  
  | Paper link: https://arxiv.org/abs/1712.09665
code: def _random_overlay(
      self,
      images: "torch.Tensor",
      patch: "torch.Tensor",
      scale: Optional[float] = None,
      mask: Optional["torch.Tensor"] = None,
  ) -> "torch.Tensor":
      import torch
      import torchvision
  
      # Ensure channels-first
      if not self.estimator.channels_first:
          images = torch.permute(images, (0, 3, 1, 2))
  
      nb_samples = images.shape[0]
  
      image_mask = self._get_circular_patch_mask(nb_samples=nb_samples)
      image_mask = image_mask.float()
  
      self.image_shape = images.shape[1:]
  
      smallest_image_edge = np.minimum(
          self.image_shape[self.i_h], self.image_shape[self.i_w]
      )
  
      image_mask = torchvision.transforms.functional.resize(
          img=image_mask,
          size=(smallest_image_edge, smallest_image_edge),
          interpolation=2,
      )
  
      pad_h_before = int(
          (
              self.image_shape[self.i_h]
              - image_mask.shape[self.i_h_patch + 1]
          )
          / 2
      )
      pad_h_after = int(
          self.image_shape[self.i_h]
          - pad_h_before
          - image_mask.shape[self.i_h_patch + 1]
      )
  
      pad_w_before = int(
          (
              self.image_shape[self.i_w]
              - image_mask.shape[self.i_w_patch + 1]
          )
          / 2
      )
      pad_w_after = int(
          self.image_shape[self.i_w]
          - pad_w_before
          - image_mask.shape[self.i_w_patch + 1]
      )
  
      image_mask = torchvision.transforms.functional.pad(
          img=image_mask,
          padding=[
              pad_w_before,
              pad_h_before,
              pad_w_after,
              pad_h_after,
          ],
          fill=0,
          padding_mode="constant",
      )
  
      if self.nb_dims == 4:
          image_mask = torch.unsqueeze(image_mask, dim=1)
          image_mask = torch.repeat_interleave(
              image_mask, dim=1, repeats=self.input_shape[0]
          )
  
      image_mask = image_mask.float()
  
      patch = patch.float()
      padded_patch = torch.stack([patch] * nb_samples)
  
      padded_patch = torchvision.transforms.functional.resize(
          img=padded_patch,
          size=(smallest_image_edge, smallest_image_edge),
          interpolation=2,
      )
  
      padded_patch = torchvision.transforms.functional.pad(
          img=padded_patch,
          padding=[
              pad_w_before,
              pad_h_before,
              pad_w_after,
              pad_h_after,
          ],
          fill=0,
          padding_mode="constant",
      )
  
      if self.nb_dims == 4:
          padded_patch = torch.unsqueeze(padded_patch, dim=1)
          padded_patch = torch.repeat_interleave(
              padded_patch, dim=1, repeats=self.input_shape[0]
          )
  
      padded_patch = padded_patch.float()
  
      image_mask_list = []
      padded_patch_list = []
  
      for i_sample in range(nb_samples):
          if self.patch_location is None:
              if scale is None:
                  im_scale = np.random.uniform(
                      low=self.scale_min, high=self.scale_max
                  )
              else:
                  im_scale = scale
          else:
              im_scale = (
                  self.patch_shape[self.i_h] / smallest_image_edge
              )
  
          if mask is None:
              if self.patch_location is None:
                  padding_after_scaling_h = (
                      self.image_shape[self.i_h]
                      - im_scale * padded_patch.shape[self.i_h + 1]
                  ) / 2.0
                  padding_after_scaling_w = (
                      self.image_shape[self.i_w]
                      - im_scale * padded_patch.shape[self.i_w + 1]
                  ) / 2.0
                  x_shift = np.random.uniform(
                      -padding_after_scaling_w, padding_after_scaling_w
                  )
                  y_shift = np.random.uniform(
                      -padding_after_scaling_h, padding_after_scaling_h
                  )
              else:
                  padding_h = int(
                      math.floor(
                          self.image_shape[self.i_h]
                          - self.patch_shape[self.i_h]
                      )
                      / 2.0
                  )
                  padding_w = int(
                      math.floor(
                          self.image_shape[self.i_w]
                          - self.patch_shape[self.i_w]
                      )
                      / 2.0
                  )
                  x_shift = -padding_w + self.patch_location[0]
                  y_shift = -padding_h + self.patch_location[1]
          else:
              mask_2d = mask[i_sample, :, :]
  
              edge_x_0 = (
                  int(im_scale * padded_patch.shape[self.i_w + 1]) // 2
              )
              edge_x_1 = (
                  int(im_scale * padded_patch.shape[self.i_w + 1])
                  - edge_x_0
              )
              edge_y_0 = (
                  int(im_scale * padded_patch.shape[self.i_h + 1]) // 2
              )
              edge_y_1 = (
                  int(im_scale * padded_patch.shape[self.i_h + 1])
                  - edge_y_0
              )
  
              mask_2d[0:edge_x_0, :] = False
              if edge_x_1 > 0:
                  mask_2d[-edge_x_1:, :] = False
              mask_2d[:, 0:edge_y_0] = False
              if edge_y_1 > 0:
                  mask_2d[:, -edge_y_1:] = False
  
              num_pos = np.argwhere(mask_2d).shape[0]
              pos_id = np.random.choice(num_pos, size=1)
              pos = np.argwhere(mask_2d)[pos_id[0]]
              x_shift = pos[1] - self.image_shape[self.i_w] // 2
              y_shift = pos[0] - self.image_shape[self.i_h] // 2
  
          phi_rotate = float(
              np.random.uniform(-self.rotation_max, self.rotation_max)
          )
  
          image_mask_i = image_mask[i_sample]
  
          height = padded_patch.shape[self.i_h + 1]
          width = padded_patch.shape[self.i_w + 1]
  
          half_height = height // 2
          half_width = width // 2
          topleft = [
              int(
                  torch.randint(
                      0,
                      int(self.distortion_scale_max * half_width) + 1,
                      size=(1,),
                  ).item()
              ),
              int(
                  torch.randint(
                      0,
                      int(self.distortion_scale_max * half_height) + 1,
                      size=(1,),
                  ).item()
              ),
          ]
          topright = [
              int(
                  torch.randint(
                      width
                      - int(self.distortion_scale_max * half_width)
                      - 1,
                      width,
                      size=(1,),
                  ).item()
              ),
              int(
                  torch.randint(
                      0,
                      int(self.distortion_scale_max * half_height) + 1,
                      size=(1,),
                  ).item()
              ),
          ]
          botright = [
              int(
                  torch.randint(
                      width
                      - int(self.distortion_scale_max * half_width)
                      - 1,
                      width,
                      size=(1,),
                  ).item()
              ),
              int(
                  torch.randint(
                      height
                      - int(self.distortion_scale_max * half_height)
                      - 1,
                      height,
                      size=(1,),
                  ).item()
              ),
          ]
          botleft = [
              int(
                  torch.randint(
                      0,
                      int(self.distortion_scale_max * half_width) + 1,
                      size=(1,),
                  ).item()
              ),
              int(
                  torch.randint(
                      height
                      - int(self.distortion_scale_max * half_height)
                      - 1,
                      height,
                      size=(1,),
                  ).item()
              ),
          ]
          startpoints = [
              [0, 0],
              [width - 1, 0],
              [width - 1, height - 1],
              [0, height - 1],
          ]
          endpoints = [topleft, topright, botright, botleft]
  
          image_mask_i = torchvision.transforms.functional.perspective(
              img=image_mask_i,
              startpoints=startpoints,
              endpoints=endpoints,
              interpolation=2,
              fill=None,
          )
  
          image_mask_i = torchvision.transforms.functional.affine(
              img=image_mask_i,
              angle=phi_rotate,
              translate=[x_shift, y_shift],
              scale=im_scale,
              shear=[0, 0],
              interpolation=torchvision.transforms.InterpolationMode.NEAREST,
              fill=None,
          )
  
          image_mask_list.append(image_mask_i)
  
          padded_patch_i = padded_patch[i_sample]
  
          padded_patch_i = (
              torchvision.transforms.functional.perspective(
                  img=padded_patch_i,
                  startpoints=startpoints,
                  endpoints=endpoints,
                  interpolation=2,
                  fill=None,
              )
          )
  
          padded_patch_i = torchvision.transforms.functional.affine(
              img=padded_patch_i,
              angle=phi_rotate,
              translate=[x_shift, y_shift],
              scale=im_scale,
              shear=[0, 0],
              interpolation=torchvision.transforms.InterpolationMode.NEAREST,
              fill=None,
          )
  
          padded_patch_list.append(padded_patch_i)
  
      image_mask = torch.stack(image_mask_list, dim=0)
      padded_patch = torch.stack(padded_patch_list, dim=0)
      inverted_mask = (
          torch.from_numpy(
              np.ones(shape=image_mask.shape, dtype=np.float32)
          ).to(self.estimator.device)
          - image_mask
      )
  
      patched_images = (
          images * inverted_mask + padded_patch * image_mask
      )
  
      if not self.estimator.channels_first:
          patched_images = torch.permute(patched_images, (0, 2, 3, 1))
  
      return patched_images
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  import math
  from typing import Any, Optional, Tuple, Union, TYPE_CHECKING
  import numpy
  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.utils import check_and_transform_label_format, is_probability, to_categorical
  from art.summary_writer import SummaryWriter
label_desc: Use image node_id 6 for calling the AdversarialPatchPyTorch obj's underlying member method code with example usage: obj._random_overlay(images, patch, scale, mask) and returns: patched_images