一、前言

🎯 做毕设的你是不是也遇到过这些问题?

临近毕业,做计算机毕设的你一定深有体会:

  • 环境配置困难:PyTorch、CUDA、各种依赖包版本不匹配,配置一次崩溃一次
  • 代码看不懂:GitHub上的代码没有注释,拿到手一脸懵逼
  • 模型训练时间长:没有GPU,训练一个模型要等几天几夜
  • 界面太简陋:写出来的程序黑乎乎的,导师看了直摇头
  • 数据集难找:网上的数据集要么不完整,要么格式不对

✨ 本项目完美解决你的所有痛点!

今天给大家分享一个基于MobileNet深度学习模型的花卉识别系统,这个项目专门为大学生毕业设计初学者实战学习打造:

  • 纯Python开发,代码规范,注释详细,小白也能看懂
  • 一键运行,无需复杂配置,训练好的权重直接可用
  • 精美UI界面,基于PyQt5开发,界面美观,功能完整
  • 15740张数据集,包含16种常见花卉,训练/验证/测试集已划分好
  • 完整源码,从数据处理到模型训练再到界面开发,全流程覆盖
  • 即拿即用,训练好的模型权重已包含,直接运行即可体验

二、系统演示

🖼️ 主界面展示

在这里插入图片描述

界面特点:

  • 精美的背景设计,支持图片背景和纯色背景切换
  • 实时显示当前日期和星期
  • 左侧显示识别结果和花卉相关信息介绍
  • 中间预览框实时展示识别图片
  • 右侧支持单张检测和批量检测功能
  • 底部表格展示批量检测的详细结果

🎯 识别效果展示

在这里插入图片描述

系统性能指标:

  • 📊 准确率:95%+
  • 识别速度:单张图片推理时间 < 100ms(CPU环境)
  • 🎯 支持类别:16种常见花卉(向日葵、康乃馨、玫瑰、雏菊、郁金香、睡莲、木兰花、风铃草、鸢尾花、黄水仙等)
  • 💪 批量处理:支持文件夹批量识别,结果可导出为CSV文件

三、核心技术栈

🛠️ 技术选型

技术 用途说明
Python3.11 核心开发语言,简单易学
PyTorch 深度学习框架,社区成熟,文档丰富
PyQt5 图形界面开发,功能强大,界面美观
PIL/Pillow 图像处理库,加载和预处理图片
torchvision 图像变换和数据增强
matplotlib 可视化训练曲线和结果分析
MobileNet 轻量级CNN模型,速度快,精度高

📝 为什么选择这些技术?

  1. PyTorch:相比TensorFlow更易上手,动态图设计让调试更方便,适合学生和初学者
  2. PyQt5:跨平台GUI框架,界面美观,功能完整,可以做出专业级应用
  3. MobileNet:轻量级模型,在移动端和CPU环境下都能快速推理,非常适合实际应用
  4. Python:语法简洁,生态丰富,是深度学习领域的主流语言

四、项目目录结构

mobile_net_flower_02/
│
├── all_data/                    # 数据集文件夹
│   ├── train/                   # 训练集(每个类别约700-800张)
│   ├── val/                     # 验证集(每个类别约100张)
│   └── test/                    # 测试集(每个类别约100张)
│
├── models/                      # 模型定义文件夹
│   └── mobilenet.py            # MobileNet模型架构实现
│
├── weights/                     # 模型权重文件夹
│   └── flower-best-epoch.pth   # 训练好的最佳模型权重
│
├── ui/                          # 界面资源文件夹
│   ├── background.png          # 背景图片
│   ├── 图像.png                # 图像按钮图标
│   └── 文件夹.png              # 文件夹按钮图标
│
├── font/                        # 字体文件夹
│   ├── simhei.ttf              # 黑体字体
│   └── simsun.ttc              # 宋体字体
│
├── 主界面.py                    # 主程序入口(GUI界面)
├── train.py                     # 模型训练脚本
├── predict.py                   # 单张图片推理脚本
├── utils.py                     # 工具函数(数据处理、训练评估等)
├── my_dataset.py                # 自定义数据集类
├── class_indices.json           # 类别索引映射文件
│
├── confusion_matrix.py          # 混淆矩阵生成脚本
├── roc_curve.py                 # ROC曲线绘制脚本
├── dataset_show.py              # 数据集可视化脚本
│
└── 先看我-项目使用说明/         # 项目说明文档
    ├── 1-项目文件介绍.png
    └── 其他说明文档...

项目结构说明:

  • 📁 all_data/:完整数据集,已按train/val/test划分,开箱即用
  • 📁 models/:模型定义清晰,便于修改和扩展
  • 📁 weights/:包含训练好的模型权重,无需重新训练即可使用
  • 📁 ui/:界面资源完整,界面美观专业
  • 📝 主要Python文件:功能模块化,代码规范,注释详细

五、核心代码展示

🔍 代码片段1:主界面初始化与模型加载

这段代码展示了如何初始化GUI界面并加载训练好的模型:

        super(MainWindow, self).__init__(parent)  # 调用父类的初始化方法
        self.setupUi(self)  # 由 Qt Designer 生成的 UI 初始化

        # 背景设置相关变量初始化
        self.use_color_bg = False  # 默认使用图片背景
        self.bg_color = "rgb(255,181,197)"  # 默认背景颜色(粉色)
        
        # 背景图自适应:初始化背景图并按窗口大小铺满
        self._bg_pixmap = QtGui.QPixmap("ui/background.png")  # 加载背景图
        self.label_8.setScaledContents(True)  # 设置标签内容可缩放
        self.label_8.setStyleSheet("background-color: transparent;")  # 设置标签背景透明
        self._update_background()  # 更新背景图显示

        # 默认设置背景样式
        # 示例:如何在代码中切换背景
        # 使用纯色背景:
        #self.set_background(use_color=True, color="rgb(255,181,197)")  # 设置为粉色背景
        # 使用图片背景:
        self.set_background(use_color=False)  # 取消注释此行可设置为图片背景
        

        # 设置文本区域的字体大小,便于阅读
        font = QFont()  # 创建字体对象
        font.setPointSize(12)  # 设置字体大小为12点
        self.textEdit.setFont(font)  # 应用字体到文本编辑框

        # 日期与星期展示区域:在顶部显示当天日期与星期几
        # 获取当前日期并转换为字符串
        today = str(datetime.datetime.now().date())

        # 获取今天是星期几(0-6,0代表星期一,6代表星期日)
        weekday = int(datetime.datetime.now().weekday())
        # print(weekday)  # 星期几的数字表示,0代表星期一,6代表星期日
        
        # 设置日期标签,格式为:年/月/日
        self.label_13.setText(today.split('-')[0] + '/' + today.split('-')[1]+ '/' + today.split('-')[2])
        
        # 根据weekday值设置对应的星期文本
        if weekday == 0:
            self.label_14.setText('星期一')
        if weekday == 1:
            self.label_14.setText('星期二')
        if weekday == 2:
            self.label_14.setText('星期三')
        if weekday == 3:
            self.label_14.setText('星期四')
        if weekday == 4:
            self.label_14.setText('星期五')
        if weekday == 5:
            self.label_14.setText('星期六')
        if weekday == 6:
            self.label_14.setText('星期日')
        # 下方表格:用于展示检测结果(序号/路径/类别/置信度)
        # 设置表格自适应大小(根据内容自动调整)
        self.tableWidget.resizeColumnsToContents()  # 列宽自适应内容
        self.tableWidget.resizeRowsToContents()  # 行高自适应内容
        
        # 设置表格初始行列数
        self.tableWidget.setRowCount(4)  # 设置初始行数为4
        self.tableWidget.setColumnCount(4)  # 设置列数为4

        # 设置表格的拉伸模式
        self.tableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
        # 列自适应(在水平方向占满容器宽度)
        self.tableWidget.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
        # 行自适应(在垂直方向占满容器高度)

        # 行/列标题是否隐藏,这里仅隐藏列表头(即行号)
        # self.tableWidget.horizontalHeader().hide()  # 隐藏水平表头(列标题)
        self.tableWidget.verticalHeader().hide()  # 隐藏垂直表头(行号)

        # 设置表头标题
        self.tableWidget.setHorizontalHeaderLabels(['序号', '图像路径', '识别类型','置信度'])
        # 显示表格网格线
        self.tableWidget.setShowGrid(True)  # 显示表格的网格线


        # 结果显示的两个标签先置空
        self.label_res.setText('')  # 清空识别结果标签
        self.label_pro.setText('')  # 清空置信度标签

        # 占位提示:便于用户理解输入位置
        self.lineEdit_pic.setPlaceholderText('  点击选择图像')  # 设置图像输入框的提示文字
        self.lineEdit_folder.setPlaceholderText('  点击选择文件夹')  # 设置文件夹输入框的提示文字
        
        # 加载检测模型的前置环境设置
        # 解决英特尔MKL库可能的冲突问题
        os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'

        # 设置推理设备(如有 CUDA 则使用 GPU,否则使用 CPU)
        self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")  # 检测并设置计算设备
        
        # 读取类别索引文件(json),用于将预测索引映射到中文类别名
        json_path = './class_indices.json'  # 类别索引文件路径
        # 确保文件存在,否则抛出异常
        assert os.path.exists(json_path), "file: '{}' dose not exist.".format(json_path)

        # 打开并加载类别索引文件
        json_file = open(json_path, "r")
        self.class_indict = json.load(json_file)  # 加载类别索引字典
        
        # 提取类别名列表(长度即为分类数,用于构建模型输出维度)
        classes = list(self.class_indict.values())  # 获取所有类别名称

        # 创建模型网络,并将其放到指定设备
        self.model = create_model(class_num=len(classes)).to(self.device)  # 创建MobileNet模型实例
        
        # 加载训练好的权重
        model_weight_path = "weights/flower-best-epoch.pth"  # 模型权重文件路径
        # 加载模型权重到当前设备
        self.model.load_state_dict(torch.load(model_weight_path, map_location=self.device))
        self.model.eval()  # 切换到评估模式(关闭 Dropout/BN 训练行为)

代码解析:

  • 🔧 环境初始化:自动检测GPU/CPU,优先使用GPU加速推理
  • 📁 模型加载:从权重文件加载训练好的MobileNet模型
  • 🎨 界面设置:配置背景、字体、表格等UI元素
  • 📅 日期显示:自动获取并显示当前日期和星期

🔍 代码片段2:图像预处理与模型推理

这段代码展示了如何对输入图像进行预处理并进行模型推理:

    def img_detect(self):
        """对当前选择的图片进行推理,并在界面上展示结果与表格条目
        
        这个方法会对用户选择的图片进行预处理,然后使用加载的模型进行推理,
        最后将结果显示在界面上的标签和表格中
        """
        # 清空表格内容并设置为只有1行
        self.tableWidget.clearContents()
        self.tableWidget.setRowCount(1)

        # 统一的图像预处理:Resize -> CenterCrop -> ToTensor -> Normalize
        img_size = 224  # 模型输入图像大小
        data_transform = transforms.Compose(
            [transforms.Resize(int(img_size * 1.143)),  # 先将图像调整为略大尺寸
             transforms.CenterCrop(img_size),  # 中心裁剪到模型所需尺寸
             transforms.ToTensor(),  # 转换为张量
             # 使用ImageNet预训练模型的标准化参数
             transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])

        # 加载图像
        # 确保文件存在
        assert os.path.exists(self.img_path), "file: '{}' dose not exist.".format(self.img_path)
        img = Image.open(self.img_path)  # 打开图像
        # 应用预处理变换 [C, H, W] 格式
        img = data_transform(img)
        # 扩展 batch 维度:从 [C,H,W] -> [1,C,H,W],因为模型需要batch维度
        img = torch.unsqueeze(img, dim=0)

        # 调用模型进行检测
        with torch.no_grad():  # 不计算梯度,节省内存
            # 将图像送入模型进行预测
            output = torch.squeeze(self.model(img.to(self.device))).cpu()  # 将输出从[1,C]压缩为[C]并移回CPU
            predict = torch.softmax(output, dim=0)  # 应用softmax获取概率分布
            predict_cla = torch.argmax(predict).numpy()  # 获取概率最高的类别索引

        # 控制台打印各类别概率(便于调试观察)
        for i in range(len(predict)):
            # 打印每个类别的名称和对应的预测概率
            print("class: {:10}   prob: {:.3}".format(self.class_indict[str(i)],
                                                      predict[i].numpy()))
        # 获取预测结果(概率最高的类别)
        res = self.class_indict[str(list(predict.numpy()).index(max(predict.numpy())))]  # 获取最高概率对应的类别名
        num = "%.2f" % (max(predict.numpy()) * 100) + "%"  # 格式化概率为百分比字符串
        print(res, num)  # 打印最终预测结果和置信度

        # 文本说明/类别名称/置信度展示
        self.textEdit.setText(data_inf[res])  # 在文本框中显示该的详细信息
        self.label_res.setText(res)  # 在标签中显示预测的类别
        self.label_pro.setText(num)  # 在标签中显示预测的置信度

        # 将该次结果填入表格第一行
        for column, data in enumerate(['1', self.img_path, res, num]):
            # 创建表格项并设置到表格的对应位置
            self.tableWidget.setItem(0, column, QtWidgets.QTableWidgetItem(str(data)))

代码解析:

  • 🖼️ 图像预处理:Resize→CenterCrop→ToTensor→Normalize,与训练时保持一致
  • 🚀 模型推理:使用torch.no_grad()节省内存,自动选择GPU/CPU
  • 📊 结果解析:通过softmax获取概率分布,取最大概率对应的类别
  • 💻 界面更新:将识别结果和置信度实时显示在界面上

🔍 代码片段3:批量检测(异步处理,避免界面卡顿)

这段代码展示了如何实现批量检测,使用定时器避免界面卡顿:

    def start_detect_folder(self):
        """启动/停止批量检测

        - 启动时:清空并设置表格行数,构建待检测图片路径列表,初始化游标并启动定时器
        - 停止时:停止定时器并恢复按钮文案
        
        这个方法实现了批量检测按钮的切换功能,可以启动或停止批量检测过程
        """


        if self.timer_folder.isActive() == False:  # 若定时器未启动

            self.tableWidget.clearContents()
            self.tableWidget.setRowCount(len(os.listdir(self.folder)))
            self.folder_list = [self.folder + '/' + path for path in os.listdir(self.folder)]
            self.folder_num = 0

            self.timer_folder.start(30)
            self.pushButton_folder_begin.setText('停止检测')

            self.folder_res=[]

        else:
            self.timer_folder.stop()
            self.pushButton_folder_begin.setText('批量检测')


    def detect_folder_timer(self):
        """定时器回调:每次处理一张图片,避免界面卡顿
        
        这个方法是定时器的回调函数,每次触发时处理一张图片,然后更新界面。
        通过这种方式可以避免同步处理大量图片导致的界面卡顿问题。
        """


        if self.folder_num==len(self.folder_list):
            self.timer_folder.stop()
            self.pushButton_folder_begin.setText('批量检测')

        else:
            img_path=self.folder_list[self.folder_num]

            print(img_path)

            image = Image.open(img_path)
            r_image = image.resize((331, 241))
            r_image.save('test.png')
            # 将检测出的图片放到界面框中
            self.label_pic.setStyleSheet("image: url(./test.png)")
            res,pro = self.img_detect2(img_path)

            print(self.folder_num)
            self.folder_res.append([str(self.folder_num + 1), img_path, res, pro])

            for column, data in enumerate([str(self.folder_num + 1), img_path, res, pro]):
                self.tableWidget.setItem(self.folder_num, column, QtWidgets.QTableWidgetItem(str(data)))

            self.folder_num += 1

代码解析:

  • ⏱️ 定时器机制:使用QTimer实现异步处理,每30ms处理一张图片
  • 🖥️ 界面响应:避免同步处理导致的界面卡顿,用户体验流畅
  • 📋 结果存储:将每张图片的识别结果存储到列表中,支持导出CSV

六、如何使用/运行步骤

📦 环境配置

步骤1:安装Python环境

推荐使用 Python 3.8 - 3.11,可以使用Anaconda或直接安装Python。

步骤2:安装依赖包

在项目根目录下打开命令行,执行:

pip install -r requirements.txt

如果没有requirements.txt文件,可以手动安装以下依赖:

pip install torch torchvision
pip install PyQt5
pip install Pillow
pip install matplotlib
pip install tqdm
步骤3:验证环境

确保以下关键库安装成功:

import torch
import torchvision
from PyQt5 import QtWidgets
from PIL import Image

print("PyTorch版本:", torch.__version__)
print("CUDA可用:", torch.cuda.is_available())

🚀 运行项目

方式1:运行GUI界面(推荐)

直接运行主界面程序:

python 主界面.py

使用说明:

  1. 单张检测

    • 点击"选择图像"按钮,选择一张花卉图片
    • 点击"开始检测"按钮,即可看到识别结果
  2. 批量检测

    • 点击"选择文件夹"按钮,选择包含多张图片的文件夹
    • 点击"批量检测"按钮,系统会自动逐张识别
    • 识别完成后,点击"结果导出"可将结果保存为CSV文件
方式2:命令行推理

如果只想进行单张图片推理,可以使用:

python predict.py

修改predict.py文件末尾的图片路径即可。

方式3:模型训练(可选)

如果你想自己训练模型:

python train.py --data-path ./all_data/train --batch-size 32 --epochs 50

训练参数可以根据实际情况调整。


七、获取源码方式

📥 完整项目资源

由于篇幅限制,本文只展示了项目的核心功能和关键代码片段。如果你想获取:

  • 完整源代码(所有Python文件,带详细注释)
  • 训练好的模型权重(flower-best-epoch.pth)
  • 完整数据集(15740张图片,已划分train/val/test)
  • UI界面文件(.ui文件和所有资源)
  • 万字项目报告(适合毕设答辩)
  • 项目使用说明文档(图文并茂)
  • 环境配置视频教程(手把手教学)

请点击下方链接获取完整资源:

项目获取链接:https://my.feishu.cn/wiki/ZB2twF4D6iZywWkEJLjctE4enIf?from=from_copylink

#Python #深度学习 #PyTorch #花卉识别 #MobileNet #计算机视觉 #毕业设计 #PyQt5

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐