How to Export Tracking Results to MOT Challenge Format in BoxMOT

BoxMOT automatically exports tracking results to the MOT Challenge format using the convert_to_mot_format and write_mot_results utilities, accessible via the boxmot eval CLI command or direct Python API calls.

The BoxMOT library (mikel-brostrom/boxmot) simplifies multi-object tracking evaluation by converting tracker outputs into the standardized MOT Challenge text format. This eliminates manual post-processing and ensures compatibility with official evaluation servers for benchmarks like MOT17 and MOT20.

Understanding the MOT Challenge Export Pipeline

BoxMOT implements a three-stage export pipeline that translates raw tracker outputs into submission-ready text files. The core utilities reside in boxmot/utils/mot_utils.py and are orchestrated by boxmot/engine/evaluator.py:

  1. convert_to_mot_format – Transforms detection arrays or Ultralytics Results objects into a NumPy matrix with nine columns matching the MOT specification. Implemented at lines 92-124 of boxmot/utils/mot_utils.py.
  2. write_mot_results – Handles directory creation and appends formatted rows to sequence-specific text files using the format string "%d,%d,%d,%d,%d,%d,%d,%d,%.6f". Implemented at lines 43-66 of boxmot/utils/mot_utils.py.
  3. run_generate_mot_results – The high-level entry point invoked by the CLI and evolutionary tuner, which iterates over sequences, applies the tracker, and coordinates the conversion and writing process. Implemented around line 860 of boxmot/engine/evaluator.py.

Data Conversion Specifications

The conversion supports two input types and produces a standardized nine-column output (frame, ID, left, top, width, height, conf, class, ignore):

For NumPy arrays with shape (N, 7) containing xmin, ymin, xmax, ymax, id, conf, cls:

  • Converts bounding boxes from xyxy to ltwh (left-top-width-height) format using ops.xyxy2ltwh
  • Generates 1-based frame indices (adds 1 to the 0-based frame index)
  • Appends a constant "not ignored" flag (1) and adjusts class indices to 1-based (cls + 1)

For Ultralytics Results objects:

  • Extracts boxes.id, boxes.xyxy, boxes.cls, and boxes.conf tensors
  • Applies identical coordinate transformation and column ordering

Exporting from the Command Line

The fastest method to generate MOT Challenge files uses the built-in evaluation command, which automates the entire pipeline:

boxmot eval \
    yolov8n \
    osnet_x0_25_msmt17 \
    deepocsort \
    --source MOT17-mini/train \
    --benchmark MOT17

During execution, the system:

  • Loads sequences using boxmot.utils.dataloaders.dataset.MOTDataset
  • Processes each frame through the specified tracker
  • Converts detections via convert_to_mot_format
  • Writes results to runs/mot/<benchmark>/<exp_folder>/<sequence>.txt

The generated files are immediately compatible with the official MOT Challenge evaluation toolkit.

Exporting Programmatically with Python

For integration into custom workflows, BoxMOT exposes both high-level dataset processors and low-level conversion helpers.

High-Level Dataset Export

Use run_generate_mot_results to process entire MOT datasets:

from pathlib import Path
import argparse
from boxmot.engine.evaluator import run_generate_mot_results

args = argparse.Namespace(
    source=Path("MOT17-mini/train"),
    project=Path("runs"),
    yolo_model=[Path("yolox_s.pt")],
    reid_model=[Path("osnet_x0_25_msmt17.pt")],
    tracking_method="deepocsort",
    benchmark="MOT17",
    fps=None,
    device="cuda",
    exp_dir=None,
)

run_generate_mot_results(args)

Low-Level Frame-by-Frame Export

For custom trackers or real-time applications, use the utility functions directly:

import numpy as np
from pathlib import Path
from boxmot.utils.mot_utils import convert_to_mot_format, write_mot_results

# Detections for frame 15 (0-based): xmin, ymin, xmax, ymax, track_id, conf, cls

detections = np.array([
    [100, 50, 200, 150, 1, 0.94, 0],
    [300, 200, 400, 300, 2, 0.88, 1],
])

# Convert to MOT format (returns shape (N, 9))

mot_frame = convert_to_mot_format(detections, frame_idx=15)

# Output columns: frame(16), ID, left, top, width, height, ignore(1), conf, class(cls+1)

txt_path = Path("runs/mot/MOT17-05.txt")
write_mot_results(txt_path, mot_frame)

Key Implementation Files

Understanding the source structure enables customization of the export behavior:

  • boxmot/utils/mot_utils.py – Contains convert_to_mot_format (lines 92-124) and write_mot_results (lines 43-66), handling the core format transformation and file I/O operations.
  • boxmot/engine/evaluator.py – Implements run_generate_mot_results (around line 860), the orchestration layer used by the CLI and evaluation tools.
  • boxmot/utils/dataloaders/dataset.py – Provides MOTDataset and MOTSequence classes that the exporter uses to iterate through frame sequences.

Summary

  • BoxMOT exports tracking results to MOT Challenge format via dedicated utilities in boxmot/utils/mot_utils.py, producing nine-column text files with ltwh coordinates.
  • The CLI command boxmot eval provides turnkey export for entire benchmarks with automatic directory management.
  • Python APIs range from high-level batch processing (run_generate_mot_results) to per-frame conversion (convert_to_mot_format and write_mot_results).
  • The export uses 1-based indexing for frame numbers and class IDs, matching official MOT Challenge specifications.

Frequently Asked Questions

What is the exact column format of the exported MOT Challenge files?

The exported text files contain nine comma-separated values: frame number (1-based), tracking ID, left coordinate, top coordinate, width, height, ignore flag (always 1), class ID (1-based), and confidence score. This structure adheres to the MOT Challenge submission format required by evaluation servers.

Can I export results from a custom tracker not included in BoxMOT?

Yes. If your tracker outputs NumPy arrays with shape (N, 7) containing xmin, ymin, xmax, ymax, track_id, confidence, class_id, you can pass these arrays directly to convert_to_mot_format followed by write_mot_results without using BoxMOT's built-in tracker implementations.

How does BoxMOT handle different bounding box coordinate formats?

The convert_to_mot_format function internally uses ops.xyxy2ltwh to convert from corner coordinates (xmin, ymin, xmax, ymax) to the left-top-width-height format required by MOT Challenge. Input data must be in xyxy format; if your data uses xywh or other formats, convert to xyxy before calling the export functions.

Where are the exported files saved when using the CLI?

By default, results are stored under runs/mot/<benchmark>/<experiment_folder>/, where <benchmark> corresponds to your --benchmark argument (e.g., "MOT17") and <experiment_folder> is automatically generated based on the model configuration and timestamp.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →