基于 YOLO11 的摄像头实时目标检测与多目标追踪实战

基于 YOLO11 的摄像头实时目标检测与多目标追踪实战

在计算机视觉落地项目中,将深度学习目标检测模型接入本地摄像头或 RTSP 实时视频流是最基础也是最核心的能力。Ultralytics 正式推出了 YOLO11(注意官方命名直接为 YOLO11 而非带“v”的 YOLOv11)。相比 YOLOv8 与 YOLOv10,YOLO11 引入了全新的 C3k2(更轻量的双卷积 CSP 瓶颈层)与 C2PSA(带空间注意力机制的卷积模块),在保持甚至降低参数量的前提下,大幅提升了小目标检测能力与推理速度。

本文将以极致轻量、适合边缘端与桌面端实时运行的 YOLO11n(Nano 版本) 为例,带大家实现从基础摄像头推理、硬件加速(CUDA / Apple Silicon MPS / CPU)、FPS 帧率计算,再到多目标追踪(ByteTrack)与高帧率异步抓流的完整工程落地。


1. 环境准备与依赖安装

YOLO11 集成在官方 ultralytics 核心库中。运行前需确保安装了 PyTorch、OpenCV 以及 Ultralytics 工具包:

1
2
3
4
5
6
7
8
# 基础依赖
pip install ultralytics opencv-python

# 根据硬件平台安装对应的 PyTorch(建议 PyTorch 2.x 以上):
# - NVIDIA GPU (CUDA 12.x):
# pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
# - Apple Silicon (M1/M2/M3/M4) 或纯 CPU:
# pip install torch torchvision

验证安装及硬件可用性:

1
python -c "import torch; print('CUDA 可用:', torch.cuda.is_available(), '| MPS 可用:', torch.backends.mps.is_available())"

2. 基础版本:摄像头实时检测与 FPS 统计

权重命名特别注意

⚠️ 避坑指南:Ultralytics 官方对 YOLO11 的模型权重文件命名规范是 yolo11n.pt(无字母 v)。如果在代码中使用 YOLO("yolov11n.pt"),Ultralytics 会尝试在本地寻找或抛出找不到模型的警告。传入 yolo11n.pt 时,若本地不存在,会自动从官方 GitHub Releases 高速拉取。

完整基础可执行代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import time
import cv2
import torch
from ultralytics import YOLO

def main():
# 1. 自动选择最优硬件加速后端
if torch.cuda.is_available():
device = "cuda"
elif torch.backends.mps.is_available():
device = "mps" # Apple Silicon Metal 加速
else:
device = "cpu"
print(f"[*] 当前使用推理设备: {device.upper()}")

# 2. 加载 YOLO11n 模型
# 官方模型包含: yolo11n, yolo11s, yolo11m, yolo11l, yolo11x
# 摄像头实时场景强烈推荐最轻量的 yolo11n (参数量仅约 2.6M)
model = YOLO("yolo11n.pt")
model.to(device)

# 3. 打开摄像头(0 通常为内置或默认 USB 摄像头)
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("[!] 无法打开摄像头,请检查设备索引或系统权限。")
return

# 设置捕获分辨率(按需调整,如 1280x720)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)

prev_time = time.time()

print("[*] 摄像头已启动,按 'q' 键退出程序...")
while True:
ret, frame = cap.read()
if not ret:
print("[!] 无法接收画面帧,退出中...")
break

# 4. 模型推理
# conf=0.4: 置信度阈值
# iou=0.7: 非极大值抑制(NMS)重叠阈值
results = model.predict(frame, conf=0.4, iou=0.7, verbose=False)

# 5. 可视化绘制(自带目标框、类别名与置信度)
annotated_frame = results[0].plot()

# 6. 计算平滑 FPS 并在左上角显示
curr_time = time.time()
fps = 1.0 / (curr_time - prev_time)
prev_time = curr_time

cv2.putText(
annotated_frame,
f"Model: YOLO11n | FPS: {fps:.1f}",
(20, 40),
cv2.FONT_HERSHEY_SIMPLEX,
1.0,
(0, 255, 0),
2,
cv2.LINE_AA
)

# 7. 渲染窗口
cv2.imshow("YOLO11 Real-Time Detection", annotated_frame)

# 按 'q' 键退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break

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

if __name__ == "__main__":
main()

3. 工程进阶:多目标追踪(Object Tracking)与业务优化

单纯的目标检测在连续视频流中容易出现前后帧 ID 丢失或频繁闪烁的问题。在实际监控、人流统计或轨迹分析中,我们需要的是多目标追踪(MOT)。

YOLO11 内置了 ByteTrack 与 BoT-SORT 跟踪算法,无需额外安装复杂的 DeepSORT 依赖,只需将 model.predict() 替换为 model.track(..., persist=True) 即可获得连续的 track_id。

增强版实战代码(支持轨迹跟踪 + 特定类别过滤 + 保存录像)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import time
import cv2
import torch
from ultralytics import YOLO

def run_tracker(output_video_path="output_detection.mp4"):
device = "cuda" if torch.cuda.is_available() else ("mps" if torch.backends.mps.is_available() else "cpu")
model = YOLO("yolo11n.pt").to(device)

cap = cv2.VideoCapture(0)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps_in = cap.get(cv2.CAP_PROP_FPS) or 30.0

# 配置视频保存器
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_video_path, fourcc, fps_in, (width, height))

prev_time = time.time()

while cap.isOpened():
ret, frame = cap.read()
if not ret:
break

# 启用跟踪器:
# persist=True: 保持前后帧间的轨迹连续
# tracker="bytetrack.yaml": 使用 ByteTrack 算法(轻量极速)
# classes=[0]: 仅检测并跟踪行人类别 (0 表示 COCO 数据集中的 person)
results = model.track(
frame,
persist=True,
tracker="bytetrack.yaml",
classes=[0],
conf=0.35,
verbose=False
)

# 获取带跟踪 ID 标记的画面
annotated_frame = results[0].plot()

# 解析检测框详细数据(可用于自定义业务逻辑)
boxes = results[0].boxes
if boxes.id is not None:
track_ids = boxes.id.int().cpu().tolist()
confidences = boxes.conf.cpu().tolist()
# 实时在控制台或界面输出当前场景活跃目标数量
# print(f"当前跟踪目标总数: {len(track_ids)}, IDs: {track_ids}")

curr_time = time.time()
fps = 1.0 / (curr_time - prev_time)
prev_time = curr_time

cv2.putText(annotated_frame, f"Tracking Persons | FPS: {fps:.1f}", (20, 40),
cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 255), 2)

# 保存并显示
out.write(annotated_frame)
cv2.imshow("YOLO11 Tracking", annotated_frame)

if cv2.waitKey(1) & 0xFF == ord('q'):
break

cap.release()
out.release()
cv2.destroyAllWindows()
print(f"[*] 录像已保存至: {output_video_path}")

if __name__ == "__main__":
run_tracker()

4. 关键性能优化技巧

在工业现场部署时,如果遇到掉帧、卡顿或画面延迟,可以应用以下调优手段:

1. 解决 OpenCV 缓冲区画面积压延迟

OpenCV 默认会缓存 3~5 帧甚至更多。当模型单帧推理耗时略长于相机采集周期时,画面会出现明显的“拖影”与“迟滞”。解决办法:

  • 设置缓冲区大小为 1:
    1
    cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
  • 或者采用多线程/协程:单独一个线程持续 cap.grab() 消费废弃帧,主线程只取最新的 cap.retrieve()。

2. 半精度(FP16)加速

在支持 Tensor Core 的现代 NVIDIA GPU 上,开启 FP16 半精度推理可以将计算速度提升近一倍,且精度几乎不损失:

1
results = model.predict(frame, half=True)

3. 输入分辨率缩放

YOLO11 默认输入尺寸为 640x640。在边缘设备(如树莓派、Jetson Nano 或老旧笔记本)上,可以通过 imgsz 参数降低输入分辨率以成倍换取速度:

1
results = model.predict(frame, imgsz=320)  # 帧率可提升 50%~100%

5. Ultralytics 原生极简一行流

如果你只是想临时做演示或查看识别效果,Ultralytics 甚至提供了内置的摄像头推流与交互界面,连 OpenCV 渲染循环都不需要自己写:

Python 单行调用

1
2
3
4
from ultralytics import YOLO

# 传入 source=0 代表开启本地摄像头,show=True 会自动弹出 OpenCV 窗口
YOLO("yolo11n.pt").predict(source="0", show=True)

CLI 命令行调用

1
2
3
4
5
# 在终端直接执行检测
yolo predict model=yolo11n.pt source=0 show=True

# 终端直接启动追踪
yolo track model=yolo11n.pt source=0 show=True

6. 常见问题排查(Troubleshooting)

问题现象 常见原因 解决方案
cap.isOpened() 返回 False macOS 系统终端无相机授权,或摄像头被占用 在「系统设置 → 隐私与安全性 → 摄像头」中勾选当前终端(Terminal / iTerm2 / VS Code)。
首次启动下载权重过慢 / 报错 GitHub Releases 访问不稳定 手动访问 Ultralytics GitHub Releases 下载 yolo11n.pt 并放入当前目录。
Apple Silicon (MPS) 报错缺少算子 PyTorch 早期版本 MPS 支持不全 升级 PyTorch 到 2.2+,若仍有个别算子异常,可在初始化时指定降级到 CPU:device='cpu'。
窗口无法关闭或卡死 漏写 cv2.waitKey() OpenCV 必须在每一帧渲染后执行 cv2.waitKey(1) 来刷新 GUI 事件循环。

小结

YOLO11 凭借全新的架构升级,在保持模型极致轻量(Nano 版模型权重仅约 5.4MB)的同时,带来了更优的检测精度和更快的端侧推理速度。无论是通过纯 Python 结合 OpenCV 自定义渲染,还是利用 Ultralytics 原生内置的多目标追踪套件,都能以极少的代码行数迅速搭建起高稳定性的实时视觉应用系统。