使用 Ultralytics YOLO 进行多目标跟踪#
在视频分析领域,对象跟踪是一项关键任务:它不仅要识别画面中对象的位置和类别,还要在视频播放过程中为每个检测到的对象持续维护唯一 ID。其应用范围几乎无穷无尽,从监控和安防到实时体育分析。
查看未发布的 YOLO27 预览版以了解计划中的追踪支持。
从 ultralytics 8.4.63 开始,OC-SORT、Deep OC-SORT、FastTracker 和 TrackTrack 与 BoT-SORT 和 ByteTrack 一起可用。
为什么选择 Ultralytics YOLO 进行对象跟踪?#
Ultralytics 跟踪器的输出与标准对象检测一致,同时增加了对象 ID。这让你可以轻松跟踪视频流中的对象,并执行后续分析。以下是你应该考虑使用 Ultralytics YOLO 满足对象跟踪需求的原因:
- **高效:**实时处理视频流,同时不影响准确率。
- **灵活:**支持多种跟踪算法和配置。
- **易于使用:**提供简单的 Python API 和 CLI 选项,便于快速集成和部署。
- **可定制:**可轻松配合自定义训练的 YOLO 模型使用,从而集成到特定领域的应用中。
Watch: How to Run Multi-Object Tracking with Ultralytics YOLO26 | BoT-SORT & ByteTrack | VisionAI 🚀
实际应用#
| 交通运输 | 零售 | 水产养殖 |
|---|---|---|
| 车辆跟踪 | 人员跟踪 | 鱼类跟踪 |
快速开始#
使用默认的 TrackTrack 跟踪器在视频上运行跟踪。更改 tracker 参数即可切换到其他跟踪器。
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
# Default tracker (TrackTrack)
results = model.track(source="https://youtu.be/LNwODJXcvt4", show=True)
# Switch to ByteTrack
results = model.track(source="https://youtu.be/LNwODJXcvt4", show=True, tracker="bytetrack.yaml")要在视频流上运行跟踪器,请使用经过训练的 Detect、Segment、Pose 或 OBB 模型,例如 YOLO26n、YOLO26n-seg、YOLO26n-pose 或 YOLO26n-obb。你可以在本地训练自定义模型,也可以使用 Ultralytics Platform 云训练。
from ultralytics import YOLO
# Load an official or custom model
model = YOLO("yolo26n.pt") # Load an official Detect model
model = YOLO("yolo26n-seg.pt") # Load an official Segment model
model = YOLO("yolo26n-pose.pt") # Load an official Pose model
model = YOLO("path/to/best.pt") # Load a custom-trained model
# Perform tracking with the model
results = model.track("https://youtu.be/LNwODJXcvt4", show=True) # Tracking with default tracker
results = model.track("https://youtu.be/LNwODJXcvt4", show=True, tracker="bytetrack.yaml") # with ByteTrack支持的跟踪器#
Ultralytics YOLO 内置六种跟踪器。将其 YAML 配置文件传递给 tracker 参数即可启用其中一种。
| 跟踪器 | 配置文件 | 运动模型 | 外观 / ReID | 相机运动补偿 | 遮挡处理 |
|---|---|---|---|---|---|
| BoT-SORT | botsort.yaml | 线性 Kalman | 可选(with_reid) | 可配置(gmc_method) | 跟踪缓冲区 + ReID 重新绑定 |
| ByteTrack | bytetrack.yaml | 线性 Kalman | 无 | 否 | 两阶段低置信度恢复 |
| OC-SORT | ocsort.yaml | 以观测为中心的 Kalman | 无 | 否 | ORU、OCM、OCR 从上次观测重新更新 |
| Deep OC-SORT | deepocsort.yaml | 以观测为中心的 Kalman | 可选(with_reid) | 可配置(gmc_method) | OC-SORT + 可选的自适应外观 EMA |
| FastTracker | fasttrack.yaml | 线性 Kalman + 回滚 | 无 | 否 | Kalman 回滚 + 遮挡时扩大 bbox |
| TrackTrack | tracktrack.yaml | 线性 Kalman(NSA) | 可选(with_reid) | 可配置(gmc_method) | 迭代式多线索关联 + TAI |
我应该使用哪个跟踪器?#
使用此流程选择起始方案;未传入 tracker 时会使用 tracktrack.yaml:
- 需要最快、最简单的基线? → ByteTrack(无 ReID、无相机运动补偿,开销最低)。
- 手持设备、无人机或移动相机拍摄的视频? → BoT-SORT(增加相机运动补偿和可选 ReID)。
- 非线性运动(体育、舞蹈、突然转向)且不需要 ReID? → OC-SORT(以观测为中心进行校正,不产生外观特征开销)。
- 在 ID 切换是主要问题的拥挤移动相机画面中? → Deep OC-SORT 或 TrackTrack(两者都支持可选的外观匹配;TrackTrack 还增加了多线索关联和重复 ID 抑制)。
- 实时场景中频繁发生部分重叠,且没有 ReID 预算? → FastTracker(支持遮挡感知并带有 Kalman 回滚的 ByteTrack 变体)。
切换跟踪器#
将跟踪器配置文件名传递给 tracker=。其他代码保持不变。
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
results = model.track(source="path/to/video.mp4", tracker="bytetrack.yaml")
results = model.track(source="path/to/video.mp4", tracker="ocsort.yaml")
results = model.track(source="path/to/video.mp4", tracker="tracktrack.yaml")配置#
跟踪参数#
跟踪配置与 Predict 模式共享一些属性,例如 conf、iou 和 show。如需进一步配置,请参阅 Predict 模型页面。
from ultralytics import YOLO
# Configure the tracking parameters and run the tracker
model = YOLO("yolo26n.pt")
results = model.track(source="https://youtu.be/LNwODJXcvt4", conf=0.1, iou=0.7, show=True)自定义跟踪器配置#
Ultralytics 还允许你使用修改后的跟踪器配置文件。为此,只需从 ultralytics/cfg/trackers 复制一份跟踪器配置文件(例如 custom_tracker.yaml),然后根据需要修改配置(tracker_type 除外)。
from ultralytics import YOLO
# Load the model and run the tracker with a custom configuration file
model = YOLO("yolo26n.pt")
results = model.track(source="https://youtu.be/LNwODJXcvt4", tracker="custom_tracker.yaml")共享跟踪器参数#
以下参数是大多数跟踪器 YAML 文件的通用参数;并非每个配置都包含所有参数:
大于或等于 track_high_thresh 的检测结果会进入第一阶段关联。介于 track_low_thresh 和 track_high_thresh 之间的检测结果可以在所选跟踪器启用低置信度关联时恢复现有跟踪,但不会启动新的跟踪。小于或等于 track_low_thresh 的检测结果会被忽略。
| 参数 | 有效值或范围 | 描述 |
|---|---|---|
tracker_type | botsort、bytetrack、ocsort、deepocsort、fasttrack、tracktrack | 指定跟踪器类型。 |
track_high_thresh | 0.0-1.0 | 第一阶段关联的阈值。影响检测结果与现有跟踪匹配时的置信程度。 |
track_low_thresh | 0.0-1.0 | 低置信度恢复检测结果的下限。OC-SORT 和 Deep OC-SORT 仅在 use_byte: True 时使用这些检测结果;TrackTrack 会将其纳入受惩罚的关联池。 |
new_track_thresh | 0.0-1.0 | 当检测结果与任何现有跟踪都不匹配时,初始化新跟踪的阈值。 |
track_buffer | >=0 | 移除前保留丢失跟踪的帧数。值越高,对遮挡的容忍度越高。 |
match_thresh | 0.0-1.0 | 跟踪匹配阈值。值越高,匹配越宽松。 |
fuse_score | True、False | 是否在匹配前将置信度分数与 IoU 距离融合。 |
gmc_method | sparseOptFlow、orb、sift、ecc、none | 全局运动补偿方法。帮助应对相机移动。 |
proximity_thresh | 0.0-1.0 | 有效 ReID 匹配所需的最小 IoU。确保在使用外观线索前具有足够的空间接近度。 |
appearance_thresh | 0.0-1.0 | ReID 所需的最小归一化外观相似度。 |
with_reid | True、False | 启用基于外观的匹配,以改善遮挡情况下的跟踪。BoT-SORT、Deep OC-SORT 和 TrackTrack 支持此功能。 |
model | auto 或兼容的 ReID 模型路径 | ReID 模型。auto 在可用时使用原生 YOLO 主干特征;否则回退到 yolo26n-cls.pt。自定义编码器可以是 .pt 检查点,也可以是导出的模型,例如 .torchscript、.onnx、.engine,或 OpenVINO 模型目录。 |
特定跟踪器参数#
每种算法都在共享参数之上提供额外的调节项。有关说明和调优建议,请参阅下方各跟踪器的章节,或直接查看配置文件:
启用 Re-Identification(ReID)#
默认禁用 ReID,以尽量减少开销。在跟踪器配置文件中设置 with_reid: True 即可启用。
ReID 模型选项:
model: auto— 使用原生 YOLO 检测器特征,仅增加极少开销。适合需要一定 ReID 能力但又不希望性能大幅下降的场景。如果检测器不提供兼容特征,则回退到yolo26n-cls.pt。- 自定义 ReID 模型 — 将
model:指向.pt检查点或兼容的导出嵌入模型,例如.torchscript、.onnx、.engine,或 OpenVINO 模型目录。导出的模型通过AutoBackend加载,并且必须直接输出嵌入张量。
每种模型尺寸都发布了可直接使用的 ONNX 编码器。将 model: 设置为其中一个名称后,文件会在跟踪器首次运行时自动下载(方式与获取 YOLO 权重相同),无需手动导出或下载:
# In your tracker config (e.g. tracktrack.yaml)
with_reid: True
model: yolo26n-reid.onnx # downloaded on first use; swap n→s/m/l/x for a larger encoder| 模型 | 大小 (像素) | 参数量 (M) | FLOPs (B) |
|---|---|---|---|
| YOLO26n-reid.onnx | 448 | 2.8 | 2.0 |
| YOLO26s-reid.onnx | 448 | 7.5 | 6.6 |
| YOLO26m-reid.onnx | 448 | 12.4 | 20.1 |
| YOLO26l-reid.onnx | 448 | 15.3 | 25.2 |
| YOLO26x-reid.onnx | 448 | 32.7 | 55.9 |
目前仅提供用于跟踪器外观分支的 ONNX ReID 编码器。ReID train、val 和 predict 模式,以及专用的 ReID 导出方案,仍在开发中。
如需配合独立的分类模型获得更佳性能,请将其导出到 TensorRT 等更快的后端:
from torch import nn
from ultralytics import YOLO
# Load the classification model
model = YOLO("yolo26n-cls.pt")
# Add average pooling layer
head = model.model.model[-1]
pool = nn.Sequential(nn.AdaptiveAvgPool2d((1, 1)), nn.Flatten(start_dim=1))
pool.f, pool.i = head.f, head.i
model.model.model[-1] = pool
# Export to TensorRT
model.export(format="engine", quantize=16, dynamic=True, batch=32)导出后,在跟踪器配置中指定 TensorRT 模型路径。
跟踪器详情#
以下部分介绍了每个追踪器的设计、特定参数和调优技巧。
Watch: Which Object Tracker Performs Better? | Speed, FPS & ID Stability | Ultralytics YOLO26 📊
BoT-SORT#
BoT-SORT(Aharon 等,2022)在 ByteTrack 的基础上增加了摄像机运动补偿和可选的 ReID:
- 摄像机运动补偿 (CMC): 每帧估计一个仿射变换(默认使用稀疏光流,也支持 ORB / ECC),并在 IoU 匹配前将其应用于 Kalman 状态。
- 可选 ReID: 外观嵌入可以融合到代价矩阵中。默认禁用;使用
with_reid: True启用。
适用场景: 通用跟踪,尤其适用于移动摄像机。当外观相似的人群导致 ID 交换时,再添加 ReID。
BoT-SORT 专用参数:
| 参数 | 有效值或范围 | 描述 |
|---|---|---|
gmc_method | sparseOptFlow、orb、sift、ecc、none | 摄像机运动补偿后端。sparseOptFlow 为默认值。none 会禁用 CMC。 |
with_reid | True、False | 启用基于外观的匹配。默认关闭。 |
model | auto 或兼容的 ReID 模型路径 | auto 在可用时使用原生 YOLO 特征;自定义模型可以是 .pt 检查点或兼容的导出模型。 |
proximity_thresh | 0.0-1.0 | 考虑外观特征前所需的最小 IoU。 |
appearance_thresh | 0.0-1.0 | ReID 匹配所需的最小归一化外观相似度。提高该值可使匹配更加严格。 |
调优技巧:
- 静态摄像机: 将
gmc_method: none设置为相应值,每帧可节省几毫秒。 - 摄像机剧烈运动: 保持
sparseOptFlow;ecc更准确,但速度更慢。 - 外观相似的人群: 启用
with_reid: True,并提高appearance_thresh(例如设置为0.85+)。
ByteTrack#
ByteTrack(Zhang 等,ECCV 2022)是轻量级基线。它使用线性 Kalman + IoU 进行两阶段关联:
- 阶段 1: 将高分检测与活跃跟踪目标进行匹配。
- 阶段 2: 将未匹配的跟踪目标与低分检测重试匹配,以恢复短暂的部分遮挡。
它没有外观模型,也没有摄像机运动补偿。
适用场景: 检测器开销占主导、且希望将跟踪器开销降至最低的静态或近似静态摄像机。
ByteTrack 专用参数: 除了共享跟踪器参数外,没有其他参数。
调优技巧:
- 检测器噪声较大: 降低
track_low_thresh,让第二阶段拥有更多候选项。 - 高召回率检测器: 提高
track_high_thresh,以减少碎片化 ID。 - ID 频繁闪烁: 提高
track_buffer,让短暂漏检的跟踪目标得以保留。
OC-SORT#
OC-SORT(Cao 等,CVPR 2023)是 SORT 的观测中心扩展。它保留了 SORT 的轻量级设计(无外观特征),并增加了三项修正:
- 观测中心重更新 (ORU): 在上一次观测与当前检测之间重放一条虚拟轨迹,重新运行 Kalman 更新,以修正偏移的速度。
- 观测中心动量 (OCM): 通过速度一致性项惩罚运动方向错误的检测。
- 观测中心恢复 (OCR): 使用最近一次观测而非预测状态,将未匹配的检测与最近丢失的跟踪目标重新检查匹配。
适用场景: 在不引入 ReID 模型开销的情况下处理非线性运动。
OC-SORT 专用参数:
| 参数 | 有效值或范围 | 描述 |
|---|---|---|
delta_t | >=1 | OCM 中用于计算速度方向的时间窗口(帧数)。值越大,平滑效果越强。 |
inertia | 0.0-1.0 | 速度一致性代价的权重。值越高,对突然改变方向的惩罚越大。 |
use_byte | True、False | 启用类似 ByteTrack 的第二次关联过程,处理低置信度检测。 |
调优技巧:
- 非线性运动: 提高
inertia(例如设置为0.3-0.4)。 - 检测稀疏: 启用
use_byte: True。 - 长时间遮挡: 提高
track_buffer,让 OCR 有更多丢失的跟踪目标可重新绑定。
使用 OBB 模型时,OCR 使用 Kalman 预测的定向框,因为系统不会保留定向的上一次观测历史。
Deep OC-SORT#
Deep OC-SORT 在 OC-SORT 的基础上增加了外观信息和摄像机运动补偿:
- 外观匹配: 余弦嵌入距离受重叠度约束,并与运动代价融合。
- 动态外观 EMA: 跟踪目标嵌入使用 EMA 更新,其平滑因子会根据检测置信度自适应调整。
- 摄像机运动补偿: 通过稀疏光流、ORB 或 ECC 在连续帧之间对 Kalman 状态进行变换。
适用场景: 拥挤或摄像机移动的场景,其中外观不同但空间位置接近的目标之间经常发生 ID 交换。
Deep OC-SORT 专用参数:
| 参数 | 有效值或范围 | 描述 |
|---|---|---|
with_reid | True、False | 启用基于外观的匹配。默认关闭。 |
model | auto 或兼容的 ReID 模型路径 | auto 在可用时使用原生 YOLO 特征;自定义模型可以是 .pt 检查点或兼容的导出模型。 |
proximity_thresh | 0.0-1.0 | 考虑外观特征前所需的最小 IoU。 |
appearance_thresh | 0.0-1.0 | ReID 匹配所需的最小归一化外观相似度。 |
alpha_fixed_emb | 0.0-1.0 | 跟踪目标嵌入更新的基础 EMA 因子。值越高,旧嵌入保留的时间越长。 |
gmc_method | sparseOptFlow、orb、sift、ecc、none | 全局运动补偿方法。 |
delta_t | >=1 | OCM 中用于计算速度方向的时间窗口(帧数)(继承自 OC-SORT)。 |
inertia | 0.0-1.0 | 速度一致性代价的权重(继承自 OC-SORT)。 |
use_byte | True、False | 启用类似 ByteTrack 的第二次关联过程,处理低置信度检测(继承自 OC-SORT)。 |
调优技巧:
- 人群中的身份交换: 提高
appearance_thresh(例如设置为0.92-0.95),并提高alpha_fixed_emb,使嵌入的适应速度更慢。 - 移动摄像机: 设置
gmc_method: sparseOptFlow(Deep OC-SORT 的默认值为none)。 - 降低延迟: 保持
with_reid: False(默认值),仅使用运动 + CMC;仅当 ID 交换是主要错误来源时才启用 ReID。
FastTracker#
FastTracker 是一种具备遮挡感知能力、且没有外观模型的 ByteTrack 变体:
- 遮挡检测: 当其他活跃跟踪目标的覆盖率超过
occ_cover_thresh时,将跟踪目标标记为被遮挡。 - 遮挡时回滚 Kalman: 使用环形缓冲区中的历史记录,将 Kalman 状态回滚到遮挡发生前的帧。
- 运动减弱和搜索扩展: 遮挡期间减弱速度,并扩大预测 bbox。
- 初始化 IoU 抑制: 防止在活跃跟踪目标上方生成新跟踪目标。
适用场景: 目标频繁相互重叠(人群、队列、体育运动)的实时纯检测流程。
FastTracker 专用参数:
| 参数 | 有效值或范围 | 描述 |
|---|---|---|
reset_velocity_offset_occ | >=0 | 遮挡开始时,向前回溯以恢复 Kalman 速度的历史帧数。 |
reset_pos_offset_occ | >=0 | 遮挡开始时,向前回溯以恢复 Kalman 位置的历史帧数。 |
enlarge_bbox_occ | >=1.0 | 遮挡期间应用于预测 bbox 的高度缩放比例(宽度通过 XYAH 宽高比进行缩放)。 |
dampen_motion_occ | 0.0-1.0 | 遮挡期间的速度乘数。值越低,跟踪目标在遮挡期间的“减速”越明显。 |
active_occ_to_lost_thresh | >=1 | 在将活跃跟踪目标移至丢失状态前允许连续遮挡的最大帧数。 |
occ_cover_thresh | 0.0-1.0 | 用于判定遮挡的面积比例,即跟踪目标的面积被另一个活跃跟踪目标覆盖的比例。 |
occ_reappear_window | >=0 | 最近被遮挡而丢失的跟踪目标保持优先重新找到状态的帧数。 |
init_iou_suppress | 0.0-1.0 | 如果新跟踪目标与任意活跃跟踪目标的 IoU 超过此值,则抑制其初始化。设置为 1.0 可禁用此功能。 |
调优技巧:
- 频繁的部分遮挡: 降低
occ_cover_thresh(例如设置为0.5-0.6)。 - 重叠区域中的重复 ID: 降低
init_iou_suppress(例如设置为0.5)。 - 长时间遮挡: 同时提高
occ_reappear_window和track_buffer。 - 快速移动的目标: 提高
dampen_motion_occ(使其更接近1.0);仅当扩大搜索区域能改善恢复效果时,才提高enlarge_bbox_occ。
TrackTrack#
TrackTrack(Shim 等,CVPR 2025)是默认跟踪器。它从每个跟踪目标的角度出发,采用多线索迭代关联:
- 基于跟踪目标视角的关联 (TPA): 结合 HMIoU、可选的余弦 ReID 距离、置信度投影距离和角点角度距离。通过逐步放宽阈值来迭代求解分配。
- 跟踪目标感知初始化 (TAI): 在创建新 ID 前抑制重复生成。
适用场景: 频繁发生遮挡且重复 ID 成为问题的拥挤场景。
TrackTrack 专用参数:
| 参数 | 有效值或范围 | 描述 |
|---|---|---|
iou_weight | 0.0-1.0 | 启用 ReID 时 HMIoU 距离的权重;否则直接使用 HMIoU。 |
reid_weight | 0.0-1.0 | 启用 ReID 时余弦 ReID 距离的权重;否则忽略该距离。 |
conf_weight | 0.0-1.0 | 置信度投影距离的权重。 |
angle_weight | 0.0-1.0 | 角点角度距离的权重。 |
penalty_p | 0.0-1.0 | 对低置信度检测的代价惩罚。 |
penalty_q | 0.0-1.0 | 对通过二次 NMS 恢复的检测的代价惩罚。 |
reduce_step | 0.0-1.0 | 每次迭代的匹配阈值放宽幅度。 |
tai_thr | 0.0-1.0 | 跟踪目标感知初始化 NMS 的 IoU 阈值。 |
min_track_len | >=0 | 确认新跟踪目标前所需的最小历史长度。 |
lost_match_thr | 0.0-1.0 | 放宽丢失重绑定流程的代价门限;0 会禁用该功能。 |
with_reid | True、False | 启用余弦 ReID 外观匹配(使用原生 YOLO 特征)。默认关闭。 |
model | auto 或兼容的 ReID 模型路径 | auto 在可用时使用原生 YOLO 特征;自定义模型可以是 .pt 检查点或兼容的导出模型。 |
gmc_method | sparseOptFlow、orb、sift、ecc、none | 全局运动补偿方法。 |
调优技巧:
- **行人拥挤:**降低
tai_thr(例如0.45),以抑制更多重复生成的轨迹;提高track_buffer,以应对更长时间的遮挡。 - **相机快速移动:**保持启用
gmc_method: sparseOptFlow。 - **小型/快速移动的对象:**略微提高
angle_weight,并降低min_track_len。 - **仅在需要时启用 ReID:**它会增加推理成本;对于较短的遮挡,默认的多线索代价通常已经足够。
对于 Segment 和 Pose 模型,TrackTrack 会跳过宽松 NMS 检测恢复,以确保掩码和关键点与其检测结果保持对齐。
Python 示例#
Watch: How to Build Interactive Object Tracking with Ultralytics YOLO | Click to Crop & Display ⚡
保持轨迹的循环#
下面是一个使用 OpenCV(cv2)和 YOLO26 在视频帧上运行对象跟踪的 Python 脚本。该脚本假设必要的软件包(opencv-python 和 ultralytics)已经安装。persist=True 参数会告知跟踪器当前图像或帧是序列中的下一帧,并应在当前图像中寻找上一张图像中的轨迹。
仅当将同一视频流中的连续帧传递给 model.track() 时,才使用 persist=True。这样,跟踪器就能复用早期帧的状态,并随时间保持一致的轨迹 ID。不要在无关图像或不同视频流之间使用 persist=True,因为之前的轨迹状态可能会延续。
你还可以通过传入跟踪器配置文件来选择跟踪器后端,例如 tracker="botsort.yaml"、tracker="bytetrack.yaml" 或 tracker="tracktrack.yaml"。
import cv2
from ultralytics import YOLO
# Load the YOLO26 model
model = YOLO("yolo26n.pt")
# Open the video file
video_path = "path/to/video.mp4"
cap = cv2.VideoCapture(video_path)
# Loop through the video frames
while cap.isOpened():
# Read a frame from the video
success, frame = cap.read()
if success:
# Run YOLO26 tracking on the frame, persisting tracks between frames
# and using the BoT-SORT tracker backend
results = model.track(frame, persist=True, tracker="botsort.yaml")
# Visualize the results on the frame
annotated_frame = results[0].plot()
# Display the annotated frame
cv2.imshow("YOLO26 Tracking", annotated_frame)
# Break the loop if 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
# Break the loop if the end of the video is reached
break
# Release the video capture object and close the display window
cap.release()
cv2.destroyAllWindows()请注意从 model(frame) 到 model.track(frame) 的变化,这会启用对象跟踪,而不是简单检测。修改后的脚本会在视频的每一帧上运行跟踪器、将结果可视化,并在窗口中显示结果。按下 'q' 可退出循环。
绘制随时间变化的轨迹#
将连续帧中的对象轨迹可视化,有助于深入了解视频中检测对象的运动模式和行为。借助 Ultralytics YOLO26,绘制这些轨迹的过程顺畅而高效。
在下面的示例中,我们演示如何利用 YOLO26 的跟踪功能,绘制检测对象在多个视频帧中的移动轨迹。该脚本会打开视频文件,逐帧读取视频,并利用 YOLO 模型识别和跟踪各种对象。通过保留检测边界框的中心点并将其连接起来,我们可以绘制表示跟踪对象移动路径的线条。
from collections import defaultdict
import cv2
import numpy as np
from ultralytics import YOLO
# Load the YOLO26 model
model = YOLO("yolo26n.pt")
# Open the video file
video_path = "path/to/video.mp4"
cap = cv2.VideoCapture(video_path)
# Store the track history
track_history = defaultdict(list)
# Loop through the video frames
while cap.isOpened():
# Read a frame from the video
success, frame = cap.read()
if success:
# Run YOLO26 tracking on the frame, persisting tracks between frames
result = model.track(frame, persist=True)[0]
# Get the boxes and track IDs
if result.boxes and result.boxes.is_track:
boxes = result.boxes.xywh.cpu()
track_ids = result.boxes.id.int().cpu().tolist()
# Visualize the result on the frame
frame = result.plot()
# Plot the tracks
for box, track_id in zip(boxes, track_ids):
x, y, w, h = box
track = track_history[track_id]
track.append((float(x), float(y))) # x, y center point
if len(track) > 30: # retain 30 tracks for 30 frames
track.pop(0)
# Draw the tracking lines
points = np.hstack(track).astype(np.int32).reshape((-1, 1, 2))
cv2.polylines(frame, [points], isClosed=False, color=(230, 230, 230), thickness=10)
# Display the annotated frame
cv2.imshow("YOLO26 Tracking", frame)
# Break the loop if 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
# Break the loop if the end of the video is reached
break
# Release the video capture object and close the display window
cap.release()
cv2.destroyAllWindows()多线程跟踪#
多线程跟踪可以同时在多个视频流上运行对象跟踪。在处理多个视频输入(例如来自多个监控摄像头的输入)时,这一功能尤其有用,因为并发处理可以显著提升效率和性能。
在所提供的 Python 脚本中,我们使用 Python 的 threading 模块并发运行多个跟踪器实例。每个线程负责对一个视频文件运行跟踪器,所有线程都会在后台同时运行。
为确保每个线程都接收到正确的参数(视频文件、要使用的模型和文件索引),我们定义了一个接受这些参数的函数 run_tracker_in_thread,其中包含主跟踪循环。该函数逐帧读取视频、运行跟踪器并显示结果。
此示例使用了两个不同的模型:yolo26n.pt 和 yolo26n-seg.pt,它们分别跟踪不同视频文件中的对象。视频文件在 SOURCES 中指定。
threading.Thread 中的 daemon=True 参数表示,主程序结束后这些线程会立即关闭。随后,我们使用 start() 启动线程,并使用 join() 让主线程等待两个跟踪线程都完成。
最后,在所有线程完成任务后,使用 cv2.destroyAllWindows() 关闭显示结果的窗口。
import threading
import cv2
from ultralytics import YOLO
# Define model names and video sources
MODEL_NAMES = ["yolo26n.pt", "yolo26n-seg.pt"]
SOURCES = ["path/to/video.mp4", "0"] # local video, 0 for webcam
def run_tracker_in_thread(model_name, filename):
"""Run YOLO tracker in its own thread for concurrent processing.
Args:
model_name (str): Model checkpoint name or path loaded inside the thread.
filename (str): The path to the video file or the identifier for the webcam/external camera source.
"""
model = YOLO(model_name)
results = model.track(filename, save=True, stream=True)
for r in results:
pass
# Create and start tracker threads using a for loop
tracker_threads = []
for video_file, model_name in zip(SOURCES, MODEL_NAMES):
thread = threading.Thread(target=run_tracker_in_thread, args=(model_name, video_file), daemon=True)
tracker_threads.append(thread)
thread.start()
# Wait for all tracker threads to finish
for thread in tracker_threads:
thread.join()
# Clean up and close windows
cv2.destroyAllWindows()通过创建更多线程并采用相同的方法,此示例可以轻松扩展,以处理更多视频文件和模型。
贡献新的跟踪器#
你是否精通多对象跟踪,并已使用 Ultralytics YOLO 成功实现或改编跟踪算法?欢迎为我们的 ultralytics/cfg/trackers 跟踪器部分贡献代码!你在真实场景中的应用和解决方案,可能会为从事跟踪任务的用户提供宝贵帮助。
通过为本部分做出贡献,你可以帮助扩展 Ultralytics YOLO 框架中可用跟踪解决方案的范围,为社区增加更多功能和实用性。
如需开始贡献,请参阅我们的 贡献指南,了解提交拉取请求 (PR) 的完整说明 🛠️。我们期待看到你的成果!
让我们携手提升 Ultralytics YOLO 生态系统的跟踪能力 🙏!
常见问题#
不可以。标准的 Ultralytics
.pt文件存储 YOLO 模型权重,而跟踪器会在推理时由model.track()创建。轨迹 ID 取决于连续帧之间的跟踪器状态,因此单张独立图像可以返回框、类别和置信度等检测结果,但无法单独生成有意义的持久轨迹 ID。部署时,请在应用程序中将检测器和跟踪器一起打包,并对来自同一视频流的帧逐帧调用
model.track(),同时使用persist=True。对于无关的视频流,请使用独立的模型或跟踪器实例,以免状态在视频之间延续。你可以从 Ultralytics 跟踪器配置目录复制现有的跟踪器配置文件(例如
custom_tracker.yaml),然后根据需要修改参数,但tracker_type除外。在跟踪模型中按如下方式使用此文件:示例from ultralytics import YOLO model = YOLO("yolo26n.pt") results = model.track(source="https://youtu.be/LNwODJXcvt4", tracker="custom_tracker.yaml")要同时在多个视频流上运行对象跟踪,你可以使用 Python 的
threading模块。每个线程负责处理一个独立的视频流。下面是设置方法示例:多线程跟踪import threading import cv2 from ultralytics import YOLO # Define model names and video sources MODEL_NAMES = ["yolo26n.pt", "yolo26n-seg.pt"] SOURCES = ["path/to/video.mp4", "0"] # local video, 0 for webcam def run_tracker_in_thread(model_name, filename): """Run YOLO tracker in its own thread for concurrent processing. Args: model_name (str): Model checkpoint name or path loaded inside the thread. filename (str): The path to the video file or the identifier for the webcam/external camera source. """ model = YOLO(model_name) results = model.track(filename, save=True, stream=True) for r in results: pass # Create and start tracker threads using a for loop tracker_threads = [] for video_file, model_name in zip(SOURCES, MODEL_NAMES): thread = threading.Thread(target=run_tracker_in_thread, args=(model_name, video_file), daemon=True) tracker_threads.append(thread) thread.start() # Wait for all tracker threads to finish for thread in tracker_threads: thread.join() # Clean up and close windows cv2.destroyAllWindows()要将多个视频帧中的对象轨迹可视化,你可以使用 YOLO 模型的跟踪功能,并结合 OpenCV 绘制检测对象的路径。下面是演示此过程的示例脚本:
绘制多个视频帧中的轨迹from collections import defaultdict import cv2 import numpy as np from ultralytics import YOLO model = YOLO("yolo26n.pt") video_path = "path/to/video.mp4" cap = cv2.VideoCapture(video_path) track_history = defaultdict(list) while cap.isOpened(): success, frame = cap.read() if success: result = model.track(frame, persist=True)[0] annotated_frame = result.plot() if result.boxes and result.boxes.is_track: boxes = result.boxes.xywh.cpu() track_ids = result.boxes.id.int().cpu().tolist() for box, track_id in zip(boxes, track_ids): x, y, w, h = box track = track_history[track_id] track.append((float(x), float(y))) if len(track) > 30: track.pop(0) points = np.hstack(track).astype(np.int32).reshape((-1, 1, 2)) cv2.polylines(annotated_frame, [points], isClosed=False, color=(230, 230, 230), thickness=10) cv2.imshow("YOLO26 Tracking", annotated_frame) if cv2.waitKey(1) & 0xFF == ord("q"): break else: break cap.release() cv2.destroyAllWindows()此脚本会绘制跟踪线,显示跟踪对象随时间变化的移动路径,从而帮助深入了解对象的行为和模式。