Measuring social distance in the time of Covid-19  

20/07/2020

Using TensorFlow Object Detection API for detecting pedestrians and calculating “social distance” between them.

Today, unfortunately, everyone is familiar with the term “social distance”. It’s something we will have to live with for a while until everything returns to normal. At Immune Technology Institute we have tried to develop an application using the TensorFlow Object Detection API for identifying and measuring the social distance between pedestrians.

 

Wait… What is the TensorFlow Object Detection API?

The TensorFlow Object Detection API is the framework for creating a deep learning network that solves object detection problems. It contains some pre-trained models trained on different datasets which can be used for inference.

Additionally, we can use this framework for applying transfer learning in pre-trained models that were previously trained on large datasets which enables us to customize these models for a certain task. For instance, we can apply transfer learning to train a model for identifying if a person is wearing a mask or not.

The intuition behind transfer learning for image classification is that if a model is trained on a large and general enough dataset, this model will effectively serve as a generic model of the visual world. You can then take advantage of these learned feature maps without having to start from scratch by training a large model on a large dataset.

In this case, we did not need to apply transfer learning since we want to identify pedestrians, and there are already some models trained to inference this. We have used the model ssd_mobilenet_v2_coco_2018_03_29 which has been trained on these objects:

 

{
{'id': 1, 'name': u'person'},
{'id': 2, 'name': u'bicycle'},
{'id': 3, 'name': u'car'},
{'id': 4, 'name': u'motorcycle'},
{'id': 5, 'name': u'airplane'},
{'id': 6, 'name': u'bus'},
{'id': 7, 'name': u'train'},
{'id': 8, 'name': u'truck'},
{'id': 9, 'name': u'boat'},
{'id': 10, 'name': u'traffic light'},
...
{'id': 90, 'name': u'toothbrush'}
}

For this use case, we only need to identify and display pedestrians, therefore we will create a function for filtering predictions by label and we are only going to display the person (id=1) labels.

Let’s go… Some Code!

When I developed this code the TensorFlow Object Detection API had not full support for TensorFlow 2 but on July 10th Google released a new version, developing support for some new functionalities. In this case, I have used TensorFlow 1 with the release r1.13.0 of TF Object Detection API and all the capacity of Google Colab for this experiment.

You can find the code in my GitHub.

First of all, we need to create our working directory, called Projects/Pedestrian_Detection in our Drive, where we will clone the TensorFlow Object Detection API repository. Then, we will able to start a notebook with Google Colab.

First of all, we need to mount our drive inside our notebook, we just need to follow the instructions.

from google.colab import drive

drive.mount('/gdrive', force_remount=True)

Then, we’ll be able to change the path to our root folder Projects/Pedestrian_Detection.

%cd /gdrive/'My Drive'/Projects/Pedestrian_Detection/models/research/

Now, we can clone the repository of TF Object Detection, in this case the release r1.13.0.

git clone https://github.com/tensorflow/models/tree/r1.13.0

 

Why did I use this release? ? Basically, because I have tested some other releases but I have found some bugs and this is the first one I tested it and it worked perfectly.

Once you clone the repository you will see a folder called Models in the directory: Projects/Pedestrian_Detection.

 

Now the fun part starts!!

The guys from TensorFlow are very nice people and they have provided us a notebook to walk you through the process of using a pre-trained model to detect objects in an image (you can find it here: Projects/Pedestrian_Detection/models/research/object_detection/colab_tutorials). However, we will create our own notebook because we are going to learn how to implement new visualization functions.

Go to Projects/Pedestrian_Detection/models/research/object_detection in Drive and create a new Google Colab in this directory.

The first thing is to set the TensorFlow version to 1.x.

%tensorflow_version 1.x
import tensorflow as tf

As we did before, we should mount our drive image into Google Colab and go to Projects/Pedestrian_Detection/models/research/

from google.colab import drive

 drive.mount('/gdrive', force_remount=True) 

%cd /gdrive/'My Drive'/Projects/Pedestrian_Detection/models/research/

We will need to install some libraries such as Cython, contextlib2, pillow, lxml, matplotlib, pycocotools and the protocbuf compiler.

!apt-get install -qq protobuf-compiler python-pil python-lxml python-tk 

!pip install -qq Cython contextlib2 pillow lxml matplotlib pycocotools 

!pip install tf-slim 

!pip install numpy==1.17.0

Now we should run the protoc compiler, which is a Google library for serializing structure data which is used by TensorFlow 

— think XML, but smaller, faster, and simpler.

Protoc is already installed in Google Colab but if you are using your own machine you have to follow these instructions.

!pwd
!protoc object_detection/protos/*.proto --python_out=.

Wait…What did protoc do? Basically, protoc has generated a python script for each file in /models/research/object_detection/protos.

 

Great!! We are a little closer ✌️. The next step is pretty straight forward since we need to set the PYTHONPATH and install the packages using setup.py.

import os
os.environ['PYTHONPATH'] += '/gdrive/My Drive/Projects/Pedestrian_Detection/models/research/:/gdrive/My Drive/Projects/Pedestrian_Detection/models/research/slim/'

!python setup.py build
!python setup.py install

In the end, you should see something like this:

One second… We need a model, right? Yeep! We need to download a pre-trained model, in this case I have chosen this one: ssd_mobilenet_v2_coco_2018_03_29 because it is fast (important in a real-time application) and has great accuracy. However, you can explore how other models perform and select the right one for your application.

!mkdir /gdrive/'My Drive'/Projects/Pedestrian_Detection/models/research/pretrained_model
%cd /gdrive/'My Drive'/Projects/Pedestrian_Detection/models/research/pretrained_model


!wget http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_coco_2018_03_29.tar.gz

!tar -xzf ssd_mobilenet_v2_coco_2018_03_29.tar.gz -C .
%cd /gdrive/'My Drive'/Projects/Pedestrian_Detection/models/research/

If everything has worked correctly you will be able to use the TensorFlow Object Detection API. The next step is to import the libraries that we are going to use.

 

import numpy as np
import os
import six.moves.urllib as urllib
import sys
import tarfile
import tensorflow as tf
import zipfile

from distutils.version import StrictVersion
from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from PIL import Image


# This is needed since the notebook is stored in the object_detection folder.
sys.path.append("..")
from object_detection.utils import ops as utils_ops

if StrictVersion(tf.__version__) < StrictVersion('1.9.0'):
raise ImportError('Please upgrade your TensorFlow installation to v1.9.* or later!')

# This is needed to display the images.
%matplotlib inline

 

from object_detection.utils import label_map_util
from object_detection.utils import visualization_utils as vis_util


import math
import itertools
from itertools import compress
from PIL import Image, ImageDraw


Currently, we are able to load our pre-trained model, we just need to define the PATH_TO_FROZEN_GRAPH, which is the path to our model, and the PATH_TO_LABELS which is the path to the labels.

# Model Name
MODEL_NAME = 'ssd_mobilenet_v2_coco_2018_03_29'

# Path to frozen detection graph. This is the actual model that is used for the object detection.
PATH_TO_FROZEN_GRAPH = "/gdrive/My Drive/Projects/Pedestrian_Detection/models/research/pretrained_model/ssd_mobilenet_v2_coco_2018_03_29/frozen_inference_graph.pb"

# List of the strings that is used to add correct label for each box.
PATH_TO_LABELS = '/gdrive/My Drive/Projects/Pedestrian_Detection/models/research/object_detection/data/mscoco_label_map.pbtxt'

# Load graph
detection_graph = tf.Graph()
with detection_graph.as_default():

od_graph_def = tf.GraphDef()

with tf.gfile.GFile(PATH_TO_FROZEN_GRAPH, 'rb') as fid:

serialized_graph = fid.read()

od_graph_def.ParseFromString(serialized_graph)

tf.import_graph_def(od_graph_def, name='')

 

Label indices are mapped to category names, so that when our convolution network predicts 1, we know that this corresponds to person. Here we use internal utility functions, but anything that returns a dictionary mapping integers to appropriate string labels would be fine.

.

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

 

 

Hold your horses…the most important function!

The function run_inference_for_single_image takes as arguments an image and our model, running the inference for our image. This function returns a dictionary output_dict, which contains the coordinates and the label for each object detected in the image.

def run_inference_for_single_image(image, graph):
with graph.as_default():
with tf.Session() as sess:
# Get handles to input and output tensors
ops = tf.get_default_graph().get_operations()
all_tensor_names = {output.name for op in ops for output in op.outputs}
tensor_dict = {}
for key in [
'num_detections', 'detection_boxes', 'detection_scores',
'detection_classes', 'detection_masks'
]:
tensor_name = key + ':0'
if tensor_name in all_tensor_names:
tensor_dict[key] = tf.get_default_graph().get_tensor_by_name(
tensor_name)
if 'detection_masks' in tensor_dict:
# The following processing is only for single image
detection_boxes = tf.squeeze(tensor_dict['detection_boxes'], [0])
detection_masks = tf.squeeze(tensor_dict['detection_masks'], [0])
# Reframe is required to translate mask from box coordinates to image coordinates and fit the image size.
real_num_detection = tf.cast(tensor_dict['num_detections'][0], tf.int32)
detection_boxes = tf.slice(detection_boxes, [0, 0], [real_num_detection, -1])
detection_masks = tf.slice(detection_masks, [0, 0, 0], [real_num_detection, -1, -1])
detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks(
detection_masks, detection_boxes, image.shape[0], image.shape[1])
detection_masks_reframed = tf.cast(
tf.greater(detection_masks_reframed, 0.5), tf.uint8)
# Follow the convention by adding back the batch dimension
tensor_dict['detection_masks'] = tf.expand_dims(
detection_masks_reframed, 0)
image_tensor = tf.get_default_graph().get_tensor_by_name('image_tensor:0')

 

# Run inference
output_dict = sess.run(tensor_dict,
feed_dict={image_tensor: np.expand_dims(image, 0)})

# all outputs are float32 numpy arrays, so convert types as appropriate
output_dict['num_detections'] = int(output_dict['num_detections'][0])
output_dict['detection_classes'] = output_dict[
'detection_classes'][0].astype(np.uint8)
output_dict['detection_boxes'] = output_dict['detection_boxes'][0]
output_dict['detection_scores'] = output_dict['detection_scores'][0]
if 'detection_masks' in output_dict:
output_dict['detection_masks'] = output_dict['detection_masks'][0]
return output_dict

 

As we said before, our model is going to predict any object contained in the category_index. However, we only want to display a category in particular: person. Therefore, we have created a function to filter our predictions based on a threshold, min_score and the label id, categories. In this case the id for the person label is 1. (we can check this in category_index).

def filter_boxes(min_score, boxes, scores, classes, categories): """Return boxes with a confidence >= `min_score`""" n = len(classes) idxs = [] for i in range(n): if classes[i] in categories and scores[i] >= min_score: idxs.append(i) filtered_boxes = boxes[idxs, ...] filtered_scores = scores[idxs, ...] filtered_classes = classes[idxs, ...] return filtered_boxes, filtered_scores, filtered_classes

 

Measuring the distance between boxes! ?

We already have a model running inferences which returns a dictionary output_dict with the predictions. We want to measure the distance between these predicted objects but this is not a trivial solution. Therefore, we have created some functions to calculate the distance between the centroids of each predicted boxes. These are the steps:

  • Get the coordinates for each object using the function calculate_coord.
  • Calculate the centroid for each box — calculate_centr.

 

  • We should calculate all possible permutations between the centroids using calculate_perm.
  •  Calculate the distance between each centroid (e.g. between person A and person B) with this function: calculate_centr_distance.
  • Finally, we calculate the middle point of each segment for displaying the distance as text in the image — midpoint and calculate_slope.

 

 

 

def calculate_coord(bbox, width, height):
"""Return boxes coordinates""
xmin = bbox[1] * width
ymin = bbox[0] * height
xmax = bbox[3] * width
ymax = bbox[2] * height

return [xmin, ymin, xmax - xmin, ymax - ymin]
 def calculate_centr(coord):
"""Calculate centroid for each box"""
return (coord[0]+(coord[2]/2), coord[1]+(coord[3]/2))

def calculate_centr_distances(centroid_1, centroid_2):
"""Calculate the distance between 2 centroids"""
return  math.sqrt((centroid_2[0]-centroid_1[0])**2 + (centroid_2[1]-centroid_1[1])**2)
def calculate_perm(centroids):
"""Return all combinations of centroids"""
permutations = []
for current_permutation in itertools.permutations(centroids, 2):
if current_permutation[::-1] not in permutations:
permutations.append(current_permutation)
return permutations

def midpoint(p1, p2):
"""Midpoint between 2 points"""
return ((p1[0] + p2[0])/2, (p1[1] + p2[1])/2)

def calculate_slope(x1, y1, x2, y2):
"""Calculate slope"""
m = (y2-y1)/(x2-x1)  
return m

 

Let’s put everything together! 

Now that we have defined these functions, we can create the main function called show_inference which will run the prediction for images and display the boxes and distances between pedestrians.

The first part of the function is responsible for getting the image and running the inference. We will get a dictionary output_dict with the boxes that the model has predicted.

image = Image.open(image_path)

# the array based representation of the image will be used later
image_np = load_image_into_numpy_array(image)

# Expanding dimensions
# Since the model expects images to have shape: [1, None, None, 3]
image_np_expanded = np.expand_dims(image_np, axis=0)

# Actual detection.
output_dict = run_inference_for_single_image(image_np, detection_graph)

 

Then, we will set the confidence_cutoff=0.5 to avoid displaying low accuracy predictions. In parallel, we will get the size of our image and we will need to set a relation “pixel-meter” to calculate the distance correctly. I have checked some images and I considered that width — 150px = 7 meters is a good relation. This part is complicated because we don’t take into account the perspective or the camera angle, it is a difficult problem to solve for all images and I encourage you to improve it and share your solution with us ?.

 

# Get boxes only for person
confidence_cutoff = 0.5

boxes, scores, classes = filter_boxes(confidence_cutoff, output_dict['detection_boxes'], output_dict['detection_scores'], output_dict['detection_classes'], [1])

# Get width and heigth
im = Image.fromarray(image_np)
width, height = im.size

# Pixel per meters - THIS IS A REFERENCE, YOU HAVE TO ADAPT THIS FOR EACH IMAGE
# In this case, we are considering that (width - 150) approximately is 7 meters
average_px_meter = (width-150) / 7

Finally, we can calculate all centroids for our predictions and generate the permutations. Then, we will be able to create the lines dx,dy that connect the centroids and display the distance.

# Calculate normalized coordinates for boxes
centroids = []
coordinates = []
for box in boxes:
coord = calculate_coord(box, width, height)
centr = calculate_centr(coord)
centroids.append(centr)
coordinates.append(coord)

# Calculate all permutations
permutations = calculate_perm(centroids)

# Display boxes and centroids
fig, ax = plt.subplots(figsize = (20,12), dpi = 90)
ax.imshow(image, interpolation='nearest')

for coord, centr in zip(coordinates, centroids):
ax.add_patch(patches.Rectangle((coord[0], coord[1]), coord[2],      coord[3], linewidth=2, edgecolor='y', facecolor='none', zorder=10))
ax.add_patch(patches.Circle((centr[0], centr[1]), 3, color='yellow', zorder=20))

 

# Display lines between centroids
for perm in permutations:
dist = calculate_centr_distances(perm[0], perm[1])
dist_m = dist/average_px_meter

print("M meters: ", dist_m)
middle = midpoint(perm[0], perm[1])
print("Middle point", middle)

x1 = perm[0][0]
x2 = perm[1][0]
y1 = perm[0][1]
y2 = perm[1][1]

slope = calculate_slope(x1, y1, x2, y2)
dy = math.sqrt(3**2/(slope**2+1))
dx = -slope*dy

To sum up, this is the final status of this function.

import matplotlib.pyplot as plt
import matplotlib.patches as patches
from random import randrange

# If you want to test the code with your images, just add path to the images to the TEST_IMAGE_PATHS.
PATH_TO_TEST_IMAGES_DIR = '/gdrive/My Drive/Projects/Pedestrian_Detection/models/research/test_images'TEST_IMAGE_PATHS = [ os.path.join(PATH_TO_TEST_IMAGES_DIR, 'image{}.jpg'.format(i)) for i in range(8, 9) ] 

# Size, in inches, of the output images.IMAGE_SIZE = (12, 8)

def show_inference(image_path):
image = Image.open(image_path)
# the array based representation of the image will be used later in order to prepare the  
# result image with boxes and labels on it.
image_np = load_image_into_numpy_array(image)
# Expand dimensions since the model expects images to have shape: [1, None, None, 3]
image_np_expanded = np.expand_dims(image_np, axis=0)
# Actual detection.
output_dict = run_inference_for_single_image(image_np, detection_graph)
# Get boxes only for person
confidence_cutoff = 0.5
boxes, scores, classes = filter_boxes(confidence_cutoff, 
output_dict['detection_boxes'], output_dict['detection_scores'], output_dict['detection_classes'], [1])

# Get width and heigth
im = Image.fromarray(image_np)
width, height = im.size

# Pixel per meters - THIS IS A REFERENCE, YOU HAVE TO ADAPT THIS FOR EACH IMAGE  
# In this case, we are considering that (width - 150) approximately is 7 meters  
average_px_meter = (width-150) / 7

# Calculate normalized coordinates for boxes
centroids = []
coordinates = []
for box in boxes:
coord = calculate_coord(box, width, height)
 centr = calculate_centr(coord)
centroids.append(centr)
coordinates.append(coord)

# Calculate all permutations
permutations = calculate_perm(centroids)

# Display boxes and centroids
fig, ax = plt.subplots(figsize = (20,12), dpi = 90)
ax.imshow(image, interpolation='nearest')
for coord, centr in zip(coordinates, centroids):
ax.add_patch(patches.Rectangle((coord[0], coord[1]), coord[2], coord[3], linewidth=2, edgecolor='y', facecolor='none', zorder=10))
ax.add_patch(patches.Circle((centr[0], centr[1]), 3, color='yellow', zorder=20))

# Display lines between centroids
for perm in permutations:
dist = calculate_centr_distances(perm[0], perm[1])
dist_m = dist/average_px_meter

print("M meters: ", dist_m)
middle = midpoint(perm[0], perm[1])
print("Middle point", middle)

x1 = perm[0][0]
x2 = perm[1][0]
y1 = perm[0][1]
y2 = perm[1][1]

slope = calculate_slope(x1, y1, x2, y2)
dy = math.sqrt(3**2/(slope**2+1))
dx = -slope*dy

# Display randomly the position of our distance text
if randrange(10) % 2== 0:
Dx = middle[0] - dx*10
Dy = middle[1] - dy*10
else:
Dx = middle[0] + dx*10
Dy = middle[1] + dy*10

if dist_m < 1.5:      
ax.annotate("{}m".format(round(dist_m, 2)), xy=middle, color='white', xytext=(Dx, Dy), fontsize=10, arrowprops=dict(arrowstyle='->', lw=1.5, color='yellow'), bbox=dict(facecolor='red', edgecolor='white', boxstyle='round', pad=0.2), zorder=30)      
ax.plot((perm[0][0], perm[1][0]), (perm[0][1], perm[1][1]), linewidth=2, color='yellow', zorder=15)    elif 1.5 < dist_m < 3.5:      
ax.annotate("{}m".format(round(dist_m, 2)), xy=middle, color='black', xytext=(Dx, Dy), fontsize=8, arrowprops=dict(arrowstyle='->', lw=1.5, color='skyblue'), bbox=dict(facecolor='y', edgecolor='white', boxstyle='round', pad=0.2), zorder=30)      
ax.plot((perm[0][0], perm[1][0]), (perm[0][1], perm[1][1]), linewidth=2, color='skyblue', zorder=15)    
else:      
pass    

# Make prediction
for file in TEST_IMAGE_PATHS:  
show_inference(file)

 

Come on!!…Let’s run some examples!

After all this work, we are able to generate some example images. We just need to add our images to this folder: ../Projects/Pedestrian_Detection/models/research/test_images

Wow! It looks pretty good but it would be even cooler if we could run this in videos. So, let’s go!

 

Inference in Videos

The code for running the model in videos is the same as for images because we use openCV to split the video in frames and we process each frame as individual images.

import cv2
import matplotlibfrom matplotlib import pyplot as plt
plt.ioff()
matplotlib.use('Agg') 

FILE_OUTPUT = '/gdrive/My Drive/Projects/Pedestrian_Detection/models/research/test_images/Rail_Station_Predicted2.mp4'

# Playing video from file
cap = cv2.VideoCapture('/gdrive/My Drive/Projects/Pedestrian_Detection/models/research/test_images/Rail_Station_Converted.mp4')

# Default resolutions of the frame are obtained.The default resolutions are system dependent.

# We convert the resolutions from float to integer.
width = int(cap.get(3))
height = int(cap.get(4)) 

dim = (width, height)
print(dim) 

tope = 10
i = 0
new = True
with detection_graph.as_default():
      with tf.Session(graph=detection_graph) as sess:
      # Definite input and output Tensors for detection_graph
image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')

# Each box represents a part of the image where a particular object was detected.
      detection_boxes =
detection_graph.get_tensor_by_name('detection_boxes:0')

# Each score represent how level of confidence for each of the objects.
# Score is shown on the result image, together with the class label.
      detection_scores = 
detection_graph.get_tensor_by_name('detection_scores:0')
       detection_classes = 
detection_graph.get_tensor_by_name('detection_classes:0')
       num_detections = 
detection_graph.get_tensor_by_name('num_detections:0')

i = 0        
while(cap.isOpened()):
      # Capture frame-by-frame
      ret, frame = cap.read()

      if ret == True:
         # Correct color
         frame = gray = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

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

# Actual detection.              
(boxes, scores, classes, num) = sess.run(                  
      [detection_boxes, detection_scores, detection_classes, num_detections],
       feed_dict={image_tensor: image_np_expanded})

# Filter boxes
confidence_cutoff = 0.5
boxes, scores, classes = filter_boxes(confidence_cutoff, np.squeeze(boxes), np.squeeze(scores), np.squeeze(classes), [1])

 # Calculate normalized coordinates for boxes
centroids = []
coordinates = []
for box in boxes:
   coord = calculate_coord(box, width, height)
   centr = calculate_centr(coord)
   centroids.append(centr) 
   coordinates.append(coord)

# Pixel per meters
average_px_meter = (width-150) / 7

permutations = calculate_perm(centroids)

# Display boxes and centroids 
fig, ax = plt.subplots(figsize = (20,12), dpi = 90, frameon=False) 
ax = fig.add_axes([0, 0, 1, 1]) 
ax.axis('off')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.get_xaxis().set_ticks([]) 
ax.get_yaxis().set_ticks([])
for coord, centr in zip(coordinates, centroids):
  ax.add_patch(patches.Rectangle((coord[0], coord[1]), coord[2], coord[3], linewidth=2, edgecolor='y', facecolor='none', zorder=10))
ax.add_patch(patches.Circle((centr[0], centr[1]), 3, color='yellow', zorder=20))

# Display lines between centroids
for perm in permutations:
  dist = calculate_centr_distances(perm[0], perm[1])
  dist_m = dist/average_px_meter

  x1 = perm[0][0]
  y1 = perm[0][1]
  x2 = perm[1][0]
  y2 = perm[1][1]

# Calculate middle point
middle = midpoint(perm[0], perm[1])

# Calculate slope
slope = calculate_slope(x1, y1, x2, y2)
dy = math.sqrt(3**2/(slope**2+1))
dx = -slope*dy

# Set random location
if randrange(10) % 2== 0:
  Dx = middle[0] - dx*10
  Dy = middle[1] - dy*10
else:
  Dx = middle[0] + dx*10
  Dy = middle[1] + dy*10

if dist_m < 1.5:
  ax.annotate("{}m".format(round(dist_m, 2)), xy=middle, color='white', xytext=(Dx, Dy), fontsize=10, arrowprops=dict(arrowstyle='->', lw=1.5, color='yellow'), bbox=dict(facecolor='red', edgecolor='white', boxstyle='round', pad=0.2), zorder=35)
ax.plot((perm[0][0], perm[1][0]), (perm[0][1], perm[1][1]), linewidth=2, color='yellow', zorder=15)

elif 1.5 < dist_m < 3.5:
  ax.annotate("{}m".format(round(dist_m, 2)), xy=middle, color='black', xytext=(Dx, Dy), fontsize=8, arrowprops=dict(arrowstyle='->', lw=1.5, color='skyblue'), bbox=dict(facecolor='y', edgecolor='white', boxstyle='round', pad=0.2), zorder=35)
  ax.plot((perm[0][0], perm[1][0]), (perm[0][1], perm[1][1]), linewidth=2, color='skyblue', zorder=15)
  else:
    pass
ax.imshow(frame, interpolation='nearest')

# This allows you to save each frame in a folder
#fig.savefig("/gdrive/My Drive/Projects/Pedestrian_Detection/models/research/test_images/TEST_{}.png".format(i))
# i += 1

# Convert figure to numpy
fig.canvas.draw()

img = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
img  = img.reshape(fig.canvas.get_width_height()[::-1] + (3,))
img = np.array(fig.canvas.get_renderer()._renderer)
img = cv2.cvtColor(img,cv2.COLOR_RGB2BGR)

if new:
print("Define out")
out = cv2.VideoWriter(FILE_OUTPUT, cv2.VideoWriter_fourcc(*'MP4V'), 20.0, (img.shape[1], img.shape[0]))
new = False

out.write(img)
else:
break

# When everything done, release the video capture and video write objects
cap.release()
out.release()

# Closes all the frames
cv2.destroyAllWindows()

As we did before, we just need to copy our video
into ../Projects/Pedestrian_Detection/models/research/test_images and update the path in cap =
cv2.VideoCapture(...). Additionally, we can set a name for the FILE_OUTPUT.

Great Job!! The code is now ready for predicting and measuring social distance.

We have developed this application because at Immune Technology Institute we try to apply the most advanced technology. We enjoy sharing knowledge since we consider that it is when it becomes powerful.

If you want to learn how to develop real-world applications such as this application for measuring “social distance”, you could be interested in our Master in Data Science. It is a program aimed at professionals that seek to specialize in Data Science, know the main Artificial Intelligence techniques and how to apply them into different industries.

If you are interested about what we do and how we do, join us to this live session. Feel free to take our code and improve it. Share the results with us! ?

 

 

 

This article and code have been written by: Alejandro Diaz Santos— (LinkedIn, GitHub)

Relacionadas

¿QUÉ ES Y CUÁL ES EL FUTURO DEL RANSOMWARE?
Sin categorizar
10/12/2019

¿QUÉ ES Y CUÁL ES EL FUTURO DEL RANSOMWARE?

Aunque parezca sorprendente, el concepto de ransomware no es nuevo. De hecho, las primeras ideas al respecto se remontan a finales de los 80 , aunque la primera propuesta completa fue hecha por ADAM L. Young y MOTI Yung

LOS PERFILES PROFESIONALES TECNOLÓGICOS MÁS DEMANDADOS EN 2019
Sin categorizar
16/01/2019

LOS PERFILES PROFESIONALES TECNOLÓGICOS MÁS DEMANDADOS EN 2019

En este 2019, donde la tecnología 5G empieza a dar sus primeros pasos y el Internet Of Things está un paso más cerca de hacerse realidad, las empresas necesitan nuevos perfiles tecnológicos con los que adaptarse a los cambios.

Midiendo la distancia social en tiempos del Covid-19
Sin categorizar
20/07/2020

Midiendo la distancia social en tiempos del Covid-19

LA AUSENCIA DE TALENTO EN CIBERSEGURIDAD
Sin categorizar
03/05/2019

LA AUSENCIA DE TALENTO EN CIBERSEGURIDAD

En el primer Impactful Tech, el ciclo de conferencias y debates puesto en marcha por IMMUNE Coding Institute, se dieron cita un total de cuatro expertos en materia de ciberseguridad para analizar los problemas que presenta esta disciplina a nivel nacional e internacional.