了解PASCAL VOC数据集
对象检测是指计算机系统从图像/场景中定位所需类型的对象的能力。
对于物体检测,训练数据可以用XML文件或JSON文件表示。每种表示方法都有其优点和缺点。
在这篇文章中,我们将了解这种数据集的表示方法如何帮助我们进行物体检测。
我们将讨论什么是PASCAL VOC格式,它背后的历史,以及我们如何使用它进行物体检测。
我们还将使用Python建立一个简单的数据集格式验证器,以验证数据集是否符合PASCAL VOC格式的规则。
前提条件
读者必须具备以下条件,才能继续阅读。
- 对如何处理机器学习数据集有良好的理解。
- 对[物体检测]有相当的了解。
- 良好的[Python]知识。
- 一个你选择的代码编辑器。
简介
为了使机器学习模型能够检测到图像中的物体,必须用一个数据集来训练它,这个数据集包含了图像中存在的所有物体的信息。
包含图像中所有物体信息的数据集是通过一个叫做注释的过程建立的。
在物体检测的背景下,注释帮助我们通过在物体上画一个矩形框(称为边界框)将物体映射到其各自的标签。

正如你在上图中所看到的,我们将物体与它们各自的标签进行映射,如car 、person 、bicycle 、或traffic light 。
每个对象-标签的映射都用一个叫做 "边界框"的矩形框表示。界限框是一系列的坐标或数值,代表一个物体在图像中的位置。
界限框的表示方法可能因数据集的不同而不同。
让我们在接下来的章节中讨论更多关于包围盒的内容。
PASCAL VOC
这个数据集为物体检测和分割问题提供了标准化的图像。
这些数据集是使用遵循标准化程序的工具建立的,用于评估和比较不同的方法。
2008年,PASCAL VOC数据集被宣布为物体检测的基准。
PASCAL VOC背后的历史
模式分析、统计建模和计算学习(PASCAL) 从2005年到2012年开展了一系列物体检测的挑战,遵循标准化的文件结构来保存这些图像注释。
PASCAL视觉物体类别(VOC)挑战有两个主要部分。
- 一个公开可用的数据集和标准化的评估软件。
- 一个年度竞赛和一个研讨会。
这项挑战的主要目标是找出模型的执行能力。
Classification- 检查一个物体是否是图像的一部分。Detection- 定位图像中存在的物体的位置。
这一系列的挑战在2012年结束,对数据集进行了重大的加强和改进。
现在,PASCAL VOC为20多个不同的类别提供了标准化的图像数据集,这些数据集通常用于物体检测、语义分割和其他分类任务等。
PASCAL VOC分类法
以下是PASCAL VOC数据集结构的一个样本,看起来像什么。

正如你在上图中看到的,这些对象注释是用以下字段表示的。
文件夹
数据集所处的父文件夹的名称。这个字段帮助我们在一个目录中定位注释的图像。
在这里,你可以看到,图像文件存在于一个名为MARMOT_ANNOTATION 的文件夹中。
文件名
数据被注释的图像文件名。这个字段指定了一个注释图像文件的相对路径。
这里,我们正在处理的文件是10.1.1.1.2006_3.bmp 。
路径
图像文件所在的绝对路径。
这里,我们有所有的图像文件存在于绝对路径下MARMOT_ANNOTATION/10.1.1.1.2006_3.bmp 。
来源
指定文件在数据库中的原始位置。
因为我们没有使用数据库,所以默认设置为Unknown 。
大小
指定一个图像的width,height,depth 。
正如你所看到的,图像的宽度为793 像素,高度为1123 像素,深度为3 像素。
在图像中,通常,
depth字段代表RGB色标,即3。
分割的
这个字段标志着图像是否包含非线性(不规则)形状的注释--通常被称为多边形。
默认情况下,segmented 值被设置为0 (线性形状)。
对象:名称
这个字段指定了注释标签的名称。这里,标签是一个column 。
对象:姿态
指定图像的偏斜度或方向。默认情况下,它被指定为Unspecified ,这意味着图像没有偏斜。
object: truncated
说明一个物体是否完全或部分可见(可以分别为0或1)。
对象:困难
说明一个物体是否难以从图像中识别(可以是0-容易或1-困难)。
对象:bndbox
这些是决定物体位置的坐标。
这些坐标表示为[xmin, ymin, xmax, ymax] ,其中它们对应于(x, y) ,即物体的左上和右下位置的坐标。
这里,界线盒的值是[458, 710, 517, 785] 。
PASCAL VOC验证器
在了解了PASCAL VOC数据集的整体结构后,现在让我们深入到用Python实现一个简单的数据集验证器。
输入库
我们将使用两个库来处理XML文件。
xmltodict- 用来处理XML文件,就像我们处理JSON文件或字典一样。xml.etree- 用于解析和创建XML数据。
如下图所示,导入它们。
import xmltodict
import xml.etree.ElementTree as ET
创建对象
在这里,我们将通过使用XML解析器来读取数据集文件,如图所示。
dataset_file = r'/sample.xml' # The path to the XML file
xml_tree = ET.parse(dataset_file) # Parse the XML file
root = xml_tree.getroot() # Find the root element
断言
为了验证PASCAL VOC数据集的有效性,我们将在Python中使用assert() 断言语句。
简单地说,assert() ,通过测试某些标准来调试代码。如果它不符合标准,它就会抛出一个默认的错误。虽然,我们可以自定义要引发的错误。
验证
强烈建议通过在新的标签或窗口中打开PASCAL VOC数据集的样本来学习。
你可以在这里找到这个样本数据集。
assert root.tag == 'annotation' or root.attrib['verified'] == 'yes', "PASCAL VOC does not contain a root element" # Check if the root element is "annotation"
assert len(root.findtext('folder')) > 0, "XML file does not contain a 'folder' element"
assert len(root.findtext('filename')) > 0, "XML file does not contain a 'filename'"
assert len(root.findtext('path')) > 0, "XML file does not contain 'path' element"
assert len(root.find('source')) == 1 and len(root.find('source').findtext('database')) > 0, "XML file does not contain 'source' element with a 'database'"
assert len(root.find('size')) == 3, "XML file doesn not contain 'size' element"
assert root.find('size').find('width').text and root.find('size').find('height').text and root.find('size').find('depth').text, "XML file does not contain either 'width', 'height', or 'depth' element"
assert root.find('segmented').text == '0' or len(root.find('segmented')) > 0, "'segmented' element is neither 0 or a list"
assert len(root.findall('object')) > 0, "XML file contains no 'object' element" # Check if the root contains zero or more 'objects'
上面的代码做了以下工作。
- 检查
root是否为annotation。让verified属性为yes,是可选的。 - 通过验证长度是否大于
0,检查数据集是否包含folder、filename、path、source。 - 检查
size对象是否包含width,height, 和depth。 - 最后,它检查
segmented参数。它必须包含一个0的值或一个空的列表。
一个
segmented列表表示该对象不是线性形状的。因此,多边形(非线性)形状的掩码值必须存在,以识别此类对象。
在涵盖了所有关于图像的元数据之后,让我们进入验证每个对象的阶段。
在
annotation键下,可能有不止一个对象。因此,我们循环浏览所有的object键。
required_objects = ['name', 'pose', 'truncated', 'difficult', 'bndbox'] # All possible meta-data about an object
for obj in root.findall('object'):
assert len(obj.findtext(required_objects[0])) > 0, "Object does not contain a parameter 'name'"
assert len(obj.findtext(required_objects[1])) > 0, "Object does not contain a parameter 'pose'"
assert int(obj.findtext(required_objects[2])) in [0, 1], "Object does not contain a parameter 'truncated'"
assert int(obj.findtext(required_objects[3])) in [0, 1], "Object does not contain a parameter 'difficult'"
assert len(obj.findall(required_objects[4])) > 0, "Object does not contain a parameter 'bndbox'"
for bbox in obj.findall(required_objects[4]):
assert int(bbox.findtext('xmin')) > 0, "'xmin' value for the bounding box is missing "
assert int(bbox.findtext('ymin')) > 0, "'ymin' value for the bounding box is missing "
assert int(bbox.findtext('xmax')) > 0, "'xmax' value for the bounding box is missing "
assert int(bbox.findtext('ymax')) > 0, "'ymax' value for the bounding box is missing "
print('The dataset format is PASCAL VOC!')
上面的代码做了以下工作。
- 声明一个包含所有可能存在于
object的元数据键的列表required_objects。 - 循环浏览每个
object,检查是否存在required_objects中的键。 truncated和difficult的可能值是二进制的。因此,我们检查提取的值是否是0或1。
如果所有的断言都成功通过,我们可以调用数据集为PASCAL VOC格式。
上面的代码片段帮助我们验证并指出错误,如果我们漏掉了任何所需的关键。
结论
PASCAL VOC数据集被用于物体检测和分割。它以XML文件的形式表示,有助于我们在使用标准化格式表示的同时,轻松定制数据集。
总结一下,读者学会了。
- 如何通过训练注释来检测物体。
- 什么是PASCAL VOC以及它是如何起源的。
- PASCAL VOC数据集表示所需的不同元数据参数。
- 最后,读者实现了一个简单的Python验证脚本来验证PASCAL VOC数据集的真实性。