ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLO实例分割实战:290张农作物病害数据集训练避坑指南

YOLO实例分割实战:290张农作物病害数据集训练避坑指南 简介这份农作物病害实例分割数据集面向农业AI诊断、精准农业监测及植物病理学交叉研究场景适合从事YOLO实例分割任务开发的中高级算法工程师与农业科技研究者使用。资源包共582个文件以290张jpg图像与290个txt标注文件为主体另含1个yaml配置文件与1份docx说明文档压缩包约58.81MB标注采用YOLO多边形格式精确勾勒病害区域边界。数据集总计290张图片其中训练集258张、验证集23张、测试集9张覆盖细菌性枯萎病、褐条病与花叶病三类典型病害兼顾细菌性与病毒性病害的代表性。目前已有89人学习下载。读者可借助该数据集直接开展实例分割模型训练与验证用于构建自动识别和分割植物病害区域的AI系统也可集成至农业物联网平台实现实时病害检测或作为农业院校植物病害识别课程的教学素材为病害早期诊断与产量提升提供可靠数据支撑。1. 农作物病害实例分割数据集290 张图、3 类病害能不能直接喂给 YOLO拿到一个只有 290 张图的农业病害实例分割数据集第一反应往往是「这么小能训出什么」。但如果你正在做农作物病害识别方向的产品原型或者手头只有分类数据集、想往实例分割任务上迁移这个包反而值得先拆开看看。它覆盖 Bacterialblight细菌性枯萎病、BrownStreakDisease褐条病、MosaicDisease花叶病三类典型病害标注走的是 YOLO 多边形格式训练集 258 张、验证集 23 张、测试集 9 张图片是常见的 JPEG/PNG。说白了这是一份能让你在半天内跑通「数据加载 → 实例分割训练 → 推理可视化」全链路的轻量数据集适合做农业 AI 诊断的早期验证、课程设计或者作为自建数据集的格式参照。它不解决精度天花板问题但能帮你把流程先立住。2. YOLO 实例分割标注格式拆解从多边形坐标到 data.yaml2.1 实例分割标注和检测标注到底差在哪目标检测的 YOLO 标签一行是class x_center y_center width height五个值框住目标就行。实例分割多了一步它要描述目标的轮廓所以标签行变成class x1 y1 x2 y2 ... xn yn后面跟的是归一化到 0~1 的多边形顶点序列。这个差别直接决定了损失函数里多了一项 mask 分支也决定了你在评估时不能只看 mAP50还得看 mask mAP。这份数据集标注的是病害区域边界不是整片叶子。也就是说同一张图里如果有多处病斑会有多行标签每行对应一个实例。常见做法是每个病斑单独成实例而不是把整株作物框成一个目标。这一点在农业场景里很关键——病斑面积占比往往很小如果按整叶标注模型学到的其实是「叶子在哪」而不是「病在哪」。提示拿到标注后先统计每张图的实例数分布。如果大部分图只有 1 个实例说明标注粒度偏粗训练时可以考虑加大 mosaic 增强来提升小目标召回。2.2 目录结构怎么摆才能被 YOLO 直接认YOLO 系列v5/v8/v11对目录结构有约定不按这个摆训练脚本第一步就报找不到图片。推荐这样组织dataset/ ├── images/ │ ├── train/ # 258 张 │ ├── val/ # 23 张 │ └── test/ # 9 张 ├── labels/ │ ├── train/ # 与 images/train 同名 .txt │ ├── val/ │ └── test/ └── data.yaml图片和标签必须同名只是扩展名不同。比如Mkundi-41-_JPG.jpg对应Mkundi-41-_JPG.txt。如果解压后发现标签全堆在一个文件夹里得先按文件名前缀或原始划分清单拆开。这一步没有捷径写个脚本按 258/23/9 的数量切或者直接沿用压缩包里已有的划分。import os, shutil, random src_img raw/images src_lbl raw/labels dst dataset # 按 258/23/9 划分固定随机种子保证可复现 random.seed(42) names [f for f in os.listdir(src_img) if f.lower().endswith((.jpg, .png))] random.shuffle(names) splits {train: names[:258], val: names[258:281], test: names[281:]} for split, files in splits.items(): os.makedirs(f{dst}/images/{split}, exist_okTrue) os.makedirs(f{dst}/labels/{split}, exist_okTrue) for f in files: stem os.path.splitext(f)[0] shutil.copy(f{src_img}/{f}, f{dst}/images/{split}/{f}) lbl f{stem}.txt if os.path.exists(f{src_lbl}/{lbl}): shutil.copy(f{src_lbl}/{lbl}, f{dst}/labels/{split}/{lbl})这段脚本做了三件事固定随机种子、按数量切分、图片和标签同步搬运。参数上random.seed(42)是为了让每次运行划分一致避免「这次训得好下次训得差」的玄学。splits里的切片索引直接对应 258/23/9如果你的实际文件数对不上先数一遍再改。2.3 data.yaml 里三个类别名不能写错path: ./dataset train: images/train val: images/val test: images/test names: 0: Bacterialblight 1: BrownStreakDisease 2: MosaicDiseasenames的索引必须和标签文件里第一列的数字严格对应。如果标签里写的是 0/1/2而 yaml 里顺序写反了模型会把褐条病学成花叶病评估指标看着还行实际推理全错。这种坑不报错只能靠可视化抽查发现。path用相对路径时训练命令要在 dataset 的上一级目录执行否则找不到文件。3. 用 YOLOv8-seg 跑通训练命令行参数与显存取舍3.1 模型选型n/s/m 三档怎么挑290 张图属于小样本直接上 yolov8m-seg 或 l-seg 大概率过拟合。常见做法是从 yolov8n-seg 起步它的参数量小、收敛快适合先验证数据管线和标注质量。如果 n 档训完 mask mAP50 能到 0.5 以上再考虑换 s 档看有没有提升。m 档以上在这个数据量下基本是浪费显存。模型参数量建议 batch适用判断yolov8n-seg3.4M16首选快速验证yolov8s-seg11.8M8n 档收敛后再试yolov8m-seg27M4数据量翻倍后再考虑显存不够时优先降 batch不要降 imgsz。实例分割对分辨率敏感病斑本身占像素少imgsz 降到 320 以下 mask 分支基本学不到东西。3.2 训练命令与关键参数yolo segment train \ datadataset/data.yaml \ modelyolov8n-seg.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ patience30 \ augmentTrue \ mosaic1.0 \ projectruns/seg \ namecrop_disease_v1逐项说epochs150对小数据集不算多配合patience30早停避免无效训练。lr00.01是 YOLOv8 的默认初始学习率小数据集可以降到 0.005 减少震荡。mosaic1.0开启马赛克增强对增加小目标样本多样性有帮助但实例分割里 mosaic 会裁剪多边形如果发现 mask 边缘异常可以降到 0.5。imgsz640是精度和显存的平衡点290 张图在 8G 显存卡上 batch16 能跑。训练过程中重点看两个指标metrics/mAP50-95(B)和metrics/mAP50-95(M)。B 是框M 是掩码。如果 B 涨但 M 不涨说明标注的多边形质量有问题或者 mask 分支学习率需要单独调。3.3 推理验证别只看 loss 曲线训练完必须做可视化推理loss 下降不代表模型学到了正确区域。from ultralytics import YOLO model YOLO(runs/seg/crop_disease_v1/weights/best.pt) results model.predict( sourcedataset/images/test, conf0.25, iou0.5, saveTrue, projectruns/predict, nametest_vis ) # 打印每个类别的实例数快速判断是否有类别被完全漏检 for r in results: boxes r.boxes if boxes is not None: cls_ids boxes.cls.cpu().numpy().astype(int) for c in set(cls_ids): print(r.path, class, c, count, list(cls_ids).count(c))conf0.25是推理置信度阈值农业病害场景可以降到 0.15 看召回但误检会增多。iou0.5控制 NMS 重叠阈值病斑密集时调高到 0.6 避免漏掉相邻实例。打印类别计数的目的是快速发现「某个类别一张图都没检出」的情况这通常意味着该类样本太少或标注有系统性偏差。4. 小样本实例分割的避坑清单从标注质量到评估指标4.1 现象训练 loss 正常但 mask 全是方块原因标签文件里的多边形顶点数太少或者坐标没有归一化。YOLO 要求多边形坐标是 0~1 的浮点数如果标注工具导出的是像素坐标模型会把所有点挤到图像左上角mask 自然变成方块。解决写个校验脚本逐行检查坐标范围。import os def check_labels(label_dir): bad [] for f in os.listdir(label_dir): if not f.endswith(.txt): continue with open(os.path.join(label_dir, f)) as fh: for i, line in enumerate(fh): parts line.strip().split() if len(parts) 7: # class 至少 3 个点 bad.append((f, i, 点数不足)) continue coords list(map(float, parts[1:])) if any(c 0 or c 1 for c in coords): bad.append((f, i, 坐标越界)) return bad issues check_labels(dataset/labels/train) print(f发现 {len(issues)} 处问题) for item in issues[:10]: print(item)这个脚本检查两件事每行至少 3 个点6 个坐标值以及所有坐标在 0~1 之间。发现越界就说明标注导出格式不对需要重新导出或手动归一化。4.2 现象验证集 mask mAP 波动超过 0.1原因验证集只有 23 张图样本量太小单张图的预测变化就能拉动整体指标。这不是模型不稳定是评估集统计效力不够。解决用 K 折交叉验证替代固定验证集或者把训练集和验证集合并后重新划分确保每个类别在验证集里至少有 5 个实例。290 张图做 5 折每折验证集约 58 张指标会稳很多。4.3 现象MosaicDisease 类别几乎检不出原因花叶病的病斑是斑驳状边界模糊多边形标注时不同标注员画的范围差异大。模型学到的是「平均轮廓」导致置信度普遍偏低。解决先统计该类别的实例数和平均多边形面积。如果实例数少于 50考虑对该类别做过采样或者在 loss 里给类别权重。另一个办法是降低该类别的置信度阈值单独看召回确认是「学不会」还是「阈值卡掉了」。4.4 现象训练到 50 epoch 后 mask mAP 反而下降原因小数据集上过拟合。模型开始记住训练集的噪声验证集指标掉头。解决把patience设小一点20~30配合dropout或者 weight decay。YOLOv8 默认有 weight decay但小数据集可以适当加大。另外检查增强是否过强mosaic 加 mixup 同时开在小数据上容易把有效信号也增强没了。4.5 现象推理时同一病斑被检出多个重叠 mask原因NMS 的 iou 阈值设太高或者模型对同一区域输出了多个高置信度实例。解决降低iou参数到 0.4~0.5或者在推理后处理里加一步按 mask 面积过滤去掉面积小于图像 0.1% 的碎片。实例分割的 NMS 比检测更复杂因为 mask 之间的 IoU 计算更耗时但效果更准。5. 把 290 张图用出 2900 张的效果增强策略与迁移技巧小样本实例分割的核心矛盾是标注成本高但模型需要多样性。这份数据集只有 290 张直接训容易过拟合但通过合理的增强和迁移策略可以把有效样本量放大一个量级。先说增强。YOLOv8 内置的增强里对实例分割最有用的是degrees旋转、translate平移、scale缩放和flipud/fliplr翻转。农业图像里叶片方向不固定旋转增强的收益比检测任务更大。我一般会把degrees开到 15~30scale设 0.5~1.5fliplr设 0.5。但要注意多边形标注在旋转后需要重新计算顶点YOLOv8 内部会处理但如果你的标注本身有自相交多边形增强后会出问题。所以增强前先跑一遍多边形合法性检查。from shapely.geometry import Polygon def check_polygon_valid(label_path): invalid [] with open(label_path) as f: for i, line in enumerate(f): parts line.strip().split() coords list(map(float, parts[1:])) points [(coords[j], coords[j1]) for j in range(0, len(coords), 2)] poly Polygon(points) if not poly.is_valid: invalid.append((i, poly.is_valid, poly.area)) return invalidshapely的is_valid能查出自相交、重复点等问题。发现无效多边形要么修要么直接丢弃该实例别留着让增强环节报错。再说迁移。如果你手头有 PlantDoc 或 PlantVillage 这类分类数据集可以先用它们做预训练把 backbone 学到的叶片纹理特征迁移过来再在 290 张图上微调分割头。常见做法是冻结 backbone 前几层只训 neck 和 head学习率设小一点0.001训 50 epoch 左右。这样比从头训收敛快mask mAP 通常能高 5~10 个点。最后一个技巧是测试时增强TTA。推理时对同一张图做水平翻转和轻微缩放把多次预测的 mask 做加权融合。YOLOv8 的predict里没有直接开 TTA 的参数但可以手动跑两次推理再合并。代价是推理时间翻倍适合离线诊断场景不适合实时监测。验证方法上除了看 mask mAP我习惯再做一个「面积误差」统计对每个预测 mask 和对应 GT mask 算面积比如果比值集中在 0.8~1.2 之外说明轮廓回归有问题。这个指标比 mAP 更直观能告诉你模型是「框对了但轮廓不准」还是「根本没找到」。从那以后我每次拿到新的实例分割数据集都强制先跑一遍多边形合法性检查和坐标范围校验再开始训。这两步花不了十分钟但能省掉后面几小时的无效训练。希望帮到你。本文还有配套的精品资源点击获取
返回列表