# Path: core/Util.py
# def calculate_ious(bboxes1, bboxes2):
#   # assume layout (x0, y0, x1, y1)
#   min_ = np.minimum(bboxes1[:, np.newaxis, :], bboxes2[np.newaxis, :, :])
#   max_ = np.maximum(bboxes1[:, np.newaxis, :], bboxes2[np.newaxis, :, :])
#   I = np.maximum(min_[..., 2] - max_[..., 0], 0) * np.maximum(min_[..., 3] - max_[..., 1], 0)
#   area1 = (bboxes1[..., 2] - bboxes1[..., 0]) * (bboxes1[..., 3] - bboxes1[..., 1])
#   area2 = (bboxes2[..., 2] - bboxes2[..., 0]) * (bboxes2[..., 3] - bboxes2[..., 1])
#   U = area1[:, np.newaxis] + area2[np.newaxis, :] - I
#   assert (U > 0).all()
#   IOUs = I / U
#   assert (IOUs >= 0).all()
#   assert (IOUs <= 1).all()
#   return IOUs
# 
# def calculate_ioas(bboxes1, bboxes2):
#   # assume layout (x0, y0, x1, y1)
#   min_ = np.minimum(bboxes1[:, np.newaxis, :], bboxes2[np.newaxis, :, :])
#   max_ = np.maximum(bboxes1[:, np.newaxis, :], bboxes2[np.newaxis, :, :])
#   I = np.maximum(min_[..., 2] - max_[..., 0], 0) * np.maximum(min_[..., 3] - max_[..., 1], 0)
#   area1 = (bboxes1[..., 2] - bboxes1[..., 0]) * (bboxes1[..., 3] - bboxes1[..., 1])
#   #area2 = (bboxes2[..., 2] - bboxes2[..., 0]) * (bboxes2[..., 3] - bboxes2[..., 1])
#   A = area1[:, np.newaxis]
#   assert (A > 0).all()
#   IOAs = I / A
#   assert (IOAs >= 0).all()
#   assert (IOAs <= 1).all()
#   return IOAs
# 
# 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/BoundingBox.py
# def get_bbox_from_segmentation_mask_np(mask):
#   # TODO check if this was a correct translation from the tensorflow version above
#   object_locations = (np.stack(np.where(np.equal(mask, 1))).T[:, :2]).astype(np.int32)
#   y0 = np.min(object_locations[:, 0])
#   x0 = np.min(object_locations[:, 1])
#   y1 = np.max(object_locations[:, 0]) + 1
#   x1 = np.max(object_locations[:, 1]) + 1
#   bbox = np.stack([y0, x0, y1, x1])
#   return bbox


import tensorflow as tf
import numpy as np
from PIL import Image
from core.Util import calculate_ious, calculate_ioas
from datasets import DataKeys
from datasets.util.BoundingBox import get_bbox_from_segmentation_mask_np
from functools import partial
from skimage.transform import integral_image



# TODO: clean this up
# These will be set init init_detection
ALL_ANCHORS = None
anchorH, anchorW = None, None

# From https://raw.githubusercontent.com/ppwwyyxx/tensorpack/master/examples/FasterRCNN/config.py
NUM_ANCHOR = 15  # This is hard coded
ANCHOR_STRIDE = 16
# TODO maybe read all of these from config too
POSITIVE_ANCHOR_THRES = 0.7
NEGATIVE_ANCHOR_THRES = 0.3
CROWD_OVERLAP_THRES = 0.7
RPN_FG_RATIO = 0.5

# Path: core/Util.py
# def calculate_ious(bboxes1, bboxes2):
#   # assume layout (x0, y0, x1, y1)
#   min_ = np.minimum(bboxes1[:, np.newaxis, :], bboxes2[np.newaxis, :, :])
#   max_ = np.maximum(bboxes1[:, np.newaxis, :], bboxes2[np.newaxis, :, :])
#   I = np.maximum(min_[..., 2] - max_[..., 0], 0) * np.maximum(min_[..., 3] - max_[..., 1], 0)
#   area1 = (bboxes1[..., 2] - bboxes1[..., 0]) * (bboxes1[..., 3] - bboxes1[..., 1])
#   area2 = (bboxes2[..., 2] - bboxes2[..., 0]) * (bboxes2[..., 3] - bboxes2[..., 1])
#   U = area1[:, np.newaxis] + area2[np.newaxis, :] - I
#   assert (U > 0).all()
#   IOUs = I / U
#   assert (IOUs >= 0).all()
#   assert (IOUs <= 1).all()
#   return IOUs
# 
# def calculate_ioas(bboxes1, bboxes2):
#   # assume layout (x0, y0, x1, y1)
#   min_ = np.minimum(bboxes1[:, np.newaxis, :], bboxes2[np.newaxis, :, :])
#   max_ = np.maximum(bboxes1[:, np.newaxis, :], bboxes2[np.newaxis, :, :])
#   I = np.maximum(min_[..., 2] - max_[..., 0], 0) * np.maximum(min_[..., 3] - max_[..., 1], 0)
#   area1 = (bboxes1[..., 2] - bboxes1[..., 0]) * (bboxes1[..., 3] - bboxes1[..., 1])
#   #area2 = (bboxes2[..., 2] - bboxes2[..., 0]) * (bboxes2[..., 3] - bboxes2[..., 1])
#   A = area1[:, np.newaxis]
#   assert (A > 0).all()
#   IOAs = I / A
#   assert (IOAs >= 0).all()
#   assert (IOAs <= 1).all()
#   return IOAs
# 
# 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/BoundingBox.py
# def get_bbox_from_segmentation_mask_np(mask):
#   # TODO check if this was a correct translation from the tensorflow version above
#   object_locations = (np.stack(np.where(np.equal(mask, 1))).T[:, :2]).astype(np.int32)
#   y0 = np.min(object_locations[:, 0])
#   x0 = np.min(object_locations[:, 1])
#   y1 = np.max(object_locations[:, 0]) + 1
#   x1 = np.max(object_locations[:, 1]) + 1
#   bbox = np.stack([y0, x0, y1, x1])
#   return bbox


# Path: datasets/util/Detection.py
import tensorflow as tf
import numpy as np
from PIL import Image
from core.Util import calculate_ious, calculate_ioas
from datasets import DataKeys
from datasets.util.BoundingBox import get_bbox_from_segmentation_mask_np
from functools import partial
from skimage.transform import integral_image




# TODO: clean this up
# These will be set init init_detection
ALL_ANCHORS = None
anchorH, anchorW = None, None

# From https://raw.githubusercontent.com/ppwwyyxx/tensorpack/master/examples/FasterRCNN/config.py
NUM_ANCHOR = 15  # This is hard coded
ANCHOR_STRIDE = 16
# TODO maybe read all of these from config too
POSITIVE_ANCHOR_THRES = 0.7
NEGATIVE_ANCHOR_THRES = 0.3
CROWD_OVERLAP_THRES = 0.7
RPN_FG_RATIO = 0.5

RPN_BATCH_PER_IM = 256