This repository has been archived by the owner on Dec 3, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtracker.py
130 lines (105 loc) · 4.74 KB
/
tracker.py
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""
Pedestrian Tracking
2018
POVa - Computer Vision
FIT - Faculty of Information Technology
BUT - Brno University of Technology
"""
import logging
from abc import ABC, abstractmethod
from typing import List
import cv2
from person import PersonTimeFrame, Person
from utils import calculate_flat_histogram
logger = logging.getLogger(__name__)
class PersonTracker(ABC):
@property
@abstractmethod
def people(self) -> List[Person]:
"""
:return: all tracked people including those not actively visible right now
"""
pass
@abstractmethod
def track(self, frame: PersonTimeFrame) -> Person:
"""
Track person from provided time frame.
Assigns given time frame to already tracked person or creates new unique person for it.
"""
pass
class NullTracker(PersonTracker):
"""
Does **not** do any real person tracking, only passes data through.
Creates person for each passed time frame.
"""
_people: List[Person]
def __init__(self):
logger.debug('Using NullTracker as PersonTracker.')
self._people = []
@property
def people(self) -> List[Person]:
return self._people
def track(self, frame: PersonTimeFrame) -> Person:
person = Person(frame)
logger.debug("New person! Person={}, 3D={}".format(person.name, person.time_frames[-1].coordinates_3d))
self._people.append(person)
logger.debug('Tracked people total: {}'.format(len(self._people)))
return person
class HistogramTracker(PersonTracker):
_people: List[Person]
def __init__(self):
logger.debug('Using HistogramTracker as PersonTracker.')
self._people = []
@property
def people(self) -> List[Person]:
return self._people
def track(self, frame: PersonTimeFrame) -> Person:
"""
If consecutive time frames have similar histogram they can belong to the same person.
Multiple hist-cmp methods are used for matching. Frames are matched to the same person only if all methods
agree on the best match.
"""
if len(self._people) == 0:
person = Person(frame)
self._people.append(person)
logger.debug("New! Person={}, 3D={}".format(person.name, person.time_frames[-1].coordinates_3d))
else:
view = frame.views[0]
torso = view.get_torso_subimage()
# cv2.imshow('torso view={}'.format(id(view)), torso) # used for debugging
# cv2.waitKey(1) # used for debugging
histogram = calculate_flat_histogram(torso)
intersect_histcmps = []
hellinger_histcmps = []
for person in self._people:
view = person.time_frames[-1].views[0]
torso = view.get_torso_subimage()
# cv2.imshow('torso person.name={}, view={}'.format(person.name, id(view)), torso) # used for debugging
# cv2.waitKey(1) # used for debugging
front_histogram = calculate_flat_histogram(torso)
intersect_histcmps.append(cv2.compareHist(front_histogram, histogram, cv2.HISTCMP_INTERSECT))
hellinger_histcmps.append(cv2.compareHist(front_histogram, histogram, cv2.HISTCMP_HELLINGER))
# INTERSECT method: HIGHER value ~ HIGHER similarity
best_intersect_match = max(x for x in intersect_histcmps if x is not None)
i_intersect_match = intersect_histcmps.index(best_intersect_match)
# HELLINGER method: LOWER value ~ HIGHER similarity
best_hellinger_match = min(x for x in hellinger_histcmps if x is not None)
i_hellinger_match = hellinger_histcmps.index(best_hellinger_match)
if i_intersect_match == i_hellinger_match: # TODO threshold
person = self._people[i_intersect_match]
person.time_frames.append(frame)
# Do not append person to `self._people` here. It is already tracked.
logger.debug("Tracked. Person={}, 3D={}".format(person.name, person.time_frames[-1].coordinates_3d))
else:
person = Person(frame)
self._people.append(person)
logger.debug("New! Person={}, 3D={}".format(person.name, person.time_frames[-1].coordinates_3d))
logger.debug('Tracked people total: {}'.format(len(self._people)))
return person
class PositionAndHistogramTracker(PersonTracker):
@property
def people(self) -> List[Person]:
raise NotImplementedError # TODO implement
def track(self, frame: PersonTimeFrame) -> Person:
# NOTE: If consecutive time frames have similar position and histogram they can belong to the same person.
raise NotImplementedError # TODO implement