简介:面向YOLO系列目标检测训练与评估的昆虫检测数据集,内含1108张真实场景JPG图片,覆盖蝴蝶、蚂蚱、蟑螂等5类常见昆虫,场景丰富,适合目标检测算法练习、模型测试与教学演示。压缩包共包含3325个文件,除1108张原始图片外,还提供1108个VOC格式xml标注和1109个YOLO格式txt标注,两种标签按目录分开存放,可直接套用YOLO训练流程,省去格式转换和目录整理;压缩包约159.48MB,结构清晰易检索。目前已有2158人学习下载。所有图片均使用lableimg逐张标注,边界框与类别信息完整,VOC/YOLO双格式兼顾不同框架使用习惯;配套博客提供了检测结果参考,便于对照验证模型精度与调参方向。无论用于昆虫识别、农业巡检还是目标检测入门实践,这份数据都能帮助读者快速搭建训练样本集,减少数据准备环节的时间投入。
1. YOLO昆虫检测数据集:从"有图"到"能训出模型"的真实一步
YOLO昆虫检测数据集这个资源,第一眼看上去就是一堆jpg和标注文件,但真正上手做过目标检测的人都知道,数据集和数据集之间的差距比模型和模型之间的差距还大。这个数据集有1000多张真实场景图、5类常见昆虫,用labelimg人工标注过,VOC和YOLO两种格式的标签分别归在两个文件夹里,下载下来就能直接喂给YOLOv5、v8甚至v11去训练。适合的人群很具体:刚接触目标检测、讨厌自己爬图自己标、或者正在做农业害虫监测类项目但苦于公开虫类数据太少的从业者。我拆这个数据集时最直观的感受是:场景足够杂、背景足够乱、目标足够小,属于"能真正用来练手而不是刷精度"那种。
2. 数据解剖:1000+张真实场景、5类昆虫、双格式标注怎么组织
2.1 图片与场景:真实场景到底"真实"在哪
先看图片本身。文件编号从000225到000229,每张图对应多个实例编号,比如000225_1.jpg、000225_2.jpg、000225_4.jpg,这是同一张背景图里切出的不同检测目标,或者是连续帧里同一昆虫的不同姿态。这种命名方式说明标注是按"一张图一个目标或多个目标"的方式组织的,不是那种每个类别一张标准照的合成数据。
真实场景体现在三个细节上。第一,背景是草地、泥土、叶片这类自然纹理,目标物和背景的对比度不高,昆虫的保护色会让模型天然难学。第二,昆虫本身姿态多变——蝴蝶翅膀张开和合拢时外形差异极大,蚂蚱侧身和正对镜头时轮廓完全不一样,这要求模型学的是"昆虫"这个概念而不是某个固定模板。第三,图片尺寸和光照条件不统一,有的目标可能只占画面很小一块面积,这正好用来检验YOLO系列在小目标上的表现。
图片格式是jpg,没有预处理痕迹,没有固定分辨率归一化,这意味着你拿到手后需要自己做letterbox或resize。实际训练时YOLO内部会做自适应缩放,但如果你要在训练前做数据清洗(剔除模糊图、裁剪纯背景图),就得自己写脚本。我一般拿到任何数据集先跑一遍统计脚本,看看图片尺寸分布和每张图的实例数分布,这个习惯能提前暴露很多"训练一半才发现"的问题。
2.2 两类标注文件:VOC的xml和YOLO的txt到底差在哪
这个数据集最省事的地方就是VOC和YOLO格式都给你备好了,分别放在两个文件夹。VOC格式以xml为后缀,记录的是object的name和bndbox的xmin、ymin、xmax、ymax,是绝对像素坐标;YOLO格式是txt,每行一个目标,结构是"类别id x_center y_center width height",全部归一化到0到1之间。两者的核心区别不只是格式差异,而是坐标系的表达方式。
| 对比项 | VOC格式 | YOLO格式 |
|---|---|---|
| 文件后缀 | .xml | .txt |
| 坐标形式 | 绝对像素坐标 | 归一化中心坐标+宽高 |
| 类别表示 | 类别名(字符串) | 类别id(整数) |
| 读取方式 | 需要xml解析库 | 纯文本按行读取 |
| 适用框架 | Faster-RCNN、SSD等 | YOLO系、部分检测框架 |
VOC转YOLO时最容易出错的不是坐标换算,而是类别索引。比如classes.txt里顺序是butterfly、locust、cockroach,那么butterfly的id是0,locust是1,cockroach是2。如果xml里的name是字符串"locust",转出来后写成id=1,但在你的训练yaml里类别顺序变成了cockroach、butterfly、locust,那这个目标就会被模型学成蟑螂,而且你不会立刻发现,只是验证集loss死活不降。这是后文避坑章节的重点。
2.3 五类昆虫的类别构成与训练前必须做的分布检查
摘要里明确了5类昆虫,能看到的有蝴蝶、蚂蚱、蟑螂,剩下的以实际数据集里的classes.txt为准。这里建议你拿到数据集后第一件事不是开训,而是统计每个类别的图片数和实例数,看看是不是均匀分布。真实场景数据集几乎必然存在类别不平衡——蝴蝶可能占了40%,蚂蚱占30%,蟑螂只占10%。
类别不平衡会带来两个直接后果。第一,模型会把高频类别学得很好,低频类别几乎不学,验证集mAP被高频类别拉高,给你一种"效果不错"的错觉;第二,如果蟑螂这种类别本身就难检(深色、小、贴地),那它会在训练后期梯度被稀释。处理办法是在yaml里给每个类别设置不同的loss权重,或者对低频类别做过采样。我一般会在数据划分前跑一个分布矩阵,确认每类在训练集和验证集中的占比和全集一致,避免验证集里恰好缺少某个低频类别导致指标虚高。
3. 跑通一次完整的YOLO昆虫训练:从环境配置到收敛出权重
3.1 环境准备:用ultralytics仓库把依赖一次装齐
训练YOLO系列最省心的路径是用ultralytics。这个包封装了YOLOv5、v8、v11的训练、验证、导出和推理流程,底层是PyTorch,对新手来说不用自己写训练循环,对熟手来说改配置也方便。
# 创建独立虚拟环境,避免污染系统Python conda create -n insect_yolo python=3.10 -y conda activate insect_yolo # 安装ultralytics,会自动拉取torch等核心依赖 pip install ultralytics # 验证安装是否成功,能打印版本号说明就绪 yolo --version参数说明:python=3.10是兼容性较好的版本,ultralytics对3.8到3.12都支持,但3.10踩坑最少。pip install ultralytics会自动安装torch、torchvision、opencv-python等依赖,不用手动一个个装。如果你用的是NVIDIA显卡,建议先装CUDA版torch再装ultralytics,避免pip默认拉CPU版导致训练慢一个数量级。装好后跑一下yolo --version确认命令行工具可用,这一步能排除路径和依赖缺失问题。
3.2 数据目录组织:YOLO训练前必须的YAML配置与目录结构
这个数据集本身已经是"图片文件 + 对应txt"的组织方式,但YOLO训练要求一个标准目录结构。常见的做法是新建一个数据集根目录,下面分images和labels两个大文件夹,再各自分出train和val子集,然后在yaml文件里指定路径和类别名。
# insect.yaml —— 数据集配置文件 path: D:/datasets/insects # 数据集根目录,绝对路径更稳 train: images/train # 训练集图片相对路径 val: images/val # 验证集图片相对路径 # 类别列表,顺序必须和标注txt里的id完全对齐 names: 0: butterfly 1: locust 2: cockroach 3: moth # 实际类别以数据集classes.txt为准 4: beetle参数说明:path那一行建议写绝对路径,YOLO在相对路径解析上偶尔会因为工作目录切换而出问题。names里的顺序0、1、2、3、4必须和训练txt标注文件里的第一个数字一致,一旦错位,整个训练就是"拿着蟑螂的标签学蝴蝶",最后模型收敛出来的特征是完全乱的。核对方法很简单:随机抽10个txt文件,比对类别id和classes.txt的顺序。
3.3 数据划分:一个脚本把训练集和验证集分开
数据集没有内置划分好的train/val文件夹,需要自己分。很多人在这一步偷懒直接把全部数据丢去训练,然后训练完才发现没有验证集可用,只能靠visualize猜效果。这里建议的是7:2:1的比例,留一部分做测试集。
import os import random import shutil random.seed(42) # 固定随机种子,保证多次划分结果一致 img_dir = 'D:/datasets/insects/all_images' lab_dir = 'D:/datasets/insects/all_labels' # 划分目标目录 for split in ['train', 'val', 'test']: os.makedirs(f'D:/datasets/insects/images/{split}', exist_ok=True) os.makedirs(f'D:/datasets/insects/labels/{split}', exist_ok=True) imgs = [f for f in os.listdir(img_dir) if f.endswith('.jpg')] random.shuffle(imgs) n_train = int(len(imgs) * 0.7) n_val = int(len(imgs) * 0.2) for i, img in enumerate(imgs): stem = os.path.splitext(img)[0] src_img = os.path.join(img_dir, img) src_lab = os.path.join(lab_dir, stem + '.txt') if i < n_train: split = 'train' elif i < n_train + n_val: split = 'val' else: split = 'test' shutil.copy(src_img, f'D:/datasets/insects/images/{split}/{img}') if os.path.exists(src_lab): shutil.copy(src_lab, f'D:/datasets/insects/labels/{split}/{stem}.txt')逻辑说明:代码先读所有jpg文件,按7:2:1切成三段,然后把图片和同名txt复制到对应子目录。关键判断点有两个:一是random.seed(42)必须写,否则每次划分结果不一样,模型效果就无法复现;二是label存在性检查不能省,有些图片可能没有对应标注文件,如果硬拷贝会导致训练时图片和标签数量不匹配,YOLO加载直接报错。
3.4 训练启动与参数:batch_size、epochs、imgsz怎么设
数据准备好后启动训练。第一次跑建议用小分辨率快速验证整个链路是否通畅,不要一上来就用大参数量跑几十个epoch,否则出了错要等很久才发现。
# 先用小分辨率和短epoch验证流程能跑通 yolo detect train \ model=yolov8n.pt \ data=D:/datasets/insects/insect.yaml \ epochs=10 \ imgsz=640 \ batch=8 \ project=insect_runs \ name=smoke_test # 流程通了之后,换大模型跑正式训练 yolo detect train \ model=yolov8s.pt \ data=D:/datasets/insects/insect.yaml \ epochs=100 \ imgsz=960 \ batch=16 \ project=insect_runs \ name=insect_v8s参数说明:model=yolov8n.pt是最轻量的预训练权重,适合做冒烟测试。imgsz=640是YOLO默认值,如果昆虫普遍偏小,建议提到960甚至1280,小目标检测的提升往往来自输入分辨率而不是模型深度。batch=8在1080Ti级别显卡上能跑,显存不够就降到4。epochs=100是保守设置,配合早停机制足够;如果100轮后验证集loss还在降就继续加。project和name决定了权重输出目录,后续找best.pt和last.pt时要用,建议每次训练换name避免覆盖之前的实验。
4. 避坑:标注错位、类别索引、小目标最容易翻车的四个地方
4.1 坑一:训练时死活找不到标签文件
现象:启动训练后终端报错提示"image X has no corresponding label"或者训练跳过了一大半图片,跑完发现训练集图片数比文件里少了一大截。
原因:这个数据集里YOLO格式的txt和图片不在同一个目录,而且是分别放在两个文件夹里的。直接把图片文件夹路径写到yaml的train字段、把txt文件夹路径留空,YOLO按照命名配对规则找不到txt。
解决:严格按3.2的目录结构把图片和txt复制到同一对images/labels关联目录下,确保每张jpg旁边有个同名txt。写一个一次性校验脚本,统计图片数和txt数是否一致,不一致就找出来手动处理,不要抱着侥幸心理开训。
4.2 坑二:VOC转YOLO后类别id错位
现象:训练可以启动,loss也在掉,但推理阶段模型把蝴蝶认成蚂蚱,或者所有目标都被归到第0类,精度灾难。
原因:转换脚本里按xml中object出现的顺序拼接类别id列表,没有先读取数据集自带的类别清单。比如xml里有三个类别,但实际全局有五个classes,这样转换脚本按局部顺序生成id,到了第4个类别就出现越界或错位。
解决:转换之前先确定类别全集,把classes.txt按固定顺序排序后写死一个全局映射字典,然后逐张图转换。转换完成后抽几张图画框检查,确保"蝴蝶图对应butterfly的txt、但框的位置仍然在蝴蝶身上"。这一步可视化验证是必须的,不然后面全都白练。
4.3 坑三:小目标训练时显存爆掉或者收敛全无
现象:imgsz调到1280后,batch=8直接OOM;或改成batch=2能跑,但训练到50个epoch验证mAP一直在0.1附近徘徊。
原因:昆虫目标普遍较小,想提精度就得提高输入分辨率,但分辨率提高带来显存压力。batch调小后bn层统计不稳定,模型学不动。另一个隐藏原因是初始学习率过高,小目标框的回归梯度本身就稀疏,大学习率直接把特征打散。
解决:分辨率从640逐档往上调,每档用相同epoch数跑一轮对比mAP;如果显存只够batch=4,就把模型从yolov8s降级到yolov8n,同时学习率从默认0.01降到0.001配AdamW。我习惯是先固定imgsz=960、batch=8能稳住显存,再用小模型探路,确认提升来自分辨率而不是模型容量。
4.4 坑四:验证集mAP高但实际场景一塌糊涂
现象:训练完成,验证集mAP@0.5有0.85以上,但是用手机拍一张草地里的蟑螂,模型什么都检不出来。
原因:验证集是从同一个数据集中随机划分出来的,背景分布和光照条件都相似,模型实际是在"背场景"。更麻烦的是蟑螂类别在数据集里低频,验证集里可能就几张,mAP被蝴蝶等高频类别拉高。
解决:划分时保证每个类别的实例数在训练集和验证集的占比一致;另外手里自己留几张"没见过的场景"图片做最终测试,不看mAP只看实际检测结果。重点检查低频类别在小目标尺度下的漏检率,如果效果不行,回到第5章的针对低频类别的数据增强方案。
5. 把数据集收益拉满:数据增强、格式互转与小目标优化三板斧
5.1 把YOLO自带增强打开到"够用但不失真"
YOLOv8默认开启mosaic增强,训练前期每张图由4张图拼合而成,对小目标检测非常友好。但azimuth翻转、色彩空间扰动这些需要看任务来调。昆虫识别任务里,颜色是重要特征——蝴蝶翅膀颜色差异是分类依据,所以HSV增强的饱和度扰动幅度不能太大。
# augment.yaml —— 数据增强参数覆盖 mosaic: 0.8 # 80%概率使用mosaic拼图 mixup: 0.2 # 较低mixup,防止昆虫特征被mixup冲淡 hsv_h: 0.02 # 色调扰动幅度保持小 hsv_s: 0.3 # 饱和度适度变化 hsv_v: 0.3 # 明度变化不能太大,真实光照下明暗差异已有 flipud: 0.0 # 昆虫有明确上下朝向,上下翻转会导致误学 fliplr: 0.5 # 左右翻转安全,不影响昆虫类别判断 scale: 0.4 # 缩放范围,兼顾大小目标参数说明:flipud设为0是因为苍蝇、蝴蝶的朝向是重要特征,上下翻转会让模型学到错误的空间关系。hsv_h只有0.02,因为颜色对昆虫分类权重很高,色调大幅扰动等于教模型忽略颜色。mosaic到0.8配合小幅mixup能显著提升小目标检测效果,但对昆虫这种"纹理细节决定类别"的目标,mixup过高会让模型学到混合特征,导致分类置信度上不去。
5.2 自建VOC到YOLO批量转换工具,不依赖第三方库
这个数据集提供了双格式,但实际操作中你可能还需要把VOC格式转成其他框架格式,或者把新标注的数据转回来。这里给一个不依赖任何第三方标注库的纯手工转换脚本,用到的全是python标准库。
import xml.etree.ElementTree as ET import os # 类别全局映射,顺序必须和训练yaml一致 CLASS_MAP = {'butterfly': 0, 'locust': 1, 'cockroach': 2, 'moth': 3, 'beetle': 4} def voc2yolo(xml_path, out_txt_path, img_w, img_h): tree = ET.parse(xml_path) root = tree.getroot() lines = [] for obj in root.findall('object'): name = obj.find('name').text if name not in CLASS_MAP: print(f'[WARN] unknown class: {name}, skipped') continue cls_id = CLASS_MAP[name] box = obj.find('bndbox') xmin = float(box.find('xmin').text) ymin = float(box.find('ymin').text) xmax = float(box.find('xmax').text) ymax = float(box.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 # 边界裁剪,防止除以图片尺寸后出现越界值 x_center = min(max(x_center, 0.0), 1.0) y_center = min(max(y_center, 0.0), 1.0) lines.append(f'{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}') with open(out_txt_path, 'w') as f: f.write('\n'.join(lines))逻辑说明:关键点是坐标转换公式——x_center是(xmin+xmax)的二分之一再除以图片宽度,width是(xmax-xmin)除以图片宽度。除以谁取决于标注坐标系:VOC是绝对像素坐标,除以图片宽高得到归一化坐标;YOLO的txt里全部要求0到1的相对坐标。最后加了裁剪会把转化误差导致的越界值拉回合法范围,防止训练时YOLO报错。注意img_w和img_h必须从图片实际读取,不能从标注xml里推测,否则图片尺寸解读错误会导至坐标整体偏移。
5.3 小目标检测的另类解法:切图推理(SAHI思路)
对小目标昆虫,尤其图片里只有零星几只、目标像素占比小于2%的情况,直接把整图喂给模型效果很差。SAHI的思路是把大图切成若干小块,逐块检测,再把结果合并回原图坐标。这个思路在"目标密度低、每张图目标数量少"的昆虫场景下收益明显。
def detect_tiles(model, img_path, tile_size=640, stride=320): img = cv2.imread(img_path) h, w = img.shape[:2] boxes = [] for y in range(0, h, stride): for x in range(0, w, stride): tile = img[y:y+tile_size, x:x+tile_size] # 模拟YOLO推理,得到tile坐标系下的检测框 results = model(tile, imgsz=640, conf=0.3) for det in results[0].boxes: x1, y1, x2, y2 = det.xyxy[0].tolist() # 关键:把tile坐标还原到原图坐标 boxes.append({ 'class': int(det.cls[0]), 'conf': float(det.conf[0]), 'bbox': [x + x1, y + y1, x + x2, y + y2] }) # 简单NMS,合并重叠框 boxes = nms_boxes(boxes, iou_threshold=0.5) return boxes参数说明:tile_size和图片本身分辨率相关,建议设置成和训练imgsz相同或略小;stride决定相邻tile的重叠程度,stride越小重叠越多,漏检率越低但推理耗时越长。重叠反而有利于靠边界的昆虫,因为YOLO对贴近边界的目标容易漏检,切图后目标在某个tile中处于中心位置就不会漏了。nms是最后一步,因为同一个昆虫可能出现在相邻tile中,检测到两次,需要用IOU过滤掉重复框。这个方案推理速度比直接整图慢2到3倍,但在"要效果不要速度"的离线分析场景中非常值得。
6. 模型验证不止看mAP:可视化检查与低频类别的单独评估
训练收敛后,很多人直接拿验证集mAP当最终结论,但mAP是个平均指标,会被高频类别撑起来,掩盖低频类别的全军覆没。我做验证通常拆成三步。第一步,在验证集上统计每个类别单独的AP值,而不是只看整体mAP。YOLO会在验证结束后输出每个类别的ap50和ap50-95,重点看cockroach这种低频类别是否拖了后腿,如果某一类AP比其他类别低20个百分点以上,模型就得针对性调。
第二步是可视化验证。把best.pt在验证集上跑一遍推理,把预测框叠加在原图上输出到文件夹,然后人工翻图。这一步能看出mAP看不到的问题——比如蝴蝶翅膀展开和合拢两种姿态下模型的表现差异,或者背景中的小昆虫是否一直在漏检。实操时我习惯随机挑20张验证图片做可视化,然后用眼睛逐一检查框的贴合度,关注框是不是过松、是不是有两类目标被归到同一类。
第三步是随机抽几张训练集里没有的场景图测试泛化能力。这一步非常关键,因为验证集即使划分合理,也和训练集来自同一分布;真正判断模型能不能用,要看模型在"没见过的场景"下的表现。我一般在项目收尾时找几张完全不同的背景图跑推理,如果模型在自然光、室内光、背光三种条件下都有稳定检出,就说明泛化能力基本够用了。正如我的一位做农业监测的同事所说,模型训出来不是用来刷自己的验证集数据,而是要去陌生环境干活的。
具体到执行,YOLOv8训练结束后会在run目录下生成confusion_matrix.png、results.png等图表。confusion_matrix.png能看到哪个类别之间容易混淆——比如蚂蚱和甲虫如果频繁互相误判,说明这些类别的视觉特征过于接近,需要在数据增强里针对性地强化它们之间的差异。results.png里能看到loss曲线和mAP曲线的收敛情况,如果val_loss在最后20个epoch还在下降,说明训练还没完全收敛,可以增加epoch或者用cosine学习率调度再跑一轮。
# 训练完成后在验证集上重新评估,输出每类AP yolo detect val \ model=D:/datasets/insects/insect_runs/insect_v8s/weights/best.pt \ data=D:/datasets/insects/insect.yaml \ imgsz=960 \ save_json=True \ project=insect_val \ name=final_check参数说明:save_json=True会额外输出一个json文件,里面包含每个类别的AP、AR、f1等详细指标,方便后续做数据分析。imgsz要和学习时保持一致,如果训练用了960验证却用640,结果会偏高或者偏低,暴露不出真实水平。我在做验证时习惯把visualize参数也加上,这样可以边看指标边翻图,比单看数字可靠得多。从那以后我每次训完模型都强制走一遍"分类别AP、可视化抽检、陌生场景跑测"这三步,再也不会因为mAP好看就草率交付了,希望这些习惯能帮你把这份数据集真正用透。
本文还有配套的精品资源,点击获取