VOC 数据集格式和 YOLO 数据集格式是计算机视觉领域中最常用的两种数据集标注格式,主要用于目标检测任务。它们的格式和结构有所不同,下面分别介绍这两种格式。
1. VOC 数据集格式
VOC(Visual Object Classes)格式最早由 Pascal VOC Challenge 引入,广泛用于目标检测任务。VOC 数据集通常包含两个主要部分:
图片(JPEG Images):存储图像数据,通常为 .jpg
文件。
标注(Annotations):存储每张图片的目标信息,通常为 XML 文件。
VOC 格式的 XML 文件结构
每个图像的标注信息存储在一个 XML 文件中。XML 文件包含了图片的基本信息以及其中目标的位置信息。一个典型的 XML 文件如下所示:
<annotation>
<folder>VOC2012</folder>
<filename>000001.jpg</filename>
<path>/path/to/000001.jpg</path>
<source>
<database>VOC2012</database>
</source>
<size>
<width>500</width>
<height>375</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<object>
<name>cat</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>100</xmin>
<ymin>150</ymin>
<xmax>200</xmax>
<ymax>250</ymax>
</bndbox>
</object>
</annotation>
filename:图片文件名,例如 000001.jpg
。
path:图片的绝对路径。
size:图像的尺寸,包括宽度 (width
)、高度 (height
) 和深度 (depth
)。
object:图像中的目标物体信息:
name:目标的类别名称(如 cat
)。
bndbox:目标的边界框(bounding box),包括左上角 (xmin
, ymin
) 和右下角 (xmax
, ymax
) 坐标。
VOC 格式的一个关键点是每个目标都会有一个对应的 <object>
标签,包含了该目标的类别和边界框。
2. YOLO 数据集格式
YOLO(You Only Look Once)格式用于目标检测任务,在 YOLO 模型中,标签通常以 txt 文件的形式存储。每个图片对应一个 .txt
文件,其中存储了所有目标的类别和位置。YOLO 数据集格式非常简洁,通常用于与 YOLO 系列模型(如 YOLOv7、YOLOv8、YOLOv9 等)配合使用。
YOLO数据集格式包含图片和对应的txt文件
YOLO 格式的 txt 文件结构
YOLO 的标注文件是纯文本格式,文件的每一行表示一个目标,格式如下:
<class_id> <x_center> <y_center> <width> <height>
class_id:目标的类别索引,从 0 开始。例如,0
代表类别1,1
代表类别2,依此类推。
x_center, y_center:目标的中心点坐标,值是归一化的,即相对于图像宽度和高度的比例。例 如,如果图像的宽度为 500,则 x_center = 0.5
表示中心点位于图像的水平中点。
width, height:目标框的宽度和高度,也归一化到图像的宽度和高度。例如,width = 0.2
表示目标宽度是图像宽度的 20%。
示例:
假设有一个图片的大小为 640x480,且其中有两个目标(一个猫,一个狗)。对应的 000001.txt
文件内容可能如下:
0 0.5 0.5 0.2 0.25
1 0.3 0.4 0.1 0.2
第一行表示一个类 ID 为 0
(比如 cat
),它的中心点位于图像的中心,宽度和高度分别占图像宽度的 20% 和高度的 25%。
第二行表示一个类 ID 为 1
(比如 dog
),它的中心点位于 (0.3, 0.4)
,宽度和高度分别占图像宽度的 10% 和高度的 20%。
YOLO 格式的关键点是 归一化的目标位置和尺寸,通常所有的标注都存储在与图像同名的 .txt
文件中。
VOC 和 YOLO 格式的对比
特性 | VOC 格式 | YOLO 格式 |
---|---|---|
文件类型 | XML 格式 | TXT 格式 |
存储信息 | 每个目标物体的类别、边界框坐标及图像基本信息 | 每个目标物体的类别和归一化的边界框位置 |
边界框格式 | 使用左上角和右下角坐标(xmin, ymin, xmax, ymax) | 使用中心点坐标和宽度、高度(归一化的 x, y, w, h) |
适用模型 | 常用于传统的检测模型,如 Faster R-CNN、SSD 等 | 主要用于 YOLO 模型 |
图片尺寸 | 不要求归一化 | 归一化到图像尺寸的比例 |
总结:
VOC格式:适用于大多数传统的目标检测框架,提供了详细的目标信息(如图像大小、目标的具体坐标等)。
YOLO格式:简洁,目标位置和大小是归一化的,适用于 YOLO 系列模型,便于高效处理和训练。
在我们运行模型框架时,发现很多都是基于YOLO格式的代码,当我们用的数据集是VOC格式时,就不能成功运行。下面提供将VOC格式转换为YOLO格式的python代码。
import xml.etree.ElementTree as ET
import os, cv2
import numpy as np
from os import listdir
from os.path import join
classes = []
def convert(size, box):
dw = 1. / (size[0])
dh = 1. / (size[1])
x = (box[0] + box[1]) / 2.0 - 1
y = (box[2] + box[3]) / 2.0 - 1
w = box[1] - box[0]
h = box[3] - box[2]
x = x * dw
w = w * dw
y = y * dh
h = h * dh
return (x, y, w, h)
def convert_annotation(xmlpath, xmlname):
with open(xmlpath, "r", encoding='utf-8') as in_file:
txtname = xmlname[:-4] + '.txt'
txtfile = os.path.join(txtpath, txtname)
tree = ET.parse(in_file)
root = tree.getroot()
filename = root.find('filename')
img = cv2.imdecode(np.fromfile('{}/{}.{}'.format(imgpath, xmlname[:-4], postfix), np.uint8), cv2.IMREAD_COLOR)
h, w = img.shape[:2]
res = []
for obj in root.iter('object'):
cls = obj.find('name').text
if cls not in classes:
classes.append(cls)
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
float(xmlbox.find('ymax').text))
bb = convert((w, h), b)
res.append(str(cls_id) + " " + " ".join([str(a) for a in bb]))
if len(res) != 0:
with open(txtfile, 'w+') as f:
f.write('\n'.join(res))
if __name__ == "__main__":
postfix = 'jpg'
imgpath = 'VOCdevkit/JPEGImages'
xmlpath = 'VOCdevkit/Annotations'
txtpath = 'VOCdevkit/txt'
if not os.path.exists(txtpath):
os.makedirs(txtpath, exist_ok=True)
list = os.listdir(xmlpath)
error_file_list = []
for i in range(0, len(list)):
try:
path = os.path.join(xmlpath, list[i])
if ('.xml' in path) or ('.XML' in path):
convert_annotation(path, list[i])
print(f'file {list[i]} convert success.')
else:
print(f'file {list[i]} is not xml format.')
except Exception as e:
print(f'file {list[i]} convert error.')
print(f'error message:\n{e}')
error_file_list.append(list[i])
print(f'this file convert failure\n{error_file_list}')
print(f'Dataset Classes:{classes}')
上面代码可以将对应的xml文件转换为txt文件。
注意:使用时要更改为自己的路径,上述代码为相对路径,为避免出错,可以改为绝对路径!!
希望对你有帮助,谢谢你的观看。