📦 引言:格式的重要性
数据标注格式是 AI 项目的“数据接口协议”。同一套图片与同一组框,如果格式不匹配,常见结果不是“训练效果差一点”,而是直接出现:
- 训练脚本读不到数据:路径组织、字段名或类别映射不符合框架约定。
- 坐标含义被误解:(xywh) vs (xyxy)、归一化 vs 像素、左上角 vs 中心点,轻则框偏移,重则全错。
- 类别 ID 全部错位:例如把
category_id=1当成第 1 类,但你的训练配置是从 0 开始。 - 后续难维护:跨团队/跨工具交付时,缺少元数据(类别表、图片尺寸、分割信息)会导致反复返工。
本文以“目标检测(bounding box)”为主线,深入拆解三种主流格式:YOLO、VOC(Pascal VOC)与 COCO。你将学到:
- 每种格式到底在表达什么(坐标系统、文件组织、元数据)
- 训练框架最在意的约定(类别映射、切分集合、空标注)
- 格式转换的关键细节(公式、边界裁剪、映射表)
🎯 YOLO格式
格式特点
YOLO 系列(尤其是 YOLOv5/v8/v9/v10)最常见的“YOLO 标注格式”,本质是:每张图片一个 .txt 文件,每行一个目标框。它追求极简与高吞吐,因此元数据通常放在一个额外的配置文件(如 data.yaml)。
文件结构:
dataset/
├── images/
│ ├── image001.jpg
│ └── image002.jpg
└── labels/
├── image001.txt
└── image002.txt
更贴近训练习惯的组织方式通常包含 train/val/test(或 train/valid/test):
dataset/
├── images/
│ ├── train/
│ ├── val/
│ └── test/
├── labels/
│ ├── train/
│ ├── val/
│ └── test/
└── data.yaml
标注文件格式(image001.txt):
class_id center_x center_y width height
0 0.5 0.5 0.3 0.4
1 0.2 0.3 0.1 0.2
格式说明:
class_id:类别 ID(通常从 0 开始,与类别表严格一一对应)center_x, center_y:边界框中心点坐标,相对图片宽高归一化到 ([0,1])width, height:边界框宽高,相对图片宽高归一化到 ([0,1])
坐标系统(最容易踩坑)
YOLO 的 xywh 是“中心点 + 宽高”,且通常是归一化:
-
从 YOLO(归一化)转像素 (xyxy):
- (x_{center}=center_x \times W),(y_{center}=center_y \times H)
- (w=width \times W),(h=height \times H)
- (x_{min}=x_{center}-\frac{w}{2}),(y_{min}=y_{center}-\frac{h}{2})
- (x_{max}=x_{center}+\frac{w}{2}),(y_{max}=y_{center}+\frac{h}{2})
-
从像素 (xyxy) 转 YOLO(归一化):
- (x_{center}=\frac{x_{min}+x_{max}}{2W}),(y_{center}=\frac{y_{min}+y_{max}}{2H})
- (width=\frac{x_{max}-x_{min}}{W}),(height=\frac{y_{max}-y_{min}}{H})
建议在转换/导出时做两件事:
- 裁剪与夹紧(clamp):确保结果落在 ([0,1]) 或 ([0,W/H]) 的合法范围内,避免训练时报错或出现 NaN。
- 保留足够小数:一般保留 6 位小数即可;过度四舍五入会让小目标“抖动”。
关键特点:
- ✅ 使用归一化坐标(0-1)
- ✅ 格式简洁,文件小
- ✅ 适合YOLO系列模型
类别表与 data.yaml
YOLO 训练通常还需要一个数据配置(以 Ultralytics/YOLOv5 生态为例):
# data.yaml
path: /abs/path/to/dataset
train: images/train
val: images/val
test: images/test
names:
0: car
1: person
这里的 names 顺序/ID 必须与你的 class_id 完全一致。如果你在不同数据集或不同导出之间改了类别顺序,模型会“学错标签”但不报错,这是最隐蔽也最昂贵的坑之一。
空标注与缺失文件
- 空标注图片:建议保留对应的空
.txt(文件存在但为空),或按训练框架要求处理;不要“直接缺文件”,否则数据加载逻辑可能把它当成异常。 - 图片与标签同名:
image001.jpg对应image001.txt。更换扩展名(jpg/png)通常不影响,但文件名(不含扩展名)必须一致。
适用场景
推荐使用:
- YOLOv5/v8/v9/v10训练
- 目标检测项目
- 需要快速训练
不推荐使用:
- 需要像素级精度的项目
- 需要详细元数据的项目
补充说明:YOLO 格式并不是“不支持”更复杂任务。以 YOLOv8 为例,分割/关键点等任务会在标签行里追加多边形点/关键点字段。但一旦进入这些扩展格式,不同工具与训练代码的约定差异会显著变大,建议统一使用同一套工具链导出与训练。
📋 VOC格式
格式特点
VOC(Pascal VOC)以 XML 表达一张图像的标注信息,可读性强、字段明确,适合“人肉排查”和传统检测框架(如早期 Faster R-CNN 系工具链)。
文件结构:
dataset/
├── images/
│ ├── image001.jpg
│ └── image002.jpg
└── annotations/
├── image001.xml
└── image002.xml
经典 VOC 数据集目录通常更“标准化”:
VOCdevkit/
└── VOC2007/
├── JPEGImages/
├── Annotations/
└── ImageSets/
└── Main/
├── train.txt
├── val.txt
└── test.txt
其中 train.txt/val.txt/test.txt 存放的是图片 id(不带扩展名),用于明确划分数据集切分。
标注文件格式(image001.xml):
<annotation>
<filename>image001.jpg</filename>
<size>
<width>640</width>
<height>480</height>
<depth>3</depth>
</size>
<object>
<name>car</name>
<bndbox>
<xmin>100</xmin>
<ymin>50</ymin>
<xmax>300</xmax>
<ymax>200</ymax>
</bndbox>
</object>
</annotation>
格式说明:
- 绝对像素坐标:通常以图片左上角为原点 ((0,0)),向右为 x 正方向,向下为 y 正方向。
- 边界框语义为 (xyxy):
xmin,ymin,xmax,ymax(左上角与右下角)。 - 内含图片尺寸:
size/width,height,depth用于校验坐标有效性与可视化。 - 可扩展元数据:如
pose、truncated、difficult等字段在许多 VOC 工具链中仍会被读取。
关键字段速查(常用但容易忽略)
一个较完整的 object 往往长这样:
<object>
<name>car</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>100</xmin>
<ymin>50</ymin>
<xmax>300</xmax>
<ymax>200</ymax>
</bndbox>
</object>
truncated:目标是否被截断(例如被画面边缘裁掉)。difficult:难样本标记。某些评估/训练流程会选择忽略difficult=1的目标。
VOC 坐标的“闭区间”争议
不同工具对 xmax/ymax 是否“包含像素点”理解不同(历史遗留)。最安全的实践是:
- 转换时保证 (xmax > xmin)、(ymax > ymin)
- 避免生成越界坐标(小于 0 或大于宽高)
- 在可视化抽查中确认边框是否偏移 1 像素(如果偏移,统一在导出端修正)
关键特点:
- ✅ 使用绝对坐标
- ✅ 包含详细元数据
- ✅ 适合Faster R-CNN等模型
适用场景
推荐使用:
- Faster R-CNN训练
- 需要详细元数据的项目
- 需要可读性好的格式
不推荐使用:
- YOLO训练(需要转换)
- 需要快速训练的项目
补充说明:如果你的项目需要频繁跨工具协作(标注→质检→训练→回流),VOC 的“人可读 XML”优势非常明显;但当数据量很大时,海量 XML 的读写性能与管理成本会逐渐显现。
🗂️ COCO格式
格式特点
COCO 是“数据工程友好型”的标注格式:用一个(或少量)JSON 文件描述全量图片、类别与标注,天然适合做统计、检索、过滤、合并与版本管理。它不仅支持检测框,还原生支持实例分割(segmentation)、**关键点(keypoints)**等任务。
文件结构:
dataset/
├── images/
│ ├── image001.jpg
│ └── image002.jpg
└── annotations/
└── instances_train.json
标注文件格式(instances_train.json):
{
"images": [
{
"id": 1,
"file_name": "image001.jpg",
"width": 640,
"height": 480
}
],
"annotations": [
{
"id": 1,
"image_id": 1,
"category_id": 1,
"bbox": [100, 50, 200, 150],
"area": 30000,
"iscrowd": 0
}
],
"categories": [
{
"id": 1,
"name": "car"
}
]
}
格式说明:
- bbox 语义为 (xywh):
bbox=[x, y, w, h],其中x,y是左上角像素坐标,不是中心点。 image_id:标注所属图片(关联images[].id)。category_id:标注所属类别(关联categories[].id)。注意:COCO 的 category_id 往往不是从 0 开始,也不要求连续。area:目标面积,常见为w*h(检测框)或多边形面积(分割)。iscrowd:是否是“群体/拥挤目标”,与分割的 RLE/多边形表达有关。
segmentation / keypoints(为什么 COCO 更“全能”)
即使你当前只做检测,也建议理解 COCO 的两个强项字段,因为很多公开数据集与训练框架会依赖它们:
- segmentation:实例分割掩码
iscrowd=0时常用多边形数组:[[x1,y1,x2,y2,...], ...]iscrowd=1时常用 RLE(Run-Length Encoding)压缩掩码
- keypoints:关键点任务(如人体姿态),通常是长度为 (3K) 的数组(
x,y,v),v表示可见性
COCO 的“全局一致性”约束(工程上很重要)
COCO JSON 往往需要满足:
images[].id唯一、annotations[].id唯一annotations[].image_id必须能在images中找到annotations[].category_id必须能在categories中找到
当你做“合并多个数据集”或“增量追加标注”时,ID 冲突是最常见的问题。最佳实践是:在合并时重写(rebase)id,并建立稳定的类别映射表。
关键特点:
- ✅ 使用绝对坐标
- ✅ 结构化数据
- ✅ 适合多种模型
适用场景
推荐使用:
- COCO数据集训练
- 需要结构化数据的项目
- 需要丰富元数据的项目
不推荐使用:
- YOLO训练(需要转换)
- 需要快速训练的项目
补充说明:COCO 并不“慢”,慢的是你用一个超大的 JSON 在每个 epoch 全量解析。实际工程通常会做缓存、索引或转成更快的内部格式,但“对外交付/对齐标准”时 COCO 依旧是首选。
🔄 格式对比
| 特性 | YOLO | VOC | COCO |
|---|---|---|---|
| 坐标系统 | 归一化(0-1) | 绝对像素 | 绝对像素 |
| 文件格式 | TXT | XML | JSON |
| 文件大小 | 小 | 中 | 大 |
| 可读性 | 低 | 高 | 中 |
| 元数据 | 少 | 中 | 多 |
| 适用模型 | YOLO系列 | Faster R-CNN | 多种模型 |
| 转换难度 | 易 | 中 | 难 |
补充维度(更贴近真实项目选型):
| 维度 | YOLO | VOC | COCO |
|---|---|---|---|
| 原生支持任务 | 检测(扩展可做分割/关键点) | 检测为主 | 检测 + 分割 + 关键点 |
| 类别体系 | 依赖外部 names 映射 |
<name> 直接写类名 |
category_id 需查表 |
| 数据集切分 | 依赖目录或列表文件 | 传统用 ImageSets/Main/*.txt |
常见为多个 json(train/val) |
| 合并/过滤/统计 | 需要遍历大量小文件 | 需要遍历大量 XML | 对数据工程最友好 |
| 人肉排查 | 一般 | 非常方便 | 需要工具或脚本 |
💡 格式选择指南
你可以用下面这个“决策思路”快速选型:
- 你训练的是 YOLO 生态(Ultralytics/YOLOv5 系)且只做检测 → 优先 YOLO
- 你要做实例分割/关键点,或数据要与主流公开数据集对齐 → 优先 COCO
- 你更依赖人工可读、需要在 XML 里挂一些业务字段,或使用传统检测工具链 → VOC 依然好用
选择YOLO格式
适合场景:
- 使用YOLO系列模型
- 需要快速训练
- 文件大小敏感
优势:
- 格式简洁
- 文件小
- 训练快
注意事项:
- 确保
names与class_id永远一致(强烈建议纳入版本管理) - 做数据增强/裁剪后要同步更新标签(尤其是 mosaic、random crop)
选择VOC格式
适合场景:
- 使用Faster R-CNN
- 需要详细元数据
- 需要可读性
优势:
- 可读性好
- 元数据丰富
- 兼容性好
注意事项:
- 保持
xmin<xmax、ymin<ymax,并确保不越界 - 跨工具时确认
xmax/ymax的边界语义,避免 1 像素偏差
选择COCO格式
适合场景:
- 使用COCO数据集
- 需要结构化数据
- 需要丰富元数据
优势:
- 结构化数据
- 元数据丰富
- 兼容多种模型
注意事项:
- 类别
id不一定连续,训练时通常需要建立category_id -> 0..N-1的映射 - 合并数据集要处理
images.id/annotations.id冲突
🔧 格式转换
转换前的“必做三件事”
无论你要在 YOLO/VOC/COCO 之间怎么转,先把这三点定死,后面才能稳定:
- 类别映射表:
- VOC 用类名、COCO 用
category_id、YOLO 用class_id。 - 建议维护一个统一的
class_name -> yolo_id映射,再派生到 VOC/COCO。
- VOC 用类名、COCO 用
- 坐标约定:
- YOLO:中心点归一化 (xywh)
- VOC:像素 (xyxy)
- COCO:像素 (xywh)(左上角 + 宽高)
- 边界与空标注策略:
- 统一裁剪越界框,过滤面积过小框(例如 (w<1) 或 (h<1))
- 空标注样本是否保留(建议保留)
YOLO → VOC
转换步骤:
- 读取YOLO格式文件
- 获取图片尺寸
- 计算绝对坐标
- 生成XML文件
代码示例:
def yolo_to_voc(yolo_file, img_width, img_height):
# 读取YOLO格式
with open(yolo_file, 'r') as f:
lines = f.readlines()
# 转换为VOC格式
annotations = []
for line in lines:
class_id, cx, cy, w, h = map(float, line.split())
xmin = int((cx - w/2) * img_width)
ymin = int((cy - h/2) * img_height)
xmax = int((cx + w/2) * img_width)
ymax = int((cy + h/2) * img_height)
annotations.append((class_id, xmin, ymin, xmax, ymax))
return annotations
VOC → YOLO
转换步骤:
- 读取XML文件
- 获取图片尺寸
- 计算归一化坐标
- 生成TXT文件
代码示例(最小可用版,演示核心公式;你需要自行补 class_name -> class_id 映射):
import xml.etree.ElementTree as ET
def voc_to_yolo(xml_file, class_name_to_id):
tree = ET.parse(xml_file)
root = tree.getroot()
size = root.find("size")
img_w = float(size.find("width").text)
img_h = float(size.find("height").text)
yolo_lines = []
for obj in root.findall("object"):
name = obj.find("name").text.strip()
if name not in class_name_to_id:
continue
bnd = obj.find("bndbox")
xmin = float(bnd.find("xmin").text)
ymin = float(bnd.find("ymin").text)
xmax = float(bnd.find("xmax").text)
ymax = float(bnd.find("ymax").text)
# clamp & sanity
xmin = max(0.0, min(xmin, img_w))
xmax = max(0.0, min(xmax, img_w))
ymin = max(0.0, min(ymin, img_h))
ymax = max(0.0, min(ymax, img_h))
if xmax <= xmin or ymax <= ymin:
continue
cx = (xmin + xmax) / 2.0 / img_w
cy = (ymin + ymax) / 2.0 / img_h
w = (xmax - xmin) / img_w
h = (ymax - ymin) / img_h
class_id = class_name_to_id[name]
yolo_lines.append(f"{class_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}")
return yolo_lines
COCO → YOLO
转换步骤:
- 读取JSON文件
- 获取图片尺寸
- 计算归一化坐标
- 生成TXT文件
代码示例(演示 COCO bbox (xywh) → YOLO 归一化中心点 (xywh)):
import json
from collections import defaultdict
def coco_to_yolo(coco_json_path, category_id_to_yolo_id):
data = json.load(open(coco_json_path, "r", encoding="utf-8"))
images = {img["id"]: img for img in data.get("images", [])}
ann_by_image = defaultdict(list)
for ann in data.get("annotations", []):
ann_by_image[ann["image_id"]].append(ann)
# 返回:file_name -> yolo_lines
result = {}
for image_id, img in images.items():
W, H = float(img["width"]), float(img["height"])
file_name = img["file_name"]
lines = []
for ann in ann_by_image.get(image_id, []):
cid = ann["category_id"]
if cid not in category_id_to_yolo_id:
continue
x, y, w, h = map(float, ann["bbox"]) # COCO: top-left xywh
if w <= 0 or h <= 0:
continue
cx = (x + w / 2.0) / W
cy = (y + h / 2.0) / H
nw = w / W
nh = h / H
# clamp
cx = max(0.0, min(1.0, cx))
cy = max(0.0, min(1.0, cy))
nw = max(0.0, min(1.0, nw))
nh = max(0.0, min(1.0, nh))
if nw == 0 or nh == 0:
continue
yolo_id = category_id_to_yolo_id[cid]
lines.append(f"{yolo_id} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}")
result[file_name] = lines
return result
建议增加“转换后验收”
格式转换完成后,务必做一个轻量验收流程(能省掉大量训练时间):
- 随机可视化抽查:至少抽 50 张,看框是否整体偏移、尺寸是否异常。
- 统计检查:每类目标数、每张图目标数、框面积分布是否与预期一致。
- 空标注占比:空标注突然大幅上升通常意味着匹配/映射出了问题(如文件名不一致或 ID 断链)。
🎁 使用TjMakeBot进行多格式标注
TjMakeBot的优势:
-
多格式支持
- YOLO格式
- VOC格式
- COCO格式
- CSV格式
-
格式转换
- 支持格式间转换
- 一键导出多种格式
- 兼容主流训练框架
你真正需要关注的是:导出时的类别映射与坐标约定是否被“锁死”。一个好的工具应当能:
- 固化类别表(导出时携带/生成
names、categories等) - 统一坐标约定(清如 YOLO 归一化中心点、COCO 左上角 (xywh))
- 对越界/异常框做可控处理(裁剪、过滤或报警)
-
批量处理
- 批量导出
- 批量转换
- 提高效率
-
免费(基础功能免费)
- 无使用限制
- 无功能限制
- 降低使用门槛
📚 相关阅读
💬 结语
选择正确的标注格式是AI项目成功的基础。YOLO、VOC、COCO各有特点,根据你的项目需求选择最适合的格式。
记住:
- YOLO格式适合YOLO系列模型
- VOC格式适合Faster R-CNN
- COCO格式适合多种模型
- 格式转换是可行的
额外建议(来自真实项目踩坑总结):
- 把“类别表”当成代码一样管理:版本化、可追溯、可回滚。
- 不要只在训练时发现问题:把可视化抽查和统计检查做成导出后的固定步骤。
- 统一团队坐标约定:在项目 README 或数据规范里写清楚((xywh)/(xyxy)、是否归一化、是否包含边界)。
选择TjMakeBot,支持多格式标注和转换!
法律声明:本文内容仅供参考,不构成任何法律、商业或技术建议。使用任何工具或方法时,请遵守相关法律法规,尊重知识产权,获得必要的授权。本文提及的所有公司名称、产品名称和商标均为其各自所有者的财产。
关于作者:TjMakeBot团队专注于AI数据标注工具开发,致力于支持多种标注格式,满足不同项目需求。
📚 推荐阅读
- 农业AI:作物病虫害检测标注实战指南
- 语义分割 vs 实例分割:深度解析与标注策略指南
- AI辅助标注vs人工标注:成本效益深度分析
- 中国数据标注市场的应用特点与用户需求
- 零售电商AI:商品识别标注的实用方法
- 数据标注中的认知偏差:如何避免标注错误
- 边缘计算与轻量化模型:标注数据的优化策略
- 数据标注工具的发展历程
关键词:YOLO格式、VOC格式、COCO格式、标注格式、格式转换、多格式标注、TjMakeBot
