news 2026/10/4 2:00:29

蟑螂检测数据集370张VOC+YOLO格式:小样本目标检测完整落地指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
蟑螂检测数据集370张VOC+YOLO格式:小样本目标检测完整落地指南

简介:一套面向蟑螂目标检测任务的数据集,包含374张已标注图片,标注类别统一为蟑螂,适合计算机视觉学习者、算法工程师用于训练与评估主流目标检测模型,也适用于智能害虫监测、消杀机器人等实际视觉项目。压缩包共1124个文件,主要包含JPG原图、Pascal VOC格式的XML标注文件、YOLO格式的TXT标注文件,整体大小仅12.29MB,便于快速下载和本地解压使用。所有图片均采集自百度网页,使用labelImg工具人工绘制矩形边界框,且已经过多轮准确性核实;数据集总标注框数达943个,单个类别标注信息完整,可放心用于模型训练或迁移学习。目前已有78人学习/下载,对于需要快速获取高质量小样本数据的开发者而言,可显著节省从数据采集、清洗到标注的时间,双格式标签还能直接对接到不同训练管线,是一份上手门槛低的实用数据集。

1. 蟑螂检测数据集370张VOC+YOLO格式:小样本目标检测的一次完整落地

半夜厨房开灯,一只蟑螂窜进橱柜缝,你掏出手机想拍清楚,它已经不见了。换成视觉检测设备,情况也差不多:蟑螂体色深、行动快、喜欢贴在墙角缝隙里,常规目标检测模型很难在小尺寸、低照度下稳定框住它。这个标题里的数据集,就是冲着这类特定场景来的——370张带标注的蟑螂图片,同时用VOC和YOLO两种格式存储,拿到手可以直接喂给YOLO系列做训练或微调,不用再花几个晚上写标注工具、统一格式。

它的价值不在数据量,而在“正好够跑通一次完整流程”。370张图对深度学习来说是小样本,但对刚入门的开发者、做毕业设计的学生、或者想给卫生害虫监测设备做验证的工程师,这个体量恰好能把数据整理、格式转换、训练调参、评估迭代整条链路走一遍。适合两类人:一类是只想搞清楚YOLO训练自己数据集每一步该怎么做的新手,另一类是已经在做害虫识别但缺种子数据、想快速验证方案可行性的从业者。接下来我会按照拿到zip之后的实际操作顺序,把它从解压到训练的完整路径拆开讲,重点落在格式转换和踩坑点上。

2. VOC与YOLO两种标注格式:先看懂再动手,别急着解压

2.1 VOC格式的结构:xml里藏着一张图的全部标注信息

VOC(Pascal VOC)是目标检测领域最经典的标注格式之一,它的核心思路是“一张图片配一个同名的XML文件”。解压之后你通常会看到两个并列的目录:JPEGImages存放jpg图片,Annotations存放xml文件。每一个xml文件里,记录了对应图片的文件名、尺寸通道数、以及每一个目标物体的类别和边界框坐标。下面是一个典型的VOC标注内容:

<annotation> <folder>JPEGImages</folder> <filename>cockroach_001.jpg</filename> <size> <width>640</width> <height>480</height> <depth>3</depth> </size> <object> <name>cockroach</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>120</xmin> <ymin>80</ymin> <xmax>300</xmax> <ymax>260</ymax> </bndbox> </object> </annotation>

XML结构中需要注意三个关键点:filename要和图片文件名完全一致,包括扩展名;size里的宽高是绝对像素值,转换格式时依赖这个值;bndbox里的四个坐标xmin、ymin、xmax、ymax也是绝对像素值。另外difficult字段很实用,表示该目标是否难以辨认(比如被遮挡、太小看不清),很多转换脚本会默认跳过difficult=1的目标,避免它们干扰训练。

VOC格式的优势是可视化友好,直接用labelImg或任何XML解析库都能打开查看;缺点也明显——每个目标都要写一段XML,一张图五六个蟑螂就是五六个object块,文件冗余且解析略重。所以在实际训练时,很少有人直接把VOC喂给YOLO系列,都是先转成YOLO格式的txt文件。

2.2 YOLO格式:一行文本搞定一个目标,归一化坐标是关键

YOLO格式和VOC最大的区别在于:每张图片对应一个同名txt文件,每一行只描述一个目标,五个数字分别是类别id、归一化中心点x、归一化中心点y、归一化宽度、归一化高度。归一化意味着所有值都除以图片的宽或高,取值范围在0~1之间。还是一张640x480的图,蟑螂边界框xmin=120、ymin=80、xmax=300、ymax=260,对应的YOLO格式是:

0 0.328125 0.354167 0.281250 0.375000

计算过程:中心点x = (120+300)/2 / 640 = 210/640 = 0.328125,中心点y = (80+260)/2 / 480 = 170/480 ≈ 0.354167,宽度=(300-120)/640=0.28125,高度=(260-80)/480=0.375。类别id为0,对应类别列表里的第一个名字,通常是cockroach。这样每一行都不依赖图片尺寸,训练时YOLO读取图片后会按照自己的输入尺寸缩放,目标位置不会错位。

使用YOLO格式时,图片和txt是分开存放的。典型的目录布局是images/train、images/val、labels/train、labels/val,图片和对应的txt文件名必须完全一致,只是扩展名不同。这也是新手最容易翻车的地方:严格区分大小写、不能有多余空格,文件名对不上就直接报找不到label。

对比项VOC格式YOLO格式
存储载体XML文件txt文件
坐标形式绝对像素(xmin, ymin, xmax, ymax)相对坐标(x_center, y_center, width, height)
是否归一化否是,全部除以图片宽高
类别表示字符串(如cockroach)整数id(从0开始)
单图多目标多个<object>块每行一个目标
训练时读取需解析XML直接按行读取,速度更快

该数据集同时提供两种格式,本质上是考虑到不同的使用路径:想用torchvision里的Faster R-CNN,可以直接读VOC格式;想用YOLOv5、YOLOv8,直接读txt。如果你拿到手的只有其中一种,后面这段转换脚本就是另一个常用方案。

2.3 VOC转YOLO格式:写一个脚本,处理一个目录,一劳永逸

假设你拿到手的只有VOC格式,或者你自己用labelImg标了一批蟑螂图片,需要一个批量转换脚本。常见做法是写一个Python脚本,遍历Annotations目录下所有xml,逐个解析出目标坐标,再除以图片宽高,写入同名txt。下面这个脚本可以直接放到数据集根目录下运行:

import os import xml.etree.ElementTree as ET def convert_voc_to_yolo(xml_dir, output_dir, class_names): """ 将VOC格式的xml标注转换为YOLO格式的txt标注 xml_dir: 存放xml文件的目录 output_dir: 存放txt文件的目录 class_names: 类别名称列表,索引即类别id """ os.makedirs(output_dir, exist_ok=True) class_name_to_id = {name: idx for idx, name in enumerate(class_names)} for xml_file in os.listdir(xml_dir): if not xml_file.endswith('.xml'): continue xml_path = os.path.join(xml_dir, xml_file) tree = ET.parse(xml_path) root = tree.getroot() img_width = int(root.find('size/width').text) img_height = int(root.find('size/height').text) txt_lines = [] for obj in root.findall('object'): name = obj.find('name').text difficult = int(obj.find('difficult').text) if difficult == 1: continue # 跳过难以辨认的目标 if name not in class_name_to_id: continue # 类别不在列表内则跳过 class_id = class_name_to_id[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 / img_width y_center = (ymin + ymax) / 2 / img_height width = (xmax - xmin) / img_width height = (ymax - ymin) / img_height txt_lines.append(f"{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}") txt_name = os.path.splitext(xml_file)[0] + '.txt' with open(os.path.join(output_dir, txt_name), 'w') as f: f.write('\n'.join(txt_lines)) if __name__ == '__main__': convert_voc_to_yolo( xml_dir='Annotations', output_dir='labels_full', class_names=['cockroach'] )

这段脚本的核心逻辑是:先建立类别名称到id的映射,然后解析每个xml拿到图片尺寸,再遍历所有object标签,把绝对坐标转成归一化坐标。这里有两个参数需要根据实际情况调整:class_names列表里的顺序决定了txt中类别id的含义,如果数据集里有其他类别(比如roach_egg、dead_cockroach),必须把全部类别名称按固定顺序写进去,否则后面训练时类别就乱了;difficult字段按需保留,如果你的场景里蟑螂都被遮挡了一半,那difficult=1的目标其实很有训练价值,建议不跳过。

反向转换(YOLO转VOC)也是常见需求。做法是解析txt每一行的五个数值,乘以图片宽高还原绝对像素坐标,再构造XML节点。需要注意YOLO格式存储的是中心点坐标,要还原成xmin、ymin时记得减去半宽半高,不然框的位置整体偏移半个目标大小。

3. 用YOLOv8在本地跑通370张蟑螂检测:最小训练流程

3.1 数据集目录统一:图片和标签按比例拆分,一个脚本搞定

拿到zip并解压后,第一件事不是急着训练,而是把目录结构统一成YOLO训练的约定样式。370张图如果不拆分,全部丢进去训练,最后连验证集都没有,根本不知道模型效果如何。常见的做法是按8:2或9:1划分训练集和验证集,同时保证图片和对应标签文件同步移动。

import os import random import shutil random.seed(42) # 固定随机种子,保证每次划分一致 image_dir = 'JPEGImages' label_dir = 'labels_full' train_ratio = 0.8 train_img_dir = 'images/train' val_img_dir = 'images/val' train_label_dir = 'labels/train' val_label_dir = 'labels/val' for d in [train_img_dir, val_img_dir, train_label_dir, val_label_dir]: os.makedirs(d, exist_ok=True) images = [f for f in os.listdir(image_dir) if f.endswith(('.jpg', '.jpeg', '.png'))] random.shuffle(images) split_idx = int(len(images) * train_ratio) for img in images[:split_idx]: label = os.path.splitext(img)[0] + '.txt' shutil.copy(os.path.join(image_dir, img), train_img_dir) shutil.copy(os.path.join(label_dir, label), train_label_dir) for img in images[split_idx:]: label = os.path.splitext(img)[0] + '.txt' shutil.copy(os.path.join(image_dir, img), val_img_dir) shutil.copy(os.path.join(label_dir, label), val_label_dir) print(f"训练集: {len(images[:split_idx])} 张, 验证集: {len(images[split_idx:])} 张")

这个脚本的核心参数是train_ratio=0.8和random.seed=42。随机种子固定以后,每次运行划分结果都一样,这很重要——当你调整了训练参数想对比效果时,必须保证训练集和验证集完全相同,否则结果差异无法归因。另外我用的是shutil.copy而不是move,保留原始目录不动,方便后续补标数据后重新划分。

有个细节值得注意:解压后的标签文件名可能是.txt,但有些第三方工具会生成.txt之外的后缀,比如.json或.xml。划分脚本里label = os.path.splitext(img)[0] + '.txt'这个拼接逻辑只对纯txt有效,如果你的标签是其他格式,先做一次批量重命名再划分。

3.2 配置data.yaml文件:类别名称顺序必须和txt里的id完全一致

划分完目录后,需要写一个data.yaml告诉YOLOv8去哪里找图片、一共几类、类别叫什么名字。这个文件放在数据集根目录下即可,内容如下:

path: /home/user/cockroach_dataset train: images/train val: images/val names: 0: cockroach

path指向数据集根目录的绝对路径,train和val是相对于path的子目录。names这个字典值得多说两句:字典里的索引必须是从0开始的连续整数,而且顺序要和txt文件里的类别id完全一致。比如txt里类别id为0的行代表蟑螂,那么names里0: cockroach;如果txt里出现id为1但names里没有定义,训练不会报错,但推理出来全是未命名类别,混淆矩阵根本没法看。

还有一个可选字段是nc(类别数量)。YOLOv8会自动根据names的长度推断,所以不写也行;但如果你用的某个修改版训练脚本,或者搞混了names和nc,建议手动加上nc: 1,多看一步没有坏处。

3.3 训练命令和关键参数:小模型起步,看loss也看PR曲线

一切就绪后,执行训练命令。以YOLOv8为例,最小可用命令是:

yolo detect train \ model=yolov8n.pt \ data=/home/user/cockroach_dataset/data.yaml \ epochs=100 \ imgsz=640 \ batch=8 \ patience=30

这条命令里每个参数都有讲究。model=yolov8n.pt是YOLOv8纳米版预训练权重,只有约3.2M参数,370张图的小数据集用nano最稳妥;如果你用yolov8x.pt这种大模型,大概率严重过拟合,loss降不下去还特别慢。imgsz=640是输入分辨率,如果原图里的蟑螂很小(比如宽度不到30像素),建议升到1280再训练,代价是显存占用翻倍、训练时间变长,后面第5章会展开讲小目标处理。batch=8取决于显卡显存,6G显存跑nano加640分辨率基本是上限;显存不够就把batch降到4,不要硬撑。patience=30表示在验证集上连续30个epoch没有提升就提前停止,小数据集通常训练不到100个epoch就停了,属于正常现象。

训练结束后,在runs/detect/train目录下会生成weights/best.pt和weights/last.pt。评估一个蟑螂检测模型好不好,不要只看loss曲线——loss下降只代表模型在训练集上拟合了,真正要关注的是results.png里的mAP50曲线以及验证集上的P(精准率)和R(召回率)。蟑螂检测的特点是漏检代价比误报更大:没框到等于放任不管,框错了最多是空报一次。所以调参时我会更看重召回率,R至少要跑到0.75以上才敢拿到真实场景用。

4. 数据集落地避坑:5个高频翻车点与排查方法

4.1 解压后图片比标注少,或者txt数量对不上:标注丢失还是文件名错位

现象:解压后JPEGImages里有370张jpg,但Annotations里只有365个xml,打开某些txt一看里面是空的。

原因:数据集制作时可能漏标了几张图片,或者标注工具批量导出时跳过了一些没有目标的图片。空txt文件在YOLO训练里不会报错,但会让模型学到“这张图什么也没有”,直接影响准确率。

解决:用脚本统计每张图片对应的txt行数,行数为0的单独拎出来检查。

import os label_dir = 'labels_full' empty_labels = [] for f in os.listdir(label_dir): if f.endswith('.txt'): path = os.path.join(label_dir, f) if os.path.getsize(path) == 0: empty_labels.append(f) print(f"空标注文件: {len(empty_labels)} 个") for f in empty_labels[:10]: print(f)

如果确认图片里确实没有蟑螂,就把对应的图片也移出训练目录(或者保留在验证集里当负样本用);如果图片里有蟑螂但txt是空的,说明标注确实丢了,要用labelImg重新打开这张图补标。

4.2 训练时报错“not found”:图片和标签的路径配置错了

现象:训练刚开始几秒就退出,控制台提示assertion failed: ... not found,经常是一长串图片路径。

原因:最常见的是data.yaml里的path写的是相对路径,而YOLOv8在解析时把它当成了相对于当前工作目录的路径,你从其他目录运行训练命令就找不到。另一个高发原因是图片是.jpg但txt是.JPG,Linux下区分大小写直接报错。

解决:把data.yaml里的path改成绝对路径,并且确认JPEGImages目录下的图片扩展名到底是.jpg还是.jpeg还是.png,用一条命令统一:

find /home/user/cockroach_dataset -name "*.JPG" -exec rename 's/\.JPG$/.jpg/' {} \;

4.3 训练正常但mAP一直是0,loss也不降:类别id错位

现象:训练日志里mAP50始终为0,P、R也是0,但loss曲线在缓慢下降,训练没有中断。

原因:数据集txt里的类别id和data.yaml里names的索引对应不上。比如txt里写的是1 0.32 0.45 0.11 0.22,而names只定义了0: cockroach,模型把id=1当成一个不存在的类别,自然永远无法正确识别。

解决:把txt第一列的所有取值打印出来,和names的索引做对比。

awk '{print $1}' labels/train/*.txt | sort | uniq -c

这个命令输出每个类别id出现的次数,如果出现了超过names长度的id,用脚本批量修正:

sed -i 's/^1 /0 /g' labels/train/*.txt labels/val/*.txt

注意sed里的^1是匹配行首的“1 ”,如果替换成0,一定要带空格,避免把坐标值里的数字也改了。

4.4 输入尺寸引起的标注失配:imgsz和原图宽高比例差太多

现象:训练没报错,mAP也还行,但推理时框的位置明显偏了,尤其图片边缘的蟑螂框总是叠不紧。

原因:原始图片分辨率是1920x1080,蟑螂目标只占很小一块;YOLOv8在训练时把图缩放到640x640,小目标被压缩成几个像素,标注框也跟着失真。这类问题在370张的小数据集中尤其明显。

解决:训练时把imgsz改成1280,同时给模型足够多的epoch去适应新分辨率。如果显存不够,先把图片按2x2切块再训练,相当于把一张大图拆成4张子图,目标相对变大,模型更容易学到蟑螂的身体纹路特征。

4.5 验证集指标挺好,换个环境就废:数据分布太单一

现象:验证集mAP50在0.9以上,结果把训练好的模型拿到厨房实地一测,亮光下还行,到了黄昏时段或者深色橱柜背景里框得七零八落。

原因:370张图可能全部来自同一个拍摄环境,比如实验室白炽灯下拍的白墙背景。深度学习模型很傻,它可能学到了“亮背景+特定反光=蟑螂”,换到偏暗的厨房环境,特征分布变了,检测率直线下降。

解决:以后采集数据时,主动覆盖不同场景——白天、夜晚、开灯、不开灯、瓷砖墙、木质橱柜、水泥地面。当前数据集不够的话,可以对图片做色彩抖动和亮度扰动来模拟不同光照,但这是治标不治本,真实场景迁移只能靠更多样的数据。实际操作中,我把训练好的模型先跑一遍数据集外的10张厨房实拍图,看它的置信度分布,凡是低于0.3的基本要当作漏检来追查。

5. 370张图怎么榨出更高精度:迁移学习、数据增强与真实场景验证

5.1 先复现再调参:第一个模型只用来跑通流程

从零训练一个yolov8s要几万张图,370张图直接随机初始化训练结果会很惨。正确做法是用预训练权重做迁移学习——yolov8n.pt已经在ImageNet上见过大量基础视觉特征,我们把它的特征提取层冻结起来,只训练检测头几个epoch,让模型先适应蟑螂的颜色纹理。具体命令:

yolo detect train \ model=yolov8n.pt \ data=/home/user/cockroach_dataset/data.yaml \ epochs=50 \ freeze=10 \ imgsz=640 \ batch=8

freeze=10表示冻结模型前10层,这些层学到的是边缘、纹理、形状这些通用特征,对蟑螂依然有效。等第一个模型跑通验证流程后,再解冻全部层,用一个较小的学习率(比如lr0=0.001)微调20个epoch。不要一上来就用默认学习率训练全部参数,370张图很容易让预训练权重在几个epoch内被破坏。

5.2 数据增强参数的几个关键旋钮:翻转变换要看场景合不合理

YOLOv8在训练参数里内置了数据增强配置,合适设置相当于把370张图扩成几千张。以下是我在蟑螂检测场景下常用的几个参数:

yolo detect train \ model=yolov8n.pt \ data=/home/user/cockroach_dataset/data.yaml \ epochs=60 \ imgsz=640 \ batch=8 \ hsv_h=0.015 \ hsv_s=0.5 \ hsv_v=0.4 \ fliplr=0.5 \ scale=0.5

hsv_h=0.015表示色调轻微扰动,蟑螂的深褐色不需要大改色调,幅度太大会让模型学到草绿色蟑螂;hsv_s=0.5和hsv_v=0.4分别控制饱和度和明度,这个幅度可以模拟夜间暗光或强光照射的情况。fliplr=0.5左右翻转是安全的,因为蟑螂左右对称;但不要用flipud(上下翻转),厨房的蟑螂不会出现在天花板视角,加了之后模型会把地板上的蟑螂和天花板上的蟑螂当成同一种特征,反而有害。scale=0.5允许图片随机缩放,这能模拟镜头远近变化,但缩放比例不要超过0.7,否则小目标直接被压缩到看不清,起不到增强作用。

调参时记住一个原则:增强策略要贴合目标在真实世界的分布,不是为了增强而增强。

5.3 一个可落地的验证技巧:拿10张“外场照片”测泛化能力

训练和调参到头来,都要回答一个问题:这个模型放在真实厨房里能不能用。我的习惯是单独留10张从未参与训练、来自不同环境的蟑螂照片做测试,用训练好的模型跑一次推理,看置信度分布,然后统计低置信度的框都集中在什么位置。

yolo predict \ model=runs/detect/train/weights/best.pt \ source=/home/user/cockroach_dataset/external_test/ \ conf=0.25 \ save_txt=True

如果这10张外场照片的平均置信度只有0.3,说明模型已经过拟合训练集了;如果平均置信度在0.6以上,这个模型基本可以进入实地部署验证阶段。conf=0.25是推理时的置信度阈值,实际部署时我会调高到0.4以上来降低误报,因为蟑螂检测器误报的代价是让后端设备空转,容易造成维护疲劳。

还有一个血泪经验:验证时不要只看画了框的图片,要看置信度的分布,而不是单纯框得准不准。有时候模型框得很准但置信度只有0.2,距离落地还差着一段调优的路。370张数据集的定位不是让你一步登天搞出99%准确率的系统,而是让你把流程走透、踩坑踩完,后续补数据有清晰方向。我自己的习惯是在数据集的目录里放一个README.md,记录每一次训练的配置参数、结束时的mAP和踩过的坑,等需要复现时不用重新试错。希望这份拆解能帮你在自己的数据集上少走几趟弯路。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 1:59:41

@vueuse/rxjs 实战指南:在 Vue 3 组件中无缝集成 RxJS 响应式编程

前端 【免费下载链接】vueuse Collection of essential Vue Composition Utilities for Vue 3 项目地址&#xff1a; https://gitcode.com/gh_mirrors/vu/vueuse 点击查看 免费下载 vueuse/rxjs 是 VueUse 生态中面向 RxJS 的官方扩展包&#xff0c;它通过 7 个精心设计的组合…

作者头像 李华
网站建设 2026/10/4 1:59:01

GitHub Skills实战:任务驱动式技能训练与自动反馈机制

看到"skills"这个标题&#xff0c;我第一时间想到的是GitHub官方那个同名学习项目&#xff0c;但转念一想&#xff0c;这个词背后藏着的其实是一整套关于"技能到底应该怎么学"的命题。技术圈里聊技能&#xff0c;要么是零散的工具技巧&#xff0c;要么是收…

作者头像 李华
网站建设 2026/10/4 1:57:10

云边协同怎么讲才不空洞?从云计算到边缘计算的完整叙事线

简介&#xff1a;一份简要介绍云边协同的演示文稿&#xff0c;适合云计算与边缘计算的初学者快速建立整体认知。内容从云计算的定义开始&#xff0c;讲清编程模型、虚拟化、池化、数据存储与管理所代表的超级计算模式&#xff0c;以及广泛网络连入、快速弹性伸缩、计量付费服务…

作者头像 李华
网站建设 2026/10/4 1:56:01

接口自动化测试登录态保持:Cookie与Session绕过验证码实战

做接口自动化测试这些年&#xff0c;我踩过最大的坑之一&#xff0c;就是登录态维护。自动化脚本跑到一半&#xff0c;突然返回“未登录”或者“验证码错误”&#xff0c;整个人都麻了。尤其是在测试环境有登录验证码、又要批量跑接口用例的场景下&#xff0c;如果每次执行都靠…

作者头像 李华