Skip to content

Commit a28abbd

Browse files
committed
Add drawing functions
1 parent 62ea522 commit a28abbd

File tree

4 files changed

+52
-33
lines changed

4 files changed

+52
-33
lines changed

fastmot/mot.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
from .detector import SSDDetector, YoloDetector, PublicDetector
77
from .feature_extractor import FeatureExtractor
88
from .tracker import MultiTracker
9-
from .utils.visualization import draw_track, draw_detection, draw_bg_flow
9+
from .utils.visualization import draw_tracks, draw_detections
10+
from .utils.visualization import draw_flow_bboxes, draw_background_flow
1011

1112

1213
LOGGER = logging.getLogger(__name__)
@@ -116,11 +117,10 @@ def step(self, frame):
116117
self.frame_count += 1
117118

118119
def _draw(self, frame, detections):
119-
for track in self.visible_tracks:
120-
draw_track(frame, track, draw_flow=self.verbose)
120+
draw_tracks(frame, self.visible_tracks, draw_flow=self.verbose)
121121
if self.verbose:
122-
for det in detections:
123-
draw_detection(frame, det)
124-
draw_bg_flow(frame, self.tracker)
122+
draw_detections(frame, detections)
123+
draw_flow_bboxes(frame, self.tracker)
124+
draw_background_flow(frame, self.tracker)
125125
cv2.putText(frame, f'visible: {len(self.visible_tracks)}', (30, 30),
126126
cv2.FONT_HERSHEY_SIMPLEX, 1, 0, 2, cv2.LINE_AA)

fastmot/tracker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ def step_kalman_filter(self):
113113
mean, cov = self.kf.warp(mean, cov, self.homography)
114114
mean, cov = self.kf.predict(mean, cov)
115115
if trk_id in self.flow_bboxes:
116-
flow_bbox = self.flow_bboxes[trk_id]
116+
flow_tlbr = self.flow_bboxes[trk_id]
117117
# give large flow uncertainty for occluded tracks
118118
# usually these with high age and low inlier ratio
119119
std_multiplier = max(self.age_factor * track.age, 1) / track.inlier_ratio
120-
mean, cov = self.kf.update(mean, cov, flow_bbox, MeasType.FLOW, std_multiplier)
120+
mean, cov = self.kf.update(mean, cov, flow_tlbr, MeasType.FLOW, std_multiplier)
121121
next_tlbr = as_rect(mean[:4])
122122
track.state = (mean, cov)
123123
track.tlbr = next_tlbr

fastmot/utils/rect.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,6 @@ def get_center(tlbr):
3333
return np.array([(xmin + xmax) / 2, (ymin + ymax) / 2])
3434

3535

36-
@nb.njit(cache=True)
37-
def get_corners(tlbr):
38-
xmin, ymin, xmax, ymax = tlbr
39-
return np.array([[xmin, ymin], [xmax, ymin], [xmax, ymax], [xmin, ymax]])
40-
41-
4236
@nb.njit(cache=True)
4337
def to_tlwh(tlbr):
4438
return np.append(tlbr[:2], get_size(tlbr))
@@ -83,9 +77,9 @@ def crop(img, tlbr):
8377

8478
@nb.njit(cache=True)
8579
def multi_crop(img, tlbrs):
86-
_tlbrs = tlbrs.astype(np.int_)
87-
return [img[_tlbrs[i][1]:_tlbrs[i][3] + 1, _tlbrs[i][0]:_tlbrs[i][2] + 1]
88-
for i in range(len(_tlbrs))]
80+
tlbrs_ = tlbrs.astype(np.int_)
81+
return [img[tlbrs_[i][1]:tlbrs_[i][3] + 1, tlbrs_[i][0]:tlbrs_[i][2] + 1]
82+
for i in range(len(tlbrs_))]
8983

9084

9185
@nb.njit(fastmath=True, cache=True)

fastmot/utils/visualization.py

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,43 @@
66
GOLDEN_RATIO = 0.618033988749895
77

88

9-
def draw_track(frame, trk, draw_flow=False):
10-
_draw_bbox(frame, trk.tlbr, _get_color(trk.trk_id), 2, str(trk.trk_id))
11-
if draw_flow:
12-
_draw_feature_match(frame, trk.keypoints, trk.prev_keypoints, (0, 255, 255))
9+
def draw_tracks(frame, tracks, draw_flow=False):
10+
for track in tracks:
11+
draw_bbox(frame, track.tlbr, get_color(track.trk_id), 2, str(track.trk_id))
12+
if draw_flow:
13+
draw_feature_match(frame, track.prev_keypoints, track.keypoints, (0, 255, 255))
1314

1415

15-
def draw_detection(frame, det):
16-
_draw_bbox(frame, det.tlbr, (255, 255, 255), 1)
16+
def draw_detections(frame, detections):
17+
for det in detections:
18+
draw_bbox(frame, det.tlbr, (255, 255, 255), 1)
1719

1820

19-
def draw_tile(frame, detector):
21+
def draw_flow_bboxes(frame, tracker):
22+
for tlbr in tracker.flow_bboxes.values():
23+
draw_bbox(frame, tlbr, 0, 1)
24+
25+
26+
def draw_tiles(frame, detector):
2027
assert hasattr(detector, 'tiles')
2128
for tile in detector.tiles:
22-
tl = np.rint(tile[:2] * detector.scale_factor).astype(int)
23-
br = np.rint(tile[2:] * detector.scale_factor).astype(int)
24-
cv2.rectangle(frame, tuple(tl), tuple(br), 0, 1)
29+
tlbr = np.rint(tile * np.tile(detector.scale_factor, 2))
30+
draw_bbox(frame, tlbr, 0, 1)
2531

2632

27-
def draw_bg_flow(frame, tracker):
28-
_draw_feature_match(frame, tracker.flow.bg_keypoints,
29-
tracker.flow.prev_bg_keypoints, (0, 0, 255))
33+
def draw_background_flow(frame, tracker):
34+
draw_feature_match(frame, tracker.flow.prev_bg_keypoints,
35+
tracker.flow.bg_keypoints, (0, 0, 255))
3036

3137

32-
def _get_color(idx, s=0.8, vmin=0.7):
38+
def get_color(idx, s=0.8, vmin=0.7):
3339
h = np.fmod(idx * GOLDEN_RATIO, 1.)
3440
v = 1. - np.fmod(idx * GOLDEN_RATIO, 1. - vmin)
3541
r, g, b = colorsys.hsv_to_rgb(h, s, v)
3642
return int(255 * b), int(255 * g), int(255 * r)
3743

3844

39-
def _draw_bbox(frame, tlbr, color, thickness, text=None):
45+
def draw_bbox(frame, tlbr, color, thickness, text=None):
4046
tlbr = tlbr.astype(int)
4147
tl, br = tuple(tlbr[:2]), tuple(tlbr[2:])
4248
cv2.rectangle(frame, tl, br, color, thickness)
@@ -48,7 +54,7 @@ def _draw_bbox(frame, tlbr, color, thickness, text=None):
4854
0.5, 0, 1, cv2.LINE_AA)
4955

5056

51-
def _draw_feature_match(frame, cur_pts, prev_pts, color):
57+
def draw_feature_match(frame, prev_pts, cur_pts, color):
5258
if len(cur_pts) > 0:
5359
cur_pts = np.rint(cur_pts).astype(np.int32)
5460
for pt in cur_pts:
@@ -57,3 +63,22 @@ def _draw_feature_match(frame, cur_pts, prev_pts, color):
5763
prev_pts = np.rint(prev_pts).astype(np.int32)
5864
for pt1, pt2 in zip(prev_pts, cur_pts):
5965
cv2.line(frame, tuple(pt1), tuple(pt2), color, 1, cv2.LINE_AA)
66+
67+
68+
def draw_covariance(frame, tlbr, covariance):
69+
tlbr = tlbr.astype(int)
70+
tl, br = tuple(tlbr[:2]), tuple(tlbr[2:])
71+
72+
def ellipse(cov):
73+
vals, vecs = np.linalg.eigh(cov)
74+
order = vals.argsort()[::-1]
75+
# 95% confidence ellipse
76+
vals, vecs = np.sqrt(vals[order] * 5.9915), vecs[:, order]
77+
axes = int(vals[0] + 0.5), int(vals[1] + 0.5)
78+
angle = np.degrees(np.arctan2(vecs[1, 0], vecs[0, 0]))
79+
return axes, angle
80+
81+
axes, angle = ellipse(covariance[:2, :2])
82+
cv2.ellipse(frame, tl, axes, angle, 0, 360, (255, 255, 255), 1)
83+
axes, angle = ellipse(covariance[2:4, 2:4])
84+
cv2.ellipse(frame, br, axes, angle, 0, 360, (255, 255, 255), 1)

0 commit comments

Comments
 (0)