第一章:计算机视觉中图像的基础认知
第二章:计算机视觉:卷积神经网络(CNN)基本概念(一)
第三章:计算机视觉:卷积神经网络(CNN)基本概念(二)
第四章:搭建一个经典的LeNet5神经网络(附代码)
第五章:计算机视觉:神经网络实战之手势识别(附代码)
第六章:计算机视觉:目标检测从简单到容易(附代码)
第七章:MTCNN 人脸检测技术揭秘:原理、实现与实战(附代码)
第八章:探索YOLO技术:目标检测的高效解决方案
第九章:计算机视觉:主流数据集整理
第十章:生成对抗网络(GAN):从概念到代码实践(附代码)
第十一章:计算机视觉:经典数据格式(VOC、YOLO、COCO)解析与转换(附代码)
第十二章:计算机视觉:YOLOv11遥感图像目标检测(附代码)
在计算机视觉(CV)领域,无论是进行目标检测、图像分类还是其他任务,理解如何处理不同格式的数据集以及掌握训练过程中涉及的关键指标至关重要。本文将探讨三种经典的数据格式(VOC、YOLO、COCO)
一、VOC 格式
VOC(Visual Object Classes)格式是一种广泛应用于目标检测任务的数据标注标准,尤其常见于PASCAL VOC挑战赛中。它使用XML文件来存储图像中的对象位置信息和类别信息。
文件结构与内容
每个图像对应一个XML文件,该文件包含了图像的基本信息以及图像中每个对象的位置和类别标签。以下是一个典型的VOC格式XML文件的内容示例:
<annotation><folder>images</folder><filename>000001.jpg</filename><size><width>500</width><height>375</height><depth>3</depth></size><object><name>dog</name><pose>Left</pose><truncated>1</truncated><difficult>0</difficult><bndbox><xmin>263</xmin><ymin>211</ymin><xmax>324</xmax><ymax>339</ymax></bndbox></object><object><name>person</name><pose>Unspecified</pose><truncated>0</truncated><difficult>0</difficult><bndbox><xmin>159</xmin><ymin>59</ymin><xmax>281</xmax><ymax>287</ymax></bndbox></object>
</annotation>
关键元素说明
<folder>
:包含图像的文件夹名称。<filename>
:图像文件名。<size>
:描述图像尺寸,包括宽度、高度和深度(通常是3表示RGB图像)。<object>
:每个对象的信息块,可以有多个,每个对象包含:<name>
:对象类别名称。<pose>
:拍摄时物体的姿态。<truncated>
:指示物体是否被裁剪(部分位于图像外)。<difficult>
:指示物体是否难以识别。<bndbox>
:边界框坐标,包括:<xmin>, <ymin>
:边界框左上角的绝对坐标(像素值)。<xmax>, <ymax>
:边界框右下角的绝对坐标(像素值)。
处理VOC数据的Python代码示例
下面是一个简单的例子,展示如何读取并解析VOC格式的XML文件,并提取其中的对象信息:
from xml.etree import ElementTreedef parse_voc_xml(file_path):tree = ElementTree.parse(file_path)root = tree.getroot()# 获取图像尺寸img_width = int(root.find("size/width").text)img_height = int(root.find("size/height").text)objects = []for obj in root.findall("object"):name = obj.find("name").textxmin = int(obj.find("bndbox/xmin").text)ymin = int(obj.find("bndbox/ymin").text)xmax = int(obj.find("bndbox/xmax").text)ymax = int(obj.find("bndbox/ymax").text)objects.append({"name": name,"bbox": [xmin, ymin, xmax, ymax]})return img_width, img_height, objects# 使用示例
file_path = "path/to/voc_annotation.xml"
width, height, objs = parse_voc_xml(file_path)
print(f"Image width: {width}, height: {height}")
for obj in objs:print(obj)
此代码段展示如何从给定的VOC格式XML文件中提取图像尺寸和每个对象的位置及类别信息。
二、YOLO 格式
YOLO(You Only Look Once)是一种流行的目标检测算法,它使用一种特定的数据标注格式来描述图像中的对象位置和类别信息。与VOC或COCO等其他数据格式不同,YOLO格式采用文本文件(.txt)存储每个图像的标注信息,这些信息包括对象的类别ID及其边界框的位置坐标。
文件结构与内容
对于每张图像,YOLO格式会有一个对应的文本文件,该文件中每一行代表一个对象,并且包含五个数值:
- 类别ID(
cls_id
) - 边界框中心点的x坐标(
x_center
) - 边界框中心点的y坐标(
y_center
) - 边界框的宽度(
w
) - 边界框的高度(
h
)
所有坐标都是相对坐标,即相对于图像宽度和高度的比例值(0到1之间的小数),而不是绝对像素值。以下是YOLO格式的一个简单示例:
假设有一张分辨率为640x480的图片,其中包含两个对象:一只狗和一个人。相应的YOLO格式标注文件可能如下所示:
0 0.500000 0.600000 0.250000 0.300000 # 狗
1 0.300000 0.200000 0.100000 0.150000 # 人
- 第一行表示“狗”的类别ID为0,其边界框中心位于图像宽度的50%、高度的60%,宽度占整个图像宽度的25%,高度占30%。
- 第二行表示“人”的类别ID为1,其边界框中心位于图像宽度的30%、高度的20%,宽度占整个图像宽度的10%,高度占15%。
处理YOLO数据的Python代码示例
以下是一个简单的例子,展示如何将VOC格式转换为YOLO格式,并读取YOLO格式的数据。
from xml.etree import ElementTreedef voc_to_yolo(voc_file_path, output_file_path, label2idx):tree = ElementTree.parse(voc_file_path)root = tree.getroot()img_width = int(root.find("size/width").text)img_height = int(root.find("size/height").text)with open(output_file_path, 'w') as f:for obj in root.findall("object"):name = obj.find("name").textcls_id = label2idx[name]xmin = int(obj.find("bndbox/xmin").text)ymin = int(obj.find("bndbox/ymin").text)xmax = int(obj.find("bndbox/xmax").text)ymax = int(obj.find("bndbox/ymax").text)# 这是计算边界框左上角和右下角的x坐标的平均值,即边界框中心点的x坐标(以像素为单位)。x_center = (xmin + xmax) / 2.0 / img_width# 这是计算边界框左上角和右下角的y坐标的平均值,即边界框中心点的y坐标(以像素为单位)。y_center = (ymin + ymax) / 2.0 / img_heightwidth = (xmax - xmin) / float(img_width)height = (ymax - ymin) / float(img_height)line = f"{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n"f.write(line)# 示例用法
label2idx = {"dog": 0, "person": 1}
voc_file_path = "path/to/voc_annotation.xml"
output_file_path = "path/to/output.txt"
voc_to_yolo(voc_file_path, output_file_path, label2idx)
在YOLO格式中,边界框的坐标是以相对坐标的形式表示的,而不是绝对像素值。具体来说,x_center
和 y_center
分别代表边界框中心点相对于图像宽度和高度的比例值(范围从0到1),而 w
和 h
分别代表边界框的宽度和高度相对于图像宽度和高度的比例值。
公式解释
x_center = (xmin + xmax) / 2.0 / img_width
y_center = (ymin + ymax) / 2.0 / img_height
计算边界框中心点的相对坐标
-
计算边界框中心点的绝对坐标:
(xmin + xmax) / 2.0
:这是计算边界框左上角和右下角的x坐标的平均值,即边界框中心点的x坐标(以像素为单位)。(ymin + ymax) / 2.0
:这是计算边界框左上角和右下角的y坐标的平均值,即边界框中心点的y坐标(以像素为单位)。
-
转换为相对坐标:
/ img_width
:将边界框中心点的x坐标除以图像的宽度,得到一个比例值(范围从0到1)。例如,如果边界框中心点的x坐标是320像素,而图像的宽度是640像素,则x_center
的值为320 / 640 = 0.5
。/ img_height
:将边界框中心点的y坐标除以图像的高度,得到一个比例值(范围从0到1)。例如,如果边界框中心点的y坐标是240像素,而图像的高度是480像素,则y_center
的值为240 / 480 = 0.5
。
示例
假设有一张分辨率为640x480的图片,其中有一个对象的边界框坐标如下:
xmin = 100
ymin = 150
xmax = 300
ymax = 350
根据上述公式计算:
-
计算边界框中心点的绝对坐标:
x_center_abs = (100 + 300) / 2.0 = 200
y_center_abs = (150 + 350) / 2.0 = 250
-
转换为相对坐标:
x_center_rel = 200 / 640 ≈ 0.3125
y_center_rel = 250 / 480 ≈ 0.5208
因此,在YOLO格式的标注文件中,该对象的标注信息可能如下所示:
0 0.3125 0.5208 0.3125 0.4167
其中:
0
是类别ID。0.3125
是边界框中心点的x坐标相对于图像宽度的比例值。0.5208
是边界框中心点的y坐标相对于图像高度的比例值。0.3125
是边界框宽度相对于图像宽度的比例值((300 - 100) / 640 = 200 / 640 ≈ 0.3125
)。0.4167
是边界框高度相对于图像高度的比例值((350 - 150) / 480 = 200 / 480 ≈ 0.4167
)。
读取YOLO格式数据
def read_yolo_annotations(file_path):annotations = []with open(file_path, 'r') as f:lines = f.readlines()for line in lines:parts = line.strip().split()cls_id = int(parts[0])x_center, y_center, w, h = map(float, parts[1:])annotations.append({"cls_id": cls_id,"bbox": [x_center, y_center, w, h]})return annotations# 示例用法
file_path = "path/to/yolo_annotation.txt"
annotations = read_yolo_annotations(file_path)
for annotation in annotations:print(annotation)
通过上述示例,可以轻松地在VOC格式和YOLO格式之间进行转换,并读取YOLO格式的数据。这对于准备训练数据集或进行数据分析非常有用。
三、COCO 格式
COCO(Common Objects in Context)格式是一种广泛用于计算机视觉任务,特别是目标检测、分割和关键点检测的数据标注标准。它采用JSON文件来存储图像及其对应的注释信息,具有高度结构化的特点,支持复杂的多对象标注。
文件结构与内容
COCO格式的JSON文件通常包含以下几个主要部分:
- images: 包含图像的基本信息。
- annotations: 描述图像中的每个对象或区域的信息。
- categories: 定义所有可能的对象类别。
以下是一个简化的COCO格式JSON文件示例:
{"images": [{"id": 0,"width": 640,"height": 480,"file_name": "000000000009.jpg"}],"annotations": [{"id": 1,"image_id": 0,"category_id": 1,"bbox": [100, 150, 200, 200],"area": 40000,"iscrowd": 0},{"id": 2,"image_id": 0,"category_id": 2,"bbox": [300, 200, 100, 150],"area": 15000,"iscrowd": 0}],"categories": [{"id": 1,"name": "person","supercategory": "person"},{"id": 2,"name": "dog","supercategory": "animal"}]
}
images
: 每个元素包含一个图像的信息,如ID、宽度、高度和文件名。annotations
: 每个元素描述一个对象的位置(通过边界框bbox
)、面积area
、是否为群体对象iscrowd
等信息。categories
: 定义了所有可能的对象类别及其ID。
关键字段解释
bbox
: 边界框的坐标,格式为[x, y, width, height]
,其中x
和y
是边界框左上角的绝对坐标(像素值),width
和height
是边界框的宽度和高度(同样以像素为单位)。area
: 对象的面积,对于目标检测任务,这通常是边界框的面积(宽度乘以高度)。iscrowd
: 标记该对象是否为群体对象(例如一群人聚集在一起)。如果为1
,则表示该对象是一个群体;如果为0
,则表示单独的对象。
处理COCO数据的Python代码示例
下面是一个简单的例子,展示如何读取并解析COCO格式的JSON文件,并提取其中的对象信息:
import jsondef parse_coco_json(file_path):with open(file_path, 'r') as f:data = json.load(f)images = {img['id']: img for img in data['images']}categories = {cat['id']: cat for cat in data['categories']}annotations = []for ann in data['annotations']:image_info = images[ann['image_id']]category_info = categories[ann['category_id']]annotation = {"image_id": ann['image_id'],"filename": image_info['file_name'],"category_id": ann['category_id'],"category_name": category_info['name'],"bbox": ann['bbox'],"area": ann['area']}annotations.append(annotation)return annotations# 示例用法
file_path = "path/to/coco_annotation.json"
annotations = parse_coco_json(file_path)
for annotation in annotations:print(annotation)
输出结果:
{'image_id': 0, 'filename': '000000000009.jpg', 'category_id': 1, 'category_name': 'person', 'bbox': [100, 150, 200, 200], 'area': 40000}
{'image_id': 0, 'filename': '000000000009.jpg', 'category_id': 2, 'category_name': 'dog', 'bbox': [300, 200, 100, 150], 'area': 15000}
上述代码首先将images
和categories
转换为字典以便快速查找,然后遍历所有的annotations
,从中提取相关信息并打印出来。