myshafazil commited on
Commit
0e4be7b
·
verified ·
1 Parent(s): 5f39b58

Upload 8 files

Browse files
deep_sort/utils/__init__.py ADDED
File without changes
deep_sort/utils/asserts.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from os import environ
2
+
3
+
4
+ def assert_in(file, files_to_check):
5
+ if file not in files_to_check:
6
+ raise AssertionError("{} does not exist in the list".format(str(file)))
7
+ return True
8
+
9
+
10
+ def assert_in_env(check_list: list):
11
+ for item in check_list:
12
+ assert_in(item, environ.keys())
13
+ return True
deep_sort/utils/draw.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+
4
+ palette = (2 ** 11 - 1, 2 ** 15 - 1, 2 ** 20 - 1)
5
+
6
+
7
+ def compute_color_for_labels(label):
8
+ """
9
+ Simple function that adds fixed color depending on the class
10
+ """
11
+ color = [int((p * (label ** 2 - label + 1)) % 255) for p in palette]
12
+ return tuple(color)
13
+
14
+
15
+ def draw_boxes(img, bbox, identities=None, offset=(0,0)):
16
+ for i,box in enumerate(bbox):
17
+ x1,y1,x2,y2 = [int(i) for i in box]
18
+ x1 += offset[0]
19
+ x2 += offset[0]
20
+ y1 += offset[1]
21
+ y2 += offset[1]
22
+ # box text and bar
23
+ id = int(identities[i]) if identities is not None else 0
24
+ color = compute_color_for_labels(id)
25
+ label = '{}{:d}'.format("", id)
26
+ t_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_PLAIN, 2 , 2)[0]
27
+ cv2.rectangle(img,(x1, y1),(x2,y2),color,3)
28
+ cv2.rectangle(img,(x1, y1),(x1+t_size[0]+3,y1+t_size[1]+4), color,-1)
29
+ cv2.putText(img,label,(x1,y1+t_size[1]+4), cv2.FONT_HERSHEY_PLAIN, 2, [255,255,255], 2)
30
+ return img
31
+
32
+
33
+
34
+ if __name__ == '__main__':
35
+ for i in range(82):
36
+ print(compute_color_for_labels(i))
deep_sort/utils/evaluation.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import copy
4
+ import motmetrics as mm
5
+ mm.lap.default_solver = 'lap'
6
+ from utils.io import read_results, unzip_objs
7
+
8
+
9
+ class Evaluator(object):
10
+
11
+ def __init__(self, data_root, seq_name, data_type):
12
+ self.data_root = data_root
13
+ self.seq_name = seq_name
14
+ self.data_type = data_type
15
+
16
+ self.load_annotations()
17
+ self.reset_accumulator()
18
+
19
+ def load_annotations(self):
20
+ assert self.data_type == 'mot'
21
+
22
+ gt_filename = os.path.join(self.data_root, self.seq_name, 'gt', 'gt.txt')
23
+ self.gt_frame_dict = read_results(gt_filename, self.data_type, is_gt=True)
24
+ self.gt_ignore_frame_dict = read_results(gt_filename, self.data_type, is_ignore=True)
25
+
26
+ def reset_accumulator(self):
27
+ self.acc = mm.MOTAccumulator(auto_id=True)
28
+
29
+ def eval_frame(self, frame_id, trk_tlwhs, trk_ids, rtn_events=False):
30
+ # results
31
+ trk_tlwhs = np.copy(trk_tlwhs)
32
+ trk_ids = np.copy(trk_ids)
33
+
34
+ # gts
35
+ gt_objs = self.gt_frame_dict.get(frame_id, [])
36
+ gt_tlwhs, gt_ids = unzip_objs(gt_objs)[:2]
37
+
38
+ # ignore boxes
39
+ ignore_objs = self.gt_ignore_frame_dict.get(frame_id, [])
40
+ ignore_tlwhs = unzip_objs(ignore_objs)[0]
41
+
42
+
43
+ # remove ignored results
44
+ keep = np.ones(len(trk_tlwhs), dtype=bool)
45
+ iou_distance = mm.distances.iou_matrix(ignore_tlwhs, trk_tlwhs, max_iou=0.5)
46
+ if len(iou_distance) > 0:
47
+ match_is, match_js = mm.lap.linear_sum_assignment(iou_distance)
48
+ match_is, match_js = map(lambda a: np.asarray(a, dtype=int), [match_is, match_js])
49
+ match_ious = iou_distance[match_is, match_js]
50
+
51
+ match_js = np.asarray(match_js, dtype=int)
52
+ match_js = match_js[np.logical_not(np.isnan(match_ious))]
53
+ keep[match_js] = False
54
+ trk_tlwhs = trk_tlwhs[keep]
55
+ trk_ids = trk_ids[keep]
56
+
57
+ # get distance matrix
58
+ iou_distance = mm.distances.iou_matrix(gt_tlwhs, trk_tlwhs, max_iou=0.5)
59
+
60
+ # acc
61
+ self.acc.update(gt_ids, trk_ids, iou_distance)
62
+
63
+ if rtn_events and iou_distance.size > 0 and hasattr(self.acc, 'last_mot_events'):
64
+ events = self.acc.last_mot_events # only supported by https://github.com/longcw/py-motmetrics
65
+ else:
66
+ events = None
67
+ return events
68
+
69
+ def eval_file(self, filename):
70
+ self.reset_accumulator()
71
+
72
+ result_frame_dict = read_results(filename, self.data_type, is_gt=False)
73
+ frames = sorted(list(set(self.gt_frame_dict.keys()) | set(result_frame_dict.keys())))
74
+ for frame_id in frames:
75
+ trk_objs = result_frame_dict.get(frame_id, [])
76
+ trk_tlwhs, trk_ids = unzip_objs(trk_objs)[:2]
77
+ self.eval_frame(frame_id, trk_tlwhs, trk_ids, rtn_events=False)
78
+
79
+ return self.acc
80
+
81
+ @staticmethod
82
+ def get_summary(accs, names, metrics=('mota', 'num_switches', 'idp', 'idr', 'idf1', 'precision', 'recall')):
83
+ names = copy.deepcopy(names)
84
+ if metrics is None:
85
+ metrics = mm.metrics.motchallenge_metrics
86
+ metrics = copy.deepcopy(metrics)
87
+
88
+ mh = mm.metrics.create()
89
+ summary = mh.compute_many(
90
+ accs,
91
+ metrics=metrics,
92
+ names=names,
93
+ generate_overall=True
94
+ )
95
+
96
+ return summary
97
+
98
+ @staticmethod
99
+ def save_summary(summary, filename):
100
+ import pandas as pd
101
+ writer = pd.ExcelWriter(filename)
102
+ summary.to_excel(writer)
103
+ writer.save()
deep_sort/utils/io.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import Dict
3
+ import numpy as np
4
+
5
+ # from utils.log import get_logger
6
+
7
+
8
+ def write_results(filename, results, data_type):
9
+ if data_type == 'mot':
10
+ save_format = '{frame},{id},{x1},{y1},{w},{h},-1,-1,-1,-1\n'
11
+ elif data_type == 'kitti':
12
+ save_format = '{frame} {id} pedestrian 0 0 -10 {x1} {y1} {x2} {y2} -10 -10 -10 -1000 -1000 -1000 -10\n'
13
+ else:
14
+ raise ValueError(data_type)
15
+
16
+ with open(filename, 'w') as f:
17
+ for frame_id, tlwhs, track_ids in results:
18
+ if data_type == 'kitti':
19
+ frame_id -= 1
20
+ for tlwh, track_id in zip(tlwhs, track_ids):
21
+ if track_id < 0:
22
+ continue
23
+ x1, y1, w, h = tlwh
24
+ x2, y2 = x1 + w, y1 + h
25
+ line = save_format.format(frame=frame_id, id=track_id, x1=x1, y1=y1, x2=x2, y2=y2, w=w, h=h)
26
+ f.write(line)
27
+
28
+
29
+ # def write_results(filename, results_dict: Dict, data_type: str):
30
+ # if not filename:
31
+ # return
32
+ # path = os.path.dirname(filename)
33
+ # if not os.path.exists(path):
34
+ # os.makedirs(path)
35
+
36
+ # if data_type in ('mot', 'mcmot', 'lab'):
37
+ # save_format = '{frame},{id},{x1},{y1},{w},{h},1,-1,-1,-1\n'
38
+ # elif data_type == 'kitti':
39
+ # save_format = '{frame} {id} pedestrian -1 -1 -10 {x1} {y1} {x2} {y2} -1 -1 -1 -1000 -1000 -1000 -10 {score}\n'
40
+ # else:
41
+ # raise ValueError(data_type)
42
+
43
+ # with open(filename, 'w') as f:
44
+ # for frame_id, frame_data in results_dict.items():
45
+ # if data_type == 'kitti':
46
+ # frame_id -= 1
47
+ # for tlwh, track_id in frame_data:
48
+ # if track_id < 0:
49
+ # continue
50
+ # x1, y1, w, h = tlwh
51
+ # x2, y2 = x1 + w, y1 + h
52
+ # line = save_format.format(frame=frame_id, id=track_id, x1=x1, y1=y1, x2=x2, y2=y2, w=w, h=h, score=1.0)
53
+ # f.write(line)
54
+ # logger.info('Save results to {}'.format(filename))
55
+
56
+
57
+ def read_results(filename, data_type: str, is_gt=False, is_ignore=False):
58
+ if data_type in ('mot', 'lab'):
59
+ read_fun = read_mot_results
60
+ else:
61
+ raise ValueError('Unknown data type: {}'.format(data_type))
62
+
63
+ return read_fun(filename, is_gt, is_ignore)
64
+
65
+
66
+ """
67
+ labels={'ped', ... % 1
68
+ 'person_on_vhcl', ... % 2
69
+ 'car', ... % 3
70
+ 'bicycle', ... % 4
71
+ 'mbike', ... % 5
72
+ 'non_mot_vhcl', ... % 6
73
+ 'static_person', ... % 7
74
+ 'distractor', ... % 8
75
+ 'occluder', ... % 9
76
+ 'occluder_on_grnd', ... %10
77
+ 'occluder_full', ... % 11
78
+ 'reflection', ... % 12
79
+ 'crowd' ... % 13
80
+ };
81
+ """
82
+
83
+
84
+ def read_mot_results(filename, is_gt, is_ignore):
85
+ valid_labels = {1}
86
+ ignore_labels = {2, 7, 8, 12}
87
+ results_dict = dict()
88
+ if os.path.isfile(filename):
89
+ with open(filename, 'r') as f:
90
+ for line in f.readlines():
91
+ linelist = line.split(',')
92
+ if len(linelist) < 7:
93
+ continue
94
+ fid = int(linelist[0])
95
+ if fid < 1:
96
+ continue
97
+ results_dict.setdefault(fid, list())
98
+
99
+ if is_gt:
100
+ if 'MOT16-' in filename or 'MOT17-' in filename:
101
+ label = int(float(linelist[7]))
102
+ mark = int(float(linelist[6]))
103
+ if mark == 0 or label not in valid_labels:
104
+ continue
105
+ score = 1
106
+ elif is_ignore:
107
+ if 'MOT16-' in filename or 'MOT17-' in filename:
108
+ label = int(float(linelist[7]))
109
+ vis_ratio = float(linelist[8])
110
+ if label not in ignore_labels and vis_ratio >= 0:
111
+ continue
112
+ else:
113
+ continue
114
+ score = 1
115
+ else:
116
+ score = float(linelist[6])
117
+
118
+ tlwh = tuple(map(float, linelist[2:6]))
119
+ target_id = int(linelist[1])
120
+
121
+ results_dict[fid].append((tlwh, target_id, score))
122
+
123
+ return results_dict
124
+
125
+
126
+ def unzip_objs(objs):
127
+ if len(objs) > 0:
128
+ tlwhs, ids, scores = zip(*objs)
129
+ else:
130
+ tlwhs, ids, scores = [], [], []
131
+ tlwhs = np.asarray(tlwhs, dtype=float).reshape(-1, 4)
132
+
133
+ return tlwhs, ids, scores
deep_sort/utils/json_logger.py ADDED
@@ -0,0 +1,383 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ References:
3
+ https://medium.com/analytics-vidhya/creating-a-custom-logging-mechanism-for-real-time-object-detection-using-tdd-4ca2cfcd0a2f
4
+ """
5
+ import json
6
+ from os import makedirs
7
+ from os.path import exists, join
8
+ from datetime import datetime
9
+
10
+
11
+ class JsonMeta(object):
12
+ HOURS = 3
13
+ MINUTES = 59
14
+ SECONDS = 59
15
+ PATH_TO_SAVE = 'LOGS'
16
+ DEFAULT_FILE_NAME = 'remaining'
17
+
18
+
19
+ class BaseJsonLogger(object):
20
+ """
21
+ This is the base class that returns __dict__ of its own
22
+ it also returns the dicts of objects in the attributes that are list instances
23
+
24
+ """
25
+
26
+ def dic(self):
27
+ # returns dicts of objects
28
+ out = {}
29
+ for k, v in self.__dict__.items():
30
+ if hasattr(v, 'dic'):
31
+ out[k] = v.dic()
32
+ elif isinstance(v, list):
33
+ out[k] = self.list(v)
34
+ else:
35
+ out[k] = v
36
+ return out
37
+
38
+ @staticmethod
39
+ def list(values):
40
+ # applies the dic method on items in the list
41
+ return [v.dic() if hasattr(v, 'dic') else v for v in values]
42
+
43
+
44
+ class Label(BaseJsonLogger):
45
+ """
46
+ For each bounding box there are various categories with confidences. Label class keeps track of that information.
47
+ """
48
+
49
+ def __init__(self, category: str, confidence: float):
50
+ self.category = category
51
+ self.confidence = confidence
52
+
53
+
54
+ class Bbox(BaseJsonLogger):
55
+ """
56
+ This module stores the information for each frame and use them in JsonParser
57
+ Attributes:
58
+ labels (list): List of label module.
59
+ top (int):
60
+ left (int):
61
+ width (int):
62
+ height (int):
63
+
64
+ Args:
65
+ bbox_id (float):
66
+ top (int):
67
+ left (int):
68
+ width (int):
69
+ height (int):
70
+
71
+ References:
72
+ Check Label module for better understanding.
73
+
74
+
75
+ """
76
+
77
+ def __init__(self, bbox_id, top, left, width, height):
78
+ self.labels = []
79
+ self.bbox_id = bbox_id
80
+ self.top = top
81
+ self.left = left
82
+ self.width = width
83
+ self.height = height
84
+
85
+ def add_label(self, category, confidence):
86
+ # adds category and confidence only if top_k is not exceeded.
87
+ self.labels.append(Label(category, confidence))
88
+
89
+ def labels_full(self, value):
90
+ return len(self.labels) == value
91
+
92
+
93
+ class Frame(BaseJsonLogger):
94
+ """
95
+ This module stores the information for each frame and use them in JsonParser
96
+ Attributes:
97
+ timestamp (float): The elapsed time of captured frame
98
+ frame_id (int): The frame number of the captured video
99
+ bboxes (list of Bbox objects): Stores the list of bbox objects.
100
+
101
+ References:
102
+ Check Bbox class for better information
103
+
104
+ Args:
105
+ timestamp (float):
106
+ frame_id (int):
107
+
108
+ """
109
+
110
+ def __init__(self, frame_id: int, timestamp: float = None):
111
+ self.frame_id = frame_id
112
+ self.timestamp = timestamp
113
+ self.bboxes = []
114
+
115
+ def add_bbox(self, bbox_id: int, top: int, left: int, width: int, height: int):
116
+ bboxes_ids = [bbox.bbox_id for bbox in self.bboxes]
117
+ if bbox_id not in bboxes_ids:
118
+ self.bboxes.append(Bbox(bbox_id, top, left, width, height))
119
+ else:
120
+ raise ValueError("Frame with id: {} already has a Bbox with id: {}".format(self.frame_id, bbox_id))
121
+
122
+ def add_label_to_bbox(self, bbox_id: int, category: str, confidence: float):
123
+ bboxes = {bbox.id: bbox for bbox in self.bboxes}
124
+ if bbox_id in bboxes.keys():
125
+ res = bboxes.get(bbox_id)
126
+ res.add_label(category, confidence)
127
+ else:
128
+ raise ValueError('the bbox with id: {} does not exists!'.format(bbox_id))
129
+
130
+
131
+ class BboxToJsonLogger(BaseJsonLogger):
132
+ """
133
+ ُ This module is designed to automate the task of logging jsons. An example json is used
134
+ to show the contents of json file shortly
135
+ Example:
136
+ {
137
+ "video_details": {
138
+ "frame_width": 1920,
139
+ "frame_height": 1080,
140
+ "frame_rate": 20,
141
+ "video_name": "/home/gpu/codes/MSD/pedestrian_2/project/public/camera1.avi"
142
+ },
143
+ "frames": [
144
+ {
145
+ "frame_id": 329,
146
+ "timestamp": 3365.1254
147
+ "bboxes": [
148
+ {
149
+ "labels": [
150
+ {
151
+ "category": "pedestrian",
152
+ "confidence": 0.9
153
+ }
154
+ ],
155
+ "bbox_id": 0,
156
+ "top": 1257,
157
+ "left": 138,
158
+ "width": 68,
159
+ "height": 109
160
+ }
161
+ ]
162
+ }],
163
+
164
+ Attributes:
165
+ frames (dict): It's a dictionary that maps each frame_id to json attributes.
166
+ video_details (dict): information about video file.
167
+ top_k_labels (int): shows the allowed number of labels
168
+ start_time (datetime object): we use it to automate the json output by time.
169
+
170
+ Args:
171
+ top_k_labels (int): shows the allowed number of labels
172
+
173
+ """
174
+
175
+ def __init__(self, top_k_labels: int = 1):
176
+ self.frames = {}
177
+ self.video_details = self.video_details = dict(frame_width=None, frame_height=None, frame_rate=None,
178
+ video_name=None)
179
+ self.top_k_labels = top_k_labels
180
+ self.start_time = datetime.now()
181
+
182
+ def set_top_k(self, value):
183
+ self.top_k_labels = value
184
+
185
+ def frame_exists(self, frame_id: int) -> bool:
186
+ """
187
+ Args:
188
+ frame_id (int):
189
+
190
+ Returns:
191
+ bool: true if frame_id is recognized
192
+ """
193
+ return frame_id in self.frames.keys()
194
+
195
+ def add_frame(self, frame_id: int, timestamp: float = None) -> None:
196
+ """
197
+ Args:
198
+ frame_id (int):
199
+ timestamp (float): opencv captured frame time property
200
+
201
+ Raises:
202
+ ValueError: if frame_id would not exist in class frames attribute
203
+
204
+ Returns:
205
+ None
206
+
207
+ """
208
+ if not self.frame_exists(frame_id):
209
+ self.frames[frame_id] = Frame(frame_id, timestamp)
210
+ else:
211
+ raise ValueError("Frame id: {} already exists".format(frame_id))
212
+
213
+ def bbox_exists(self, frame_id: int, bbox_id: int) -> bool:
214
+ """
215
+ Args:
216
+ frame_id:
217
+ bbox_id:
218
+
219
+ Returns:
220
+ bool: if bbox exists in frame bboxes list
221
+ """
222
+ bboxes = []
223
+ if self.frame_exists(frame_id=frame_id):
224
+ bboxes = [bbox.bbox_id for bbox in self.frames[frame_id].bboxes]
225
+ return bbox_id in bboxes
226
+
227
+ def find_bbox(self, frame_id: int, bbox_id: int):
228
+ """
229
+
230
+ Args:
231
+ frame_id:
232
+ bbox_id:
233
+
234
+ Returns:
235
+ bbox_id (int):
236
+
237
+ Raises:
238
+ ValueError: if bbox_id does not exist in the bbox list of specific frame.
239
+ """
240
+ if not self.bbox_exists(frame_id, bbox_id):
241
+ raise ValueError("frame with id: {} does not contain bbox with id: {}".format(frame_id, bbox_id))
242
+ bboxes = {bbox.bbox_id: bbox for bbox in self.frames[frame_id].bboxes}
243
+ return bboxes.get(bbox_id)
244
+
245
+ def add_bbox_to_frame(self, frame_id: int, bbox_id: int, top: int, left: int, width: int, height: int) -> None:
246
+ """
247
+
248
+ Args:
249
+ frame_id (int):
250
+ bbox_id (int):
251
+ top (int):
252
+ left (int):
253
+ width (int):
254
+ height (int):
255
+
256
+ Returns:
257
+ None
258
+
259
+ Raises:
260
+ ValueError: if bbox_id already exist in frame information with frame_id
261
+ ValueError: if frame_id does not exist in frames attribute
262
+ """
263
+ if self.frame_exists(frame_id):
264
+ frame = self.frames[frame_id]
265
+ if not self.bbox_exists(frame_id, bbox_id):
266
+ frame.add_bbox(bbox_id, top, left, width, height)
267
+ else:
268
+ raise ValueError(
269
+ "frame with frame_id: {} already contains the bbox with id: {} ".format(frame_id, bbox_id))
270
+ else:
271
+ raise ValueError("frame with frame_id: {} does not exist".format(frame_id))
272
+
273
+ def add_label_to_bbox(self, frame_id: int, bbox_id: int, category: str, confidence: float):
274
+ """
275
+ Args:
276
+ frame_id:
277
+ bbox_id:
278
+ category:
279
+ confidence: the confidence value returned from yolo detection
280
+
281
+ Returns:
282
+ None
283
+
284
+ Raises:
285
+ ValueError: if labels quota (top_k_labels) exceeds.
286
+ """
287
+ bbox = self.find_bbox(frame_id, bbox_id)
288
+ if not bbox.labels_full(self.top_k_labels):
289
+ bbox.add_label(category, confidence)
290
+ else:
291
+ raise ValueError("labels in frame_id: {}, bbox_id: {} is fulled".format(frame_id, bbox_id))
292
+
293
+ def add_video_details(self, frame_width: int = None, frame_height: int = None, frame_rate: int = None,
294
+ video_name: str = None):
295
+ self.video_details['frame_width'] = frame_width
296
+ self.video_details['frame_height'] = frame_height
297
+ self.video_details['frame_rate'] = frame_rate
298
+ self.video_details['video_name'] = video_name
299
+
300
+ def output(self):
301
+ output = {'video_details': self.video_details}
302
+ result = list(self.frames.values())
303
+ output['frames'] = [item.dic() for item in result]
304
+ return output
305
+
306
+ def json_output(self, output_name):
307
+ """
308
+ Args:
309
+ output_name:
310
+
311
+ Returns:
312
+ None
313
+
314
+ Notes:
315
+ It creates the json output with `output_name` name.
316
+ """
317
+ if not output_name.endswith('.json'):
318
+ output_name += '.json'
319
+ with open(output_name, 'w') as file:
320
+ json.dump(self.output(), file)
321
+ file.close()
322
+
323
+ def set_start(self):
324
+ self.start_time = datetime.now()
325
+
326
+ def schedule_output_by_time(self, output_dir=JsonMeta.PATH_TO_SAVE, hours: int = 0, minutes: int = 0,
327
+ seconds: int = 60) -> None:
328
+ """
329
+ Notes:
330
+ Creates folder and then periodically stores the jsons on that address.
331
+
332
+ Args:
333
+ output_dir (str): the directory where output files will be stored
334
+ hours (int):
335
+ minutes (int):
336
+ seconds (int):
337
+
338
+ Returns:
339
+ None
340
+
341
+ """
342
+ end = datetime.now()
343
+ interval = 0
344
+ interval += abs(min([hours, JsonMeta.HOURS]) * 3600)
345
+ interval += abs(min([minutes, JsonMeta.MINUTES]) * 60)
346
+ interval += abs(min([seconds, JsonMeta.SECONDS]))
347
+ diff = (end - self.start_time).seconds
348
+
349
+ if diff > interval:
350
+ output_name = self.start_time.strftime('%Y-%m-%d %H-%M-%S') + '.json'
351
+ if not exists(output_dir):
352
+ makedirs(output_dir)
353
+ output = join(output_dir, output_name)
354
+ self.json_output(output_name=output)
355
+ self.frames = {}
356
+ self.start_time = datetime.now()
357
+
358
+ def schedule_output_by_frames(self, frames_quota, frame_counter, output_dir=JsonMeta.PATH_TO_SAVE):
359
+ """
360
+ saves as the number of frames quota increases higher.
361
+ :param frames_quota:
362
+ :param frame_counter:
363
+ :param output_dir:
364
+ :return:
365
+ """
366
+ pass
367
+
368
+ def flush(self, output_dir):
369
+ """
370
+ Notes:
371
+ We use this function to output jsons whenever possible.
372
+ like the time that we exit the while loop of opencv.
373
+
374
+ Args:
375
+ output_dir:
376
+
377
+ Returns:
378
+ None
379
+
380
+ """
381
+ filename = self.start_time.strftime('%Y-%m-%d %H-%M-%S') + '-remaining.json'
382
+ output = join(output_dir, filename)
383
+ self.json_output(output_name=output)
deep_sort/utils/log.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+
3
+
4
+ def get_logger(name='root'):
5
+ formatter = logging.Formatter(
6
+ # fmt='%(asctime)s [%(levelname)s]: %(filename)s(%(funcName)s:%(lineno)s) >> %(message)s')
7
+ fmt='%(asctime)s [%(levelname)s]: %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
8
+
9
+ handler = logging.StreamHandler()
10
+ handler.setFormatter(formatter)
11
+
12
+ logger = logging.getLogger(name)
13
+ logger.setLevel(logging.INFO)
14
+ logger.addHandler(handler)
15
+ return logger
16
+
17
+
deep_sort/utils/tools.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from functools import wraps
2
+ from time import time
3
+
4
+
5
+ def is_video(ext: str):
6
+ """
7
+ Returns true if ext exists in
8
+ allowed_exts for video files.
9
+
10
+ Args:
11
+ ext:
12
+
13
+ Returns:
14
+
15
+ """
16
+
17
+ allowed_exts = ('.mp4', '.webm', '.ogg', '.avi', '.wmv', '.mkv', '.3gp')
18
+ return any((ext.endswith(x) for x in allowed_exts))
19
+
20
+
21
+ def tik_tok(func):
22
+ """
23
+ keep track of time for each process.
24
+ Args:
25
+ func:
26
+
27
+ Returns:
28
+
29
+ """
30
+ @wraps(func)
31
+ def _time_it(*args, **kwargs):
32
+ start = time()
33
+ try:
34
+ return func(*args, **kwargs)
35
+ finally:
36
+ end_ = time()
37
+ print("time: {:.03f}s, fps: {:.03f}".format(end_ - start, 1 / (end_ - start)))
38
+
39
+ return _time_it