数据集格式转换:从VOC格式转YOLOv8格式(Dataset format conversion: from VOC format to YOLOv8 format)

本文以鸟巢检测数据集为例,展示如何把 voc 格式的数据集转换成 yolov8 格式数据集,本文将从数据集下载、数据集格式转换和数据集划分三个方面进行解说。

(1)数据集下载。

本次所使用的数据集是鸟巢检测数据集,该数据集共有200张图片,展示了在输电线上鸟巢的搭建情况,鸟类在这些线路杆塔上筑巢可能带来安全隐患,如引发短路事故。因此,及时检测并处理鸟巢至关重要。

数据集下载地址:https://aistudio.baidu.com/datasetdetail/110254

备注:百度飞浆的 AI Studio 数据集专栏中有很多现实场景的实用数据集,是个很好的数据集查找网址,建议收藏保存。

下载下来的数据集如下图所示:

 

 (2)VOC 格式转 YOLOv8 格式。

代码实现:

 1 import xml.etree.ElementTree as ET
 2 import os
 3 import re
 4 from pathlib import Path
 5 import shutil
 6 
 7 file_save = "yolo_format"
 8 
 9 # 判断是否存在保存文件,如果存在则删除文件
10 if os.path.exists(file_save):
11     shutil.rmtree(file_save)
12 # 新建文件
13 os.makedirs(file_save)
14 
15 # 原始数据集标注文件路径
16 file_annotation = "E:\python_project\datasets\guojiadianwang_datasets\VOCdevkit\VOC2012\Annotations"
17 
18 # 原始数据集标签
19 classes = ['ganta_02']
20 
21 # 遍历所有标签文件 
22 for i in os.listdir(file_annotation):
23     
24     # 获取该文件最后一个/除后缀名以外的内容
25     p = Path(i)
26     name = p.stem
27 
28     # 解析xml文件
29     tree = ET.parse(os.path.join(file_annotation, i))
30     root = tree.getroot()  # 获取根节点
31     
32     # 遍历子节点size
33     for size in root.iter('size'):
34         width = int(size.find('width').text)     # 获取图片的宽度
35         height = int(size.find('height').text)   # 获取图片的高度
36     
37     # 遍历子节点object
38     all_content = ''
39     for obj in root.iter('object'):
40         cls = obj.find('name').text  # 获取标签名
41         # 获取当前类别的id
42         cls_id = classes.index(cls)
43 
44         # 获取VOC格式标签的坐标信息
45         xmlbox = obj.find('bndbox')
46         xmin = int(xmlbox.find('xmin').text)
47         ymin = int(xmlbox.find('ymin').text)
48         xmax = int(xmlbox.find('xmax').text)
49         ymax = int(xmlbox.find('ymax').text)
50 
51         # 把VOC格式的坐标转换成YOLO格式坐标
52         x = (xmin+xmax)/2/width
53         y = (ymin+ymax)/2/height
54         w = (xmax-xmin)/width
55         h = (ymax-ymin)/height
56 
57         # 保存当前标注框信息
58         one_content = '{} {:.4f} {:.4f} {:.4f} {:.4f}'.format(cls_id, x, y, w, h)
59         # 整合本张图像中所有标签信息
60         all_content = all_content + one_content + '\n'
61  
62     # 移除字符串头尾的换行符
63     all_content = all_content.strip('\n')
64     # 新建和标签文件同名的txt文件
65     file = open(os.path.join(file_save, '{}.txt'.format(name)), 'w')
66     # 写入数据并关闭文件
67     print(all_content, file=file, flush=True)

代码运行结果:

注意:原始数据标签 classes = ['ganta_02'] 的由来如果在下载绍数据集时候没有详细介绍,那么就需要我们通过代码实现获取,具体方法就是新建一个空集合,然后用 add 方法添加 obj.find('name').text 内容,最后通过集合的去重功能就可以得到标签的类型,具体主要代码如下:

data = set()
data.add(obj.find('name').text)

 

(3)数据集划分(这里就把数据集划分成训练集和测试集)。

代码实现:

import os
import shutil
import random
from pathlib import Path

# 原始图片路径
file_original_image = "E:\python_project\datasets\guojiadianwang_datasets\VOCdevkit\VOC2012\JPEGImages"
# 修改成yolov8格式后的标签路径
file_original_annotation = "yolo_format"
# 训练集数据存储路径
file_train = "train"
# 测试集数据存储路径
file_test = "test"
# 训练集所占比例
factor = 0.8

# 判断是否存在训练集存储路径文件,如果存在,则删除,然后新建训练集文件,训练集下的图像文件和训练集下的标签文件
if os.path.exists(file_train):
    shutil.rmtree(file_train)
os.makedirs(file_train)
os.makedirs(os.path.join(file_train, "images"))
os.makedirs(os.path.join(file_train, "labels"))
# 判断是否存在测试集存储路径文件,如果存在,则删除,然后新建测试集文件,测试集下的图像文件和测试集下的标签文件
if os.path.exists(file_test):
    shutil.rmtree(file_test)
os.makedirs(file_test)
os.makedirs(os.path.join(file_test, "images"))
os.makedirs(os.path.join(file_test, "labels"))

# 得到原始标签文件下的所有文件列表
datas = os.listdir(file_original_annotation)
# 得到数据集长度
num = len(datas)
# random.seed(1)
# 打乱数据集
random.shuffle(datas)

# 遍历所有标签文件
for i, j in enumerate(datas):
    # 获取文件最后一个/除后缀名之外的内容,即文件名称
    p = Path(j)
    name = p.stem

    # 获取该标签文件对应的图片
    src_images = os.path.join(file_original_image, name + ".jpg")
    # 获取该标签文件
    src_labels = os.path.join(file_original_annotation, j)
    # 判断是否是训练集,如果是则指定目的地文件目录文训练集存放图片和标签的路径,如果不是,那么久指定目的地文件目录为测试集存放图片和标签的路径
    if i < num * factor:
        dst_images = os.path.join(os.path.join(file_train), "images")
        dst_labels = os.path.join(os.path.join(file_train), "labels")
    else:
        dst_images = os.path.join(os.path.join(file_test), "images")
        dst_labels = os.path.join(os.path.join(file_test), "labels")
    # 使用复制功能把图片从原始存放目录复制到目的地
    shutil.copy(src_images, dst_images)
    shutil.copy(src_labels, dst_labels)

pass

代码运行结果:

 由此就可以实现把数据集从 VOC 格式转换成 YOLOv8 格式,并且也实现了数据集划分成训练集和测试集的过程。

数据集划分好之后,就可以使用 YOLOv8 对数据集进行目标检测,具体实现可参考 “yolov8 训练自定义数据集(windows+CPU)” 一文。

 

posted @ 2024-11-12 09:23  ttweixiao9999  阅读(9)  评论(0编辑  收藏  举报