# -*- coding: utf-8 -*-
"""Obj Det Resp.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1X2-LH5c1VMTI0LbGdLuiBJERA1g4j4WH
"""

import os, sys
import pathlib
from google.colab import drive
drive.mount('/content/drive')

# Commented out IPython magic to ensure Python compatibility.
# Add path environment
PERSONAL_DIR = "/content/drive/My Drive/"
BASE_DIR = PERSONAL_DIR + "models/"
# %set_env PYTHONPATH=/content/drive/My Drive/Laeveteinn/KopiOey/models/research:/content/drive/My Drive/Laeveteinn/KopiOey/models/research/slim
import os
os.environ['PYTHONPATH'] += ":/content/drive/My Drive/models"
import sys
sys.path.insert(1, os.path.join(BASE_DIR, "official"))
print(sys.path)

#!pip install -U --pre tensorflow=="2.*"
!pip install tf_slim
!pip install pycocotools
!pip install keyboard
!apt-get install protobuf-compiler python-pil python-lxml python-tk
!pip install Cython

# CLONE DE GIT
# try:
#   if "drive/My\ Drive/models" in pathlib.Path.cwd().parts:
#     while "drive/My\ Drive/models" in pathlib.Path.cwd().parts:
#       os.chdir('/content/drive/My Drive')
#   elif not pathlib.Path('drive/My\ Drive/models').exists():
#     os.chdir('/content/drive/My Drive')
#     !git clone --depth 1 https://github.com/tensorflow/models
# except:
#   None

# Commented out IPython magic to ensure Python compatibility.
# compile proto files
# make sure you are in BASE_DIR/research/ (see cell below)
# %cd /content/drive/My Drive/models/research/
# !protoc object_detection/protos/*.proto --python_out=.
# !cp object_detection/packages/tf2/setup.py .
# !python -m pip install .

print(os.getcwd())
os.chdir("/content/drive/My Drive/models/research/object_detection")
print(os.getcwd())
try:
  DATA_DIR = os.path.join(os.getcwd(), 'data')
  MODELS_DIR = os.path.join(DATA_DIR, 'models')
  for dir in [DATA_DIR, MODELS_DIR]:
    if not os.path.exists(dir):
      os.mkdir(dir)
except:
  print('error')

import os
import tarfile
import urllib.request

# os.chdir('/research')

# Download and extract model
MODEL_DATE = '20200711'
#'efficientdet_d2_coco17_tpu-32' #my primary model
#'centernet_resnet101_v1_fpn_512x512_coco17_tpu-8' #secondary model
MODEL_NAME = 'efficientdet_d2_coco17_tpu-32'
MODEL_TAR_FILENAME = MODEL_NAME + '.tar.gz'
MODELS_DOWNLOAD_BASE = 'http://download.tensorflow.org/models/object_detection/tf2/'
MODEL_DOWNLOAD_LINK = MODELS_DOWNLOAD_BASE + MODEL_DATE + '/' + MODEL_TAR_FILENAME
PATH_TO_MODEL_TAR = os.path.join(MODELS_DIR, MODEL_TAR_FILENAME)
PATH_TO_CKPT = os.path.join(MODELS_DIR, os.path.join(MODEL_NAME, 'checkpoint/'))
PATH_TO_CFG = os.path.join(MODELS_DIR, os.path.join(MODEL_NAME, 'pipeline.config'))
if not os.path.exists(PATH_TO_CKPT):
  print('Downloading model. This may take a while... ', end='')
  urllib.request.urlretrieve(MODEL_DOWNLOAD_LINK, PATH_TO_MODEL_TAR)
  tar_file = tarfile.open(PATH_TO_MODEL_TAR)
  tar_file.extractall(MODELS_DIR)
  tar_file.close()
  os.remove(PATH_TO_MODEL_TAR)
  print('Done')

# Download labels file
LABEL_FILENAME = 'mscoco_label_map.pbtxt'
LABELS_DOWNLOAD_BASE = \
    'https://raw.githubusercontent.com/tensorflow/models/master/research/object_detection/data/'
PATH_TO_LABELS = os.path.join(MODELS_DIR, os.path.join(MODEL_NAME, LABEL_FILENAME))
if not os.path.exists(PATH_TO_LABELS):
  print('Downloading label file... ', end='')
  urllib.request.urlretrieve(LABELS_DOWNLOAD_BASE + LABEL_FILENAME, PATH_TO_LABELS)
  print('Done')# %%bash

print(os.getcwd())

print(PATH_TO_CFG)

os.chdir('/content/drive/My Drive/models/research')

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'    # Suppress TensorFlow logging
import tensorflow as tf
from object_detection.utils import label_map_util
from object_detection.utils import config_util
from object_detection.utils import visualization_utils as viz_utils
os.chdir('/content/drive/My Drive/models')
from object_detection.builders import model_builder

tf.get_logger().setLevel('ERROR')           # Suppress TensorFlow logging (2)

# Enable GPU dynamic memory allocation
# gpus = tf.config.experimental.list_physical_devices('GPU')
# for gpu in gpus:
#     tf.config.experimental.set_memory_growth(gpu, True)

# Load pipeline config and build a detection model
configs = config_util.get_configs_from_pipeline_file(PATH_TO_CFG)
model_config = configs['model']
detection_model = model_builder.build(model_config=model_config, is_training=False)

# Restore checkpoint
ckpt = tf.compat.v2.train.Checkpoint(model=detection_model)
ckpt.restore(os.path.join(PATH_TO_CKPT, 'ckpt-0')).expect_partial()

@tf.function
def detect_fn(image):
    """Detect objects in image."""

    image, shapes = detection_model.preprocess(image)
    prediction_dict = detection_model.predict(image, shapes)
    detections = detection_model.postprocess(prediction_dict, shapes)

    return detections, prediction_dict, tf.reshape(shapes, [-1])

category_index = label_map_util.create_category_index_from_labelmap(PATH_TO_LABELS,
                                                                    use_display_name=True)

print(category_index)

import cv2
import numpy as np

def draw_centroid(frame, centroid):
  red = (0, 0, 255)
  value = tuple(centroid)
  cv2.circle(frame, value, 1, red, 10)

def draw_text(frame, centroid, id):
  centroid = tuple(centroid)
  green = (0, 255, 0)
  font = cv2.FONT_HERSHEY_PLAIN
  cv2.putText(frame, "Person #" + str(id), centroid, font, 1, green, 1, cv2.LINE_AA)

from scipy.spatial import distance as dist
from collections import OrderedDict
import numpy as np

class CentroidTracker():
	def __init__(self, frame_shape, maxDisappeared=50):
		# initialize the next unique object ID along with two ordered
		# dictionaries used to keep track of mapping a given object
		# ID to its centroid and number of consecutive frames it has
		# been marked as "disappeared", respectively
		self.nextObjectID = 0
		self.objects = OrderedDict()
		self.disappeared = OrderedDict()
		# Height, width and color channel of the frame
		self.height, self.width, self.channel = frame_shape

		# store the number of maximum consecutive frames a given
		# object is allowed to be marked as "disappeared" until we
		# need to deregister the object from tracking
		self.maxDisappeared = maxDisappeared

	def register(self, centroid):
		# when registering an object we use the next available object
		# ID to store the centroid
		self.objects[self.nextObjectID] = centroid
		self.disappeared[self.nextObjectID] = 0
		self.nextObjectID += 1

	def deregister(self, objectID):
		# to deregister an object ID we delete the object ID from
		# both of our respective dictionaries
		del self.objects[objectID]
		del self.disappeared[objectID]

	def update(self, frame, rects):
		# check to see if the list of input bounding box rectangles
		# is empty
		if len(rects) == 0:
			# loop over any existing tracked objects and mark them
			# as disappeared
			for objectID in list(self.disappeared.keys()):
				self.disappeared[objectID] += 1

				# if we have reached a maximum number of consecutive
				# frames where a given object has been marked as
				# missing, deregister it
				if self.disappeared[objectID] > self.maxDisappeared:
					self.deregister(objectID)

			# return early as there are no centroids or tracking info
			# to update
			return self.objects

		# initialize an array of input centroids for the current frame
		inputCentroids = np.zeros((len(rects), 2), dtype="int")

		# loop over the bounding box rectangles
		for (i, (endY, endX, startY, startX)) in enumerate(rects):
			# denormalize the bounding box coordinate
			d_minX = startX * self.height
			d_maxX = endX * self.height
			d_minY = startY * self.width
			d_maxY = endY * self.width
			# use the bounding box coordinates to derive the centroid
			cX = int((d_minX + d_maxX) / 2.0)
			cY = int((d_minY + d_maxY) / 2.0)
			inputCentroids[i] = (cX, cY)

		# if we are currently not tracking any objects take the input
		# centroids and register each of them
		if len(self.objects) == 0:
			for i in range(0, len(inputCentroids)):
				draw_centroid(frame, inputCentroids[i])
				self.register(inputCentroids[i])
				draw_text(frame, inputCentroids[i], self.nextObjectID-1)

		# otherwise, are are currently tracking objects so we need to
		# try to match the input centroids to existing object
		# centroids
		else:
			# grab the set of object IDs and corresponding centroids
			objectIDs = list(self.objects.keys())
			objectCentroids = list(self.objects.values())

			# compute the distance between each pair of object
			# centroids and input centroids, respectively -- our
			# goal will be to match an input centroid to an existing
			# object centroid
			D = dist.cdist(np.array(objectCentroids), inputCentroids)

			# in order to perform this matching we must (1) find the
			# smallest value in each row and then (2) sort the row
			# indexes based on their minimum values so that the row
			# with the smallest value as at the *front* of the index
			# list
			rows = D.min(axis=1).argsort()

			# next, we perform a similar process on the columns by
			# finding the smallest value in each column and then
			# sorting using the previously computed row index list
			cols = D.argmin(axis=1)[rows]

			# in order to determine if we need to update, register,
			# or deregister an object we need to keep track of which
			# of the rows and column indexes we have already examined
			usedRows = set()
			usedCols = set()

			# loop over the combination of the (row, column) index
			# tuples
			for (row, col) in zip(rows, cols):
				# if we have already examined either the row or
				# column value before, ignore it
				# val
				if row in usedRows or col in usedCols:
					continue

				# otherwise, grab the object ID for the current row,
				# set its new centroid, and reset the disappeared
				# counter
				objectID = objectIDs[row]
				self.objects[objectID] = inputCentroids[col]
				self.disappeared[objectID] = 0
				draw_centroid(frame, inputCentroids[col])
				draw_text(frame, inputCentroids[col], objectID)

				# indicate that we have examined each of the row and
				# column indexes, respectively
				usedRows.add(row)
				usedCols.add(col)

			# compute both the row and column index we have NOT yet
			# examined
			unusedRows = set(range(0, D.shape[0])).difference(usedRows)
			unusedCols = set(range(0, D.shape[1])).difference(usedCols)

			# in the event that the number of object centroids is
			# equal or greater than the number of input centroids
			# we need to check and see if some of these objects have
			# potentially disappeared
			if D.shape[0] >= D.shape[1]:
				# loop over the unused row indexes
				for row in unusedRows:
					# grab the object ID for the corresponding row
					# index and increment the disappeared counter
					objectID = objectIDs[row]
					self.disappeared[objectID] += 1

					# check to see if the number of consecutive
					# frames the object has been marked "disappeared"
					# for warrants deregistering the object
					if self.disappeared[objectID] > self.maxDisappeared:
						self.deregister(objectID)

			# otherwise, if the number of input centroids is greater
			# than the number of existing object centroids we need to
			# register each new input centroid as a trackable object
			else:
				for col in unusedCols:
					self.register(inputCentroids[col])
					draw_centroid(frame, inputCentroids[col])
					draw_text(frame, inputCentroids[col], self.nextObjectID-1)

		# return the set of trackable objects
		return self.objects

def confidence_pruning(boxes, scores, min_threshold=0.3):
  indices = np.squeeze(np.argwhere(scores >= min_threshold))
  boxes_pruned = boxes[[indices]]
  if boxes_pruned.ndim < 2:
    boxes_pruned = np.expand_dims(boxes_pruned, axis=0)
  return boxes_pruned

import time
from datetime import date

today = str(date.today())

### INPUT & OUTPUT VIDEO FILES ###
#25 AGST 20 1145 1200.avi #my main vid
#1 sept 2020 1100 1130.avi #second vid
VIDEO_NAME = '1 sept 2020 1100 1130.avi'
VIDEODIR = '/content/drive/My Drive/objDet/vid/' + VIDEO_NAME
OUTDIR = '/content/drive/My Drive/objDet/outvid/' + today + '_' + MODEL_NAME + '__' + VIDEO_NAME

### SETTING UP CV2 & VIDEO ###
cap = cv2.VideoCapture(VIDEODIR) #Getting video for cv2
#centerDet thresh = 0.55
#centerNet thresh = 0.3 ~ 0.35
thresh = 0.55 #threshold for filtering person

### VIDEO TECHNICAL ###
ret, image_np = cap.read()
fshape = image_np.shape
fheight = fshape[0]
fwidth = fshape[1]
fps = int(cap.get(cv2.CAP_PROP_FPS))
print("fps :",fps)
res = (fwidth , fheight)
print("res :",res)
#.mp4 format : *'MP4V' ; .avi : *'XVID'
out = cv2.VideoWriter(OUTDIR,cv2.VideoWriter_fourcc(*'XVID'), fps, res)

### GETTING CENTROID IF ANY DETECTION ###
Tracker = CentroidTracker([fwidth,fheight,3], maxDisappeared=50)

### SETTING UP WHEN to START & STOP, SHOWING DURATION ###   <---------------------------------###########################
startDetection = 8 * 60 #when to start detect
length = 1 * 5 #in second(s)  #Length how long to detect

l_startDetection = startDetection * fps #how many frames to skip detect
cap.set(cv2.CAP_PROP_POS_FRAMES, l_startDetection) #skip frame
l_fps = length * fps #how many frames to detect
i = 0 #initiate first frame

startTime = time.time() #how long it takes to process desired length video

### IT'S ALL BEGIN ###
if not (startDetection == 0):
  print('{} s ARE SKIPPED!'.format(startDetection))
print('WE ARE READY BOII!')
while (i < l_fps): #start to detect
  # Read frame from video
  ret, image_np = cap.read()

  if not ret:
    break

  # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
  #image_np_expanded = np.expand_dims(image_np, axis=0)
  
  #image_np = cv2.resize(image_np, (512, 512))

  # Things to try:
  # Flip horizontally
  # image_np = np.fliplr(image_np).copy()

  # Convert image to grayscale
  # image_np = np.tile(
  #     np.mean(image_np, 2, keepdims=True), (1, 1, 3)).astype(np.uint8)

  input_tensor = tf.convert_to_tensor(np.expand_dims(image_np, 0), dtype=tf.float32)
  detections, predictions_dict, shapes = detect_fn(input_tensor)

  label_id_offset = 1
  image_np_with_detections = image_np.copy()

  indices = np.squeeze(np.argwhere((detections['detection_classes'][0].numpy() + label_id_offset).astype(int) == 1))
  boxes = detections['detection_boxes'][0].numpy()
  boxes = boxes[[indices]]
  classes = (detections['detection_classes'][0] + label_id_offset).numpy()
  classes = classes[[indices]].astype(int)
  scores = detections['detection_scores'][0].numpy()
  scores = scores[[indices]]
  boxes = confidence_pruning(boxes, scores, thresh)

  People = Tracker.update(image_np_with_detections, boxes)

  # for j in range(boxes.shape[0]):
  #   if scores is None or scores[j] > tresh:
  #     box = tuple(boxes[j].tolist())
  #     x = int(((box[1]+box[0])/2) * fwidth)
  #     y = int(((box[2]+box[3])/2) * fheight)
  #     #print(box)
  #   image = cv2.circle(image_np_with_detections, (x,y), 3, (0, 0, 255) , -1)
  #     #print('scores = ',scores[i])

  #print("\r progress: "+str(int(((i+1)/fps)))+" s", end =" ")
  print("\r progress: {} s / {} s".format(str(int(((i+1)/fps))),length), end =" ")
  
  #print(scores, str(int(((i+1)/fps)))+" s")

  viz_utils.visualize_boxes_and_labels_on_image_array(
    image_np_with_detections,
    #image,
    boxes,
    classes,
    scores,
    category_index,
    use_normalized_coordinates=True,
    max_boxes_to_draw=200,
    min_score_thresh=thresh,
    agnostic_mode=False)

  # Display output
  #nFrame = cv2.resize(image_np_with_detections, (800, 600))
  #cv2.imshow('object detection', nFrame)
  
  # write the frame
  out.write(image_np_with_detections)

  i = i+1

  # if cv2.waitKey(25) & 0xFF == ord('q'):
  #     break

cap.release()
out.release()
doneTime = time.time()-startTime
print("")
print("DONE! Saved as :",OUTDIR)
print("Finish in : {} (s)".format(doneTime))


# -*- coding: utf-8 -*-
"""Obj Det Resp.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1X2-LH5c1VMTI0LbGdLuiBJERA1g4j4WH
"""

import os, sys
import pathlib
from google.colab import drive
drive.mount('/content/drive')

# Commented out IPython magic to ensure Python compatibility.
# Add path environment
PERSONAL_DIR = "/content/drive/My Drive/"
BASE_DIR = PERSONAL_DIR + "models/"
# %set_env PYTHONPATH=/content/drive/My Drive/Laeveteinn/KopiOey/models/research:/content/drive/My Drive/Laeveteinn/KopiOey/models/research/slim
import os
os.environ['PYTHONPATH'] += ":/content/drive/My Drive/models"
import sys
sys.path.insert(1, os.path.join(BASE_DIR, "official"))
print(sys.path)

#!pip install -U --pre tensorflow=="2.*"
!pip install tf_slim
!pip install pycocotools
!pip install keyboard
!apt-get install protobuf-compiler python-pil python-lxml python-tk
!pip install Cython

# CLONE DE GIT
# try:
#   if "drive/My\ Drive/models" in pathlib.Path.cwd().parts:
#     while "drive/My\ Drive/models" in pathlib.Path.cwd().parts:
#       os.chdir('/content/drive/My Drive')
#   elif not pathlib.Path('drive/My\ Drive/models').exists():
#     os.chdir('/content/drive/My Drive')
#     !git clone --depth 1 https://github.com/tensorflow/models
# except:
#   None

# Commented out IPython magic to ensure Python compatibility.
# compile proto files
# make sure you are in BASE_DIR/research/ (see cell below)
# %cd /content/drive/My Drive/models/research/
# !protoc object_detection/protos/*.proto --python_out=.
# !cp object_detection/packages/tf2/setup.py .
# !python -m pip install .

print(os.getcwd())
os.chdir("/content/drive/My Drive/models/research/object_detection")
print(os.getcwd())
try:
  DATA_DIR = os.path.join(os.getcwd(), 'data')
  MODELS_DIR = os.path.join(DATA_DIR, 'models')
  for dir in [DATA_DIR, MODELS_DIR]:
    if not os.path.exists(dir):
      os.mkdir(dir)
except:
  print('error')

import os
import tarfile
import urllib.request

# os.chdir('/research')

# Download and extract model
MODEL_DATE = '20200711'
#'efficientdet_d2_coco17_tpu-32' #my primary model
#'centernet_resnet101_v1_fpn_512x512_coco17_tpu-8' #secondary model
MODEL_NAME = 'efficientdet_d2_coco17_tpu-32'
MODEL_TAR_FILENAME = MODEL_NAME + '.tar.gz'
MODELS_DOWNLOAD_BASE = 'http://download.tensorflow.org/models/object_detection/tf2/'
MODEL_DOWNLOAD_LINK = MODELS_DOWNLOAD_BASE + MODEL_DATE + '/' + MODEL_TAR_FILENAME
PATH_TO_MODEL_TAR = os.path.join(MODELS_DIR, MODEL_TAR_FILENAME)
PATH_TO_CKPT = os.path.join(MODELS_DIR, os.path.join(MODEL_NAME, 'checkpoint/'))
PATH_TO_CFG = os.path.join(MODELS_DIR, os.path.join(MODEL_NAME, 'pipeline.config'))
if not os.path.exists(PATH_TO_CKPT):
  print('Downloading model. This may take a while... ', end='')
  urllib.request.urlretrieve(MODEL_DOWNLOAD_LINK, PATH_TO_MODEL_TAR)
  tar_file = tarfile.open(PATH_TO_MODEL_TAR)
  tar_file.extractall(MODELS_DIR)
  tar_file.close()
  os.remove(PATH_TO_MODEL_TAR)
  print('Done')

# Download labels file
LABEL_FILENAME = 'mscoco_label_map.pbtxt'
LABELS_DOWNLOAD_BASE = \
    'https://raw.githubusercontent.com/tensorflow/models/master/research/object_detection/data/'
PATH_TO_LABELS = os.path.join(MODELS_DIR, os.path.join(MODEL_NAME, LABEL_FILENAME))
if not os.path.exists(PATH_TO_LABELS):
  print('Downloading label file... ', end='')
  urllib.request.urlretrieve(LABELS_DOWNLOAD_BASE + LABEL_FILENAME, PATH_TO_LABELS)
  print('Done')# %%bash

print(os.getcwd())

print(PATH_TO_CFG)

os.chdir('/content/drive/My Drive/models/research')

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'    # Suppress TensorFlow logging
import tensorflow as tf
from object_detection.utils import label_map_util
from object_detection.utils import config_util
from object_detection.utils import visualization_utils as viz_utils
os.chdir('/content/drive/My Drive/models')
from object_detection.builders import model_builder

tf.get_logger().setLevel('ERROR')           # Suppress TensorFlow logging (2)

# Enable GPU dynamic memory allocation
# gpus = tf.config.experimental.list_physical_devices('GPU')
# for gpu in gpus:
#     tf.config.experimental.set_memory_growth(gpu, True)

# Load pipeline config and build a detection model
configs = config_util.get_configs_from_pipeline_file(PATH_TO_CFG)
model_config = configs['model']
detection_model = model_builder.build(model_config=model_config, is_training=False)

# Restore checkpoint
ckpt = tf.compat.v2.train.Checkpoint(model=detection_model)
ckpt.restore(os.path.join(PATH_TO_CKPT, 'ckpt-0')).expect_partial()

@tf.function
def detect_fn(image):
    """Detect objects in image."""

    image, shapes = detection_model.preprocess(image)
    prediction_dict = detection_model.predict(image, shapes)
    detections = detection_model.postprocess(prediction_dict, shapes)

    return detections, prediction_dict, tf.reshape(shapes, [-1])

category_index = label_map_util.create_category_index_from_labelmap(PATH_TO_LABELS,
                                                                    use_display_name=True)

print(category_index)

import cv2
import numpy as np

def draw_centroid(frame, centroid):
  red = (0, 0, 255)
  value = tuple(centroid)
  cv2.circle(frame, value, 1, red, 10)

def draw_text(frame, centroid, id):
  centroid = tuple(centroid)
  green = (0, 255, 0)
  font = cv2.FONT_HERSHEY_PLAIN
  cv2.putText(frame, "Person #" + str(id), centroid, font, 1, green, 1, cv2.LINE_AA)

from scipy.spatial import distance as dist
from collections import OrderedDict
import numpy as np

class CentroidTracker():
	def __init__(self, frame_shape, maxDisappeared=50):
		# initialize the next unique object ID along with two ordered
		# dictionaries used to keep track of mapping a given object
		# ID to its centroid and number of consecutive frames it has
		# been marked as "disappeared", respectively
		self.nextObjectID = 0
		self.objects = OrderedDict()
		self.disappeared = OrderedDict()
		# Height, width and color channel of the frame
		self.height, self.width, self.channel = frame_shape

		# store the number of maximum consecutive frames a given
		# object is allowed to be marked as "disappeared" until we
		# need to deregister the object from tracking
		self.maxDisappeared = maxDisappeared

	def register(self, centroid):
		# when registering an object we use the next available object
		# ID to store the centroid
		self.objects[self.nextObjectID] = centroid
		self.disappeared[self.nextObjectID] = 0
		self.nextObjectID += 1

	def deregister(self, objectID):
		# to deregister an object ID we delete the object ID from
		# both of our respective dictionaries
		del self.objects[objectID]
		del self.disappeared[objectID]

	def update(self, frame, rects):
		# check to see if the list of input bounding box rectangles
		# is empty
		if len(rects) == 0:
			# loop over any existing tracked objects and mark them
			# as disappeared
			for objectID in list(self.disappeared.keys()):
				self.disappeared[objectID] += 1

				# if we have reached a maximum number of consecutive
				# frames where a given object has been marked as
				# missing, deregister it
				if self.disappeared[objectID] > self.maxDisappeared:
					self.deregister(objectID)

			# return early as there are no centroids or tracking info
			# to update
			return self.objects

		# initialize an array of input centroids for the current frame
		inputCentroids = np.zeros((len(rects), 2), dtype="int")

		# loop over the bounding box rectangles
		for (i, (endY, endX, startY, startX)) in enumerate(rects):
			# denormalize the bounding box coordinate
			d_minX = startX * self.height
			d_maxX = endX * self.height
			d_minY = startY * self.width
			d_maxY = endY * self.width
			# use the bounding box coordinates to derive the centroid
			cX = int((d_minX + d_maxX) / 2.0)
			cY = int((d_minY + d_maxY) / 2.0)
			inputCentroids[i] = (cX, cY)

		# if we are currently not tracking any objects take the input
		# centroids and register each of them
		if len(self.objects) == 0:
			for i in range(0, len(inputCentroids)):
				draw_centroid(frame, inputCentroids[i])
				self.register(inputCentroids[i])
				draw_text(frame, inputCentroids[i], self.nextObjectID-1)

		# otherwise, are are currently tracking objects so we need to
		# try to match the input centroids to existing object
		# centroids
		else:
			# grab the set of object IDs and corresponding centroids
			objectIDs = list(self.objects.keys())
			objectCentroids = list(self.objects.values())

			# compute the distance between each pair of object
			# centroids and input centroids, respectively -- our
			# goal will be to match an input centroid to an existing
			# object centroid
			D = dist.cdist(np.array(objectCentroids), inputCentroids)

			# in order to perform this matching we must (1) find the
			# smallest value in each row and then (2) sort the row
			# indexes based on their minimum values so that the row
			# with the smallest value as at the *front* of the index
			# list
			rows = D.min(axis=1).argsort()

			# next, we perform a similar process on the columns by
			# finding the smallest value in each column and then
			# sorting using the previously computed row index list
			cols = D.argmin(axis=1)[rows]

			# in order to determine if we need to update, register,
			# or deregister an object we need to keep track of which
			# of the rows and column indexes we have already examined
			usedRows = set()
			usedCols = set()

			# loop over the combination of the (row, column) index
			# tuples
			for (row, col) in zip(rows, cols):
				# if we have already examined either the row or
				# column value before, ignore it
				# val
				if row in usedRows or col in usedCols:
					continue

				# otherwise, grab the object ID for the current row,
				# set its new centroid, and reset the disappeared
				# counter
				objectID = objectIDs[row]
				self.objects[objectID] = inputCentroids[col]
				self.disappeared[objectID] = 0
				draw_centroid(frame, inputCentroids[col])
				draw_text(frame, inputCentroids[col], objectID)

				# indicate that we have examined each of the row and
				# column indexes, respectively
				usedRows.add(row)
				usedCols.add(col)

			# compute both the row and column index we have NOT yet
			# examined
			unusedRows = set(range(0, D.shape[0])).difference(usedRows)
			unusedCols = set(range(0, D.shape[1])).difference(usedCols)

			# in the event that the number of object centroids is
			# equal or greater than the number of input centroids
			# we need to check and see if some of these objects have
			# potentially disappeared
			if D.shape[0] >= D.shape[1]:
				# loop over the unused row indexes
				for row in unusedRows:
					# grab the object ID for the corresponding row
					# index and increment the disappeared counter
					objectID = objectIDs[row]
					self.disappeared[objectID] += 1

					# check to see if the number of consecutive
					# frames the object has been marked "disappeared"
					# for warrants deregistering the object
					if self.disappeared[objectID] > self.maxDisappeared:
						self.deregister(objectID)

			# otherwise, if the number of input centroids is greater
			# than the number of existing object centroids we need to
			# register each new input centroid as a trackable object
			else:
				for col in unusedCols:
					self.register(inputCentroids[col])
					draw_centroid(frame, inputCentroids[col])
					draw_text(frame, inputCentroids[col], self.nextObjectID-1)

		# return the set of trackable objects
		return self.objects

def confidence_pruning(boxes, scores, min_threshold=0.3):
  indices = np.squeeze(np.argwhere(scores >= min_threshold))
  boxes_pruned = boxes[[indices]]
  if boxes_pruned.ndim < 2:
    boxes_pruned = np.expand_dims(boxes_pruned, axis=0)
  return boxes_pruned

import time
from datetime import date

today = str(date.today())

### INPUT & OUTPUT VIDEO FILES ###
#25 AGST 20 1145 1200.avi #my main vid
#1 sept 2020 1100 1130.avi #second vid
VIDEO_NAME = '1 sept 2020 1100 1130.avi'
VIDEODIR = '/content/drive/My Drive/objDet/vid/' + VIDEO_NAME
OUTDIR = '/content/drive/My Drive/objDet/outvid/' + today + '_' + MODEL_NAME + '__' + VIDEO_NAME

### SETTING UP CV2 & VIDEO ###
cap = cv2.VideoCapture(VIDEODIR) #Getting video for cv2
#centerDet thresh = 0.55
#centerNet thresh = 0.3 ~ 0.35
thresh = 0.55 #threshold for filtering person

### VIDEO TECHNICAL ###
ret, image_np = cap.read()
fshape = image_np.shape
fheight = fshape[0]
fwidth = fshape[1]
fps = int(cap.get(cv2.CAP_PROP_FPS))
print("fps :",fps)
res = (fwidth , fheight)
print("res :",res)
#.mp4 format : *'MP4V' ; .avi : *'XVID'
out = cv2.VideoWriter(OUTDIR,cv2.VideoWriter_fourcc(*'XVID'), fps, res)

### GETTING CENTROID IF ANY DETECTION ###
Tracker = CentroidTracker([fwidth,fheight,3], maxDisappeared=50)

### SETTING UP WHEN to START & STOP, SHOWING DURATION ###   <---------------------------------###########################
startDetection = 8 * 60 #when to start detect
length = 1 * 5 #in second(s)  #Length how long to detect

l_startDetection = startDetection * fps #how many frames to skip detect
cap.set(cv2.CAP_PROP_POS_FRAMES, l_startDetection) #skip frame
l_fps = length * fps #how many frames to detect
i = 0 #initiate first frame

startTime = time.time() #how long it takes to process desired length video

### IT'S ALL BEGIN ###
if not (startDetection == 0):
  print('{} s ARE SKIPPED!'.format(startDetection))
print('WE ARE READY BOII!')
while (i < l_fps): #start to detect
  # Read frame from video
  ret, image_np = cap.read()

  if not ret:
    break

  # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
  #image_np_expanded = np.expand_dims(image_np, axis=0)
  
  #image_np = cv2.resize(image_np, (512, 512))

  # Things to try:
  # Flip horizontally
  # image_np = np.fliplr(image_np).copy()

  # Convert image to grayscale
  # image_np = np.tile(
  #     np.mean(image_np, 2, keepdims=True), (1, 1, 3)).astype(np.uint8)

  input_tensor = tf.convert_to_tensor(np.expand_dims(image_np, 0), dtype=tf.float32)
  detections, predictions_dict, shapes = detect_fn(input_tensor)

  label_id_offset = 1
  image_np_with_detections = image_np.copy()

  indices = np.squeeze(np.argwhere((detections['detection_classes'][0].numpy() + label_id_offset).astype(int) == 1))
  boxes = detections['detection_boxes'][0].numpy()
  boxes = boxes[[indices]]
  classes = (detections['detection_classes'][0] + label_id_offset).numpy()
  classes = classes[[indices]].astype(int)
  scores = detections['detection_scores'][0].numpy()
  scores = scores[[indices]]
  boxes = confidence_pruning(boxes, scores, thresh)

  People = Tracker.update(image_np_with_detections, boxes)

  # for j in range(boxes.shape[0]):
  #   if scores is None or scores[j] > tresh:
  #     box = tuple(boxes[j].tolist())
  #     x = int(((box[1]+box[0])/2) * fwidth)
  #     y = int(((box[2]+box[3])/2) * fheight)
  #     #print(box)
  #   image = cv2.circle(image_np_with_detections, (x,y), 3, (0, 0, 255) , -1)
  #     #print('scores = ',scores[i])

  #print("\r progress: "+str(int(((i+1)/fps)))+" s", end =" ")
  print("\r progress: {} s / {} s".format(str(int(((i+1)/fps))),length), end =" ")
  
  #print(scores, str(int(((i+1)/fps)))+" s")

  viz_utils.visualize_boxes_and_labels_on_image_array(
    image_np_with_detections,
    #image,
    boxes,
    classes,
    scores,
    category_index,
    use_normalized_coordinates=True,
    max_boxes_to_draw=200,
    min_score_thresh=thresh,
    agnostic_mode=False)

  # Display output
  #nFrame = cv2.resize(image_np_with_detections, (800, 600))
  #cv2.imshow('object detection', nFrame)
  
  # write the frame
  out.write(image_np_with_detections)

  i = i+1

  # if cv2.waitKey(25) & 0xFF == ord('q'):
  #     break

cap.release()
out.release()
doneTime = time.time()-startTime
print("")
print("DONE! Saved as :",OUTDIR)
print("Finish in : {} (s)".format(doneTime))


# -*- coding: utf-8 -*- Obj Det Resp.ipynb  Automatically generated by Colaboratory.  Original file is located at     https://colab.research.google.com/drive/1X2-LH5c1VMTI0LbGdLuiBJERA1g4j4WH # Commented out IPython magic to ensure Python compatibility. # Add path environment # %set_env PYTHONPATH=/content/drive/My Drive/Laeveteinn/KopiOey/models/research:/content/drive/My Drive/Laeveteinn/KopiOey/models/research/slim #!pip install -U --pre tensorflow=="2.*" # CLONE DE GIT # try: #   if "drive/My\ Drive/models" in pathlib.Path.cwd().parts: #     while "drive/My\ Drive/models" in pathlib.Path.cwd().parts: #       os.chdir('/content/drive/My Drive') #   elif not pathlib.Path('drive/My\ Drive/models').exists(): #     os.chdir('/content/drive/My Drive') #     !git clone --depth 1 https://github.com/tensorflow/models # except: #   None # Commented out IPython magic to ensure Python compatibility. # compile proto files # make sure you are in BASE_DIR/research/ (see cell below) # %cd /content/drive/My Drive/models/research/ # !protoc object_detection/protos/*.proto --python_out=. # !cp object_detection/packages/tf2/setup.py . # !python -m pip install . # os.chdir('/research') # Download and extract model #'efficientdet_d2_coco17_tpu-32' #my primary model #'centernet_resnet101_v1_fpn_512x512_coco17_tpu-8' #secondary model # Download labels file # %%bash # Suppress TensorFlow logging # Suppress TensorFlow logging (2) # Enable GPU dynamic memory allocation # gpus = tf.config.experimental.list_physical_devices('GPU') # for gpu in gpus: #     tf.config.experimental.set_memory_growth(gpu, True) # Load pipeline config and build a detection model # Restore checkpoint Detect objects in image. #" + str(id), centroid, font, 1, green, 1, cv2.LINE_AA) # initialize the next unique object ID along with two ordered # dictionaries used to keep track of mapping a given object # ID to its centroid and number of consecutive frames it has # been marked as "disappeared", respectively # Height, width and color channel of the frame # store the number of maximum consecutive frames a given # object is allowed to be marked as "disappeared" until we # need to deregister the object from tracking # when registering an object we use the next available object # ID to store the centroid # to deregister an object ID we delete the object ID from # both of our respective dictionaries # check to see if the list of input bounding box rectangles # is empty # loop over any existing tracked objects and mark them # as disappeared # if we have reached a maximum number of consecutive # frames where a given object has been marked as # missing, deregister it # return early as there are no centroids or tracking info # to update # initialize an array of input centroids for the current frame # loop over the bounding box rectangles # denormalize the bounding box coordinate # use the bounding box coordinates to derive the centroid # if we are currently not tracking any objects take the input # centroids and register each of them # otherwise, are are currently tracking objects so we need to # try to match the input centroids to existing object # centroids # grab the set of object IDs and corresponding centroids # compute the distance between each pair of object # centroids and input centroids, respectively -- our # goal will be to match an input centroid to an existing # object centroid # in order to perform this matching we must (1) find the # smallest value in each row and then (2) sort the row # indexes based on their minimum values so that the row # with the smallest value as at the *front* of the index # list # next, we perform a similar process on the columns by # finding the smallest value in each column and then # sorting using the previously computed row index list # in order to determine if we need to update, register, # or deregister an object we need to keep track of which # of the rows and column indexes we have already examined # loop over the combination of the (row, column) index # tuples # if we have already examined either the row or # column value before, ignore it # val # otherwise, grab the object ID for the current row, # set its new centroid, and reset the disappeared # counter # indicate that we have examined each of the row and # column indexes, respectively # compute both the row and column index we have NOT yet # examined # in the event that the number of object centroids is # equal or greater than the number of input centroids # we need to check and see if some of these objects have # potentially disappeared # loop over the unused row indexes # grab the object ID for the corresponding row # index and increment the disappeared counter # check to see if the number of consecutive # frames the object has been marked "disappeared" # for warrants deregistering the object # otherwise, if the number of input centroids is greater # than the number of existing object centroids we need to # register each new input centroid as a trackable object # return the set of trackable objects ### INPUT & OUTPUT VIDEO FILES ### #25 AGST 20 1145 1200.avi #my main vid #1 sept 2020 1100 1130.avi #second vid ### SETTING UP CV2 & VIDEO ### #Getting video for cv2 #centerDet thresh = 0.55 #centerNet thresh = 0.3 ~ 0.35 #threshold for filtering person ### VIDEO TECHNICAL ### #.mp4 format : *'MP4V' ; .avi : *'XVID' ### GETTING CENTROID IF ANY DETECTION ### ### SETTING UP WHEN to START & STOP, SHOWING DURATION ###   <---------------------------------########################### #when to start detect #in second(s)  #Length how long to detect #how many frames to skip detect #skip frame #how many frames to detect #initiate first frame #how long it takes to process desired length video ### IT'S ALL BEGIN ### #start to detect # Read frame from video # Expand dimensions since the model expects images to have shape: [1, None, None, 3] #image_np_expanded = np.expand_dims(image_np, axis=0) #image_np = cv2.resize(image_np, (512, 512)) # Things to try: # Flip horizontally # image_np = np.fliplr(image_np).copy() # Convert image to grayscale # image_np = np.tile( #     np.mean(image_np, 2, keepdims=True), (1, 1, 3)).astype(np.uint8) # for j in range(boxes.shape[0]): #   if scores is None or scores[j] > tresh: #     box = tuple(boxes[j].tolist()) #     x = int(((box[1]+box[0])/2) * fwidth) #     y = int(((box[2]+box[3])/2) * fheight) #     #print(box) #   image = cv2.circle(image_np_with_detections, (x,y), 3, (0, 0, 255) , -1) #     #print('scores = ',scores[i]) #print("\r progress: "+str(int(((i+1)/fps)))+" s", end =" ") #print(scores, str(int(((i+1)/fps)))+" s") #image, # Display output #nFrame = cv2.resize(image_np_with_detections, (800, 600)) #cv2.imshow('object detection', nFrame) # write the frame # if cv2.waitKey(25) & 0xFF == ord('q'): #     break