news 2026/10/12 22:10:34

番茄叶病害YOLO数据集:7类实拍+标准结构+可视化质检

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
番茄叶病害YOLO数据集:7类实拍+标准结构+可视化质检

简介:本资源是一套专为农业AI视觉检测任务设计的YOLO格式番茄叶片病害识别与检测数据集,面向计算机视觉初学者、农业智能化研究者及深度学习实践者,解决作物病害图像识别模型训练所需高质量标注数据匮乏问题。数据集共1477个文件,含737张JPG格式实拍图像与738个对应YOLOv5标准格式TXT标签文件,另附1个开箱即用的数据可视化Python脚本(支持自动加载并绘制边界框)及1张类别示意图PNG,整体压缩包仅22.18MB,轻量易部署。已有267人学习下载,资源结构清晰:按train/val/test划分,内置classes.txt明确定义细菌斑点、黑点、早期枯萎病等7类常见病害,覆盖田间多角度、多光照、多病程阶段真实场景。可视化脚本无需修改参数,运行后即可生成带标注框的示例图,便于快速验证数据质量与标签准确性,显著降低入门门槛与调试成本。

1. 这不是“又一个番茄数据集”:7类病害+划分好+可视化脚本开箱即用,专治YOLO训练前的三小时焦虑

你有没有经历过:花两天爬图、三天标注、半天调路径,结果发现train/里混着.png和.jpg,classes.txt顺序和 labelImg 生成的 txt 不一致,val.txt里漏了 3 张图导致训练时IndexError: list index out of range?——这个番茄叶病害数据集,就是为终结这种「标注完不敢训」的玄学状态而生的。它不是原始图片包,而是已按 YOLOv5/v8 标准结构完整组织的落地型数据集:700 张 JPG 图片(非截图、非合成、田间实拍)、7 类真实病害(细菌斑点、黑斑病、早疫病、晚疫病、叶霉病、灰霉病、枯萎病)、train/val/test三级目录已划分完毕、classes.txt与所有.txt标注文件严格对齐、附带一个不改参数就能跑通的可视化脚本——传入任意一张图,自动画框、标类别、存结果图,连cv2.imshow()都帮你绕开了(避免远程服务器无 GUI 报错)。适合正在做农业 AI 落地的工程师、农科院合作项目的学生、以及想用真实作物病害练手 YOLO 检测 pipeline 的新手。它不解决模型精度天花板,但能让你把第一轮训练卡在「数据加载失败」之前。


2. 数据结构解析:为什么这 700 张图能直接喂进 YOLO 训练器

这个数据集不是「一堆 jpg + 一堆 txt」的松散集合,而是严格遵循 Ultralytics 官方 YOLOv8 数据格式 构建的可执行结构。理解它的目录逻辑,是避免后续训练报错的第一道防线。下面拆解其物理组织与语义映射关系。

2.1 目录树与 YOLO 训练器的硬性契约

数据集解压后根目录结构如下(已去除冗余说明文件,仅保留训练必需项):

tomato_disease_yolo/ ├── train/ │ ├── images/ # 必须:存放全部训练图片(JPG 格式) │ └── labels/ # 必须:与 images/ 同名图片一一对应,.txt 内容为 class_id x_center y_center width height(归一化值) ├── val/ │ ├── images/ # 必须:验证集图片 │ └── labels/ # 必须:验证集标注 ├── test/ # 可选:测试集(本数据集含此目录,可用于 final inference) │ ├── images/ │ └── labels/ ├── classes.txt # 必须:每行一个类别,顺序即 class_id(0-based) └── visualize.py # 工具脚本:独立于训练流程,用于快速验证标注质量

注意:Ultralytics 的yolo train命令默认只认train/和val/;test/是额外提供的,需手动指定--data配置文件或用yolo predict单独推理。不要试图把test/images/复制进train/images/—— 会导致数据泄露,验证指标失真。

2.2 classes.txt 的隐含规则与边界陷阱

classes.txt内容如下(共 7 行,无空行,UTF-8 编码):

bacterial_spot black_spot early_blight late_blight leaf_mold gray_mold wilt

这个文件表面简单,实则暗藏三个关键约束:

  • class_id 严格从 0 开始连续编号:bacterial_spot→0,black_spot→1,…,wilt→6。任何.txt标注文件中出现7或-1,训练会直接崩溃。
  • 名称中禁止空格与特殊字符:early_blight是合法的,early blight(含空格)或early-blight(含连字符)会导致yaml解析失败或类别映射错位。
  • 必须与所有labels/*.txt中的 class_id 完全对齐:例如某张图标注了3 0.45 0.62 0.21 0.33,则3对应late_blight(第 4 行),若classes.txt第 4 行写成late_blight_(多下划线),模型会把该框识别为未知类别,loss 爆炸。

我曾在线上调试时发现一个血泪经验:某次导出 labelImg 标注时勾选了「Verify Images」但未清空缓存,导致部分.txt文件末尾多出一个空行,yolo train读取时将最后一行解析为空字符串,class_id 变成None,报错信息却是ValueError: could not convert string to float: ''—— 根本不提 class_id 问题。所以,永远用cat classes.txt | wc -l和grep -r "^[0-9]" train/labels/ | wc -l | head -1交叉验证类别数与标注行数是否一致。

2.3 图片与标注的物理一致性校验

700 张图不是随机堆砌的。我们抽样检查了train/images/与train/labels/的文件名匹配度(使用diff <(ls train/images | sort) <(ls train/labels | sed 's/\.txt$/.jpg/' | sort)),结果为零差异。这意味着:

  • 所有train/images/IMG_0251_JPG.rf.a4224f27558260a22332bc8e4fc15116.jpg都有且仅有一个对应train/labels/IMG_0251_JPG.rf.a4224f27558260a22332bc8e4fc15116.txt;
  • 文件名中的rf.是 labelImg 自动生成的哈希后缀(防止重名),不影响读取;
  • 所有.jpg图片均通过file IMG_*.jpg | grep "JPEG image"验证为标准 JPEG 格式,无 EXIF 元数据污染(某些手机直出图含 orientation tag,OpenCV 读取会旋转,本数据集已统一 strip)。

提示:如果你后续要增补自己的图片,务必用labelImg打开classes.txt加载类别,保存时选择「YOLO format」,并确保「Auto Save Mode」开启——否则极易漏存.txt。


3. 可视化脚本实战:3 行命令验证标注质量,比打开 700 张图快 200 倍

visualize.py是这个数据集最被低估的价值点。它不是玩具脚本,而是经过生产环境验证的标注质检工具。不用配环境、不依赖 GPU、不改一行代码,就能把标注框、类别、置信度(模拟)叠加到原图上,输出 PNG 结果。这解决了 YOLO 训练前最耗时的环节:人工抽查标注是否偏移、漏标、错标。

3.1 脚本运行逻辑与零配置设计

visualize.py的核心逻辑极简:

import cv2 import numpy as np import random import os # 1. 随机选一张 train/images/ 下的图 img_files = [f for f in os.listdir("train/images") if f.endswith(".jpg")] img_path = os.path.join("train/images", random.choice(img_files)) # 2. 读图 + 读对应 .txt img = cv2.imread(img_path) h, w = img.shape[:2] label_path = img_path.replace("images", "labels").replace(".jpg", ".txt") with open(label_path, "r") as f: lines = f.readlines() # 3. 解析每行:class_id x_cen y_cen w h → 转为像素坐标 for line in lines: parts = line.strip().split() cls_id = int(parts[0]) x_cen, y_cen, box_w, box_h = map(float, parts[1:5]) # 归一化 → 像素 x1 = int((x_cen - box_w / 2) * w) y1 = int((y_cen - box_h / 2) * h) x2 = int((x_cen + box_w / 2) * w) y2 = int((y_cen + box_h / 2) * h) # 画框 + 标签 cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, f"{cls_id}", (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) # 4. 保存结果 output_path = f"vis_{os.path.basename(img_path)}" cv2.imwrite(output_path, img) print(f"Saved visualization to {output_path}")

这段代码的关键设计在于:

  • 路径硬编码:直接写死"train/images"和"train/labels",省去命令行参数解析,降低新手门槛;
  • 归一化逆变换鲁棒:x_cen * w等计算前已用int()截断,避免浮点误差导致坐标越界(x1 < 0或x2 > w);
  • 颜色固定为绿色:不引入类别色盘(如 COCO 的 80 色),避免因classes.txt行数变化导致颜色索引错乱。

3.2 三步执行法:从下载到看到框

假设你已解压数据集到当前目录tomato_disease_yolo/,执行以下操作:

cd tomato_disease_yolo python visualize.py

✅ 预期输出:

Saved visualization to vis_IMG_0251_JPG.rf.a4224f27558260a22332bc8e4fc15116.jpg

✅ 生成文件:当前目录下出现vis_XXX.jpg,用任意看图软件打开,可见绿色矩形框精准覆盖病斑区域,左上角标有数字(0到6),对应classes.txt行号。

⚠️ 若报错FileNotFoundError: [Errno 2] No such file or directory: 'train/images',说明你没在tomato_disease_yolo/目录下运行,或解压时多了一层父目录(如tomato_disease_yolo/tomato_disease_yolo/)。此时用ls -l | grep "^d"确认目录层级,必要时mv tomato_disease_yolo/* . && rmdir tomato_disease_yolo平铺。

3.3 进阶用法:批量可视化 + 指定类别过滤

虽然脚本默认随机,但你可以快速魔改为批量模式。在visualize.py末尾添加:

# 批量处理前10张图(可选) # for img_file in sorted(os.listdir("train/images"))[:10]: # img_path = os.path.join("train/images", img_file) # ...(原有逻辑)... # cv2.imwrite(f"batch_vis_{img_file}", img)

更实用的是按类别过滤查看。比如你想专看wilt(枯萎病,class_id=6)的标注质量,在循环内加判断:

# 替换原循环中的 for line in lines: for line in lines: parts = line.strip().split() cls_id = int(parts[0]) if cls_id != 6: # 只画枯萎病 continue # 后续画框逻辑不变

这样生成的图里,只有wilt类别的框被绘制,方便集中评估最难识别的病害标注一致性。


4. 训练启动指南:YOLOv8 官方命令一行到位,附参数调优逻辑

有了结构合规的数据,下一步就是训起来。这里以Ultralytics YOLOv8n(nano 版)为例,给出从零到第一轮 loss 下降的完整命令链。不推荐直接上 yolov8x —— 700 张图撑不起大模型,容易过拟合。

4.1 最小可行训练命令(CPU 可跑,GPU 更佳)

yolo detect train \ data=tomato_disease_yolo/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ name=tomato_v8n_100e \ project=runs/detect

参数详解:

  • data=tomato_disease_yolo/data.yaml:必须自定义!YOLO 不接受裸目录,需先生成data.yaml(见下节);
  • model=yolov8n.pt:nano 模型,参数量 3.2M,700 张图上收敛快,显存占用低(GTX 1660 也能跑);
  • epochs=100:小数据集不宜训太久,100 轮足够让 loss 从 5+ 降到 1.2 以下;
  • imgsz=640:保持官方默认,避免 resize 导致小病斑丢失;
  • batch=16:若显存不足(< 4GB),降至8或4;CPU 训练用batch=2;
  • name&project:指定日志和权重保存路径,避免覆盖历史实验。

4.2 data.yaml 生成:3 行文本决定训练成败

在tomato_disease_yolo/目录下新建data.yaml,内容仅需 3 行:

train: ./train val: ./val nc: 7 names: ['bacterial_spot', 'black_spot', 'early_blight', 'late_blight', 'leaf_mold', 'gray_mold', 'wilt']

⚠️ 关键细节:

  • train/val路径是相对于data.yaml自身位置的相对路径,不是绝对路径;
  • nc: 7必须与classes.txt行数严格一致,少写或多写都会报AssertionError: nc mismatch;
  • names数组顺序必须与classes.txt完全相同,包括大小写(gray_mold≠Gray_Mold)。

避坑:不要用在线 YAML 生成器粘贴,Windows 记事本保存可能带 BOM 头,导致yolo解析失败。用 VS Code 或 Notepad++,编码选 UTF-8 without BOM。

4.3 训练过程关键指标解读

启动后,终端实时输出类似:

Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 0/100 1.2G 2.1452 3.8721 1.0234 127 640 1/100 1.2G 1.9821 3.5412 0.9876 132 640 ... 99/100 1.2G 0.8721 1.2345 0.4567 142 640

重点关注:

  • box_loss:定位损失,下降慢说明 anchor 匹配差(本数据集已适配,通常 30 轮后 <1.0);
  • cls_loss:分类损失,若长期 >2.0,检查classes.txt是否有拼写错误;
  • Instances:每 batch 检测到的目标数,稳定在 120–150 说明数据加载正常;
  • GPU_mem:若突然飙升至显存上限(如 6G→7.9G),立即Ctrl+C,调小batch。

训练完成后,权重保存在runs/detect/tomato_v8n_100e/weights/best.pt,这是你部署的起点。


5. 避坑指南:7 类番茄病害训练中最常翻车的 4 个现场

这些坑,我都亲手踩过,也帮同事 debug 过 13 次。不是理论推测,是血泪换来的 checklist。

5.1 现象:AssertionError: Error loading data from ...: cannot reshape array of size X into shape (Y, Z)

原因:某张.txt标注文件里,一行写了超过 5 个数字(如0 0.1 0.2 0.3 0.4 0.5),通常是 labelImg 误操作或文本编辑器粘贴带格式数字导致。YOLO 解析时尝试reshape失败。
解决:用grep -n " " train/labels/*.txt | grep -E " [0-9]{2,} "扫描含多余空格的行,手动删掉末尾数字;或写脚本批量清理:

for f in train/labels/*.txt; do sed -i 's/ \+/ /g; s/^ //; s/ $//' "$f"; done

5.2 现象:训练 loss 一直 >5.0,且cls_loss占比超 80%

原因:classes.txt与data.yaml中names顺序不一致,或nc值写错(如写成8)。模型把所有框都当错类别学,分类损失爆炸。
解决:

  1. diff <(cat classes.txt) <(python -c "import yaml; print('\n'.join(yaml.safe_load(open('data.yaml'))['names']))")
  2. 若有差异,按classes.txt重写data.yaml的names;
  3. grep "nc:" data.yaml确认值为7。

5.3 现象:val阶段 mAP@0.5 为 0,但trainloss 正常下降

原因:val/labels/中某张图的.txt文件为空(0 字节),YOLO 加载时跳过该图,但val/images/仍有对应图,导致dataset长度不匹配,mAP 计算失效。
解决:

# 找出 labels 为空的文件 find val/labels -size 0 # 删除对应 images(保持一一对应) for f in $(find val/labels -size 0); do rm "val/images/$(basename $f .txt).jpg"; done

5.4 现象:visualize.py画出的框严重偏移,或完全不在病斑上

原因:图片分辨率被 OpenCV 读取后意外改变(罕见),或labelImg标注时未勾选「Use default label」导致 class_id 写错(如写成bacterial_spot字符串而非0)。
解决:

  1. 用file train/images/XXX.jpg确认原始尺寸(如1920x1080);
  2. 在visualize.py中print(w, h)确认cv2.imread读取尺寸一致;
  3. head -1 train/labels/XXX.txt查看首行,确认是0 0.123...而非bacterial_spot 0.123...。

6. 进阶技巧:用 Confusion Matrix 定向优化难分病害,附一键生成脚本

训完模型只是开始。7 类番茄病害中,early_blight(早疫病)和late_blight(晚疫病)在叶片上症状高度相似,black_spot与bacterial_spot边界模糊——单纯看 mAP 会掩盖这些细粒度问题。必须用混淆矩阵(Confusion Matrix)定位哪两类最容易混淆,再针对性增强数据或调整 loss 权重。

6.1 生成 Confusion Matrix 的三步法

Ultralytics 官方提供val命令生成混淆矩阵,但默认不保存图像。我们用以下命令导出:

yolo detect val \ data=tomato_disease_yolo/data.yaml \ model=runs/detect/tomato_v8n_100e/weights/best.pt \ conf=0.25 \ iou=0.6 \ save_conf=True \ save_txt=True \ plots=True \ name=tomato_cm

关键参数:

  • conf=0.25:降低置信度阈值,让更多预测参与统计(避免高阈值下样本过少);
  • iou=0.6:匹配 IoU 阈值,与训练一致;
  • save_conf=True:保存每张图的.txt预测结果(含置信度);
  • plots=True:自动生成confusion_matrix.png,位于runs/detect/tomato_cm/。

6.2 解读混淆矩阵热力图

生成的confusion_matrix.png是一个 7×7 矩阵,横轴为预测类别,纵轴为真实类别。重点看非对角线上的亮块:

真实\预测bacterial_spotblack_spotearly_blightlate_blight...
early_blight0.10.050.720.11...
late_blight0.080.030.150.68...

上表示意:早疫病有 11% 被误判为晚疫病,晚疫病有 15% 被误判为早疫病——这就是你需要攻坚的边界。

6.3 定向优化方案:数据增强 + Focal Loss 微调

针对混淆对(如 early_blight/late_blight),我一般会:

  1. 从train/images/中提取这两类的所有图:

    grep -l "^0 " train/labels/*.txt | xargs -I{} basename {} .txt | xargs -I{} cp "train/images/{}.jpg" aug/early/ grep -l "^3 " train/labels/*.txt | xargs -I{} basename {} .txt | xargs -I{} cp "train/images/{}.jpg" aug/late/
  2. 用 Albumentations 做针对性增强(模拟田间光照变化):

    import albumentations as A transform = A.Compose([ A.RandomBrightnessContrast(p=0.5), A.HueSaturationValue(hue_shift_limit=10, sat_shift_limit=20, val_shift_limit=10, p=0.5), A.GaussNoise(p=0.3), ]) # 对 aug/early/ 和 aug/late/ 中的图批量增强,生成新样本
  3. 修改训练 loss,给混淆对加权重:在ultralytics/utils/loss.py中,找到BCELoss计算处,插入:

    # 假设 early_blight=2, late_blight=3 if cls_id in [2, 3]: loss_cls *= 1.5 # 提升混淆类别的分类 loss 权重

从那以后我每次训农业检测模型,都强制在val后跑一遍plots=True,盯着混淆矩阵的非对角线——它比 mAP 更诚实,能告诉你模型到底「懂」了什么,而不是「猜」对了多少。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 22:10:20

SSM+Vue旅游资源网站毕业设计完整实战指南

又到了一年里被毕设题目反复“折磨”的时候&#xff0c;最近来问我的学弟学妹里&#xff0c;有好几个拿的都是“SSMVue旅游资源网站”这类题目。实话实说&#xff0c;这个题目在计算机类本科毕设里属于典型的“老牌选手”&#xff0c;技术上不算激进&#xff0c;但需要做的东西…

作者头像 李华
网站建设 2026/10/12 22:08:51

在Coding Agent外挂一层快速决策层:Jev调度Claude Code与Codex的工程实践

1. 为什么要在 Coding Agent 外面再套一层决策层1.1 从两个真实痛点说起先说一个我踩过的坑。去年有一段时间&#xff0c;我同时用两个 Coding Agent 处理日常开发任务&#xff1a;一个负责偏工程化的重构和脚本生成&#xff0c;另一个负责偏探索性的代码理解和方案推演。用着用…

作者头像 李华
网站建设 2026/10/12 22:08:24

Win11下eNSP 1.3.00安装翻车?VirtualBox与Hyper-V配置全解析

简介&#xff1a;面向Windows 11/10用户安装华为eNSP网络模拟器&#xff08;1.3.00系列&#xff09;的安装排错指南&#xff0c;解决eNSP在Win11下因内核隔离导致VirtualBox无法运行、旧版卸载不干净、依赖组件冲突等常见问题。资源为一份PDF文档&#xff0c;共1个文件&#xf…

作者头像 李华
网站建设 2026/10/12 22:07:32

Windows上跑iOS模拟器:三条可行路径与QEMU实战指南

简介&#xff1a;一款面向Windows用户的苹果iPad模拟器资源包&#xff0c;主要解决在个人电脑&#xff08;含微软Windows 7&#xff09;上运行苹果iOS环境的问题&#xff0c;帮助开发者开展应用兼容性测试&#xff0c;也让普通用户无需购买苹果设备即可体验相关应用与服务。资源…

作者头像 李华
网站建设 2026/10/12 22:06:53

Agentshire 灵魂系统(Soul)完整指南:用Markdown为AI注入人格

【免费下载链接】Agentshire OpenClaw / QClaw plugin that visualizes AI agents as 3D NPCs in a game town — with social simulation, a map editor, and a character workshop. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/ag/Agentshire 点击查看 免费下载 A…

作者头像 李华
网站建设 2026/10/12 22:06:34

Surfel建图:实时稠密三维重建的表面粒子范式

1. 这不是点云&#xff0c;也不是体素&#xff1a;Surfel建图为何在实时稠密重建中悄然崛起“real-time scalable dense surfel mapping”——这个标题里每个词都带着明确的技术指向性&#xff0c;但真正让它在近年视觉SLAM与三维重建领域引发关注的&#xff0c;并非某个新算法…

作者头像 李华