尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

水稻虫害检测数据集全解析:从VOC/YOLO标注到YOLOv8训练实战

水稻虫害检测数据集全解析:从VOC/YOLO标注到YOLOv8训练实战 简介面向农业信息化与智能病虫害检测的研究人员和开发者这份资源以docx文档形式系统梳理了水稻虫害检测数据集的完整规格能帮助读者快速掌握该数据集是否适合自己的模型训练需求。内容明确数据集共包含5212张高分辨率jpg图片每张均配有Pascal VOC格式的xml标注文件和YOLO格式的txt文件覆盖褐飞虱、绿叶蝉、稻纵卷叶螟、稻水象甲、茎螟、螺纹虫6个害虫类别总计8104个矩形标注框文档还分项列出每类框数如褐飞虱1578框、稻纵卷叶螟1459框、螺纹虫1616框等可辅助进行类别均衡分析或迁移学习前的数据校验。同时介绍使用labelImg工具完成矩形框标注并说明图片与标注文件按images等目录分类存放便于后期检索与处理。该数据集同时支持VOC格式的详细描述与YOLO格式的高效解析可适配多种主流目标检测框架。资源为单个docx文件压缩包约2.08MB查阅和保存都很方便目前已有121人学习下载适合正在开展水稻虫害目标检测课题的科研人员、农业工程师和学生使用。1. 水稻虫害检测数据集5212张图、8104个框VOC与YOLO双格式直接开训做农业视觉方向的工程师应该都有体会模型结构再新没有干净、标注一致的数据集训练就是在碰运气。这次拆解的水稻虫害检测数据集一共5212张jpg原图每张都带Pascal VOC的xml标注和YOLO格式的txt标注覆盖6类水稻虫害总框数8104个。它解决的是目标检测任务里最磨人的数据准备环节——不用再做格式转换、不用自己写脚本清洗标注、也不用纠结类别名称对不上的问题解压之后就能直接丢进YOLOv5、YOLOv8或者SSD这类检测框架开训。适合正在做农业植保、智慧农田监测、虫害计数这类项目的算法工程师和学生尤其是那些刚接触检测任务、想用一份现成数据集跑通全流程的人。2. 数据集的真实结构从文件夹布局到标签内容的完整拆解拿到一份数据集我一般不会急着解压就开训。先花十分钟把目录结构和标注内容梳理清楚能省掉后面排查问题的半天时间。这个数据集在组织方式上走的是目标检测任务最常见的双目录结构images文件夹放图labels相关的文件夹放标注图和标注通过同名文件关联。2.1 目录结构与文件关联机制解压之后你会看到这样的顶层结构dataset_root/ ├── images/ │ ├── 000001.jpg │ ├── 000002.jpg │ └── ... ├── annotations_xml/ │ ├── 000001.xml │ ├── 000002.xml │ └── ... ├── labels_txt/ │ ├── 000001.txt │ ├── 000002.txt │ └── ... └── classes.txt图片文件、xml标注、txt标注三者的文件名完全一致关联关系就是靠这个同命名规则建立的。images下是5212张jpg原图annotations_xml下是5212个VOC格式xml文件labels_txt下是对应的5212个YOLO格式txt文件classes.txt记录了完整的类别名称列表。这种组织方式的好处在于训练脚本只需要按文件名前缀去三个目录里取对应文件即可不用解析额外的索引文件或JSON映射表。如果你自己写数据加载器核心逻辑就是遍历images目录拿到文件名前缀然后去另外两个目录拼接出xml和txt的完整路径。2.2 VOC标注与YOLO标注的内容差异VOC格式的xml标注是完整的结构化文档一个典型文件长这样annotation folderimages/folder filename000001.jpg/filename size width1920/width height1080/height depth3/depth /size object namebrown-planthopper/name bndbox xmin356/xmin ymin482/ymin xmax512/xmax ymax625/ymax /bndbox /object object nameleaf-folder/name bndbox xmin840/xmin ymin317/ymin xmax1003/xmax ymax455/ymax /bndbox /object /annotationxml里最重要的是三块图像尺寸信息、目标类别名称、边界框的绝对像素坐标。这个格式的优势是易读、信息完整但也带来了两个低效点一是文件体积大二是坐标是绝对像素值图像resize之后必须同步换算。YOLO格式的txt就精简多了每行对应一个目标3 0.226562 0.512037 0.081250 0.066204 0 0.484375 0.357407 0.085417 0.063889每行五个数值依次是类别ID、归一化中心x、归一化中心y、归一化宽度w、归一化高度h。所有坐标值都已除以图像宽高做了归一化范围落在0到1之间所以训练时不管输入分辨率怎么变标注都不需要再转换。把两种格式放在一起对比VOC格式适合人眼检查、做数据筛选和二次标注YOLO格式适合直接喂给训练框架。这个数据集两种都提供了等于把格式转换这一层工作省掉了。2.3 classes.txt才是类别顺序的唯一依据这里要特别强调一个容易想当然的坑类别在txt标注里的数字ID和数据集说明里列出的类别列表顺序并不一致。数据集说明里写了六个类别名称但那段顺序不是YOLO标注里用的顺序txt标注里的类别ID对应关系要以labels目录下的classes.txt为准。# classes.txt 内容示例实际以数据集内文件为准 brown-planthopper green-leafhopper leaf-folder rice-bug stem-borer whorl-maggot凡是使用这个数据集训练的人第一步就应该是用文本编辑器打开classes.txt确认每个类别ID对应的类别名再去修改训练配置里的类别列表。如果直接用数据集描述里那段顺序去配YOLOv5的data.yaml类别ID错位是必然结果训练出来的模型推理时标签会张冠李戴。提示训练前先把classes.txt的内容复制到data.yaml的names字段里这是避免类别错位最直接的做法。3. 训练前的数据质检格式正确不等于可以直接开训很多拿到数据集的人习惯直接套用yolov5的train.py命令开训但我建议先做一轮数据质检。这个数据集虽然标注完整但检测任务里数据质量决定模型上限花二十分钟把数据过一遍比训练完发现mAP异常再回头查数据要划算得多。3.1 用脚本审计txt标注的数值合法性YOLO格式的txt文件因为只有数字肉眼很难发现问题所以我一般会写个快速审计脚本跑一遍检查坐标是否越界、类别ID是否超范围、是否存在空标注文件。import os labels_dir labels_txt num_classes 6 issues [] for filename in os.listdir(labels_dir): if not filename.endswith(.txt): continue filepath os.path.join(labels_dir, filename) with open(filepath, r) as f: lines f.readlines() if len(lines) 0: issues.append((filename, empty file)) continue for line_idx, line in enumerate(lines): parts line.strip().split() if len(parts) ! 5: issues.append((filename, fline {line_idx}: expected 5 values, got {len(parts)})) continue cls_id int(parts[0]) if cls_id 0 or cls_id num_classes: issues.append((filename, fline {line_idx}: class id {cls_id} out of range)) x_center float(parts[1]) y_center float(parts[2]) w float(parts[3]) h float(parts[4]) if w 0 or h 0: issues.append((filename, fline {line_idx}: non-positive w/h)) if x_center 0 or x_center 1 or y_center 0 or y_center 1: issues.append((filename, fline {line_idx}: center out of [0,1])) print(fchecked {len(os.listdir(labels_dir))} files) print(ffound {len(issues)} issues) for issue in issues[:50]: print(issue)这段脚本做的事情很直接先检查文件是否为空再逐行解析五个数值验证类别ID是否在0到5之间、宽高是否为正数、中心点坐标是否在归一化范围内。跑完之后如果输出issues数量为0说明标注数值层面没有问题。如果查出问题记录下来的文件名和行号可以直接定位到具体文件去修。这种审计脚本不需要很复杂但能挡住最基础的数据异常。常见的情况是某些标注工具导出时小数位截断导致h为0或者类别ID写到了6以上——这些异常用训练框架的报错信息去排查会很痛苦因为批量训练时错误信息只显示图片路径不会告诉你是哪一行标注出了问题。3.2 用可视化脚本抽查标注框贴合度数值审计只能说明格式合法不能说明标注质量。矩形框是否贴合虫体需要人工抽查。把xml里的坐标画回图上是最直观的检验方式。import cv2 import xml.etree.ElementTree as ET image_path images/000001.jpg xml_path annotations_xml/000001.xml img cv2.imread(image_path) tree ET.parse(xml_path) root tree.getroot() for obj in root.findall(object): name obj.find(name).text bbox obj.find(bndbox) xmin int(float(bbox.find(xmin).text)) ymin int(float(bbox.find(ymin).text)) xmax int(float(bbox.find(xmax).text)) ymax int(float(bbox.find(ymax).text)) cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2) cv2.putText(img, name, (xmin, ymin - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imwrite(check_000001.jpg, img)这个脚本从xml里读取类别名和坐标用OpenCV画框并保存为新的jpg文件。抽查时不用每张都看在images目录里随机挑30到50张扫一眼框的位置和大小是否符合直觉。水稻虫害的检测有个特殊性褐飞虱、绿叶蝉这类害虫体型很小在1920分辨率下可能只有几十个像素宽框稍微画松一点或者画紧一点都很常见。抽查时重点看两类问题一是框是否包含了大片背景区域二是小目标框是否被切掉了虫体的一部分。如果抽查50张里大部分框都比较贴合那这个数据集的标注质量就是可以接受的。3.3 按类别统计框数与目标尺度分布类别框数分布对训练策略影响很大。这个数据集的标注统计显示brown-planthopper 1578框、green-leafhopper 1077框、leaf-folder 1459框、rice-bug 1294框、stem-borer 1080框、whorl-maggot 1616框总计8104框。从分布来看框数最多的whorl-maggot比最少的green-leafhopper多了接近50%属于中等程度的不平衡还没到需要做复杂重采样的程度。我一般会做的是把每类框的面积分布画出来看看因为水稻害虫里混着小型害虫和中等体型的卷叶螟、茎螟目标尺度差异会影响anchor设置。之前用这组数据跑过一次YOLOv8损失函数里对框回归做了scale-aware处理小目标多的类别收敛速度明显比预期快。如果用的是YOLOv5系模型建议把anchors重新聚一次类不要直接用coco预训练锚点因为农业场景的害虫目标尺寸分布和日常物体差异很大。4. 直接开训从数据划分到YOLOv8训练配置数据质检没问题接下来就是划分数据集和配置训练参数。这个环节看起来简单但数据集划分的随机种子、验证集比例、类别配置表的写法都会直接影响训练效果。4.1 按6比2比2划分训练验证测试集目标检测训练通常需要三个子集训练集、验证集、测试集。这里我推荐一个稳妥的划分脚本按6比2比2分配加入随机种子保证可复现。import os import random import shutil random.seed(42) image_dir images label_dir labels_txt train_dir dataset_split/train val_dir dataset_split/val test_dir dataset_split/test for d in [train_dir, val_dir, test_dir]: os.makedirs(os.path.join(d, images), exist_okTrue) os.makedirs(os.path.join(d, labels), exist_okTrue) filenames [f for f in os.listdir(image_dir) if f.endswith(.jpg)] random.shuffle(filenames) n_total len(filenames) n_train int(n_total * 0.6) n_val int(n_total * 0.2) for idx, name in enumerate(filenames): base os.path.splitext(name)[0] img_src os.path.join(image_dir, name) label_src os.path.join(label_dir, base .txt) if idx n_train: img_dst os.path.join(train_dir, images, name) label_dst os.path.join(train_dir, labels, base .txt) elif idx n_train n_val: img_dst os.path.join(val_dir, images, name) label_dst os.path.join(val_dir, labels, base .txt) else: img_dst os.path.join(test_dir, images, name) label_dst os.path.join(test_dir, labels, base .txt) shutil.copy(img_src, img_dst) shutil.copy(label_src, label_dst) print(ftrain: {n_train}, val: {n_val}, test: {n_total - n_train - n_val})这段脚本的关键点有三个一是random.seed(42)固定随机种子保证每次划分结果一致二是先shuffle再切片避免文件名顺序导致的数据分布偏差三是用shutil.copy而不是move保留原始数据不动方便之后重新划分。划分比例方面5212张图按6比2比2会得到约3127张训练图、1043张验证图、1042张测试图。如果项目对测试集没有硬性需求也可以按7比2比1划分把更多数据留给训练。但验证集最好不要低于总数据量的15%否则模型选型时的评估结果方差会很大。4.2 配置YOLOv8的data.yaml数据划分好之后接下来是写YOLOv8的data.yaml配置文件。这个文件是训练流程里最容易被忽略但最容易出错的地方。# dataset.yaml path: dataset_split train: train/images val: val/images test: test/images names: 0: brown-planthopper 1: green-leafhopper 2: leaf-folder 3: rice-bug 4: stem-borer 5: whorl-maggot注意names字典里的顺序必须与labels_txt目录下classes.txt的类别顺序完全一致。这里有个细节YOLOv8的配置文件里names可以写成列表也可以写成字典效果相同但顺序错位是训练静默报错的重灾区模型能训练完mAP也正常但输出的类别标签全部错位。path字段建议写相对路径。如果path用相对路径YOLOv8会基于当前工作目录去拼接如果你在项目根目录下执行训练命令配置写成上面那样就没问题。建议训练前先用一行代码验证配置正确性python -c import yaml; cfg yaml.safe_load(open(dataset.yaml)); print(cfg[names])4.3 训练命令与关键参数YOLOv8训练命令相对简洁但有几个参数对这个数据集特别重要yolo detect train \ datadataset.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ patience20 \ save_period10 \ plotsTrue模型我推荐从yolov8n或者yolov8s开始。这个数据集的目标是小虫体但图片分辨率高用轻量模型跑通流程确认数据没问题后再换大模型提升精度。epochs设100是底线配合patience20做早停一般到60到80轮就会收敛。save_period10建议打开每隔10轮保存一次权重防止中途断电丢了全部训练进度。imgsz设640是标准做法。如果后续出现小目标漏检较多的情况可以考虑把imgsz调到960或者1280训练但显存占用会大幅上升。batch大小根据显卡显存调整显存不够优先降batch而不是降imgsz。5. 避坑记录标注格式与训练环节的五个高频问题这个数据集整体标注质量我抽查下来是靠谱的但训练过程中仍然有几个问题会反复出现。有些是这个数据集自身的特征导致的有些是目标检测任务通用的坑。5.1 类别顺序错位导致推理输出标签混乱现象训练过程正常loss正常下降mAP也不低但把训练好的模型拿到验证集上推理发现框的位置是准的类别标签却明显不对比如把褐飞虱识别成了茎螟。原因数据集的classes.txt里的类别顺序和数据集描述文档里的类别列表顺序不一致。训练时data.yaml里的names顺序写错了模型学到的类别ID映射和真实的类别映射错位。解决训练前打开labels目录下的classes.txt按里面的顺序配置data.yaml的names字段不要根据数据集描述文档里的列表去猜。如果已经训练完才发现这个错误只能修正配置后重训这个代价很大所以第一次配置时就要检查这个点。5.2 小目标过多导致验证集mAP虚低现象训练完看验证集mAP只有0.4左右但可视化推理结果时发现很多目标其实检出来了只是预测框和真实框的IoU不够高被判定为漏检。原因水稻害虫里褐飞虱、绿叶蝉这类目标在640分辨率下可能只有15到20个像素大小小目标的框回归误差对大目标的IoU计算方式更敏感几个像素的偏差就能让IoU从0.7掉到0.3。解决评估时同时关注mAP50和mAP50-95两个指标mAP50对框的位置精度要求低一些更能反映小目标检测的真实水平。如果小目标漏检严重优先考虑把输入分辨率从640提到960或者1280或者在推理时做多尺度测试增强。5.3 图像分辨率不一致导致标注比例失真现象训练过程中出现loss异常波动或者验证时某些图的检测效果特别差检查发现这些图的标注框位置明显偏了。原因数据集的图如果来自不同的采集设备长宽比可能不一致。YOLO格式的txt用的是归一化坐标短边被拉伸或压缩后标注虽然数值不变但实际对应的像素位置变形了。解决训练前统计所有图片的宽高比分布。如果差异较大在数据加载脚本里统一做letterbox预处理让图片等比缩放到统一尺寸多余区域用灰色填充。YOLOv8默认就带letterbox逻辑但如果自己写数据加载器这一步务必做。5.4 验证集和训练集存在相近场景导致精度虚高现象验证集mAP很高但模型在真实农田环境里表现明显变差泛化能力不足。原因这个数据集的图像如果来自连续拍摄或者同一地块的不同角度相似的背景和光照会在划分时同时出现在训练集和验证集里导致验证集评估结果偏乐观。解决划分时不要用完全随机的方式最好按拍摄批次或地块分组。先把图像按照采集来源排序同一来源的图分到同一个子集再从不同来源里抽图组分配给训练验证测试。这样可以避免数据泄漏。5.5 标注框重叠导致后处理NMS误抑制现象同一张图里密集分布的虫害目标推理时出现漏检尤其是一片区域内同时有多只虫时只输出了一个框。原因水稻害虫聚集性强标注框之间本身存在重叠。训练时如果标签分配策略对重叠框处理不好模型学到的是合并预测推理时NMS阈值稍低重叠的预测框就被抑制掉了。解决推理时调低NMS的IoU阈值YOLOv8里默认是0.45可以试着降到0.3或者0.25让重叠度较高的框也能保留下来。代价是可能多输出一些重复框但做检测计数类任务时漏检的代价更高。提示数据集中每张图的目标数量差异可能很大训练时如果开启mosaic增强要注意目标数量过多导致标注被裁剪掉的情况。6. 数据增强组合拳与小目标检测的验证技巧模型训练稳定之后真正拉开效果差距的其实是数据增强和数据利用的方式。这个数据集的类别尺度和数量分布有明确特征针对性地做增强和验证能比直接套默认配置多出几个点的mAP。第一个推荐的做法是使用YOLOv8自带的增强策略基础上增加小目标复制粘贴增强。具体做法是用脚本把图片中的小目标框提取出来随机粘贴到同一批次的其它图片上同时把对应的标注写入txt。这个策略对害虫这类小目标尤其有效等于在不增加采集成本的情况下扩充了小目标样本量。import cv2 import random import numpy as np def paste_small_objects(source_img, target_img, source_boxes, target_boxes): h, w target_img.shape[:2] for box in source_boxes: x1, y1, x2, y2 box obj_w x2 - x1 obj_h y2 - y1 if obj_w 32 and obj_h 32: cx random.randint(obj_w // 2, w - obj_w // 2) cy random.randint(obj_h // 2, h - obj_h // 2) nx1, ny1 cx - obj_w // 2, cy - obj_h // 2 nx2, ny2 nx1 obj_w, ny1 obj_h roi source_img[y1:y2, x1:x2] target_img[ny1:ny2, nx1:nx2] roi target_boxes.append((nx1, ny1, nx2, ny2)) return target_img, target_boxes上面这段脚本的思路是从一张图里提取小目标切片贴到另一张图的随机位置并生成新的框坐标。核心参数是obj_w和obj_h的阈值这里设为32像素小于这个尺寸的才算小目标可以按自己训练的imgsz调整。复制粘贴的目标图建议选背景干净一些的不然粘贴区域边缘会有明显色差模型容易学到不真实的纹理特征。第二个建议是把训练集里所有小目标单独抽取一份做二次训练。具体做法是先跑一轮基准训练记录下验证集里所有预测失败的样本把这些样本里gt框小于32像素的目标单独做一个子集用这个子集在原有模型基础上多训20到30轮。这种两阶段训练方式在害虫检测里效果很明显因为模型第一轮学到的是大目标特征为主第二轮针对小目标专项学习能有效拉高召回率。验证方面除了常规的mAP指标建议在测试集上额外统计小目标的AP值。YOLOv8的validation输出里会按目标尺寸分桶统计重点看ASmall那一列。如果ASmall明显低于其它尺寸桶的平均水平说明小目标还是短板优先调imgsz和数据增强策略如果ASmall和AMedium差距在5个点以内那这个数据集的利用基本到位了。最后提一个我在多个数据上验证过的习惯每轮训练前都随机重新划分一次数据集用不同划分下的mAP均值和方差来评估模型稳定性。单次划分的mAP高不一定是模型好可能只是划分运气好。这个数据集的图源比较集中多跑几次随机划分取多次训练的平均结果比盯着一轮结果下结论靠谱得多。从那以后我每次拿到新的检测数据集都强制走一遍同样的流程先看目录结构、再审计标注数值、然后抽查可视化、最后划分数据开训。这套流程看着多花了两三个小时但每次都能在训练前期就暴露数据问题而不是等模型训完才发现标注错位或者划分泄漏。这份水稻虫害数据集本身是干净且可直接使用的把前面几步走扎实训练结果会比较顺利希望这一套流程对你也有帮助。本文还有配套的精品资源点击获取
返回列表