简介:这份蝴蝶目标检测数据集面向计算机视觉入门与进阶开发者,适用于训练和验证蝴蝶识别模型,也可作为课程设计、算法对比实验的素材。资源以VOC与YOLO双格式提供,共1425张jpg图片,每张均配有对应的xml与txt标注文件,标注类别统一为butterfly,使用labelImg完成,框选边界准确、目标覆盖完整,并经过一致性检查。压缩包为rar格式,无需解压密码,内含图片、xml、txt三个文件夹,解压后可直接用标注软件查看。包内文件总数2000个,以1425个xml和575个txt为主,整体约60.54MB,图片体积在1至500KB之间,便于快速加载与批量处理。目前已有235人学习下载,适合需要现成标注数据来验证检测流程、调试训练脚本或补充蝴蝶类样本的读者。
1. 蝴蝶数据集 VOC 与 YOLO 双格式:1425 张标注到底怎么用
手上拿到一份蝴蝶数据集,1425 张图,同时给了 VOC 和 YOLO 两套标注,第一反应往往是「直接丢进 YOLO 训练不就行了」。真上手就会发现事情没这么简单:VOC 的 XML 和 YOLO 的 txt 描述的是同一批框,但坐标系、类别映射、目录结构完全不同,混用一次就翻车。这份数据集的价值在于它把两种主流标注格式都备齐了,省掉自己 labelImg 打标的时间,但前提是你得清楚每套格式的字段含义、转换边界,以及 1425 张这个量级在目标检测里属于什么水平。这篇笔记面向已经会用 Python、准备拿这份数据跑通一次蝴蝶检测训练的从业者,从格式拆解讲到训练配置,把能抄的步骤和会踩的坑都摆出来。蝴蝶这类目标的特点是姿态多变、翅膀纹理细、背景常是花叶,属于典型的小目标加类内差异大的场景,正好用来验证你的数据管线和增强策略是否靠谱。
2. 拆开 VOC 与 YOLO 两套标注:字段、坐标系与目录约定
2.1 VOC XML 里每个字段到底约束了什么
VOC 格式的核心是一个图像对应一个 XML 文件,文件名和图片名一致,放在Annotations/下。打开一份蝴蝶的 XML,结构大致是这样:
<annotation> <folder>butterfly</folder> <filename>img_0001.jpg</filename> <size> <width>640</width> <height>480</height> <depth>3</depth> </size> <object> <name>butterfly</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>112</xmin> <ymin>88</ymin> <xmax>305</xmax> <ymax>260</ymax> </bndbox> </object> </annotation>size里的宽高必须是原图像素尺寸,不是缩放后的,这一点在后续转换时是校验基准。bndbox用的是绝对像素坐标,左上角(xmin, ymin)、右下角(xmax, ymax),原点在图像左上角。name是类别字符串,蝴蝶数据集如果只有一类,这里通常就是butterfly;如果分了品种,就会是monarch、swallowtail这类。difficult和truncated在训练时经常被忽略,但做数据清洗时有用:difficult=1的框一般建议在评估时跳过,truncated=1说明目标被裁切,增强时要小心。
一个容易忽略的点是 XML 里可能没有<object>,也就是纯背景图。1425 张里如果有这种负样本,转换脚本要能处理,否则会报空列表错误。
2.2 YOLO txt 的归一化坐标与类别索引
YOLO 格式每张图对应一个 txt,文件名同图片名,内容每行一个目标:
0 0.325781 0.362500 0.301563 0.358333五个字段依次是:类别索引、中心点 x、中心点 y、框宽、框高。后四个全部是相对图像宽高的归一化值,范围 0 到 1。类别索引从 0 开始,对应一个classes.txt或data.yaml里的names列表顺序。这里最常见的坑是类别顺序对不上:VOC 里写的是字符串butterfly,YOLO 里是数字0,如果数据集里有多类,映射表错一位,训练出来的模型就会把两个品种混为一谈。
归一化公式要记牢:
x_center = (xmin + xmax) / 2 / width y_center = (ymin + ymax) / 2 / height w = (xmax - xmin) / width h = (ymax - ymin) / height反过来从 YOLO 还原 VOC 时,先乘回宽高再取整,注意边界裁剪到[0, width-1],否则会出现xmax超出图像宽度的非法框。
2.3 目录结构:两套格式怎么摆才不乱
一份同时带 VOC 和 YOLO 的数据集,常见组织方式有两种。第一种是分开放:
butterfly_dataset/ ├── VOC/ │ ├── JPEGImages/ # 1425 张 jpg │ ├── Annotations/ # 1425 个 xml │ └── ImageSets/Main/ # train.txt val.txt └── YOLO/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml第二种是共享图片、只分标注目录。我一般推荐第一种,因为 YOLO 训练时images/labels必须成对且路径规则固定,混在一起容易在data.yaml的path上出错。1425 张按 8:2 划分,训练集约 1140 张、验证集 285 张,这个量级单类检测够用,多类品种识别就偏少,需要靠增强补。
提示:划分前先确认有没有同一只蝴蝶的多角度连拍。如果随机划分,连拍图会同时进训练和验证,验证指标虚高。按拍摄批次或图片前缀分组划分更稳。
3. 从 VOC 转 YOLO:转换脚本、类别映射与校验
3.1 写一个能跑通 1425 张的转换脚本
不用现成工具也能转,核心就是解析 XML、算归一化、写 txt。下面这个脚本处理单类和多类都行,类别顺序由classes列表决定:
import os import xml.etree.ElementTree as ET from PIL import Image # 类别顺序即 YOLO 索引顺序,必须和 data.yaml 的 names 一致 classes = ["butterfly"] class_to_id = {c: i for i, c in enumerate(classes)} def convert(xml_dir, img_dir, out_dir): os.makedirs(out_dir, exist_ok=True) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(".xml"): continue tree = ET.parse(os.path.join(xml_dir, xml_file)) root = tree.getroot() # 用实际图片尺寸,不信任 XML 里的 size img_name = root.find("filename").text img_path = os.path.join(img_dir, img_name) with Image.open(img_path) as im: W, H = im.size lines = [] for obj in root.findall("object"): name = obj.find("name").text.strip() if name not in class_to_id: continue # 未登记类别直接跳过,避免索引错位 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, xmax = max(0, xmin), min(W - 1, xmax) ymin, ymax = max(0, ymin), min(H - 1, ymax) if xmax <= xmin or ymax <= ymin: continue # 退化框丢弃 xc = (xmin + xmax) / 2 / W yc = (ymin + ymax) / 2 / H w = (xmax - xmin) / W h = (ymax - ymin) / H lines.append(f"{class_to_id[name]} {xc:.6f} {yc:.6f} {w:.6f} {h:.6f}") out_name = os.path.splitext(xml_file)[0] + ".txt" with open(os.path.join(out_dir, out_name), "w") as f: f.write("\n".join(lines)) convert("VOC/Annotations", "VOC/JPEGImages", "YOLO/labels/all")逻辑上分四步:读 XML、用 PIL 拿真实宽高、逐框算归一化、写 txt。参数说明:classes列表决定索引,改类别只改这里;:.6f保留六位小数,YOLO 官方推荐至少六位,位数太少在 1425 张里累积误差会让小框偏移;continue那两处分别处理未登记类别和退化框,宁可丢几个框也别写非法值进去。
3.2 转换后必须做的三项校验
转完不校验,训练时 loss 不降你都不知道问题出在哪。三项检查按顺序做:
第一,数量对齐。ls VOC/Annotations | wc -l和ls YOLO/labels/all | wc -l应该都是 1425,少一个就说明有 XML 解析失败。
第二,坐标范围。写个脚本扫所有 txt,任何一行后四个值超出[0,1]就报出来:
import os bad = [] for f in os.listdir("YOLO/labels/all"): for i, line in enumerate(open(os.path.join("YOLO/labels/all", f))): parts = line.split() if len(parts) != 5: bad.append((f, i, "字段数不对")) continue vals = list(map(float, parts[1:])) if any(v < 0 or v > 1 for v in vals): bad.append((f, i, "越界")) print(bad[:20], "共", len(bad))第三,可视化抽查。随机抽 20 张,把 YOLO 框还原画回图上,肉眼看框是否贴合蝴蝶。这一步能抓出坐标系搞反(比如把 xy 写反)这种脚本查不出的错。
3.3 类别映射表怎么定才不出错
单类蝴蝶最简单,classes = ["butterfly"],索引只有 0。如果数据集分了品种,比如 5 种,映射表要固定下来并写进data.yaml:
path: ./YOLO train: images/train val: images/val nc: 5 names: ["monarch", "swallowtail", "blue_morpho", "painted_lady", "other"]names的顺序就是索引 0 到 4,转换脚本里的classes必须逐字一致,大小写、下划线都不能差。我见过把blue_morpho写成blue morpho导致索引错位、模型把两个品种学混的血泪经验。改类别时,转换脚本和data.yaml要同时改,改完重新转一遍,别手动改 txt。
4. 用这份数据跑通 YOLO 训练:环境、配置与增强参数
4.1 环境搭建与最小可跑配置
环境这块,Anaconda 建个独立环境最省事,避免和系统里的包打架:
conda create -n butterfly python=3.10 -y conda activate butterfly pip install ultralytics pillowultralytics装好就自带 YOLO 命令行和 Python API,不用单独装 torch,它会拉对应版本。装完yolo checks能看环境是否正常。数据按第 3 章的目录摆好,data.yaml的path指向YOLO目录。
最小训练命令:
yolo detect train data=YOLO/data.yaml model=yolov8n.pt epochs=100 imgsz=640 batch=16参数说明:model=yolov8n.pt用预训练权重,1425 张从零训容易过拟合,迁移学习收敛快;imgsz=640是输入尺寸,蝴蝶翅膀纹理细,如果显存够可以上 800 或 960,小目标召回会好一些;batch=16按显存调,8G 显存跑 640 大概能到 16,跑 960 就得降到 4 或 8;epochs=100是起点,看验证集 mAP 曲线,还在涨就加到 200。
4.2 针对蝴蝶场景的增强参数怎么调
默认增强对蝴蝶不一定合适。蝴蝶常停在花上,翻转、旋转是安全的,但上下翻转(flipud)会让蝴蝶倒挂,自然界少见,可能引入噪声。我一般这样调:
yolo detect train data=YOLO/data.yaml model=yolov8n.pt epochs=150 imgsz=800 \ batch=8 fliplr=0.5 flipud=0.0 degrees=15.0 scale=0.5 mosaic=1.0 close_mosaic=10fliplr=0.5水平翻转概率,蝴蝶左右对称,安全;flipud=0.0关掉上下翻转;degrees=15.0小角度旋转,模拟拍摄角度变化;scale=0.5缩放范围,让模型适应不同距离;mosaic=1.0四图拼接,对小数据集提升明显,但close_mosaic=10表示最后 10 个 epoch 关掉 mosaic,让模型在真实分布上收尾,这一步对最终精度影响不小。
如果验证时发现小蝴蝶漏检多,把imgsz提到 960,同时batch降到 4,再开copy_paste或mixup增加小目标样本。反过来如果过拟合严重(训练 mAP 高、验证 mAP 低),降mosaic、加weight_decay、减epochs。
4.3 训练过程看什么指标、怎么判断收敛
训练日志里重点看三列:box_loss、cls_loss、mAP50。box_loss管框位置,cls_loss管分类,两个都该稳步下降。mAP50是 IoU 0.5 下的平均精度,单类蝴蝶能到 0.9 以上算正常,低于 0.7 就要查数据。验证集mAP50连续 20 个 epoch 不涨就可以停。
训练完在runs/detect/train/下有results.png和confusion_matrix.png。混淆矩阵如果出现大量背景被误判成蝴蝶,说明负样本不够或置信度门限太低;如果蝴蝶被漏检,看PR_curve,曲线右端掉得快就是召回不足,调低推理时的conf门限试试。
注意:1425 张单类数据,验证集只有 285 张,mAP 波动会比较大。别只看一个 epoch 的数,看平滑后的趋势。想更稳就做 5 折交叉验证,虽然费时间但结论可靠。
5. 避坑与排查:这份数据集最容易翻车的五个地方
现象一:训练一开始 loss 就是 nan。原因通常是 txt 里有非法值,比如坐标超出 1 或者字段数不对。解决:跑第 3.2 节的校验脚本,把越界行对应的图挑出来重标或删掉,重新转换。
现象二:模型把所有蝴蝶都框成一个大框。原因是类别索引和data.yaml的names对不上,或者转换时把多类都映射成了 0。解决:核对classes列表和data.yaml的names是否逐字一致,重新转换,别手动改。
现象三:验证 mAP 很高,实际测试图漏检严重。原因是训练验证划分时连拍图泄漏,验证集和训练集有近似重复图。解决:按图片前缀或拍摄批次分组划分,确保同一只蝴蝶不出现在两边。
现象四:小蝴蝶目标几乎检不到。原因是imgsz太小,640 下小目标缩到几十像素,特征丢失。解决:imgsz提到 800 或 960,开mosaic和scale,必要时对含小目标的图做上采样复制。
现象五:推理时置信度门限设 0.25 还是 0.5 拿不准。门限低召回高但误检多,门限高精度高但漏检多。解决:在验证集上跑一遍不同门限,画F1-conf曲线,取 F1 最高的点。蝴蝶场景背景干净的话 0.3 到 0.4 通常合适,背景杂乱就提到 0.5。
6. 把 1425 张用到极致:交叉验证、难例挖掘与导出部署
数据量固定,想再提精度就得在用法上做文章。第一个技巧是分层交叉验证:把 1425 张按蝴蝶品种和拍摄背景分成 5 折,每折轮流做验证,最终 mAP 取平均。这样得到的指标比单次划分可信得多,也能暴露某些品种样本太少的问题。实现上不用手写,ultralytics支持data.yaml里配多个val路径,或者用split参数配合脚本生成 5 份 yaml 循环训练。
第二个技巧是难例挖掘。第一轮训练完,用模型在验证集上推理,把漏检和误检的图挑出来,人工复核标注,补进训练集再训一轮。1425 张里通常有几十张是标注质量差或场景特殊的,这一轮补完 mAP 能涨几个点。具体做法:
yolo detect predict model=runs/detect/train/weights/best.pt \ source=YOLO/images/val save_txt=True conf=0.25 iou=0.5save_txt=True会把预测框存成 YOLO 格式,和真值对比就能找出差异大的图。conf=0.25故意设低,让漏检暴露出来。
第三个技巧是导出部署格式。训练完的best.pt在服务器上跑没问题,要上边缘设备就得转。常见做法是导出 ONNX 或 TensorRT:
yolo export model=runs/detect/train/weights/best.pt format=onnx opset=12 simplify=Trueopset=12兼容性好,simplify=True会做图优化,去掉冗余算子。导出后务必用同一张测试图对比 ONNX 和 pt 的输出,确认框坐标一致,差太多就是导出环节出了问题。边缘设备上推理时,conf门限要比服务器上略高,因为量化会带来精度损失,误检更容易冒出来。
最后说个习惯:每次改数据或改参数,都在runs/下留一份带备注的目录名,比如train_v2_imgsz800_flipud0。蝴蝶数据集不大,实验迭代快,不记清楚两周后就分不清哪次是哪次,这个后悔药我吃过不止一次。希望帮到你。
本文还有配套的精品资源,点击获取