
1. 项目缘起与整体设计思路机械零件检测这件事在工厂里是个老生常谈的话题。传统做法无非两种一是靠老师傅拿卡尺、塞规一个个量二是上昂贵的专用视觉检测设备。前者效率低、一致性差后者动辄几十万小厂根本吃不消。我所在的团队去年接了个活儿要帮一家做精密五金件的客户搭一套能识别零件表面缺陷划痕、缺料、毛刺和分类计数的系统预算有限但要求能落地、能演示、能后续自己维护。选型的时候我们对比了几条路线。OpenCV传统图像处理做缺陷检测对光照和零件摆放姿态极其敏感换个批次的产品就得重新调参维护成本太高。商用视觉软件如Halcon、VisionPro效果确实好但授权费用摆在那里而且客户希望后续能自己改模型、加新零件种类闭源方案不现实。最后锁定YOLOv8理由很直接它是目前目标检测领域里工程化程度最高、社区最活跃的模型之一训练和推理的代码封装得足够简洁文档齐全遇到问题搜得到答案。更关键的是YOLOv8支持从检测到分类再到分割的多任务统一框架后续客户想加分类功能不用换模型。界面这块客户明确要求“像手机App一样好用”操作员不需要懂命令行。PySide6是Qt官方Python绑定控件丰富、跨平台、文档完善而且和Python生态无缝衔接。用PySide6做可视化界面配合YOLOv8的Python推理接口整个系统可以打包成一个exe双击就能跑这对产线操作员来说是最友好的形态。整体架构我设计成三层底层是YOLOv8推理引擎负责加载模型、处理图像、输出检测结果中间层是业务逻辑处理检测结果的过滤、计数、报警逻辑上层是PySide6界面负责展示视频流、检测框、统计数据和操作按钮。三层之间通过信号槽机制解耦界面不直接调用推理代码而是通过信号触发这样后续换模型或改界面都不会互相影响。提示架构设计阶段一定要把“推理”和“界面”彻底分开。我见过太多项目把推理代码直接写在按钮的槽函数里后期想换个模型或者加个批量处理功能改起来牵一发动全身。2. 环境搭建与YOLOv8基础配置2.1 Python环境与CUDA版本选择环境配置是新手最容易卡住的地方。我的建议是不要用最新版的Python也不要盲目追最新的CUDA。经过多次实测Python 3.9或3.10配合CUDA 11.8是目前YOLOv8最稳的组合。PyTorch 2.0以上版本对CUDA 11.8的支持非常成熟而YOLOv8的ultralytics库在这个组合下几乎没有兼容性问题。显卡方面GTX 1660 Ti 6GB显存跑YOLOv8n或YOLOv8s完全够用训练时batch size设到8或16都没问题。如果是RTX 3060 12GB可以上YOLOv8m。显存低于4GB的话建议只用YOLOv8n并且推理时把imgsz降到416或320。这里有个经验显存不足时不要硬撑大模型YOLOv8n在机械零件这种类别少、特征明显的场景下精度损失很小但速度提升明显。安装步骤我习惯用conda建独立环境避免污染系统Pythonconda create -n yolov8_env python3.10 conda activate yolov8_env pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics pip install pyside6装完之后验证一下import torch print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))如果输出True和显卡型号说明环境没问题。如果False大概率是CUDA版本和PyTorch不匹配重新装对应版本的PyTorch即可。2.2 PySide6安装与中文手册使用PySide6的安装很简单pip install pyside6就行。但新手常遇到的问题是装完之后不知道从哪开始写界面。我的建议是先用Qt Designer拖控件生成.ui文件再用pyside6-uic转换成.py文件。这样上手快而且界面布局直观。PySide6中文手册网上有社区维护的版本虽然不如官方英文文档全但常用控件的说明基本都有。我查手册的习惯是先看控件有哪些信号signal再看有哪些槽slot最后看常用方法。比如QPushButton的clicked信号、QLabel的setPixmap方法这些是高频使用的。注意PySide6和PyQt5的API有差异网上很多PyQt5的代码不能直接复制到PySide6里跑。主要区别在信号槽的连接语法和部分枚举类型。遇到报错先查是不是版本差异导致的。2.3 YOLOv8模型下载与预训练权重ultralytics库自带模型下载功能第一次运行时会自动从官方仓库拉取预训练权重。但国内网络环境有时候不稳定建议手动下载yolov8n.pt、yolov8s.pt放到项目目录下然后在代码里指定路径加载。预训练权重的作用是迁移学习。机械零件检测的数据集通常不大几百到几千张图从零训练容易过拟合。用COCO数据集预训练的权重做初始化模型已经学会了提取边缘、纹理等基础特征微调时收敛快、精度高。我实测过同样500张训练图从预训练权重开始训练mAP50能到0.92从零训练只有0.78左右。3. 机械零件数据集制作与训练调参3.1 数据采集与标注规范机械零件的数据采集有几个坑。第一光照要尽量模拟产线环境不要用实验室的均匀光源否则模型到现场就废了。第二零件摆放姿态要覆盖实际可能出现的角度特别是容易混淆的正反面。第三背景要干净但要有一定变化纯白背景训练出来的模型换到灰色传送带上就识别不准。标注用LabelImg或Roboflow都行格式选YOLO格式txt文件每行是类别id、中心点x、中心点y、宽、高全部归一化到0-1。标注时有个经验缺陷区域如果很小比如细微划痕标注框不要贴得太紧稍微外扩几个像素给模型一点上下文信息召回率会更高。数据集划分比例建议7:2:1训练集、验证集、测试集。如果数据量少于500张可以用8:1:1但测试集至少要留50张否则评估结果不可靠。3.2 训练参数配置与freeze技巧YOLOv8的训练命令很简洁yolo detect train datadataset.yaml modelyolov8n.pt epochs100 imgsz640 batch16 lr00.01 freeze10这里重点说几个参数。freeze10表示冻结骨干网络的前10层只训练检测头。机械零件数据集小的时候冻结骨干能防止过拟合而且训练速度更快。我通常先freeze训练50轮再解冻全部训练50轮效果比直接全量训练好。lr0是初始学习率默认0.01。如果loss震荡厉害降到0.001。batch size根据显存来GTX 1660 Ti用16RTX 3060用32。imgsz默认640如果零件特别小可以提到1280但显存占用会翻倍。训练过程中可以用tensorboard看损失曲线tensorboard --logdir runs/detect/train关注三个指标box_loss定位损失、cls_loss分类损失、mAP50。正常情况下box_loss和cls_loss应该稳步下降mAP50稳步上升。如果cls_loss不降反升说明学习率太大或者标注有问题。3.3 数据增强与轻量化改进YOLOv8默认开启了Mosaic、HSV增强、随机翻转等数据增强。机械零件场景下我建议关掉随机旋转degrees0因为零件有方向性旋转后可能变成不合理的姿态。HSV增强可以保留模拟不同光照条件。如果要在嵌入式设备上部署比如RK3588需要做轻量化改进。常见做法是把骨干网络换成MobileNetV3或ShuffleNetV2或者用剪枝工具砍掉冗余通道。我试过用YOLOv8n配合通道剪枝模型从6MB压到3MB推理速度提升40%精度只掉1.5个百分点。RK3588部署YOLOv8的流程是PyTorch模型转ONNX再转RKNN最后用RKNN Toolkit推理。正点原子的RK3588开发板有完整的部署教程跟着走就行。4. PySide6可视化界面开发实战4.1 界面布局设计与控件选型主界面我分成四个区域顶部是工具栏选择模型、打开摄像头、开始/停止检测左侧是视频显示区右侧是检测结果列表和统计面板底部是状态栏显示FPS、检测总数、报警信息。视频显示用QLabel配合setPixmap每帧更新。检测结果列表用QTableWidget显示类别、置信度、坐标。统计面板用QLabel显示各类别计数。状态栏用QStatusBar。关键控件选型说明视频显示不要用QVideoWidget那个适合播放视频文件不适合逐帧处理。用QLabel最简单可控。检测框的绘制不要在QLabel上直接画而是用OpenCV在图像上画好框再转成QPixmap显示这样性能更好。4.2 信号槽机制与多线程处理这是PySide6开发的核心难点。YOLOv8推理是计算密集型任务如果放在主线程里跑界面会卡死。必须用QThread开子线程做推理通过信号把结果传回主线程更新界面。我的做法是定义一个InferenceWorker类继承QThread在run方法里循环读取视频帧、调用YOLOv8推理、发射结果信号。主线程连接这个信号到更新界面的槽函数。class InferenceWorker(QThread): result_ready Signal(object, object) def run(self): while self.running: frame self.cap.read() results self.model(frame) self.result_ready.emit(frame, results)注意子线程里绝对不能直接操作界面控件否则会崩溃。所有界面更新必须通过信号槽切回主线程。4.3 检测结果可视化与统计逻辑检测框绘制我用OpenCV的rectangle和putText。颜色按类别区分比如划痕用红色缺料用橙色毛刺用黄色。置信度显示在框的左上角。统计逻辑要注意去重。同一帧里同一个零件可能被多个框检测到需要用NMS非极大值抑制过滤。YOLOv8推理时默认开启NMS但IoU阈值要调。机械零件密集摆放时IoU设0.5容易漏检相邻零件设0.7又容易重复计数。我实测0.6比较平衡。计数逻辑用字典维护每个类别的累计数量每帧更新。如果要做产线计数还需要加一个“已计数”标记避免同一个零件在多帧里被重复计数。简单做法是记录每个检测框的中心点如果新框的中心点和已有框距离小于阈值就认为是同一个零件。5. 常见问题排查与避坑经验5.1 环境与依赖问题速查问题现象可能原因解决方法torch.cuda.is_available()返回FalseCUDA与PyTorch版本不匹配重装对应CUDA版本的PyTorch导入ultralytics报错缺少依赖或版本冲突pip install ultralytics --upgradePySide6界面显示乱码字体编码问题设置QFont为支持中文的字体推理速度慢用了CPU推理或imgsz太大确认GPU可用降低imgsz显存溢出batch size或模型太大换YOLOv8n减小batch5.2 训练过程中的典型问题loss不下降先检查标注文件格式对不对类别id是不是从0开始。再看学习率是不是太大降到0.001试试。如果还不行可能是数据集太小加数据或做更强的数据增强。mAP震荡正常现象只要整体趋势向上就行。如果震荡幅度超过10个百分点说明batch size太小或学习率太大。过拟合训练集mAP很高但验证集很低。解决办法加数据、加正则化weight_decay、早停patience20、冻结骨干。检测框重叠NMS的IoU阈值调低或者训练时加更多密集摆放的样本。5.3 界面卡顿与崩溃排查界面卡顿九成是因为推理在主线程跑。检查QThread有没有正确启动信号有没有正确连接。另一个原因是每帧都更新整个界面可以只更新变化的区域。崩溃常见于子线程直接操作控件。记住一个原则子线程只发信号主线程收信号更新界面。如果崩溃时没有任何报错大概率是这个问题。提示开发阶段可以在槽函数里加print确认信号有没有发出来、有没有被接收到。PySide6的信号槽如果连接失败不会报错只是静默不执行。6. 模型部署与性能优化6.1 ONNX导出与TensorRT加速PyTorch模型直接推理速度一般生产环境建议转ONNX或TensorRT。YOLOv8导出ONNX很简单yolo export modelbest.pt formatonnx opset12 simplifyTrueTensorRT加速更明显GTX 1660 Ti上YOLOv8n的PyTorch推理约15ms一帧TensorRT能压到5ms。导出TensorRT引擎yolo export modelbest.pt formatengine halfTrue device0halfTrue表示用FP16精度速度更快精度损失很小。但TensorRT引擎和显卡型号绑定换显卡要重新导出。6.2 模型轻量化与剪枝实践如果要在RK3588这类嵌入式设备上跑模型必须轻量化。除了换骨干网络还可以用ultralytics自带的剪枝功能或者用NNI、Torch-Pruning等工具。我试过Torch-Pruning对YOLOv8n做通道剪枝剪掉30%通道后模型大小从6MB降到4.2MBRK3588上推理速度从80ms降到55msmAP50从0.92降到0.90完全可以接受。剪枝的流程是先稀疏训练加L1正则化再剪枝最后微调。稀疏训练让部分通道的权重趋近于零剪枝时把这些通道去掉微调恢复精度。6.3 多模型切换与热更新客户后续可能要加新零件种类需要支持多模型切换。我的做法是在界面上加一个下拉框列出所有可用的模型文件选择后重新加载。加载模型时用QThread异步加载避免界面卡死。热更新是指不重启程序就能更新模型。实现方式是监听模型文件的变化检测到更新后自动重新加载。这个功能在产线上很实用工程师远程更新模型后操作员不用做任何操作。7. 项目打包与交付注意事项打包用PyInstaller命令pyinstaller --onefile --windowed --add-data best.pt;. --add-data icon.ico;. main.py--onefile生成单个exe--windowed去掉命令行窗口--add-data把模型文件和图标打包进去。注意路径问题打包后资源文件的路径会变代码里要用sys._MEIPASS获取临时目录。交付前一定要在干净的机器上测试确认没有缺失的DLL。常见缺失的是CUDA相关的DLL如果目标机器没装CUDA需要把CUDA运行时库一起打包或者用CPU推理版本。注意PyInstaller打包PySide6时有时候会漏掉Qt插件导致界面显示异常。解决办法是手动把PySide6的plugins目录复制到打包输出目录或者在spec文件里指定。8. 个人实操体会与后续扩展方向这套系统从零到交付用了大约三周其中环境配置和界面调试占了一半时间。最大的体会是不要追求一步到位先跑通最小闭环——能加载模型、能显示视频、能画框然后再加统计、报警、多模型切换这些功能。每加一个功能就测试一次避免最后一起调试时问题堆在一起。后续扩展方向有几个。一是加分类头YOLOv8本身支持分类任务可以在检测框的基础上再判断零件等级合格、返修、报废。二是加跟踪算法比如ByteTrack实现产线上的连续计数和轨迹分析。三是加报警逻辑检测到连续多个缺陷时触发声光报警。四是做Web端远程监控用FastAPI把检测结果推送到浏览器方便主管在办公室查看产线状态。最后分享一个小技巧调试界面时把推理结果保存成视频文件方便回放分析。我习惯每批测试都录一段视频标注好参数后面对比不同模型和参数的效果时非常有用。这个习惯帮我省了很多重复测试的时间。