使用 Python + YOLOv8 实现 CPU 版模型对视频的检测
引言
在计算机视觉模型训练(尤其是 YOLO 系列)完成后,我们通常会得到 .pt 格式的模型文件,而评估模型效果最直观的方式是对 .mp4 格式的视频进行实时检测。很多开发者在测试时会遇到两个核心问题:一是如何快速加载模型并处理视频、可视化检测结果;二是部分场景下无 GPU 环境,需要强制使用 CPU 完成推理。本文将详细讲解如何编写通用脚本,实现 .pt 模型对 .mp4 视频的检测,并针对 “强制 CPU 推理” 的需求做定制化改造,帮助初学者快速验证模型训练效果。
一、问题提出
需要开发一个 Python 脚本,满足以下核心需求:
- 1. 加载
.pt 格式的训练模型(以 YOLOv8 为例); - 2. 对
.mp4 格式的视频进行逐帧推理,可视化检测框、类别和置信度; - 4. 强制使用 CPU 完成推理(排除 CUDA 自动适配的干扰);
- 5. 脚本具备鲁棒性,包含文件校验、资源释放等逻辑。
二、核心知识点拆解
2.1 关键依赖库作用
实现该需求需依赖以下 4 个核心库,各自分工明确:
- • ultralytics:官方维护的 YOLOv8 核心库,支持
.pt 模型加载、视频帧推理和检测结果可视化; - • torch:PyTorch 基础库,负责模型设备(CPU/GPU)的指定;
- • opencv-python(cv2):处理视频的读取、绘制检测框、结果视频保存;
- • numpy:辅助数值计算(脚本中隐式依赖,无需额外编写逻辑)。
2.2 设备指定逻辑
YOLOv8 默认会自动适配设备(优先 CUDA/GPU),而强制 CPU 推理的核心是:
# 自动适配(原逻辑)device = 'cuda'if torch.cuda.is_available() else'cpu'# 强制CPU(改造后)device = 'cpu'
同时需在模型推理时显式指定 device=device,确保全程使用 CPU。
2.3 视频处理核心流程
flowchart LRA[打开视频文件] --> B[读取单帧画面]B --> C[模型推理(CPU)]C --> D[绘制检测框/类别/置信度]D --> E[写入结果视频]E --> F{是否读完所有帧?}F -- 否 --> BF -- 是 --> G[释放视频资源]
三、代码实现
3.1 前置准备:安装依赖库
打开终端执行以下命令,安装所有必需依赖:
pip install ultralytics torch opencv-python numpy
推荐版本:
3.2 完整 CPU 版检测脚本
import cv2import torchfrom ultralytics import YOLOimport osdefdetect_model_on_video(model_path, video_path, output_path="output.mp4", conf_threshold=0.5):""" 加载.pt模型(强制CPU)检测.mp4视频,保存带检测结果的视频 参数说明: model_path: str, .pt模型文件路径(如'best.pt') video_path: str, 待检测的.mp4视频路径(如'test_video.mp4') output_path: str, 检测结果视频保存路径 conf_threshold: float, 置信度阈值(0-1),过滤低置信度检测结果 """# 1. 校验文件是否存在(避免路径错误导致运行失败)ifnot os.path.exists(model_path):raise FileNotFoundError(f"模型文件不存在:{model_path}")ifnot os.path.exists(video_path):raise FileNotFoundError(f"视频文件不存在:{video_path}")# 2. 强制使用CPU(核心改造点) device = 'cpu'print(f"当前强制使用计算设备:{device}")# 3. 加载.pt模型并指定CPU model = YOLO(model_path) model.to(device)# 4. 打开视频文件 cap = cv2.VideoCapture(video_path)ifnot cap.isOpened():raise RuntimeError(f"无法打开视频:{video_path}")# 5. 获取视频基础参数(保证输出视频与原视频同步) fps = int(cap.get(cv2.CAP_PROP_FPS)) # 视频帧率 width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # 视频宽度 height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))# 视频高度 fourcc = cv2.VideoWriter_fourcc(*'mp4v') # MP4编码格式# 6. 创建视频写入器,用于保存检测结果 out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))# 7. 逐帧处理视频 frame_count = 0print("开始检测视频(CPU模式),请稍候...")while cap.isOpened(): ret, frame = cap.read()ifnot ret:break# 视频读取完毕# 单帧推理(过滤低置信度结果,强制CPU) results = model(frame, conf=conf_threshold, device=device)# 绘制检测框、类别、置信度到帧上(YOLOv8内置可视化函数) annotated_frame = results[0].plot()# 写入结果到输出视频 out.write(annotated_frame)# 实时预览检测画面(按q键可提前退出) cv2.imshow('Model Detection Preview (CPU)', annotated_frame) frame_count += 1# 每处理10帧打印进度,便于监控if frame_count % 10 == 0:print(f"已处理帧数:{frame_count}")# 按下q键退出预览if cv2.waitKey(1) & 0xFF == ord('q'):break# 8. 释放资源(关键:避免内存泄漏) cap.release() out.release() cv2.destroyAllWindows()# 输出检测结果print("\n检测完成!")print(f"结果视频保存路径:{output_path}")print(f"总共处理帧数:{frame_count}")# -------------------------- 自定义配置区 --------------------------if __name__ == "__main__":# 请替换为你自己的文件路径! YOUR_MODEL_PATH = "your_model.pt"# 你的.pt模型路径 YOUR_VIDEO_PATH = "test_video.mp4"# 你的.mp4视频路径 OUTPUT_VIDEO_PATH = "detection_result_cpu.mp4"# 结果保存路径try: detect_model_on_video( model_path=YOUR_MODEL_PATH, video_path=YOUR_VIDEO_PATH, output_path=OUTPUT_VIDEO_PATH, conf_threshold=0.5# 可根据模型效果调整(比如0.3/0.6) )except Exception as e:print(f"检测出错:{e}")
3.3 关键代码解释
- 1. 文件校验:脚本开头检查
.pt 模型和 .mp4 视频是否存在,避免因路径错误导致运行中断; - 2. 强制 CPU:直接指定
device='cpu',并通过 model.to(device) 和推理时的 device=device 双重确保 CPU 运行; - 3. 视频参数对齐:读取原视频的帧率、分辨率,保证输出视频的播放速度和尺寸与原视频一致;
- 4. 实时预览与终止:通过
cv2.imshow 展示检测画面,按 q 键可提前终止,适合快速测试; - 5. 资源释放:
cap.release()、out.release()、cv2.destroyAllWindows() 是必加逻辑,避免视频文件被占用或内存泄漏。
3.4 实际运行示例
输入输出示例
配置示例:
YOUR_MODEL_PATH = "yolov8n.pt"# 使用YOLOv8n预训练模型YOUR_VIDEO_PATH = "traffic.mp4"# 交通场景测试视频OUTPUT_VIDEO_PATH = "traffic_detected.mp4"# 检测结果保存路径
运行输出:
当前强制使用计算设备:cpu开始检测视频(CPU模式),请稍候...已处理帧数:10已处理帧数:20已处理帧数:30...检测完成!结果视频保存路径:traffic_detected.mp4总共处理帧数:120
检测效果:
- • 检测结果:视频中每个目标都被框出,并标注类别(如 car、person)和置信度
四、易错点提醒
- 1. 文件路径问题:务必将
YOUR_MODEL_PATH 和 YOUR_VIDEO_PATH 替换为实际路径(绝对路径 / 相对路径均可),路径错误会直接触发 FileNotFoundError; - 2. CPU 推理性能:CPU 处理视频的速度远慢于 GPU,建议先截取 10 秒以内的短视频片段测试,避免等待过久;
- 3. 置信度阈值调整:
conf_threshold 默认 0.5,值越大检测结果越严格(减少误检),值越小越灵敏(可能增加误检),需根据模型效果微调; - 4. 资源未释放:若脚本强行终止(如 Ctrl+C),可能导致视频文件无法打开,需手动关闭 Python 进程后重试;
- 5. 编码格式问题:部分环境下
mp4v 编码可能不兼容,可替换为 avc1 尝试; - 6. 模型输入要求:YOLOv8 模型默认输入尺寸为 640x640,若视频分辨率过高,会自动缩放到该尺寸进行推理。
五、性能优化建议
5.1 CPU 推理速度优化
- 1. 降低视频分辨率:使用
cv2.resize(frame, (640, 480)) 缩小输入尺寸,显著提升推理速度; - 2. 减少检测类别:若只需检测特定类别,可在模型初始化时指定
classes 参数; - 3. 批量处理:虽然 CPU 并行能力有限,但可尝试使用
torch.set_num_threads() 优化线程数; - 4. 使用轻量级模型:优先选择 YOLOv8n、YOLOv8s 等轻量级模型,减少计算量。
5.2 内存使用优化
- 2. 及时释放资源:确保在脚本结束前释放所有视频相关资源;
- 3. 减少预览窗口:若不需要实时预览,可注释掉
cv2.imshow 相关代码。
六、总结
核心收获
- 1. 掌握了基于 YOLOv8 加载
.pt 模型、处理 .mp4 视频的完整流程,包括视频读取、逐帧推理、结果可视化和保存; - 2. 理解了设备指定的核心逻辑,实现从 “自动适配 CUDA/CPU” 到 “强制 CPU 推理” 的改造;
- 3. 学会了编写鲁棒的脚本,包含文件校验、进度监控、异常处理和资源释放等工程化细节;
知识点关联
依赖库安装 → 设备配置(CPU) → 视频 IO 操作 → 模型推理 → 检测结果可视化 → 资源释放,这是计算机视觉视频检测的通用流程,适配绝大多数基于 PyTorch 的模型(如 YOLOv5/YOLOv8)。
七、拓展建议
- 1. 适配其他模型:若
.pt 模型是图像分类模型,可将 results[0].plot() 替换为 cv2.putText(),绘制分类结果和置信度;若为分割模型(YOLOv8-seg),脚本无需修改,plot() 会自动绘制分割掩码; - 2. 批量处理视频:新增遍历文件夹的逻辑,实现对多个
.mp4 视频的批量检测; - 3. 统计检测指标:结合
ultralytics 的 metrics 功能,统计精确率(Precision)、召回率(Recall)等量化指标,更客观评估模型效果; - 4. 保存检测日志:将每帧的检测类别、置信度、坐标保存到 CSV 文件,便于后续分析模型的漏检 / 误检情况;
- 5. 添加时间戳:在检测结果视频中添加时间戳,便于定位特定时刻的检测情况;
- 6. 实现实时视频流检测:将视频文件输入改为摄像头输入(
cap = cv2.VideoCapture(0)),实现实时检测。
学习小贴士
- 1. 先简后繁:测试新脚本时,优先用最短的视频片段和最简单的模型验证流程,再逐步扩展功能;
- 2. 参数调优优先:模型效果不佳时,先调整置信度、IOU 阈值等参数,再考虑重新训练;
- 3. 关注异常信息:脚本抛出的异常(如
RuntimeError)通常包含明确的错误原因,是排查问题的关键; - 4. 复用核心逻辑:本文的视频处理、资源释放逻辑可复用至其他计算机视觉任务(如目标跟踪、行为识别);
- 5. 版本兼容性:注意依赖库版本的兼容性,尤其是 ultralytics 和 torch 的版本匹配问题。
个人矩阵
- • 抖音账号:从 0 至 1(日常分享实操、效率工具教程)
- • 微信公众号:从 0 至 1(可通过该渠道获取完整代码包及EXE程序)
- • 博客网站:www.from0to1.cn(持续更新实战教程、技术干货内容)
- • GitHub账号:https://github.com/mtnljbydd(开源更多实用工具脚本及项目工程)