简介:这是一份面向计算机视觉初学者与目标检测实践者的蜈蚣识别数据集,适用于训练和验证单类别检测模型,可服务于农业虫害监测、生物多样性调查等场景。资源包共713个文件,包含237张jpg原图、237个VOC格式xml标注文件、237个yolo格式txt标注文件,另有少量说明性txt,压缩包约68.14MB,两种标注格式可直接对接主流检测框架,省去格式转换环节。所有图片均由labelImg手工画框标注,类别为Centipede,共255个标注框,标注准确合理。目前已有96人学习下载,适合需要快速验证模型或补充单类别样本的读者。数据集不保证训练精度,但提供完整可用的标注结构,便于直接投入实验与对比测试。
1. 蜈蚣数据集实测:237 张 VOC+YOLO 双格式,单类别检测到底够不够用
手上有个做爬虫识别或者中药材分拣的项目,需要定位蜈蚣目标,但公开数据集里专门针对蜈蚣的标注资源少得可怜。这份firc_Centipede数据集就是冲着这个缺口来的:237 张 jpg 原图,每张都配了同名的 VOC 格式 xml 和 YOLO 格式 txt,标注工具是 labelImg,类别只有一个Centipede,总框数 255。也就是说平均每张图 1.07 个目标框,绝大多数图里只有一条蜈蚣,少数图有两条。
这个量级放在目标检测里属于「小样本」范畴,指望它从零训出一个泛化能力强的模型不现实,但用来做迁移学习后的微调、验证某个检测头在小目标上的表现、或者跑通 YOLO 训练全流程,它是够用的。适合谁?适合手头有预训练权重、想快速验证蜈蚣这一类目标检测可行性的工程师,也适合刚入门 YOLO、需要一个干净单类别数据集练手的人。不适合谁?不适合想直接拿它训生产级模型的人,237 张的覆盖度撑不起复杂场景。
数据集本身不承诺任何模型精度,只保证标注准确合理。这句话不是免责套话,是实话——小数据集的精度天花板由你的数据增强策略和预训练权重决定,跟数据集本身关系不大。下面从格式解析、训练配置、避坑到进阶技巧,把这份资源拆开讲透。
2. VOC 与 YOLO 双格式拆解:xml 和 txt 到底怎么对应
2.1 VOC 格式的目录结构与字段含义
拿到压缩包解压后,常见做法是看到JPEGImages、Annotations两个目录,或者所有文件平铺在一个文件夹里。这份数据集摘要里明确说了「不包含分割路径的 txt 文件,仅仅包含 jpg 图片以及对应的 VOC 格式 xml 文件和 yolo 格式 txt 文件」,所以大概率是平铺结构,文件名一一对应:
firc_Centipede_44.jpg firc_Centipede_44.xml firc_Centipede_44.txtVOC 格式的 xml 是 labelImg 默认输出,核心字段如下:
<annotation> <folder>images</folder> <filename>firc_Centipede_44.jpg</filename> <size> <width>640</width> <height>480</height> <depth>3</depth> </size> <object> <name>Centipede</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>112</xmin> <ymin>85</ymin> <xmax>430</xmax> <ymax>390</ymax> </bndbox> </object> </annotation>size里的宽高是原图尺寸,bndbox是左上角和右下角绝对像素坐标。name字段就是类别名,这里统一是Centipede。truncated和difficult在单类别小数据集里通常都是 0,训练时一般忽略。
2.2 YOLO 格式的归一化坐标与类别索引
YOLO 格式的 txt 每行代表一个目标,格式是:
<class_id> <x_center> <y_center> <width> <height>五个值都是归一化到 0~1 的浮点数。以同一张图为例,假设 xml 里 bndbox 是(112, 85, 430, 390),图片尺寸640x480,转换逻辑是:
# VOC bndbox 转 YOLO 归一化坐标 xmin, ymin, xmax, ymax = 112, 85, 430, 390 img_w, img_h = 640, 480 x_center = (xmin + xmax) / 2.0 / img_w # (112+430)/2/640 = 0.4234 y_center = (ymin + ymax) / 2.0 / img_h # (85+390)/2/480 = 0.4948 w = (xmax - xmin) / img_w # (430-112)/640 = 0.4969 h = (ymax - ymin) / img_h # (390-85)/480 = 0.6354 # 输出: 0 0.4234 0.4948 0.4969 0.6354class_id从 0 开始,这份数据集只有一个类别Centipede,所以所有 txt 里第一列都是 0。如果你后续要合并其他数据集训练,类别索引必须重新映射,否则会出现「蜈蚣被识别成其他类」的翻车现场。
2.3 双格式并存的实际用途与选型建议
为什么同一份数据要同时给 xml 和 txt?因为不同框架吃不同格式。VOC 的 xml 适合torchvision.datasets.VOCDetection、MMDetection 这类框架直接读取;YOLO 的 txt 适合 Ultralytics 系列的YOLODataset加载。你不需要自己写转换脚本,但需要知道两者之间的对应关系,方便校验标注是否一致。
常见做法是:先用 xml 在 labelImg 里可视化检查一遍标注框有没有明显偏移,再用 txt 直接喂给 YOLO 训练。如果发现某个 txt 的坐标超出 0~1 范围,说明转换时图片尺寸读错了,这种样本要单独拎出来看。
提示:解压后先统计 jpg、xml、txt 三种文件数量是否都是 237,缺一个都会导致训练时找不到标签而报错。
3. 用这份数据集跑通 YOLO 训练:从 data.yaml 到第一轮收敛
3.1 目录重组与 data.yaml 配置
Ultralytics YOLO 对目录结构有固定要求,不能直接拿平铺文件训练。我一般会按下面的结构重组:
centipede_dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml237 张按 8:2 划分,训练集 190 张,验证集 47 张。划分脚本:
import os, random, shutil src_dir = "firc_Centipede_flat" # 解压后的平铺目录 dst_dir = "centipede_dataset" random.seed(42) files = [f for f in os.listdir(src_dir) if f.endswith(".jpg")] random.shuffle(files) split = int(len(files) * 0.8) train_files, val_files = files[:split], files[split:] for phase, file_list in [("train", train_files), ("val", val_files)]: img_out = os.path.join(dst_dir, "images", phase) lbl_out = os.path.join(dst_dir, "labels", phase) os.makedirs(img_out, exist_ok=True) os.makedirs(lbl_out, exist_ok=True) for f in file_list: base = os.path.splitext(f)[0] shutil.copy(os.path.join(src_dir, f), os.path.join(img_out, f)) shutil.copy(os.path.join(src_dir, base + ".txt"), os.path.join(lbl_out, base + ".txt"))random.seed(42)保证每次划分结果一致,方便复现。split取 0.8 是经验值,小数据集验证集别低于 15%,否则评估指标波动太大。
data.yaml内容:
path: ./centipede_dataset train: images/train val: images/val nc: 1 names: ["Centipede"]nc是类别数,必须和 txt 里最大 class_id + 1 一致。这里只有 0 类,所以nc: 1。
3.2 训练命令与关键参数设置
用 Ultralytics YOLOv8n 做迁移学习,命令如下:
yolo detect train \ data=centipede_dataset/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.001 \ patience=20 \ augment=True \ project=runs/centipede \ name=exp1参数逐个说:model=yolov8n.pt用 COCO 预训练权重,小数据集必须迁移学习,从零训基本不收敛。epochs=100配合patience=20,20 轮验证指标不提升就早停,防止过拟合。lr0=0.001比默认的 0.01 小一个量级,小数据集用大学习率容易震荡。batch=16在 8G 显存上跑 640 分辨率够用,显存不够就降到 8。augment=True开启默认增强,包括 mosaic、HSV 抖动、随机翻转,对 237 张的扩充很关键。
训练启动后看第一轮输出,重点看box_loss和cls_loss是否在下降。如果cls_loss一直是 0 或者 NaN,说明标签路径没配对,YOLO 没读到 txt。
3.3 验证集评估与指标解读
训练结束后跑验证:
yolo detect val \ model=runs/centipede/exp1/weights/best.pt \ data=centipede_dataset/data.yaml \ imgsz=640输出里关注mAP50和mAP50-95。单类别小数据集,mAP50能到 0.85 以上算正常,低于 0.6 就要查标注质量或者增强策略。mAP50-95通常比mAP50低 0.2 左右,因为高 IoU 阈值下小数据集更难命中。
如果验证集指标远低于训练集,说明过拟合,常见做法是加大增强、减少 epochs、或者加 dropout。如果两者都低,先检查标注框有没有系统性偏移,比如所有框都偏右下角,那可能是 xml 转 txt 时坐标算错了。
注意:这份数据集只有 255 个框,验证集里可能只有 50 个左右目标,指标波动会比较大,建议跑 3 次不同随机种子取平均。
4. 小样本单类别检测的避坑清单:从标签错位到过拟合
4.1 标签文件缺失或命名不匹配
现象:训练启动后cls_loss为 0,验证时mAP全为 0,但box_loss正常下降。
原因:YOLO 按图片文件名去labels目录找同名 txt,如果 txt 缺失或者扩展名不对(比如.TXT大写),就当成无标签样本处理,只算背景损失。
解决:训练前跑一遍校验脚本,统计 images 和 labels 目录下同名文件数量是否一致:
import os img_dir, lbl_dir = "centipede_dataset/images/train", "centipede_dataset/labels/train" imgs = {os.path.splitext(f)[0] for f in os.listdir(img_dir)} lbls = {os.path.splitext(f)[0] for f in os.listdir(lbl_dir)} print("缺失标签:", imgs - lbls) print("多余标签:", lbls - imgs)4.2 归一化坐标越界导致训练崩溃
现象:训练中途报AssertionError或 loss 突然变 NaN。
原因:YOLO 要求 txt 里坐标在 0~1 之间,如果某张图的 xml 里 bndbox 超出图片尺寸(标注时拖拽越界),转换后坐标会大于 1 或小于 0。
解决:批量检查所有 txt,把越界行打印出来人工修正:
import os lbl_dir = "centipede_dataset/labels/train" for f in os.listdir(lbl_dir): with open(os.path.join(lbl_dir, f)) as fp: for i, line in enumerate(fp): vals = list(map(float, line.strip().split()[1:])) if any(v < 0 or v > 1 for v in vals): print(f"{f} 第{i}行越界: {vals}")4.3 类别索引不一致导致识别错位
现象:模型能检测到目标,但类别置信度很低,或者和别的类别混淆。
原因:如果后续合并了其他数据集,不同数据集的 class_id 映射不同,比如这份数据Centipede是 0,另一个数据集里 0 是Spider,合并后标签就乱了。
解决:合并前统一重映射 class_id,用脚本把所有 txt 第一列按新映射表替换,并同步更新data.yaml的names列表。
4.4 验证集划分不合理导致指标虚高
现象:验证集mAP50很高,但实际推理新图片效果差。
原因:237 张如果按顺序取前 190 张训练、后 47 张验证,而数据是按拍摄场景排序的,验证集和训练集分布差异大,指标不可信。
解决:划分前先 shuffle,并且检查验证集里是否包含所有场景类型。如果数据有连续帧,要按帧分组划分,避免同一场景的相邻帧同时出现在训练和验证集里。
4.5 数据增强过度导致小目标丢失
现象:训练 loss 正常下降,但验证时小目标漏检严重。
原因:mosaic 增强会把四张图拼成一张,蜈蚣目标被缩小到原来的四分之一,如果原图里蜈蚣本来就小,增强后可能只剩几个像素,模型学不到有效特征。
解决:小数据集且目标偏小时,关掉 mosaic 或者降低其概率,改用 HSV 抖动、随机翻转、随机裁剪这类不改变目标尺度的增强。Ultralytics 里可以通过mosaic=0.0关闭。
5. 进阶技巧:用 237 张数据把蜈蚣检测推到可用水平
小样本单类别检测的瓶颈不在模型结构,在数据利用效率。237 张、255 个框,想推到可用水平,核心思路是「让每一张图被模型看到更多次,但每次看到的形态不同」。
第一个技巧是分阶段训练。先用mosaic=1.0跑 50 轮,让模型快速学到蜈蚣的全局特征;然后关掉 mosaic,用mosaic=0.0再跑 50 轮,让模型适应真实尺度的目标。这个策略在 YOLOv5/v8 上都验证过,比全程开 mosaic 的mAP50能高 3~5 个点。命令上就是分两次yolo detect train,第二次用--weights runs/centipede/exp1/weights/best.pt加载第一次的权重继续训。
第二个技巧是用验证集做困难样本挖掘。跑完验证后,把漏检和误检的图单独拎出来,人工检查标注是否有问题。常见情况是蜈蚣身体被遮挡只标了可见部分,但模型学到了「整条蜈蚣」的模式,导致遮挡样本漏检。这时候要么补标遮挡部分,要么在训练时把这类样本复制多份加权。
第三个技巧是测试时增强(TTA)。推理时对同一张图做水平翻转、多尺度缩放,把多次预测结果做 NMS 融合。Ultralytics 里加augment=True参数即可:
yolo detect predict \ model=runs/centipede/exp1/weights/best.pt \ source=test_images/ \ imgsz=640 \ augment=True \ conf=0.25conf=0.25是置信度阈值,蜈蚣检测建议从 0.25 起步,太高会漏检,太低会误检。TTA 能提升 1~2 个点mAP,代价是推理速度慢 2~3 倍,看你的场景能不能接受。
最后说一个验证方法:拿 10 张训练集里没有的蜈蚣图片,手动标注后跑yolo detect val,看mAP50是否和验证集接近。如果差距超过 10 个点,说明验证集划分有问题,或者模型过拟合了训练场景。从那以后我每次拿到小数据集,都强制先跑一遍「训练集外测试」,确认指标没有虚高再往下做。希望帮到你。
本文还有配套的精品资源,点击获取