Skip to content

Commit 8b01276

Browse files
committed
fix bugs in c_biou track
1 parent 0a18efb commit 8b01276

File tree

4 files changed

+52
-54
lines changed

4 files changed

+52
-54
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ git checkout v2 # change to v2 branch !!
2121

2222
## 🗺️ Latest News
2323

24+
- ***2024.11.29*** Fix bugs of C-BIoU Track (the state prediction and updating bugs)
2425
- ***2024.10.24*** Add Hybrid SORT and fix some errors and bugs of OC-SORT.
2526

2627
## ❤️ Introduction

README_CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ git checkout v2 # change to v2 branch !!
1515

1616
## 🗺️ 最近更新
1717

18+
- ***2024.11.29*** 修复了C-BIoU Tracker中轨迹状态的更新和预测的错误
1819
- ***2024.10.24*** 增加了 Hybrid SORT 并且修复了OC-SORT的一些bug和错误。
1920

2021

tracker/trackers/c_biou_tracker.py

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,11 @@ def update(self, output_results, img, ori_img):
3939
categories = output_results[:, -1]
4040

4141
remain_inds = scores > self.args.conf_thresh
42-
inds_low = scores > 0.1
43-
inds_high = scores < self.args.conf_thresh
44-
45-
inds_second = np.logical_and(inds_low, inds_high)
46-
dets_second = bboxes[inds_second]
4742
dets = bboxes[remain_inds]
4843

4944
cates = categories[remain_inds]
50-
cates_second = categories[inds_second]
5145

5246
scores_keep = scores[remain_inds]
53-
scores_second = scores[inds_second]
5447

5548
if len(dets) > 0:
5649
'''Detections'''
@@ -68,7 +61,7 @@ def update(self, output_results, img, ori_img):
6861
else:
6962
tracked_tracklets.append(track)
7063

71-
''' Step 2: First association, with high score detection boxes'''
64+
''' Step 2: First association, with small buffer IoU'''
7265
tracklet_pool = joint_tracklets(tracked_tracklets, self.lost_tracklets)
7366

7467
# Predict the current location with Kalman
@@ -89,40 +82,29 @@ def update(self, output_results, img, ori_img):
8982
track.re_activate(det, self.frame_id, new_id=False)
9083
refind_tracklets.append(track)
9184

92-
''' Step 3: Second association, with low score detection boxes'''
93-
# association the untrack to the low score detections
94-
if len(dets_second) > 0:
95-
'''Detections'''
96-
detections_second = [Tracklet_w_bbox_buffer(tlwh, s, cate, motion=self.motion) for
97-
(tlwh, s, cate) in zip(dets_second, scores_second, cates_second)]
98-
else:
99-
detections_second = []
100-
r_tracked_tracklets = [tracklet_pool[i] for i in u_track if tracklet_pool[i].state == TrackState.Tracked]
85+
unmatched_tracklets = [tracklet_pool[i] for i in u_track if tracklet_pool[i].state == TrackState.Tracked]
86+
unmatched_detections = [detections[i] for i in u_detection]
10187

88+
'''Step 3: Second association, with large buffer IoU'''
10289

103-
dists = buffered_iou_distance(r_tracked_tracklets, detections_second, level=2)
90+
dists = buffered_iou_distance(unmatched_tracklets, unmatched_detections, level=2)
91+
92+
matches, u_track, u_detection = linear_assignment(dists, thresh=0.5)
10493

105-
matches, u_track, u_detection_second = linear_assignment(dists, thresh=0.5)
10694
for itracked, idet in matches:
107-
track = r_tracked_tracklets[itracked]
108-
det = detections_second[idet]
95+
track = unmatched_tracklets[itracked]
96+
det = unmatched_detections[idet]
10997
if track.state == TrackState.Tracked:
11098
track.update(det, self.frame_id)
11199
activated_tracklets.append(track)
112100
else:
113101
track.re_activate(det, self.frame_id, new_id=False)
114102
refind_tracklets.append(track)
115103

116-
for it in u_track:
117-
track = r_tracked_tracklets[it]
118-
if not track.state == TrackState.Lost:
119-
track.mark_lost()
120-
lost_tracklets.append(track)
121-
122104
'''Deal with unconfirmed tracks, usually tracks with only one beginning frame'''
123-
detections = [detections[i] for i in u_detection]
105+
detections = [unmatched_detections[i] for i in u_detection]
124106
dists = buffered_iou_distance(unconfirmed, detections, level=1)
125-
107+
126108
matches, u_unconfirmed, u_detection = linear_assignment(dists, thresh=0.7)
127109

128110
for itracked, idet in matches:
@@ -133,15 +115,15 @@ def update(self, output_results, img, ori_img):
133115
track.mark_removed()
134116
removed_tracklets.append(track)
135117

136-
""" Step 4: Init new tracklets"""
118+
'''Step 4. Inital new tracks'''
137119
for inew in u_detection:
138120
track = detections[inew]
139121
if track.score < self.det_thresh:
140122
continue
141123
track.activate(self.frame_id)
142124
activated_tracklets.append(track)
143125

144-
""" Step 5: Update state"""
126+
''' Step 5: Update state'''
145127
for track in self.lost_tracklets:
146128
if self.frame_id - track.end_frame > self.max_time_lost:
147129
track.mark_removed()

tracker/trackers/tracklet.py

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,14 @@ class Tracklet_w_bbox_buffer(Tracklet):
438438
Tracklet class with buffer of bbox, for C_BIoU track.
439439
"""
440440
def __init__(self, tlwh, score, category, motion='byte'):
441-
super().__init__(tlwh, score, category, motion)
441+
# initial position
442+
self._tlwh = np.asarray(tlwh, dtype=np.float)
443+
self.is_activated = False
444+
445+
self.score = score
446+
self.category = category
447+
448+
# Note in C-BIoU tracker the kalman filter is abandoned
442449

443450
# params in motion state
444451
self.b1, self.b2, self.n = 0.3, 0.5, 5
@@ -448,6 +455,7 @@ def __init__(self, tlwh, score, category, motion='byte'):
448455
self.buffer_bbox1 = self.get_buffer_bbox(level=1)
449456
self.buffer_bbox2 = self.get_buffer_bbox(level=2)
450457
# motion state, s^{t + \delta} = o^t + (\delta / n) * \sum_{i=t-n+1}^t(o^i - o^{i-1}) = o^t + (\delta / n) * (o^t - o^{t - n})
458+
self.motion_state0 = self._tlwh # original tlwh
451459
self.motion_state1 = self.buffer_bbox1.copy()
452460
self.motion_state2 = self.buffer_bbox2.copy()
453461

@@ -483,22 +491,38 @@ def re_activate(self, new_track, frame_id, new_id=False):
483491
# update stored bbox
484492
if (len(self.origin_bbox_buffer) > self.n):
485493
self.origin_bbox_buffer.popleft()
486-
self.origin_bbox_buffer.append(self._tlwh)
487-
else:
488-
self.origin_bbox_buffer.append(self._tlwh)
494+
495+
self.origin_bbox_buffer.append(self._tlwh)
489496

490497
self.buffer_bbox1 = self.get_buffer_bbox(level=1)
491498
self.buffer_bbox2 = self.get_buffer_bbox(level=2)
499+
500+
self.motion_state0 = self._tlwh
492501
self.motion_state1 = self.buffer_bbox1.copy()
493502
self.motion_state2 = self.buffer_bbox2.copy()
494503

504+
def predict(self):
505+
# Note that in C-BIoU Tracker, no need to use Kalman Filter
506+
self.time_since_update += 1
507+
508+
# Average motion model: s^{t + \delta} = o^t + (\delta / n) * (o^t - o^{t - n})
509+
assert len(self.origin_bbox_buffer), 'The bbox buffer is empty'
510+
511+
motion_state = self.origin_bbox_buffer[-1] + \
512+
(self.time_since_update / len(self.origin_bbox_buffer)) * (self.origin_bbox_buffer[-1] - self.origin_bbox_buffer[0])
513+
514+
self.motion_state0 = motion_state
515+
self.motion_state1 = self.get_buffer_bbox(level=1, bbox=motion_state)
516+
self.motion_state2 = self.get_buffer_bbox(level=2, bbox=motion_state)
517+
518+
495519
def update(self, new_track, frame_id):
496520
self.frame_id = frame_id
497521

498522
new_tlwh = new_track.tlwh
499523
self.score = new_track.score
500524

501-
self.kalman_filter.update(self.convert_func(new_tlwh))
525+
# self.kalman_filter.update(self.convert_func(new_tlwh)) # no need to use Kalman Filter
502526

503527
self.state = TrackState.Tracked
504528
self.is_activated = True
@@ -508,25 +532,15 @@ def update(self, new_track, frame_id):
508532
# update stored bbox
509533
if (len(self.origin_bbox_buffer) > self.n):
510534
self.origin_bbox_buffer.popleft()
511-
self.origin_bbox_buffer.append(new_tlwh)
512-
else:
513-
self.origin_bbox_buffer.append(new_tlwh)
514-
515-
# update motion state
516-
if self.time_since_update: # have some unmatched frames
517-
if len(self.origin_bbox_buffer) < self.n:
518-
self.motion_state1 = self.get_buffer_bbox(level=1, bbox=new_tlwh)
519-
self.motion_state2 = self.get_buffer_bbox(level=2, bbox=new_tlwh)
520-
else: # s^{t + \delta} = o^t + (\delta / n) * (o^t - o^{t - n})
521-
motion_state = self.origin_bbox_buffer[-1] + \
522-
(self.time_since_update / self.n) * (self.origin_bbox_buffer[-1] - self.origin_bbox_buffer[0])
523-
self.motion_state1 = self.get_buffer_bbox(level=1, bbox=motion_state)
524-
self.motion_state2 = self.get_buffer_bbox(level=2, bbox=motion_state)
525-
526-
else: # no unmatched frames, use current detection as motion state
527-
self.motion_state1 = self.get_buffer_bbox(level=1, bbox=new_tlwh)
528-
self.motion_state2 = self.get_buffer_bbox(level=2, bbox=new_tlwh)
535+
self.origin_bbox_buffer.append(new_tlwh)
529536

537+
# Drop kalman filter, rewrite the tlwh function
538+
@property
539+
def tlwh(self):
540+
"""Get current position in bounding box format `(top left x, top left y,
541+
width, height)`.
542+
"""
543+
return self.motion_state0
530544

531545
class Tracklet_w_depth(Tracklet):
532546
"""

0 commit comments

Comments
 (0)