ARTICLE DETAIL

资讯详情

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

水稻害虫目标检测数据集实战:从解压到YOLO基线跑通

水稻害虫目标检测数据集实战:从解压到YOLO基线跑通 简介这份水稻害虫目标检测数据集面向智能农业、植保科研与农技教育场景帮助开发者与研究人员解决田间害虫自动识别与精准施药中的目标定位问题。数据覆盖亚洲水稻螟虫、褐飞虱、稻纵卷叶螟、蓟马等12类主要害虫涵盖蛀茎、刺吸、食叶等不同危害类型采集自真实稻田环境包含不同生长周期、光照与植株密度条件并按YOLO规范提供标准化边界框坐标与类别索引可直接用于主流检测框架训练。资源包共2000个文件以1481个txt标注文件、517张jpg图像为主另含1个yaml配置文件与1份docx说明文档压缩包约52.83MB训练集1296张、验证集123张、测试集62张划分清晰。已有305人学习下载适合构建田间害虫监测模型、开发精准施药决策系统或作为农技培训的图像识别基础数据。1. 水稻害虫目标检测数据集从拿到压缩包到跑通第一条基线水稻害虫测报这件事真正卡住人的往往不是模型结构而是数据。田间拍回来的照片背景杂乱、虫体小、类别还容易混稻飞虱、二化螟、稻纵卷叶螟这些目标在整幅图里可能只占几十个像素。你手里如果只有一个「水稻害虫目标检测数据集.zip」第一反应通常是里面是什么格式、类别怎么定义的、能不能直接喂给 YOLO 系列训练。这篇笔记就围绕这个压缩包展开把解压后的目录结构、标注格式转换、训练配置、小目标调参和踩坑排查一条线讲清楚。适合已经会跑 YOLOv8 或 YOLOv11 基础训练、但第一次接触农业虫害数据的同学也适合做植保测报、想验证模型能不能落地的工程师。目标很明确让你从拿到 zip 到跑出一条能看的 mAP 曲线中间不靠玄学。2. 解压先别急着训练把数据集结构和标注格式摸清楚2.1 水稻害虫数据集常见的三种目录组织拿到压缩包先解压到一个干净的路径别直接扔在下载目录里。农业类目标检测数据集常见的组织方式有三种第一种是已经切好 train/val/test 的 YOLO 格式每个 split 下有 images 和 labels 两个文件夹第二种是原始图片加一个 annotations 文件夹里面是 Pascal VOC 的 XML第三种是图片全堆在一起标注是一个总的 COCO json。这三种处理路径完全不同所以第一步永远是看目录而不是先写训练脚本。# 解压并查看顶层结构先不急着进训练 unzip 水稻害虫目标检测数据集.zip -d ./rice_pest cd rice_pest find . -maxdepth 2 -type d | sort # 统计图片数量和标注文件数量两者对不上就说明有问题 find . -type f \( -iname *.jpg -o -iname *.png \) | wc -l find . -type f \( -iname *.xml -o -iname *.json -o -iname *.txt \) | wc -l这段命令的逻辑是先建立目录全貌再用文件计数做一次粗校验。参数上-maxdepth 2是为了避免在深层目录里刷屏-iname忽略大小写是因为很多数据集里混着 JPG 和 jpg。如果图片数和标注数差距超过百分之五基本可以判定有漏标或者多余文件后面训练时会出现大量空标签mAP 会莫名其妙偏低。2.2 判断标注是 VOC、COCO 还是 YOLO txt判断格式有个笨但可靠的办法随便打开一个标注文件看头几行。XML 开头是annotationCOCO 是一个大 json 里有images、annotations、categories三个键YOLO txt 则是每行class_id x_center y_center width height而且数值都在 0 到 1 之间。这里有个容易翻车的点有些数据集号称是 YOLO 格式但坐标没归一化还是像素值直接训练会让损失爆炸。import json, os, glob # 抽查一个标注文件判断格式和坐标范围 ann_dir ./rice_pest/annotations sample glob.glob(os.path.join(ann_dir, *.json))[0] with open(sample, r, encodingutf-8) as f: data json.load(f) print(顶层键:, list(data.keys())) if annotations in data: ann data[annotations][0] print(bbox 示例:, ann.get(bbox)) print(类别数:, len(data.get(categories, []))) # COCO bbox 是 [x, y, w, h] 像素值转 YOLO 要除以图宽高这段代码的作用是确认 COCO 结构并查看 bbox 的表示方式。COCO 的 bbox 是左上角坐标加宽高单位是像素YOLO 要的是中心点加宽高且全部归一化到 0 到 1。参数上要注意categories里的 id 不一定从 0 连续有些数据集从 1 开始转换时必须重映射否则类别索引会整体错位一位训练出来的模型把所有类别都认成隔壁那一类。2.3 类别名和类别数必须落成一份固定映射水稻害虫数据集的类别命名经常不统一有的写中文「稻飞虱」有的写拉丁学名有的写拼音。训练前一定要把类别名固定成一份data.yaml并且确认类别顺序和标注里的 id 完全对应。常见做法是先把所有类别名收集起来排序生成一个从 0 开始的映射表再统一改写标注。# 生成类别映射并写出 data.yaml classes sorted([稻飞虱, 二化螟, 稻纵卷叶螟, 稻苞虫, 褐飞虱]) class_map {name: i for i, name in enumerate(classes)} with open(data.yaml, w, encodingutf-8) as f: f.write(fpath: ./rice_pest\n) f.write(train: images/train\n) f.write(val: images/val\n) f.write(fnc: {len(classes)}\n) f.write(fnames: {classes}\n) print(class_map)逻辑说明nc是类别数names的顺序就是模型输出的索引顺序必须和标注里的 class_id 一一对应。参数上path用相对路径方便迁移train和val指向图片目录YOLO 会自动去找同级的 labels 目录。这里如果类别顺序写错模型不会报错但验证时每一类都错位属于典型的黑匣子式翻车。3. 把 VOC 或 COCO 转成 YOLO转换脚本与四个边界坑3.1 VOC XML 转 YOLO txt 的完整脚本VOC 格式在农业数据集里很常见尤其是早期人工标注的项目。转换的核心是把xmin, ymin, xmax, ymax换成中心点归一化坐标。下面这个脚本可以直接抄处理单个目录下的所有 XML。import os, glob import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_dir, out_dir, class_map): tree ET.parse(xml_path) root tree.getroot() img_name root.find(filename).text img_path os.path.join(img_dir, img_name) w, h Image.open(img_path).size lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in class_map: continue # 未登记类别直接跳过避免索引错乱 cls_id class_map[name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 裁剪到图像边界防止标注越界 xmin, ymin max(0, xmin), max(0, ymin) xmax, ymax min(w, xmax), min(h, ymax) xc (xmin xmax) / 2 / w yc (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) out_path os.path.join(out_dir, os.path.splitext(img_name)[0] .txt) with open(out_path, w) as f: f.write(\n.join(lines))逻辑说明先读图拿到真实宽高再逐目标换算。参数上:.6f保留六位小数YOLO 对精度不敏感但太短会有累积误差。class_map里没有的类别直接跳过这是防止类别索引错位的后悔药。注意filename字段有时和实际文件名不一致如果对不上要改成用 XML 文件名反推图片名。3.2 COCO json 转 YOLO 的批量处理COCO 转 YOLO 要处理images和annotations的关联用image_id做键。下面脚本按 split 分别处理避免 train 和 val 混在一起。import json, os from collections import defaultdict from PIL import Image def coco_to_yolo(json_path, img_dir, out_dir, class_map): with open(json_path, r, encodingutf-8) as f: data json.load(f) img_info {img[id]: img for img in data[images]} anns defaultdict(list) for ann in data[annotations]: anns[ann[image_id]].append(ann) os.makedirs(out_dir, exist_okTrue) for img_id, img in img_info.items(): w, h img[width], img[height] lines [] for ann in anns[img_id]: cat_name next(c[name] for c in data[categories] if c[id] ann[category_id]) if cat_name not in class_map: continue cls_id class_map[cat_name] x, y, bw, bh ann[bbox] xc (x bw / 2) / w yc (y bh / 2) / h lines.append(f{cls_id} {xc:.6f} {yc:.6f} {bw/w:.6f} {bh/h:.6f}) name os.path.splitext(img[file_name])[0] with open(os.path.join(out_dir, name .txt), w) as f: f.write(\n.join(lines))逻辑说明用defaultdict把标注按图片聚合避免每张图都遍历整个标注列表。参数上img[width]和img[height]必须和实际图片一致有些数据集这两项是错的训练时框会整体偏移。转换完一定要抽查几张可视化别等训练完才发现框全歪了。3.3 转换后必须做的三项校验转换脚本跑完不代表没事至少做三项校验一是图片和 txt 文件名一一对应没有孤儿文件二是每行五个值class_id 是整数且在[0, nc-1]内三是坐标都在 0 到 1 之间。这三项任何一项出问题训练都会以损失不下降或者 mAP 恒为零的形式表现出来。# 校验找出没有对应 txt 的图片以及坐标越界的行 python - PY import os, glob img_dir, lbl_dir rice_pest/images/train, rice_pest/labels/train imgs {os.path.splitext(os.path.basename(p))[0] for p in glob.glob(img_dir /*)} lbls {os.path.splitext(os.path.basename(p))[0] for p in glob.glob(lbl_dir /*.txt)} print(缺标注的图片数:, len(imgs - lbls)) print(多余标注数:, len(lbls - imgs)) bad 0 for p in glob.glob(lbl_dir /*.txt): for line in open(p): parts line.split() if len(parts) ! 5 or not (0 float(parts[1]) 1): bad 1 print(异常标注行数:, bad) PY逻辑说明用集合差找孤儿文件再逐行检查字段数和坐标范围。参数上0 float(parts[1]) 1只查了 x 中心实际项目里五个值都要查一遍。这一步花两分钟能省掉后面几个小时的排查。3.4 四个边界坑越界、空图、重复框、类别错位越界框在农业数据集里特别多因为虫体常出现在叶片边缘标注员容易把框拖出图像。空图指的是图片没有任何目标YOLO 允许空 txt但如果空图比例超过三成模型会偏向背景召回率上不去。重复框是同一目标被标了两次转换后会出现两个几乎重合的框训练时 NMS 阶段才暴露。类别错位前面提过根源是类别映射没对齐。这四个坑的共同点是训练不报错但指标异常属于血泪经验级别的隐蔽问题。4. 用 YOLOv8 跑通水稻害虫基线配置、参数与首轮结果4.1 环境准备和最小训练命令环境用常见的 ultralytics 即可不追求最新版本稳定优先。水稻害虫数据量通常不大几千张图单卡就能跑。下面是最小训练命令先跑通再调参。pip install ultralytics # 从预训练权重起步农业数据集样本少从头训容易过拟合 yolo detect train \ data./rice_pest/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectruns/rice_pest \ namebaseline逻辑说明modelyolov8n.pt用 nano 版本先验证流程确认数据没问题再换 s 或 m。参数上imgsz640是默认值但水稻害虫目标小后面要单独调。batch16看显存显存不够就降到 8。project和name决定输出目录方便对比多次实验。4.2 小目标场景下 imgsz 和 anchor 的取舍水稻害虫在整幅图里往往只有几十像素640 输入下经过多次下采样到检测头时特征图可能只剩几个像素模型根本学不到。常见做法是把imgsz提到 1024 甚至 1280代价是显存和训练时间成倍增加。另一个思路是切图训练把大图裁成小块让目标相对变大。YOLOv8 是 anchor-free 的不用手动设 anchor但可以调close_mosaic让最后若干轮关闭马赛克增强小目标在拼接图里容易被裁掉。# 小目标优先提高输入分辨率最后 10 轮关闭 mosaic yolo detect train \ data./rice_pest/data.yaml \ modelyolov8s.pt \ epochs150 \ imgsz1024 \ batch8 \ close_mosaic10 \ device0 \ projectruns/rice_pest \ namesmall_obj逻辑说明imgsz1024让目标占据更多像素close_mosaic10在最后十轮用原始图训练减少拼接带来的目标截断。参数上batch8是因为分辨率翻倍后显存吃紧。如果显存还是不够可以用梯度累积但 ultralytics 里要自己加回调不如直接降 batch。4.3 数据增强参数怎么设才不伤小目标YOLO 默认增强里有缩放、平移、HSV 调整和 mosaic。对水稻害虫来说HSV 调整很有用因为田间光照变化大但大幅缩放会伤害小目标建议把scale控制在 0.5 以内。mosaic 能提升泛化但小目标在四宫格里被缩得更小所以要么降低 mosaic 概率要么提前关闭。# 温和增强保护小目标 yolo detect train \ data./rice_pest/data.yaml \ modelyolov8s.pt \ epochs150 \ imgsz1024 \ batch8 \ scale0.4 \ mosaic0.5 \ hsv_h0.015 hsv_s0.7 hsv_v0.4 \ close_mosaic15 \ device0逻辑说明scale0.4限制随机缩放幅度mosaic0.5把拼接概率降到一半hsv_*是颜色抖动模拟不同光照。参数上close_mosaic15比默认更早关闭给小目标留出干净的训练轮次。这些值不是绝对最优但作为起点比默认值稳。4.4 首轮结果怎么看mAP、召回和混淆矩阵训练完先看results.png和confusion_matrix.png。水稻害虫数据集如果类别不平衡整体 mAP 会被多数类拉高要看每一类的 AP。召回低说明漏检多常见原因是小目标特征弱或者置信度阈值太高。混淆矩阵能看出哪两类容易混比如稻飞虱和褐飞虱形态接近模型分不清很正常这时候要么合并类别要么补样本。# 用验证集跑一次评估输出每类指标 yolo detect val \ modelruns/rice_pest/small_obj/weights/best.pt \ data./rice_pest/data.yaml \ imgsz1024 \ conf0.001 \ iou0.6逻辑说明conf0.001是为了画 PR 曲线时保留所有预测评估 mAP 时用低阈值更准。参数上iou0.6是 NMS 的 IoU 阈值小目标密集时调低一点能减少漏检。看结果时重点关注小类别的 AP如果某一类 AP 长期低于 0.2先回去查标注质量别急着改模型。5. 训练崩了先查这些水稻害虫数据集的五类常见翻车5.1 损失不下降mAP 恒为零现象训练几十轮后 box_loss 和 cls_loss 几乎不动验证 mAP 一直是 0。原因通常是标注格式不对比如坐标没归一化或者 class_id 超出nc范围。解决回到第 3 章的校验脚本逐行检查坐标范围和类别索引确认data.yaml里的nc和实际类别数一致。这类问题不报错只能靠校验发现。5.2 训练正常但验证集全漏检现象训练损失正常下降但验证时几乎不框任何目标。原因多半是验证集路径写错YOLO 找不到图片或者验证集标注是空的。解决检查data.yaml里val指向的目录确认图片和 labels 都在并且 labels 里有内容。另一个可能是验证集和训练集分布差异太大比如训练集是实验室拍摄验证集是田间拍摄。5.3 某一类 AP 特别低其他类正常现象多数类别 AP 在 0.6 以上某一类只有 0.1。原因可能是该类样本太少或者标注质量差框得不准。解决先统计每类样本数少于总样本百分之五的类别考虑补数据或做重采样。再看该类标注框是否普遍偏大或偏小必要时重新标注。类别形态接近时合并类别比硬分更实际。5.4 显存溢出和训练中断现象训练到一半报 CUDA out of memory。原因通常是imgsz或batch设太大或者 dataloader 的 worker 数过多。解决降batch或者用imgsz640先跑通再逐步加。workers在 Windows 上容易出问题设成 0 或 2 更稳。如果用了 mosaic拼接图会临时增加显存占用可以提前关闭。5.5 推理时框重叠严重现象推理结果里同一目标出现多个重叠框。原因是 NMS 的 IoU 阈值设太高或者模型对同一目标输出了多个高置信度框。解决推理时把iou降到 0.5 左右或者训练时增加重复框的惩罚。如果标注里本身有重复框先清洗标注模型学到的就是重复输出。6. 把水稻害虫检测做扎实切图推理与类别合并的取舍6.1 大图切块推理让小目标在推理阶段也占够像素训练时提了imgsz但推理时如果直接喂整幅大图小目标还是会被缩得很小。一个实用技巧是切图推理把大图按重叠窗口切成小块逐块推理后再把框映射回原图坐标最后统一做 NMS。这样每个小目标在局部图里占的像素更多召回明显提升。代价是推理时间增加需要权衡。import cv2 from ultralytics import YOLO model YOLO(runs/rice_pest/small_obj/weights/best.pt) img cv2.imread(field.jpg) H, W img.shape[:2] tile, overlap 1024, 200 step tile - overlap all_boxes [] for y in range(0, H, step): for x in range(0, W, step): crop img[y:ytile, x:xtile] if crop.size 0: continue res model.predict(crop, imgsz1024, conf0.25, verboseFalse)[0] for box in res.boxes: xyxy box.xyxy[0].tolist() # 映射回原图坐标 all_boxes.append([xyxy[0]x, xyxy[1]y, xyxy[2]x, xyxy[3]y, float(box.conf), int(box.cls)]) # 对 all_boxes 再做一次全局 NMS这里省略具体实现逻辑说明按step滑动窗口切图每块单独推理再把坐标加回偏移量。参数上overlap200是为了避免目标正好落在切缝上被截断重叠越大越安全但越慢。最后必须做全局 NMS否则重叠区域的同一目标会被重复保留。6.2 类别合并形态接近的害虫不必硬分水稻害虫里有些类别形态非常接近比如不同种类的飞虱肉眼都难分模型更难。如果业务上不需要区分到种只到属或到功能类合并类别能显著提升指标。合并后类别数减少每类样本增多模型更容易学。这个取舍要和业务方确认因为测报有时确实需要区分种类。方案类别数优点代价细分到种8信息全小类样本少AP 低合并到属4指标稳丢失种类信息按危害类型合并3最稳信息最粗6.3 验证方法别只看 mAP去田间抽检mAP 是离线指标真正决定能不能用的是田间抽检。我的习惯是训练完拿一批没参与训练的新图人工数一遍虫再和模型输出对比算漏检率和误检率。农业场景里误检往往比漏检更烦人因为把叶片斑点认成虫会误导测报。抽检时按光照、生育期、拍摄角度分层抽样别只挑清晰的图。这一步花时间但能避免模型上线后翻车。6.4 一个具体技巧用置信度分层看漏检推理时把conf设到 0.01导出所有预测再按置信度分档统计。如果大量真实目标落在 0.05 到 0.25 之间说明模型其实「看到」了但不够自信这时候降推理阈值比重新训练更划算。如果真实目标连 0.01 都没有那就是特征太弱得回去补数据或提分辨率。这个技巧帮我省过好几次重训的时间。我自己的习惯是每拿到一个新数据集先花半天做格式校验和可视化再花半天跑基线最后才动模型和增强参数。水稻害虫这类小目标数据数据质量对结果的影响远大于模型选型别一上来就换更大的网络。希望帮到你。本文还有配套的精品资源点击获取
返回列表