简介:这是一份面向计算机、人工智能相关专业学生及课程学习者的智能垃圾分类系统项目资料,可作为毕业设计或课程作业的完整参考。项目围绕计算机视觉、机器学习与大数据分析展开,涵盖图像预处理、特征提取、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 PyQt5==5.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 tensorflow==2.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 文件,需要先转成 Python:
pyuic5 kid_ui.ui -o kid_ui.pypyuic5 是 PyQt5 自带的工具,装完 PyQt5 就有。转出来的 kid_ui.py 里是一个 Ui_MainWindow 类,里面定义了所有控件。然后你需要写一个入口脚本,继承 QMainWindow 并调用 setupUi:
from 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(), aspectRatioMode=1 # Qt.KeepAspectRatio ) self.ui.label.setPixmap(scaled)逻辑说明:getOpenFileName 返回一个元组,第一个元素是文件路径,第二个是过滤器。aspectRatioMode=1 对应 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, axis=0) return img逻辑说明:cv2.imread 默认读成 BGR,模型通常用 RGB,所以转一下;resize 到模型输入尺寸;归一化到 0-1;expand_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( rescale=1./255, rotation_range=20, width_shift_range=0.1, height_shift_range=0.1, horizontal_flip=True, validation_split=0.2 ) train_generator = train_datagen.flow_from_directory( 'dataset', target_size=(224, 224), batch_size=32, class_mode='categorical', subset='training' ) val_generator = train_datagen.flow_from_directory( 'dataset', target_size=(224, 224), batch_size=32, class_mode='categorical', subset='validation' )逻辑说明:rescale 把像素归一化;rotation_range 等做数据增强,防止过拟合;validation_split 自动切分训练集和验证集。参数说明:batch_size 根据显存调,CPU 训练建议 16 或 32;class_mode='categorical' 对应多分类 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_top=False, weights='imagenet' ) base_model.trainable = False model = models.Sequential([ base_model, layers.GlobalAveragePooling2D(), layers.Dense(128, activation='relu'), layers.Dropout(0.5), layers.Dense(6, activation='softmax') ]) model.compile( optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'] )逻辑说明:include_top=False 去掉 ImageNet 的 1000 类分类头;trainable=False 冻结卷积基;后面接全局平均池化、全连接和 dropout;最后输出 6 类 softmax。参数说明:Dense(6) 对应六个类别,如果你合并了类别要改这个数字;Dropout(0.5) 是常用正则化强度,数据少可以加到 0.6。
训练时用 ModelCheckpoint 保存最佳权重:
from tensorflow.keras.callbacks import ModelCheckpoint checkpoint = ModelCheckpoint( 'best_model.h5', monitor='val_accuracy', save_best_only=True, mode='max' ) history = model.fit( train_generator, epochs=20, validation_data=val_generator, callbacks=[checkpoint] )逻辑说明:save_best_only=True 只保留验证集准确率最高的那一轮,避免最后几轮过拟合。参数说明: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 PyQt5==5.15.9 PyQt5-sip==12.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)或者没做推理优化。毕设场景通常用 CPU,MobileNet 或 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, verbose=0)) y_true.append(idx) y_pred.append(pred) print(confusion_matrix(y_true, y_pred)) print(classification_report(y_true, y_pred, target_names=class_names))逻辑说明:按类别文件夹遍历,真实标签就是文件夹索引,预测标签来自模型。confusion_matrix 能看出哪两类容易混,比如 paper 和 cardboard 经常分错。参数说明:verbose=0 关闭进度条,批量测试时更干净。如果某类样本太少,classification_report 的 recall 会很低,需要考虑补数据或调类别权重。
从那以后我每次拿到这种毕设压缩包,都强制先跑一遍 test 脚本,再动界面。因为界面报错往往只是表象,底层模型或数据路径的问题才是根子。希望帮到你。
本文还有配套的精品资源,点击获取