基于 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
|
验证安装及硬件可用性:
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(): if torch.cuda.is_available(): device = "cuda" elif torch.backends.mps.is_available(): device = "mps" else: device = "cpu" print(f"[*] 当前使用推理设备: {device.upper()}")
model = YOLO("yolo11n.pt") model.to(device)
cap = cv2.VideoCapture(0) if not cap.isOpened(): print("[!] 无法打开摄像头,请检查设备索引或系统权限。") return
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
results = model.predict(frame, conf=0.4, iou=0.7, verbose=False)
annotated_frame = results[0].plot()
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 )
cv2.imshow("YOLO11 Real-Time Detection", annotated_frame)
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
results = model.track( frame, persist=True, tracker="bytetrack.yaml", classes=[0], conf=0.35, verbose=False )
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()
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)
|
5. Ultralytics 原生极简一行流
如果你只是想临时做演示或查看识别效果,Ultralytics 甚至提供了内置的摄像头推流与交互界面,连 OpenCV 渲染循环都不需要自己写:
Python 单行调用
1 2 3 4
| from ultralytics import YOLO
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 原生内置的多目标追踪套件,都能以极少的代码行数迅速搭建起高稳定性的实时视觉应用系统。