Multi object tracking
This page contains advanced examples for the tno.quantum.problems.mot package.
Requirements
Install the following dependencies to run the examples below:
pip install tno.quantum.problems.mot
pip install ultralytics
Example: getting detections with ultralytics
Starting from a video file, first generate a detection file compatible with ultralytics. This can be done, for example, with a pre-trained YOLO model, as shown below
1import csv
2from ultralytics import YOLO
3
4model = YOLO("path/to/model")
5video_path = "path/to/video"
6detections_csv_path = "path/to/output.csv"
7
8# Run inference frame-by-frame
9results = model(
10 video_path,
11 stream=True, # important for video
12 conf=0.25,
13)
14
15with open(detections_csv_path, mode="w", newline="") as f:
16 writer = csv.writer(f)
17 for frame_idx, r in enumerate(results):
18 if r.boxes is None:
19 continue
20
21 for box in r.boxes:
22 cls_id = int(box.cls[0])
23 conf = float(box.conf[0])
24 x, y, w, h = box.xywhn[0].tolist()
25
26 writer.writerow(
27 [
28 frame_idx,
29 cls_id,
30 f"{x:.6f}",
31 f"{y:.6f}",
32 f"{w:.6f}",
33 f"{h:.6f}",
34 f"{conf:.6f}",
35 ]
36 )
Example: re-id module
The following example shows how to run the tracking algorithm of ultralytics and the re-id module on top to fix an ID switch.
1import importlib.resources
2import pandas as pd
3
4from ultralytics.trackers import BOTSORT
5from ultralytics.utils import YAML, IterableSimpleNamespace
6
7from tno.quantum.problems.mot import (
8 DetectionSequence,
9 ultralytics_track,
10 FlowReID,
11)
12from tno.quantum.problems.mot.dataset import (
13 make_gif_with_detections,
14)
15
16# Load detections from CSV file
17detections_csv_path = "path/to/detections.csv"
18detections = pd.read_csv(detections_csv_path, header=None)
19detections = DetectionSequence.from_dataframe(detections)
20
21# Run ultralytics tracking algorithm
22tracker_path = str(
23 importlib.resources.files("ultralytics.cfg") / "trackers" / "botsort.yaml"
24)
25cfg = IterableSimpleNamespace(**YAML.load(tracker_path))
26tracker = BOTSORT(cfg, frame_rate=30)
27detections = ultralytics_track(detections, tracker)
28
29# Select a snippet that contains an ID loss
30first_frame = 253 # some frame
31last_frame = first_frame + 50
32detections_snippet = detections[first_frame:last_frame]
33flow_reid_obj = FlowReID()
34reid_detections_snippet = flow_reid_obj.run_classic(detections_snippet)
35
36# Create visualization
37video_path = "path/to/video"
38make_gif_with_detections(
39 detections_snippet,
40 input_filename=video_path,
41 output_filename="before.gif",
42 fps=20,
43 first_frame=first_frame,
44)
45make_gif_with_detections(
46 reid_detections_snippet,
47 input_filename=video_path,
48 output_filename="after.gif",
49 fps=20,
50 first_frame=first_frame,
51)
This results in the following video snippets.
Instead of selecting a frame sequence manually, use the pick_sequences method to find frame sequences where an ID loss or ID switch is suspected.
1import pandas as pd
2from tno.quantum.problems.mot import (
3 DetectionSequence,
4 FlowReID,
5)
6from tno.quantum.problems.mot.dataset import (
7 make_video_with_detections,
8)
9
10# Load detections from CSV file
11detections_csv_path = "path/to/detections.csv"
12detections = pd.read_csv(detections_csv_path, header=None)
13detections = DetectionSequence.from_dataframe(detections)
14
15# Pick sequences
16flow_reid_obj = FlowReID()
17sequences = flow_reid_obj.pick_sequences(detections)
18print(sequences)
19print(f"Found {len(sequences)} frame sequences for re-id.")
20
21# To run re-id continuously on each of the detected sequences, use
22# run_continuous_reid.
23reid_detections = flow_reid_obj.run_continuous_reid(detections)
24
25# Save the video after re-id
26make_video_with_detections(
27 reid_detections,
28 input_filename="example_video.avi",
29 output_filename="after.avi",
30 fps=50,
31)