Skip to content

Examples

Code examples demonstrating motcpp features.

Quick Examples

Minimal Tracking

#include <motcpp/trackers/bytetrack.hpp>

int main() {
    motcpp::trackers::ByteTrack tracker;

    cv::Mat frame = cv::imread("frame.jpg");

    // Detections: [x1, y1, x2, y2, conf, class]
    Eigen::MatrixXf dets(2, 6);
    dets << 100, 100, 200, 200, 0.9, 0,
            300, 300, 400, 400, 0.8, 0;

    // Track
    auto tracks = tracker.update(dets, frame);

    std::cout << "Tracked " << tracks.rows() << " objects\n";
    return 0;
}

Video Processing

#include <motcpp/trackers/ocsort.hpp>
#include <opencv2/opencv.hpp>

int main(int argc, char** argv) {
    cv::VideoCapture cap(argv[1]);
    motcpp::trackers::OCSort tracker;

    cv::Mat frame;
    while (cap.read(frame)) {
        Eigen::MatrixXf dets = detect(frame);  // Your detector
        auto tracks = tracker.update(dets, frame);

        visualize(frame, tracks);
        cv::imshow("Tracking", frame);
        if (cv::waitKey(1) == 27) break;
    }
    return 0;
}

Per-Class Tracking

#include <motcpp/trackers/bytetrack.hpp>

int main() {
    // Enable per-class tracking
    motcpp::trackers::ByteTrack tracker(
        0.3f,   // det_thresh
        30,     // max_age
        50,     // max_obs
        3,      // min_hits
        0.3f,   // iou_threshold
        true,   // per_class = TRUE
        80      // nr_classes
    );

    // Detections with different classes
    Eigen::MatrixXf dets(3, 6);
    dets << 100, 100, 200, 200, 0.9, 0,   // Person
            300, 300, 400, 400, 0.8, 2,   // Car
            500, 100, 600, 200, 0.7, 0;   // Person

    auto tracks = tracker.update(dets, frame);
    // Each class tracked independently
    return 0;
}

Oriented Bounding Boxes

#include <motcpp/trackers/sort.hpp>

int main() {
    // Enable OBB tracking
    motcpp::trackers::Sort tracker(
        0.3f, 1, 50, 3, 0.3f,
        false, 80, "iou_obb",
        true  // is_obb = TRUE
    );

    // OBB format: [cx, cy, w, h, angle, conf, class]
    Eigen::MatrixXf obb_dets(1, 7);
    obb_dets << 150, 150, 100, 50, 0.785, 0.9, 0;  // 45 degrees

    auto tracks = tracker.update(obb_dets, frame);
    return 0;
}

Complete Examples

1. Pedestrian Tracking

Full example for pedestrian tracking with visualization.

// examples/pedestrian_tracking.cpp
#include <motcpp/trackers/bytetrack.hpp>
#include <opencv2/opencv.hpp>
#include <fstream>
#include <sstream>

// Load detections from file (MOT format)
Eigen::MatrixXf load_detections(const std::string& path, int frame_id) {
    std::vector<std::vector<float>> dets;
    std::ifstream file(path);
    std::string line;

    while (std::getline(file, line)) {
        std::stringstream ss(line);
        std::string token;
        std::vector<float> det;

        while (std::getline(ss, token, ',')) {
            det.push_back(std::stof(token));
        }

        if (static_cast<int>(det[0]) == frame_id) {
            // Convert [frame,id,x,y,w,h,conf,...] to [x1,y1,x2,y2,conf,cls]
            dets.push_back({
                det[2],              // x1
                det[3],              // y1
                det[2] + det[4],     // x2
                det[3] + det[5],     // y2
                det[6],              // conf
                0                    // class (pedestrian)
            });
        }
    }

    Eigen::MatrixXf result(dets.size(), 6);
    for (size_t i = 0; i < dets.size(); ++i) {
        for (int j = 0; j < 6; ++j) {
            result(i, j) = dets[i][j];
        }
    }
    return result;
}

int main(int argc, char** argv) {
    if (argc < 3) {
        std::cerr << "Usage: " << argv[0] << " <video> <detections>\n";
        return 1;
    }

    cv::VideoCapture cap(argv[1]);
    std::string det_path = argv[2];

    // Optimized ByteTrack for pedestrians
    motcpp::trackers::ByteTrack tracker(
        0.25f,  // Lower threshold for partial occlusions
        50,     // Longer max_age for crowded scenes
        100,    // More observation history
        2,      // Quick confirmation
        0.3f,   // Standard IoU threshold
        false,  // Single class
        1,      // Only pedestrians
        "iou",  // Standard IoU
        false,  // Axis-aligned boxes
        0.1f,   // Include low-confidence detections
        0.4f,   // Track threshold
        0.85f,  // Match threshold
        50,     // Track buffer
        30.0f   // 30 FPS
    );

    cv::Mat frame;
    int frame_id = 1;

    // Track statistics
    std::set<int> unique_ids;
    int total_tracks = 0;

    while (cap.read(frame)) {
        auto dets = load_detections(det_path, frame_id);
        auto tracks = tracker.update(dets, frame);

        // Update statistics
        for (int i = 0; i < tracks.rows(); ++i) {
            unique_ids.insert(static_cast<int>(tracks(i, 4)));
        }
        total_tracks += tracks.rows();

        // Visualize
        for (int i = 0; i < tracks.rows(); ++i) {
            int x1 = tracks(i, 0), y1 = tracks(i, 1);
            int x2 = tracks(i, 2), y2 = tracks(i, 3);
            int id = tracks(i, 4);

            auto color = motcpp::BaseTracker::id_to_color(id);
            cv::rectangle(frame, {x1, y1}, {x2, y2}, color, 2);

            std::string label = "ID:" + std::to_string(id);
            int baseline;
            auto size = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 
                                        0.5, 1, &baseline);
            cv::rectangle(frame, {x1, y1 - size.height - 4}, 
                         {x1 + size.width, y1}, color, -1);
            cv::putText(frame, label, {x1, y1 - 2}, 
                       cv::FONT_HERSHEY_SIMPLEX, 0.5, {255, 255, 255}, 1);
        }

        // Display stats
        std::string stats = "Frame: " + std::to_string(frame_id) + 
                           " | Tracks: " + std::to_string(tracks.rows()) +
                           " | Unique IDs: " + std::to_string(unique_ids.size());
        cv::putText(frame, stats, {10, 30}, cv::FONT_HERSHEY_SIMPLEX, 
                   0.7, {0, 255, 0}, 2);

        cv::imshow("Pedestrian Tracking", frame);
        if (cv::waitKey(1) == 27) break;

        ++frame_id;
    }

    std::cout << "\n=== Tracking Summary ===\n";
    std::cout << "Total frames: " << frame_id - 1 << "\n";
    std::cout << "Unique IDs: " << unique_ids.size() << "\n";
    std::cout << "Avg tracks/frame: " << total_tracks / (frame_id - 1.0) << "\n";

    return 0;
}

2. Multi-Camera Tracking

Track objects across multiple camera views.

// examples/multi_camera.cpp
#include <motcpp/trackers/strongsort.hpp>
#include <thread>
#include <map>

struct CameraTracker {
    std::unique_ptr<motcpp::trackers::StrongSORT> tracker;
    int camera_id;
    std::map<int, Eigen::VectorXf> track_embeddings;
};

// Match tracks across cameras using embeddings
std::map<std::pair<int,int>, int> match_cross_camera(
    const std::vector<CameraTracker>& cameras,
    float threshold = 0.5f) {

    std::map<std::pair<int,int>, int> global_ids;
    int next_global_id = 1;

    // For each pair of cameras
    for (size_t i = 0; i < cameras.size(); ++i) {
        for (size_t j = i + 1; j < cameras.size(); ++j) {
            // Compare embeddings
            for (auto& [id1, emb1] : cameras[i].track_embeddings) {
                for (auto& [id2, emb2] : cameras[j].track_embeddings) {
                    float dist = (emb1 - emb2).norm();
                    if (dist < threshold) {
                        // Same person across cameras
                        auto key_i = std::make_pair(cameras[i].camera_id, id1);
                        auto key_j = std::make_pair(cameras[j].camera_id, id2);

                        if (global_ids.count(key_i)) {
                            global_ids[key_j] = global_ids[key_i];
                        } else if (global_ids.count(key_j)) {
                            global_ids[key_i] = global_ids[key_j];
                        } else {
                            global_ids[key_i] = next_global_id;
                            global_ids[key_j] = next_global_id;
                            ++next_global_id;
                        }
                    }
                }
            }
        }
    }

    return global_ids;
}

3. Streaming Integration

Integrate with video streaming protocols.

// examples/streaming.cpp
#include <motcpp/trackers/bytetrack.hpp>

int main() {
    // RTSP stream
    cv::VideoCapture cap("rtsp://camera_ip:554/stream");

    // Low-latency tracker settings
    motcpp::trackers::ByteTrack tracker(
        0.4f,   // Higher threshold for cleaner tracks
        10,     // Short max_age for responsiveness
        20,     // Limited history
        1,      // Immediate confirmation
        0.4f,   // Higher IoU threshold
        false, 80, "iou", false,
        0.2f, 0.5f, 0.9f, 10, 25.0f
    );

    cv::Mat frame;
    while (cap.read(frame)) {
        auto start = std::chrono::high_resolution_clock::now();

        Eigen::MatrixXf dets = fast_detector(frame);
        auto tracks = tracker.update(dets, frame);

        auto end = std::chrono::high_resolution_clock::now();
        auto latency = std::chrono::duration_cast<std::chrono::milliseconds>(
            end - start).count();

        // Ensure low latency
        if (latency > 33) {  // > 30 FPS
            std::cerr << "Warning: High latency " << latency << "ms\n";
        }

        // Send tracks downstream
        publish_tracks(tracks);
    }
    return 0;
}

File Index

File Description
simple_tracking.cpp Minimal tracking example
pedestrian_tracking.cpp Full pedestrian tracker
multi_camera.cpp Cross-camera tracking
streaming.cpp RTSP stream integration
benchmark.cpp Performance benchmarking
custom_tracker.cpp Implementing custom tracker