4、常见标注格式详解(中):Pascal VOC XML格式、YOLO TXT格式
好,咱们接着聊标注格式。上一节我们把 COCO 的 JSON 格式拆了个七七八八,这一节轮到另外两个“老熟人”——Pascal VOC 和 YOLO。
说实话,这两个格式在工业界和学术界的出场率极高。我最早接触目标检测时,用的就是 VOC 格式。那时候年轻,觉得 XML 好啰嗦,后来才发现,啰嗦有啰嗦的好处。
4.1 Pascal VOC XML 格式:老牌标杆
Pascal VOC 是什么?它最初是一个视觉竞赛(Visual Object Classes),后来它的标注格式成了行业标准。很多开源检测模型,比如 Faster R-CNN、SSD,原生就支持这种格式。
它的核心是 XML 文件。每张图片对应一个同名的 XML 文件。比如 cat.jpg 对应 cat.xml。
4.1.1 文件结构长什么样?
我直接给你看一个典型的 VOC XML 文件。你感受一下它的“骨架”:
<annotation>
<folder>images</folder>
<filename>cat_001.jpg</filename>
<size>
<width>640</width>
<height>480</height>
<depth>3</depth>
</size>
<object>
<name>cat</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>
</annotation>
嗯,结构很清晰。根节点是 <annotation>,里面包含图片信息和所有目标。
我个人习惯把 <size> 和
4.1.2 核心字段解读
| 字段 | 含义 | 说明 |
|---|---|---|
| filename | 图片文件名 | 不含路径,只含文件名 |
| size | 图片尺寸 | width、height、depth(通道数) |
| object | 目标实例 | 一个图片可以有多个 object |
| name | 类别名称 | 比如 cat、dog、person |
| bndbox | 边界框 | xmin、ymin、xmax、ymax(像素坐标) |
| truncated | 是否被截断 | 0 表示完整,1 表示被图片边界截断 |
| difficult | 是否难识别 | 1 表示该目标很难辨认,通常训练时忽略 |
这里有个细节我想提一下。<truncated> 和 <difficult> 这两个字段,很多新手会忽略。我在项目中遇到过,有些目标只有半个身子露在画面里,如果不标记 truncated,模型会学到“猫只有半截身子”这种错误特征。你想想看,这多坑。
4.1.3 坐标格式:左上右下
VOC 的坐标是 绝对像素坐标。也就是 xmin 和 ymin 是框的左上角,xmax 和 ymax 是右下角。
举个例子:
- 图片宽 640,高 480
- 框的左上角在 (100, 50)
- 框的右下角在 (300, 200)
那这个框的宽度就是 300 - 100 = 200,高度是 200 - 50 = 150。
4.2 YOLO TXT 格式:简洁至上
YOLO 格式,说白了就是“极简主义”。它没有 XML 那么啰嗦,一个 TXT 文件搞定所有标注信息。
我第一次用 YOLO 格式时,心里想的是:“这才对嘛,标注数据就该这么干净。” 但后来发现,简洁的代价是——你必须严格遵守它的目录结构。
4.2.1 文件结构
YOLO 格式的目录通常长这样:
dataset/
├── images/
│ ├── train/
│ │ ├── img_001.jpg
│ │ └── img_002.jpg
│ └── val/
│ └── img_003.jpg
└── labels/
├── train/
│ ├── img_001.txt
│ └── img_002.txt
└── val/
└── img_003.txt
看到了吗?图片和标注文件是分开存放的。图片在 images/ 下,标注在 labels/ 下。而且文件名必须一一对应,只是后缀不同。
4.2.2 TXT 文件内容
一个 YOLO 标注文件的内容长这样:
0 0.546875 0.260417 0.312500 0.416667
1 0.750000 0.520833 0.250000 0.291667
每一行代表一个目标。每行有 5 个数字,用空格分隔:
- 类别索引:从 0 开始。比如 0 代表 cat,1 代表 dog
- 中心点 x:归一化后的 x 坐标(值在 0~1 之间)
- 中心点 y:归一化后的 y 坐标(值在 0~1 之间)
- 宽度 w:归一化后的宽度(值在 0~1 之间)
- 高度 h:归一化后的高度(值在 0~1 之间)
说白了,YOLO 不存绝对坐标,它存的是 相对比例。这样做的好处是:不管图片怎么缩放,标注数据都不用改。
4.2.3 坐标转换:从 VOC 到 YOLO
这是面试常考题,也是实际工作中最常用的技能。我直接给你公式:
# 假设图片宽为 W,高为 H
# VOC 坐标:xmin, ymin, xmax, ymax
# 计算中心点
center_x = (xmin + xmax) / 2.0 / W
center_y = (ymin + ymax) / 2.0 / H
# 计算宽高
width = (xmax - xmin) / W
height = (ymax - ymin) / H
# 输出 YOLO 格式
# class_id center_x center_y width height
举个例子:
- 图片宽 640,高 480
- VOC 框:xmin=100, ymin=50, xmax=300, ymax=200
- 计算:center_x = (100+300)/2/640 = 0.3125
- 计算:center_y = (50+200)/2/480 = 0.2604
- 计算:width = (300-100)/640 = 0.3125
- 计算:height = (200-50)/480 = 0.3125
- 最终结果:
0 0.3125 0.2604 0.3125 0.3125
4.3 两种格式的对比
我整理了一张对比表,方便你快速决策:
| 对比维度 | Pascal VOC XML | YOLO TXT |
|---|---|---|
| 文件格式 | XML(可读性强) | TXT(极简) |
| 坐标类型 | 绝对像素坐标 | 归一化相对坐标 |
| 坐标表示 | 左上角 + 右下角 | 中心点 + 宽高 |
| 每张图片 | 一个 XML 文件 | 一个 TXT 文件 |
| 类别信息 | 类别名称(字符串) | 类别索引(整数) |
| 额外信息 | 支持 truncated、difficult 等 | 无额外信息 |
| 适用场景 | 学术研究、通用检测 | YOLO 系列模型、工业部署 |
我个人建议:如果你在做学术研究或者需要保留丰富的标注信息(比如遮挡、截断),选 VOC。如果你在落地 YOLO 项目,直接上 TXT 格式,省心省力。
4.4 知识体系结构图
下面这张图,帮你理清这两种格式的核心逻辑:
4.5 避坑指南
最后,分享几个我踩过的坑:
- 类别索引别搞错:YOLO 的类别索引从 0 开始。如果你有 3 个类别,索引是 0、1、2。我曾经把索引写成 1、2、3,结果模型把猫认成了狗。
- 归一化别除错:计算 YOLO 坐标时,分母是图片的宽和高。别把宽高搞反了。我见过有人用宽去除高度,结果框全变形了。
- XML 解析注意编码:VOC 的 XML 文件默认是 UTF-8 编码。如果你用 Python 的
xml.etree.ElementTree解析,记得指定编码,否则中文路径会报错。 - 空图片的处理:如果一张图片里没有目标,VOC 格式可以没有
<object>节点。但 YOLO 格式必须有一个空的 TXT 文件(0 字节),不能没有文件。
嗯,这两种格式就先讲到这里。你只要记住:VOC 是“详细派”,YOLO 是“极简派”。实际工作中,两者经常需要互相转换。下一节我们会聊更复杂的格式,比如 JSON 和 COCO 的变体,到时候你就知道这些基础有多重要了。
公众号:蓝海资料掘金营,微信deep3321