智能垃圾分类毕设资源拆解:PyQt5界面与深度学习模型实战
简介这是一份面向计算机、人工智能相关专业学生及课程学习者的智能垃圾分类系统项目资料可作为毕业设计或课程作业的完整参考。项目围绕计算机视觉、机器学习与大数据分析展开涵盖图像预处理、特征提取、CNN分类模型训练及数据平台构建等环节帮助读者理解AI技术在环保场景中的落地思路。压缩包共20个文件约35.12MB以Python源码为主另含多个数据集压缩包、UI界面文件、C测试文件及说明文档目录结构清晰便于按模块查阅。目前已有121人学习。资料中包含系统设计文档、算法实现代码、训练数据集与测试报告等读者可据此复现分类流程、研究模型调优与特征工程细节并借鉴界面设计与项目组织方式巩固理论并提升工程实践能力。1. 从一堆散装文件到能跑的智能垃圾分类系统这份毕设资源到底值不值得拆如果你正在找一份能直接跑起来、结构还算清晰的智能垃圾分类毕设或课程作业参考这个压缩包大概率能让你少熬两个通宵。它不是一个封装好的 exe 或者在线 demo而是一套完整的工程文件UI 设计稿kid_ui.ui、a.ui、Python 主逻辑classify.py、garbage.py、main_ui.py、ui.py、garbage_ui.py、测试脚本test-1.py、test-4.py、C 测试文件test.cpp以及按类别切分的图片数据集cardboard.zip、glass.zip、paper.zip、trash.zip、meat.zip、plastic.zip。从文件命名和结构看这是一个典型的“界面 分类模型 数据集”三件套适合用来理解智能垃圾分类系统从图像输入到类别输出的完整链路。它解决的核心问题是让你不用从零标注数据、不用从零搭界面直接在一个可运行的骨架上改模型、换数据集、调界面。适合谁正在做计算机视觉或人工智能方向毕设的本科生、需要交课程大作业的研究生以及想快速验证垃圾分类模型效果的一线开发者。但注意它不是一个开箱即用的产品更像一个半成品工作台——你得自己补环境、理依赖、调路径才能看到分类结果。2. 拆包先看结构UI 文件、Python 脚本和数据集怎么对上号2.1 三类文件的分工与调用关系拿到压缩包后别急着 pip install。先花十分钟把文件按角色分堆能省掉后面一半的报错。从文件清单看这套资源大致分三层第一层是界面层。kid_ui.ui 和 a.ui 是 Qt Designer 生成的 XML 布局文件描述控件位置、大小和信号槽。garbage_ui.py、main_ui.py、ui.py 则是这些 .ui 文件转成 Python 后的代码或者手写的界面逻辑。kid_ui.ui 对应的界面截图是 界面.jpg你可以先打开这张图对系统长什么样有个预期——通常是上传图片、显示预览、点击分类、输出类别这几个区域。第二层是业务逻辑层。classify.py 和 garbage.py 是核心。classify.py 大概率封装了模型加载和推理函数garbage.py 可能负责类别映射、结果后处理或数据库记录。test-1.py 和 test-4.py 是测试入口用来单独验证分类函数是否正常不依赖界面。第三层是数据层。cardboard.zip、glass.zip、paper.zip、trash.zip、meat.zip、plastic.zip 是六个类别的图片压缩包。注意这里出现了 meat肉类这个类别和常见的可回收/有害/厨余/其他四分类不完全一致说明这套数据集可能是按更细的物理材质分的。每个 zip 解压后应该是一堆图片文件文件名可能带标签或只是序号。调用关系上常见做法是main_ui.py 启动主窗口加载 ui.py 里的界面类用户点击按钮后信号触发 classify.py 里的推理函数推理函数读取模型文件资源里没明确列出 .h5 或 .pth可能在 Graduation Design 文件夹里对图片做预处理输出类别garbage.py 把类别转成中文或业务字段回显到界面。提示先确认 Graduation Design 文件夹里有没有模型权重文件。如果没有你需要自己训练一个或者找预训练模型替换。2.2 环境依赖的排查顺序这套代码大概率是 Python 3 PyQt5 OpenCV 深度学习框架TensorFlow 或 PyTorch的组合。但资源里没有 requirements.txt所以你得手动补。我一般按这个顺序排查第一步看 import。打开 classify.py 和 main_ui.py把前 20 行的 import 语句抄下来。常见的会有import sys import cv2 import numpy as np from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5.QtGui import QPixmap, QImage from tensorflow.keras.models import load_model如果看到 tensorflow.keras说明是 TF 2.x如果看到 torch就是 PyTorch。两者装法不同别混装。第二步装 PyQt5。这是界面能跑起来的前提。命令很简单pip install PyQt55.15.9版本别太新5.15.x 对老代码兼容性最好。装完后用 python -c from PyQt5.QtWidgets import QApplication; print(ok) 验证。第三步装 OpenCV 和数值库pip install opencv-python numpy pillowOpenCV 用来读图、缩放、转颜色空间Pillow 有时用于界面显示。第四步装深度学习框架。如果代码里是 tensorflow.keras就pip install tensorflow2.10.0选 2.10 是因为它同时支持 CPU 和 GPU且对 Keras 接口稳定。如果是 torch就pip install torch torchvision具体版本看你的 CUDA 版本没有 GPU 就用 CPU 版。第五步跑 test-1.py 或 test-4.py。这两个脚本通常不依赖界面能直接暴露模型加载和推理的问题。如果报“No module named ‘tensorflow’”说明框架没装对如果报“Invalid model file”说明模型路径不对或文件缺失。2.3 数据集解压与路径对齐六个 zip 包解压后建议统一放到一个 dataset 目录下按类别建子文件夹mkdir -p dataset/cardboard dataset/glass dataset/paper dataset/trash dataset/meat dataset/plastic unzip cardboard.zip -d dataset/cardboard unzip glass.zip -d dataset/glass unzip paper.zip -d dataset/paper unzip trash.zip -d dataset/trash unzip meat.zip -d dataset/meat unzip plastic.zip -d dataset/plastic这样做的目的是让后续训练脚本可以用 ImageDataGenerator 或 Dataset API 直接按文件夹读标签。如果你只是跑推理那只需要确认 classify.py 里读图的路径和实际解压路径一致。常见坑是代码里写死了 “./cardboard/xxx.jpg”但你解压到了 “./dataset/cardboard/”那就得改代码或建软链接。参数说明unzip 的 -d 指定解压目录如果目录不存在会自动创建。注意 zip 包内可能还有一层同名文件夹解压后变成 dataset/cardboard/cardboard/xxx.jpg这时候要么把内层文件移出来要么改代码路径。3. 把界面跑起来PyQt5 信号槽与分类函数的对接3.1 从 .ui 文件到可执行窗口资源里有 kid_ui.ui 和 a.ui 两个界面文件还有对应的 .py。如果你拿到的是 .ui 文件需要先转成 Pythonpyuic5 kid_ui.ui -o kid_ui.pypyuic5 是 PyQt5 自带的工具装完 PyQt5 就有。转出来的 kid_ui.py 里是一个 Ui_MainWindow 类里面定义了所有控件。然后你需要写一个入口脚本继承 QMainWindow 并调用 setupUifrom PyQt5.QtWidgets import QApplication, QMainWindow from kid_ui import Ui_MainWindow import sys class MainWindow(QMainWindow): def __init__(self): super().__init__() self.ui Ui_MainWindow() self.ui.setupUi(self) # 绑定按钮点击事件 self.ui.pushButton.clicked.connect(self.on_classify) def on_classify(self): # 这里调用 classify.py 里的推理函数 pass if __name__ __main__: app QApplication(sys.argv) window MainWindow() window.show() sys.exit(app.exec_())逻辑说明setupUi 负责把 .ui 里定义的控件挂到窗口上clicked.connect 把按钮点击信号连到你的槽函数on_classify 里再去调分类逻辑。参数说明sys.argv 传给 QApplication 是为了支持命令行参数sys.exit(app.exec_()) 保证窗口关闭时进程正常退出。如果资源里已经提供了 main_ui.py 或 ui.py那大概率已经做了这一步你直接运行 python main_ui.py 就行。但要注意有些老代码用 from PyQt5 import QtWidgets 而不是 from PyQt5.QtWidgets import QApplication两种写法都对但混用会报 ImportError。3.2 图片上传与预览的完整链路智能垃圾分类系统的交互起点是用户选一张图片。常见做法是用 QFileDialog 打开文件选择框拿到路径后用 QPixmap 显示到 QLabel 上。代码片段from PyQt5.QtWidgets import QFileDialog from PyQt5.QtGui import QPixmap def on_open_image(self): file_path, _ QFileDialog.getOpenFileName( self, 选择图片, , Images (*.png *.jpg *.jpeg) ) if file_path: self.current_image_path file_path pixmap QPixmap(file_path) # 缩放到 label 大小保持比例 scaled pixmap.scaled( self.ui.label.width(), self.ui.label.height(), aspectRatioMode1 # Qt.KeepAspectRatio ) self.ui.label.setPixmap(scaled)逻辑说明getOpenFileName 返回一个元组第一个元素是文件路径第二个是过滤器。aspectRatioMode1 对应 Qt.KeepAspectRatio防止图片被拉伸变形。参数说明label.width() 和 label.height() 是当前控件尺寸如果界面还没显示可能拿到默认值建议在 show() 之后再调或者用固定尺寸。拿到图片路径后分类函数需要读图并做预处理。常见做法是import cv2 import numpy as np def preprocess(image_path, target_size(224, 224)): img cv2.imread(image_path) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img cv2.resize(img, target_size) img img.astype(np.float32) / 255.0 img np.expand_dims(img, axis0) return img逻辑说明cv2.imread 默认读成 BGR模型通常用 RGB所以转一下resize 到模型输入尺寸归一化到 0-1expand_dims 增加 batch 维度。参数说明target_size 要和训练模型时一致常见是 224x224 或 299x299。如果模型是 PyTorch还需要 transpose 成 (C, H, W) 并转 tensor。3.3 分类结果回显与置信度展示推理完成后界面需要显示类别和置信度。假设 classify.py 返回的是类别索引和概率数组def on_classify(self): if not hasattr(self, current_image_path): return img preprocess(self.current_image_path) preds model.predict(img) class_idx np.argmax(preds[0]) confidence preds[0][class_idx] class_names [cardboard, glass, paper, trash, meat, plastic] result_text f类别{class_names[class_idx]} 置信度{confidence:.2%} self.ui.result_label.setText(result_text)逻辑说明argmax 取概率最大的索引class_names 要和训练时的类别顺序一致。置信度用百分比显示更直观。参数说明如果模型输出是 logits 而不是 softmax 概率需要先加一层 softmax。如果类别顺序和数据集文件夹字母序不一致结果会全错这是血泪经验——一定要打印 class_indices 确认。注意有些代码用 model.predict_classes这个函数在新版 TF 里被移除了换成 np.argmax(model.predict(x), axis-1)。4. 模型训练与替换用自带数据集跑一个基线4.1 数据增强与生成器配置如果你没有预训练模型或者想用自己的数据重训可以用 Keras 的 ImageDataGenerator 快速搭一个基线。代码from tensorflow.keras.preprocessing.image import ImageDataGenerator train_datagen ImageDataGenerator( rescale1./255, rotation_range20, width_shift_range0.1, height_shift_range0.1, horizontal_flipTrue, validation_split0.2 ) train_generator train_datagen.flow_from_directory( dataset, target_size(224, 224), batch_size32, class_modecategorical, subsettraining ) val_generator train_datagen.flow_from_directory( dataset, target_size(224, 224), batch_size32, class_modecategorical, subsetvalidation )逻辑说明rescale 把像素归一化rotation_range 等做数据增强防止过拟合validation_split 自动切分训练集和验证集。参数说明batch_size 根据显存调CPU 训练建议 16 或 32class_modecategorical 对应多分类 one-hot 标签。flow_from_directory 会按文件夹名自动生成类别索引打印 train_generator.class_indices 可以看到映射关系。4.2 迁移学习用 MobileNetV2 做特征提取从零训练一个小数据集容易过拟合常见做法是拿预训练模型做迁移学习。以 MobileNetV2 为例from tensorflow.keras.applications import MobileNetV2 from tensorflow.keras import layers, models base_model MobileNetV2( input_shape(224, 224, 3), include_topFalse, weightsimagenet ) base_model.trainable False model models.Sequential([ base_model, layers.GlobalAveragePooling2D(), layers.Dense(128, activationrelu), layers.Dropout(0.5), layers.Dense(6, activationsoftmax) ]) model.compile( optimizeradam, losscategorical_crossentropy, metrics[accuracy] )逻辑说明include_topFalse 去掉 ImageNet 的 1000 类分类头trainableFalse 冻结卷积基后面接全局平均池化、全连接和 dropout最后输出 6 类 softmax。参数说明Dense(6) 对应六个类别如果你合并了类别要改这个数字Dropout(0.5) 是常用正则化强度数据少可以加到 0.6。训练时用 ModelCheckpoint 保存最佳权重from tensorflow.keras.callbacks import ModelCheckpoint checkpoint ModelCheckpoint( best_model.h5, monitorval_accuracy, save_best_onlyTrue, modemax ) history model.fit( train_generator, epochs20, validation_dataval_generator, callbacks[checkpoint] )逻辑说明save_best_onlyTrue 只保留验证集准确率最高的那一轮避免最后几轮过拟合。参数说明epochs 根据数据量调一般 15-30 轮能看到收敛如果 val_accuracy 波动大把 batch_size 调小或加更多增强。4.3 替换模型后如何对接原界面训练完得到 best_model.h5 后把 classify.py 里的模型加载路径改掉from tensorflow.keras.models import load_model model load_model(best_model.h5)如果原代码用的是 PyTorch那就把 torch.load 的路径改掉并确保模型结构定义一致。常见坑是训练时用了 6 类但界面里的 class_names 还是旧的 4 类导致索引越界或显示错误。改完模型后一定要跑一遍 test-1.py用几张测试图验证输出。提示如果原代码把模型路径写死在多个文件里用 grep -r model_path . 搜一下统一改。5. 避坑与排查路径、版本、编码和性能的五个翻车现场5.1 现象运行 main_ui.py 报 “No module named ‘PyQt5.sip’”原因PyQt5 安装不完整或者和 PyQt5-sip 版本不匹配。常见于用 pip 装了一半中断或者 Python 环境里混了 conda 装的 PyQt。解决先卸载再重装pip uninstall PyQt5 PyQt5-sip PyQt5-Qt5 pip install PyQt55.15.9 PyQt5-sip12.11.0如果还不行检查 Python 版本3.11 以上对老 PyQt5 兼容性差建议用 3.8 或 3.9。5.2 现象分类结果永远是同一个类别原因图片预处理和训练时不一致。比如训练用了 RGB 和 0-1 归一化推理时用了 BGR 和 0-255或者模型输入尺寸不对resize 后图像内容全乱。解决把训练时的预处理代码复制到推理函数里逐行对比。打印 img.shape 和 img.max()确认范围。如果是 PyTorch 模型检查是否漏了 torchvision.transforms.Normalize。5.3 现象界面能显示但点击按钮没反应原因信号槽没连上或者槽函数被异常吞掉了。常见于 .ui 文件里按钮的 objectName 和代码里写的不一致。解决在 setupUi 之后打印 self.ui.pushButton.objectName()确认名字。然后在槽函数第一行加 print(clicked)看是否触发。如果触发了但没结果在推理函数里加 try-except 把异常打出来。5.4 现象数据集解压后中文文件名乱码原因zip 包在 Windows 下压缩文件名用了 GBK 编码Linux 解压默认 UTF-8。解决用 unzip -O GBK 指定编码或者用 Python 的 zipfile 模块手动解码import zipfile with zipfile.ZipFile(cardboard.zip) as z: for name in z.namelist(): correct_name name.encode(cp437).decode(gbk) z.extract(name, dataset/cardboard) # 然后重命名文件如果文件名不影响读图也可以忽略但路径里带乱码可能导致 cv2.imread 返回 None。5.5 现象CPU 推理一张图要好几秒原因模型太大如 ResNet50或者没做推理优化。毕设场景通常用 CPUMobileNet 或 SqueezeNet 更合适。解决换轻量模型或者用 ONNX Runtime 加速。如果只是演示可以把输入尺寸从 224 降到 128速度会快一倍但准确率可能掉几个点。另一个常见原因是每次点击都重新加载模型应该把 load_model 放到全局或类初始化里只加载一次。6. 进阶技巧用 test.cpp 做交叉验证与批量测试脚本资源里有一个 test.cpp这在 Python 项目里比较少见。常见做法是把它当作一个独立的 C 测试入口用来验证某些底层图像处理逻辑或者对比 OpenCV C 和 Python 的推理结果。如果你不熟悉 C可以忽略它但如果你想做交叉验证可以把它编译成一个命令行工具输入图片路径输出分类结果然后和 Python 端对比。编译命令g test.cpp -o test_garbage pkg-config --cflags --libs opencv4逻辑说明pkg-config 自动找 OpenCV 头文件和库路径。如果报找不到 opencv4改成 opencv。参数说明-o 指定输出文件名。编译成功后运行 ./test_garbage image.jpg看输出是否和 Python 一致。不一致的地方往往是颜色通道顺序或归一化系数不同。另一个实用技巧是写一个批量测试脚本遍历验证集所有图片统计混淆矩阵。代码import os import numpy as np from sklearn.metrics import confusion_matrix, classification_report def batch_test(model, test_dir, class_names): y_true, y_pred [], [] for idx, cls in enumerate(class_names): cls_dir os.path.join(test_dir, cls) for fname in os.listdir(cls_dir): path os.path.join(cls_dir, fname) img preprocess(path) pred np.argmax(model.predict(img, verbose0)) y_true.append(idx) y_pred.append(pred) print(confusion_matrix(y_true, y_pred)) print(classification_report(y_true, y_pred, target_namesclass_names))逻辑说明按类别文件夹遍历真实标签就是文件夹索引预测标签来自模型。confusion_matrix 能看出哪两类容易混比如 paper 和 cardboard 经常分错。参数说明verbose0 关闭进度条批量测试时更干净。如果某类样本太少classification_report 的 recall 会很低需要考虑补数据或调类别权重。从那以后我每次拿到这种毕设压缩包都强制先跑一遍 test 脚本再动界面。因为界面报错往往只是表象底层模型或数据路径的问题才是根子。希望帮到你。本文还有配套的精品资源点击获取