ARTICLE DETAIL

资讯详情

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

水稻褐飞虱目标检测数据集与YOLOv8训练实战

水稻褐飞虱目标检测数据集与YOLOv8训练实战 简介面向农业AI、目标检测算法研发与植保应用菲律宾水稻褐飞虱成虫目标检测数据集提供真实农田环境下的害虫现场图像与YOLO格式标注。数据采集自菲律宾水稻种植区覆盖水稻生长周期不同阶段包含自然光照变化、叶片遮挡等复杂田间情况比合成数据更贴近实际部署环境。资源共2000个文件以1458个txt标注文件和540张jpg现场图片为核心另附1个yaml配置与1个docx说明文档压缩包约56.36MB可直接导入YOLO系列框架训练与验证。数据集包含训练、验证、测试划分便于复现实验和评估模型泛化能力已有196人学习适合智能虫害监测系统开发、精准施药决策支持以及农业院校与研究机构的算法教学。全部标注经农业专家校验聚焦褐飞虱成虫这一关键水稻害虫能帮助开发者减少数据清洗与格式转换成本加快害虫识别模型从实验到落地的进程。1. 菲律宾水稻褐飞虱成虫目标检测数据集先弄懂它是什么再决定怎么训做过水稻虫情测报的人都有印象一块田要蹲在田埂上拿白瓷盘垫在稻株下面拍打然后蹲在地上数落在盘里的褐飞虱成虫数完一丛要几分钟一片田数完人已经眼花。灯诱的虫瓶更夸张一晚上能收上千头成虫第二天早上对着放大镜一头头分雌雄、分长翅短翅测报站的老技术员最怕的就是虫峰期。这个标题里的“菲律宾水稻褐飞虱成虫目标检测数据集”本质上就是把这类“田间数虫”的场景整理成了带标注框的图片集图片拍的是菲律宾稻区田间与灯诱条件下的水稻褐飞虱成虫标注框框住的是成虫个体交付形态是压缩包解压之后是图片、标注文件和划分好的数据集目录。它解决的问题很直接让训练出来的目标检测模型替代人工数虫或者至少把数虫从“肉眼逐头数”降级成“模型预筛、人工复核”。适合正在做植保智能测报、虫情监测设备识别算法、或者打算用 yolo 系模型训练自己的害虫数据集的人。2. 数据集的构成与采集逻辑理解菲律宾稻区才能看懂这批图像2.1 图像来源与拍摄姿态灯诱、拍盘、原位三类场景差异很大拿到数据集先别急着解压训练第一步是认清图像来源。菲律宾稻区地处热带褐飞虱周年繁殖、世代重叠田间成虫和若虫同时存在虫口密度远高于我国大部分稻区。这个数据集里的图像按拍摄方式大致可以分成三类灯诱成像俯拍灯诱盘或接虫盒常见黑色或深色背景成虫密度极高个体之间有重叠触角、翅脉纹理还比较清楚。这类图背景单一检测难度相对低但虫体密集造成的重叠会让小目标容易漏检。拍盘成像白瓷盘拍打稻株后直接俯拍浅色背景褐飞虱成虫的淡褐色虫体和白色背景对比度尚可但瓷盘反光、水渍、稻株碎屑会带来噪声。背景单一、目标清晰训练初期用它打底最舒服。原位成像稻丛基部直接拍摄背景是茎秆、叶片、泥土和光影虫体被遮挡、姿态杂乱。这是真正贴近测报场景的图也是难度最高的图。最终部署时如果希望模型能直接处理田间原位图像数据里缺了这类图模型很可能在实测时翻车。常见做法是把三类图都保留而不是只挑某一类这样训练出来的模型才不会被单一背景绑架。2.2 类别设计为什么只标“成虫”不把若虫一起标进去标题里特意写了“成虫”这不是随口一说而是有标注逻辑的。褐飞虱若虫无翅、体长只有 1~3 毫米和稻飞虱科其他种类的若虫白背飞虱、灰飞虱的若虫肉眼几乎分不清标框时误标率极高。如果数据集里把若虫也标进去类别就变成了“褐飞虱若虫”和“褐飞虱成虫”但实际标注时连专业测报员都可能把白背飞虱若虫标进褐飞虱框里标签噪声一大模型训练出来就变成“见虫就框”而不是“框褐飞虱成虫”。所以只标成虫是更稳的选择成虫有翅、体型 4~5 毫米、有相对稳定的体色和翅型标注一致性容易保证模型学到的特征也更集中。拿到的标注通常只有一个类别名常见写法是 bph_adult 或 brown_planthopper_adult。标注文件里类别索引从 0 开始比如 YOLO 格式的一条记录长这样0 0.4532 0.6121 0.0315 0.0420含义是类别 0、归一化后的中心点 x、中心点 y、框宽 w、框高 h。后面四个值都是 0~1 之间的小数。2.3 压缩包目录组织解压后先确认格式再动手训练这类目标检测数据集的压缩包常见目录组织是下面这样的路径内容说明images/train训练集图片JPG 或 PNG尺寸不完全统一images/val验证集图片用来调参和选模型images/test测试集图片最终评估用别拿它调参annotations/标注文件可能是 VOC 的 xml、COCO 的 json 或 YOLO 的 txtlabels/trainYOLO 格式标签如果直接提供说明已经转好格式classes.txt类别清单一行一个类名顺序就是类别索引README 或 data.yaml数据说明与训练配置里面写了类别数、路径和拍摄说明划分比例常见是 8:1:1或者 9:0.5:0.5。拿到手第一步不是打开图片看而是看 annotations 目录下的文件后缀是 .xml走 VOC 转换流程是 .json先看是 COCO 格式还是自定义格式已经是 .txt直接检查坐标是否归一化。下面第三部分就按这三种情况分别处理。提示如果压缩包里图片尺寸差异很大有大到 4000x3000 的田间原图也有几百像素的灯诱裁剪图保留原始尺寸即可训练时用 imgsz 统一输入大小不要提前缩放图片否则小目标会被严重削弱。3. 标注格式检查与转换把压缩包变成能喂给 yolo 训练目录3.1 先判断拿到的是哪种标注格式用文本方式打开任意一个标注文件看开头内容就能判断head -n 20 annotations/xxxx.xml如果看到annotation包裹的object结构和bndbox坐标这是 VOC 格式如果看到{images: [...]}和annotations字段这是 COCO 格式如果是纯数字行如0 0.45 0.61 0.03 0.04这是 YOLO 格式。这一步判断决定了后续走哪条转换路径跳过去直接套脚本是新手最容易翻车的地方。3.2 VOC 转 YOLO一张 xml 对应一个 txtVOC 的标注是左上角和右下角坐标xmin, ymin, xmax, ymaxYOLO 需要的是归一化后的中心点加宽高。转换脚本我一般这样写import xml.etree.ElementTree as ET import os from pathlib import Path # 和训练的 data.yaml 里 names 的顺序保持一致 CLASSES [bph_adult] def voc_to_yolo(xml_path, out_dir): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(object): name obj.find(name).text.strip() if name not in CLASSES: continue box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) x_c ((x1 x2) / 2) / img_w y_c ((y1 y2) / 2) / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h # 边界裁剪防止坐标越界 x_c min(max(x_c, 0.0), 1.0) y_c min(max(y_c, 0.0), 1.0) w min(max(w, 0.0), 1.0) h min(max(h, 0.0), 1.0) lines.append(f{CLASSES.index(name)} {x_c:.6f} {y_c:.6f} {w:.6f} {h:.6f}) out_txt Path(out_dir) / (Path(xml_path).stem .txt) out_txt.write_text(\n.join(lines), encodingutf-8) xml_dir annotations out_dir labels/train os.makedirs(out_dir, exist_okTrue) for xml_file in Path(xml_dir).glob(*.xml): voc_to_yolo(xml_file, out_dir)逻辑不复杂两个细节必须注意一是类名列表的顺序脚本里 CLASSES 的顺序必须和后面 data.yaml 的 names 顺序完全一致顺序错一位类别就全错二是边界裁剪那四行有些 VOC 标注的框会超出图像边界不裁剪的话训练时可能会报坐标越界错误裁剪后能挡掉这个隐患。3.3 COCO 转 YOLO用 pycocotools 读取再归一化COCO 格式在目标检测数据集里也很常见转 YOLO 的脚本核心部分如下from pycocotools.coco import COCO from pathlib import Path coco COCO(annotations/instances_train.json) cat_map {cat[id]: i for i, cat in enumerate(coco.loadCats(coco.getCatIds()))} out_dir Path(labels/train) out_dir.mkdir(parentsTrue, exist_okTrue) for img_id in coco.getImgIds(): info coco.loadImgs(img_id)[0] img_w, img_h info[width], info[height] lines [] for ann in coco.loadAnns(coco.getAnnIds(imgIdsimg_id)): x, y, w, h ann[bbox] # COCO bbox 是左上角坐标 宽高 cx (x w / 2) / img_w cy (y h / 2) / img_h fw w / img_w fh h / img_h lines.append(f{cat_map[ann[category_id]]} {cx:.6f} {cy:.6f} {fw:.6f} {fh:.6f}) out_txt out_dir / (Path(info[file_name]).stem .txt) out_txt.write_text(\n.join(lines), encodingutf-8)注意 COCO 的 bbox 是[x, y, width, height]和 VOC 的[xmin, ymin, xmax, ymax]不一样别拿 VOC 公式直接套。pycocotools 在 Windows 上的安装比较麻烦常见做法是pip install pycocotools-windowsLinux 和 macOS 直接pip install pycocotools就行。跑完之后抽查几个 txt 文件肉眼确认坐标值都在 0~1 范围内再进下一步。3.4 补充标注与复核用预标注加人工修正清理脏标签如果解压后发现有些图没有标注文件或者跑一轮快速训练后觉得漏检多常见做法是先跑一轮预标注再用标注工具人工修正。标注工具方面labelImg 是老牌选择支持 VOC 与 YOLO 格式导出X-AnyLabeling 更现代支持自动分割和半自动标注对小目标的框选效率高一些。导出 YOLO 格式时注意类别顺序要从 classes.txt 里读别在工具里另建一套顺序否则又会出现 3.2 节里说的错位问题。这个“先粗标一轮、再人工复核”的思路特别适合褐飞虱这种小目标密集的数据先用预训练模型把所有疑似目标框出来再人工删掉误检、补上漏检比从头逐图手标快数倍。4. 用 YOLOv8 训练褐飞虱成虫模型从数据配置到小目标调优4.1 编写 data.yaml路径与类别顺序是唯一不能错的地方训练前先准备数据集配置文件。拿到的压缩包里如果自带 data.yaml检查一下路径是否还是打包者的本机绝对路径是的话改成当前机器的路径。自己写的话参考这个模板path: /home/user/bph_dataset train: images/train val: images/val test: images/test names: 0: bph_adultpath用绝对路径最省心用相对路径也行但容易因为当前工作目录不同而找不到图片。names的 0 号索引必须和标签文件里的第一个数字对应这是整个训练流程里最容易出错也最难排查的地方。写完跑一句验证python -c from ultralytics import YOLO; m YOLO(yolov8s.pt); print(m.task)能正常打印detect说明环境没问题接下来进入训练。4.2 训练命令与核心参数褐飞虱是典型小目标参数不能照搬默认值褐飞虱成虫在整张田间图里通常只有几十个像素拿默认的 imgsz640 直接训小目标特征很容易在降采样过程中丢光。我一般这样起训yolo detect train \ modelyolov8s.pt \ databph.yaml \ imgsz1280 \ epochs150 \ batch16 \ optimizerAdamW \ lr00.0005 \ weight_decay0.0005 \ mosaic1.0 \ close_mosaic10 \ copy_paste0.3 \ patience30 \ projectruns/bph几个关键参数的选择逻辑如下参数取值选择理由imgsz1280褐飞虱是小目标输入尺寸越大保留的目标像素越多显存不够时降到 960 或 1024实在不够就用切片推理batch16取决于显存1280 输入下 16 是比较稳的起点值OOM 就减半optimizerAdamW小数据集上 AdamW 收敛比 SGD 稳动量参数不用改默认值lr00.0005迁移学习微调用别用默认的 0.01数据量小的时候容易把预训练权重冲坏close_mosaic10最后 10 个 epoch 关闭 Mosaic让模型在接近真实分布的图像上微调避免小目标被切碎后学不到完整形态copy_paste0.3褐飞虱常呈群体分布复制粘贴增强能把单张图里的虫口密度放大提高高密度场景下的召回率训练中观察results.png里的曲线重点关注验证集 mAP50-95 是否还在上升。单类目标 150 个 epoch 通常足够mAP50-95 连续 20 个 epoch 不涨基本就到头了patience30会自己停掉不用一直守着。4.3 迁移学习与微调策略避免目标检测模型微调崩掉从yolov8s.pt预训练权重开始是常见做法COCO 上训过的权重对纹理、边缘、遮挡这些底层特征提取有很好的先验。数据量小、单类别场景下我一般会先冻结 backbone 前 10 层用较低学习率跑 30 个 epoch让检测头先适应褐飞虱的框分布再解冻全部层正常训练# 先用冻结训练找稳定的检测头 yolo detect train \ modelyolov8s.pt \ databph.yaml \ imgsz1280 \ epochs30 \ lr00.0002 \ freeze10如果这一步就开始崩比如 loss 震荡、mAP 归零多半是标签顺序错位或者标签坐标有越界回第三部分重新检查数据别硬调参数。数据有问题时调参纯属玄学越调越乱。4.4 小目标处理的推理端方案切片推理比单纯改 imgsz 更可靠训练完的模型投入实测时灯诱图虫体密集、原位图目标太小直接整图推理往往漏检严重。常见做法是引入 SAHI 切片推理把图切成带重叠的若干小块分别推理再合并结果重叠区的目标用 NMS 去重。这样等效于把 imgsz 做大的同时不丢失大图的光照全局信息对高密度小目标场景的召回率提升非常明显。实测中同一张 4000x3000 的灯诱图整图推理检到 80 头切片推理能检到 200 头以上差距就出在那些被降采样抹掉的微小个体上。5. 褐飞虱数据集常见问题排查五个让我熬夜调参的真实坑5.1 训练到一半 Loss 变成 NaN程序直接中断现象训练跑到第 20 到 40 个 epochloss 突然变成nan日志里出现Gradidents溢出警告或直接报错。原因最常见的有两个。一是标签坐标中有大于 1 或小于 0 的值或者框宽高为负数这通常是 VOC/COCO 转换时没做边界裁剪二是学习率设得过高预训练权重在小数据集上被一步更新冲爆。解决先跑数据检查脚本统计所有标签文件中坐标的最小值和最大值grep -oP (?\s)\d\.\d labels/train/*.txt | awk {print $1} | sort -g | head -n 1 grep -oP (?\s)\d\.\d labels/train/*.txt | awk {print $1} | sort -g | tail -n 1最小值应该大于等于 0最大值应该小于等于 1。发现越界就回第三部分在转换脚本里加裁剪逻辑重新转。坐标没问题就降学习率lr0从 0.0005 降到 0.0001再不行就排除混合精度影响在训练命令里加ampFalse试一次。5.2 训练曲线正常但验证集 mAP 一直为 0现象loss 正常下降验证集的 Precision、Recall 也看着有模有样但 mAP50 和 mAP50-95 死死钉在 0 上不动。原因类别索引错位这是目标检测里最经典的“微调崩了”场景。标签文件里的第一个数字是 0但 data.yaml 里names顺序或类别数配置不对或者 VOC 转 YOLO 时 CLASSES 列表名写错导致全部目标被过滤掉标签文件是空的文本。解决检查空标签和属类映射先看没有标签的图片有多少find labels/train -name *.txt -size 0 | wc -l再看任意一张标注图用 Python 加载标签并打印所有类别编号python -c import numpy as np; data np.loadtxt(labels/train/xxx.txt); print(np.unique(data[:,0]))如果打印出来的类别编号不是 0而是 1 或 2说明转标签时 CLASSES 顺序和 yaml 的 names 不一致。统一按二进制之前确认classes.txt第一行写什么名字yaml 里 0 号位置就放什么名字。5.3 高密度灯诱图中重叠成虫漏检严重现象单张图里虫口密度超过 100 头时模型只框出不到一半漏检密集地出现在虫体重叠区域。原因训练数据里高密度图太少或者 Mosaic 增强把本来就小的高密度群切得更碎。模型没见过“很多虫挤在一起”的完整形态推理时遇到重叠目标只会保留重叠率低的那一部分。解决三个方向同时做。一是把copy_paste从 0.3 提到 0.5手工复制粘贴虫群区域增加高密度样本二是在训练最后阶段设置close_mosaic10让模型在接近真实分布的图像上收敛三是推理端用 SAHI 切片把大图切成小块分别检测重叠区域的目标就“散开”了。5.4 田间原位图上模型把白背飞虱、灰飞虱也都框了出来现象部署到田间原位图像后模型输出里出现大量非褐飞虱的框尤其是白背飞虱和灰飞虱成虫它们体型、体色接近肉眼都要细看才能分。原因数据集类别只有 bph_adult但没有在标注层面做难负样本挖。“没标过”不等于“识别成不要的”模型没见过同类近似物种自然把它们当作目标的一部分。解决收集一批含白背飞虱、灰飞虱的图作为负样本目录加入训练标签留空。在 data.yaml 的 train 配置里把负样本图片目录也加到train路径下模型在训练中看到这些图但没有任何框与之匹配它才会学会抑制这些相似目标。这个做法的效果往往比加数据增强更直接。5.5 导出 ONNX 或 TensorRT 后精度明显下降现象PyTorch 推理时 mAP50 是 0.85导出成 ONNX 后掉到 0.7转成 TensorRT 的 FP16 又掉几个点。原因小目标对量化里精度损失极其敏感。FP16 保留的是浮点精度的低半精度虫体只有几十像素时特征值本身很小量化截断就把关键梯度抹掉了。另外导出时如果用了过小的最小框阈值会在 NMS 阶段丢掉小目标。解决导出 ONNX 时指定opset12关闭简化选项转 TensorRT 时不要用 FP16先跑 FP32 试一次。如果 FP32 有大幅提升说明是量化问题检查 TensorRT 版本和动态输入设置。褐飞虱这种小目标场景把计算卡的 FP16 关掉换来的精度收益往往比省下的那点延迟值钱。6. 验证策略与数据增强技巧怎么判断模型真的会数虫6.1 验证集别按图像随机分按田块分才有说服力很多人在处理数据集时按图片随机划分训练验证集这在褐飞虱场景里会虚高 mAP。同一块田不同时刻拍的图像背景、稻株、光照高度相似随机划分会把“同一个场景”的相似图像同时分进训练和验证验证集的 mAP 自然漂亮但模型换到另一块田就立刻露馅。常见做法是按拍摄田块或按时间批次分组整组划分确保验证集里的图像在采集条件上独立于训练集。这才是“遥感图像目标检测”里常说的跨场景泛化评估对农业小目标模型同样适用。6.2 用计数误差评估而不是只看 mAP目标检测的 mAP 衡量的是“框得准不准”但植保测报关心的是“每百丛有多少头虫”。模型框偏了一点mAP 掉一截对虫量统计却完全没影响反过来漏检 10% 的虫mAP 可能只掉 1 个点对测报结论却是天壤之别。所以评估时除了 mAP务必额外统计一个指标计数相对误差 预测虫头数 / 人工数虫数 - 1。部署时设定可接受阈值比如误差在正负 15% 以内算合格比盯着 mAP 调参更符合业务落地的直观逻辑。6.3 增强优先级轻扰动、少翻转、高密度靠复制粘贴褐飞虱成虫有轻微趋光性和方向性但田间拍摄时虫子姿态基本随机大幅旋转增强意义不大反而会让模型学习到错误的朝向先验。我一般只保留 0~15 度的随机旋转不做 180 度翻转避免把“腹面朝上”这种不可能出现的姿态增强出来。HSV 扰动用轻微档重点模拟不同时段拍摄的光照差异比单纯调亮度更接近灯诱图与白天田间图的色温差。数据增强组合里先保证偏差不漏再考虑增加多样性。最后说一个我自己的习惯训练完后不急着部署先拿几张灯诱、拍盘、原位的典型图各测一遍计数误差误差超过 20% 就直接回数据集找原因而不是继续加轮数。这套流程走顺之后褐飞虱这类小目标场景的数据处理与模型调优速度会快很多希望帮到你。本文还有配套的精品资源点击获取
返回列表