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.

Tracking before re-id. Tracking after re-id.

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)