
这次我们直接解决一个很现实的问题训练或下载到best.pt权重之后代码到底怎么接因为很多 YOLO 项目做到一半数据标注、训练、验证都跑通了最后卡在部署这一步——单独测一张图可以但要处理视频、要接摄像头、要批量跑文件夹里的图片甚至要封装成 HTTP 接口给其他系统调用代码一下子乱掉。这篇文章围绕“YOLO26/11/v8 实现图片、视频和摄像头检测【调用 best.pt】”这个工程主题展开把推理端最常用的一套调用方式整理清楚。先说明一点无论权重来自 YOLOv8、YOLO11 还是其他版本只要它是基于 Ultralytics 生态训练出来的并且文件名是best.pt那推理接口就是同一套写法区别主要是内部网络结构和精度差异。所以这篇文章的核心目标是你拿到任意一个best.pt能在一份代码里跑通图片、视频、摄像头三种输入并且知道结果怎么保存、参数怎么调、接口怎么暴露、显存和性能怎么观察。阅读本文需要你有 Python 基础不需要重新学目标检测理论。如果你还没进入训练环节也可以先拿官方预训练权重yolo11n.pt或yolov8n.pt把流程走通后面再换成自己训练的best.pt代码完全不用改。下面按“环境准备 - 权重规划 - 三类输入检测 - 参数与批量 - 接口集成 - 性能排查”的顺序展开。1. YOLO 推理项目核心能力速览先把大家最关心的规格和结论放在前面。能力项说明项目类型YOLO 目标检测推理工程支持输入图片jpg/png、视频文件mp4/avi 等、摄像头实时流、RTSP/网络流权重文件best.pt来自自定义训练或官方预训练权重模型版本标题涉及 YOLO26/11/v8推理代码基于 Ultralytics API版本迁移成本低推荐硬件NVIDIA GPU CUDA 环境无 GPU 时 CPU 也可推理速度会明显下降是否支持 CPU支持但高分辨率视频或大模型尺寸下帧率会低是否支持批量任务支持可传入图片列表或批量文件路径是否支持 API支持可用 Flask/FastAPI 封装或由其他推理框架接入启动方式Python 脚本或yolo命令行主要输出目标框坐标、类别 ID、置信度、标注后的图片/视频适合场景自定义模型效果验证、批量图片检测、视频结构化分析、摄像头实时监控预警这套推理方案最大的价值不是某个版本的新特性而是把“训练产物”和“实际使用”之间的那段路打通。训练结束之后模型文件通常放在runs/detect/train/weights/best.pt你需要把它复制到统一目录然后通过简单的YOLO(best.pt)加载后续所有检测都可以围绕这一个模型实例展开。需要提醒的是具体显卡型号、显存占用和帧率不能用一句“多少 G 够用”概括因为推理速度受输入分辨率、模型尺寸、批次大小和硬件共同影响。这篇文章不硬编数字后文会给出你自己测量和判断的方法。2. YOLO26、YOLO11、YOLOv8 版本关系与权重评估从项目标题看你可能手里有不同版本的权重也可能是在不同机器、不同训练脚本里导出的模型。这里先说清楚版本之间的关系避免你花大量时间在“导入失败”上。YOLOv8 是 Ultralytics 团队把检测、分割、分类、姿态估计统一到同一套框架后的代表性版本yolov8n.pt、yolov8s.pt这类官方权重用YOLO(yolov8n.pt)就能加载训练完成后自动保存best.pt和last.pt。YOLO11注意不是YOLOv11文件名里没有 v延续了同一套 API官方权重命名是yolo11n.pt、yolo11s.pt等模型加载、预测、导出的用法基本不变。至于 YOLO26如果它是某个后续版本或二次开发的工程代号最终训练得到的权重如果仍是 Ultralytics 格式那么调用方式也保持一致如果它不是标准格式你需要在项目 README 中确认它到底通过什么模块加载不要盲目套用YOLO(best.pt)。在开始写检测代码之前先确认权重本身是什么任务产出的。best.pt可能来自三种情况官方预训练权重或迁移学习后的权重类别数量通常是 80 类对应 COCO 数据集可以直接检测人、车、猫、狗等常见目标。自定义数据集训练产物best.pt的类别列表就是你训练时的data.yaml中配置的类别输出框只会包含你标注过的目标类型。第三方分享或剪枝蒸馏后的权重这种权重来源不明使用前一定要确认类别顺序、输入尺寸和模型格式不能假设它和你的业务类别一致。判断你手里的权重是做什么任务、多少类别的办法很简单加载后直接打印model.names。from ultralytics import YOLO model YOLO(weights/best.pt) print(model.names)输出的model.names是一个字典键是类别 ID值是对应的类别名称。比如{0: person, 1: car}。如果这里的类别和你业务预期不一致后面检测出来的框即使坐标正确类别含义也可能是错的这一点必须在一开始就排查掉。另外一个高频问题是应该用best.pt还是last.pt部署训练默认会把验证集指标最好的权重保存为best.pt把最后一轮权重保存为last.pt。正常情况部署选best.pt如果你训练中断需要继续训练可以加载last.pt续跑但现在做推理测试时直接加载best.pt最合理。3. 环境准备与工程目录规划YOLO 推理工程对机器不算苛刻但环境不一致会导致很多“代码对但跑不通”的问题。我建议无论你最终用 GPU 还是 CPU都按下面这套流程把环境梳理一遍。3.1 硬件与驱动检查如果你的电脑是 NVIDIA 显卡先确认驱动版本是否足够新。Windows 上可以在命令行执行nvidia-smi能看到显卡型号和驱动版本就说明驱动正常。Linux 和 Windows 都适用该命令。如果执行后提示找不到命令通常是驱动没装好或者命令路径没加入环境变量。AMD 显卡或者核显用户经常问“能不能跑 YOLO”。这里给出一个稳妥的判断PyTorch 官方 Windows 版本默认支持 NVIDIA CUDAAMD 显卡无法直接享受同样的 CUDA 加速你可以用 CPU 推理先把功能跑通也可以通过其他部署方式做加速测试但需要自己额外配置并验证兼容性。不是所有优化方案都稳定新手不要一上来就折腾底层加速先确认模型逻辑是否正确。想查看 Python 环境是否能调用 GPU不要只看 PyTorch 装没装要看 CUDA 是否真的可用。在 Python 里执行import torch print(torch version:, torch.__version__) print(cuda available:, torch.cuda.is_available()) if torch.cuda.is_available(): print(gpu name:, torch.cuda.get_device_name(0))如果cuda available输出 True说明 PyTorch 能正常调用 GPU。如果输出 False即使你安装了 CUDA 版 PyTorch也可能是显卡太老、驱动不匹配或者安装的 PyTorch 实际是 CPU 版本。此时程序仍然能跑但会走 CPU 推理速度需要单独评估。3.2 Python 环境安装推荐用虚拟环境隔离项目依赖避免把系统 Python 环境弄得一团糟。创建并激活环境后安装 Ultralytics 和常用图像处理库conda create -n yolo python3.10 -y conda activate yolo pip install ultralytics opencv-python numpy pillow如果你的网络使用默认源下载很慢可以自行选择国内镜像源这里不做展开。安装完成后执行pip show ultralytics查看具体版本号记录一下后面如果出现接口不兼容的问题可以判断是不是版本差异导致。3.3 工程目录规划一个典型的 YOLO 推理工程建议按下面结构组织yolo_project/ ├── weights/ │ └── best.pt ├── test_images/ │ ├── 1.jpg │ └── 2.png ├── test_videos/ │ └── demo.mp4 ├── runs/ # Ultralytics 默认输出目录 ├── detect_image.py ├── detect_video.py ├── detect_camera.py └── api_server.pyweights/下放权重文件test_images/和test_videos/放测试素材所有脚本输出统一落到runs/。这样做的好处是模型文件、输入素材、输出结果三部分解耦批量任务和日志排查都更清晰不会出现代码里散落一堆绝对路径的情况。4. 图片检测调用 best.pt 做单张与批量推理图片检测是 YOLO 最基础的用法所有其他输入类型的推理最终都是把图像帧交给模型处理。先写单张图片检测脚本。4.1 单张图片检测脚本新建detect_image.py内容如下from ultralytics import YOLO # 加载权重 model YOLO(weights/best.pt) # 对单张图片做推理 results model.predict( sourcetest_images/1.jpg, conf0.25, saveTrue, projectruns, nameimage_detect, ) # 查看第一张图的检测结果 boxes results[0].boxes print(检测到目标数量:, len(boxes)) print(类别 ID:, boxes.cls.tolist()) print(置信度:, boxes.conf.tolist()) print(坐标 xyxy:, boxes.xyxy.tolist())这里有几个常用参数需要解释。source可以是图片路径、视频路径、摄像头整数编号、图片列表或文件夹路径。conf0.25表示只保留置信度大于等于 0.25 的目标框如果检测场景比较复杂或者你的模型训练样本少可以先把conf调低到 0.05 或 0.1 观察漏检情况。saveTrue表示保存标注后的结果图片。project和name控制输出目录最终结果会保存到runs/image_detect/下。如果多次运行同名任务Ultralytics 一般会自动追加序号不会直接覆盖原有结果。执行脚本python detect_image.py正常情况会在输出目录生成带检测框的图片控制台也会打印每张图片的检测数量和耗时。如果你还想看到当前用的是 GPU 还是 CPU可以加一行print(当前设备:, model.device)Ultralytics 会自动判断可用的设备。如果你明确想指定 GPU 编号或使用 CPU可以在predict里加device0或devicecpu。4.2 批量图片检测批量检测并不需要写循环一张张读图片直接把文件路径列表传给source即可。from pathlib import Path from ultralytics import YOLO model YOLO(weights/best.pt) # 收集文件夹下所有 jpg 和 png 图片 image_dir Path(test_images) image_paths list(image_dir.glob(*.jpg)) list(image_dir.glob(*.png)) if not image_paths: raise FileNotFoundError(test_images 目录下没有找到 jpg/png 图片) results model.predict( sourceimage_paths, conf0.25, saveTrue, projectruns, namebatch_detect, ) print(f共处理 {len(results)} 张图片) for i, result in enumerate(results): print(f第 {i 1} 张图检测框数量: {len(result.boxes)})批量推理时results是一个列表每个元素对应一张输入图片。如果你的图片大小差距较大Ultralytics 会统一缩放到默认输入尺寸再送入模型。这种批量方式适合目录数据整理比单独循环调用更快代码也更简洁。4.3 检测结果怎样才算正常图片检测跑通之后要验证的不是“有没有报错”而是“检测结果是否符合预期”。判断标准有四点输出目录里出现了标注图片且图片中目标被画框。打印的坐标数量与画面中可辨识的目标数量基本匹配。类别 ID 对应的名称与你训练的类别一致。置信度分布合理没有被过度误检或大量漏检。如果一张明显包含目标的图片检测结果为 0 个框优先检查conf是否设得过高以及best.pt的类别列表是否覆盖了当前场景。如果类别都不在训练数据里不管置信度怎么调都不会有结果。5. 视频与摄像头检测从文件到实时流视频检测的本质仍然是逐帧推理只是多了一步视频读取和结果回写。Ultralytics 的predict方法对视频源做了封装调用起来和图片类似但实时摄像头场景建议用循环方式这样你能控制退出逻辑。5.1 视频文件检测本地视频文件检测可以直接写from ultralytics import YOLO model YOLO(weights/best.pt) results model.predict( sourcetest_videos/demo.mp4, conf0.25, saveTrue, projectruns, namevideo_detect, ) print(视频推理完成)运行后输出目录下会自动生成检测后的视频文件。这里有一个容易被忽略的点如果视频很大推理时间会明显拉长它不是实时播放而是逐帧处理后写文件。所以如果你只想快速看效果先用短视频测试。如果视频推理过程中显存不足需要降低输入分辨率比如把imgsz640改成imgsz480或imgsz320代价是小目标可能更容易漏检。视频推理的一个优势是可以配合streamTrue使用生成器方式逐帧处理避免一次性把所有帧结果都存在内存里。对于超长视频建议使用from ultralytics import YOLO model YOLO(weights/best.pt) results model.predict( sourcetest_videos/demo.mp4, conf0.25, saveTrue, streamTrue, projectruns, namevideo_stream_detect, ) for result in results: # 逐段处理避免内存持续上涨 passstreamTrue时predict返回生成器对象遍历一次处理一段适合日志型视频分析。5.2 摄像头实时检测摄像头检测建议用OpenCV读取视频帧再把每一帧交给 YOLO 推理。代码并不复杂关键是要处理摄像头打不开、退出按键、资源释放这三件事。import cv2 from ultralytics import YOLO model YOLO(weights/best.pt) # 0 表示默认摄像头如果有多个摄像头可改成 1、2 cap cv2.VideoCapture(0) if not cap.isOpened(): raise RuntimeError(摄像头无法打开请检查编号或是否被其他程序占用) while True: ret, frame cap.read() if not ret: print(读取视频帧失败退出) break # 单帧推理 results model.predict(frame, conf0.25, imgsz640, verboseFalse) annotated_frame results[0].plot() # 显示标注后的画面 cv2.imshow(YOLO Detection, annotated_frame) # 按 q 退出 if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这里把verboseFalse设置上是为了避免每帧都在控制台刷日志否则实时检测时终端输出会非常乱。results[0].plot()返回的是已经画好检测框的帧你可以直接显示也可以保存。若需要保存摄像头检测视频就需要在循环里用cv2.VideoWriter把annotated_frame连续写入文件。如果你要接入网络摄像头或 RTSP 流把cap cv2.VideoCapture(rtsp://your_ip:554/stream)替换即可。要注意的是RTSP 地址通常包含用户名和密码不要把敏感地址直接提交到公开仓库或公网日志中。延迟和断线重连也需要单独处理实时流网络不稳定时建议加入自动重连逻辑和异常捕获。6. 检测参数调节与批量任务设计YOLO 推理时最常调的参数其实不多但每个参数都会直接影响检测效果和资源占用。建议把下面这张表保存下来后续调优时对照使用。参数作用建议conf置信度阈值低于该值的框会被过滤场景简单用 0.25场景复杂或想观察漏检时降低到 0.1 以下iou非极大值抑制时的 IoU 阈值同一个目标被多个框覆盖时适当降低iou能减少重叠框imgsz推理输入尺寸默认 640显存不足或追求速度可以降低到 480/320device指定 GPU 或 CPUdevice0表示第一张 GPUdevicecpu表示 CPUsave是否保存推理结果图片/视频文件建议 True摄像头实时预览可先 Falsestream是否使用流式输出长视频、摄像头场景建议 True避免内存上涨verbose是否输出详细日志摄像头实时检测建议 False否则不断刷屏classes只检测指定类别例如classes[0]只检测 person适合特定业务如果你需要处理大量图片或视频建议在批量任务外层加入日志与失败重试机制。一个可复用的批量处理写法是先准备任务列表再逐项调用推理并把每项状态写入日志。from pathlib import Path from ultralytics import YOLO model YOLO(weights/best.pt) task_dir Path(test_images) tasks list(task_dir.glob(*.jpg)) list(task_dir.glob(*.png)) failed [] for task in tasks: try: model.predict( sourcestr(task), conf0.15, imgsz640, saveTrue, projectruns, namebatch_task, verboseFalse, ) print(f[OK] {task.name}) except Exception as exc: failed.append(task.name) print(f[ERROR] {task.name}: {exc}) if failed: print(失败文件:, failed) else: print(全部任务处理完成)这样的好处是即使中间某张图损坏导致异常后续任务仍然能继续跑失败清单也会单独记录。数据量比较大时还可以把任务列表写入文本文件处理完一个删一行实现断点续跑。7. 资源占用与显存性能观察很多读者关心 YOLO 推理到底要吃多少显存但这没有一个固定答案。模型本身结构、输入分辨率、批次大小以及是否开启半精度都会影响显存占用。不同机器跑同一个best.pt显存数值也可能差很多。所以更关键的是学会自己观察。NVIDIA 用户可以在推理过程中另开一个终端执行nvidia-smi -l 1-l 1表示每秒刷新一次能实时看到显存和 GPU 利用率变化。Windows 下如果nvidia-smi刷新太快不容易观察也可以打开任务管理器查看 GPU 显存曲线。在 Python 代码里也可以用 PyTorch 查询当前显存占用比如在单张图片推理前后分别打印一次import torch from ultralytics import YOLO model YOLO(weights/best.pt) model.predict(sourcetest_images/1.jpg, conf0.25, saveTrue, verboseFalse) if torch.cuda.is_available(): print(当前显存占用 MB:, torch.cuda.memory_allocated() / 1024 / 1024) print(GPU 缓存显存 MB:, torch.cuda.memory_reserved() / 1024 / 1024)如果你发现显存占用过高优先检查三件事输入尺寸imgsz是不是太大降低到 640 以下能显著降低显存。推理时是否意外把多张图片拼成了一个大 batch批量任务建议单张或小 batch 运行。best.pt模型本身是不是大型号yolo11x这类模型对显存的要求会比yolo11n高很多。CPU 推理虽然没有显存问题但速度会下降明显尤其处理视频时可能达不到实时。如果你想在 AMD 显卡或核显上尝试先把工程用 CPU 模式跑通再评估是否要引入额外的部署加速工具。对于大多数测试场景优先保证功能和结果正确性能优化放到后面。8. 接口 API 与工程集成示例当best.pt检测要接入到现有系统时只写脚本是不够的你需要一个可以接收输入并返回结构化结果的 HTTP 接口。这里用 Flask 做一个最小可用的图片检测接口。首先安装依赖pip install flask然后创建api_server.pyimport cv2 import numpy as np from flask import Flask, request, jsonify from ultralytics import YOLO app Flask(__name__) # 模型只加载一次避免每次请求都重新读权重 model YOLO(weights/best.pt) app.route(/detect, methods[POST]) def detect(): file request.files.get(image) if file is None: return jsonify({code: 400, message: 请上传 image 字段}), 400 # 将上传的图片读取为 OpenCV 图像 data np.frombuffer(file.read(), np.uint8) image cv2.imdecode(data, cv2.IMREAD_COLOR) if image is None: return jsonify({code: 400, message: 图片解析失败}), 400 # 推理 results model.predict(image, conf0.25, verboseFalse) boxes_data results[0].boxes return jsonify({ code: 0, count: len(boxes_data), boxes: boxes_data.xyxy.tolist(), confs: boxes_data.conf.tolist(), classes: boxes_data.cls.tolist(), }) if __name__ __main__: # 本地开发调试时使用生产环境需要更换服务器 app.run(host127.0.0.1, port5000)启动服务python api_server.py用curl测试curl -X POST http://127.0.0.1:5000/detect \ -F imagetest_images/1.jpg返回结果是一个 JSON包含目标数量、每个框的 xyxy 坐标、置信度和类别 ID。这样外部系统就能直接根据返回结果做业务判断比如检测到人员数量超过阈值后进行告警。接口化之后要注意并发问题。Flask 开发服务器默认支持多线程但 Ultralytics 的模型对象如果被多个请求同时调用不能保证绝对线程安全。稳妥的做法是图片检测接口在单线程应用里没问题但并发量高时建议用锁保护推理调用或者把检测逻辑放到独立进程/队列中由 API 服务只负责接收请求和返回结果。生产环境要限制接口的访问范围不要把服务直接暴露到公网至少加一层访问控制。9. 常见问题与排查方法YOLO 推理写起来不长但实际运行中会有各种环境问题。下面按现象整理了排查思路。问题现象可能原因排查方式解决方案ModuleNotFoundError: No module named ultralytics依赖没有安装检查当前 Python 环境执行pip install ultralyticstorch.cuda.is_available()返回 FalsePyTorch 是 CPU 版本或驱动不匹配打印 torch.version重新安装匹配 CUDA 的 PyTorch 版本确认 NVIDIA 驱动正常加载best.pt时提示权重格式错误权重文件不是 Ultralytics 格式或文件损坏检查文件大小确认来源使用正确的best.pt如果是第三方权重阅读项目 README推理结果 0 个框conf过高或类别不匹配先降低 conf 到 0.05 测试尝试官方预训练权重检查训练数据和当前场景是否一致摄像头打不开摄像头编号错误或被占用打印cap.isOpened()把cv2.VideoCapture(0)改成 1 或 2关闭占用摄像头的软件视频推理内存或显存持续上升未使用流式处理或输入批次过大观察任务管理器曲线开启streamTrue降低imgsz单张推理CUDA out of memory显存不足查看nvidia-smi占用情况关闭其他程序降低 imgsz 或 batch模型换小版本不同版本 YOLO 权重混用时报错权重与代码版本不匹配pip show ultralytics查看版本升级或降级 ultralytics 到与训练环境一致API 服务请求速度慢模型加载了多次或并发问题查看服务日志把模型初始化放到全局避免每次请求新建模型画面显示卡顿但 CPU 占用很高使用 CPU 推理或 GPU 未生效model.device打印设备安装 GPU 版 PyTorch确认 CUDA 可用如果出现“代码照抄也报错”的情况请先按错误日志原样搜索而不是盲目重装环境。绝大多数问题都可以通过查看报错堆栈和版本号定位到具体环节。10. 最佳实践与合规边界工程上要稳定运行不是代码能跑就结束。这里给几条实际建议按重要性从高到低排列。第一第一次测试一定用最小的参数组合。先用单张图片、imgsz640、conf0.25走通再逐步加大输入规模。不要一上来就喂一个小时的 4K 视频否则环境问题、显存问题、代码问题会混在一起排错成本很高。第二权重、输入、输出分类管理。权重放weights/素材统一放test_images/、test_videos/模型运行产生的临时结果放在runs/。这样写脚本时相对路径清晰清理垃圾文件也安全。绝对路径能少用就少用尤其是把项目放到别的机器或 Docker 容器里时绝对路径最容易出问题。第三摄像头和视频推理涉及隐私和数据合规。如果摄像头画面包含人员肖像、车牌、办公场所等敏感信息使用前必须获得相应授权处理后的视频和日志也要控制访问范围。对人脸识别、人员追踪类应用还需要确认是否符合当地法律法规和应用场景的合规要求。测试阶段尽量使用公开数据集或自己拍摄的授权素材。第四目标检测不是识别一切。best.pt只能检测出训练集中出现过的类别。如果一个目标在训练数据里没有推理时模型不会画框这是正常现象不是 bug。如果你需要检测新类别需要回到数据标注和训练阶段而不是在推理侧强行加规则。第五接口服务尽量内网访问。API 推理服务暴露给公网之前一定要做访问控制和身份验证避免被恶意调用消耗资源。批量任务也要在接口层做超时和并发限制防止单次大任务把服务打挂。11. 总结与下一步这篇围绕best.pt展开的 YOLO 推理工程把图片、视频、摄像头三种输入方式串成了一套统一调用的代码思路。加载模型用YOLO(weights/best.pt)推理用model.predict(source...)不同的source类型决定了它处理图片、视频还是摄像头这个设计习惯值得保留下来。拿到一个新项目后建议你先跑通单张图片检测验证模型能加载、类别列表正确、检测框输出正常再用视频文件测试流式处理和保存路径最后接摄像头实时检测。最容易踩坑的不是 YOLO 检测代码而是 PyTorch 的 CUDA 环境没配对、best.pt不是 Ultralytics 格式、摄像头资源被占用这三类问题。把这些前置条件确认好后面的批量任务和 API 集成会顺很多。这篇文章可以配合你自己的训练工程直接使用训练结束把runs/detect/train/weights/best.pt复制到weights/下按第 4 节到第 7 节的内容跑通三种输入再根据业务需要决定是否封装接口。建议收藏备用如果你正好卡在“训练完不知道怎么部署”这一步照着配置一遍就能少走弯路。