Spaces:
Build error
Build error
Commit ·
8689046
1
Parent(s): 54c4dfe
wip tracking uniformization with main repo
Browse files- tracking/postprocess_and_count_tracks.py +22 -7
- tracking/track_video.py +20 -55
- tracking/trackers.py +8 -1
- tracking/utils.py +50 -11
tracking/postprocess_and_count_tracks.py
CHANGED
|
@@ -3,6 +3,7 @@ import argparse
|
|
| 3 |
from scipy.signal import convolve
|
| 4 |
from tracking.utils import write_tracking_results_to_file, read_tracking_results
|
| 5 |
from collections import defaultdict
|
|
|
|
| 6 |
|
| 7 |
import json
|
| 8 |
|
|
@@ -21,14 +22,20 @@ def filter_tracks(tracklets, kappa, tau):
|
|
| 21 |
for det in dets:
|
| 22 |
results.append((det[0], tracker_nb, det[1], det[2], det[3], det[4]))
|
| 23 |
|
| 24 |
-
# for tracker_nb, associated_detections in enumerate(tracks):
|
| 25 |
-
# for det in associated_detections:
|
| 26 |
-
# results.append((associated_detection[0], tracker_nb, associated_detection[1], associated_detection[2]))
|
| 27 |
-
|
| 28 |
results = sorted(results, key=lambda x: x[0])
|
| 29 |
return results
|
| 30 |
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
def postprocess_for_api(results, class_dict=defaultdict(lambda: "fragment")):
|
| 33 |
""" Converts tracking results into json object for API
|
| 34 |
"""
|
|
@@ -47,11 +54,18 @@ def postprocess_for_api(results, class_dict=defaultdict(lambda: "fragment")):
|
|
| 47 |
result_list.append({"label":classname,
|
| 48 |
"id": id,
|
| 49 |
"frame_to_box": {str(frame_number): box},
|
| 50 |
-
"
|
| 51 |
# otherwise, retrieve the jsonline and append the box
|
| 52 |
else:
|
| 53 |
result_list[id_list[id]]["frame_to_box"][str(frame_number)] = box
|
| 54 |
-
result_list[id_list[id]]["
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
return {"detected_trash": result_list}
|
| 57 |
|
|
@@ -63,10 +77,11 @@ def count_objects(input_json, class_dict):
|
|
| 63 |
results[trash["label"]] += 1
|
| 64 |
total += 1
|
| 65 |
|
| 66 |
-
if total==0:
|
| 67 |
total = 1
|
| 68 |
return {k+f": {str(v)}":v/total for k,v in results.items()}
|
| 69 |
|
|
|
|
| 70 |
def write(results, output_name):
|
| 71 |
""" Writes the results in two files:
|
| 72 |
- tracking in a Mathis format xxx_track.txt (frame, id, box_x, box_y, ...)
|
|
|
|
| 3 |
from scipy.signal import convolve
|
| 4 |
from tracking.utils import write_tracking_results_to_file, read_tracking_results
|
| 5 |
from collections import defaultdict
|
| 6 |
+
from statistics import mode
|
| 7 |
|
| 8 |
import json
|
| 9 |
|
|
|
|
| 22 |
for det in dets:
|
| 23 |
results.append((det[0], tracker_nb, det[1], det[2], det[3], det[4]))
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
results = sorted(results, key=lambda x: x[0])
|
| 26 |
return results
|
| 27 |
|
| 28 |
|
| 29 |
+
def process_class_and_confidences(class_confs):
|
| 30 |
+
''' Finds the majority and most confident class from list [(classid, conf), ...]
|
| 31 |
+
'''
|
| 32 |
+
d = defaultdict(lambda: (0, 0.0))
|
| 33 |
+
for (cls, conf) in class_confs:
|
| 34 |
+
d[cls] = (d[cls][0] + 1, d[cls][1] + conf)
|
| 35 |
+
best_class = sorted(d.items(), key=lambda v: v[1][0]+v[1][1])[-1]
|
| 36 |
+
return best_class[0], round(best_class[1][1]/best_class[1][0],2)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
def postprocess_for_api(results, class_dict=defaultdict(lambda: "fragment")):
|
| 40 |
""" Converts tracking results into json object for API
|
| 41 |
"""
|
|
|
|
| 54 |
result_list.append({"label":classname,
|
| 55 |
"id": id,
|
| 56 |
"frame_to_box": {str(frame_number): box},
|
| 57 |
+
"frame_to_class_conf": {str(frame_number): (res[5], conf)}})
|
| 58 |
# otherwise, retrieve the jsonline and append the box
|
| 59 |
else:
|
| 60 |
result_list[id_list[id]]["frame_to_box"][str(frame_number)] = box
|
| 61 |
+
result_list[id_list[id]]["frame_to_class_conf"][str(frame_number)] = (res[5], conf)
|
| 62 |
+
|
| 63 |
+
# Finally, collapse the confidence and class
|
| 64 |
+
for res in result_list:
|
| 65 |
+
classid, avg_conf = process_class_and_confidences(res.pop("frame_to_class_conf").values())
|
| 66 |
+
res["avg_conf"] = avg_conf
|
| 67 |
+
# update the label
|
| 68 |
+
res["label"] = class_dict[classid]
|
| 69 |
|
| 70 |
return {"detected_trash": result_list}
|
| 71 |
|
|
|
|
| 77 |
results[trash["label"]] += 1
|
| 78 |
total += 1
|
| 79 |
|
| 80 |
+
if total==0:
|
| 81 |
total = 1
|
| 82 |
return {k+f": {str(v)}":v/total for k,v in results.items()}
|
| 83 |
|
| 84 |
+
|
| 85 |
def write(results, output_name):
|
| 86 |
""" Writes the results in two files:
|
| 87 |
- tracking in a Mathis format xxx_track.txt (frame, id, box_x, box_y, ...)
|
tracking/track_video.py
CHANGED
|
@@ -2,56 +2,22 @@ import cv2
|
|
| 2 |
import numpy as np
|
| 3 |
import os
|
| 4 |
from detection.detect import detect
|
| 5 |
-
from tracking.utils import in_frame
|
| 6 |
from tools.optical_flow import compute_flow
|
| 7 |
from tracking.trackers import get_tracker
|
| 8 |
-
import matplotlib.pyplot as plt
|
| 9 |
from scipy.spatial.distance import euclidean
|
| 10 |
from scipy.optimize import linear_sum_assignment
|
| 11 |
import torch
|
| 12 |
|
| 13 |
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
self.legends = []
|
| 23 |
-
self.plot_count = 0
|
| 24 |
-
|
| 25 |
-
def display(self, trackers):
|
| 26 |
-
|
| 27 |
-
something_to_show = False
|
| 28 |
-
for tracker_nb, tracker in enumerate(trackers):
|
| 29 |
-
if tracker.enabled:
|
| 30 |
-
tracker.fill_display(self, tracker_nb)
|
| 31 |
-
something_to_show = True
|
| 32 |
-
|
| 33 |
-
self.ax.imshow(self.latest_frame_to_show)
|
| 34 |
-
|
| 35 |
-
if len(self.latest_detections):
|
| 36 |
-
self.ax.scatter(self.latest_detections[:, 0], self.latest_detections[:, 1], c='r', s=40)
|
| 37 |
-
|
| 38 |
-
if something_to_show:
|
| 39 |
-
self.ax.xaxis.tick_top()
|
| 40 |
-
plt.legend(handles=self.legends)
|
| 41 |
-
self.fig.canvas.draw()
|
| 42 |
-
if self.interactive:
|
| 43 |
-
plt.show()
|
| 44 |
-
while not plt.waitforbuttonpress():
|
| 45 |
-
continue
|
| 46 |
-
else:
|
| 47 |
-
plt.savefig(os.path.join('plots',str(self.plot_count)))
|
| 48 |
-
self.ax.cla()
|
| 49 |
-
self.legends = []
|
| 50 |
-
self.plot_count+=1
|
| 51 |
-
|
| 52 |
-
def update_detections_and_frame(self, latest_detections, frame):
|
| 53 |
-
self.latest_detections = latest_detections
|
| 54 |
-
self.latest_frame_to_show = cv2.cvtColor(cv2.resize(frame, self.display_shape), cv2.COLOR_BGR2RGB)
|
| 55 |
|
| 56 |
|
| 57 |
def build_confidence_function_for_trackers(trackers, flow01):
|
|
@@ -63,19 +29,23 @@ def build_confidence_function_for_trackers(trackers, flow01):
|
|
| 63 |
confidence_functions.append(tracker.build_confidence_function(flow01))
|
| 64 |
return tracker_nbs, confidence_functions
|
| 65 |
|
| 66 |
-
|
|
|
|
| 67 |
tracker_nbs, confidence_functions = build_confidence_function_for_trackers(trackers, flow01)
|
| 68 |
assigned_trackers = [None]*len(detections_for_frame)
|
| 69 |
if len(tracker_nbs):
|
| 70 |
cost_matrix = np.zeros(shape=(len(detections_for_frame),len(tracker_nbs)))
|
| 71 |
-
for detection_nb, detection in enumerate(detections_for_frame):
|
| 72 |
for tracker_id, confidence_function in enumerate(confidence_functions):
|
| 73 |
score = confidence_function(detection)
|
|
|
|
|
|
|
|
|
|
| 74 |
if score > confidence_threshold:
|
| 75 |
-
cost_matrix[detection_nb,tracker_id] = score
|
| 76 |
else:
|
| 77 |
-
cost_matrix[detection_nb,tracker_id] = 0
|
| 78 |
-
row_inds, col_inds = linear_sum_assignment(cost_matrix,maximize=True)
|
| 79 |
for row_ind, col_ind in zip(row_inds, col_inds):
|
| 80 |
if cost_matrix[row_ind,col_ind] > confidence_threshold: assigned_trackers[row_ind] = tracker_nbs[col_ind]
|
| 81 |
|
|
@@ -83,8 +53,7 @@ def associate_detections_to_trackers(detections_for_frame, trackers, flow01, con
|
|
| 83 |
|
| 84 |
|
| 85 |
def interpret_detection(detections_for_frame, downsampling_factor, is_yolo=False):
|
| 86 |
-
"""
|
| 87 |
-
normalizes the detections depending whether they come from centernet or yolo
|
| 88 |
"""
|
| 89 |
if not is_yolo:
|
| 90 |
confs = [0.0]*len(detections_for_frame)
|
|
@@ -112,7 +81,6 @@ def track_video(reader, detections, args, engine, transition_variance, observati
|
|
| 112 |
delta = 0.005*max_distance
|
| 113 |
|
| 114 |
if display is not None and display.on:
|
| 115 |
-
|
| 116 |
display.display_shape = (reader.output_shape[0] // args.downsampling_factor, reader.output_shape[1] // args.downsampling_factor)
|
| 117 |
display.update_detections_and_frame(detections_for_frame, frame0)
|
| 118 |
|
|
@@ -132,15 +100,12 @@ def track_video(reader, detections, args, engine, transition_variance, observati
|
|
| 132 |
if len(detections_for_frame):
|
| 133 |
trackers = init_trackers(engine, detections_for_frame, confs, labels, frame_nb, transition_variance, observation_variance, delta)
|
| 134 |
init = True
|
| 135 |
-
|
| 136 |
else:
|
| 137 |
-
|
| 138 |
new_trackers = []
|
| 139 |
flow01 = compute_flow(frame0, frame1, args.downsampling_factor)
|
| 140 |
|
| 141 |
if len(detections_for_frame):
|
| 142 |
-
|
| 143 |
-
assigned_trackers = associate_detections_to_trackers(detections_for_frame, trackers,
|
| 144 |
flow01, args.confidence_threshold)
|
| 145 |
|
| 146 |
for detection, conf, label, assigned_tracker in zip(detections_for_frame, confs, labels, assigned_trackers):
|
|
|
|
| 2 |
import numpy as np
|
| 3 |
import os
|
| 4 |
from detection.detect import detect
|
| 5 |
+
from tracking.utils import in_frame
|
| 6 |
from tools.optical_flow import compute_flow
|
| 7 |
from tracking.trackers import get_tracker
|
|
|
|
| 8 |
from scipy.spatial.distance import euclidean
|
| 9 |
from scipy.optimize import linear_sum_assignment
|
| 10 |
import torch
|
| 11 |
|
| 12 |
|
| 13 |
+
def init_trackers(engine, detections, confs, labels, frame_nb, state_variance, observation_variance, delta):
|
| 14 |
+
""" Initializes the trackers based on detections
|
| 15 |
+
"""
|
| 16 |
+
trackers = []
|
| 17 |
+
for detection, conf, label in zip(detections, confs, labels):
|
| 18 |
+
tracker_for_detection = engine(frame_nb, detection, conf, label, state_variance, observation_variance, delta)
|
| 19 |
+
trackers.append(tracker_for_detection)
|
| 20 |
+
return trackers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
|
| 23 |
def build_confidence_function_for_trackers(trackers, flow01):
|
|
|
|
| 29 |
confidence_functions.append(tracker.build_confidence_function(flow01))
|
| 30 |
return tracker_nbs, confidence_functions
|
| 31 |
|
| 32 |
+
|
| 33 |
+
def associate_detections_to_trackers(detections_for_frame, confs, labels, trackers, flow01, confidence_threshold):
|
| 34 |
tracker_nbs, confidence_functions = build_confidence_function_for_trackers(trackers, flow01)
|
| 35 |
assigned_trackers = [None]*len(detections_for_frame)
|
| 36 |
if len(tracker_nbs):
|
| 37 |
cost_matrix = np.zeros(shape=(len(detections_for_frame),len(tracker_nbs)))
|
| 38 |
+
for detection_nb, (detection, conf, label) in enumerate(zip(detections_for_frame, confs, labels)):
|
| 39 |
for tracker_id, confidence_function in enumerate(confidence_functions):
|
| 40 |
score = confidence_function(detection)
|
| 41 |
+
cls_score = trackers[tracker_id].cls_score_function(conf, label)
|
| 42 |
+
if cls_score < 0.5:
|
| 43 |
+
score = score * 0.1 # if wrong class, reduce the score, to tweak
|
| 44 |
if score > confidence_threshold:
|
| 45 |
+
cost_matrix[detection_nb, tracker_id] = score
|
| 46 |
else:
|
| 47 |
+
cost_matrix[detection_nb, tracker_id] = 0
|
| 48 |
+
row_inds, col_inds = linear_sum_assignment(cost_matrix, maximize=True)
|
| 49 |
for row_ind, col_ind in zip(row_inds, col_inds):
|
| 50 |
if cost_matrix[row_ind,col_ind] > confidence_threshold: assigned_trackers[row_ind] = tracker_nbs[col_ind]
|
| 51 |
|
|
|
|
| 53 |
|
| 54 |
|
| 55 |
def interpret_detection(detections_for_frame, downsampling_factor, is_yolo=False):
|
| 56 |
+
""" normalizes the detections depending whether they come from centernet or yolo
|
|
|
|
| 57 |
"""
|
| 58 |
if not is_yolo:
|
| 59 |
confs = [0.0]*len(detections_for_frame)
|
|
|
|
| 81 |
delta = 0.005*max_distance
|
| 82 |
|
| 83 |
if display is not None and display.on:
|
|
|
|
| 84 |
display.display_shape = (reader.output_shape[0] // args.downsampling_factor, reader.output_shape[1] // args.downsampling_factor)
|
| 85 |
display.update_detections_and_frame(detections_for_frame, frame0)
|
| 86 |
|
|
|
|
| 100 |
if len(detections_for_frame):
|
| 101 |
trackers = init_trackers(engine, detections_for_frame, confs, labels, frame_nb, transition_variance, observation_variance, delta)
|
| 102 |
init = True
|
|
|
|
| 103 |
else:
|
|
|
|
| 104 |
new_trackers = []
|
| 105 |
flow01 = compute_flow(frame0, frame1, args.downsampling_factor)
|
| 106 |
|
| 107 |
if len(detections_for_frame):
|
| 108 |
+
assigned_trackers = associate_detections_to_trackers(detections_for_frame, confs, labels, trackers,
|
|
|
|
| 109 |
flow01, args.confidence_threshold)
|
| 110 |
|
| 111 |
for detection, conf, label, assigned_tracker in zip(detections_for_frame, confs, labels, assigned_trackers):
|
tracking/trackers.py
CHANGED
|
@@ -8,7 +8,6 @@ import matplotlib.patches as mpatches
|
|
| 8 |
class Tracker:
|
| 9 |
|
| 10 |
def __init__(self, frame_nb, X0, confidence, class_id, transition_variance, observation_variance, delta):
|
| 11 |
-
|
| 12 |
self.transition_covariance = np.diag(transition_variance)
|
| 13 |
self.observation_covariance = np.diag(observation_variance)
|
| 14 |
self.updated = False
|
|
@@ -49,12 +48,20 @@ class Tracker:
|
|
| 49 |
|
| 50 |
return lambda coord: confidence_from_multivariate_distribution(coord, distribution)
|
| 51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
def get_display_colors(self, display, tracker_nb):
|
| 53 |
colors = display.colors
|
| 54 |
color = colors[tracker_nb % len(colors)]
|
| 55 |
display.legends.append(mpatches.Patch(color=color, label=len(self.tracklet)))
|
| 56 |
return colors[tracker_nb % len(colors)]
|
| 57 |
|
|
|
|
| 58 |
class SMC(Tracker):
|
| 59 |
def set_param(param):
|
| 60 |
SMC.n_particles = int(param)
|
|
|
|
| 8 |
class Tracker:
|
| 9 |
|
| 10 |
def __init__(self, frame_nb, X0, confidence, class_id, transition_variance, observation_variance, delta):
|
|
|
|
| 11 |
self.transition_covariance = np.diag(transition_variance)
|
| 12 |
self.observation_covariance = np.diag(observation_variance)
|
| 13 |
self.updated = False
|
|
|
|
| 48 |
|
| 49 |
return lambda coord: confidence_from_multivariate_distribution(coord, distribution)
|
| 50 |
|
| 51 |
+
def cls_score_function(self, conf, label):
|
| 52 |
+
""" generates a score based on classes associated with observation in this tracker
|
| 53 |
+
"""
|
| 54 |
+
class_conf = sum([tr[2] for tr in self.tracklet if tr[3]==label])
|
| 55 |
+
other_conf = sum([tr[2] for tr in self.tracklet])
|
| 56 |
+
return (class_conf+conf) / (other_conf+conf)
|
| 57 |
+
|
| 58 |
def get_display_colors(self, display, tracker_nb):
|
| 59 |
colors = display.colors
|
| 60 |
color = colors[tracker_nb % len(colors)]
|
| 61 |
display.legends.append(mpatches.Patch(color=color, label=len(self.tracklet)))
|
| 62 |
return colors[tracker_nb % len(colors)]
|
| 63 |
|
| 64 |
+
|
| 65 |
class SMC(Tracker):
|
| 66 |
def set_param(param):
|
| 67 |
SMC.n_particles = int(param)
|
tracking/utils.py
CHANGED
|
@@ -10,8 +10,10 @@ from detection.transforms import TransformFrames
|
|
| 10 |
from collections import defaultdict
|
| 11 |
from skimage.transform import downscale_local_mean
|
| 12 |
from skvideo.io import FFmpegWriter
|
|
|
|
| 13 |
from tracking.gps import get_media_duration
|
| 14 |
|
|
|
|
| 15 |
class GaussianMixture(object):
|
| 16 |
def __init__(self, means, covariance, weights):
|
| 17 |
self.components = [multivariate_normal(
|
|
@@ -33,22 +35,13 @@ class GaussianMixture(object):
|
|
| 33 |
result += weight*component.cdf(x)
|
| 34 |
return result
|
| 35 |
|
| 36 |
-
def init_trackers(engine, detections, confs, labels, frame_nb, state_variance, observation_variance, delta):
|
| 37 |
-
trackers = []
|
| 38 |
-
|
| 39 |
-
for detection, conf, label in zip(detections, confs, labels):
|
| 40 |
-
tracker_for_detection = engine(frame_nb, detection, conf, label, state_variance, observation_variance, delta)
|
| 41 |
-
trackers.append(tracker_for_detection)
|
| 42 |
-
|
| 43 |
-
return trackers
|
| 44 |
|
| 45 |
def exp_and_normalise(lw):
|
| 46 |
w = np.exp(lw - lw.max())
|
| 47 |
return w / w.sum()
|
| 48 |
|
| 49 |
-
def in_frame(position, shape, border=0.02):
|
| 50 |
-
|
| 51 |
|
|
|
|
| 52 |
shape_x = shape[1]
|
| 53 |
shape_y = shape[0]
|
| 54 |
x = position[0]
|
|
@@ -56,6 +49,7 @@ def in_frame(position, shape, border=0.02):
|
|
| 56 |
|
| 57 |
return x > border*shape_x and x < (1-border)*shape_x and y > border*shape_y and y < (1-border)*shape_y
|
| 58 |
|
|
|
|
| 59 |
def gather_filenames_for_video_in_annotations(video, images, data_dir):
|
| 60 |
images_for_video = [image for image in images
|
| 61 |
if image['video_id'] == video['id']]
|
|
@@ -65,8 +59,8 @@ def gather_filenames_for_video_in_annotations(video, images, data_dir):
|
|
| 65 |
return [os.path.join(data_dir, image['file_name'])
|
| 66 |
for image in images_for_video]
|
| 67 |
|
| 68 |
-
def get_detections_for_video(reader, detector, batch_size=16, device=None):
|
| 69 |
|
|
|
|
| 70 |
detections = []
|
| 71 |
dataset = TorchIterableFromReader(reader, TransformFrames())
|
| 72 |
loader = DataLoader(dataset, batch_size=batch_size)
|
|
@@ -244,6 +238,7 @@ def gather_tracklets(tracklist):
|
|
| 244 |
tracklets = list(tracklets.values())
|
| 245 |
return tracklets
|
| 246 |
|
|
|
|
| 247 |
class FramesWithInfo:
|
| 248 |
def __init__(self, frames, output_shape=None):
|
| 249 |
self.frames = frames
|
|
@@ -264,3 +259,47 @@ class FramesWithInfo:
|
|
| 264 |
|
| 265 |
def __iter__(self):
|
| 266 |
return self
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
from collections import defaultdict
|
| 11 |
from skimage.transform import downscale_local_mean
|
| 12 |
from skvideo.io import FFmpegWriter
|
| 13 |
+
import matplotlib.pyplot as plt
|
| 14 |
from tracking.gps import get_media_duration
|
| 15 |
|
| 16 |
+
|
| 17 |
class GaussianMixture(object):
|
| 18 |
def __init__(self, means, covariance, weights):
|
| 19 |
self.components = [multivariate_normal(
|
|
|
|
| 35 |
result += weight*component.cdf(x)
|
| 36 |
return result
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
|
| 39 |
def exp_and_normalise(lw):
|
| 40 |
w = np.exp(lw - lw.max())
|
| 41 |
return w / w.sum()
|
| 42 |
|
|
|
|
|
|
|
| 43 |
|
| 44 |
+
def in_frame(position, shape, border=0.02):
|
| 45 |
shape_x = shape[1]
|
| 46 |
shape_y = shape[0]
|
| 47 |
x = position[0]
|
|
|
|
| 49 |
|
| 50 |
return x > border*shape_x and x < (1-border)*shape_x and y > border*shape_y and y < (1-border)*shape_y
|
| 51 |
|
| 52 |
+
|
| 53 |
def gather_filenames_for_video_in_annotations(video, images, data_dir):
|
| 54 |
images_for_video = [image for image in images
|
| 55 |
if image['video_id'] == video['id']]
|
|
|
|
| 59 |
return [os.path.join(data_dir, image['file_name'])
|
| 60 |
for image in images_for_video]
|
| 61 |
|
|
|
|
| 62 |
|
| 63 |
+
def get_detections_for_video(reader, detector, batch_size=16, device=None):
|
| 64 |
detections = []
|
| 65 |
dataset = TorchIterableFromReader(reader, TransformFrames())
|
| 66 |
loader = DataLoader(dataset, batch_size=batch_size)
|
|
|
|
| 238 |
tracklets = list(tracklets.values())
|
| 239 |
return tracklets
|
| 240 |
|
| 241 |
+
|
| 242 |
class FramesWithInfo:
|
| 243 |
def __init__(self, frames, output_shape=None):
|
| 244 |
self.frames = frames
|
|
|
|
| 259 |
|
| 260 |
def __iter__(self):
|
| 261 |
return self
|
| 262 |
+
|
| 263 |
+
class Display:
|
| 264 |
+
""" Display tracking
|
| 265 |
+
"""
|
| 266 |
+
def __init__(self, on, interactive=True):
|
| 267 |
+
self.on = on
|
| 268 |
+
self.fig, self.ax = plt.subplots()
|
| 269 |
+
self.interactive = interactive
|
| 270 |
+
if interactive:
|
| 271 |
+
plt.ion()
|
| 272 |
+
self.colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
|
| 273 |
+
self.legends = []
|
| 274 |
+
self.plot_count = 0
|
| 275 |
+
|
| 276 |
+
def display(self, trackers):
|
| 277 |
+
|
| 278 |
+
something_to_show = False
|
| 279 |
+
for tracker_nb, tracker in enumerate(trackers):
|
| 280 |
+
if tracker.enabled:
|
| 281 |
+
tracker.fill_display(self, tracker_nb)
|
| 282 |
+
something_to_show = True
|
| 283 |
+
|
| 284 |
+
self.ax.imshow(self.latest_frame_to_show)
|
| 285 |
+
|
| 286 |
+
if len(self.latest_detections):
|
| 287 |
+
self.ax.scatter(self.latest_detections[:, 0], self.latest_detections[:, 1], c='r', s=40)
|
| 288 |
+
|
| 289 |
+
if something_to_show:
|
| 290 |
+
self.ax.xaxis.tick_top()
|
| 291 |
+
plt.legend(handles=self.legends)
|
| 292 |
+
self.fig.canvas.draw()
|
| 293 |
+
if self.interactive:
|
| 294 |
+
plt.show()
|
| 295 |
+
while not plt.waitforbuttonpress():
|
| 296 |
+
continue
|
| 297 |
+
else:
|
| 298 |
+
plt.savefig(os.path.join('plots',str(self.plot_count)))
|
| 299 |
+
self.ax.cla()
|
| 300 |
+
self.legends = []
|
| 301 |
+
self.plot_count+=1
|
| 302 |
+
|
| 303 |
+
def update_detections_and_frame(self, latest_detections, frame):
|
| 304 |
+
self.latest_detections = latest_detections
|
| 305 |
+
self.latest_frame_to_show = cv2.cvtColor(cv2.resize(frame, self.display_shape), cv2.COLOR_BGR2RGB)
|