5
5
from pathlib import Path
6
6
import numpy as np
7
7
from tqdm import tqdm
8
+ import configparser
8
9
import shutil
9
10
import json
10
11
import queue
@@ -235,13 +236,16 @@ def generate_dets_embs(args: argparse.Namespace, y: Path, source: Path) -> None:
235
236
np .savetxt (f , embs , fmt = '%f' )
236
237
237
238
238
- def generate_mot_results (args : argparse .Namespace , config_dict : dict = None ) -> None :
239
+ def generate_mot_results (args : argparse .Namespace , config_dict : dict = None ) -> dict [ str , np . ndarray ] :
239
240
"""
240
241
Generates MOT results for the specified arguments and configuration.
241
242
242
243
Args:
243
244
args (Namespace): Parsed command line arguments.
244
245
config_dict (dict, optional): Additional configuration dictionary.
246
+
247
+ Returns:
248
+ dict[str, np.ndarray]: {seq_name: array} with frame ids used for MOT
245
249
"""
246
250
args .device = select_device (args .device )
247
251
tracker = create_tracker (
@@ -267,19 +271,51 @@ def generate_mot_results(args: argparse.Namespace, config_dict: dict = None) ->
267
271
txt_path = args .exp_folder_path / (source .parent .name + '.txt' )
268
272
all_mot_results = []
269
273
270
- for frame_idx , d in enumerate (tqdm (dataset , desc = source .parent .name , leave = False )):
271
- if frame_idx == len (dataset ):
272
- break
274
+ # Change FPS
275
+ if args .fps :
276
+
277
+ # Extract original FPS
278
+ conf_path = source .parent / 'seqinfo.ini'
279
+ conf = configparser .ConfigParser ()
280
+ conf .read (conf_path )
281
+
282
+ orig_fps = int (conf .get ("Sequence" , "frameRate" ))
283
+
284
+ if orig_fps < args .fps :
285
+ LOGGER .warning (f"Original FPS ({ orig_fps } ) is lower than "
286
+ f"requested FPS ({ args .fps } ) for sequence "
287
+ f"{ source .parent .name } . Using original FPS." )
288
+ target_fps = orig_fps
289
+ else :
290
+ target_fps = args .fps
291
+
292
+
293
+ step = orig_fps / target_fps
294
+ else :
295
+ step = 1
296
+
297
+ # Create list with frame numbers according to needed step
298
+ frame_nums = np .arange (1 , len (dataset ) + 1 , step ).astype (int ).tolist ()
299
+
300
+ seq_frame_nums = {source .parent .name : frame_nums .copy ()}
301
+
302
+ for frame_num , d in enumerate (tqdm (dataset , desc = source .parent .name ), 1 ):
303
+ # Filter using list with needed numbers
304
+ if len (frame_nums ) > 0 :
305
+ if frame_num < frame_nums [0 ]:
306
+ continue
307
+ else :
308
+ frame_nums .pop (0 )
273
309
274
310
im = d [1 ][0 ]
275
- frame_dets_n_embs = dets_n_embs [dets_n_embs [:, 0 ] == frame_idx + 1 ]
311
+ frame_dets_n_embs = dets_n_embs [dets_n_embs [:, 0 ] == frame_num ]
276
312
277
313
dets = frame_dets_n_embs [:, 1 :7 ]
278
314
embs = frame_dets_n_embs [:, 7 :]
279
315
tracks = tracker .update (dets , im , embs )
280
316
281
317
if tracks .size > 0 :
282
- mot_results = convert_to_mot_format (tracks , frame_idx + 1 )
318
+ mot_results = convert_to_mot_format (tracks , frame_num )
283
319
all_mot_results .append (mot_results )
284
320
285
321
if all_mot_results :
@@ -289,6 +325,8 @@ def generate_mot_results(args: argparse.Namespace, config_dict: dict = None) ->
289
325
290
326
write_mot_results (txt_path , all_mot_results )
291
327
328
+ return seq_frame_nums
329
+
292
330
293
331
def parse_mot_results (results : str ) -> dict :
294
332
"""
@@ -340,6 +378,7 @@ def trackeval(args: argparse.Namespace, seq_paths: list, save_dir: Path, MOT_res
340
378
"--TRACKER_SUB_FOLDER" , "" ,
341
379
"--NUM_PARALLEL_CORES" , str (4 ),
342
380
"--SKIP_SPLIT_FOL" , "True" ,
381
+ "--GT_LOC_FORMAT" , "{gt_folder}/{seq}/gt/gt_temp.txt" ,
343
382
"--SEQ_INFO" , * d
344
383
]
345
384
@@ -384,7 +423,8 @@ def process_single_mot(opt: argparse.Namespace, d: Path, e: Path, evolve_config:
384
423
new_opt = copy .deepcopy (opt )
385
424
new_opt .dets_file_path = d
386
425
new_opt .embs_file_path = e
387
- generate_mot_results (new_opt , evolve_config )
426
+ frames_dict = generate_mot_results (new_opt , evolve_config )
427
+ return frames_dict
388
428
389
429
def run_generate_mot_results (opt : argparse .Namespace , evolve_config : dict = None ) -> None :
390
430
"""
@@ -427,16 +467,21 @@ def run_generate_mot_results(opt: argparse.Namespace, evolve_config: dict = None
427
467
# Submit the task to process this file pair in parallel
428
468
tasks .append (executor .submit (process_single_mot , opt , d , e , evolve_config ))
429
469
470
+ # Dict with {seq_name: [frame_nums]}
471
+ seqs_frame_nums = {}
430
472
# Wait for all tasks to complete and log any exceptions
431
473
for future in concurrent .futures .as_completed (tasks ):
432
474
try :
433
- future .result ()
475
+ seqs_frame_nums . update ( future .result () )
434
476
except Exception as exc :
435
477
LOGGER .error (f'Error processing file pair: { exc } ' )
436
478
437
479
# Postprocess data with gsi if requested
438
480
if opt .gsi :
439
- gsi (mot_results_folder = opt .exp_folder_path )
481
+ gsi (mot_results_folder = opt .exp_folder_path )
482
+
483
+ with open (opt .exp_folder_path / 'seqs_frame_nums.json' , 'w' ) as f :
484
+ json .dump (seqs_frame_nums , f )
440
485
441
486
442
487
def run_trackeval (opt : argparse .Namespace ) -> dict :
@@ -477,6 +522,7 @@ def parse_opt() -> argparse.Namespace:
477
522
parser .add_argument ('--reid-model' , nargs = '+' , type = Path , default = [WEIGHTS / 'osnet_x0_25_msmt17.pt' ], help = 'reid model path' )
478
523
parser .add_argument ('--source' , type = str , help = 'file/dir/URL/glob, 0 for webcam' )
479
524
parser .add_argument ('--imgsz' , '--img' , '--img-size' , nargs = '+' , type = int , default = None , help = 'inference size h,w' )
525
+ parser .add_argument ('--fps' , type = int , default = None , help = 'video frame-rate' )
480
526
parser .add_argument ('--conf' , type = float , default = 0.01 , help = 'min confidence threshold' )
481
527
parser .add_argument ('--iou' , type = float , default = 0.7 , help = 'intersection over union (IoU) threshold for NMS' )
482
528
parser .add_argument ('--device' , default = '' , help = 'cuda device, i.e. 0 or 0,1,2,3 or cpu' )
0 commit comments