1. 项目概述
这个基于Java+Vue的细粒度商品识别系统是一个融合了深度学习技术的全栈应用,主要解决电商、零售等行业中商品精细分类和识别的需求。系统采用前后端分离架构,后端基于SpringBoot框架提供RESTful API服务,前端使用Vue.js构建交互式用户界面,核心的深度学习模型采用CNN等算法实现细粒度图像分类。
细粒度商品识别与传统商品识别最大的区别在于,它需要区分同一大类下的细微差异。比如不仅能识别"运动鞋",还能精确到"耐克Air Jordan 1 Retro High OG"这样的具体型号。这种能力在电商平台、智能货架、无人零售等场景中具有重要价值。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 整体架构
系统采用典型的三层架构:
- 前端:Vue 3 + Element Plus + Axios
- 后端:Spring Boot 2.7 + MyBatis Plus + Redis
- AI服务:Python + PyTorch + Flask
前后端通过REST API交互,AI服务通过HTTP接口提供模型推理能力。这种架构解耦了各组件,便于独立开发和部署。
2.2 数据库设计
核心表结构包括:
sql复制CREATE TABLE `goods` (
`id` bigint NOT NULL AUTO_INCREMENT,
`goods_code` varchar(32) NOT NULL COMMENT '商品编码',
`name` varchar(128) NOT NULL COMMENT '商品名称',
`category_id` bigint NOT NULL COMMENT '分类ID',
`brand` varchar(64) DEFAULT NULL COMMENT '品牌',
`spec` varchar(128) DEFAULT NULL COMMENT '规格',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_code` (`goods_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `goods_image` (
`id` bigint NOT NULL AUTO_INCREMENT,
`goods_id` bigint NOT NULL,
`url` varchar(255) NOT NULL COMMENT '图片URL',
`is_main` tinyint(1) DEFAULT '0' COMMENT '是否主图',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_goods` (`goods_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `recognition_result` (
`id` bigint NOT NULL AUTO_INCREMENT,
`image_id` bigint NOT NULL,
`predicted_label` varchar(128) NOT NULL,
`confidence` decimal(5,4) NOT NULL,
`status` enum('PENDING','SUCCESS','CORRECTED') DEFAULT 'PENDING',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_image` (`image_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 核心功能实现
3.1 商品图片上传与处理
前端采用Element Upload组件实现图片上传:
vue复制<template>
<el-upload
action="/api/goods/upload"
:headers="{Authorization: token}"
:on-success="handleSuccess"
:show-file-list="false"
list-type="picture-card"
>
<i class="el-icon-plus"></i>
</el-upload>
</template>
<script>
export default {
data() {
return {
token: localStorage.getItem('token')
}
},
methods: {
handleSuccess(res) {
this.$emit('uploaded', res.imageId)
}
}
}
</script>
后端使用Spring MVC处理文件上传:
java复制@RestController
@RequestMapping("/api/goods")
public class GoodsController {
@PostMapping("/upload")
public Result<ImageUploadResult> uploadImage(
@RequestParam("file") MultipartFile file,
@RequestParam(required = false) Long goodsId) {
if (file.isEmpty()) {
return Result.fail("文件不能为空");
}
try {
String originalName = file.getOriginalFilename();
String ext = originalName.substring(originalName.lastIndexOf("."));
String fileName = UUID.randomUUID() + ext;
Path path = Paths.get(uploadPath, fileName);
Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
GoodsImage image = new GoodsImage();
image.setGoodsId(goodsId);
image.setUrl("/uploads/" + fileName);
imageMapper.insert(image);
return Result.success(new ImageUploadResult(image.getId(), "/uploads/" + fileName));
} catch (Exception e) {
log.error("上传失败", e);
return Result.fail("上传失败");
}
}
}
3.2 深度学习模型集成
系统采用Python Flask提供模型推理服务:
python复制from flask import Flask, request, jsonify
import torch
from PIL import Image
import io
import numpy as np
app = Flask(__name__)
model = torch.load('fine_grained_model.pt')
model.eval()
@app.route('/predict', methods=['POST'])
def predict():
if 'file' not in request.files:
return jsonify({'error': 'no file uploaded'}), 400
file = request.files['file']
img_bytes = file.read()
img = Image.open(io.BytesIO(img_bytes))
# 图像预处理
img = img.resize((224, 224))
img_array = np.array(img) / 255.0
img_tensor = torch.from_numpy(img_array).permute(2, 0, 1).float()
img_tensor = img_tensor.unsqueeze(0)
# 推理
with torch.no_grad():
outputs = model(img_tensor)
probs = torch.nn.functional.softmax(outputs, dim=1)
conf, pred = torch.max(probs, 1)
return jsonify({
'predicted_label': class_names[pred.item()],
'confidence': conf.item()
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Java后端通过RestTemplate调用Python服务:
java复制@Service
public class RecognitionService {
@Value("${ai.service.url}")
private String aiServiceUrl;
public RecognitionResult recognize(Long imageId) {
String imageUrl = imageMapper.selectById(imageId).getUrl();
byte[] imageBytes = downloadImage(imageUrl);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", new ByteArrayResource(imageBytes) {
@Override
public String getFilename() {
return "upload.jpg";
}
});
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
RecognitionResult result = restTemplate.postForObject(aiServiceUrl + "/predict",
requestEntity, RecognitionResult.class);
saveResult(imageId, result);
return result;
}
}
4. 系统特色功能
4.1 细粒度识别结果修正
系统支持人工修正识别结果,并将修正后的数据反馈给模型用于后续训练:
java复制@PostMapping("/recognition/correct")
public Result<?> correctRecognition(@RequestBody @Valid CorrectRequest request) {
RecognitionResult result = recognitionMapper.selectById(request.getId());
if (result == null) {
return Result.fail("记录不存在");
}
result.setPredictedLabel(request.getCorrectedLabel());
result.setStatus("CORRECTED");
recognitionMapper.updateById(result);
// 将修正数据发送到AI服务用于模型优化
feedbackToModel(result.getImageId(), request.getCorrectedLabel());
return Result.success();
}
4.2 模型版本管理
系统支持多版本模型管理和热切换:
java复制@PostMapping("/model/deploy")
public Result<?> deployModel(@RequestParam Long modelId) {
AIModel model = modelMapper.selectById(modelId);
if (model == null) {
return Result.fail("模型不存在");
}
// 更新当前活跃模型
AIModel current = modelMapper.selectOne(new QueryWrapper<AIModel>()
.eq("status", "ACTIVE"));
if (current != null) {
current.setStatus("INACTIVE");
modelMapper.updateById(current);
}
model.setStatus("ACTIVE");
model.setDeployTime(LocalDateTime.now());
modelMapper.updateById(model);
return Result.success();
}
5. 部署与优化
5.1 系统部署方案
推荐使用Docker Compose部署整个系统:
yaml复制version: '3'
services:
backend:
build: ./backend
ports:
- "8080:8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/goods_recognition
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=123456
depends_on:
- mysql
- redis
frontend:
build: ./frontend
ports:
- "80:80"
ai-service:
build: ./ai-service
ports:
- "5000:5000"
volumes:
- ./ai-service/models:/app/models
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=goods_recognition
volumes:
- ./data/mysql:/var/lib/mysql
redis:
image: redis:alpine
5.2 性能优化建议
-
图片处理优化:
- 使用OpenCV替代PIL进行图像处理
- 实现图片预加载和缓存机制
- 对大图进行分块处理
-
模型推理优化:
- 使用TorchScript将模型转换为脚本模式
- 实现批量推理(batch inference)
- 使用ONNX Runtime加速推理
-
系统级优化:
- 引入消息队列处理识别请求
- 使用Redis缓存高频访问数据
- 实现API响应缓存
6. 常见问题与解决方案
6.1 识别准确率不高
问题现象:对某些相似商品区分度不够
解决方案:
- 增加训练数据,特别是难样本
- 使用更精细的标注标准
- 尝试不同的网络结构(如ResNet, EfficientNet)
- 引入注意力机制
6.2 系统响应慢
问题现象:图片上传后识别等待时间过长
优化方案:
java复制@Async
public void asyncRecognize(Long imageId) {
RecognitionResult result = recognize(imageId);
// 通过WebSocket推送结果给前端
websocketServer.sendToUser(userId, result);
}
6.3 模型更新困难
问题现象:新模型上线需要重启服务
解决方案:
- 实现模型热加载
- 使用模型版本控制
- 建立AB测试机制
7. 扩展功能建议
- 移动端适配:开发微信小程序或React Native应用
- 数据标注工具:集成标注功能闭环数据流
- 多模态识别:结合文本、条码等信息提升准确率
- 商品比价功能:对接电商API实现价格比较
这个细粒度商品识别系统通过深度学习技术与传统Web开发的结合,解决了商品精细分类的实际问题。系统采用模块化设计,便于功能扩展和性能优化。在实际部署中,可以根据业务需求调整模型结构和系统架构。
