# Path: datasets/DataKeys.py
# SEGMENTATION_LABELS = "segmentation_labels"
# SEGMENTATION_LABELS_ORIGINAL_SIZE = "segmentation_labels_original_size"
# BBOX_GUIDANCE = "bbox_guidance"
# UNSIGNED_DISTANCE_TRANSFORM_GUIDANCE = "unsigned_distance_transform_guidance"
# SIGNED_DISTANCE_TRANSFORM_GUIDANCE = "signed_distance_transform_guidance"
# LASER_GUIDANCE = "laser_guidance"
# IMAGES = "images"
# RAW_IMAGES = "raw_images"
# INPUTS = "inputs"
# IMAGE_FILENAMES = "image_filenames"
# CLASSES = "classes"
# IDS = "ids"  # bounding box number 1,2,3...  or 0 if no bounding box
# DT_METHOD = "dt_method"
# RAW_SEGMENTATION_LABELS = "raw_segmentation_labels"
# CLICK_MAPS = "clicks_maps"
# NEG_CLICKS = "neg_clicks"
# POS_CLICKS = "pos_clicks"
# OBJ_TAGS = "obj_tags"
# FEATUREMAP_LABELS = "featuremap_labels"
# FEATUREMAP_BOXES = "featuremap_boxes"
# IMAGE_ID = "image_id"
# IS_CROWD = "is_crowd"
# SEGMENTATION_MASK = "segmentation_mask"
# SKIP_EXAMPLE = "skip_example"  # If true, filter the corresponding example from the datastream. Useful, when an example
# RAW_IMAGE_SIZES = "raw_image_sizes"  # h, w
# TIME_OFFSETS = "time_offsets"
# SPACE_OFFSETS = "space_offsets"
# SEGMENTATION_INSTANCE_LABELS = "segmentation_instance_labels"
# N_VALID_IDS = "n_valid_ids"
# 
# Path: datasets/util/Util.py
# def resize_image(img, out_size, bilinear):
#   if bilinear:
#     img = tf.image.resize_images(img, out_size)
#   else:
#     img = tf.image.resize_nearest_neighbor(tf.expand_dims(img, 0), out_size)
#     img = tf.squeeze(img, 0)
#   return img
# 
# def random_crop_image(img, size, offset=None):
#   # adapted from code from tf.random_crop
#   shape = tf.shape(img)
#   #remove the assertion for now since it makes the queue filling slow for some reason
#   #check = tf.Assert(
#   #  tf.reduce_all(shape[:2] >= size),
#   #  ["Need value.shape >= size, got ", shape, size])
#   #with tf.control_dependencies([check]):
#   #  img = tf.identity(img)
#   if offset is None:
#     offset = get_crop_offset(shape, size)
#   size0 = size[0] if isinstance(size[0], int) else None
#   size1 = size[1] if isinstance(size[1], int) else None
#   size_im = tf.stack([size[0], size[1], img.get_shape().as_list()[2]])
#   img_cropped = tf.slice(img, offset, size_im)
#   out_shape_img = [size0, size1, img.get_shape()[2]]
#   img_cropped.set_shape(out_shape_img)
#   return img_cropped, offset
# 
# def resize_coords_yxyx(tensor, out_size, original_size):
#   y_ratio = tf.ones([tf.shape(tensor)[0], 1]) * tf.cast(out_size[0] / original_size[0], tf.float32)
#   x_ratio = tf.ones([tf.shape(tensor)[0], 1]) * tf.cast(out_size[1] / original_size[1], tf.float32)
# 
#   tensor = tf.cast(tensor, tf.float32) * tf.concat([y_ratio, x_ratio, y_ratio, x_ratio], axis=1)
#   return tensor
# 
# def resize_coords_xy(tensor, out_size, original_size):
#   y_ratio = tf.cast(out_size[0], tf.float32) / tf.cast(original_size[0], tf.float32)
#   x_ratio = tf.cast(out_size[1], tf.float32) / tf.cast(original_size[1], tf.float32)
# 
#   tensor = tf.cast(tensor, tf.float32) * tf.stack([x_ratio, y_ratio])
#   return tensor
# 
# def get_crop_offset(img_shape, crop_size):
#   limit = img_shape[:2] - crop_size + 1
#   dtype = tf.int32
#   offset = tf.random_uniform(shape=(2,), dtype=dtype, maxval=dtype.max, seed=None) % limit
#   offset = tf.stack([offset[0], offset[1], 0])
#   return offset


from enum import Enum, unique
from functools import partial
from datasets import DataKeys
from datasets.util.Util import resize_image, random_crop_image, resize_coords_yxyx, resize_coords_xy, \
  get_crop_offset
import tensorflow as tf
import numpy as np
  for key in keys_to_resize_nn:
    resize_(key, Resizing_.NN)
  for key in keys_to_resize_coords_yxyx:
    resize_(key, Resizing_.Coords_yxyx)
  for key in keys_to_resize_coords_xy:
    resize_(key, Resizing_.Coords_xy)
  return tensors_resized


def resize_fixed_percentage(tensors, size):
  assert len(size) == 1
  percentage = float(size[0])/100.0
  h = tf.cast(tf.shape(tensors[DataKeys.IMAGES])[0], tf.float32)
  w = tf.cast(tf.shape(tensors[DataKeys.IMAGES])[1], tf.float32)

  newh = tf.multiply(percentage, h)
  neww = tf.multiply(percentage, w)

  newh = tf.cast(tf.round(newh), tf.int32)
  neww = tf.cast(tf.round(neww), tf.int32)

  return resize_fixed_size(tensors, tf.stack([newh, neww], axis=0))


def resize_min_short_edge_max_long_edge(tensors, size):
  # Reference: CustomResize._get_augment_params in
  # https://github.com/ppwwyyxx/tensorpack/blob/master/examples/FasterRCNN/common.py
  assert len(size) == 2
  min_short_edge = float(size[0])
  max_long_edge = float(size[1])

# Path: datasets/DataKeys.py
# SEGMENTATION_LABELS = "segmentation_labels"
# SEGMENTATION_LABELS_ORIGINAL_SIZE = "segmentation_labels_original_size"
# BBOX_GUIDANCE = "bbox_guidance"
# UNSIGNED_DISTANCE_TRANSFORM_GUIDANCE = "unsigned_distance_transform_guidance"
# SIGNED_DISTANCE_TRANSFORM_GUIDANCE = "signed_distance_transform_guidance"
# LASER_GUIDANCE = "laser_guidance"
# IMAGES = "images"
# RAW_IMAGES = "raw_images"
# INPUTS = "inputs"
# IMAGE_FILENAMES = "image_filenames"
# CLASSES = "classes"
# IDS = "ids"  # bounding box number 1,2,3...  or 0 if no bounding box
# DT_METHOD = "dt_method"
# RAW_SEGMENTATION_LABELS = "raw_segmentation_labels"
# CLICK_MAPS = "clicks_maps"
# NEG_CLICKS = "neg_clicks"
# POS_CLICKS = "pos_clicks"
# OBJ_TAGS = "obj_tags"
# FEATUREMAP_LABELS = "featuremap_labels"
# FEATUREMAP_BOXES = "featuremap_boxes"
# IMAGE_ID = "image_id"
# IS_CROWD = "is_crowd"
# SEGMENTATION_MASK = "segmentation_mask"
# SKIP_EXAMPLE = "skip_example"  # If true, filter the corresponding example from the datastream. Useful, when an example
# RAW_IMAGE_SIZES = "raw_image_sizes"  # h, w
# TIME_OFFSETS = "time_offsets"
# SPACE_OFFSETS = "space_offsets"
# SEGMENTATION_INSTANCE_LABELS = "segmentation_instance_labels"
# N_VALID_IDS = "n_valid_ids"
# 
# Path: datasets/util/Util.py
# def resize_image(img, out_size, bilinear):
#   if bilinear:
#     img = tf.image.resize_images(img, out_size)
#   else:
#     img = tf.image.resize_nearest_neighbor(tf.expand_dims(img, 0), out_size)
#     img = tf.squeeze(img, 0)
#   return img
# 
# def random_crop_image(img, size, offset=None):
#   # adapted from code from tf.random_crop
#   shape = tf.shape(img)
#   #remove the assertion for now since it makes the queue filling slow for some reason
#   #check = tf.Assert(
#   #  tf.reduce_all(shape[:2] >= size),
#   #  ["Need value.shape >= size, got ", shape, size])
#   #with tf.control_dependencies([check]):
#   #  img = tf.identity(img)
#   if offset is None:
#     offset = get_crop_offset(shape, size)
#   size0 = size[0] if isinstance(size[0], int) else None
#   size1 = size[1] if isinstance(size[1], int) else None
#   size_im = tf.stack([size[0], size[1], img.get_shape().as_list()[2]])
#   img_cropped = tf.slice(img, offset, size_im)
#   out_shape_img = [size0, size1, img.get_shape()[2]]
#   img_cropped.set_shape(out_shape_img)
#   return img_cropped, offset
# 
# def resize_coords_yxyx(tensor, out_size, original_size):
#   y_ratio = tf.ones([tf.shape(tensor)[0], 1]) * tf.cast(out_size[0] / original_size[0], tf.float32)
#   x_ratio = tf.ones([tf.shape(tensor)[0], 1]) * tf.cast(out_size[1] / original_size[1], tf.float32)
# 
#   tensor = tf.cast(tensor, tf.float32) * tf.concat([y_ratio, x_ratio, y_ratio, x_ratio], axis=1)
#   return tensor
# 
# def resize_coords_xy(tensor, out_size, original_size):
#   y_ratio = tf.cast(out_size[0], tf.float32) / tf.cast(original_size[0], tf.float32)
#   x_ratio = tf.cast(out_size[1], tf.float32) / tf.cast(original_size[1], tf.float32)
# 
#   tensor = tf.cast(tensor, tf.float32) * tf.stack([x_ratio, y_ratio])
#   return tensor
# 
# def get_crop_offset(img_shape, crop_size):
#   limit = img_shape[:2] - crop_size + 1
#   dtype = tf.int32
#   offset = tf.random_uniform(shape=(2,), dtype=dtype, maxval=dtype.max, seed=None) % limit
#   offset = tf.stack([offset[0], offset[1], 0])
#   return offset


# Path: datasets/Resize.py
from enum import Enum, unique
from functools import partial
from datasets import DataKeys
from datasets.util.Util import resize_image, random_crop_image, resize_coords_yxyx, resize_coords_xy, \
  get_crop_offset
import tensorflow as tf
import numpy as np

  for key in keys_to_resize_nn:
    resize_(key, Resizing_.NN)
  for key in keys_to_resize_coords_yxyx:
    resize_(key, Resizing_.Coords_yxyx)
  for key in keys_to_resize_coords_xy:
    resize_(key, Resizing_.Coords_xy)
  return tensors_resized


def resize_fixed_percentage(tensors, size):
  assert len(size) == 1
  percentage = float(size[0])/100.0
  h = tf.cast(tf.shape(tensors[DataKeys.IMAGES])[0], tf.float32)
  w = tf.cast(tf.shape(tensors[DataKeys.IMAGES])[1], tf.float32)

  newh = tf.multiply(percentage, h)
  neww = tf.multiply(percentage, w)

  newh = tf.cast(tf.round(newh), tf.int32)
  neww = tf.cast(tf.round(neww), tf.int32)

  return resize_fixed_size(tensors, tf.stack([newh, neww], axis=0))


def resize_min_short_edge_max_long_edge(tensors, size):
  # Reference: CustomResize._get_augment_params in
  # https://github.com/ppwwyyxx/tensorpack/blob/master/examples/FasterRCNN/common.py
  assert len(size) == 2
  min_short_edge = float(size[0])
  max_long_edge = float(size[1])

  h = tf.cast(tf.shape(tensors[DataKeys.IMAGES])[0], tf.float32)