☰
YOLOv10可回收塑料识别分类检测系统:数据集训练到界面部署全流程
2026/10/19 12:24:59 网站建设 项目流程

做过识别项目的人应该都有同感:模型选型只是第一步,真正磨人的是数据、训练和产品化那一段路。这个项目标题里写的“YOLOv10可回收塑料识别分类检测系统”,本质上就是一个完整的目标检测小产品——从塑料瓶到塑料袋,能在画面里标出来类别、画上框,再通过界面直接操作。YOLOv10负责模型侧,数据集负责教会模型认瓶子,UI界面负责把能力交到用户手里。这篇文章就把整个系统从数据集到界面部署完整拆开讲一遍,内容包括七个典型可回收塑料类别的标注与训练、v10的端到端推理优势、基于PySide6的界面实现、摄像头与图片检测的接入方式,以及我在实际搭建中踩过的一些坑。无论你是课程设计、毕业项目还是想做环保方向的Demo,这套思路可以直接复用。

1. 项目整体拆解与选型思路

1.1 系统解决的核心问题

可回收塑料的分拣在现实里并不像想象中那么简单。一只压扁的矿泉水瓶、一个酱料罐、一张保鲜膜,从视觉上看都是“塑料”,但材质完全不同——PET、HDPE、PP这些名称背后对应的是不同的回收再生流程。人工目检分拣效率低、容易疲劳,传统图像处理又很难适应复杂背景和光照变化,所以一套能自动识别并分类塑料材质的视觉系统,在环保回收、智慧垃圾分拣、循环经济园区这些场景下都有实际价值。

这个项目把任务明确为:输入一张图片、一段视频或者摄像头实时画面,输出画面中每个塑料目标的类别标签和边界框坐标,同时用可视化界面展示结果。用一个统一的系统来完成检测和展示闭环,而不是只停留在跑通一个训练脚本的程度。

从这个角度看,系统的核心能力落在三个层面:模型要认得准、推理要快、界面要能直接用。三个层面里任何一层瘸腿,整体体验都会打折扣。

1.2 为什么选YOLOv10而不是其他检测方案

目标检测领域可选的方案不少,老牌的两阶段代表Faster R-CNN精度高但速度是短板,单阶段的SSD轻快但小目标和遮挡场景表现一般,YOLO系列则一直走速度与精度平衡的路线。到了YOLOv10,几个关键变化值得注意:它设计了一个无NMS(非极大值抑制)的训练推理框架,统一了标签分配策略(双标签分配),推理时不再需要额外的后处理步骤,延迟更低、端到端特性更强。

对塑料识别这个场景来说,实时性非常关键。在传送带分拣或者摄像头扫视的场景里,单帧处理时间往往决定了系统能不能落地。实测在同一张测试图上,YOLOv10的推理延迟相比同尺寸的YOLOv8有一定幅度的下降,同时mAP并没有明显牺牲。选择v10不是因为它是最新的所以无脑用,而是因为这个场景确实需要低延迟、高吞吐,端到端推理也能让部署代码更简洁。

1.3 整体技术架构与目录结构

系统的技术栈比较典型:Python做主体,PyTorch + ultralytics做训练和推理,PySide6做桌面界面,OpenCV处理图像流。模型选用YOLOv10s(small版本)作为默认档位,平衡了显存占用、速度和精度。项目目录一般按以下方式划分,建议从一开始就规范好,后面迭代会省很多事:

plastic_recognition/ ├── dataset/ # 标注后的数据集,images/ + labels/ ├── weights/ # 预训练权重和训练产出的最佳模型 ├── scripts/ # 训练、验证、转换脚本 ├── ui/ # 界面代码,主窗口和各个检测子模块 ├── models/ # 网络配置或推理封装类 └── requirements.txt

界面层和数据层分开,模型推理封装成独立类,这样后面换模型版本或者从图片检测扩展到视频流检测时,不需要把界面代码重写一遍。

2. 可回收塑料数据集构建全流程

2.1 类别体系怎么定

可回收塑料的材质分类,行业里通常参考塑料制品底部的三角形回收标识编号,也就是树脂编码体系。项目把数据集定位成七个类别:PET(聚酯,常见矿泉水瓶、饮料瓶)、HDPE(高密度聚乙烯,常见洗护用品瓶、药瓶)、PVC(聚氯乙烯,常见管道、保鲜膜)、LDPE(低密度聚乙烯,常见塑料袋、保鲜膜)、PP(聚丙烯,常见食品容器、瓶盖)、PS(聚苯乙烯,常见一次性餐盒、泡沫),再加上一个Other用于兜底不确定的塑料制品。

这里有一个经验:不要一开始就追求十二三个细分类,类别越多标注成本和训练难度越高,而且材质相近的类别容易互相干扰。比如LDPE薄膜和PP薄片在图片里长得很像,如果标注不仔细,模型会学到错误特征。先用七个大类把流程跑通,需要细分再逐步加类别,项目节奏更可控。

2.2 图片采集的实操建议

训练数据质量直接决定模型的动手能力。采集阶段不需要昂贵设备,手机拍摄即可,但有几点直接影响效果的细节值得注意。

多场景原则是第一位的。同一只矿泉水瓶,要拍它在桌面、草地、传送带、纸箱、反光面等不同背景下的样子,同时覆盖室内灯、晴天窗边光、逆光、阴天等光照变化。这样模型学到的才是“瓶子本身的特征”,而不是“某个桌面的纹理”。其次要拍压扁、揉皱、堆叠、半遮挡、倾斜等不同状态,因为回收场景里干净的完整瓶子反而是少数。再就是同一物品的不同品牌和颜色,比如不同色号的洗护瓶——它们材质可能都是HDPE,但外形设计差异很大,样本多样性要够。

拍摄后建议统一做人工筛图,剔除模糊、无目标、过度重复的帧。宁可要质量高的一千张,不要勉强凑数的一万张。

2.3 标注格式与工具操作

目标检测的数据标注格式里,YOLO格式应该说是坑最少的一种。每张图片对应一个同名txt文件,每行表示一个目标:

class_id x_center y_center width height

和VOC的XML或者COCO的JSON不同,YOLO格式的坐标是相对于图片宽高的归一化数值。举个例子,一张640x640的图里,一只瓶子的中心点在像素坐标(400, 300),宽200,高400,对应的归一化标注就是:

0 0.625 0.46875 0.3125 0.625

计算公式很简单:中心点x除以宽度、中心点y除以高度、目标宽除以图片宽、目标高除以图片高。为什么要归一化?因为模型训练时输入图片会被resize到固定尺寸,归一化坐标在resize过程中保持不变,省去了大量坐标变换的麻烦。

标注工具推荐LabelImg或者Label Studio。LabelImg老牌稳定,单机标注足够;Label Studio功能更多,支持多人协作,适合数据集比较大的情况。标注时有一条重要经验:可回收塑料的外形边界常常不规则,尤其塑料袋和薄膜,标注框要尽量贴合最主要的目标物体,不要把背景大面积框进框里,否则模型训练时会学到多余背景信息。

2.4 数据增强与划分策略

数据集规模方面,按我的经验,七类塑料、每类300-500张干净标注图是一个出效果的最低门槛。总计2500-3500张左右,配合增强手段,足以支撑YOLOv10s训出一个应用级模型。如果部分类别(比如PVC)样本数少,可以采用同类别过采样或者用增强手段额外生成样本。

数据增强在ultralytics框架里开箱即用,训练时默认会做随机翻转、缩放、色域变换等。针对塑料识别这个场景,我觉得有两个增强特别值得加:一是亮度对比度扰动,因为塑料表面反光强烈,光照变化对视觉特征影响大;二是随机遮挡(cutout),模拟瓶瓶罐罐堆叠遮挡的场景。增强不是越多越好,过强的增强会让模型学不到真实分布,建议用预置增强配置训练一个baseline,再逐步增强观察验证集指标变化。

划分策略上,train/val/test按8:1:1比较常见。test集务必保证来自不同的拍摄批次或场景,不要和train集高度相似,否则验证结果会虚高,部署到真实场景会瞬间现原形。

3. YOLOv10模型训练与核心参数解析

3.1 环境准备与预训练模型选择

训练环境的版本组合直接影响到能否顺利复现,这里给出一套实测兼容性较好的组合:

组件推荐版本说明
Python3.8 - 3.113.10和3.11都稳,避免过新的3.12踩第三方包兼容坑
PyTorch2.xCUDA版本根据显卡驱动对应的版本安装
ultralytics8.x已内置YOLOv10模型定义
OpenCV4.x负责图像读取和处理
PySide66.x搭建界面

权重选择上,YOLOv10官方提供n/s/m/l/x五个尺寸档位。塑料识别不是超大规模类别任务,s(small)是性价比最高的起点,显存要求低、速度快。如果你的标注数据质量很高、样本量很大,后续可以换m档进一步提高精度;如果是部署到嵌入式设备,n档也是可以接受的选择。

使用预训练权重做迁移学习非常关键。完全随机初始化训练一个检测头在几千张图的小数据集上很难收敛好,而从COCO预训练的权重出发,模型已经具备通用的物体边缘、纹理、形状特征提取能力,我们只需要微调它认识塑料材质类别,收敛速度和最终精度都会明显更好。

3.2 训练脚本与参数配置

ultralytics框架把训练入口封装得很简洁,核心训练脚本如下:

from ultralytics import YOLO model = YOLO("yolov10s.pt") # 加载COCO预训练权重 model.train( data="./dataset/data.yaml", epochs=200, imgsz=640, batch=16, lr0=0.01, patience=30, device=0, # GPU索引,CPU训练则设为"cpu" workers=4, project="./runs", name="plastic_exp" )

每个参数都有讲究。imgsz=640是精度和速度的经典平衡点,如果主要检测小目标,可以提高到768或896,代价是显存占用上升;batch=16在8G显存的卡上跑YOLOv10s是安全的,如果显存不足可以降为8并适当提高训练轮数;lr0=0.01是默认值,通常不用动,如果发现loss震荡明显,可以降到0.005试试。

data.yaml是训练入口,内容和格式很重要:

# dataset/data.yaml path: ./dataset train: images/train val: images/val test: images/test nc: 7 names: ["PET", "HDPE", "PVC", "LDPE", "PP", "PS", "Other"]

这里的path路径必须是真实的,nc类别数和names列表顺序必须和标注时保持一致。特别提醒:如果标注时把类别顺序搞乱了,比如训练脚本里names顺序和生成txt时用的class_id顺序不一致,模型会学一个错位的映射,表面看loss在降,实际推理结果全是乱的。

3.3 训练过程监控与指标解读

训练过程中,ultralytics会输出每个epoch的loss、mAP、precision、recall等指标。对新手来说,不要只看loss降没降,重点盯三个东西:

第一个是mAP50,代表IoU阈值为0.5时的平均精度,反映了模型“大概框对、类别对”的能力,这个指标在八九十以上才算可用。第二个是mAP50-95,它跨多个IoU阈值计算,更加严格,能反映框的贴合度和定位精度,塑料识别场景里如果这个指标太低,框会明显偏大偏小,影响分拣判断。第三个是precision和recall的平衡,前者是查准率,指检出的目标里真正正确的比例;后者是查全率,指真实目标被成功找出的比例。

训练全过程里一个常见趋势是:epoch前中期loss下降明显,mAP快速上升;到了后期,mAP可能出现震荡,这通常是学习率过大或者数据噪声导致的。这时候patience=30的早停机制会发挥作用——连续30轮验证集指标没有提升就自动停止,保存最优权重。建议训练完看runs/plastic_exp/weights/best.pt和last.pt,best是验证集表现最好的权重,也是后面推理、部署要用的。

3.4 训练踩坑与优化方向

我实际训练这个项目时碰到过两个典型的坑。第一个是类别不平衡:PET和HDPE瓶子样本充足,PVC和PS样本偏少,导致模型整体mAP不错,但单独看PVC这一类的recall只有五十多。解决办法有二,一是增加PVC样本的采集和标注,二是在训练时给少数类提高损失权重。ultralytics中可以在data.yaml里为各类配置不同权重,或者在数据加载层面过采样。第二个坑是薄膜类目标标注框太大、目标占比太小,导致模型在遮挡情况下经常只检出半个目标。后来提高imgsz到768并增加了更多小目标的整图样本,提升了这部分表现。

还有一个方向值得尝试:如果场景光照条件比较固定(比如室内传送带),可以采集一部分高质量的同场景图片微调模型,这种迁移在真实部署中往往效果立竿见影。

4. UI界面与检测推理的工程实现

4.1 界面功能需求与模块设计

模型训好之后,系统的价值需要通过界面真正释放出来。界面功能我按实际使用流程来设计:打开程序后可以选择图片检测、视频文件检测或摄像头实时检测三种模式。检测结果区域实时显示标注框和类别;右侧信息栏显示当前目标数量、各类别置信度、单帧推理耗时;底部提供“导出结果”按钮,可以把标注后的图片或视频保存到本地。

界面和推理逻辑务必分层,否则后续扩展会非常痛苦。Detector类负责加载权重、执行前向推理、解析结果、提供检测数据;MainWindow负责接收用户交互、展示画面、刷新统计信息。两者通过信号槽解耦,界面线程永不阻塞,检测结果通过信号传回界面线程刷新,这是一套标准的PySide6开发模式。

4.2 核心检测流程代码解析

我先封装一个推理类,把所有YOLOv10的调用逻辑集中起来:

# ui/detector.py from ultralytics import YOLO import numpy as np class Detector: def __init__(self, model_path="./weights/yolov10s_plastic.pt", conf_thres=0.35, iou_thres=0.5): self.model = YOLO(model_path) self.conf_thres = conf_thres self.iou_thres = iou_thres def predict_frame(self, frame): # 输入BGR帧,输出标注后的帧和检测信息 results = self.model.predict(frame, conf=self.conf_thres, iou=self.iou_thres, verbose=False) result = results[0] annotated = result.plot() # ultralytics自带画框函数 boxes = result.boxes detections = [] if boxes is not None: for box in boxes: cls_id = int(box.cls[0].item()) conf = float(box.conf[0].item()) xyxy = [round(v, 2) for v in box.xyxy[0].tolist()] detections.append({ "class": self.model.names[cls_id], "confidence": round(conf, 3), "bbox": xyxy }) return annotated, detections

这里有两个细节值得说明。一是置信度阈值conf_thres的设定,默认0.35是我做塑料识别时反复试出来的折中值——阈值太高会漏检反光导致的不清晰目标,太低会出现大量误检框,如果某个场景重遮挡,可以单独调整。二是result.plot()可以直接把框和标签画到图上,省去了手动调OpenCV画框的代码量,但如果想自定义框的颜色和标签样式,可以基于boxes.xyxy自己用cv2.rectangle绘制。

界面里通过按钮触发图片检测的流程如下:

# ui/main_window.py 关键片段 def on_load_image(self): file_path, _ = QFileDialog.getOpenFileName(self, "选择图片", "", "图片文件 (*.jpg *.png)") if not file_path: return frame = cv2.imread(file_path) annotated, detections = self.detector.predict_frame(frame) self.display_result(annotated, detections) # 显示到QLabel上

摄像头实时检测稍微复杂一点,核心在于用QThread跑视频帧循环,避免界面卡死。每读一帧就送入检测器,检测结果更新画面,但我强烈建议做帧率控制——不是每一帧都必须检测,比如设定每两帧检测一次,其余帧用最近一次检测结果展示,实际体验会流畅非常多。

4.3 界面布局与交互细节

界面布局我选用左右结构:左侧占主要宽度,是检测画面显示区,支持缩放适应窗口;右侧是控制区和信息区。控制区放三个模式切换按钮(图片检测/视频检测/摄像头检测)、置信度滑块、打开文件按钮;信息区放检测结果表格,按行显示类别、置信度、坐标,表格下方有汇总的“当前画面目标总数”和一个导出按钮。

有一个交互细节容易被忽略:摄像头检测模式下,用户往往希望程序能截图保存当前检测结果。这个功能实现很简单——把当前帧的标注图用cv2.imwrite写一份,配上时间戳文件名,加一个按钮就行。别小看这个功能,在样板展示和现场调试时非常常用。

导出结果方面,图片模式直接保存标注图,视频模式则是把逐帧标注图合并写为一个新视频,需要用cv2.VideoWriter,注意保持帧率和分辨率一致,否则导出的视频会出问题。

5. 常见问题与排查技巧实录

5.1 训练阶段典型问题速查

现象可能原因排查思路
loss不降或降得很慢学习率过大/过小、标注质量差观察训练前几十轮loss曲线,超参回退默认值,抽样检查标注框是否贴合
mAP高但recall低类别不平衡、难样本未覆盖单独查看每个类别的recall,针对性补充样本
训练到一半显存溢出batch过大、图片尺寸过大降低batch、降imgsz,或开启梯度累积
验证集指标与测试集差异大数据划分泄漏、场景单一检查train/val是否来自同批次拍图,重新划分场景独立的test集

训练阶段最常见也是我最想强调的问题:不要盲目堆epoch。很多人认为训练轮数越多模型越好,实际上在YOLOv10这种预训练模型微调场景里,150-200轮之后模型很可能过拟合训练集,导致验证集mAP下滑。观察验证集loss曲线,它如果开始反弹,就应该停了。

5.2 推理阶段常见问题速查

现象可能原因排查思路
检测框正确但类别错类别定义边界模糊、材质相似样本不足增加相似物对照样本,检查标注class_id是否错位
反光塑料漏检高光区域特征丢失、置信度过高降低conf_thres,加入亮度扰动增强样本
重叠目标框黏连NMS-free模型在密集场景有固有特点提高iou_thres,或用m尺寸模型提升特征表达
摄像头画面卡顿推理耗时大于帧间隔跳帧检测、减小输入分辨率、换GPU推理

反光漏检是塑料识别场景里最典型的问题。塑料表面光滑,在强光下会产生大片高光,严重时瓶子整个区域都是白色反光,特征完全丢失。我处理的方法是在训练集里专门加了一组“反光覆盖”样本,拍摄时用台灯直射塑料表面制造高光;同时在推理时给画面做一次轻微的Gamma调整,压低高光区域的过曝。双管齐下,漏检率能明显下降。

5.3 环境与打包常见问题速查

环境层面,最常遇到的是CUDA版本和PyTorch版本不匹配导致GPU用不上。检查方法很直接:跑python -c "import torch; print(torch.cuda.is_available())",如果输出False,说明PyTorch的CUDA版本和驱动对不上,按官方推荐的匹配版本重装即可。

打包成独立可执行文件时,PyInstaller是常见选择。需要注意两点:一是ultralytics和PySide6体积大,打包时用--exclude-module排除不需要的模块,二是模型权重文件要作为数据文件随程序打包,不然启动时会找不到模型路径。我打包时用的是:

pyinstaller --noconfirm --onefile --windowed \ --add-data "weights/yolov10s_plastic.pt:weights" \ --add-data "dataset/data.yaml:dataset" \ ui/main.py

打包后的exe体积可能在150MB以上,这是正常现象,不要试图用各种压缩手段去硬砍体积,框架和模型文件本身就占这么多。

6. 部署扩展与二次开发方向

6.1 模型轻量化与加速

系统跑通之后,如果想进一步提高性能或者部署到更低配置的设备,有两个主要方向。

一个是模型导出格式的转换。ultralytics可以一行代码导出ONNX格式,然后可以通过ONNXRuntime进行推理,比PyTorch原生推理快不少,还能脱离PyTorch环境部署:

from ultralytics import YOLO model = YOLO("./weights/yolov10s_plastic.pt") model.export(format="onnx", imgsz=640)

导出后可以用onnxruntime加载推理,代码改动量不大,但在CPU上的推理速度有明显提升。如果目标是边缘设备(如树莓派、Jetson系列),可以继续转成TensorRT或OpenVINO格式,把模型的性能和兼容性进一步优化。

另一个是模型尺寸的调整。如果发现s尺寸精度不满足要求,直接换m或者l重新训练,数据加载和训练代码完全不用改;如果对速度极度敏感,用n尺寸模型搭配ONNXRuntime,实时性会更好。这套架构的可替换性是我当初选择ultralytics框架的重要原因——换模型档位只是改一行代码的事。

6.2 业务逻辑扩展思路

作为可回收塑料识别系统的基础版,当前版本完成了“识别-检测-展示”的核心闭环。再进一步扩展时,可以考虑的方向包括:分类统计报表,把每帧检测结果累计到Excel或数据库,生成一段时间内的塑料类别占比报告;流水线分拣对接,把检测坐标输出给PLC或者机械臂控制模块,实现自动分拣;远程上报,通过API把检测数据推送到云端管理平台,适合园区级部署。

我实际做扩展时,最先加的是统计报表功能。原理很简单:每次检测完累计一个字典,按类别计数,在程序关闭时用openpyxl写入Excel表,再附带一个柱状图。这个功能对于客户演示和实际使用中的管理层报告价值很大,而实现成本却很可控——只需要在Detector类里加一个累加方法,在界面关闭事件里触发导出。

6.3 代码组织规范建议

项目文件多了以后,代码规范比功能本身更要紧。我给几个亲测有效的建议:第一,检测类必须提供统一的输入输出结构,不管输入是图片路径、numpy数组还是视频帧,输出统一成(标注图, 检测列表),这样界面层永远不需要关心检测内部逻辑;第二,训练和推理的配置尽量用.yaml文件维护,不要散落到各脚本的魔法变量里;第三,数据、权重这类大文件不进版本管理,但requirements.txt和训练参数记录必须提交,保证任何一个人拿到源码都能重跑实验。

7. 一点经验体会

整套系统从零搭到跑通,我最有感触的一点是数据集的重要性远超想象。最初为了快速出效果,我用网上找的混杂物图片训练了一个版本,跑出来的指标还行,但一放到真实摄像头面前就露馅——场景一换,反光一变,mAP跌得厉害。后来老老实实自己拍、自己标,把各类别在真实摆放场景下的样本补足,模型的稳定性才真正上了一个台阶。

另外,如果你是这个领域的新手,我建议不要一开始就在界面设计上花太多时间。先把模型跑通,用ultralytics自带的CLI建一个图片目录做测试,确认检测效果基本满足要求,再开始写界面。否则界面写了半天,模型却因为数据问题迟迟没有进展,很容易消磨信心。

这个项目的扩展空间是相当大的。环保和回收行业目前对自动化识别有实打实的需求,而在技术侧,模型框架、数据管线、界面交互都已经沉淀成了可以复用的模板。把这套流程跑通一次,后面换任何检测对象,比如纸类、玻璃、金属的分类识别,都只是换数据集和重新微调的事。希望这篇文章能帮你把这条路走顺。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询