ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

番茄健康叶片检测数据集:3100张YOLO标注与智慧农业实战

番茄健康叶片检测数据集:3100张YOLO标注与智慧农业实战

1. 番茄叶片检测数据集到底解决什么问题

1.1 从一次大棚巡检的真实痛点说起

去年秋天我帮一个做设施农业的朋友调试巡检机器人,他种的是串收番茄,三个大棚加起来不到八亩地。当时他提的需求特别朴素:机器人每天沿着垄沟走两趟,把叶片上有病斑的位置标出来,最好能区分是早疫、晚疫还是叶霉。听起来不难,但真正动手才发现,卡脖子的根本不是模型结构,而是没有一份能直接拿来训练的番茄健康叶片检测数据集。

网上公开的农业数据集要么是分类任务(一张图一个标签,告诉你这片叶子病了),要么是整株级别的粗标注,真正做成目标检测格式、带边界框、能直接喂给 YOLO 的番茄叶片数据少得可怜。而实际巡检场景里,一张图里往往同时出现健康叶片、早期病斑叶片、被遮挡的叶片,分类模型根本没法定位,你连病斑在哪都不知道,喷药机械臂往哪伸?

这就是"番茄健康叶片检测数据集 | 3100张YOLO智慧农业数据集"这类资源存在的意义。它把问题从"这张图是不是病叶"推进到"这张图里每一片叶子的位置和健康状态分别是什么",直接对接目标检测的落地链路。3100张这个量级不算大,但对于一个垂直细分场景来说,已经足够跑通从训练到部署的完整闭环,尤其是配合迁移学习。

1.2 数据集的核心构成与标注逻辑

先把这个数据集拆开看。3100张图像,通常按 8:1:1 或者 7:2:1 划分训练集、验证集、测试集。类别设计上,番茄叶片检测一般围绕两个维度展开:健康状态和叶片个体。常见的类别方案是healthy(健康)、diseased(患病)两大类,也有更细的会拆成early_blight、late_blight、leaf_mold、healthy四类甚至更多。

标注格式是 YOLO 标准的 txt 文件,每行class_id x_center y_center width height,坐标全部归一化到 0-1 之间。这一点特别关键,很多人第一次拿到数据集会懵:为什么坐标是小数?因为 YOLO 训练时输入图像会被 resize 到固定尺寸(比如 640×640),归一化坐标能让标注与分辨率解耦,换输入尺寸不用重新标。

提示:拿到数据集第一件事不是急着训练,而是抽查标注质量。用脚本把 txt 画回原图,肉眼过一遍,看看框有没有偏移、漏标、类别错标。农业数据集最常见的坑就是叶片重叠区域标注不一致,同一片叶子在不同图里框的大小差很多。

数据集的图像来源通常是田间实拍,包含不同光照(顺光、逆光、阴天)、不同生长阶段(苗期、开花期、结果期)、不同遮挡情况。这种多样性是好事,但也意味着长尾分布问题:健康叶片样本往往远多于患病叶片,因为田里健康植株本来就占多数。如果不做处理,模型会倾向于把所有叶子都预测成健康,准确率看着高,实际没用。

1.3 谁适合用这份数据集

这份数据集不是给纯算法研究员刷 SOTA 用的,它更适合三类人:一是做智慧农业落地的工程团队,需要快速验证巡检机器人或无人机方案的可行性;二是农业院校的学生做课程设计或毕业设计,想找一个有实际意义又不至于太泛的目标检测题目;三是想入门 YOLO 但苦于没有合适数据的开发者,番茄叶片目标清晰、背景相对单一,比 COCO 那种复杂场景友好得多。

我个人的判断是,如果你的目标是发论文冲顶会,3100张可能偏少,需要做数据增强或者半监督扩充;但如果目标是做一个能跑起来、能演示、能小范围试用的系统,这个量级完全够用,关键在于你怎么用。

2. 数据集使用前的关键准备与选型考量

2.1 为什么选 YOLO 而不是其他检测框架

目标检测框架一大堆,Faster R-CNN、SSD、RetinaNet、DETR,为什么农业场景里 YOLO 系列出镜率这么高?我踩过几次坑之后总结出三个现实原因。

第一是速度。农业巡检设备大多是边缘端,Jetson Nano、树莓派加加速棒、或者工控机,算力有限。YOLO 单阶段检测的特性决定了它在同等精度下推理速度远快于两阶段方法。你在棚里让机器人以 0.5m/s 走,摄像头 30fps 采集,如果模型只能跑 5fps,那漏检率会高得离谱。

第二是部署生态。YOLO 从 v5 开始,导出 ONNX、TensorRT、OpenVINO 的链路非常成熟,一行命令的事。你训完模型想上边缘设备,不用自己写算子适配。相比之下 DETR 系列虽然精度好,但部署时 transformer 结构的算子支持在部分边缘芯片上还是麻烦。

第三是社区资源。遇到问题搜一下,YOLO 相关的中文资料、踩坑记录、调参经验铺天盖地。农业场景本身小众,如果框架再小众,你连问都没地方问。

具体版本选择上,我的建议是:新手从 YOLOv8 起步,追求极致速度上 YOLOv8n 或 YOLOv10n,追求精度用 YOLOv8m 或 YOLOv11m。v5 虽然经典,但官方已经停止大版本更新,新项目没必要从它开始。v8 的 API 设计对新手友好,model.train()一行搞定,配置文件也清晰。

2.2 环境搭建:PyCharm 加 YOLO 的实操路径

热词里"使用pycharm安装并使用yolo"出现频率很高,说明很多人卡在环境这一步。我把完整流程走一遍,你照着做基本不会出问题。

首先是 Python 版本。YOLOv8 要求 Python 3.8 以上,我实测 3.10 最稳,3.11 和 3.12 在部分依赖上还有兼容问题,尤其是 torch 和 torchvision 的版本匹配。别用最新的,用 3.10。

创建虚拟环境这一步别省。很多人图省事直接装在 base 环境,结果后面装别的库冲突了,哭都来不及。在 PyCharm 里新建项目时勾选 "New environment using Virtualenv",或者命令行:

python -m venv tomato_yolo # Windows tomato_yolo\Scripts\activate # Linux/Mac source tomato_yolo/bin/activate

然后装 ultralytics:

pip install ultralytics

这一条命令会把 torch、torchvision、numpy、opencv-python 等依赖一起装上。如果你有 NVIDIA 显卡想用 CUDA 加速,建议先去 PyTorch 官网查对应 CUDA 版本的安装命令,先单独装 torch,再装 ultralytics,避免 pip 自动装成 CPU 版本。

注意:装完之后一定要验证 GPU 是否可用。在 PyCharm 的 Python Console 里跑import torch; print(torch.cuda.is_available()),返回 True 才算成功。返回 False 的话,要么是没装 CUDA 版 torch,要么是显卡驱动版本不匹配。这个坑我见过太多人踩,训练半天发现用的是 CPU,速度差几十倍。

2.3 数据集目录结构的规范组织

YOLO 对目录结构有约定,不按规矩来训练脚本会找不到文件。标准结构是这样的:

tomato_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml

images/train里放 jpg 或 png,labels/train里放同名的 txt。注意文件名必须一一对应,img_001.jpg对应img_001.txt,差一个字符都会报错。

data.yaml是数据集描述文件,内容大概长这样:

path: /home/user/tomato_dataset train: images/train val: images/val test: images/test nc: 2 names: ['healthy', 'diseased']

nc是类别数,names是类别名列表,顺序必须和标注文件里的 class_id 对应。如果你把 healthy 标成 0、diseased 标成 1,那 names 里第一个就得是 healthy,搞反了模型学出来的结果完全是错的。

我见过有人把path写成相对路径,结果换个目录跑就报错。建议写绝对路径,或者用os.path动态拼接,省心。

3. 从零跑通番茄叶片检测训练全流程

3.1 数据增强策略:小数据集的救命稻草

3100张图,说实话不算多。番茄叶片检测里,模型需要学会识别不同角度、不同光照、不同遮挡下的叶片,原始数据很难覆盖所有情况。数据增强就是用小样本撬动大泛化的关键手段。

YOLOv8 内置了增强参数,在训练配置里可以直接调。我常用的组合是这样的:

from ultralytics import YOLO model = YOLO('yolov8m.pt') model.train( data='tomato_dataset/data.yaml', epochs=150, imgsz=640, batch=16, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=15.0, translate=0.1, scale=0.5, shear=2.0, flipud=0.3, fliplr=0.5, mosaic=1.0, mixup=0.1, )

逐个解释这些参数为什么这么设。hsv_h/s/v是色调、饱和度、明度扰动,农业场景光照变化大,这三个值适当调高能让模型对光照不敏感。degrees=15是随机旋转,番茄叶片在自然状态下朝向各异,旋转增强很合理,但别超过 30 度,否则叶片形态失真。flipud=0.3是上下翻转,注意这个值不能设太高,因为植物有向光性,倒过来的叶片在现实中很少见,设 0.3 是折中。fliplr=0.5左右翻转可以放心用,叶片左右对称性较强。

mosaic=1.0是 YOLO 的招牌增强,把四张图拼成一张,能大幅提升小目标检测能力,同时变相增加 batch 内的多样性。mixup=0.1是图像混合,比例别太高,0.1 到 0.2 之间比较稳,太高会让叶片边界模糊,反而伤害定位精度。

实操心得:数据增强不是越多越好。我试过把 degrees 开到 45、scale 开到 0.8,结果验证集 mAP 反而掉了。原因是增强后的图像分布偏离了真实田间分布,模型学了一堆现实中不存在的形态。增强的目的是模拟真实变化,不是创造新世界。

3.2 训练参数调优:学习率与 batch size 的配合

学习率是训练里最敏感的旋钮。YOLOv8 默认用余弦退火加 warmup,初始 lr 一般设 0.01,但这是针对 COCO 这种大数据集的。番茄数据集小,我建议初始 lr 降到 0.001 到 0.005 之间,避免早期震荡。

batch size 受显存限制。如果你用 8G 显存的卡,imgsz=640 的情况下 batch 大概能开到 16;12G 能到 32。batch 太小会导致 BN 层统计不稳定,训练曲线抖动;batch 太大则泛化可能变差。我的经验是在显存允许范围内取中等偏大,16 到 32 是比较舒服的区间。

训练轮数上,3100 张图配合预训练权重,100 到 200 epoch 通常能收敛。判断收敛不要只看 loss,要看验证集的 mAP50 和 mAP50-95。如果连续 20 个 epoch 这两个指标都不涨了,就可以停。YOLOv8 有patience参数,设成 30 会自动早停。

这里有个细节:冻结骨干网络训练。如果你数据量特别小(比如只有几百张),可以先冻结 backbone 只训 head,跑 50 epoch,再解冻全量微调。这样能防止预训练权重被小数据带偏。3100 张的话,直接全量微调问题不大,但如果发现过拟合严重,可以试试这个策略。

3.3 训练过程监控与指标解读

训练启动后,YOLO 会在runs/detect/train/下生成一堆文件,最重要的是results.csv和weights/目录。results.csv记录了每个 epoch 的 loss 和指标,可以用 pandas 读出来画图。

关键指标有三个:box_loss、cls_loss、mAP50。box_loss 衡量边界框回归误差,cls_loss 衡量分类误差。正常情况下两个 loss 都应该是下降趋势,如果 box_loss 降但 cls_loss 不降,说明定位学好了但分类没学好,可能是类别不平衡或者类别特征不明显。如果 cls_loss 降但 box_loss 不降,可能是标注框质量有问题。

mAP50 是 IoU 阈值 0.5 时的平均精度,mAP50-95 是 0.5 到 0.95 每隔 0.05 取一次的平均。农业场景里,mAP50 能到 0.85 以上就算不错,mAP50-95 能到 0.6 以上说明定位比较准。如果 mAP50 高但 mAP50-95 低,说明框大概位置对但不够精确,可以考虑调 anchor 或者用更高分辨率的输入。

我一般会在训练中途用验证集跑一次可视化,把预测框画到原图上,肉眼看看哪些叶片漏检了、哪些误检了。数字指标有时候会骗人,肉眼看图最直接。比如模型可能把相邻两片叶子框成一个大框,mAP 看着还行,但实际没法用。

4. 常见问题排查与实战避坑指南

4.1 训练不收敛或指标异常的排查思路

训练过程中最容易遇到的问题是 loss 不降或者 mAP 一直上不去。我整理了一个排查顺序,按这个走基本能定位到原因。

现象可能原因排查方法解决方向
loss 为 nan学习率过高、数据有脏标注检查 lr、抽查标注降 lr、清洗数据
loss 不降数据路径错、类别数不对打印数据集长度、检查 yaml修正路径和 nc
mAP 一直为 0标注格式错、坐标未归一化可视化标注重新转换格式
只检出健康叶片类别不平衡统计各类样本数过采样、加权损失
框位置偏移严重标注框与图像不对应画框回原图修正标注
验证集好测试集差数据分布不一致对比两个集合来源重新划分数据

其中"mAP 一直为 0"这个坑我踩过。当时标注文件里坐标是像素值不是归一化值,模型怎么学都学不对。后来写了个脚本检查,发现所有坐标都大于 1,一眼就看出问题。所以拿到数据集第一件事,写个校验脚本,检查每行是不是 5 个值、class_id 是不是在范围内、坐标是不是都在 0-1 之间。

类别不平衡也是高频问题。番茄田里健康叶片本来就多,如果 healthy 有 8000 个框、diseased 只有 2000 个,模型会偏向预测 healthy。解决办法有几个:一是对少数类做过采样,复制图像并做增强;二是在 loss 里给少数类更高权重;三是用 focal loss 替代交叉熵。YOLOv8 默认的 cls loss 已经带了部分处理,但极端不平衡时还是需要手动干预。

4.2 推理部署阶段的性能优化

模型训完只是第一步,真正落地要考虑推理速度和资源占用。我拿 YOLOv8m 在 Jetson Orin Nano 上实测过,PyTorch 原生推理 640×640 大概 15fps,导出 TensorRT 后能到 45fps 左右,提升非常明显。

导出命令很简单:

from ultralytics import YOLO model = YOLO('runs/detect/train/weights/best.pt') model.export(format='engine', half=True, imgsz=640)

half=True是 FP16 量化,精度损失很小但速度提升明显。format='engine'是 TensorRT,如果是其他平台可以选onnx、openvino、tflite。

注意:导出 TensorRT 时 imgsz 必须和训练时一致,否则精度会掉。另外 TensorRT 引擎是跟设备绑定的,在 A 设备导出的 engine 拿到 B 设备上可能跑不了,需要在目标设备上重新导出。

还有一个容易被忽略的点是输入预处理。训练时 YOLO 会自动做 letterbox 填充,推理时如果你自己写预处理,一定要保持一致,否则检测框会偏移。我见过有人推理时直接 resize 不填充,结果框全歪了,查了半天以为是模型问题。

4.3 农业场景特有的数据陷阱

农业数据集和通用数据集有个很大区别:背景干扰。番茄大棚里除了叶片,还有吊蔓绳、地膜、滴灌管、甚至工人的手。如果这些元素在训练集里出现得少,模型可能把它们误检成叶片。解决办法是在标注时把明显不是叶片的区域也标出来,或者增加包含这些干扰的负样本。

另一个陷阱是叶片重叠。番茄叶片密集生长,一片压一片很常见。标注时如果只标可见部分,模型学到的就是"半片叶子",遇到完整叶片反而框不准。我的做法是:重叠区域如果超过 50% 被遮挡,就不标;如果遮挡少于 50%,按可见轮廓标,但框可以适当外扩到估计的完整范围。这个标准要在整个数据集里统一,不能一张图一个标法。

光照也是大问题。大棚里中午阳光直射,叶片反光严重,病斑特征被淹没;傍晚光线暗,叶片发黑,健康和不健康看起来差不多。如果数据集里某种光照条件样本太少,模型在那种条件下就会失效。建议在划分数据集时,按光照条件分层抽样,保证训练集和验证集里各种光照都有。

最后说一个我自己的经验:别迷信公开数据集的标注。3100 张图,标注工作量巨大,难免有疏漏。我一般会随机抽 100 张,自己重新标一遍,和原标注对比,算一下 IoU。如果平均 IoU 低于 0.7,说明标注质量堪忧,要么自己重标,要么用半自动方式修正。这个前期投入很值得,脏数据训出来的模型,后面调参调到死也救不回来。

5. 从数据集到落地系统的扩展思路

5.1 多模态融合的想象空间

单纯的目标检测只能告诉你"哪里有叶片、健不健康",但农业决策往往需要更多信息。比如同样是病斑,早期和晚期的处理方式完全不同。这时候可以考虑多模态融合:可见光图像做检测,红外图像做温度分析,高光谱做成分分析。

我试过一个简化方案:用 YOLO 检测出叶片位置后,裁剪出叶片区域,送进一个分类网络做病害细分类。检测负责"在哪",分类负责"是什么",两级串联。这样做的好处是分类网络可以做得更深更准,因为输入已经是干净的叶片区域,没有背景干扰。缺点是速度会慢一些,但农业巡检对实时性要求没那么苛刻,几秒出一张图的结果完全可以接受。

再进一步,可以把检测结果和 GPS 坐标、时间戳结合,生成田间的病害分布热力图。哪片区域病斑密集,哪片区域健康,一目了然。这种空间信息对精准施药特别有价值,能大幅减少农药用量。

5.2 模型迭代与持续学习

农业场景有个特点:季节性强。番茄生长周期几个月,不同阶段叶片形态差异很大。你春天训的模型,到秋天可能就不太准了。所以落地系统一定要有持续学习的机制。

我的做法是:部署时开启一个"难例挖掘"模块,把模型置信度低或者人工复核发现错误的样本自动存下来,定期人工标注后加入训练集,重新训练。这样模型会随着使用越来越准,形成一个正向循环。

另外,不同品种的番茄叶片形态也有差异。如果你从一种番茄换到另一种,最好重新采集一批数据微调。直接迁移过去可能也能用,但精度会打折扣。微调时学习率设小一点,比如 0.0001,只训几十个 epoch,让模型适应新品种的特征,同时不忘记之前学的东西。

5.3 边缘端部署的工程细节

最后聊聊部署。农业现场往往网络条件差,不可能把图像传到云端推理,必须边缘端本地处理。硬件选型上,Jetson 系列是主流,Orin Nano 性价比不错,算力够跑 YOLOv8m。如果预算有限,树莓派加加速棒也能跑,但只能上 YOLOv8n 这种小模型,精度会降一些。

软件层面,建议用 Docker 打包环境,避免现场设备依赖问题。把模型、推理代码、预处理逻辑全部容器化,换设备时直接拉镜像就行。我吃过亏,现场设备 Python 版本和开发机不一致,跑起来各种报错,后来全部 Docker 化才省心。

功耗和散热也要考虑。大棚里夏天温度能到 40 度以上,边缘设备如果没有主动散热,很容易降频甚至死机。选型时留足散热余量,或者加个小风扇。这些细节看着不起眼,但真正落地时往往就是它们决定系统能不能稳定跑下去。

我个人在实际操作中的体会是,番茄叶片检测这个方向,数据集是起点不是终点。3100 张图能帮你跑通流程、验证想法,但真正要做好,还得结合具体场景不断迭代。别指望一个模型打天下,农业的复杂性远超实验室环境,多下地、多看真实数据、多和种植户聊,比闷头调参有用得多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进