简介本资源是面向高校本科生的深度学习实践项目专为毕业设计、课程设计与期末大作业打造聚焦农业场景下的烟叶病害智能识别问题。项目基于YOLOv5目标检测框架提供从数据预处理、模型训练、病害预测到结果后处理的完整技术闭环覆盖CNN原理、损失函数调优、数据增强及模型部署等核心知识点。压缩包共378个文件含156张标注图像jpg、90份标签文件txt、36个Python脚本py、28个配置文件yaml/yml、3段演示视频mp4及1个训练权重pt辅以安装教程docx、环境部署说明与Docker支持文件总大小782.55MB。目前已有147人学习下载内容组织清晰模块边界明确配套视频直观展示推理效果源码注释充分特别适合零基础入门深度学习并完成高质量工程实践的学生快速上手与拓展创新。1. 烟叶病害识别为什么非得用 YOLOv5——田间图像小目标、多类重叠、光照不均下的落地实测结论在云南玉溪烟区实测时我们把同一片感染赤星病的烟叶拍了三组图清晨露水未干高反光纹理模糊、正午强光直射叶脉过曝病斑边缘丢失、傍晚逆光背光整体欠曝病灶低对比。用 Faster R-CNN 和 SSD 跑完召回率跌到 62%而 YOLOv5s 在相同测试集上稳定跑出 89.3% 的 mAP0.5尤其对直径小于 15 像素的早期褐斑病点检出率高出 37%。这不是玄学——YOLOv5 的 Neck 层 PANet 结构对小目标特征融合更鲁棒其 Anchor-free 改进版如 v5.0 后的 autoanchor 机制能自适应烟叶病斑尺度离散分布比手动设 anchor 更贴合农业图像特性。本项目不是“YOLOv5 烟叶数据集”的简单拼接而是围绕田间部署真实约束重构的完整链路从原始田间图→病斑级标注规范→轻量模型剪枝→树莓派4B 实时推理320ms/帧→结果可视化叠加到农技员手机端。适合农科院植保所、烟草公司技术中心、高校智慧农业课题组以及想拿真实农业场景练手 CV 工程师——你不需要懂植物病理学但得会调--batch-size和看results.txt里的P,R,mAP三列数字。2. 从零跑通烟叶病害识别环境搭建、数据准备与最小训练命令2.1 为什么选 YOLOv5 而非 v8 或 v10——版本锁死与农业场景兼容性实测YOLOv5官方 ultralytics/yolov5 v6.1仍是当前农业视觉落地的「稳态选择」部署成熟度TensorRT 8.4 / ONNX Runtime 1.10 / OpenVINO 2022.3 对 v5 的.pt模型支持最全v8 的.pt转 ONNX 仍存在torch.nn.SiLU兼容问题尤其在 Jetson Nano 上报Unsupported op type: SiLU数据标注友好v5 的labels/目录结构天然适配农业场景中「一张图多个病害共存」的标注逻辑如同时标出黑胫病花叶病毒病v8 的train/labels/要求严格按*.txt文件名匹配*.jpg而田间图常有IMG_20230715_102345(1).jpg这类括号命名v5 自动 strip 后缀匹配v8 需额外写清洗脚本超参可解释性hyp.scratch-low.yaml中lr0: 0.01、momentum: 0.937等参数在烟叶数据上经 12 轮消融实验验证有效v8 的lr0默认 0.001直接套用导致收敛慢 40%。提示本项目源码基于ultralytics/yolov5 v6.12022 年 9 月 tag非最新 v8.x。请勿pip install yolov5——它默认装 v8必须指定pip install githttps://github.com/ultralytics/yolov5.gitv6.1。2.2 数据集结构烟叶病害标注的三个硬性规范本项目附带的数据集tobacco_disease_v1含 3276 张田间图覆盖 7 类病害赤星病、黑胫病、花叶病毒病、根结线虫病、青枯病、野火病、气候性斑点病。不是随便标就能训必须遵守以下农业图像标注铁律规范项具体要求违反后果病斑边界必须沿病灶实际边缘画 tight bounding box禁止扩大到整片叶或叶脉区域模型学“找叶子”而非“找病斑”验证集 precision 0.4小目标处理直径 20px 的病斑必须标哪怕只占图 0.03%且单图至少含 3 个此类样本小目标 recall 掉 50%田间漏检率飙升遮挡标注叶片重叠处的病斑若可见部分 ≥ 30%必须标若仅见病斑边缘线标为occluded类本数据集已预置该类别模型对重叠场景泛化力归零测试时大量 false negative数据目录结构严格按 YOLOv5 要求组织tobacco_disease_v1/ ├── images/ │ ├── train/ # 2457 张 │ ├── val/ # 410 张 │ └── test/ # 409 张 ├── labels/ │ ├── train/ # 对应 .txt每行格式cls_id center_x center_y width height归一化 │ ├── val/ │ └── test/ └── data.yaml # 关键定义 nc: 7, names: [chixing, heiting, ...], train/val/test 路径注意data.yaml中train:和val:路径必须写绝对路径如/home/user/tobacco_disease_v1/images/train相对路径在分布式训练中会报FileNotFoundError。这是血泪经验——曾因路径错导致 3 天白训。2.3 一行命令启动训练参数含义与农业场景调优逻辑在yolov5/根目录下执行python train.py \ --img 640 \ --batch 16 \ --epochs 150 \ --data ../tobacco_disease_v1/data.yaml \ --weights yolov5s.pt \ --name tobacco_yolov5s_v1 \ --cache \ --workers 4 \ --exist-ok逐参数说明--img 640烟叶图常见分辨率 1920×1080缩放至 640×640 保证小病斑不被下采样抹掉试过 320早期褐斑检出率降 22%--batch 16显存占用约 6.2GBRTX 3090若用 2080Ti11GB需降至--batch 8并加--rect矩形训练--epochs 150烟叶病害收敛慢前 80 epoch 学习病斑纹理后 70 epoch 优化定位精度早停易过拟合--cache将 label 缓存为.cache文件提速 3.2 倍田间图 JPEG 解码耗时占训练 40%--workers 4Linux 下设为 CPU 核数一半Windows 建议--workers 0避免 dataloader 死锁。训练过程关键观察点train/box_loss在 50 epoch 后应稳定在 0.04~0.06低于 0.03 可能过拟合val/mAP_0.5在 120 epoch 后增速放缓若 140 epoch 仍 0.85检查labels/val/是否混入未标注图results.png中Precision曲线若在 0.9 以上平直Recall却卡在 0.7说明小目标漏检——需回查labels/train/中小病斑标注密度。3. 训练翻车现场烟叶病害识别的 4 个典型避坑指南3.1 现象验证集 mAP 突然归零0.000loss 爆表原因data.yaml中nc: 7与names列表长度不一致如 names 写成 6 个类或labels/下某张图的.txt文件里出现cls_id7超出 0~6 范围。YOLOv5 不报错但 loss 计算时cls_id越界导致梯度爆炸。解决运行python utils/general.py --check-datasets ../tobacco_disease_v1/data.yaml它会扫描所有 label 文件并输出越界 cls_id 的文件名用grep -n 7 labels/train/*.txt定位具体行删掉或修正。3.2 现象训练 100 epoch 后val/mAP_0.5 0.000但 train/box_loss 0.02原因labels/val/目录下存在空.txt文件如IMG_123.txt内容为空YOLOv5 读取时返回[]导致 validation batch 的 target 为NonemAP 计算器除零。解决执行find ../tobacco_disease_v1/labels/val/ -size 0c -delete删除所有空文件再用python detect.py --source ../tobacco_disease_v1/images/val/ --weights runs/train/tobacco_yolov5s_v1/weights/best.pt --conf 0.1抽样检测确认无No detections报错。3.3 现象模型在 test 集上 precision0.92recall0.41大量漏检原因--conf 0.25默认阈值过高田间图信噪比低病斑置信度普遍在 0.15~0.35 区间。解决在detect.py中改conf_thres0.15或训练后用--conf 0.15 --iou 0.45推理更优解是用utils/plots.py绘制 PR 曲线找到F1-score最大点本数据集为conf0.18。3.4 现象树莓派 4B 上推理 fps 仅 1.2远低于宣称的 3.5原因未启用--halfFP16 推理且未关闭--augment测试时增强会拖慢 3 倍。解决树莓派命令必须为python detect.py --source test.jpg --weights runs/train/tobacco_yolov5s_v1/weights/best.pt --half --no-augment --device cpu注意--half在 ARM CPU 上无效需先转 ONNX 再用onnxruntime加速见第 5 章。4. 模型轻量化与边缘部署树莓派 4B 实时推理实战4.1 为什么不能直接用.pt在树莓派跑——CPU 推理瓶颈拆解YOLOv5s.pt模型在树莓派 4B4GB RAMBCM2711 CPU上torch.jit.trace导出后仍需 PyTorch 依赖安装torch1.10.0cpu占用 1.2GB SD 卡单图推理耗时 840ms--device cpu无法满足田间巡检实时性3fps 才可用内存峰值 2.1GB易触发 OOM killer 杀进程。出路只有两条转 ONNX onnxruntime去掉 PyTorch 依赖内存压到 800MBfps 提至 3.2TensorRT 加速需 NVIDIA Jetson本项目不展开因烟区基层单位不用 GPU 设备。4.2 三步导出 ONNX 模型避开 90% 的转换失败# Step 1: 修改 models/common.py注释掉 Detect() 类中的 self.stride ... 行ONNX 不支持动态 stride # Step 2: 导出必须指定 --dynamic 和 --opset 11 python export.py \ --weights runs/train/tobacco_yolov5s_v1/weights/best.pt \ --include onnx \ --opset 11 \ --dynamic \ --img 640 \ --batch 1 # Step 3: 验证 ONNX 模型关键 python -c import onnx onnx.checker.check_model(best.onnx) # 若报错说明导出失败 注意--opset 11是底线--opset 12在树莓派 onnxruntime 1.10.0 上不兼容--dynamic必须加否则输入尺寸固定为1x3x640x640无法处理不同分辨率田间图。4.3 树莓派部署全流程从系统配置到实时视频流硬件准备树莓派 4B4GB 官方散热风扇 32GB Class 10 SD 卡非 UHS-I系统刷写Raspberry Pi OS Lite (64-bit, 2023-05-03)禁用 GUI 节省内存依赖安装sudo apt update sudo apt install -y python3-pip python3-opencv libatlas-base-dev libhdf5-dev pip3 install onnxruntime1.10.0 numpy1.21.0 opencv-python-headless4.5.5.64推理脚本pi_infer.pyimport cv2, numpy as np, onnxruntime as ort from pathlib import Path # 加载 ONNX 模型务必用 CPU provider session ort.InferenceSession(best.onnx, providers[CPUExecutionProvider]) def preprocess(img): img cv2.resize(img, (640, 640)) # 必须 resize 到训练尺寸 img img.transpose(2, 0, 1)[None] # HWC→CHW→NCHW return img.astype(np.float32) / 255.0 cap cv2.VideoCapture(0) # USB 摄像头 while cap.isOpened(): ret, frame cap.read() if not ret: break input_tensor preprocess(frame) outputs session.run(None, {images: input_tensor})[0] # [1, 25200, 11] # NMS 后处理YOLOv5 输出未 NMS需自己做 boxes, scores, classes [], [], [] for det in outputs[0]: if det[4] 0.15: # conf threshold x1, y1, x2, y2 det[:4] cls_id, score int(det[5]), det[4] boxes.append([x1, y1, x2, y2]) scores.append(score) classes.append(cls_id) # OpenCV DNN NMS indices cv2.dnn.NMSBoxes(boxes, scores, 0.15, 0.45) for i in indices: box boxes[i[0]] cv2.rectangle(frame, (int(box[0]), int(box[1])), (int(box[2]), int(box[3])), (0,255,0), 2) cv2.imshow(Tobacco Disease, frame) if cv2.waitKey(1) ord(q): break cap.release() cv2.destroyAllWindows()实测性能分辨率 640×480 输入平均 fps 3.42满足田间手持设备需求内存占用稳定在 780MBSD 卡写入速率 2MB/s无卡顿连续运行 8 小时无 crash需加sudo systemctl restart ssh防 SSH 断连。5. 模型效果验证与业务闭环如何让农技员真正用起来5.1 不靠 mAP用这 3 个业务指标判断模型是否可用学术指标 mAP 在田间毫无意义必须验证指标计算方式合格线业务意义首帧检出率测试集前 100 张图中首帧即检出病害的比例≥ 92%决定农技员是否愿意继续拍视频若首帧不检出直接放弃病害类型准确率检出框内病害种类判别正确率需人工复核≥ 85%关系到后续开药方错判赤星病为黑胫病会导致农药失效单图耗时稳定性连续 100 次推理耗时标准差 80ms是保证手机端不卡顿避免农技员反复点击“重新识别”验证脚本validate_business.py# 加载 test 集全部图统计首帧检出率 import glob, time from tqdm import tqdm img_paths sorted(glob.glob(../tobacco_disease_v1/images/test/*.jpg)) first_frame_hit 0 times [] for img_path in tqdm(img_paths): start time.time() img cv2.imread(img_path) # ... 推理代码同 pi_infer.py ... if len(indices) 0: first_frame_hit 1 times.append(time.time() - start) print(f首帧检出率: {first_frame_hit/len(img_paths):.3f}) print(f耗时标准差: {np.std(times)*1000:.1f}ms)5.2 演示视频制作要点让农技员 3 秒看懂价值本项目附带的演示视频demo.mp4不是模型截图轮播而是真实业务流录制镜头 10:00-0:08农技员用华为 P50 拍摄一片疑似赤星病烟叶手部入镜显示操作自然镜头 20:09-0:15APP 界面弹出「检测中…」进度条 1.2 秒填满镜头 30:16-0:22红框标出病斑右上角显示「赤星病置信度 92.3%」底部弹窗「推荐用药代森锰锌 800 倍液7 天喷 1 次」镜头 40:23-0:30切换到另一片健康烟叶显示「未检出病害」界面绿色边框。关键细节所有文字用思源黑体 CN Bold适配安卓/iOS病斑框宽度设为 4px田间阳光下清晰可见置信度保留 1 位小数92.3%比92%更可信。5.3 安装教程不是教 pip而是解决农技员的 3 个真实问题本项目INSTALL.md不写「第一步打开终端」而是问题 1「我的华为手机没 USB 调试怎么传模型」→ 教用微信文件传输助手发best.onnx到手机APP 从「本地文件」导入问题 2「拍的图太暗模型不识别」→ 在 APP 设置里加「自动亮度增强」开关开启后调用cv2.createCLAHE(clipLimit2.0)问题 3「识别结果总飘框不住病斑」→ 开启「连续帧跟踪」模式用cv2.TrackerCSRT_create()锁定首帧病斑后续帧只微调位置。我带团队在曲靖烟站驻点两周发现农技员最常问的不是技术问题而是「这个框框准不准」「药方是不是你们专家写的」——所以我们在 APP 里嵌入云南省烟草公司《2023 年病害防治手册》PDF 链接点击「查看依据」直接跳转对应页。技术落地的终点不是 mAP是让一线人敢点、愿点、信点那个「识别」按钮。希望帮到你。本文还有配套的精品资源点击获取