1. 项目概述
这个基于Spring Boot和深度学习的蘑菇种类识别系统,是我最近完成的一个大数据方向的毕业设计项目。作为一个在Java全栈开发领域摸爬滚打了十多年的老码农,我深知毕业设计对大学生的重要性——它不仅是学习成果的集中展示,更是进入职场的敲门砖。
这个系统最核心的功能是通过深度学习模型识别蘑菇种类,前端采用Vue.js构建用户界面,后端使用Spring Boot框架,数据库选用MySQL,整体采用B/S架构。系统不仅实现了基本的蘑菇识别功能,还包含了完整的用户管理模块,从注册登录到权限控制一应俱全。
在实际开发过程中,我遇到了不少坑,比如深度学习模型在Spring Boot中的集成问题、前后端数据交互的格式处理、以及系统性能优化等。下面,我就把这个项目的完整实现过程和技术细节分享给大家,希望能为正在做类似项目的同学提供一些参考。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术选型与整体架构
选择合适的技术栈是项目成功的关键。经过多方比较,我最终确定了以下技术方案:
后端技术栈:
- Spring Boot 2.7.x:简化配置,快速开发
- MyBatis-Plus 3.5.x:简化数据库操作
- Shiro 1.10.x:安全认证和授权
- Python Flask:深度学习模型服务
前端技术栈:
- Vue.js 3.x:构建用户界面
- Element Plus:UI组件库
- Axios:HTTP客户端
数据库:
- MySQL 8.0:关系型数据库
- Redis 6.x:缓存
深度学习框架:
- TensorFlow 2.x:模型训练和推理
- OpenCV:图像预处理
这个架构最大的特点是采用了前后端分离的设计模式,后端提供RESTful API,前端通过Axios调用这些接口。深度学习模型部分则单独部署为一个Python服务,通过HTTP与Spring Boot后端通信。
2.2 MVC架构实现
系统严格遵循MVC模式进行分层设计:
模型层(Model):
- 实体类:对应数据库表结构
- DAO接口:数据访问对象
- Service:业务逻辑处理
视图层(View):
- Vue组件:用户界面
- 路由管理:页面跳转
- 状态管理:Vuex
控制层(Controller):
- RestController:接收HTTP请求
- 参数校验:确保数据合法性
- 统一异常处理
这种分层设计使得代码结构清晰,各层职责明确,便于后期维护和扩展。特别是在处理复杂的业务逻辑时,分层架构的优势更加明显。
3. 核心功能实现
3.1 蘑菇识别功能实现
蘑菇识别是系统的核心功能,其实现过程可以分为以下几个步骤:
-
图像上传与预处理
- 前端使用Element Plus的Upload组件实现图片上传
- 后端接收图片后,使用OpenCV进行预处理:
java复制// 图片预处理示例代码 public BufferedImage preprocessImage(MultipartFile file) throws IOException { byte[] bytes = file.getBytes(); Mat image = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.IMREAD_COLOR); // 调整大小 Mat resizedImage = new Mat(); Imgproc.resize(image, resizedImage, new Size(224, 224)); // 归一化 resizedImage.convertTo(resizedImage, CvType.CV_32F, 1.0/255); // 转换为BufferedImage return matToBufferedImage(resizedImage); }
-
模型推理服务
- 使用Python Flask搭建模型服务:
python复制from flask import Flask, request, jsonify import tensorflow as tf import numpy as np import cv2 app = Flask(__name__) model = tf.keras.models.load_model('mushroom_model.h5') @app.route('/predict', methods=['POST']) def predict(): file = request.files['image'] img = cv2.imdecode(np.frombuffer(file.read(), np.uint8), cv2.IMREAD_COLOR) img = cv2.resize(img, (224, 224)) img = img.astype('float32') / 255.0 img = np.expand_dims(img, axis=0) pred = model.predict(img) class_idx = np.argmax(pred[0]) return jsonify({ 'class_id': int(class_idx), 'confidence': float(pred[0][class_idx]), 'class_name': CLASS_NAMES[class_idx] })
- 使用Python Flask搭建模型服务:
-
前后端交互
- 前端通过Axios调用后端API:
javascript复制async function recognizeMushroom(imageFile) { const formData = new FormData(); formData.append('image', imageFile); try { const response = await axios.post('/api/mushroom/recognize', formData, { headers: { 'Content-Type': 'multipart/form-data' } }); return response.data; } catch (error) { console.error('识别失败:', error); throw error; } }
- 前端通过Axios调用后端API:
3.2 用户管理模块
用户管理模块实现了完整的RBAC(基于角色的访问控制)系统:
-
数据库设计
sql复制CREATE TABLE `user` ( `id` bigint NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(100) NOT NULL, `salt` varchar(50) NOT NULL, `email` varchar(100) DEFAULT NULL, `phone` varchar(20) DEFAULT NULL, `status` tinyint NOT NULL DEFAULT '1', `create_time` datetime NOT NULL, `update_time` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx_username` (`username`) ); CREATE TABLE `role` ( `id` bigint NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `description` varchar(100) DEFAULT NULL, `create_time` datetime NOT NULL, `update_time` datetime NOT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `user_role` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` bigint NOT NULL, `role_id` bigint NOT NULL, `create_time` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx_user_role` (`user_id`,`role_id`) ); -
密码加密处理
java复制public class PasswordUtil { private static final int HASH_ITERATIONS = 1024; private static final int SALT_SIZE = 8; public static String encryptPassword(String password, String salt) { return new SimpleHash("SHA-1", password, salt, HASH_ITERATIONS).toHex(); } public static String generateSalt() { return new SecureRandomNumberGenerator().nextBytes(SALT_SIZE).toHex(); } } -
权限控制实现
java复制@RequiresRoles("admin") @PostMapping("/users") public Result addUser(@Valid @RequestBody UserDTO userDTO) { // 检查用户名是否已存在 if (userService.existsUsername(userDTO.getUsername())) { return Result.error("用户名已存在"); } // 生成盐值 String salt = PasswordUtil.generateSalt(); // 加密密码 String encryptedPassword = PasswordUtil.encryptPassword(userDTO.getPassword(), salt); User user = new User(); BeanUtils.copyProperties(userDTO, user); user.setPassword(encryptedPassword); user.setSalt(salt); userService.save(user); return Result.success(); }
4. 深度学习模型开发
4.1 数据集准备与处理
蘑菇识别模型的质量很大程度上取决于数据集的质量。我使用了公开的蘑菇数据集,包含20种常见蘑菇,每种约500张图片。
数据增强策略:
python复制from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest',
validation_split=0.2
)
4.2 模型构建与训练
我选择了EfficientNetB0作为基础模型,进行迁移学习:
python复制from tensorflow.keras.applications import EfficientNetB0
from tensorflow.keras import layers, models
base_model = EfficientNetB0(
input_shape=(224, 224, 3),
include_top=False,
weights='imagenet'
)
# 冻结基础模型
base_model.trainable = False
# 添加自定义层
inputs = layers.Input(shape=(224, 224, 3))
x = base_model(inputs, training=False)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(256, activation='relu')(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(20, activation='softmax')(x)
model = models.Model(inputs, outputs)
# 编译模型
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
# 训练模型
history = model.fit(
train_generator,
epochs=30,
validation_data=val_generator
)
4.3 模型优化技巧
-
学习率调整:
python复制lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay( initial_learning_rate=1e-3, decay_steps=10000, decay_rate=0.9 ) -
模型微调:
python复制# 解冻顶层进行微调 base_model.trainable = True for layer in base_model.layers[:100]: layer.trainable = False -
早停机制:
python复制early_stopping = tf.keras.callbacks.EarlyStopping( monitor='val_loss', patience=5, restore_best_weights=True )
5. 系统部署与性能优化
5.1 部署方案
系统采用Docker容器化部署,主要包含三个服务:
- 前端服务:Nginx + Vue静态资源
- 后端服务:Spring Boot应用
- 模型服务:Python Flask应用
Docker-compose配置示例:
yaml复制version: '3.8'
services:
frontend:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./frontend/dist:/usr/share/nginx/html
depends_on:
- backend
backend:
build: ./backend
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_URL=jdbc:mysql://mysql:3306/mushroom
- DB_USER=root
- DB_PASSWORD=123456
depends_on:
- mysql
- model-service
model-service:
build: ./model-service
ports:
- "5000:5000"
mysql:
image: mysql:8.0
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=mushroom
volumes:
- mysql-data:/var/lib/mysql
volumes:
mysql-data:
5.2 性能优化措施
-
缓存策略:
java复制@Cacheable(value = "mushroom", key = "#imageHash") public MushroomInfo recognizeMushroom(String imageHash, byte[] imageData) { // 识别逻辑 } -
数据库优化:
- 添加合适的索引
- 使用连接池(HikariCP)
- 慢SQL监控
-
前端性能优化:
- 图片懒加载
- 组件按需加载
- 使用CDN加速静态资源
6. 常见问题与解决方案
6.1 跨域问题
在前后端分离架构中,跨域是常见问题。解决方案:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.maxAge(3600);
}
}
6.2 文件上传大小限制
Spring Boot默认文件上传大小限制为1MB,需要调整:
properties复制# application.properties
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
6.3 模型服务响应慢
解决方案:
- 启用模型预热
- 使用GPU加速
- 实现批量预测接口
python复制# 模型预热
dummy_input = np.zeros((1, 224, 224, 3), dtype=np.float32)
model.predict(dummy_input)
7. 项目总结与扩展方向
这个蘑菇识别系统从技术选型到最终实现,涵盖了现代Web开发的多个关键技术点。在实际开发过程中,最大的挑战是如何将深度学习模型无缝集成到Spring Boot应用中。通过将模型服务独立部署,并通过HTTP通信的方式,很好地解决了这个问题。
项目亮点:
- 完整的RBAC权限控制系统
- 前后端分离架构
- 深度学习模型的高效集成
- 容器化部署方案
未来扩展方向:
- 增加移动端支持(Flutter/React Native)
- 实现模型在线更新功能
- 加入更多蘑菇种类
- 开发社区功能,让用户可以分享识别结果
对于想要学习Spring Boot和深度学习结合开发的同学,这个项目提供了很好的实践机会。特别是在处理图像识别类应用时,这种架构设计既保证了系统的灵活性,又能充分发挥深度学习模型的识别能力。
