简介:这份资源面向从事农业虫害智能监测、目标检测算法练习与课程设计的研究者与开发者,提供柑橘害虫检测的YOLOv5格式数据集,可直接投入训练,省去格式转换与标注整理环节。数据聚焦苍蝇与木虱两类害虫,图像为1000至4000像素的大尺度RGB实拍图,覆盖真实果园场景,适合检验模型对小目标与高分辨率输入的适应能力。压缩包共603个文件,以301个txt标注文件、300张jpeg图像为主,另附1个可视化py脚本与1张png示意图,整体约260MB;其中训练集含240张图片及对应标签,验证集含60张图片及对应标签,并给出2类别文本信息。可视化脚本无需修改即可运行,随机传入一张图片便能绘制边界框并保存到当前目录,便于快速核查标注质量。目前已有402人学习,适合作为虫害检测入门与算法对比的实用数据基础。
1. 柑橘害虫检测数据集:2 类别、YOLOV5 目录格式到底解决了什么问题
柑橘园的虫害防治有个尴尬现实:果农发现叶片卷曲、果实出现蛀孔时,往往已经错过最佳施药窗口。人工巡园一天走下来,能覆盖的株数有限,而且不同人对虫态的识别标准不一致。把这件事交给视觉模型,前提是得有一份标注规范、目录结构统一、能直接喂给 YOLOV5 训练流程的数据集。这份柑橘害虫检测数据集就是干这个的——2 个类别,训练集和验证集分开,目录格式对齐 YOLOV5 的要求,拿到手改个 data.yaml 就能开跑。
它适合三类人:一是做农业视觉方向、想快速验证检测方案可行性的算法同学;二是手里有果园图像但不知道怎么整理成训练格式的工程人员;三是拿它当目标检测练手项目、想跑通「数据集到推理」完整链路的学习者。2 类别意味着任务本身不复杂,模型收敛快,单卡就能训,重点不在堆算力,而在把数据组织、标注校验、训练配置这几步做扎实。下面从目录结构讲起,一路讲到训练、评估和踩坑。
2. YOLOV5 目录格式拆解:从 images/labels 到 data.yaml 的完整链路
2.1 为什么 YOLOV5 认这套目录,而不是别的
YOLOV5 的数据加载逻辑写在 datasets.py 里,它不关心你的图片叫什么名字,只认两件事:图片路径和对应的标签路径之间存在可推导的映射关系。默认规则是把路径里的/images/替换成/labels/,再把扩展名换成.txt。所以只要你的目录满足这个替换规则,YOLOV5 就能自动配对,不需要额外写索引文件。
常见做法是长这样:
citrus_pest/ ├── images/ │ ├── train/ │ │ ├── 0001.jpg │ │ └── ... │ └── val/ │ ├── 0101.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── 0001.txt │ │ └── ... │ └── val/ │ ├── 0101.txt │ └── ... └── data.yaml注意 images 和 labels 是同级目录,train/val 各自对应。很多人第一次整理时把 labels 塞进 images 里面,结果训练时提示找不到标签,翻车就翻在这里。YOLOV5 的路径替换是字符串级别的,images/train/0001.jpg替换后得到labels/train/0001.txt,如果你的实际结构是images/train/labels/0001.txt,那自然对不上。
标签文件是每行一个目标,格式为class_id x_center y_center width height,后四个值都是归一化到 0~1 的相对坐标。这里有个容易忽略的点:归一化用的是整张图的宽高,不是标注框的宽高。我见过有人把宽高也按框自身归一化,训练 loss 一直不降,排查半天才发现是标注坐标算错了。
2.2 把原始标注转成 YOLO txt:脚本与参数说明
假设你手里是 LabelImg 导出的 XML(VOC 格式),或者从标注平台导出的 JSON,需要转成 YOLO txt。下面这个脚本处理 VOC XML,逻辑清晰,改几行就能适配其他格式:
import xml.etree.ElementTree as ET import os # 类别映射:根据你的数据集实际类别名修改 CLASS_MAP = {"citrus_leaf_miner": 0, "citrus_aphid": 1} def voc_to_yolo(xml_path, img_w, img_h, out_path): tree = ET.parse(xml_path) root = tree.getroot() 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) # 转为中心点 + 宽高,再归一化 x_center = (xmin + xmax) / 2.0 / img_w y_center = (ymin + ymax) / 2.0 / img_h w = (xmax - xmin) / img_w h = (ymax - ymin) / img_h # 裁剪到 [0,1],防止标注越界导致训练异常 x_center = min(max(x_center, 0.0), 1.0) y_center = min(max(y_center, 0.0), 1.0) w = min(max(w, 0.0), 1.0) h = min(max(h, 0.0), 1.0) lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}") with open(out_path, "w") as f: f.write("\n".join(lines))逻辑说明:先读 XML 里的 object 节点,拿到类别名和边界框坐标。类别名通过 CLASS_MAP 转成 0/1 的整数 ID,这一步必须和 data.yaml 里的 names 顺序一致,否则模型学到的类别会错位。坐标转换是核心:xmin/ymin/xmax/ymax 是绝对像素值,先算中心点和宽高,再分别除以图片宽高做归一化。最后裁剪到 [0,1] 是防御性写法,实际标注里偶尔会出现框超出图片边界的情况,不裁剪的话 YOLOV5 会警告甚至报错。
参数说明:img_w 和 img_h 必须用该图片的真实尺寸,不能统一用某个固定值。如果你的图片尺寸不一致,建议在转换前先统一 resize,或者转换时逐张读取尺寸。CLASS_MAP 的键要和标注文件里的 name 完全匹配,大小写敏感。
2.3 data.yaml 的四个字段与路径写法
data.yaml 是 YOLOV5 训练时的入口配置,字段不多但每个都关键:
path: /data/citrus_pest # 数据集根目录 train: images/train # 相对 path 的训练图片目录 val: images/val # 相对 path 的验证图片目录 nc: 2 # 类别数 names: ["citrus_leaf_miner", "citrus_aphid"] # 类别名,顺序对应 class_idpath 写绝对路径最稳妥,train 和 val 写相对 path 的路径。names 列表的顺序就是 class_id 的顺序,0 对应第一个,1 对应第二个。如果你只有 2 个类别但 names 写了 3 个,训练时不会立刻报错,但评估阶段计算 mAP 时会出现类别对不上的问题。nc 必须等于 len(names),这是硬性约束。
提示:data.yaml 里不要写中文路径,YOLOV5 在某些环境下对非 ASCII 路径处理不稳定,容易在 DataLoader 阶段报编码错误。
3. 用这份数据集跑通 YOLOV5 训练:环境、命令与参数调优
3.1 环境配置:conda 建环境到依赖安装
YOLOV5 对环境的要求不算苛刻,但版本对不上会出各种玄学问题。我一般用 conda 建一个干净环境,Python 选 3.8 或 3.9,这两个版本和 PyTorch 的兼容性最稳:
conda create -n yolo5 python=3.9 -y conda activate yolo5 # 安装 PyTorch,根据你的 CUDA 版本选对应命令 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 克隆 YOLOV5 源码后安装依赖 git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txtCUDA 版本用nvidia-smi看右上角的 CUDA Version,然后去 PyTorch 官网找对应安装命令。如果装完torch.cuda.is_available()返回 False,大概率是 PyTorch 版本和驱动不匹配,卸载重装比折腾环境变量快。
3.2 训练命令与关键参数怎么设
数据准备好之后,训练命令本身不复杂:
python train.py \ --data /data/citrus_pest/data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0 \ --project runs/train \ --name citrus_exp1参数逐个说:--weights yolov5s.pt用预训练权重,2 类别的任务从 COCO 预训练模型微调,收敛速度比从头训快很多,通常 50~100 epoch 就能到不错的 mAP。--img 640是输入分辨率,柑橘害虫目标通常不大,640 是起点,如果虫体在图中占比很小,可以提到 1024,但显存占用会翻倍。--batch 16在 8G 显存上跑 640 分辨率基本够用,显存不够就降到 8,或者用--batch -1让 YOLOV5 自动选。--epochs 100配合预训练权重通常足够,如果验证集 mAP 在 60 epoch 后还在涨,可以加到 150。
--device 0指定第一块 GPU,多卡用--device 0,1。--project和--name控制输出目录,训练日志、权重、混淆矩阵都会存在runs/train/citrus_exp1/下面。
3.3 训练过程看什么:loss 曲线与 mAP 的判读
训练启动后,控制台会逐 epoch 打印 box_loss、obj_loss、cls_loss 和 mAP@0.5。box_loss 衡量边界框回归误差,obj_loss 是目标置信度,cls_loss 是分类误差。三个 loss 整体趋势应该是下降的,如果某个 loss 震荡剧烈或者不降,对应的问题不同。
box_loss 不降,通常是标注框坐标有问题,回头检查归一化是否正确。obj_loss 不降,可能是正负样本比例失衡,柑橘害虫在叶片上往往是小目标密集分布,可以试试调整 anchor 或者用--rect做矩形推理。cls_loss 不降,检查类别映射是否和 data.yaml 一致。
mAP@0.5 是主要评估指标,2 类别任务在 100 epoch 后通常能到 0.85 以上,如果低于 0.7,先别急着调模型,把验证集的可视化结果拉出来看,大概率是标注质量问题。
注意:训练中途不要频繁中断再 resume,YOLOV5 的 resume 逻辑会恢复优化器状态,但数据加载器的随机种子可能变化,导致 loss 曲线出现跳变,影响判断。
4. 避坑与排查:标注、路径、显存这三类问题最容易翻车
4.1 标签文件为空或格式错误
现象:训练启动后提示No labels found,或者某个 epoch 的 obj_loss 直接是 nan。
原因:标签文件为空(图片里没有目标但生成了空 txt),或者每行字段数不对(比如只有 4 个值,少了 class_id)。YOLOV5 对空标签文件是容忍的,但格式错误会直接导致解析失败。
解决:写个校验脚本遍历所有 labels 目录下的 txt,检查每行是否恰好 5 个字段、class_id 是否在 [0, nc-1] 范围内、坐标是否在 [0,1] 之间。发现异常就打印文件名和行号,逐个修。
4.2 图片和标签文件名对不上
现象:训练时提示images and labels count mismatch,或者某些图片被跳过。
原因:图片是0001.jpg,标签是0001.JPG.txt或者0001_1.txt,路径替换后找不到对应文件。YOLOV5 只做扩展名替换,不做模糊匹配。
解决:用脚本批量检查 images 和 labels 目录下的文件名(去掉扩展名后)是否一一对应。不对应的要么改名,要么删掉。我一般会在转换脚本最后加一步自动校验,省得训练时才发现。
4.3 显存溢出与 batch size 的取舍
现象:训练启动几秒后报CUDA out of memory。
原因:batch size 太大、img size 太大、或者模型选了 yolov5l/x 这种大模型。8G 显存跑 yolov5s + 640 + batch 16 是安全的,但换成 yolov5m 就可能爆。
解决:优先降 batch,从 16 降到 8 再试。如果还爆,降 img 到 512。实在不行换 yolov5n。另外--workers设太大会导致内存占用高,一般设 4 或 8 就够,设 16 反而可能因为数据加载进程过多拖慢训练。
4.4 验证集 mAP 远低于训练集
现象:训练集 loss 很低,但验证集 mAP 只有 0.5 左右。
原因:训练集和验证集分布不一致,比如训练集全是晴天拍摄,验证集有阴天或逆光图片;或者验证集里某个类别的样本太少,模型没学好。
解决:先看混淆矩阵,确认是哪个类别拖后腿。如果是样本不均衡,可以在训练时用--weights加载预训练权重后冻结 backbone 先训几轮,再解冻全量微调。另外检查验证集标注是否和训练集用了同一套标准,标注尺度不一致也会导致 mAP 偏低。
4.5 推理时检测框偏移或漏检
现象:用训练好的 best.pt 推理,框的位置明显偏了,或者小目标漏检。
原因:推理时的 img size 和训练时不一致,YOLOV5 会做 letterbox 缩放,但如果推理代码里手动 resize 没保持长宽比,坐标映射就会错。小目标漏检通常是训练分辨率不够,或者 anchor 尺寸不匹配。
解决:推理时用--img指定和训练相同的尺寸,并且用 YOLOV5 自带的 detect.py,它内部处理了 letterbox 和坐标还原。小目标问题可以试试在训练时加--img 1024,或者用--rect做矩形训练,减少 padding 带来的信息损失。
5. 从 2 类别到更多类别:数据增强与类别扩展的实操技巧
这份数据集只有 2 个类别,跑通之后如果想扩展到更多害虫种类,或者提升现有类别的检测精度,有几个方向可以试。
第一个是数据增强。YOLOV5 内置了 mosaic、mixup、HSV 增强,训练时默认开启 mosaic。对于柑橘害虫这种小目标场景,mosaic 把 4 张图拼成 1 张,等效于增加了小目标的出现频率,效果通常不错。如果发现模型对遮挡场景表现差,可以调高--mixup的比例,但 mixup 对小目标不太友好,容易把虫体混没,建议从 0.1 开始试。
第二个是类别扩展。新增类别时,不需要重新标注所有旧数据,只需要在新图片上标注新类别,然后在 data.yaml 里把 nc 改成新的类别数,names 列表追加新类别名。但要注意,旧数据的标签文件里 class_id 不变,新类别的 class_id 从旧的最大值往后排。如果旧数据里某个类别被合并或删除,需要批量改标签文件里的 class_id,这个操作不可逆,改之前先备份。
第三个是验证方法。训练完成后,除了看 mAP,我习惯用val.py跑一遍验证集,加上--save-txt和--save-conf,把预测结果和置信度存下来。然后写个小脚本统计每个类别的漏检和误检数量,漏检多说明 recall 不够,可以调低置信度阈值;误检多说明 precision 不够,可以调高 NMS 的 IoU 阈值。这两个参数在 detect.py 里分别是--conf-thres和--iou-thres,默认 0.25 和 0.45,实际部署时根据业务容忍度调整。
最后一个技巧是关于 anchor 的。YOLOV5 默认 anchor 是基于 COCO 数据集聚类出来的,如果你的害虫目标尺寸和 COCO 里的通用目标差异大,可以跑一遍python utils/autanchor.py --data data.yaml重新聚类 anchor,替换模型配置文件里的 anchor 值。这一步对 mAP 的提升通常在 1~3 个点,代价是要重新训练。
我自己踩过最深的坑是标注一致性。同一张叶片上,不同标注人员对「虫体边界」的理解不一样,有人框得紧,有人框得松,模型学出来的框就会忽大忽小。后来我定了个规矩:标注框统一包含虫体完整轮廓,不留触角,不切翅膀。这个标准写进标注手册之后,验证集 mAP 稳定了不少。数据质量这件事,工具帮不了你,只能靠规范和复核。希望帮到你。
本文还有配套的精品资源,点击获取