
先理清一个判断这类“YOLOv8 PyQt5 抽烟检测”项目真正的难点通常不在模型本身而在“怎么把模型训练好、怎么让界面不卡死、怎么在别人电脑上也能跑起来”。模型结构有现成的训练脚本有公开的界面框架也有官方示例但把这三者拼成一个能稳定使用的系统中间会踩到很多文档里不会写的坑。这篇文章就按我实际落地时的顺序来写先讲清楚这个系统解决什么问题再给训练和界面集成的完整思路最后补性能和打包经验。内容主要以通用实践为基础原始材料里没有给出具体版本和参数时我会用“以你的环境为准”来说明边界。1. 先确认需求是做一个课堂演示还是要真的在工地上用很多人看到“抽烟检测系统”第一反应是这不就是目标检测加一个界面吗思路没错但需求不同技术方案差别很大。如果只是课程设计、毕业设计或者公司内部技术验证那核心目标是“能跑通、能演示、能截图写报告”。这种情况下模型精度差一点可以接受界面只要能上传图片和视频、显示出检测框就算完成。但如果是打算放到工地、厂区、食堂走廊这类真实场景里长期跑那就完全是另一回事。你需要考虑摄像头流接入、识别延迟、误报率、日志留存、报警联动甚至还要处理多人同时吸烟、远处小目标、逆光环境、夜间红外画面等复杂情况。这两个方向对数据集、模型选型和界面架构的要求完全不同。我给你的建议是先确定你的验收标准是什么。老师或者领导问你要“能跑通的系统”那按演示版做别过度设计如果对方说“要能在监控室连续跑一周”那就必须把稳定性、日志和报警机制放在第一位。对大多数读者来说第一版建议按演示系统来做但要给后续扩展留好接口。具体来说就是模型文件单独放一个目录检测逻辑写成独立模块界面只负责调用和展示。这样就算后面换模型、加摄像头也不需要重写界面。2. YOLOv8 训练前的准备工作数据集、环境、硬件评估2.1 数据集是整条链路里最重要的一环抽烟检测的数据集不像 COCO 那样容易获得因为“人吸烟”这个动作带有很强的场景属性。很多公开数据集里的图片是摆拍或特写跟监控摄像头拍到的画面差异很大。如果你手头没有现成数据可以按以下方式准备搜集公开的吸烟检测数据集注意看图片分辨率、场景类型和标注格式。如果数据不够自己去拍摄或截图。手机拍、监控截图、视频抽帧都可以。标注工具推荐 LabelImg 或 LabelStudio导出 YOLO 格式。至少要覆盖这些类别person人、smoke烟/烟雾、cigarette香烟具体看你希望检测到什么粒度。这里有个重要判断检测“吸烟”和检测“烟”是两种难度。烟本身很小在监控画面里可能只有几个像素很容易漏检而“人手持烟”这个状态往往更稳定。更稳妥的方案是先检测人再检测人附近的烟用逻辑判断是否在吸烟。很多论文和开源项目也是这么做的。2.2 环境安装与版本匹配YOLOv8 的训练环境以 PyTorch 为主PyQt5 负责界面两者本身不冲突但 Python 版本和依赖包版本会影响你是否能顺利装完。常见组合可以参考软件推荐版本说明Python3.8 到 3.10PyQt5 和 PyTorch 都有较好的兼容性PyTorch2.x 或 1.13以官网和你本机 CUDA 版本为准CUDA11.8 或 12.1用在 NVIDIA 显卡上训练ultralytics8.xYOLOv8 的官方包PyQt55.15.x较稳定如果你用的是 GTX 1660 Ti 这类老显卡建议先查一下你的 CUDA 驱动支持哪个版本的 PyTorch不要一上来就装最新版。显存不够时可以把batch-size调到 4 或 2也可以把输入分辨率从 640 降到 512。原始材料里有“GTX1660ti跑yolov8”这个热搜词说明不少人都在关心低显存能不能训练。答案是能但要把训练轮数和图像尺寸控制好训练时间会明显变长。2.3 数据标注格式转换YOLOv8 训练需要的是 txt 格式的标签文件每行内容为类别编号 中心点x 中心点y 宽度 高度其中坐标值是相对于图片宽高的比例取值在 0 到 1 之间。标注软件一般会帮你转好但如果拿到的是 XML 或 JSON 格式需要写脚本转换。网上有很多现成脚本核心就是读取标注框坐标再除以图片宽高。训练前最好写一个检查脚本确认每张图片都有对应的 txt 文件且标签文件里没有超过图片边界的坐标。不要跳过这一步我在实际项目中碰过不少次“训练能跑但 mAP 一直很低”最后发现是标注坐标越界。3. 训练 YOLOv8 模型参数、命令、验证与改进3.1 准备数据集配置文件YOLOv8 训练需要一份 YAML 配置文件指定训练集和验证集路径以及类别名称。例如path: D:/smoke_detect/data train: images/train val: images/val nc: 2 names: [person, smoke]如果你的标注里还有 cigarette 类别就把nc改成 3并在 names 里对应添加。注意类别顺序一定要和标注文件里的编号一致否则模型训练出来会乱。3.2 训练命令与参数说明在终端进入项目目录执行yolo detect train datasmoke.yaml modelyolov8s.pt epochs100 batch8 imgsz640这里有几个参数值得细说modelyolov8s.pt表示加载 YOLOv8s 预训练权重作为起点。如果你机器性能一般选yolov8n.pt更轻量但精度会略低。epochs不是越大越好。常见经验是小数据集 50 到 100 轮足够如果训练到后面损失不再下降再增加轮数意义不大。batch受显存限制。显存报错时优先调小 batch再考虑调小 imgsz。imgsz训练分辨率。640 是默认值检测小目标时可以考虑 960但显存占用和耗时都会上升。训练过程中要盯两个东西一是 loss 曲线是否在下降二是 val 集的 mAP50 和 mAP50-95 是否在上升。不要只看 lossloss 下降不代表检测效果好。3.3 模型验证训练完以后项目目录下会生成runs/detect/train文件夹里面有训练曲线、验证图片和最佳权重best.pt。用下面命令验证效果yolo detect predict modelruns/detect/train/weights/best.pt sourcetest.jpg预测结果会保存到runs/detect/predict下。这时候你需要人工检查检测框位置准不准、有没有误报、小目标有没有漏掉。模型好不好靠肉眼看图比看指标更直观。3.4 精度不够时怎么改进如果你的模型在测试集上表现一般先别急着换模型结构。按这个顺序排查数据集是否足够大。低于 1000 张图可以考虑做数据增强或补充样本。标注是否准确。标注框过大或过小都会影响学习效果。类别是否容易混淆。烟和烟雾、香烟和笔这类相似物体需要更多标注。检测头是否适合小目标。YOLOv8 本身有小目标检测能力但如果你的目标只有十几个像素可以尝试在 YAML 配置里调整 anchor 或添加 P2 检测层也可以参考网上“YOLOv8小目标检测头”的改进思路。注意力机制。像“引入多头注意力机制MHSA”这类改进通常在特定数据集上有效但会增加计算量建议在 baseline 跑通后再尝试。记住先保证 baseline 能稳定复现再谈改进。很多人一上来就叠注意力、换网络结构结果模型是跑起来了但精度提升不明显的案例我见过不少。4. PyQt5 界面集成线程、信号槽、实时显示4.1 界面功能怎么规划一个抽烟检测系统的界面至少要包含以下模块图片检测选择图片显示检测结果。视频检测选择视频文件逐帧检测并播放结果。实时摄像头检测打开摄像头实时识别。参数区置信度阈值、IOU 阈值。日志区显示每次检测的时间、目标数量、耗时。模型加载状态显示当前加载的权重路径。第一次写界面时先别把功能做全。我的经验是先跑通“图片检测 日志输出”再扩展视频和摄像头。视频和摄像头本质上都是“取帧 - 检测 - 显示”的循环区别只在于取帧来源。4.2 线程处理是重点中的重点很多人用 PyQt5 做检测系统遇到最典型的问题是点击“开始检测”后界面直接卡死。原因是检测过程是耗时操作如果你把它直接放在 GUI 线程里执行界面就会失去响应。正确做法是用QThread或QTimer把视频流读取、模型推理和界面刷新拆开。最简单的方案是自定义一个继承自QThread的检测线程class DetectThread(QThread): frame_signal pyqtSignal(QImage) log_signal pyqtSignal(str) def __init__(self): super().__init__() self.model YOLO(best.pt) self.running True self.source 0 # 0 表示摄像头 def run(self): cap cv2.VideoCapture(self.source) while self.running: ret, frame cap.read() if not ret: break results self.model(frame, conf0.5) annotated_frame results[0].plot() # 转换为 QImage发信号到主界面显示 self.frame_signal.emit(self.cv2qimage(annotated_frame)) cap.release() def stop(self): self.running False界面主线程通过接收到frame_signal来更新 QLabel 显示通过log_signal更新日志。这样界面就不会卡死。注意不要在run()里直接修改界面控件所有界面更新都用信号槽来完成。这是 PyQt5 开发的铁律。4.3 视频播放的“伪实时”问题检测系统跑视频文件时很常见一个现象画面播放速度比实际视频慢很多甚至几秒才出一帧。这不是单纯代码效率问题而是模型推理速度跟不上视频帧率。处理方法有两种跳过帧比如每 2 帧或 3 帧检测一次中间帧直接显示原图。降低分辨率把输入帧缩小到 640x640 以内再做检测显示时再放大回去。如果是摄像头实时检测还要考虑视频缓冲。OpenCV 默认会积压摄像头帧导致你画面看到的是几秒前的旧画面。可以设置cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)这行代码能减少延迟在实时监控场景里很有用。4.4 下拉框闪退和超链接问题原始热搜词里有“pyqt5 下拉框闪退”和“pyqt5 文本框超链接点击后执行自定义操作”这两个问题都很典型。下拉框闪退常见原因是QComboBox的 item 数据里有特殊字符或者在某些 PyQt5 5.15.x 版本下样式表冲突。解决办法是不要自定义复杂样式表使用默认样式测试如果仍然闪退检查 Python 环境和 PyQt5 是否多个版本混乱建议在干净虚拟环境重装。超链接点击执行自定义操作可以用QTextBrowser或QLabel的setOpenExternalLinks(False)然后通过anchorClicked信号绑定自己的函数。这属于界面小技巧但如果你要在日志区输出带颜色的链接文本这个功能很实用。5. 性能优化和部署低配置也能跑但要有取舍5.1 单条任务跑的稳再谈批量处理很多人在开发阶段只跑一条视频觉得没问题就结束了。但一旦你想把这个系统用于真实场景就要考虑批量任务、连续运行和失败重试。这里面最容易忽略的是输出命名冲突。连续处理多张图片时如果输出文件都叫result.jpg后来的会覆盖先前的。视频文件损坏或格式不支持。建议在代码里加 try-except检测失败的帧或视频要跳过或记录。日志输出。每一帧检测到的数量、耗时和置信度都要有时间戳方便以后排查。资源释放。摄像头长期打开不释放内存会持续上涨。我更建议的做法是先写一个不依赖界面的命令行脚本把图片文件夹、视频文件夹和输出目录规划好跑通批量任务后再让界面调用同一个检测函数。这样既方便测试也方便以后做服务化接口。5.2 CPU 推理的边界如果你电脑没有 NVIDIA 显卡YOLOv8 也能在 CPU 上跑推理但速度会慢很多。以 YOLOv8n 为例CPU 上单帧 640x640 大概需要 100 到 300 毫秒左右具体和 CPU 性能有关人眼看起来就是 3 到 10 帧每秒。如果换成 YOLOv8s 或更大模型幀率会进一步下降。对于 CPU 环境有几个优化方向使用model.predict(source, halfTrue)不会生效因为 CPU 不支持半精度。可以忽略。使用 OpenCV 的cv2.dnn转换 ONNX 模型推理有时比 PyTorch 快一点但通用性差一些。降低检测分辨率。model.predict(frame, imgsz480)会减少计算量。换用 YOLOv8n 或 YOLOv8n-seg轻量版在低配机器上体验差异很大。如果你要在嵌入式设备比如 RK3588上跑思路更不一样。RK3588 的 NPU 需要把模型转换成 RKNN 格式转换过程中有些算子可能不支持需要做算子和精度验证。原始热搜词里也有“rk3588部署yolov8”说明这是一个常见的部署方向。我的建议是先在本机确认检测效果再考虑交叉编译和部署否则调试成本会反复叠加。5.3 ONNX 转换和跨平台思路如果你想脱离 Python 环境运行或者把模型接入 C/C# 程序把 YOLOv8 导出成 ONNX 是一种常见做法。命令如下yolo export modelbest.pt formatonnx opset12导出后用onnxruntime在 Python 里做推理可以脱离 PyTorch。速度快一些部署也更方便。但要注意ONNX 导出后有些后处理逻辑如 NMS需要自己实现ultralytics 的 Python 包已经封装好了但如果你要接入 PyQt5 之外的框架需要额外处理。模型导出后可能存在精度下降建议导出后跑一批测试图片对比结果。如果你要用 GPU 版本的 onnxruntime需要额外安装onnxruntime-gpu版本和 CUDA 需要匹配。如果只是做一个本地 GUI 系统直接用 ultralytics 包就够了没必要为了“看起来专业”强行导出 ONNX。6. 开发中常见的报错和排查思路6.1 报错不一定是模型问题先排查环境和数据我遇到过很多次“代码换一台电脑就报错”的情况。刚开始我会去查模型结构和推理逻辑后来发现 80% 的问题出在环境依赖上。下面是几个高频问题的排查顺序现象排查方向备注启动即报错ModuleNotFoundError检查依赖是否安装齐全特别是 PyQt5、ultralytics、opencv-python在虚拟环境里重新安装模型加载报错检查权重路径、ultralytics 版本是否兼容不同版本之间权重文件可能有差异摄像头打开失败检查摄像头编号、权限、是否被其他程序占用了摄像头Windows 上摄像头编号通常从 0 开始视频卡顿或延迟高看推理耗时和显示耗时优先对推理部分做耗时统计不要一开始就改界面逻辑检测结果没有框检查置信度阈值是否过高检查输入图片是否过大导致缩放异常可以先把阈值调到 0.1 测试6.2 日志是排查问题的第一工具写检测系统时最好从一开始就加入日志输出。日志内容至少包括[2025-01-15 10:23:45] 加载模型完成: best.pt [2025-01-15 10:23:45] 开始处理视频: demo.mp4 [2025-01-15 10:23:46] 帧 120: 检测到 1 个目标, 耗时 45ms [2025-01-15 10:24:01] 视频处理完成, 总帧数 1200, 平均耗时 50ms这些日志不仅帮你验证功能是否正常也方便以后接入消息通知或数据库。如果系统在真实环境运行日志留存是必须的不然出了问题没有依据。6.3 界面和模型解耦是以后扩展的基础现在很多项目会宣传“多模态检测识别”“基于视觉检测的深度学习模型构建”听起来很复杂但落地时核心还是模型、数据、界面、存储四层。如果一开始就把模型和界面写得耦合在一起后续换模型、加功能都会动到界面代码风险很高。一个更稳妥的目录结构是smoke_detect_system/ ├── models/ # 存放训练好的权重文件 │ └── best.pt ├── ui/ # 界面代码 │ ├── main_window.py │ └── detect_thread.py ├── core/ # 检测逻辑不依赖界面 │ ├── detector.py │ └── video_processor.py ├── data/ # 输入输出数据 │ ├── input/ │ └── output/ ├── logs/ # 日志目录 ├── requirements.txt └── main.pydetector.py里只负责模型加载和推理返回标注后的图像和检测结果列表video_processor.py负责读视频、循环调detector、控制帧率main_window.py只负责按钮事件和信号槽。这样分工清晰以后加摄像头、加数据库、加 Web 接口都很方便。7. 几个容易被忽略但很影响体验的细节7.1 阈值调节的实时性很多检测系统把置信度阈值写死在代码里用户不能调。但不同场景下阈值需求差异很大室内光线好0.5 可能够用室外逆光时识别结果置信度普遍偏低需要下调到 0.35 左右。界面设计时用QSlider绑定置信度参数并让检测线程实时读取阈值是提升系统可用性的关键。不要在每次滑动滑块后重新加载模型只需要让线程在下一帧推理时使用新阈值即可。7.2 结果保存和报警如果你做的检测系统要用于安全监督检测到吸烟行为后需要截图保存并触发报警或记录到表格。保存图片的命名最好带上时间戳和检测目标数比如20250115_102345_box1_conf0.82.jpg这样方便以后统计和回查。报警可以先用界面弹窗或声音提示更高级的可以接企业微信机器人或短信接口。这部分因场景而异但一定要做记录否则“检测到了”和“提醒到了”是两回事。7.3 关于“多模态”和“注意力机制改进”的建议网上很多项目会提到“引入多头注意力机制MHSA”“多模态检测识别数据集”等改进方向。如果你是为了学习可以跟读论文和代码但如果你是为了交付一个抽烟检测系统我建议先把 baseline 跑通再考虑改进。原因很简单注意力机制通常会增加参数量和计算量你的显卡可能扛不住。改进效果和数据集高度相关在公开数据集上有效不代表在你的烟头数据集上有效。训练时间会大幅增加调试成本也更高。先拿到稳定可运行的 v1 版本再在 v2 里做改进是比较推荐的节奏。8. 打包和交付让别人也能双击运行8.1 PyInstaller 打包的注意事项开发完成后如果要把系统给没有 Python 环境的同事用需要用 PyInstaller 打包成 exeWindows。打包命令示例pyinstaller -w -F main.py --hidden-importultralytics --hidden-importPyQt5有几个坑非常常见-w表示不显示命令行窗口但这样出错时看不到输出建议调试阶段先去掉-w。模型文件 best.pt 不会被自动打包进去需要单独放一个目录然后用路径访问。可以通过sys._MEIPASS处理临时路径也可以直接把模型放在 exe 同级目录下。PyQt5 有些插件文件比如platforms/qwindows.dll会被 PyInstaller 自动处理但如果你用了非标准控件或样式要检查是否缺 DLL。打包以后 exe 体积会比较大一般 100MB 起步属于正常现象不必太过纠结。8.2 给用户的最小使用说明系统交付时建议附一个简单的 README 或运行说明至少包括模型文件放在哪里。Python 版本和依赖怎么安装。第一次启动要修改哪些路径。检测阈值默认值是多少如何在界面上调整。日志文件在哪里出现问题时发哪部分日志。这些细节看起来琐碎但在实际使用中特别重要。很多系统“开发的时候一切正常一交付就各种莫名其妙的问题”绝大多数是路径不对、目录没有权限、模型文件缺失导致。9. 最后留几个我会优先看的点如果你准备动手做这个系统或者在已有代码上改建议按下面的顺序检查一遍数据集标注格式是否正确图片和 txt 文件是否一一对应。这一步最基础也最容易出错。训练配置里类别数量和你标注的类别总数是否一致。训练完成后用best.pt在测试视频上验证不要只看验证集指标。界面加载模型时确认模型路径、置信度阈值、输出目录都是可配置的不要写死。摄像头实时检测时确认帧率和延迟是否可接受不要打开摄像头后界面假死。打包时确认权重文件是否已经放入正确目录在另外一台机器上测试过再交付。这类“深度学习模型 桌面界面”的项目真正验证功力的地方不在于模型多高级而在于能不能稳定运行、能不能方便维护、能不能解决实际场景里的具体问题。先把单条图片检测做稳再把视频和摄像头接起来最后再考虑批量化和打包这个顺序能帮你少走很多弯路。