免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

棉花病害检测数据集实战:YOLO标注格式解析与训练避坑指南

棉花病害检测数据集实战:YOLO标注格式解析与训练避坑指南 简介这份棉花植物病害图像目标检测数据集面向从事农业视觉检测、YOLO 系列模型训练与改进的开发者及学生提供可直接投入训练的真实标注样本。数据覆盖枯萎病、卷曲、灰霉、健康叶片、叶斑病等 6 个类别标签采用 YOLO 通用格式并已预先完成训练集、验证集与测试集划分省去自行清洗与切分的繁琐步骤。压缩包共约 2000 个文件以 1999 个 txt 标注文件和 1 个 show.py 可视化脚本为主整体约 156.57MB运行脚本即可快速查看图像与标注框的对应效果。目前已有 47 人学习关注适合作为目标检测课程设计、病害识别课题或模型对比实验的基础数据。借助该数据读者可完成从数据加载、类别统计到模型训练与评估的完整流程并配合作者主页的 YOLOv5 改进实战内容进一步验证注意力机制、特征融合等改进策略在农业场景下的实际效果。1. 棉花病害检测数据集4,600 张已标注图像能省掉多少前期脏活棉花叶片上的病斑早期跟健康组织的色差极小轮纹、褪绿、水渍状边缘混在一起肉眼在田间巡检时经常要凑到 20 厘米内才敢下判断。这份资源就是冲着这个场景来的约 4,600 张棉花植物病害图像全部完成目标检测标注直接给到 YOLO 格式的 txt 标签拿来就能进训练管线。它解决的不是模型结构问题而是目标检测里最耗人力的那一环——数据采集与标注。适合谁做农业视觉的算法工程师、要快速验证病害检测方案的学生、以及手上有 YOLO 训练流程但缺行业数据的从业者。你不需要从零拍图、标框、清洗拿到手先跑通 baseline再决定要不要扩数据。下面按「数据长什么样 → 怎么接进 YOLO → 坑在哪 → 怎么验证」的顺序拆开讲。2. YOLO 标注格式拆解从目录结构到类别映射的落地检查2.1 先看清一份 YOLO 检测数据集到底由什么组成目标检测数据集不是「一堆图加一堆 txt」这么简单。YOLO 格式的核心约定是每张图像对应一个同名 txt 文件txt 里每一行代表一个目标框格式为class_id x_center y_center width height后四个值都是相对图像宽高的归一化浮点数范围 0 到 1。这意味着标签本身不携带像素坐标读取时必须结合原图尺寸还原。这份棉花病害数据约 4,600 张按常见组织方式目录里通常会有images/和labels/两个平行文件夹再各自分train/、val/也可能直接平铺。拿到手第一件事不是训练是核对三件事图像与标签是否一一对应、类别 id 是否从 0 连续编号、归一化值有没有越界。我一般会先跑一段统计脚本把类别分布和框的尺寸分布打出来。棉花病害里如果某类病斑特别小框的宽高归一化后可能只有 0.02 到 0.05这种小目标在默认 640 输入下经过多次下采样后特征几乎消失是后面训练不收敛的高频原因。先看清分布再决定输入尺寸和 anchor 策略比盲目开训省时间。2.2 用脚本核对图像与标签的配对关系下面这段脚本做三件事遍历图像目录、检查同名标签是否存在、统计每个类别的框数量。放在数据集根目录运行即可。import os from collections import Counter from pathlib import Path IMG_EXTS {.jpg, .jpeg, .png, .bmp} root Path(.) # 数据集根目录按实际路径改 img_dir root / images lbl_dir root / labels missing_label, empty_label [], [] cls_counter Counter() box_sizes [] for img_path in img_dir.rglob(*): if img_path.suffix.lower() not in IMG_EXTS: continue # 标签路径把 images 替换成 labels后缀换成 .txt rel img_path.relative_to(img_dir).with_suffix(.txt) lbl_path lbl_dir / rel if not lbl_path.exists(): missing_label.append(str(img_path)) continue lines [l.strip() for l in lbl_path.read_text().splitlines() if l.strip()] if not lines: empty_label.append(str(img_path)) continue for line in lines: parts line.split() if len(parts) ! 5: print(格式异常:, lbl_path, line) continue cid int(float(parts[0])) w, h float(parts[3]), float(parts[4]) cls_counter[cid] 1 box_sizes.append((w, h)) print(缺失标签数:, len(missing_label)) print(空标签数:, len(empty_label)) print(类别分布:, dict(sorted(cls_counter.items()))) if box_sizes: ws sorted(s[0] for s in box_sizes) hs sorted(s[1] for s in box_sizes) print(框宽中位数:, ws[len(ws)//2], 框高中位数:, hs[len(hs)//2]) print(最小框宽:, ws[0], 最小框高:, hs[0])逻辑说明rglob(*)递归遍历兼容train/val子目录结构标签路径用relative_to加with_suffix推导避免手写字符串替换出错。参数说明IMG_EXTS按你实际拿到的图像后缀调整如果数据里混了.tif要补进去cls_counter输出的是每个类别 id 的框总数正常情况应该是连续编号且没有某个 id 为 0box_sizes的中位数和最小值直接告诉你小目标占比最小框宽低于 0.03 就要警惕。2.3 类别名与 data.yaml 的对应关系YOLO 训练不认类别名只认 id但评估和可视化需要名字。所以必须有一份data.yaml把 id 映射回病害名称。这份数据如果没附带 yaml你得自己按标注时的类别顺序补。常见棉花病害类别大致是枯萎病、黄萎病、叶斑病、红腐病这类但具体以数据实际标注为准不要凭经验硬套。# data.yaml path: ./cotton_disease # 数据集根目录 train: images/train val: images/val nc: 4 # 类别数按实际改 names: 0: fusarium_wilt 1: verticillium_wilt 2: leaf_spot 3: red_rot参数说明nc必须等于 names 的条目数写错会在训练启动时报维度不匹配train和val是相对path的路径别写成绝对路径换机器会崩。如果数据只有 train 没有 val常见做法是从 train 里按 8:2 切一份出来切的时候要连图像带标签一起移动不能只移图像。3. 接进 YOLOv8 训练管线环境、配置与首轮 baseline3.1 环境配置与依赖版本选择YOLOv8 走 ultralytics 包环境比早期 YOLOv5 干净很多。Anaconda 建环境时 Python 选 3.9 或 3.10 最稳3.11 以上偶尔会遇到某些依赖轮子没跟上。CUDA 版本跟你的显卡驱动匹配即可不强制最新。装的时候一条命令搞定但要注意它会把 torch 一起拉下来如果你机器上已有特定 torch 版本先确认会不会被覆盖。conda create -n cotton_yolo python3.10 -y conda activate cotton_yolo pip install ultralytics # 验证安装与 GPU 可见性 yolo checks逻辑说明yolo checks会打印 ultralytics 版本、torch 版本、CUDA 是否可用、显卡型号。这一步别跳过很多「训练报错」其实是环境根本没认到 GPU跑在 CPU 上慢到怀疑人生。参数说明如果yolo checks显示 CUDA 不可用先查驱动再查 torch 是不是 CPU 版pip install ultralytics默认装最新版若你要复现某个特定版本行为用pip install ultralytics8.x.x锁版本。3.2 首轮训练命令与关键参数baseline 不要一上来就调参先用默认配置跑通确认数据管线没问题。下面这条命令是最小可用集。yolo detect train \ data./cotton_disease/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectruns/cotton \ namebaseline逻辑说明modelyolov8n.pt用 nano 版先跑通速度快、显存占用低适合验证数据device0指定第一块 GPU多卡用device0,1。参数说明imgsz640是默认输入尺寸如果 2.2 节统计出小目标很多可以提到 1024但显存和速度要重新评估batch16在 8G 显存上跑 640 一般够报 OOM 就降到 8 或 4epochs100对 4,600 张数据通常够看到趋势但别拿它当最终结果先看 loss 曲线和 mAP 有没有正常下降上升。训练启动后重点盯三个输出box_loss是否稳定下降、cls_loss是否发散、验证集 mAP50 是否在 20 个 epoch 后有起色。如果 box_loss 一直平多半是标签归一化有问题如果 cls_loss 震荡剧烈可能是类别不平衡或学习率偏大。3.3 从训练日志判断数据质量YOLOv8 会在runs/cotton/baseline/下生成results.csv和混淆矩阵图。results.csv每行一个 epoch列里有train/box_loss、metrics/mAP50、metrics/mAP50-95。我一般会先看 mAP50 的爬升曲线正常数据在 30 到 50 epoch 应该能看到明显上升如果 100 epoch 还在 0.1 以下先别怀疑模型回去查标签。混淆矩阵能告诉你哪两类在互相误判棉花病害里叶斑和轮纹斑如果标注边界模糊这两类混淆是常态属于数据本身的问题不是训练能救的。提示首轮训练不要开数据增强的激进配置默认增强已经够用。等 baseline 跑通、确认标签无误后再考虑加 mosaic、mixup 或调整 anchor。4. 避坑与排查这份数据最容易翻车的五个地方4.1 标签归一化值越界或坐标系搞反现象训练启动不报错但 box_loss 居高不下预测框全部挤在图像中心或飞出边界。原因标注工具导出时用了像素坐标没归一化或者把x_center y_center写成了x_min y_min。YOLO 只认归一化中心点格式像素坐标直接喂进去数值大于 1模型学到的就是错误分布。解决跑 2.2 的脚本加一段检查0 x 1的逻辑越界的行打印出来用脚本批量转换或退回标注工具重新导出。4.2 图像与标签文件名大小写或后缀不一致现象脚本统计显示「缺失标签数」很高但你去文件夹里看明明有对应 txt。原因图像是.JPG大写标签是.jpg.txt或.txt或者文件名里有多余空格。Linux 下大小写敏感Windows 下不敏感跨平台搬运就会翻车。解决统一后缀为小写标签命名严格用「图像主名 .txt」不要带原后缀。批量重命名用脚本处理别手动改。4.3 类别 id 不连续或从 1 开始现象训练时提示Label class X exceeds nc或者某一类永远学不出来。原因标注时类别从 1 开始编号而 YOLO 要求从 0 开始且连续或者中间某个 id 没有样本nc设成了最大 id 加一导致空类占位。解决统计实际出现的 id重新映射成 0 到 n-1 连续编号同步改data.yaml的nc和names。映射关系要记录别改完自己都忘了哪个 id 对应哪种病。4.4 训练集与验证集图像重复导致指标虚高现象验证集 mAP 高得离谱部署到新图上效果断崖式下跌。原因切分时随机打乱同一张图或同一株棉花的连拍图同时进了 train 和 val模型等于见过验证集。解决按拍摄批次或植株 id 切分同一来源的图只进一个集合。如果数据没有批次信息至少做一次图像哈希去重把重复图剔掉再切。4.5 小目标病斑在默认输入下丢失现象大斑块检测正常早期小病斑全部漏检。原因640 输入下归一化宽高小于 0.03 的框经过 backbone 下采样后特征图上的响应只剩一两个像素。解决提高imgsz到 1024 或 1280或者改用带 P2 小目标检测层的模型结构。提高输入尺寸会显著增加显存和推理耗时部署前要权衡。5. 验证与进阶用混淆矩阵和置信度门限把模型调到能用训练跑完不等于能用。我习惯在部署前强制走一遍验证流程第一步是拿val集跑yolo detect val看每个类别的 P、R、mAP50。棉花病害里如果某类召回率特别低先别调模型回去看这类样本量是不是太少。4,600 张里如果某类只有一两百框属于长尾常见做法是过采样或加类别权重但更稳的是补数据。第二步是调置信度门限。默认conf0.25对农业检测偏保守漏检多调到 0.1 能捞回小病斑但误检会上升。我的做法是画一条 P-R 曲线找 F1 最大的点作为门限而不是拍脑袋。下面这段脚本用验证集预测结果算不同门限下的 F1。from ultralytics import YOLO import numpy as np model YOLO(runs/cotton/baseline/weights/best.pt) results model.val(data./cotton_disease/data.yaml, conf0.001, iou0.6) # results.box 里含每个类别的 precision/recall 曲线数据 # 实际调门限时遍历 conf 从 0.05 到 0.5取 F1 最大点 for conf in np.arange(0.05, 0.55, 0.05): r model.val(data./cotton_disease/data.yaml, conffloat(conf), verboseFalse) p, rec r.box.mp, r.box.mr f1 2 * p * rec / (p rec 1e-9) print(fconf{conf:.2f} P{p:.3f} R{rec:.3f} F1{f1:.3f})逻辑说明conf0.001先跑一次拿全量预测再逐门限评估r.box.mp和r.box.mr是 ultralytics 返回的平均精度和平均召回。参数说明iou0.6是 NMS 的 IoU 阈值检测密集小目标时可以降到 0.5 减少框合并门限最终值要结合业务宁可误检不可漏检的场景就选召回高的点。第三步是看混淆矩阵。runs/cotton/baseline/下会有confusion_matrix.png横轴预测、纵轴真实。如果叶斑和轮纹斑互相误判严重说明这两类在视觉上确实接近要么合并类别要么在数据里补充区分性强的样本。这一步没有捷径只能对着矩阵一类一类看。最后说个我自己的习惯每次拿到新数据集不管多急都先跑一遍配对检查和类别统计再切一小份 200 张的子集做 10 epoch 快速验证。子集能跑通、loss 正常下降再上全量。这个习惯帮我挡掉过好几次标签格式错误和路径写错的问题省下的返工时间远超那十分钟。希望这份棉花病害数据能帮你把前期脏活压缩掉把精力留给模型和业务本身。本文还有配套的精品资源点击获取
返回列表