Skip to content

Commit 13486e4

Browse files
committed
add tracktrack, improassoc, re arrange all codes
1 parent ae28142 commit 13486e4

29 files changed

+1564
-1140
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ In addition, you can also specify
230230

231231
- Hybrid SORT: `python tracker/track.py --dataset visdrone_part --detector yolo_ultra --tracker hybridsort --kalman_format hybridsort --detector_model_path weights/yolov8l_VisDrone_35epochs_20230509.pt --save_images`
232232

233+
- ImproAssoc: `python tracker/track.py --dataset visdrone_part --detector yolo_ultra --tracker improassoc --kalman_format bot --detector_model_path weights/yolov8l_VisDrone_35epochs_20230509.pt --save_images`
234+
235+
- TrackTrack: `python tracker/track.py --dataset visdrone_part --detector yolo_ultra --tracker tracktrack --kalman_format bot --detector_model_path weights/yolov8l_VisDrone_35epochs_20230509.pt --save_images --nms_thresh 0.95 --reid`
236+
233237
> **Important notes for UCMC Track:**
234238
>
235239
> 1. Camera parameters. The UCMC Track need the intrinsic and extrinsic parameter of camera. Please organize like the format of `tracker/cam_param_files/uavdt/M0101.txt`. One video sequence corresponds to one txt file. If you do not have the labelled parameters, you can refer to the estimating toolbox in original repo ([https://github.com/corfyi/UCMCTrack](https://github.com/corfyi/UCMCTrack)).

requirements.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
numpy
2-
cython-bbox==0.1.3
2+
Cython
33
loguru
44
motmetrics==1.4.0
55
ninja
6+
opencv-python
67

78
pandas
89
Pillow
@@ -11,6 +12,7 @@ PyYAML
1112

1213
scikit-learn
1314
scipy
15+
filterpy
1416
seaborn
1517

1618
thop
@@ -22,3 +24,5 @@ tqdm
2224
wandb
2325

2426
gdown
27+
28+
ultralytics

tracker/config_files/visdrone_part.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Config file of VisDrone dataset
22

3-
DATASET_ROOT: '/data/wujiapeng/datasets/VisDrone2019/VisDrone2019'
3+
DATASET_ROOT: '/root/datasets/visdrone/'
44
SPLIT: val
55
CATEGORY_NAMES:
66
- 'pedestrain'

tracker/track.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
from trackers.sparse_tracker import SparseTracker
3131
from trackers.ucmc_tracker import UCMCTracker
3232
from trackers.hybridsort_tracker import HybridSortTracker
33+
from trackers.tracktrack_tracker import TrackTrackTracker
34+
from trackers.improassoc_tracker import ImproAssocTracker
3335

3436
# YOLOX modules
3537
try:
@@ -74,7 +76,9 @@
7476
'strongsort': StrongSortTracker,
7577
'sparsetrack': SparseTracker,
7678
'ucmctrack': UCMCTracker,
77-
'hybridsort': HybridSortTracker
79+
'hybridsort': HybridSortTracker,
80+
'tracktrack': TrackTrackTracker,
81+
'improassoc': ImproAssocTracker
7882
}
7983

8084
def get_args():
@@ -90,13 +94,14 @@ def get_args():
9094

9195
parser.add_argument('--kalman_format', type=str, default='default', help='use what kind of Kalman, sort, deepsort, byte, etc.')
9296
parser.add_argument('--img_size', type=int, default=1280, help='image size, [h, w]')
93-
94-
parser.add_argument('--conf_thresh', type=float, default=0.2, help='filter detections')
97+
98+
# thresholds
99+
parser.add_argument('--conf_thresh', type=float, default=0.2, help='filter detections, serve as high conf thresh in two-stage association')
95100
parser.add_argument('--conf_thresh_low', type=float, default=0.1, help='filter low conf detections, used in two-stage association')
96-
parser.add_argument('--nms_thresh', type=float, default=0.7, help='thresh for NMS')
97-
parser.add_argument('--iou_thresh', type=float, default=0.5, help='IOU thresh to filter tracks')
101+
parser.add_argument('--init_thresh', type=float, default=0.3, help='filter new detections, larger than this thresh consider as new tracklet')
102+
parser.add_argument('--nms_thresh', type=float, default=0.45, help='thresh for NMS')
98103

99-
parser.add_argument('--device', type=str, default='6', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
104+
parser.add_argument('--device', type=str, default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
100105

101106
"""yolox"""
102107
parser.add_argument('--yolox_exp_file', type=str, default='./tracker/yolox_utils/yolox_m.py')
@@ -121,9 +126,15 @@ def get_args():
121126

122127
parser.add_argument('--track_eval', type=bool, default=True, help='Use TrackEval to evaluate')
123128

129+
parser.add_argument('--cmc_method', type=str, default='orb', help='feature discriptor in camera motion compensation')
130+
124131
"""camera parameter"""
125132
parser.add_argument('--camera_parameter_folder', type=str, default='./tracker/cam_param_files', help='folder path of camera parameter files')
126133

134+
135+
"""tensorrt options"""
136+
parser.add_argument('--tensorrt', action='store_true', help='use tensorrt engine to detect and reid')
137+
127138
return parser.parse_args()
128139

129140
def main(args, dataset_cfgs):
@@ -291,7 +302,7 @@ def main(args, dataset_cfgs):
291302
timer.toc()
292303

293304
if args.save_images:
294-
plot_img(img=ori_img, frame_id=frame_idx, results=[cur_tlwh, cur_id, cur_cls],
305+
plot_img(img=ori_img, frame_id=frame_idx + 1, results=[cur_tlwh, cur_id, cur_cls],
295306
save_dir=os.path.join(save_dir, 'vis_results'))
296307

297308
save_results(save_dir=save_dir,

tracker/track_demo.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
from trackers.sparse_tracker import SparseTracker
3030
from trackers.ucmc_tracker import UCMCTracker
3131
from trackers.hybridsort_tracker import HybridSortTracker
32+
from trackers.tracktrack_tracker import TrackTrackTracker
33+
from trackers.improassoc_tracker import ImproAssocTracker
3234

3335
# YOLOX modules
3436
try:
@@ -73,7 +75,9 @@
7375
'strongsort': StrongSortTracker,
7476
'sparsetrack': SparseTracker,
7577
'ucmctrack': UCMCTracker,
76-
'hybridsort': HybridSortTracker
78+
'hybridsort': HybridSortTracker,
79+
'tracktrack': TrackTrackTracker,
80+
'improassoc': ImproAssocTracker
7781
}
7882

7983
def get_args():
@@ -93,8 +97,8 @@ def get_args():
9397

9498
parser.add_argument('--conf_thresh', type=float, default=0.2, help='filter tracks')
9599
parser.add_argument('--conf_thresh_low', type=float, default=0.1, help='filter low conf detections, used in two-stage association')
100+
parser.add_argument('--init_thresh', type=float, default=0.3, help='filter new detections, larger than this thresh consider as new tracklet')
96101
parser.add_argument('--nms_thresh', type=float, default=0.7, help='thresh for NMS')
97-
parser.add_argument('--iou_thresh', type=float, default=0.5, help='IOU thresh to filter tracks')
98102

99103
parser.add_argument('--device', type=str, default='6', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
100104

@@ -122,6 +126,8 @@ def get_args():
122126

123127
parser.add_argument('--track_eval', type=bool, default=True, help='Use TrackEval to evaluate')
124128

129+
parser.add_argument('--cmc_method', type=str, default='orb', help='feature discriptor in camera motion compensation')
130+
125131
"""camera parameter"""
126132
parser.add_argument('--camera_parameter_folder', type=str, default='./tracker/cam_param_files', help='folder path of camera parameter files')
127133
return parser.parse_args()
@@ -265,7 +271,7 @@ def main(args):
265271
results.append((frame_idx + 1, cur_id, cur_tlwh, cur_cls, cur_score))
266272

267273
if args.save_images:
268-
plot_img(img=ori_img, frame_id=frame_idx, results=[cur_tlwh, cur_id, cur_cls],
274+
plot_img(img=ori_img, frame_id=frame_idx + 1, results=[cur_tlwh, cur_id, cur_cls],
269275
save_dir=os.path.join(save_dir, save_obj_name, 'vis_results'))
270276

271277
save_results(save_dir=save_dir,

tracker/trackers/basetrack.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
"""
2+
Base class of Tracklets, used in tracklet.py
3+
"""
4+
15
import numpy as np
26
from collections import OrderedDict
37

tracker/trackers/basetracker.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
"""
2+
Base class for every tracker, embedded some general codes
3+
like init, get_features and tracklet merge
4+
for code clearity
5+
"""
6+
7+
import numpy as np
8+
import torch
9+
from .reid_models.engine import crop_and_resize
10+
from .matching import iou_distance
11+
12+
class BaseTracker(object):
13+
def __init__(self, args, frame_rate=30):
14+
15+
self.tracked_tracklets = [] # list[Tracklet]
16+
self.lost_tracklets = [] # list[Tracklet]
17+
self.removed_tracklets = [] # list[Tracklet]
18+
19+
self.frame_id = 0
20+
self.args = args
21+
22+
self.init_thresh = args.init_thresh
23+
self.buffer_size = int(frame_rate / 30.0 * args.track_buffer)
24+
self.max_time_lost = self.buffer_size
25+
26+
self.motion = args.kalman_format
27+
28+
def update(self, output_results, img, ori_img):
29+
raise NotImplementedError
30+
31+
@torch.no_grad()
32+
def get_feature(self, tlwhs, ori_img):
33+
"""
34+
get apperance feature of an object
35+
tlwhs: shape (num_of_objects, 4)
36+
ori_img: original image, np.ndarray, shape(H, W, C)
37+
"""
38+
39+
if tlwhs.size == 0:
40+
return np.empty((0, 512))
41+
42+
crop_bboxes = crop_and_resize(tlwhs, ori_img, input_format='tlwh', sz=(64, 128))
43+
features = self.reid_model(crop_bboxes).cpu().numpy()
44+
45+
return features
46+
47+
48+
def merge_tracklets(self, activated_tracklets, refind_tracklets, lost_tracklets, removed_tracklets):
49+
"""
50+
update tracklets with current association results
51+
"""
52+
self.tracked_tracklets = BaseTracker.joint_tracklets(self.tracked_tracklets, activated_tracklets)
53+
self.tracked_tracklets = BaseTracker.joint_tracklets(self.tracked_tracklets, refind_tracklets)
54+
self.lost_tracklets = BaseTracker.sub_tracklets(self.lost_tracklets, self.tracked_tracklets)
55+
self.lost_tracklets.extend(lost_tracklets)
56+
self.lost_tracklets = BaseTracker.sub_tracklets(self.lost_tracklets, self.removed_tracklets)
57+
self.removed_tracklets.extend(removed_tracklets)
58+
self.tracked_tracklets, self.lost_tracklets = BaseTracker.remove_duplicate_tracklets(self.tracked_tracklets, self.lost_tracklets)
59+
60+
@staticmethod
61+
def joint_tracklets(tlista, tlistb):
62+
exists = {}
63+
res = []
64+
for t in tlista:
65+
exists[t.track_id] = 1
66+
res.append(t)
67+
for t in tlistb:
68+
tid = t.track_id
69+
if not exists.get(tid, 0):
70+
exists[tid] = 1
71+
res.append(t)
72+
return res
73+
74+
@staticmethod
75+
def sub_tracklets(tlista, tlistb):
76+
tracklets = {}
77+
for t in tlista:
78+
tracklets[t.track_id] = t
79+
for t in tlistb:
80+
tid = t.track_id
81+
if tracklets.get(tid, 0):
82+
del tracklets[tid]
83+
return list(tracklets.values())
84+
85+
@staticmethod
86+
def remove_duplicate_tracklets(trackletsa, trackletsb):
87+
pdist = iou_distance(trackletsa, trackletsb)
88+
pairs = np.where(pdist < 0.15)
89+
dupa, dupb = list(), list()
90+
for p, q in zip(*pairs):
91+
timep = trackletsa[p].frame_id - trackletsa[p].start_frame
92+
timeq = trackletsb[q].frame_id - trackletsb[q].start_frame
93+
if timep > timeq:
94+
dupb.append(q)
95+
else:
96+
dupa.append(p)
97+
resa = [t for i, t in enumerate(trackletsa) if not i in dupa]
98+
resb = [t for i, t in enumerate(trackletsb) if not i in dupb]
99+
return resa, resb

0 commit comments

Comments
 (0)