简介农业害虫目标检测数据集是一份面向智能农业与作物保护领域的目标检测训练资源适合农林院校、农业AI开发者及无人机植保团队使用。数据集中包含378张农业场景图像覆盖蚜虫、粘虫成虫与幼虫、黑切虫成虫与幼虫五类高危害害虫的典型形态并采用YOLO格式的归一化边界框标注可直接导入YOLOv5/v8等主流框架训练减少预处理成本。整个压缩包共758个文件包括378个jpg图像、378个txt标注、1个yaml配置文件及1个docx说明文档包体约18.11MB结构简洁便于用户快速开展训练与验证。数据源自实际农田监控环境图像包含复杂背景与害虫多样姿态有助于提升模型在野外部署时的鲁棒性除目标检测任务外还可延伸用于害虫分类、计数等衍生研究配合说明文档可系统了解标注规范与类别定义。目前已获得483人学习下载适合需要真实农业场景数据来训练害虫识别模型的研究者与工程人员。1. 农业害虫目标检测数据集先想清楚它能不能落地再解压农业害虫目标检测数据集这几个字听起来像是把一堆农田图片丢给你实际上它是一份结构明确的目标检测训练资源农作物害虫图片配上 YOLO 格式的 txt 标注整体打包成 zip 文件分发。它的价值在于省掉最耗时的标注环节让你直接把精力放在模型训练和落地场景上无论是做智能虫情测报灯、田间摄像头还是植保无人机图像识别都能拿它当第一份训练数据。适合它的用户是手上已经有目标检测基础、缺的只是高质量带标注数据的人以及想完整跑通一遍 YOLO 训练链的学生或工程师。但我也见过不少人拿到这类包后当晚就翻车原因不是模型难调而是没先搞清楚包内目录规则和标注含义直接把脏数据喂进了训练脚本。2. 数据集包从里到外目录结构、标注格式与类别索引对应2.1 解压后的第一件事把目录树和文件完整性摸清楚拿到“农业害虫目标检测数据集22.zip”这样一个压缩包我一般不会急着写训练脚本而是先解压把目录结构看明白。这里有个细节Windows 环境我常用 7-Zip 右键解压Linux 服务器上则用 unzip。两种方式在长文件名和中文文件名上的表现有差异我遇到过 Windows 压缩包在 Linux 下中文名乱码的情况所以稳妥起见会先在解压前跑一遍完整性测试unzip -t 农业害虫目标检测数据集22.zip | tail -n 10这段命令是测试模式不真正解压文件只检查压缩包内部的 CRC 校验。tail -n 10让输出只保留末尾 10 行看到 “No errors detected in compressed data” 这类结论就可以了如果有文件损坏这里会显示error: invalid compressed data to inflate。测试通过之后再正式解压unzip -q 农业害虫目标检测数据集22.zip -d pest_dataset参数说明-q是安静模式避免成百上千个文件名刷屏-d指定解压到 pest_dataset 目录。解压完我习惯用tree看一眼整体结构没有 tree 命令时用find代替find pest_dataset -maxdepth 2 -type d | sort标准 YOLO 数据集通常长成下面这个结构pest_dataset/ ├── images/ │ ├── train/ │ │ └── 000001.jpg │ └── val/ │ └── 000002.jpg ├── labels/ │ ├── train/ │ │ └── 000001.txt │ └── val/ │ └── 000002.txt ├── classes.txt └── data.yaml这里有个核心规则images 和 labels 目录下的文件名必须一一对应000001.jpg的标注只能叫000001.txt后缀可以不同但主名必须相同。很多从网上下载的数据集并不完全长这样有的图片和标注混在一个目录有的多了一层annotations目录还有的残留着 VOC 格式的.xml标注。这些都不影响使用但需要先整理因为 YOLO 训练只认“图片目录 标签目录”这一套。我还会顺手检查图片和标签数量是否一致。最典型的坑是图片总张数和 txt 总张数对不上训练集里多出几张没有对应标注的图或者多几个孤立的 txt 文件。出现这种情况先统计一下ls images/train | wc -l ls labels/train | wc -l如果差得不多大概率是标注人员漏标了几张或者打包时混进了预览图。漏标图我一般保留在目录里但不放 labels等于让模型当作负样本处理但如果这个数量超过总样本的 5%就要清理掉否则模型会花太多精力学“空场景”训练出来的模型对真实害虫的响应变钝。2.2 标注 txt 的每一行其实是一个五元组YOLO 的 txt 标注是纯文本每行代表一个目标框。我常用一个小脚本把前几行读出来from pathlib import Path txt_path Path(labels/train/000001.txt) lines txt_path.read_text().strip().splitlines() for idx, line in enumerate(lines[:5]): parts line.split() cls int(parts[0]) cx, cy, w, h map(float, parts[1:]) print(f第{idx}个目标: class{cls}, cx{cx:.4f}, cy{cy:.4f}, w{w:.4f}, h{h:.4f})输出类似这样第0个目标: class3, cx0.5820, cy0.4414, w0.2344, h0.4023 第1个目标: class7, cx0.6836, cy0.4922, w0.1875, h0.3125每一行五个数字的含义依次是类别索引、目标中心点的横坐标比例、中心点的纵坐标比例、目标宽度比例、目标高度比例。所谓“比例”是指相对于图片宽高的归一化值取值范围在 0 到 1 之间。比如cx0.5820表示目标中心在图片宽度的 58.2% 位置。要还原成像素坐标只需要对图片宽高做一次乘法import cv2 img cv2.imread(images/train/000001.jpg) H, W img.shape[:2] # OpenCV 返回的高在前、宽在后 x1 int((cx - w / 2) * W) y1 int((cy - h / 2) * H) x2 int((cx w / 2) * W) y2 int((cy h / 2) * H) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite(check.jpg, img)这段“反归一化”逻辑不只为验证坐标更重要的是发现坏数据如果坐标里出现大于 1 或者负数的值说明这批 txt 不是 YOLO 原生格式很可能从 VOC 或其他标注平台导出时没有做归一化直接带了像素坐标进来。这种数据不清理模型训练早期就会在 loss 计算时出现异常。还有一个容易被忽略的点是类别索引。classes.txt文件里每一行的顺序就是类别 ID 的顺序第一行对应 ID 0第二行对应 ID 1。这个包里的 txt 大多从 LabelImg 或 X-AnyLabeling 这类目标检测标注工具导出这些工具默认会维护一个 classes.txt。整理数据时我始终以包内 classes.txt 的行号为准不凭文件名猜类别。提示如果 classes.txt 里的类别名含空格或大写字母没关系模型输出的是索引最后显示类别名靠 names 映射但nc必须与 classes.txt 行数一致否则训练时报错。3. 用 YOLOv8 跑起来先把目录和数据配置对齐3.1 写 data.yaml 前先想清楚你是在“能跑”还是在“能落地”数据配置是所有 YOLO 项目里看起来最不起眼、却最容易出错的一环。我看到的失败案例里有一半不是模型问题而是 yaml 里路径写错、类别数量不对、或者验证集指向了训练集。常见配置如下# pest_data.yaml path: /home/user/pest_dataset train: images/train val: images/val nc: 12 names: 0: aphid 1: whitefly 2: leafhopper 3: armyworm 4: cotton bollworm 5: beet armyworm 6: diamondback moth 7: spodoptera litura 8: borer 9: locust 10: spider mite 11: thrips参数说明path是整个数据集的根目录我推荐写成绝对路径。为什么不用相对路径因为这个文件可能被多个脚本复用一旦当前工作目录变了相对路径会把训练命令带偏报的错还很难看出来。train和val是相对于 path 的目录不要在前面加斜杠或./。nc是类别总数必须和 names 列表长度一致一个常见错误是只改了 names 没改 ncultralytics 会直接报 nc 不匹配。names的顺序必须和 classes.txt 一致我习惯直接复制包内的 classes.txt 内容不全凭记忆写。写完后用下面这行命令做一个“冒烟测试”验证数据能否被正常加载python -c from ultralytics import YOLO; m YOLO(yolov8n.pt); m.train(datapest_data.yaml, epochs1, imgsz640, batch2, devicecpu)跑一个 epoch重点看日志里是否出现Scanning labels/且后面没有报错。如果这一步顺利再换正式训练命令。3.2 正式训练的命令参数不是越大越好单卡 GPU 训练是最常见的情况命令如下yolo detect train \ datapest_data.yaml \ modelyolov8n.pt \ epochs150 \ imgsz640 \ batch16 \ device0 \ projectruns/pest_detect \ nameexp01 \ patience80 \ cos_lrTrue参数拆解modelyolov8n.pt使用 nano 版本预训练权重数据集如果在千张量级nano 已经够用换成yolov8s.pt训练时间明显变长最终 mAP 不一定更高。epochs设 150 是为了配合 early stopping实际可能在 60 到 100 就停了这很正常。imgsz640是最稳妥的起步值但如果数据里有大量像蚜虫、红蜘蛛这种二三十像素的小目标这个值可能需要改成 1024 或 1280后面避坑章节会展开。batch16在 8G 显存上比较稳24G 显存可以调到 32显存小就降到 8否则报CUDA out of memory。device0指定第一张显卡。训练过程中真正该看的是项目目录下自动生成的results.png它把 loss、精度、召回、mAP 全部画成曲线。曲线有锯齿是正常的但如果一路跌到 NaN问题多半在数据集而不是超参数。不要一上来就调学习率先去查标注。3.3 训练完之后用验证集做一次带框可视化验证训练完命令行会打印每个类别的 AP但数值好看不等于模型能用在你的实际场景。我用下面的命令把验证集预测结果画出图来yolo detect val \ modelruns/pest_detect/exp01/weights/best.pt \ datapest_data.yaml \ save_jsonTrue \ save_txtTrue \ save_confTrue参数说明save_jsonTrue生成predictions.json里面是每张图上每个预测框的类别、置信度和坐标后续统计很方便save_txtTrue把每张图的预测结果写成 YOLO 格式文本save_confTrue会在 txt 里追加置信度列否则默认只输出类别和坐标。我拿这个 json 再做一次统计看每个类别的预测框数量与标注数量差异如果一个类实际有 200 框预测只出了 30 框基本是漏检严重如果预测出了 500 框那就是误检严重。这一步比单一 mAP 数值直观得多。验证集是模型没见过但“同分布”的数据mAP 看着不错换到实际场景立刻掉这不算玄学而是分布偏移。真正要做的验收我在最后一章单独讲。4. 训练前给数据集做全身体检三类检查脚本与划分逻辑4.1 样本量和类别分布决定你该用哪个模型数据集包里的图片数量、每个类别的框数决定了后续所有策略。不检查直接开训等于把黑匣子赌在运气上。我先统计最基础的两个数字图片总数和每个类别的目标框数。# check_labels.py from pathlib import Path from collections import Counter label_dir Path(labels/train) class_counter Counter() empty_txt 0 total_txt 0 total_boxes 0 for txt in label_dir.glob(*.txt): total_txt 1 lines [ln.strip() for ln in txt.read_text().splitlines() if ln.strip()] if not lines: empty_txt 1 continue for ln in lines: cls int(ln.split()[0]) class_counter[cls] 1 total_boxes 1 print(f标注文件总数: {total_txt}) print(f空标注文件数: {empty_txt}) print(f总目标框数: {total_boxes}) for idx in sorted(class_counter): print(fclass {idx}: {class_counter[idx]} boxes)脚本逻辑遍历标签目录下所有 txtlines是过滤掉空行后的有效行无有效行记为空标注每行第一个字段是类别索引用int()转成整数后累加。参数说明label_dir可以换成labels/val或合并后的目录就能统计整个包。如果脚本在这里报错说明文件格式不是 YOLO 纯文本可能是 CSV 或者 XML 残留。怎么解读结果某个类只有 100 来个框另一个类却有 3000 框我会把前者归为“尾部类”。训练时尾部类即使最终 mAP 数值不错实际预测中也容易被漏掉因为整个 loss 被大头类主导。一个缓解手段是给这些类多复制样本或者业务允许时合并相近类别把类别数从 12 降到 6 到 8。4.2 检查坐标越界和过小框别让坏标注带偏 loss坐标越界是数据集里比较隐蔽的问题。我一般这样查# check_bad_boxes.py from pathlib import Path bad_boxes [] small_boxes [] for txt in Path(labels/train).glob(*.txt): for ln in txt.read_text().strip().splitlines(): parts ln.split() if len(parts) ! 5: bad_boxes.append((txt.name, 列数不对, ln)) continue cls, cx, cy, w, h int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) if not (0 cx 1 and 0 cy 1 and 0 w 1 and 0 h 1): bad_boxes.append((txt.name, 越界, (cls, cx, cy, w, h))) if 0 w 0.005 or 0 h 0.005: small_boxes.append((txt.name, 尺寸过小, (cls, w, h))) print(f异常标注行: {len(bad_boxes)}) print(f过小目标框: {len(small_boxes)}) for item in bad_boxes[:10]: print(item)参数说明合法 YOLO 坐标的 cx、cy 在 0 到 1 之间w、h 也应在 0 到 1 之间且不为 0。出现越界通常有两种来源一是标注工具导出时坐标系算错把基于左上角坐标的格式直接当 YOLO 写二是图片被裁剪后标注没有跟着更新。过小框阈值我取 0.005意思是目标宽度小于图片宽度的 0.5%在 640 分辨率下大概就是不到 4 个像素这种框基本是噪声。对于异常行我一般先可视化看具体图确认是“该删”还是“该修”。个别越界直接删行几百行越界说明整个标注格式有问题需要回到导出流程重新处理。4.3 划分训练集和验证集保持类别分布不漂有的资源包会直接把 train 和 val 分好有的只有一个大目录。后者就需要自己划分。我用随机划分加固定随机种子保证每次跑出来的结果一致# split_dataset.py import random import shutil from pathlib import Path random.seed(42) train_dir Path(images/train) / imgs val_dir Path(images/val) / imgs train_dir.parent.mkdir(parentsTrue, exist_okTrue) val_dir.parent.mkdir(parentsTrue, exist_okTrue) all_images sorted(list(Path(images/all).glob(*.jpg))) random.shuffle(all_images) split_idx int(len(all_images) * 0.9) for img in all_images[:split_idx]: shutil.copy(img, train_dir / img.name) src_lbl Path(labels/all) / (img.stem .txt) if src_lbl.exists(): shutil.copy(src_lbl, Path(labels/all) / (img.stem .txt)) for img in all_images[split_idx:]: shutil.copy(img, val_dir / img.name)逻辑说明先建目录再按 9:1 比例复制图片random.seed(42)固定随机序列否则每次划分不同后续对比无法复现。这里的关键点是图片复制了但 txt 不存在时那张图会被当作无目标负样本更稳的做法是划分前先校验图片和 txt 一一对应缺 txt 的图片直接不进入训练集。我在脚本中故意保留if src_lbl.exists()是为了方便观察哪些图缺标签你也可以改成日志输出。划分比例通常用 9:1 或 8:2。害虫数据如果总量很少8:2 会让验证集只有几十张mAP 波动非常大这时我会改用 k 折交叉验证的思路把数据分成 5 份轮流做验证集最终取均值。但这不是必须的先用 9:1 跑通流程后面有时间再精细化。5. 农业害虫数据避坑记录三个最容易翻车的地方5.1 zip 报“加密”但解不开先确认是不是伪加密现象下载得到的“农业害虫目标检测数据集22.zip”在命令行里用 unzip 解压直接提示要密码但下载页面和包内 README 里都没有写密码换 7-Zip 测试时有的版本能直接通过有的版本也要求输密码。原因这大概率不是真加密而是 zip 文件头里的加密标志位被错误置位业界叫“伪加密”。真加密时压缩包里的文件数据是被密钥变换过的伪加密则只是标志位写了 1数据本身没加密因此 7-Zip 等工具会选择忽略该标志直接解压而 unzip 这类严格按规范走的工具会坚持要密码。解决先判断是真是假别急着找“破解工具”。用下面的命令查看加密标志zipinfo -v 农业害虫目标检测数据集22.zip | grep -i encryption如果显示encryption: none但解压又提示密码基本确定是伪加密。我用 7-Zip 直接试解压多数场景下它不问密码就出来了如果 7-Zip 也问我会尝试用它的修复功能重置一次文件头问题通常就消失。不建议去下载来历不明的“Zip 密码移除”工具这些小工具对几十 MB 的文件也许有效对动辄几个 GB 的数据集会卡死还容易被捆绑安装。若分享方明确给了密码那密码通常写在下载说明或包内 readme 里先找一遍再折腾。解压之后记得再用unzip -t测试一次完整性因为伪加密修复偶尔会造成个别文件 CRC 错带着坏文件训练后面会随机报错。5.2 训练时 loss 变成 NaN别急着调学习率现象训练跑到第 40 个 epoch 左右loss 曲线突然从 0.7 掉到 NaN或者训练没报错但验证阶段 mAP 一直是 0点开预测图发现模型把整张图都标记成背景。原因我在多个数据集里复现过这个问题最后归因基本都是标注文件里的脏数据。最常见的三种一是空 txt 文件造成的YOLO 把空 txt 当负样本但如果负样本比例过大损失函数在早期不稳定二是某一行坐标越界比如 cx12.34这会让目标框和真实框的 IoU 计算异常三是标注类型混用比如一行里有逗号分隔而不是空格分隔解析时把多个字段当成了一个字符串。解决先用第 4 章的体检脚本把空 txt 和越界行列出来这一步能解决掉 90% 的 NaN。如果脚本没查出来就去看results.png里是哪个 loss 先变成 NaN如果是box_loss先崩基本是坐标问题如果是cls_loss先崩更可能是类别索引对不上。别一上来就改学习率这个锅学习率背不起。另外空 txt 不一定全部要删YOLOv8 支持负样本它会用“没有目标”的图参与背景分类。但空标注文件比例超过 10% 时我会把部分空图从训练集移走因为大多数 batch 被背景主导模型学不到害虫特征。把这些空标注单独拎到一个目录观察它们是不是集中在特定背景下再决定去留。5.3 小目标怎么都检不出来imgsz 640 不一定是标准答案现象训练和验证时大个头的鳞翅目害虫菜青虫、棉铃虫识别得很好mAP50 能到 0.8 以上但蚜虫、飞虱、红蜘蛛这些小目标类别mAP50 基本在 0.2 以下预测结果里也几乎看不到它们的框。原因一个 30 像素宽的蚜虫在 640x640 的输入里占不到图像宽度的 5%。经过 YOLOv8 的骨干网络下采样 5 次后这个目标的特征可能只剩 2 个像素左右在特征金字塔里几乎无迹可寻。这属于输入分辨率和目标尺寸的结构性矛盾不是把 confidence 阈值调低一点就能解决的。解决分几层处理。第一把训练输入尺寸提高到imgsz1280小目标的像素面积变成原来的 4 倍特征不再轻易丢失显存不够就把 batch 从 16 降到 8。第二推理时用 SAHI 这类切片推理方案把大图切成带重叠的 patch每个 patch 单独推理最后再把框坐标合并回去这个方案不用重训只改推理流程。第三训练时加 copy-paste 增强把一张图里的小目标复制到另一张图YOLOv8 默认开 mosaic但 mosaic 对小目标帮助有限copy-paste 更直接。改进之后要做的验证是单独统计小目标类别的 AP。只看整体 mAP 无法发现小目标变好还是变差因为大目标类别数量多会把均值拉高。我一般用验证集的 json按类别输出 AP再对照面积阈值小于 32x32 像素算小目标看单独指标这样心里才有底。6. 验收模型mAP 之外还要过一遍实拍图6.1 用训练好的权重做批量推理训练结束后最直接的做法是拿runs/pest_detect/exp01/weights/best.pt对一批新场景图做推理yolo predict \ modelruns/pest_detect/exp01/weights/best.pt \ sourcereal_field_photos/ \ saveTrue \ conf0.25参数说明source指向一个目录时会对里面所有图片做推理saveTrue把画好框的结果保存到runs/detect/predictconf0.25过滤低置信度框。我要强调一个习惯source 目录里放的是“它没见过的场景”最好和训练集不在同一天、同一设备上采集。比如训练集是实验室白背景拍的那验收就放田间黄板或农场监控截图这样才能看出真实分布差异。6.2 别只盯 mAP先看 P、R 和每类 AP指标含义害虫场景侧重mAP50IoU 阈值 0.5 下的平均精度粗略看漏检情况mAP50-95IoU 从 0.5 到 0.95 的平均精度框定位精度PrecisionP预测框里确实有目标的比率误检高低RecallR真目标被检出来的比率漏检高低害虫检测里我优先看 Recall因为漏检一只虫意味着农情报告可能漏报一条信息Precision 低一点后期可以用更高的 conf 阈值卡掉误检。每类 AP 也是必看的整体 mAP 高但某一类低常见于小目标和背景复杂的目标按类处理才有效果。我第一次用这类农业害虫数据集时mAP50 跑到了 0.68觉得自己已经搞定了结果拿回去对着一块粘虫板实拍图一跑掉得惨不忍睹。原因后来排查清楚了训练图都是俯拍单虫背景干净而实拍有黄板反光、虫子重叠、光线偏色。从那以后我每次训练完都强制走一遍新场景实拍图推理把漏检的框手动标记出来回看是哪个类别、什么姿态、什么背景再决定是补数据还是调增强。这个流程如果省了后面返工的时间会成倍补回来。农业害虫数据集能不能用不是看验证集 mAP 有多漂亮而是看你把它放进真实场景之后还能不能在复杂背景里把那只蚜虫找出来。希望这段经验能帮你少绕两次弯路。本文还有配套的精品资源点击获取