1. 项目概述:当YOLO遇上生菜——一个农业技术人的实战记录
去年在参观某大型植物工厂时,我注意到技术员每天要花费3小时手动记录生菜生长状态。作为计算机视觉从业者,我当即决定开发一套自动化检测系统。经过半年迭代,这套基于多版本YOLO和SpringBoot的生菜生长周期检测系统已经成功部署在多个生产基地。
这个系统能做什么?简单说就是通过摄像头"看"生菜,自动判断它处于哪个生长阶段(发芽期、幼苗期等),并给出种植建议。就像给生菜配了个24小时不休息的"植物医生"。下面我会从技术选型到落地细节,完整分享这个项目的开发历程。
2. 系统核心设计思路
2.1 为什么选择生菜作为检测对象?
生菜是植物工厂最常见的叶菜,其生长周期短(通常25-35天)、阶段特征明显。通过长期观察,我们确定了5个关键检测阶段:
- 空定植篮(empty_pod):种植前的空容器状态
- 发芽期(germination):播种后3-5天,两片子叶展开
- 幼苗期(young):真叶出现到叶片覆盖定植篮50%
- 定植篮可见(pod):叶片覆盖50%-80%
- 可采收(ready):叶片完全覆盖定植篮
2.2 技术架构选型考量
系统采用经典的三层架构:
code复制[前端] Vue.js + Element Plus
↑
[后端] SpringBoot (REST API)
↑
[AI服务] YOLO系列模型 + DeepSeek
选择SpringBoot是因为:
- 成熟的Java生态,适合企业级应用
- 完善的权限管理和事务支持
- 与MySQL等传统数据库配合良好
而前端选用Vue.js则是考虑到:
- 响应式设计适配不同设备
- 丰富的可视化组件库
- 与后端API对接简便
3. 核心模块实现细节
3.1 数据采集与标注
我们使用工业相机在3个植物工厂采集了2000+张生菜图像,最终筛选出1410张高质量样本。标注工具采用LabelImg,标注规范包括:
- 每个定植篮作为一个检测单元
- 遮挡超过30%的样本剔除
- 不同光照条件(早/中/晚)均衡分布
数据集分布示例:
| 类别 | 样本数 | 占比 |
|---|---|---|
| empty_pod | 320 | 22.7% |
| germination | 280 | 19.9% |
| young | 310 | 22.0% |
| pod | 290 | 20.6% |
| ready | 210 | 14.9% |
3.2 模型训练关键参数
我们对比了YOLOv8/v10/v11/v12四个版本,以YOLOv8s为例,训练配置如下:
python复制model = YOLO('yolov8s.pt') # 加载预训练模型
results = model.train(
data='lettuce.yaml',
epochs=300, # 实测300轮后loss收敛
batch=32, # Tesla V100显存限制
imgsz=640, # 输入图像尺寸
optimizer='AdamW', # 比SGD收敛更快
lr0=0.01, # 初始学习率
weight_decay=0.0005,
augment=True, # 启用Mosaic等增强
)
3.3 模型性能对比
在测试集上的表现(RTX 3090):
| 模型 | mAP@0.5 | 参数量(M) | 推理速度(ms) |
|---|---|---|---|
| YOLOv8n | 0.872 | 3.2 | 8.2 |
| YOLOv8s | 0.916 | 11.4 | 12.7 |
| YOLOv10n | 0.885 | 3.5 | 7.8 |
| YOLOv10s | 0.923 | 12.6 | 11.9 |
| YOLOv11s | 0.928 | 10.1 | 13.2 |
| YOLOv12s | 0.931 | 14.3 | 15.6 |
最终系统选择YOLOv10s作为默认模型,因其在精度和速度间取得了最佳平衡。
4. 系统集成与优化
4.1 SpringBoot后端设计
核心API接口示例:
java复制@RestController
@RequestMapping("/api/detect")
public class DetectionController {
@PostMapping("/image")
public Result detectImage(@RequestParam MultipartFile file,
@RequestParam(defaultValue = "yolov10s") String modelType) {
// 1. 保存上传文件
String imgPath = fileStorageService.store(file);
// 2. 调用Python服务运行检测
DetectionResult detection = yolService.runDetection(imgPath, modelType);
// 3. 调用DeepSeek生成报告
String analysis = deepSeekService.generateReport(detection);
// 4. 保存记录
detectionRecordService.saveRecord(detection, analysis);
return Result.success(detection);
}
}
4.2 前端关键实现
视频检测组件核心逻辑:
javascript复制// 使用WebRTC获取摄像头流
const startCamera = async () => {
const stream = await navigator.mediaDevices.getUserMedia({
video: { width: 1280, height: 720 }
});
videoRef.value.srcObject = stream;
// 每500ms截帧检测
intervalId = setInterval(async () => {
const canvas = document.createElement('canvas');
canvas.width = videoRef.value.videoWidth;
canvas.height = videoRef.value.videoHeight;
canvas.getContext('2d').drawImage(videoRef.value, 0, 0);
const imageBlob = await new Promise(resolve =>
canvas.toBlob(resolve, 'image/jpeg', 0.9));
const formData = new FormData();
formData.append('file', imageBlob, 'frame.jpg');
const res = await axios.post('/api/detect/image', formData);
updateDetectionResult(res.data);
}, 500);
};
5. 部署与性能优化
5.1 生产环境部署方案
我们采用Docker Compose编排服务:
yaml复制version: '3.8'
services:
backend:
image: lettuce-detection-backend:1.2
ports:
- "8080:8080"
depends_on:
- redis
- mysql
ai-service:
image: yolov10-service:1.0
gpus: all # 需要NVIDIA GPU支持
environment:
- PYTHONUNBUFFERED=1
mysql:
image: mysql:8.0
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:alpine
volumes:
mysql_data:
5.2 性能优化技巧
- 模型量化:将FP32模型转为INT8,体积减小4倍,速度提升2倍
python复制model.export(format='onnx', int8=True, dynamic=False)
-
缓存机制:
- 使用Redis缓存常用检测结果
- 对相同图片的重复检测直接返回缓存
-
异步处理:
java复制@Async
public void asyncDetection(String imagePath) {
// 耗时检测任务
}
6. 实际应用案例
在某植物工厂的对比测试中:
- 人工检测:3名技术员每天共需3小时,准确率约85%
- 系统检测:全天候运行,准确率92.3%,主要误判发生在:
- 新叶展开与成熟期交界(约5%)
- 光照异常时的颜色误判(约2.7%)
典型检测结果示例:
json复制{
"image": "lettuce_0234.jpg",
"detections": [
{
"class": "ready",
"confidence": 0.96,
"box": [125, 80, 320, 280]
}
],
"analysis": "当前生菜已进入最佳采收期(第28天),叶片完全覆盖定植篮,建议在24小时内采收以获得最佳口感。周边3株出现轻微黄化,建议检查EC值是否偏高。"
}
7. 开发中的经验教训
-
数据采集的坑:
- 初期只在9-11点采集,模型在其他时段表现差
- 解决方案:建立全天候采集计划,覆盖不同光照条件
-
模型选择的误区:
- 最初追求最新模型(YOLOv12),实际部署发现:
- 对硬件要求高
- 速度提升不明显
- 最终选择更稳定的YOLOv10
- 最初追求最新模型(YOLOv12),实际部署发现:
-
前后端协作问题:
- 视频流检测最初采用base64编码传输,导致延迟高
- 优化为二进制流传输后,延迟从1.2s降至0.3s
8. 系统扩展方向
-
多作物支持:
- 正在收集草莓、菠菜的生长数据
- 需要解决不同作物形态差异大的问题
-
3D生长预测:
- 结合时序检测结果预测未来3天生长状态
- 需要引入LSTM等时序模型
-
硬件集成:
- 与自动灌溉系统联动
- 开发专用边缘计算设备
这套系统从构思到落地用了6个月时间,期间经历了3次大的架构调整。最大的体会是:农业AI应用不能只追求算法精度,更要考虑实际生产环境的复杂性。比如植物工厂的高湿度会导致镜头起雾,我们最终不得不为摄像头加装了自动除雾装置。