Skip to content

Commit

Permalink
make it pythonic
Browse files Browse the repository at this point in the history
  • Loading branch information
gustavz committed May 29, 2018
1 parent 6575dd7 commit aaa64a2
Show file tree
Hide file tree
Showing 68 changed files with 1,121 additions and 476 deletions.
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ Results in up to x10 performance increase depending on the running system <br />


## Inference:
- create a copy of `config.sample.yml` called `config.yml`
- optional: Change Parameters in `config.yml` to load other models or to modify configurations.<br />
For example: If you are not interested in visualization: set `visualize` to `False`, <br />
or if you want to switch off the speed hack set `split_model` to `False`, <br />
- to be able to use KCF_Tracking run `build_kcf.sh` to build it and set `use_tracker` to `true` to use it <br />
(currently only works for pure object detection models without `split_model`)
- Change Inference Configurations inside `rod/config.py` according to your needs
For example: If you are not interested in visualization: set `VISUALIZE` to `False`, <br />
or if you want to switch off the speed hack set `SPLIT_MODEL` to `False`, <br />
- to be able to use KCF_Tracking inside `scripts/` run `bash build_kcf.sh` to build it and set `USE_TRACKER` to `True` to use it <br />
(currently only works for pure object detection models without `SPLIT_MODEL`)
- for realtime inference using video stream run: `run_objectdetection.py` or `run_deeplab.py`
- for benchmark tests on sample images run: `test_objectdetection.py`or `test_deeplab.py` <br />
(put them as `.jpg` into `test_images/`)
(put them as `.jpg` into `test_images/`. timeline results will appear in `test_results/`)
- Enjoy!


Expand Down
2 changes: 0 additions & 2 deletions build_kcf.sh

This file was deleted.

41 changes: 0 additions & 41 deletions config.sample.yml

This file was deleted.

File renamed without changes.
69 changes: 69 additions & 0 deletions rod/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
@author: www.github.com/GustavZ
"""
import numpy as np

class Config(object):
"""
Inference Configuration class
Replaces 'config.sample.yml' of v1.0
"""
### Inference Config
VIDEO_INPUT = 0 # Input Must be OpenCV readable
VISUALIZE = True # Disable for performance increase


### Testing
IMAGE_PATH = 'test_images' # path for test.py test_images
LIMIT_IMAGES = None # if set to None, all images are used
CPU_ONLY = False # CPU Placement for speed test
WRITE_TIMELINE = True # write json timeline file (slows infrence)


### Object_Detection
WIDTH = 600 # OpenCV only supports 4:3 formats others will be converted
HEIGHT = 600 # 600x600 leads to 640x480
MAX_FRAMES = 5000 # only used if visualize==False
FPS_INTERVAL = 5 # Interval [s] to print fps of the last interval in console
DET_INTERVAL = 500 # intervall [frames] to print detections to console
DET_TH = 0.5 # detection threshold for det_intervall
## speed hack
SPLIT_MODEL = True # Splits Model into a GPU and CPU session (currently only works for ssd_mobilenets)
SSD_SHAPE = 300 # used for the split model algorithm (currently only supports ssd networks trained on 300x300 and 600x600 input)
## Tracking
USE_TRACKER = False # Use a Tracker (currently only works properly WITHOUT split_model)
TRACKER_FRAMES = 20 # Number of tracked frames between detections
NUM_TRACKERS = 5 # Max number of objects to track
## Model
OD_MODEL_NAME = 'ssd_mobilenet_v11_coco'
OD_MODEL_PATH = 'models/ssd_mobilenet_v11_coco/frozen_inference_graph.pb'
LABEL_PATH = 'rod/data/mscoco_label_map.pbtxt'
NUM_CLASSES = 90


### DeepLab
ALPHA = 0.3 # mask overlay factor
BBOX = True # compute boundingbox in postprocessing
MINAREA = 500 # min Pixel Area to apply bounding boxes (avoid noise)
## Model
DL_MODEL_NAME = 'deeplabv3_mnv2_pascal_train_aug_2018_01_29'
DL_MODEL_PATH = 'models/deeplabv3_mnv2_pascal_train_aug/frozen_inference_graph.pb'
LABEL_NAMES = np.asarray([
'background', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus',
'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike',
'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tv'])


def __init__(self):
## TimeLine File naming
if self.CPU_ONLY:
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
self.DEVICE = '_CPU'
else:
self.DEVICE = '_GPU'
if self.SPLIT_MODEL:
self.SM = '_SM'
else:
self.SM = ''
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
"""
import tensorflow as tf

from stuff.object_detection.core import box_list
from stuff.object_detection.utils import shape_utils
from rod.core import box_list
from rod.utils import shape_utils


class SortOrder(object):
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
185 changes: 11 additions & 174 deletions stuff/helper.py → rod/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,189 +3,26 @@
"""
Created on Fri Dec 22 11:53:52 2017
@author: GustavZ
@author: www.github.com/GustavZ
"""
import datetime
import cv2
import threading
import time
import numpy as np
import tensorflow as tf
import tarfile
import copy
import os
import json
import six.moves.urllib as urllib
from tensorflow.core.framework import graph_pb2

import sys
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
if PY2:
if sys.version_info[0] == 2:
import Queue
elif PY3:
elif sys.version_info[0] == 3:
import queue as Queue

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




class Model:
"""
Model Class to handle all kind of detection preparation
"""
def __init__(self, type, model_name, model_path, label_path=None, num_classes=90, split_model=False, ssd_shape=300 ):
assert type in ['od','dl'], "only deeplab or object_detection models"
assert ssd_shape in [300,600], "only ssd_mobilenet models of shape 300x300 or 600x600 supported"
self.type = type
self.model_name = model_name
self.model_path = model_path
self.split_model = split_model
self.label_path = label_path
self.num_classes = num_classes
self.ssd_shape = ssd_shape
self.detection_graph = tf.Graph()
self.category_index = None
self.score = None
self.expand = None

def download_model(self):
if self.type == 'dl':
download_base = 'http://download.tensorflow.org/models/'
elif self.type == 'od':
download_base = 'http://download.tensorflow.org/models/object_detection/'
model_file = self.model_name + '.tar.gz'
if not os.path.isfile(self.model_path):
print('> Model not found. Downloading it now.')
opener = urllib.request.URLopener()
opener.retrieve(download_base + model_file, model_file)
tar_file = tarfile.open(model_file)
for file in tar_file.getmembers():
file_name = os.path.basename(file.name)
if 'frozen_inference_graph.pb' in file_name:
tar_file.extract(file, os.getcwd() + '/models/')
os.remove(os.getcwd() + '/' + model_file)
else:
print('> Model found. Proceed.')

def _node_name(self,n):
if n.startswith("^"):
return n[1:]
else:
return n.split(":")[0]

def load_frozenmodel(self):
print('> Loading frozen model into memory')
if (self.type == 'od' and self.split_model):
# load a frozen Model and split it into GPU and CPU graphs
# Hardcoded split points for ssd_mobilenet
split_nodes = ['Postprocessor/convert_scores','Postprocessor/ExpandDims_1']
input_graph = tf.Graph()
with tf.Session(graph=input_graph):
if self.ssd_shape == 600:
shape = 7326
else:
shape = 1917
self.score = tf.placeholder(tf.float32, shape=(None, shape, self.num_classes), name=split_nodes[0])
self.expand = tf.placeholder(tf.float32, shape=(None, shape, 1, 4), name=split_nodes[1])
for node in input_graph.as_graph_def().node:
if node.name == split_nodes[0]:
score_def = node
if node.name == split_nodes[1]:
expand_def = node

with self.detection_graph.as_default():
od_graph_def = tf.GraphDef()
with tf.gfile.GFile(self.model_path, 'rb') as fid:
serialized_graph = fid.read()
od_graph_def.ParseFromString(serialized_graph)

edges = {}
name_to_node_map = {}
node_seq = {}
seq = 0
for node in od_graph_def.node:
n = self._node_name(node.name)
name_to_node_map[n] = node
edges[n] = [self._node_name(x) for x in node.input]
node_seq[n] = seq
seq += 1
for d in split_nodes:
assert d in name_to_node_map, "%s is not in graph" % d

nodes_to_keep = set()
next_to_visit = split_nodes[:]

while next_to_visit:
n = next_to_visit[0]
del next_to_visit[0]
if n in nodes_to_keep: continue
nodes_to_keep.add(n)
next_to_visit += edges[n]

nodes_to_keep_list = sorted(list(nodes_to_keep), key=lambda n: node_seq[n])
nodes_to_remove = set()

for n in node_seq:
if n in nodes_to_keep_list: continue
nodes_to_remove.add(n)
nodes_to_remove_list = sorted(list(nodes_to_remove), key=lambda n: node_seq[n])

keep = graph_pb2.GraphDef()
for n in nodes_to_keep_list:
keep.node.extend([copy.deepcopy(name_to_node_map[n])])

remove = graph_pb2.GraphDef()
remove.node.extend([score_def])
remove.node.extend([expand_def])
for n in nodes_to_remove_list:
remove.node.extend([copy.deepcopy(name_to_node_map[n])])

with tf.device('/gpu:0'):
tf.import_graph_def(keep, name='')
with tf.device('/cpu:0'):
tf.import_graph_def(remove, name='')
else:
# default model loading procedure
with self.detection_graph.as_default():
od_graph_def = tf.GraphDef()
with tf.gfile.GFile(self.model_path, 'rb') as fid:
serialized_graph = fid.read()
od_graph_def.ParseFromString(serialized_graph)
tf.import_graph_def(od_graph_def, name='')

def load_labelmap(self):
print('> Loading label map')
label_map = label_map_util.load_labelmap(self.label_path)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=self.num_classes, use_display_name=True)
self.category_index = label_map_util.create_category_index(categories)

def get_tensordict(self, outputs):
ops = self.detection_graph.get_operations()
all_tensor_names = {output.name for op in ops for output in op.outputs}
self.tensor_dict = {}
for key in outputs:
tensor_name = key + ':0'
if tensor_name in all_tensor_names:
self.tensor_dict[key] = self.detection_graph.get_tensor_by_name(tensor_name)
return self.tensor_dict

def prepare_od_model(self):
self.download_model()
self.load_frozenmodel()
self.load_labelmap()
return self

def prepare_dl_model(self):
self.download_model()
self.load_frozenmodel()
return self

from utils import visualization_utils as vis_util


class FPS:
class FPS(object):
"""
Class for FPS calculation
"""
Expand Down Expand Up @@ -234,7 +71,7 @@ def fps_local(self):
return 0.0


class Timer:
class Timer(object):
"""
Timer class for benchmark test purposes
"""
Expand Down Expand Up @@ -287,7 +124,7 @@ def stop(self):
print ("> [INFO] resulting median fps: {}".format(self._medianfps))


class WebcamVideoStream:
class WebcamVideoStream(object):
"""
Class for Video Input frame capture
Based on OpenCV VideoCapture
Expand Down Expand Up @@ -371,7 +208,7 @@ def vis_text(image, string, pos):
cv2.putText(image,string,(pos),
cv2.FONT_HERSHEY_SIMPLEX, 0.75, (77, 255, 9), 2)

def vis_detection(image, visualize, boxes, classes, scores, masks, category_index, det_interval, det_th, max_frames, fps=None):
def vis_detection(image, boxes, classes, scores, masks, category_index, fps=None, visualize=False, det_interval=5, det_th=0.5, max_frames=500):
if visualize:
vis_util.visualize_boxes_and_labels_on_image_array(
image,
Expand Down Expand Up @@ -450,7 +287,7 @@ def conv_track2detect(box, width, height):
return newbox


class SessionWorker():
class SessionWorker(object):
"""
TensorFlow Session Thread for split_model spead Hack
from https://github.com/naisy/realtime_object_detection/blob/master/lib/session_worker.py
Expand Down Expand Up @@ -535,7 +372,7 @@ def stop(self):
self.sess_queue.task_done()
return

class TimeLiner:
class TimeLiner(object):
"""
TimeLiner Class for creating multiple session json timing files
"""
Expand All @@ -559,7 +396,7 @@ def save(self, f_name):
json.dump(self._timeline_dict, f)


class RosDetectionPublisher:
class RosDetectionPublisher(object):
"""
Class for publishing Ros messages
Not yet used
Expand Down
Binary file added rod/kcf/KCF.so
Binary file not shown.
File renamed without changes.
File renamed without changes.
Binary file added rod/kcf/build/temp.linux-x86_64-2.7/python/KCF.o
Binary file not shown.
Binary file added rod/kcf/build/temp.linux-x86_64-2.7/python/cvt.o
Binary file not shown.
Binary file added rod/kcf/build/temp.linux-x86_64-2.7/src/fhog.o
Binary file not shown.
Binary file not shown.
Binary file added rod/kcf/cvt.so
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit aaa64a2

Please sign in to comment.