# How to Export Tracking Results to MOT Challenge Format in BoxMOT

> Easily export tracking results to MOT Challenge format with BoxMOT. Learn to use the boxmot eval CLI or Python API for seamless conversion. Get started today.

- Repository: [Mike/boxmot](https://github.com/mikel-brostrom/boxmot)
- Tags: how-to-guide
- Published: 2026-03-07

---

**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`](https://github.com/mikel-brostrom/boxmot/blob/main/boxmot/utils/mot_utils.py) and are orchestrated by [`boxmot/engine/evaluator.py`](https://github.com/mikel-brostrom/boxmot/blob/main/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`](https://github.com/mikel-brostrom/boxmot/blob/main/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`](https://github.com/mikel-brostrom/boxmot/blob/main/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`](https://github.com/mikel-brostrom/boxmot/blob/main/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`](https://github.com/mikel-brostrom/boxmot/blob/main/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:

```bash
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:

```python
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:

```python
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`](https://github.com/mikel-brostrom/boxmot/blob/main/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`](https://github.com/mikel-brostrom/boxmot/blob/main/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`](https://github.com/mikel-brostrom/boxmot/blob/main/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`](https://github.com/mikel-brostrom/boxmot/blob/main/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.