forked from karolmajek/TrafficAnalysis
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathIOUTracker.py
More file actions
112 lines (88 loc) · 3.65 KB
/
IOUTracker.py
File metadata and controls
112 lines (88 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import numpy as np
from uuid import uuid4
from common import random_color
class TrackState:
Tentative = 1
Confirmed = 2
Deleted = 3
Finished = 4
class Track:
def __init__(self, detection, max_age, n_init,sigma_h, color=None):
self.color = color if color is not None else random_color()
self.detections = [detection]
self.ious = []
self.id = uuid4()
self._max_age = max_age
self._n_init = n_init
self.hits = 1
self.age = 1
self.time_since_update = 0
self.state = TrackState.Tentative
self.sigma_h = sigma_h
def predict(self):
# does nothing because this is a simply IOU tracker with no propagation
self.age += 1
self.time_since_update += 1
def update(self, detection):
self.ious.append(detection.iou(self.detections[-1]))
self.detections.append(detection)
self.hits += 1
self.time_since_update = 0
if self.state == TrackState.Tentative and self.hits >= self._n_init:
self.state = TrackState.Confirmed
def mark_missed(self):
if self.state == TrackState.Tentative:
self.state = TrackState.Deleted
elif max(self.ious) > self.sigma_h:
self.state = TrackState.Finished
else:
self.state = TrackState.Deleted
def get_ious(self, detections):
return [self.detections[-1].iou(x) for x in detections]
def show_history(self, frame, width=2, n=30):
if self.is_confirmed():
self.detections[-1].show(frame, self.color, width=width)
for b in self.detections[-n:]:
b.show_center(frame, self.color, width=-1)
def is_tentative(self):
return self.state == TrackState.Tentative
def is_confirmed(self):
return self.state == TrackState.Confirmed
def is_deleted(self):
return self.state == TrackState.Deleted
def is_finished(self):
return self.state == TrackState.Finished
class IOUTracker:
def __init__(self, sigma_iou_discard=0.05, sigma_iou=0.4, sigma_h=0.7, max_age=2, n_init=3):
self.sigma_iou_discard = sigma_iou_discard
self.sigma_iou = sigma_iou # minimal to be consider as overlapping
self.sigma_h = sigma_h
self.max_age = max_age
self.n_init = n_init
self.finished_tracks = []
self.active_tracks = []
def predict(self):
for track in self.active_tracks:
track.predict()
def update(self, detections, frame_bbox):
for track in self.active_tracks:
ious = np.array(track.get_ious(detections))
if len(ious) == 0:
track.mark_missed()
else:
i = np.argmax(ious)
if ious[i] >= self.sigma_iou:
track.update(detections[i])
detections.remove(detections[i])
else:
track.mark_missed()
for detection in detections:
ious = detection.get_ious([track.detections[-1] for track in self.active_tracks])
# skip those that sufficiently overlap with existing active tracks
if not np.any(np.array(ious) > self.sigma_iou_discard) and detection.is_inside(frame_bbox):
self.active_tracks.append(Track(detection, self.max_age, self.n_init, self.sigma_h))
tracks_finished = [track for track in self.active_tracks if track.is_finished()]
tracks_deleted = [track for track in self.active_tracks if track.is_deleted()]
self.finished_tracks += tracks_finished
for track in tracks_finished + tracks_deleted:
self.active_tracks.remove(track)