Enforces size of perturbation on images, and compute hashes for all images.

  Args:
    dataset_batch_dir: directory with the images of specific dataset batch
    adv_dir: directory with generated adversarial images
    output_dir: directory where to copy result
    epsilon: size of perturbation

  Returns:
    dictionary with mapping form image ID to hash.

def enforce_epsilon_and_compute_hash(dataset_batch_dir, adv_dir, output_dir,
                                     epsilon):
  """Enforces size of perturbation on images, and compute hashes for all images.

  Args:
    dataset_batch_dir: directory with the images of specific dataset batch
    adv_dir: directory with generated adversarial images
    output_dir: directory where to copy result
    epsilon: size of perturbation

  Returns:
    dictionary with mapping form image ID to hash.
  """
  dataset_images = [f for f in os.listdir(dataset_batch_dir)
                    if f.endswith('.png')]
  image_hashes = {}
  resize_warning = False
  for img_name in dataset_images:
    if not os.path.exists(os.path.join(adv_dir, img_name)):
      logging.warning('Image %s not found in the output', img_name)
      continue
    image = np.array(
        Image.open(os.path.join(dataset_batch_dir, img_name)).convert('RGB'))
    image = image.astype('int32')
    image_max_clip = np.clip(image + epsilon, 0, 255).astype('uint8')
    image_min_clip = np.clip(image - epsilon, 0, 255).astype('uint8')
    # load and resize adversarial image if needed
    adv_image = Image.open(os.path.join(adv_dir, img_name)).convert('RGB')
    # Image.size is reversed compared to np.array.shape
    if adv_image.size[::-1] != image.shape[:2]:
      resize_warning = True
      adv_image = adv_image.resize((image.shape[1], image.shape[0]),
                                   Image.BICUBIC)
    adv_image = np.array(adv_image)
    clipped_adv_image = np.clip(adv_image,
                                image_min_clip,
                                image_max_clip)
    Image.fromarray(clipped_adv_image).save(os.path.join(output_dir, img_name))
    # compute hash
    image_hashes[img_name[:-4]] = hashlib.sha1(
        clipped_adv_image.view(np.uint8)).hexdigest()
  if resize_warning:
    logging.warning('One or more adversarial images had incorrect size')
  return image_hashes