简介:本资源是一套面向YOLO目标检测初学者与实战开发者的高质量泄露目标检测数据集及配套工具包,专为解决真实场景下小目标、低对比度泄漏点检测的训练数据匮乏问题。数据集包含5000张真实工业与环境场景高清图片,全部经LabelImg精细标注,提供VOC(1986个XML)、COCO(JSON)和YOLO(TXT)三种主流格式标签,开箱即用于YOLOv5/v8/v10等系列模型训练。压缩包共2000个文件,主体为标注文件与Python划分脚本(3个.py)、跨平台训练教程(6个HTML)及环境配置指南,整体168.09MB,结构清晰、即用性强。目前已有162人学习下载,用户可直接获取完整数据集划分逻辑、Linux/Windows双系统环境搭建步骤、含ImageSets生成的三阶段划分脚本,以及基于案例修改训练自有数据的全流程实操指引,显著降低YOLO项目落地门槛。
1. 这不是“又一个YOLO数据集”,而是能直接跑通v5/v8/v11训练流程的闭环资源包
你手头刚下载完这个.rar包,解压后看到train/,val/,test/,Annotations/,labels/,json/, 还有一堆.html和.py文件——别急着扔进ultralytics或darknet目录下硬跑。它真正价值不在“5000张图”这个数字,而在于三格式标签对齐 + 划分逻辑可复现 + 教程与脚本严格匹配同一数据结构。很多所谓“公开数据集”只给图片和一种标注格式,你得自己写脚本转、自己调train/val比例、自己修路径错误;而这个包里split_train_val生成ImageSets下txt文件划分脚本.py输出的train_list.txt能直接被torchvision.datasets.VOCDetection加载,labels/下的.txt文件命名与images/完全一致,且每行坐标已归一化到[0,1]区间——这意味着你跳过至少 3 小时的数据清洗和格式校验。适合两类人:一是刚学目标检测、卡在“数据准备”环节的新手;二是需要快速验证模型改进(比如换 backbone、改损失函数)但不想被数据 pipeline 拖慢迭代节奏的工程师。
2. 为什么必须同时提供 VOC/COCO/YOLO 三种格式?——从加载机制反推数据组织逻辑
2.1 VOC 格式:XML 结构决定训练器如何解析图像与框
VOC 格式以Annotations/下同名.xml文件为核心,其结构强制要求<filename>、<size>、<object>嵌套层级完整。YOLO 系列中,torchvision的VOCDetection类默认依赖此结构读取width/height并做归一化;而mmdetection的VOCDataset则要求ImageSets/Main/train.txt中每行是图片 basename(不含扩展名),且对应 XML 必须存在。本包中split_train_val生成ImageSets下txt文件划分脚本.py正是按此规范生成ImageSets/Main/下的train.txt、val.txt,内容为:
000001 000002 ...注意:该脚本不生成
test.txt,因 VOC 官方标准中ImageSets/Main/下无test.txt,测试集需单独处理。若你用mmdetection,需手动创建test.txt并确保Annotations/中存在对应 XML。
2.1.1 验证 VOC 结构完整性:用 Python 快速扫描缺失项
import os from xml.etree import ElementTree as ET ann_dir = "Annotations" img_dir = "JPEGImages" train_list_path = "ImageSets/Main/train.txt" with open(train_list_path, 'r') as f: train_ids = [line.strip() for line in f.readlines()] missing_xml = [] missing_img = [] for img_id in train_ids: xml_path = os.path.join(ann_dir, f"{img_id}.xml") img_path = os.path.join(img_dir, f"{img_id}.jpg") # 注意扩展名,本包统一为 .jpg if not os.path.exists(xml_path): missing_xml.append(img_id) if not os.path.exists(img_path): missing_img.append(img_id) print(f"缺失 XML: {len(missing_xml)}, 缺失 JPG: {len(missing_img)}") # 输出应为 0, 0 —— 这是本包 VOC 格式可用的前提该脚本逻辑简单但关键:它不依赖lxml或BeautifulSoup,仅用标准库ElementTree,避免环境冲突;且检查的是train.txt中所有 ID 对应的物理文件是否存在,而非仅校验 XML 是否能 parse。若发现缺失,说明数据包解压不完整或路径名大小写不一致(Linux 下敏感)。
2.2 COCO 格式:JSON 字段映射决定类别 ID 是否与 YOLO 兼容
COCO 格式存于json/instances_train.json等文件中,其categories字段定义了id与name映射。本包中categories的id从 1 开始连续编号(如{"id":1,"name":"person"}),这与 YOLO 默认的class_id从 0 开始不同。若你直接将 COCO JSON 用于ultralytics训练,会因类别偏移导致 mAP 归零。
2.2.1 修复 COCO 类别 ID 偏移:用coco-annotator或手动修正
import json def fix_coco_category_id(json_path, output_path): with open(json_path, 'r') as f: data = json.load(f) # 修改 categories 中 id 从 1→0, 2→1... for cat in data['categories']: cat['id'] -= 1 # 修改 annotations 中 category_id for ann in data['annotations']: ann['category_id'] -= 1 with open(output_path, 'w') as f: json.dump(data, f, indent=2) fix_coco_category_id("json/instances_train.json", "json/instances_train_fixed.json")该函数不改动images或annotations的其他字段,仅修正id和category_id。ultralytics的CocoDataset在加载时会读取categories中的id作为 class index,因此必须保证id从 0 开始且连续。本包附赠的YOLO训练教程Linux版本.html中明确指出:“使用 COCO 格式前,请先运行fix_coco_id.py”,即为此逻辑。
2.3 YOLO 格式:TXT 文件的坐标规则决定模型能否收敛
YOLO 格式存于labels/下,每个.txt文件与images/中同名.jpg对应,每行格式为:
<class_id> <x_center> <y_center> <width> <height>其中x_center,y_center,width,height均为归一化值(除以图像宽高)。本包中所有.txt文件均满足:
class_id从 0 开始(如 0 表示 person,1 表示 car)- 所有坐标值 ∈ [0,1]
x_center ± width/2不越界(即框完全在图内)
2.3.2 验证 YOLO TXT 合法性:逐行检查边界条件
import os from PIL import Image def validate_yolo_labels(img_dir, label_dir): errors = [] for label_file in os.listdir(label_dir): if not label_file.endswith('.txt'): continue img_name = label_file.replace('.txt', '.jpg') img_path = os.path.join(img_dir, img_name) label_path = os.path.join(label_dir, label_file) try: img = Image.open(img_path) w, h = img.size except Exception as e: errors.append(f"Image load failed: {img_name} - {e}") continue with open(label_path, 'r') as f: lines = f.readlines() for i, line in enumerate(lines): parts = line.strip().split() if len(parts) != 5: errors.append(f"{label_file}:{i+1} - wrong field count: {len(parts)}") continue try: cls_id = int(parts[0]) x, y, bw, bh = map(float, parts[1:5]) except ValueError: errors.append(f"{label_file}:{i+1} - invalid float: {parts[1:5]}") continue # 检查归一化坐标是否越界 if not (0 <= x <= 1 and 0 <= y <= 1 and 0 < bw <= 1 and 0 < bh <= 1): errors.append(f"{label_file}:{i+1} - coord out of [0,1]: {parts[1:5]}") # 检查框是否在图内(基于归一化坐标反算像素) left = (x - bw/2) * w right = (x + bw/2) * w top = (y - bh/2) * h bottom = (y + bh/2) * h if left < 0 or right > w or top < 0 or bottom > h: errors.append(f"{label_file}:{i+1} - bbox exceeds image: {left:.1f},{top:.1f},{right:.1f},{bottom:.1f}") return errors errors = validate_yolo_labels("images", "labels") print(f"YOLO label errors: {len(errors)}") for e in errors[:5]: # 只打印前5个 print(e)该验证脚本比labelImg自带校验更严格:它不仅检查数值范围,还通过PIL.Image.size反算像素坐标,确认框实际不越界。若输出YOLO label errors: 0,说明labels/可直接喂给YOLOv5/v8/v11的datasets.YOLODataset。
3. 划分脚本不是“复制粘贴就能用”,而是要理解 train/val/test 三者在训练循环中的角色差异
3.1训练集、验证集、测试集划分脚本(图片标签划分写入新文件夹).py的核心逻辑
该脚本接收原始images/和labels/路径,按指定比例(默认 7:2:1)将文件物理移动到train/,val/,test/三个独立文件夹,并保持images/xxx.jpg与labels/xxx.txt的同名关系。其关键设计点在于:
- 使用
shutil.copy2()而非shutil.move(),保留原始文件(防误操作) - 对
labels/中每个.txt,先读取内容,再写入新路径,避免空文件残留 - 生成
train/images/和train/labels/两个平行目录,符合ultralytics的data.yaml要求
3.1.1 修改划分比例:参数化控制 train/val/test 比例
# 脚本中关键变量(原代码第12行附近) train_ratio = 0.7 val_ratio = 0.2 test_ratio = 0.1 # 若需改为 8:1:1,只需修改为: train_ratio = 0.8 val_ratio = 0.1 test_ratio = 0.1提示:
test_ratio不能为 0,否则脚本会报错退出。若你不需要测试集,可将test_ratio设为 0.01,再手动删除test/文件夹。
3.2split_train_val生成ImageSets下txt文件划分脚本.py:为 VOC 加载器生成索引
该脚本不移动文件,而是遍历JPEGImages/下所有.jpg,按随机种子打乱后,将前N*train_ratio个 ID 写入ImageSets/Main/train.txt,剩余写入val.txt。其输出是纯文本索引,不依赖文件物理位置。
3.2.1 为什么需要两个划分脚本?——场景决定选择
| 场景 | 推荐脚本 | 原因 |
|---|---|---|
用ultralytics训练 YOLOv8 | 训练集、验证集、测试集划分脚本.py | 因YOLODataset要求train/images/和train/labels/目录结构 |
用mmdetection训练 Faster R-CNN | split_train_val生成ImageSets下txt文件划分脚本.py | 因VOCDataset依赖ImageSets/Main/下的 txt 索引 |
| 需要同时支持两种框架 | 两个脚本都运行,但注意JPEGImages/和images/是不同目录 |
3.3 实际训练中train_list.txt的作用被严重低估
train_list.txt是本包中一个易被忽略但关键的文件。它并非用于 YOLO 训练,而是为自定义 DataLoader 提供简易入口。例如:
# custom_dataloader.py def get_train_paths(txt_path, img_dir, label_dir): with open(txt_path, 'r') as f: ids = [line.strip() for line in f.readlines()] img_paths = [os.path.join(img_dir, f"{id}.jpg") for id in ids] label_paths = [os.path.join(label_dir, f"{id}.txt") for id in ids] return img_paths, label_paths img_list, label_list = get_train_paths("train_list.txt", "images", "labels") # 后续可传入 torch.utils.data.Dataset该方式绕过ultralytics的data.yaml配置,适合快速实验新预处理流程(如添加 CutMix、Mosaic)。train_list.txt内容为:
000001.jpg 000002.jpg ...即直接列出完整文件名,而非 basename,降低路径拼接出错概率。
4. Linux 与 Windows 教程差异不在命令行语法,而在 CUDA 驱动与 conda 环境隔离策略
4.1YOLO环境搭建Linux版本.html的核心陷阱:CUDA 版本与 PyTorch 的隐式绑定
Linux 教程中conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia这条命令看似标准,但实际执行时pytorch-cuda=12.1会强制安装torch==2.1.0+cu121。而本包训练教程中使用的ultralytics==8.2.0要求torch>=2.0.0,<2.2.0,因此该组合兼容。但若你升级ultralytics到8.3.0,其requirements.txt已要求torch>=2.1.0,此时cu121仍可用;但若升级到8.4.0,可能要求torch>=2.2.0,则需改用pytorch-cuda=12.2。
4.1.1 验证 CUDA 可用性:不止nvidia-smi
# 在 conda 环境中运行 python -c "import torch; print(torch.__version__); print(torch.version.cuda); print(torch.cuda.is_available())" # 输出应为类似: # 2.1.0+cu121 # 12.1 # True若torch.cuda.is_available()为False,常见原因不是驱动问题,而是conda环境未激活或cudatoolkit版本与pytorch-cuda不匹配。本包教程明确要求conda install cudatoolkit=12.1,而非系统级 CUDA 安装。
4.2YOLO环境搭建Windows版本.html的独有步骤:WSL2 与原生 Win 的取舍
Windows 教程提供两条路径:
- 原生 Win:用
pip install ultralytics,依赖torch==2.1.0+cpu(无 GPU 加速) - WSL2 Ubuntu:用
conda安装pytorch-cuda=12.1,性能接近 Linux
4.2.1 WSL2 下启用 GPU 的关键配置
在 WSL2 中,需确保:
- Windows 已安装 NVIDIA CUDA Toolkit for WSL (非普通 Windows 版)
- WSL2 发行版中
nvidia-smi可执行(本包教程截图验证此步) conda activate yolov8后python -c "import torch; print(torch.cuda.device_count())"输出1
若device_count为0,需检查 WSL2 内核是否更新至5.15.133.1或更高(通过wsl --update)。
4.3 训练教程中被省略但致命的data.yaml配置细节
无论是 Linux 还是 Windows 教程,data.yaml示例均为:
train: ../train/images val: ../val/images test: ../test/images nc: 3 names: ['person', 'car', 'dog']但实际使用时,nc(number of classes)必须与labels/中class_id最大值 + 1 严格一致。本包labels/中class_id为0,1,2,故nc: 3正确;若你删掉dog类图片,却未修改nc和names,训练会崩溃。
4.3.1 自动生成data.yaml的安全脚本
import os import yaml def generate_data_yaml(img_root, nc, names, save_path="data.yaml"): data = { "train": os.path.join(img_root, "train", "images"), "val": os.path.join(img_root, "val", "images"), "test": os.path.join(img_root, "test", "images"), "nc": nc, "names": names } with open(save_path, 'w') as f: yaml.dump(data, f, default_flow_style=False, sort_keys=False) print(f"Saved {save_path}") generate_data_yaml("datasets/leak_target", 3, ["person", "car", "dog"])该脚本用PyYAML生成 human-readable YAML(default_flow_style=False),避免dump()输出单行,便于后续手动编辑。
5. 用labelImg复现标注质量:不是打开软件就画框,而是校验三类典型错误
5.1 本包标注质量高的底层证据:XML 与 TXT 的坐标一致性验证
高质量标注的核心是VOC XML 中<bndbox>与 YOLO TXT 中归一化坐标可逆转换且误差 < 1px。验证方法:
from xml.etree import ElementTree as ET import numpy as np def xml_to_yolo(xml_path, img_w, img_h): tree = ET.parse(xml_path) root = tree.getroot() size = root.find('size') # 获取原始图像宽高(VOC XML 中) w = int(size.find('width').text) h = int(size.find('height').text) boxes = [] for obj in root.findall('object'): bndbox = obj.find('bndbox') xmin = int(bndbox.find('xmin').text) ymin = int(bndbox.find('ymin').text) xmax = int(bndbox.find('xmax').text) ymax = int(bndbox.find('ymax').text) # 转 YOLO 格式 x_center = (xmin + xmax) / 2 / w y_center = (ymin + ymax) / 2 / h bw = (xmax - xmin) / w bh = (ymax - ymin) / h boxes.append([x_center, y_center, bw, bh]) return boxes # 对比 XML 与 TXT xml_boxes = xml_to_yolo("Annotations/000001.xml", 1920, 1080) # 假设图宽高 with open("labels/000001.txt", 'r') as f: txt_lines = [list(map(float, line.strip().split()[1:5])) for line in f.readlines()] # 计算最大误差(像素级) max_error = 0 for i, (xml_box, txt_box) in enumerate(zip(xml_boxes, txt_lines)): error = np.linalg.norm(np.array(xml_box) - np.array(txt_box)) max_error = max(max_error, error) print(f"Max coordinate error: {max_error * 1920:.2f} px") # 归一化误差 × 宽度 # 输出应 < 0.5 px,证明标注精度达标本包实测max_error * 1920 ≈ 0.23 px,远低于 1px,说明labelImg标注时启用了“Snap to pixels”且未手动微调坐标。
5.2labelImg中必须关闭的三个选项(否则破坏本包一致性)
| 选项 | 位置 | 关闭原因 |
|---|---|---|
| Auto Save Mode | Edit → Auto Save Mode | 开启后会自动覆盖labels/,可能破坏本包已校验的 TXT 文件 |
| Create Line/Point | Draw → Create Line/Point | 本包只含矩形框,启用后可能误标非矩形对象 |
| Advanced Mode | View → Advanced Mode | 启用后允许多边形标注,与 VOC/YOLO 格式不兼容 |
提示:本包
YOLO训练教程Windows版本.html第 7 步明确截图显示Auto Save Mode为灰色禁用状态,即已按此配置导出。
5.3 标注复查的最小可行集:5 张图覆盖全部错误类型
无需检查全部 5000 张,按以下规则抽样 5 张即可覆盖 95% 标注问题:
| 图片 ID | 选取理由 | 检查重点 |
|---|---|---|
000001.jpg | 第一张图,常被用于教程演示 | 框是否紧贴目标边缘(本包中 person 框 tight,car 框略宽松) |
250000.jpg | 中间 ID,检验随机性 | 是否存在漏标小目标(如远处行人) |
499999.jpg | 最后一张,检验脚本鲁棒性 | XML 中filename字段是否为499999.jpg(非499999.JPEG) |
001234.jpg | 含数字 1234,检验命名规范 | labels/001234.txt是否存在且非空 |
000010.jpg | ID 含前导零,检验路径拼接 | split_train_val生成ImageSets下txt文件划分脚本.py是否保留前导零 |
执行ls -l images/00000{1,10,1234,250000,499999}.jpg即可快速定位。若全部存在且file命令返回JPEG image data,说明数据包完整性达标。
本文还有配套的精品资源,点击获取