资讯动态

VOC2007完整版数据集:10000张图+三格式标签,YOLO训练省心起点

发布时间:2026/9/28 17:19:02 来源:尧图企业网站定制
简介这份资源面向目标检测初学者与需要快速搭建训练流程的开发者提供YOLO系列可直接使用的VOC2007完整版数据集解决数据获取难、标注格式不统一、训练集划分繁琐等问题。压缩包共2000个文件约846.91MB以1986个xml标注文件为主另含少量html教程、txt说明与py脚本覆盖图片标注、格式转换与数据集划分等环节。资源同时提供voc、coco和yolo三种格式标签分别存放于不同文件夹适配不同框架的读取需求。附带的划分脚本可按需生成训练集、验证集与测试集教程则涵盖Windows与Linux环境搭建及训练案例修改方法便于读者对照跑通自己的数据。目前已有1264人学习下载适合作为课程设计、毕业设计或算法验证的实战数据基础。1. VOC2007 完整版数据集为什么 10000 张图 三格式标签是目标检测的省心起点如果你刚配好 YOLO 环境准备拿自己的数据跑第一轮训练大概率会卡在同一个地方手头没有一份「拿来就能用」的数据集。网上搜 VOC2007出来的要么是残缺的 5000 张子集要么只有 XML 没有 YOLO 格式要么标签和图片对不上号。这个标题讲的就是一份把 VOC2007 补到 10000 张图片、同时给出 VOC、COCO、YOLO 三种格式标签、附带划分脚本和训练教程的完整方案。它解决的不是算法问题而是数据准备阶段最耗时的格式转换和目录组织问题。适合两类人一是想快速验证 YOLO 训练流程是否跑通的新手二是需要一个标准基准来对比自己改进效果的老手。VOC2007 本身只有 20 类但它的标注质量经过多年检验作为目标检测的入门数据集比直接上 COCO 要轻量得多10000 张图的规模也刚好卡在单卡能跑、又不至于太小的区间。2. 三种标签格式到底差在哪VOC、COCO、YOLO 的目录结构与字段对照2.1 VOC 格式XML 的树形结构决定了它最啰嗦VOC 格式的核心是每张图对应一个 XML 文件文件名和图片名一致放在Annotations目录下。XML 里记录了图片尺寸、目标类别和边界框的左上角与右下角坐标。这种格式的好处是可读性强用文本编辑器打开就能看懂坏处是解析慢而且不同人写的解析脚本对difficult、truncated这些字段的处理不一致容易埋坑。一个典型的 VOC XML 长这样annotation folderVOC2007/folder filename000001.jpg/filename size width500/width height375/height depth3/depth /size object nameperson/name difficult0/difficult bndbox xmin100/xmin ymin80/ymin xmax300/xmax ymax350/ymax /bndbox /object /annotationname是类别名bndbox是绝对坐标。注意difficult为 1 的目标在评估时通常会被忽略但训练时是否保留要看你的策略。我一般会在转换时把 difficult 为 1 的框直接丢掉避免模型学到模糊样本。2.2 COCO 格式一个 JSON 管所有但索引容易绕晕COCO 格式把所有标注塞进一个 JSON 文件结构分images、annotations、categories三个顶层字段。images里每张图有唯一的idannotations里每条标注通过image_id关联到图片通过category_id关联到类别。边界框是[x, y, width, height]注意这里是宽高而不是右下角坐标转换时最容易在这里翻车。{ images: [{id: 1, file_name: 000001.jpg, width: 500, height: 375}], annotations: [ {id: 1, image_id: 1, category_id: 1, bbox: [100, 80, 200, 270], area: 54000, iscrowd: 0} ], categories: [{id: 1, name: person, supercategory: none}] }bbox的四个值是左上角 x、左上角 y、宽度、高度。area是框面积iscrowd为 1 表示这是密集人群之类的区域训练时通常忽略。COCO 格式适合做多数据集统一评估但如果你只是跑 YOLO没必要绕这一圈。2.3 YOLO 格式归一化坐标 类别索引最简但最不直观YOLO 格式每张图对应一个.txt文件每行一个目标格式是类别索引 x_center y_center width height所有坐标都除以图片宽高做了归一化取值在 0 到 1 之间。类别索引用的是从 0 开始的整数对应一个classes.txt里的顺序。0 0.400000 0.573333 0.400000 0.720000这行表示类别 0中心点在图片宽度的 40%、高度的 57.33% 处框宽占图片宽度的 40%框高占图片高度的 72%。归一化的好处是模型输入尺寸变化时标签不用改坏处是肉眼没法直接判断框的位置对不对调试时得反算回去。三种格式的对照关系可以看这张表维度VOCCOCOYOLO存储方式每图一个 XML单个 JSON每图一个 TXT坐标类型绝对坐标 xmin/ymin/xmax/ymax绝对坐标 x/y/w/h归一化中心点 宽高类别表示字符串名称数字 id 名称映射从 0 开始的索引适合场景传统评估、可读性要求高多数据集统一评测YOLO 系列直接训练选型建议很直接如果你确定用 YOLO 训练最终一定要转成 YOLO 格式VOC 格式保留作为原始标注备份COCO 格式只在需要和其他数据集合并评估时才有必要生成。这份方案同时给三种格式省得你后面想换框架时再回头转一遍。3. 从 VOC 到 YOLO划分脚本与格式转换的完整操作流程3.1 目录组织先定结构再动手避免路径写死拿到数据集后第一件事不是急着跑脚本而是把目录结构定下来。我一般会这样组织dataset/ ├── VOC2007/ │ ├── Annotations/ # 原始 XML │ ├── JPEGImages/ # 原始图片 │ ├── ImageSets/ │ │ └── Main/ # 划分后的 train/val/test 列表 │ └── labels/ # 转换后的 YOLO txt ├── coco/ │ └── annotations.json └── data.yaml # YOLO 训练配置ImageSets/Main下放train.txt、val.txt、test.txt每行一个图片文件名不带扩展名。这个结构是 VOC 官方约定很多脚本默认从这里读划分列表保持它省事。3.2 划分脚本按 8:1:1 分层抽样固定随机种子划分脚本的核心是保证每类在 train/val/test 中的比例大致一致尤其是样本少的类。下面这个脚本按 8:1:1 划分固定随机种子输出三个列表文件import os import random from collections import defaultdict random.seed(42) # 固定种子保证每次划分结果一致 anno_dir VOC2007/Annotations img_dir VOC2007/JPEGImages out_dir VOC2007/ImageSets/Main os.makedirs(out_dir, exist_okTrue) # 统计每张图包含的类别用于分层抽样 img_classes defaultdict(set) for xml_file in os.listdir(anno_dir): if not xml_file.endswith(.xml): continue img_id xml_file[:-4] with open(os.path.join(anno_dir, xml_file), r) as f: content f.read() for line in content.splitlines(): if name in line: cls line.strip().replace(name, ).replace(/name, ) img_classes[img_id].add(cls) # 按主类别分组保证每类都有样本进入验证集 groups defaultdict(list) for img_id, classes in img_classes.items(): main_cls sorted(classes)[0] # 取第一个类别作为分组依据 groups[main_cls].append(img_id) train, val, test [], [], [] for cls, ids in groups.items(): random.shuffle(ids) n len(ids) n_train int(n * 0.8) n_val int(n * 0.1) train.extend(ids[:n_train]) val.extend(ids[n_train:n_train n_val]) test.extend(ids[n_train n_val:]) for name, ids in [(train, train), (val, val), (test, test)]: with open(os.path.join(out_dir, f{name}.txt), w) as f: f.write(\n.join(sorted(ids)))random.seed(42)是关键不固定种子的话每次划分结果不同实验没法复现。按主类别分组是为了防止某个类全部被分进训练集验证时该类指标直接为零。如果你的数据集类别极不均衡可以把main_cls换成更细的分组策略比如按类别组合分组。3.3 格式转换VOC XML 转 YOLO TXT 的四个边界处理转换脚本本身不长但边界情况多。下面这个版本处理了四个常见问题图片尺寸缺失、坐标越界、difficult 标记、类别名不在预设列表import os import xml.etree.ElementTree as ET classes [aeroplane, bicycle, bird, boat, bottle, bus, car, cat, chair, cow, diningtable, dog, horse, motorbike, person, pottedplant, sheep, sofa, train, tvmonitor] class_to_idx {c: i for i, c in enumerate(classes)} def convert(anno_dir, img_dir, out_dir): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(anno_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(anno_dir, xml_file)) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) if w 0 or h 0: print(f跳过 {xml_file}尺寸异常) continue lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_to_idx: continue if obj.find(difficult) is not None and obj.find(difficult).text 1: continue bbox obj.find(bndbox) xmin max(0, int(bbox.find(xmin).text)) ymin max(0, int(bbox.find(ymin).text)) xmax min(w, int(bbox.find(xmax).text)) ymax min(h, int(bbox.find(ymax).text)) if xmax xmin or ymax ymin: continue x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{class_to_idx[name]} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}) out_path os.path.join(out_dir, xml_file[:-4] .txt) with open(out_path, w) as f: f.write(\n.join(lines)) convert(VOC2007/Annotations, VOC2007/JPEGImages, VOC2007/labels)max(0, ...)和min(w, ...)是防止标注框超出图片边界VOC2007 里确实存在这种脏数据。difficult为 1 的直接跳过避免模型学习模糊目标。类别名不在classes列表里的也跳过防止索引错位。转换完记得抽查几个 txt用反算公式验证一下坐标是否落在合理范围。3.4 生成 data.yamlYOLO 训练配置的必填项YOLO 训练需要一个 yaml 文件告诉它图片和标签在哪、类别有哪些path: ./dataset train: VOC2007/ImageSets/Main/train.txt val: VOC2007/ImageSets/Main/val.txt nc: 20 names: [aeroplane, bicycle, bird, boat, bottle, bus, car, cat, chair, cow, diningtable, dog, horse, motorbike, person, pottedplant, sheep, sofa, train, tvmonitor]path是数据集根目录train和val是相对于path的列表文件路径。nc是类别数names的顺序必须和转换时的classes列表完全一致否则标签全错。这个文件写错一个字符训练时 loss 会直接不降别问我是怎么知道的。4. 训练教程用这份数据集跑通 YOLO 的第一轮迭代4.1 环境确认三个版本号必须对齐在跑训练之前先确认三个东西的版本Python、PyTorch、YOLO 框架。我一般用 Python 3.8 到 3.10PyTorch 1.12 以上YOLOv5 或 YOLOv8 都行。版本不对齐最常见的表现是ImportError或者 CUDA 报错。用下面命令快速检查python -c import torch; print(torch.__version__, torch.cuda.is_available())如果cuda.is_available()返回 False先别急着跑训练检查显卡驱动和 CUDA 版本。CPU 训练 10000 张图会慢到让你怀疑人生建议至少有一张 8G 显存的卡。4.2 启动训练命令行参数逐个说清以 YOLOv5 为例训练命令如下python train.py \ --data data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0 \ --project runs/train \ --name voc2007_exp1--data指向刚才写的 yaml 文件。--weights用预训练权重从零训练收敛慢且效果差常见做法是加载 COCO 预训练权重再微调。--img 640是输入尺寸VOC2007 图片普遍偏小640 够用想提精度可以上 1280 但显存翻倍。--batch 16在 8G 显存上跑 640 尺寸比较稳显存不够就降到 8。--epochs 100是上限实际看验证集指标早停。--device 0指定第一张卡。训练启动后重点看三个输出box_loss、obj_loss、cls_loss。正常情况三个 loss 都该下降如果obj_loss不降反升大概率是标签格式有问题回头检查 txt 文件里的坐标是不是归一化后的值。4.3 验证与推理确认模型真的学到了东西训练完在验证集上跑评估python val.py --data data.yaml --weights runs/train/voc2007_exp1/weights/best.pt --img 640看mAP0.5和mAP0.5:0.95两个指标。VOC2007 上 YOLOv5s 跑 100 epochmAP0.5 通常在 0.75 到 0.82 之间低于 0.7 说明训练有问题。推理单张图python detect.py --weights runs/train/voc2007_exp1/weights/best.pt --source test_image.jpg --img 640输出图会画在runs/detect/exp下。重点看小目标和密集目标有没有漏检VOC2007 里person和car的密集场景是重灾区。5. 避坑与排查标签转换和训练中最容易翻车的五个点5.1 现象训练 loss 一直不降mAP 接近零原因YOLO 标签的类别索引和data.yaml里的names顺序对不上。转换脚本里classes列表的顺序和 yaml 里写的不一致模型学的是错位的类别。解决把转换脚本里的classes列表和 yaml 里的names逐字对比确保顺序完全一致。最稳妥的做法是只维护一份类别列表转换和训练都从同一个文件读。5.2 现象验证集 mAP 正常但推理时框全偏了原因图片在训练时被 resize 了但推理时没有保持同样的预处理。YOLO 默认会做 letterbox 填充如果你自己写了推理脚本没做这一步坐标就会偏。解决直接用框架自带的detect.py不要自己手写预处理。如果必须自己写确保 letterbox 的缩放比例和填充值跟训练时一致。5.3 现象某些类完全检测不到原因划分时该类样本全部进了训练集验证集里没有或者该类样本太少被模型忽略。解决检查train.txt和val.txt里每个类的出现次数样本少于 50 的类考虑做数据增强或者过采样。VOC2007 里pottedplant和sofa样本偏少容易出这个问题。5.4 现象训练到一半 loss 突然变成 NaN原因学习率太大或者 batch 里有脏数据坐标归一化后超出 0 到 1 范围。解决先把学习率降到 0.001 试一轮。如果还 NaN用脚本扫一遍所有 txt检查有没有坐标值大于 1 或小于 0 的行。转换时的max(0, ...)和min(w, ...)就是防这个的但如果你用了别的转换脚本不一定有这层保护。5.5 现象COCO 格式评估时 AP 和 YOLO 自带的 mAP 对不上原因COCO 的 AP 计算方式和 YOLO 的 mAP0.5 不是一回事COCO 用的是 0.5 到 0.95 多阈值平均且对小目标的定义不同。解决对比指标时统一用同一个评估工具。如果要用 COCO 评估先把 YOLO 格式转回 COCO JSON再用 pycocotools 跑不要拿两个不同工具的数字直接比。6. 进阶技巧用这份数据集做消融实验和类别平衡当你跑通第一轮训练后这份数据集真正的价值在于做对比实验。我一般会固定三组配置一组用全部 10000 张图一组只用 5000 张一组对稀有类做过采样然后对比 mAP 变化。这样能快速判断你的改进到底是来自算法还是来自数据量。具体操作上写一个简单的采样脚本控制训练集规模import random random.seed(42) with open(VOC2007/ImageSets/Main/train.txt) as f: ids f.read().splitlines() # 按比例采样比如只用 50% sample_ratio 0.5 sampled random.sample(ids, int(len(ids) * sample_ratio)) with open(VOC2007/ImageSets/Main/train_half.txt, w) as f: f.write(\n.join(sampled))然后在data.yaml里把train指向train_half.txt其他不变跑一轮看 mAP 掉多少。如果掉得不多说明你的模型对数据量不敏感可以往轻量化方向走如果掉得厉害优先补数据而不是改结构。另一个技巧是检查类别分布。VOC2007 的person类占了将近 30% 的标注框pottedplant不到 2%。这种长尾分布会让模型偏向多数类。我通常会在损失函数里给稀有类加权重或者用重采样让每个 batch 里稀有类至少出现一次。YOLO 框架本身不直接支持类别加权但可以在数据加载器里做。最后说一个我踩过的坑不要用测试集调参。test.txt里的图在训练和验证阶段都不该出现只有最终报告结果时才跑一次。我见过有人把 test 当 val 用调出来的模型在真实场景里一塌糊涂。固定好train、val、test的划分random.seed写死这是实验可复现的底线。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑