#include <opencv2/opencv.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/tracking/tracking_legacy.hpp>
#include <iostream>

int main() {
    // 打开视频或摄像头
    cv::VideoCapture cap(0);  // 使用摄像头,或者替换为视频文件路径
    if (!cap.isOpened()) {
        std::cout << "无法打开视频源" << std::endl;
        return -1;
    }

    // 创建 MOSSE 跟踪器
    cv::Ptr<cv::legacy::TrackerMOSSE> tracker = cv::legacy::TrackerMOSSE::create();

    // 读取第一帧
    cv::Mat frame;
    cap >> frame;
    if (frame.empty()) {
        std::cout << "无法读取视频帧" << std::endl;
        return -1;
    }

    // 选择要跟踪的目标区域,使用 Rect2d
    cv::Rect2d bbox = cv::selectROI("跟踪", frame, false);

    // 初始化跟踪器
    tracker->init(frame, bbox);

    while (true) {
        // 读取新的一帧
        cap >> frame;
        if (frame.empty())
            break;

        // 更新跟踪器,使用 Rect2d
        bool ok = tracker->update(frame, bbox);

        if (ok) {
            // 绘制跟踪框
            cv::rectangle(frame, bbox, cv::Scalar(255, 0, 0), 2, 1);
        }
        else {
            // 跟踪失败
            cv::putText(frame, "Tracking failure", cv::Point(100, 80),
                cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(0, 0, 255), 2);
        }

        // 显示结果
        cv::imshow("跟踪", frame);

        // 按 ESC 键退出
        char c = (char)cv::waitKey(1);
        if (c == 27)
            break;
    }

    cap.release();
    cv::destroyAllWindows();
    return 0;
}

另外python版本的opencv也有追踪功能

4.x版本的话

import cv2
import sys


def main():
    # 1. 设置视频源:0 代表默认摄像头,也可以换成视频文件路径,例如 'video.mp4'
    video_path = "vtest.avi"
    cap = cv2.VideoCapture(video_path)

    if not cap.isOpened():
        print("无法打开视频源")
        sys.exit()

    # 2. 创建追踪器
    # OpenCV 4.x 推荐使用 CSRT,精度高;如果追求速度可以使用 KCF
    tracker = cv2.TrackerCSRT_create()

    # 状态标记
    is_tracking = False

    print("操作说明:")
    print("1. 视频正在播放...")
    print("2. 按下【空格键】暂停视频并开始框选对象")
    print("3. 鼠标框选后,再次按下【空格键】或【回车键】确认框选并开始追踪")
    print("4. 按下【ESC】退出程序")

    while True:
        # 读取一帧
        ret, frame = cap.read()
        if not ret:
            print("视频结束或无法读取")
            break

        # 如果正在追踪状态,更新追踪器
        if is_tracking:
            success, box = tracker.update(frame)
            if success:
                # box 返回的是 (x, y, w, h)
                (x, y, w, h) = [int(v) for v in box]
                # 画出矩形框
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
                cv2.putText(frame, "Tracking", (x, y - 10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
            else:
                cv2.putText(frame, "Lost", (50, 50),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

        # 显示当前帧
        cv2.imshow("Object Tracker (Space to Select)", frame)

        # 键盘监听
        key = cv2.waitKey(30) & 0xFF

        # 按下 ESC 退出
        if key == 27:
            break

        # 按下 空格键 (ASCII 32) 进入选择模式
        elif key == 32:
            print("--- 已暂停,请用鼠标框选对象 ---")
            print("--- 框选完成后,按 空格 或 回车 开始追踪 ---")

            # selectROI 是 OpenCV 自带的工具
            # 它会暂停画面,允许用户画框
            # 参数:窗口名,图像帧,是否从中心开始画(False),是否显示十字准星(False)
            bbox = cv2.selectROI("Object Tracker (Space to Select)", frame, fromCenter=False, showCrosshair=True)

            # bbox 返回 (x, y, w, h),如果用户取消选择通常返回全是0
            if bbox[2] > 0 and bbox[3] > 0:  # 宽度高度大于0
                # 重新创建追踪器(为了支持多次重新框选,每次都新建一个)
                tracker = cv2.TrackerCSRT_create()
                # 初始化追踪器
                tracker.init(frame, bbox)
                is_tracking = True
                print("--- 开始追踪 ---")
            else:
                print("--- 未选择对象,继续播放 ---")
                is_tracking = False

    # 释放资源
    cap.release()
    cv2.destroyAllWindows()


if __name__ == "__main__":
    main()

或者有模式选择的

import cv2
import sys

# ================= 配置区域 =================
# 可选模式: "csrt", "kcf", "mil", "boosting", "tld", "medianflow", "mosse"
# 推荐: "csrt" (最准), "kcf" (速度快), "mosse" (速度极快但不如kcf准)
TRACKER_TYPE = "csrt"


# ===========================================

def create_tracker(tracker_type):
    """
    根据名称创建追踪器工厂函数
    注意:在 OpenCV 4.x 中,部分老旧追踪器被移到了 cv2.legacy 包中
    """
    tracker_type = tracker_type.lower()

    # 核心追踪器 (直接可用)
    if tracker_type == 'csrt':
        return cv2.TrackerCSRT_create()
    elif tracker_type == 'kcf':
        return cv2.TrackerKCF_create()
    elif tracker_type == 'mil':
        return cv2.TrackerMIL_create()

    # Legacy 追踪器 (位于 opencv-contrib 的 legacy 模块中)
    # 如果报错 AttributeError,说明你可能没装 opencv-contrib-python 或者版本差异
    try:
        if tracker_type == 'boosting':
            return cv2.legacy.TrackerBoosting_create()
        elif tracker_type == 'tld':
            return cv2.legacy.TrackerTLD_create()
        elif tracker_type == 'medianflow':
            return cv2.legacy.TrackerMedianFlow_create()
        elif tracker_type == 'mosse':
            return cv2.legacy.TrackerMOSSE_create()
    except AttributeError:
        print(f"错误: 你的 OpenCV 版本似乎不支持 {tracker_type},请尝试 csrt 或 kcf")
        sys.exit()

    print(f"不支持的追踪器类型: {tracker_type}")
    sys.exit()


def main():
    # 1. 设置视频源
    video_path = "vtest.avi"
    cap = cv2.VideoCapture(video_path)

    if not cap.isOpened():
        print("无法打开视频源")
        sys.exit()

    # 初始化追踪器变量
    tracker = create_tracker(TRACKER_TYPE)
    is_tracking = False

    print(f"当前使用追踪器算法: 【{TRACKER_TYPE.upper()}】")
    print("-" * 40)
    print("操作说明:")
    print(" [空格键] : 暂停视频 -> 鼠标框选 -> 再次按空格/回车开始追踪")
    print(" [ESC键]  : 退出程序")
    print(" [C 键]   : 清除当前追踪目标 (不暂停)")
    print("-" * 40)

    while True:
        ret, frame = cap.read()
        if not ret:
            print("视频结束")
            break

        # 如果正在追踪
        if is_tracking:
            success, box = tracker.update(frame)
            if success:
                (x, y, w, h) = [int(v) for v in box]
                # 绘制追踪框
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

                # 显示算法名称
                cv2.putText(frame, f"{TRACKER_TYPE.upper()} Tracker", (x, y - 10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
            else:
                cv2.putText(frame, "Tracking Failed", (50, 80),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

        # 显示帮助信息
        info_text = "Tracking: ON" if is_tracking else "Tracking: OFF (Press Space)"
        color = (0, 255, 0) if is_tracking else (0, 255, 255)
        cv2.putText(frame, info_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2)

        cv2.imshow("Multi-Tracker Object Tracking", frame)

        # 键盘监听
        key = cv2.waitKey(30) & 0xFF

        # ESC 退出
        if key == 27:
            break

        # C 键清除追踪
        elif key == ord('c'):
            is_tracking = False
            print("--- 追踪已清除 ---")

        # 空格键:暂停并选择
        elif key == 32:
            print("\n--- 进入选择模式 ---")
            # 必须重新创建追踪器,否则旧的历史数据会干扰新的追踪
            tracker = create_tracker(TRACKER_TYPE)

            # 弹出选择框
            bbox = cv2.selectROI("Multi-Tracker Object Tracking", frame, fromCenter=False, showCrosshair=True)

            # 如果框选了区域 (宽和高 > 0)
            if bbox[2] > 0 and bbox[3] > 0:
                tracker.init(frame, bbox)
                is_tracking = True
                print(f"--- 目标已锁定,使用 {TRACKER_TYPE} 开始追踪 ---")
            else:
                is_tracking = False
                print("--- 未选择区域,取消追踪 ---")

    cap.release()
    cv2.destroyAllWindows()


if __name__ == "__main__":
    main()

老版本的opencv例如3.4.2.17可参考以下代码

如果需要更高的准确率,并且可以容忍延迟的话,使用CSRT

如果需要更快的FPS,并且可以容许稍低一点的准确率的话,使用KCF

如果纯粹的需要速度的话,用MOSSE。

import cv2
import sys

(major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')
if __name__ == '__main__':
    # Set up tracker.
    # Instead of MIL, you can also use
    tracker_types = ['BOOSTING', 'MIL', 'KCF', 'TLD', 'MEDIANFLOW', 'GOTURN', 'MOSSE', 'CSRT']
    tracker_type = tracker_types[2]
    if int(minor_ver) < 3:
        tracker = cv2.Tracker_create(tracker_type)
    else:
        if tracker_type == 'BOOSTING':
            tracker = cv2.TrackerBoosting_create()
        if tracker_type == 'MIL':
            tracker = cv2.TrackerMIL_create()
        if tracker_type == 'KCF':
            tracker = cv2.TrackerKCF_create()
        if tracker_type == 'TLD':
            tracker = cv2.TrackerTLD_create()
        if tracker_type == 'MEDIANFLOW':
            tracker = cv2.TrackerMedianFlow_create()
        if tracker_type == 'GOTURN':
            tracker = cv2.TrackerGOTURN_create()
        if tracker_type == 'MOSSE':
            tracker = cv2.TrackerMOSSE_create()
        if tracker_type == "CSRT":
            tracker = cv2.TrackerCSRT_create()
    # Read video
    video = cv2.VideoCapture("1.mp4")
    # Exit if video not opened.
    if not video.isOpened():
        print
        "Could not open video"
        sys.exit()
    # Read first frame.
    ok, frame = video.read()
    if not ok:
        print
        'Cannot read video file'
        sys.exit()

    # Define an initial bounding box
    bbox = (287, 23, 86, 320)
    # Uncomment the line below to select a different bounding box
    bbox = cv2.selectROI(frame, False)
    # Initialize tracker with first frame and bounding box
    ok = tracker.init(frame, bbox)
    while True:
        # Read a new frame
        ok, frame = video.read()
        if not ok:
            break
        # Start timer
        timer = cv2.getTickCount()
        # Update tracker
        ok, bbox = tracker.update(frame)
        # Calculate Frames per second (FPS)
        fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer);
        # Draw bounding box
        if ok:
            # Tracking success
            p1 = (int(bbox[0]), int(bbox[1]))
            p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))
            cv2.rectangle(frame, p1, p2, (255, 0, 0), 2, 1)
        else:
            # Tracking failure
            cv2.putText(frame, "Tracking failure detected", (100, 80), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)

        # Display tracker type on frame
        cv2.putText(frame, tracker_type + " Tracker", (100, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (50, 170, 50), 2);

        # Display FPS on frame
        cv2.putText(frame, "FPS : " + str(int(fps)), (100, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (50, 170, 50), 2);

        # Display result
        cv2.imshow("Tracking", frame)

        # Exit if ESC pressed
        k = cv2.waitKey(1) & 0xff
        if k == 27: break

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐