简介:这份资源是面向高校学生与深度学习入门者的垃圾识别分类课程设计完整方案,基于卷积神经网络实现图像分类,适合作为期末大作业、课程设计或自学练手项目。压缩包共43个文件,约315.77MB,包含12个Python源码文件、13张png与3张jpg图片素材、4个xml配置、3个psd设计稿,以及h5模型文件、db数据库、docx说明文档和exe安装包等,覆盖训练、界面测试、图片爬取、模型测试、再训练、登录等模块,代码注释清晰,下载即可运行。资源附有详细文档说明,曾获97分高分评价,已有235人学习。读者可从中获得完整的垃圾分类识别实现流程、可复用的CNN模型与数据集、界面交互与数据管理思路,并能在现有代码基础上进行二次开发,快速完成从环境搭建到模型部署的实践闭环。
1. 从一份能跑通的垃圾分类 CNN 课设说起
课程设计选题最怕两件事:一是题目太虚,代码全靠拼;二是跑不起来,答辩现场翻车。这份「基于深度学习卷积神经网络实现垃圾识别分类系统」的 Python 源码包,恰好卡在一个很实用的位置上——它是一套完整的、带数据集和训练好模型的垃圾分类识别系统,用 CNN 做图像分类,配套 Tkinter 图形界面,还附了手册文档。如果你正在找深度学习入门级的完整项目练手,或者需要一个能直接交差的课程设计底子,这套东西的完成度是够看的。
它解决的核心问题很具体:给定一张垃圾图片,判断它属于哪一类(可回收、厨余、有害、其他这类常见四分类),并把结果通过界面反馈出来。适合三类人:刚学完卷积神经网络原理、想找个真实项目把理论跑通的学生;需要快速搭一个图像分类 demo 的开发者;以及想拿一份带注释源码做二次开发的人。包里带了waste3_model.h5这个训练好的权重文件,意味着你不训练也能先看到效果,这对新手特别友好。
2. 拆开压缩包:文件结构和 CNN 垃圾分类的技术选型
2.1 目录里到底有什么,哪些是核心
先把包里的文件按职责分个类,不然一堆.py和杂项文件容易看花眼。核心逻辑集中在训练、推理、界面三条线上,其余是资源和配置。
| 文件/目录 | 作用 | 是否核心 |
|---|---|---|
训练.py | 模型训练主脚本,构建 CNN 并喂数据 | 核心 |
模型测试.py/测试.py | 加载.h5做推理验证 | 核心 |
界面.py/main.py | Tkinter 图形界面入口 | 核心 |
waste3_model.h5 | 训练好的模型权重 | 核心 |
再训练.py | 在已有模型上继续训练 | 进阶 |
图片爬取.py | 采集扩充数据集 | 辅助 |
垃圾分类查询.png/判断.txt | 类别说明与查询资源 | 辅助 |
手册.docx | 项目文档说明 | 参考 |
.idea/*.iml | PyCharm 工程配置 | 可忽略 |
.idea、misc.xml、modules.xml、aws.xml这些是 IDE 自动生成的工程文件,换台机器打开基本没用,别被它们干扰。真正要盯的是训练.py、界面.py、waste3_model.h5这三样,它们决定了项目能不能跑、跑出来对不对。
2.2 为什么用 CNN 而不是传统方法
垃圾分类识别本质是图像分类。传统做法靠人工设计特征——颜色直方图、边缘算子、纹理统计,再喂给 SVM 或随机森林。这条路在类别少、背景干净时能凑合,但垃圾图片的干扰太强:光照不一、拍摄角度随意、同类物体形态差异大。手工特征很难覆盖这些变化,泛化能力差是硬伤。
卷积神经网络的优势在于它把特征提取也交给网络自己学。卷积层用局部感受野抓边缘和纹理,池化层做下采样保留主要信息,堆叠几层后高层特征就能表达「这是塑料瓶」这种语义。对垃圾分类这种类内差异大、类间又有相似性的任务,CNN 的端到端学习明显更稳。这也是为什么现在做图像分类,CNN 基本是默认起点,而不是可选项。
2.3 环境准备:Python 与依赖怎么装
项目是纯 Python 技术栈,跑之前先把环境理顺。常见做法是建一个独立虚拟环境,避免和系统里的包打架。
# 创建并激活虚拟环境(Windows 用 venv\Scripts\activate) python -m venv venv source venv/bin/activate # 安装核心依赖,版本按你本地 Python 适配 pip install tensorflow==2.10.0 pip install numpy pillow matplotlib pip install opencv-python这里tensorflow是训练和加载.h5模型的关键,pillow负责图片读取和预处理,opencv-python在部分图像处理脚本里会用到。版本上有个坑:.h5是 Keras 旧格式,TensorFlow 2.10 之后对它的原生支持在收紧,如果你装的是 2.16 以上,加载模型可能报错。稳妥起见先用 2.10 到 2.13 之间的版本。装完用python -c "import tensorflow as tf; print(tf.__version__)"确认一下,能打印版本号就说明环境通了。
提示:如果
pip install tensorflow卡在下载,换国内镜像源,例如-i https://pypi.tuna.tsinghua.edu.cn/simple,能省不少等待时间。
3. 训练脚本怎么读:CNN 结构、数据管道与参数含义
3.1 数据组织与预处理
CNN 训练的第一步是把图片整理成网络能吃的格式。这类项目通常按类别分文件夹存放,每个子文件夹名就是类别标签。数据管道一般用ImageDataGenerator或tf.data来批量读取、归一化、做数据增强。
import tensorflow as tf from tensorflow.keras.preprocessing.image import ImageDataGenerator # 图片统一缩放到 224x224,batch 设为 32 IMG_SIZE = (224, 224) BATCH_SIZE = 32 # 训练集做增强,验证集只做归一化 train_datagen = ImageDataGenerator( rescale=1./255, # 像素值归一到 0~1 rotation_range=20, # 随机旋转 ±20 度 width_shift_range=0.1, # 水平平移 height_shift_range=0.1, # 垂直平移 horizontal_flip=True # 水平翻转 ) val_datagen = ImageDataGenerator(rescale=1./255) train_gen = train_datagen.flow_from_directory( 'dataset/train', target_size=IMG_SIZE, batch_size=BATCH_SIZE, class_mode='categorical' ) val_gen = val_datagen.flow_from_directory( 'dataset/val', target_size=IMG_SIZE, batch_size=BATCH_SIZE, class_mode='categorical' )rescale=1./255把 0 到 255 的像素压到 0 到 1,这是让网络更容易收敛的常规操作。增强参数(旋转、平移、翻转)是为了在数据量有限时人为扩充样本多样性,降低过拟合。class_mode='categorical'表示多分类,标签会转成 one-hot 向量。target_size必须和后面网络输入层一致,否则会报维度不匹配。
3.2 卷积网络结构逐层拆解
一个能打的垃圾分类 CNN,结构上通常是「卷积—池化」堆叠几组,再接全连接分类头。下面是一个典型写法,和这类课设项目的思路一致。
from tensorflow.keras import layers, models model = models.Sequential([ # 第一组:抓边缘和颜色 layers.Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3)), layers.MaxPooling2D((2, 2)), # 第二组:抓纹理和局部形状 layers.Conv2D(64, (3, 3), activation='relu'), layers.MaxPooling2D((2, 2)), # 第三组:抓更高层语义 layers.Conv2D(128, (3, 3), activation='relu'), layers.MaxPooling2D((2, 2)), layers.Flatten(), # 展平成一维 layers.Dense(128, activation='relu'), layers.Dropout(0.5), # 随机丢弃,抑制过拟合 layers.Dense(4, activation='softmax') # 4 分类输出概率 ]) model.compile( optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'] )Conv2D的第一个参数是卷积核数量,从 32 到 64 再到 128 逐层翻倍,是为了让网络在浅层抓细节、深层抓语义。(3, 3)是卷积核尺寸,3×3 是最常用的平衡选择。MaxPooling2D((2, 2))每次把特征图长宽减半,减少计算量同时保留显著特征。Flatten把三维特征拉平送进全连接层。Dropout(0.5)在训练时随机屏蔽一半神经元,是防过拟合的常用手段。最后一层Dense(4, softmax)输出四个类别的概率,数字 4 要和你实际类别数对齐——类别变了这里必须改。
3.3 训练、保存与关键参数
结构定好后就是喂数据训练,并把权重存成.h5。
history = model.fit( train_gen, epochs=20, # 训练轮数 validation_data=val_gen, verbose=1 ) model.save('waste3_model.h5') # 保存模型,供界面调用epochs是训练轮数,太小欠拟合、太大过拟合,20 轮是个常见起点,实际看验证集准确率是否还在涨。validation_data每轮结束后在验证集上评估,方便你判断有没有过拟合。model.save存的是结构和权重,界面脚本加载它就能直接推理。如果训练时准确率一直上不去,先别急着加轮数,回头查数据标注有没有错、类别是否均衡。
4. 界面与推理:把模型接进 Tkinter 并跑通识别
4.1 加载模型做单张图片推理
界面背后干的事,是把用户选的图片预处理成模型要的格式,再喂进去拿结果。
import numpy as np from tensorflow.keras.models import load_model from tensorflow.keras.preprocessing import image model = load_model('waste3_model.h5') class_names = ['可回收', '厨余', '有害', '其他'] # 顺序要和训练时一致 def predict(img_path): img = image.load_img(img_path, target_size=(224, 224)) arr = image.img_to_array(img) / 255.0 # 归一化 arr = np.expand_dims(arr, axis=0) # 加 batch 维度 preds = model.predict(arr) idx = np.argmax(preds) # 取概率最大的类别 return class_names[idx], float(preds[0][idx])load_img的target_size必须和训练时一致,否则输入维度对不上。img_to_array转成数组后除以 255 做归一化,这一步漏了会导致预测结果完全乱掉。np.expand_dims是给单张图补一个 batch 维度,因为模型predict期望的是(batch, h, w, c)。np.argmax取最大概率的下标,再映射回类别名。class_names的顺序必须和训练时flow_from_directory的类别顺序一致,这个顺序是按文件夹名字母序排的,搞错了结果就会张冠李戴。
4.2 Tkinter 界面骨架
界面部分负责选图、显示、调推理函数、回显结果。核心是按钮绑定事件。
import tkinter as tk from tkinter import filedialog from PIL import Image, ImageTk root = tk.Tk() root.title("垃圾分类识别系统") root.geometry("500x600") def choose_and_predict(): path = filedialog.askopenfilename( filetypes=[("图片", "*.jpg *.png *.jpeg")] ) if not path: return img = Image.open(path).resize((300, 300)) photo = ImageTk.PhotoImage(img) img_label.config(image=photo) img_label.image = photo # 保持引用,否则图片不显示 label, conf = predict(path) result_label.config(text=f"识别结果:{label} 置信度:{conf:.2f}") btn = tk.Button(root, text="选择图片并识别", command=choose_and_predict) btn.pack(pady=10) img_label = tk.Label(root) img_label.pack() result_label = tk.Label(root, text="等待识别", font=("微软雅黑", 14)) result_label.pack(pady=20) root.mainloop()filedialog.askopenfilename弹出文件选择框,filetypes限定图片格式。ImageTk.PhotoImage把 PIL 图片转成 Tkinter 能显示的格式,这里有个经典坑:img_label.image = photo这行必须写,否则图片对象被垃圾回收,界面显示空白。command=choose_and_predict把按钮点击和推理函数绑起来。root.mainloop()启动事件循环,界面才会响应操作。
4.3 从命令行到界面:完整跑通顺序
按这个顺序走,能最快看到效果:
- 激活虚拟环境,确认 TensorFlow 能导入。
- 把
waste3_model.h5和界面脚本放同一目录。 - 运行
python 界面.py,弹出窗口。 - 点按钮选一张垃圾图片,看识别结果和置信度。
- 想验证模型本身,直接跑
python 模型测试.py,看批量测试的准确率。
如果界面能弹但识别结果离谱,八成是class_names顺序错了或归一化漏了。如果界面直接报错,先看是不是waste3_model.h5路径不对或 TensorFlow 版本不兼容。
5. 避坑与排查:那些让课设当场翻车的细节
5.1 模型加载报错,提示 unknown layer 或格式不支持
现象:运行界面或测试脚本时,load_model抛异常,说无法识别某个层或.h5格式不被支持。 原因:.h5是 Keras 旧格式,新版 TensorFlow(2.16 及以上)默认改用.keras格式,对旧格式兼容性下降;或者模型里用了自定义层,加载时没注册。 解决:把 TensorFlow 降到 2.10 到 2.13 之间,这是对.h5支持最稳的区间。如果必须用新版,用tf.keras.models.load_model('waste3_model.h5', compile=False)跳过编译信息再试。
5.2 预测结果永远是同一类
现象:不管喂什么图片,识别结果都输出同一个类别,置信度还很高。 原因:最常见是归一化没做,像素值还是 0 到 255,网络输入分布和训练时对不上;其次是class_names顺序和训练时类别顺序不一致。 解决:确认推理时做了/255.0;打印训练时train_gen.class_indices看真实类别顺序,把class_names按它调整。这两个点排查完,基本能恢复正常。
5.3 界面图片显示空白
现象:选了图片,识别结果正常,但界面上图片区域一片空白。 原因:ImageTk.PhotoImage对象是局部变量,函数执行完就被回收,Tkinter 拿不到引用。 解决:把 photo 对象挂到 label 上,写img_label.image = photo,强制保留引用。这是 Tkinter 显示图片的血泪经验,不写这行必翻车。
5.4 训练准确率高但测试拉胯
现象:训练时准确率冲到 95% 以上,换新图片测试却错得离谱。 原因:过拟合,模型把训练集背下来了;或者训练集和验证集图片来自同一批,没有真正区分。 解决:加大数据增强力度,加Dropout,减少网络参数量;确保验证集图片和训练集不重叠。判断过拟合看验证集准确率是否远低于训练集,是的话就得动手调。
5.5 中文路径或中文类别导致读取失败
现象:图片放在中文目录下,load_img报错找不到文件;或类别名是中文时显示乱码。 原因:部分图像库对非 ASCII 路径支持不好;字体没设置导致中文渲染异常。 解决:图片路径尽量用英文;界面里设置中文字体,如font=("微软雅黑", 14),避免默认字体显示方块。
6. 二次开发与验证:换类别、扩数据、量化评估
拿到能跑的版本只是起点,真正拉开差距的是你能不能改得动、验得准。这套源码留了足够的接口给你折腾。
先说换类别。假设你想从四分类改成更细的六分类,改动集中在三处:数据集按新类别建文件夹、训练脚本最后一层Dense的输出数改成 6、推理脚本的class_names同步更新。改完重新跑训练.py,生成新的.h5覆盖旧的即可。这里有个容易忽略的点:类别数变了,categorical_crossentropy不用改,但标签必须是 one-hot,flow_from_directory会自动处理,前提是文件夹结构对。
再说扩数据。包里带了图片爬取.py,思路是批量采集图片补充样本。扩充后别一股脑全塞进训练集,按 8:2 切出验证集,否则评估结果会虚高。数据量上来后,可以适当加深网络或增加epochs,但每次只改一个变量,改完看验证集指标,不然出了问题都不知道是哪一步导致的。
验证模型好坏,别只看一个准确率。混淆矩阵能告诉你哪两类最容易混——垃圾分类里「厨余」和「其他」经常互相误判,看到这个再针对性补样本,比盲目加轮数有效得多。
from sklearn.metrics import confusion_matrix, classification_report import numpy as np # 假设 y_true 是真实标签,y_pred 是模型预测 y_pred = np.argmax(model.predict(val_gen), axis=1) y_true = val_gen.classes print(confusion_matrix(y_true, y_pred)) print(classification_report(y_true, y_pred, target_names=class_names))confusion_matrix输出的是每个类别被预测成各个类别的次数,对角线是预测对的。classification_report给出每类的精确率、召回率和 F1,比单一准确率更能暴露问题。如果某一类召回率特别低,说明模型对这类学得不好,优先补这类样本。
我自己的习惯是:每次改完模型或数据,先跑一遍混淆矩阵,确认没有类别被系统性误判,再去看整体准确率。从那以后我每次动训练脚本,都强制先在小批量数据上跑通再上全量,省得等半天发现参数写错。这套垃圾分类课设的底子不错,改起来不费劲,希望帮到你。
本文还有配套的精品资源,点击获取