VOC转YOLO,VOC/YOLO数据集的划分

1.VOC格式标注文件转换成Yolo格式标注文件

Yolo标注的格式与VOC格式不同之处在于:

(1)Yolo格式下的每张图片的所有包含的目标的标注信息,都统一以txt文件的形式储存。一张图片对应一个与其相同名称的txt文件。在txt文件中,每一行对应图片中一个目标的信息,用一个数字指代种类编号,剩下四个数字代表坐标信息。

VOC格式则是每张图片对应一个与其相同名称的xml格式文件。

(2)Yolo格式的数据集,是将训练数据和验证(测试)数据分成两个文件夹,例如训练数据文件夹下包括:训练图片文件夹、训练图片对应的标注文件(txt格式)的文件夹。

VOC格式则是将所有图片(无论是训练图片还是测试图片)都放在一个文件夹下、将所有标注文件(无论是训练的还是测试的)也都放在一个文件夹下,最后用两个txt格式的文件来指定那些是训练数据,哪些是测试数据:例如,train.txt中将所有训练数据(训练图片的名称,去掉.jpg后缀)按每行对应一个的方式储存,test.txt则将所有测试数据的名称(去掉后缀)储存起来。

由此,我们在将Yolo格式的数据集转换成voc格式的数据集时,主要有两部分工作:

(1)将所有的txt标注文件转化成xml标注文件。(2)将yolo数据集的整理形式转化成voc的整理形式:包括将分成train和val(test)两个部分的图片、标注文件合到一起,同时将所有训练集数据名称(去掉后缀)写入到train.txt、将所有测试集数据名称(去掉后缀)写入到test.txt。

以上介绍的转换工作对应的代码均在下面列出。
 


# 将VOC格式标注文件(xml文件)转换成Yolo格式标注文件(txt文件)

import xml.etree.ElementTree as ET
import os
 
 
voc_folder = r"datasets\Annotations" #储存voc格式的标注文件的文件夹,相对路径
yolo_folder = r"yolo_datasets\Annotations" #转换后的yolo格式标注文件的储存文件夹,相对路径
 
class_id = ["pig","stand","lie","eat"] #储存数据集中目标种类名称的列表,接下来的转换函数中会将该列表中种类名称对应的列表索引号作为写入yolo标注文件中该类目标的种类序号
 
#voc标注的目标框坐标值转换到yolo标注的目标框坐标值的函数
def convert(size, box):
    dw = 1. / size[0]
    dh = 1. / size[1]
    x = (box[0] + box[1]) / 2.0
    y = (box[2] + box[3]) / 2.0
    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)
 
#对单个voc标注文件进行转换成其对应的yolo文件的函数
def convert_annotation(xml_file):
    file_name = xml_file.strip(".xml")  # 这一步将所有voc格式标注文件取出后缀名“.xml”,方便接下来作为yolo格式标注文件的名称
    in_file = open(os.path.join(voc_folder,xml_file)) #打开当前转换的voc标注文件
    out_file = open(os.path.join(yolo_folder,file_name + ".txt",),'w') #创建并打开要转换成的yolo格式标注文件
    tree = ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)
    for obj in root.iter('object'):
        cls = obj.find('name').text
        cls_id = class_id.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)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
 
 
 
xml_fileList = os.listdir(voc_folder) #将所有voc格式的标注文件的名称取出存放到列表xml_fileList中
for xml_file in xml_fileList: #这里的for循环开始依次对所有voc格式标注文件生成其对应的yolo格式的标注文件
    convert_annotation(xml_file)

print("success!")



运行结果。

 

根据VOC格式中的train.txt和test.txt文件来将数据集图片和标注归类到Yolo格式下的train和val文件夹中。

因为Yolo格式的数据集是将训练数据和验证(测试)数据分成两个文件夹,

而VOC格式是将所有图片放在一个图片文件夹、所有标注文件放在一个标注文件夹中。

所有在上面的转换步骤完成后,我们还需要将训练数据和验证(测试)数据分别存放。

2.YOLO数据集划分 

分析:

划分数据集主要的步骤就是,首先要将数据集打乱顺序,然后按照一定的比例将其分为训练集,验证集和测试集。
这里我定的比例是7:1:2。

步骤:

1、将数据集打乱顺序

数据集有图片和标注文件,我们需要把两种文件绑定然后将其打乱顺序。
首先读取数据后,将两种文件通过zip函数绑定。

然后打乱顺序,再将两个列表分开。

2、按照确定好的比例将两个列表元素分割

分别用三个列表储存一下图片和标注文件的元素

3、在本地生成文件夹,将划分好的数据集分别保存

这样就保存好了。

4.生成 train_list.txtval_list.txttrain_list.txt存放了所有训练图片的路径,val_list.txt则是存放了所有验证图片的路径

import os
import shutil
import random

random.seed(0)


def split_data(file_path,xml_path, new_file_path, train_rate, val_rate, test_rate):
    each_class_image = []
    each_class_label = []
    for image in os.listdir(file_path):
        each_class_image.append(image)
    for label in os.listdir(xml_path):
        each_class_label.append(label)
        each_class_image.sort()
        each_class_label.sort()
    data=list(zip(each_class_image,each_class_label))
    total = len(each_class_image)
    random.shuffle(data)
    each_class_image,each_class_label=zip(*data)
    train_images = each_class_image[0:int(train_rate * total)]
    val_images = each_class_image[int(train_rate * total):int((train_rate + val_rate) * total)]
    test_images = each_class_image[int((train_rate + val_rate) * total):]
    train_labels = each_class_label[0:int(train_rate * total)]
    val_labels = each_class_label[int(train_rate * total):int((train_rate + val_rate) * total)]
    test_labels = each_class_label[int((train_rate + val_rate) * total):]

    for image in train_images:
        
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'train' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)

    for label in train_labels:
        
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'train' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)

    for image in val_images:
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'val' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)

    for label in val_labels:
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'val' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)

    for image in test_images:
        old_path = file_path + '/' + image
        new_path1 = new_file_path + '/' + 'test' + '/' + 'images'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + image
        shutil.copy(old_path, new_path)

    for label in test_labels:
        old_path = xml_path + '/' + label
        new_path1 = new_file_path + '/' + 'test' + '/' + 'labels'
        if not os.path.exists(new_path1):
            os.makedirs(new_path1)
        new_path = new_path1 + '/' + label
        shutil.copy(old_path, new_path)
        print("success!")


if __name__ == '__main__':
    file_path = "datasets\JPEGlmages"   #图片所在路径
    xml_path = 'yolo_datasets\Annotations'  #YOLO数据集标签所在路径,相对路径
    new_file_path = "yolo_datasets"         #划分后,yolo数据集所在路径,相对路径
    split_data(file_path,xml_path, new_file_path, train_rate=0.7, val_rate=0.1, test_rate=0.2)

dataset_path = 'yolo_datasets'  # 数据集路径
train_list_file = 'yolo_datasets/train_list.txt'  # 保存训练集图像路径的文件 此处要用/
val_list_file = 'yolo_datasets/val_list.txt'  # 保存验证集图像路径的文件 此处要用/

train_dir = os.path.join(dataset_path, 'train\images')  # 训练集文件夹路径
val_dir = os.path.join(dataset_path, 'val\images')  # 验证集文件夹路径

# 获取训练集图像文件列表
train_image_files = [f for f in os.listdir(train_dir) if f.endswith('.jpg')]

# 获取验证集图像文件列表
val_image_files = [f for f in os.listdir(val_dir) if f.endswith('.jpg')]

# 将训练集图像路径写入文件
with open(train_list_file, 'w') as f:
    for file in train_image_files:
        image_path = os.path.join('train', file)
        f.write(image_path + '\n')

# 将验证集图像路径写入文件
with open(val_list_file, 'w') as f:
    for file in val_image_files:
        image_path = os.path.join('val', file)
        f.write(image_path + '\n')

print("train_list.txt and val_list.txt generated successfully.")

 运行完毕。图片和标注文件乱序,且一一对应。(Annotations是voc转YOLO后,标注文件所在的文件夹)

3.VOC数据集划分

import os
import random
import shutil

# 数据集文件夹路径,相对路径
dataset_dir = "datasets\JPEGlmages" 

# 训练集和验证集比例
train_ratio = 0.7

# 指定保存train_list.txt和val_list.txt的文件夹路径,相对路径
output_dir = "datasets"

# 获取数据集中的图像文件列表
image_files = [file for file in os.listdir(dataset_dir) if file.endswith(".jpg")]

# 随机打乱图像文件列表
random.shuffle(image_files)

# 计算训练集和验证集的分割索引
split_index = int(len(image_files) * train_ratio)

# 分割图像文件列表为训练集和验证集
train_files = image_files[:split_index]
val_files = image_files[split_index:]

# 生成train_list.txt文件
train_list_path = os.path.join(output_dir, "train_list.txt")
with open(train_list_path, "w") as train_list_file:
    for file in train_files:
        train_list_file.write(os.path.join(dataset_dir, file) + "\n")

# 生成val_list.txt文件
val_list_path = os.path.join(output_dir, "val_list.txt")
with open(val_list_path, "w") as val_list_file:
    for file in val_files:
        val_list_file.write(os.path.join(dataset_dir, file) + "\n")

# 移动train_list.txt和val_list.txt到指定文件夹
shutil.move(train_list_path, os.path.join(output_dir, "train_list.txt"))
shutil.move(val_list_path, os.path.join(output_dir, "val_list.txt"))
print("success!")

 运行结果。

PS:

做完以上步骤,若直接开始训练,会报错:

解决方法:
找到  utils/dataset.py 文件,搜索框搜索 Define label,然后修改代码。

亦或者重新划分数据集,可参考我这篇文章:https://blog.csdn.net/weixin_45819759/article/details/131211495

 参考文章:

将VOC格式标注文件转换为Yolo格式_voc转yolo格式_WentingDu的博客-CSDN博客

【yolov5】将标注好的数据集进行划分(附完整可运行python代码)_yolov5数据集划分_freezing?的博客-CSDN博客

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用以下步骤将voc数据换为yolo格式的数据集: 1. 下载并安装YOLO: 首先,您需要下载并安装YOLO (You Only Look Once)。您可以从YOLO的GitHub存储库中获取源代码和相关文档。 2. 准备YOLO配置文件: 在YOLO中,您需要一个配置文件来定义训练和测试模型的参数。根据您的数据集进行相应的配置,包括类别数、输入图像大小等。 3. 解析VOC数据集: 将VOC数据集中的XML注释文件换为YOLO标签格式。每个XML文件都对应一个图像,其中包含了目标对象的位置和类别。 4. 换坐标: YOLO使用归一化坐标来表示边界框位置。将VOC数据集中的边界框坐标换为归一化坐标。 5. 创建YOLO数据集文件: 创建包含图像路径和边界框信息的txt文件,以供YOLO使用。每行包含图像路径和对应的边界框信息。 6. 划分训练和测试集: 将数据集分为训练集和测试集,通常按照比例进行划分。 7. 修改YOLO配置文件: 根据划分的训练集和测试集的路径,修改YOLO配置文件中的训练和测试数据集路径。 8. 训练YOLO模型: 使用换后的YOLO数据集和修改后的配置文件,进行模型训练。根据YOLO的文档,执行相应的命令来开始训练。 请注意,上述步骤只是一个大致的指南,具体实现可能因您使用的数据集和工具版本而有所不同。建议您参考YOLO的文档和相关教程,以获得更详细的指导。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值