首先转为yolov5,然后通过label_convert工具转换yolov5到yolov8。
VOC数据格式如下
根据该文件夹,使用代码images_tag.py
# images_tag.py 该脚本文件需要修改第11-12行,设置train、val、test的切分的比率
import os
import random
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--xml_path', default=r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1\Annotations', type=str,
help='input xml label path')
parser.add_argument('--txt_path', default=r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1/imagesets', type=str,
help='output txt label path')
opt = parser.parse_args()
trainval_percent = 0.9
train_percent = 0.7 # 这里的train_percent 是指占trainval_percent中的
xmlfilepath = opt.xml_path
txtsavepath = opt.txt_path
total_xml = os.listdir(xmlfilepath)
if not os.path.exists(txtsavepath):
os.makedirs(txtsavepath)
num = len(total_xml)
list_index = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list_index, tv)
train = random.sample(trainval, tr)
file_trainval = open(txtsavepath + '/trainval.txt', 'w', encoding='utf-8')
file_test = open(txtsavepath + '/test.txt', 'w', encoding='utf-8')
file_train = open(txtsavepath + '/train.txt', 'w', encoding='utf-8')
file_val = open(txtsavepath + '/val.txt', 'w', encoding='utf-8')
for i in list_index:
name = total_xml[i][:-4] + '\n'
if i in trainval:
file_trainval.write(name)
if i in train:
file_train.write(name)
else:
file_val.write(name)
else:
file_test.write(name)
file_trainval.close()
file_train.close()
file_val.close()
file_test.close()
然后使用代码
# mian.py 该脚本文件需要修改第10行(classes)即可
# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET
from tqdm import tqdm
import os
from os import getcwd
sets = ['train', 'test', 'val']
# 这里使用要改成自己的类别
classes = ['red', 'yellow', 'green', 'off']
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
x = round(x, 6)
w = round(w, 6)
y = round(y, 6)
h = round(h, 6)
return x, y, w, h
# 后面只用修改各个文件夹的位置
def convert_annotation(image_id):
# try:
in_file = open(r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1/Annotations/%s.xml' % (image_id), encoding='utf-8')
out_file = open(r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1/labels/%s.txt' % (image_id), 'w', encoding='utf-8')
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'):
difficult = obj.find('difficult').text
cls = obj.find('name').text
if cls not in classes or int(difficult) == 1:
continue
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))
b1, b2, b3, b4 = b
# 标注越界修正
if b2 > w:
b2 = w
if b4 > h:
b4 = h
b = (b1, b2, b3, b4)
bb = convert((w, h), b)
out_file.write(str(cls_id) + " " +
" ".join([str(a) for a in bb]) + '\n')
# except Exception as e:
# print(e, image_id)
# yolov5_to_yolov8 --data_dir D:\DeepLearning\VOC2Yolo\S2TLD\normal_1 --mode_list train,val
# 这一步生成的txt文件写在data.yaml文件里
wd = getcwd()
for image_set in sets:
if not os.path.exists(r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1/labels/'):
os.makedirs(r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1/labels/')
# image_ids = open(r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1/Imagesets/%s.txt' %
# (image_set)).read().strip().split()
image_ids = open(r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1/Imagesets/%s.txt' %(image_set), encoding='utf-8').read().strip().split()
list_file = open(r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1/%s.txt' % (image_set), 'w', encoding='utf-8')
for image_id in tqdm(image_ids):
list_file.write('D:/DeepLearning/VOC2Yolo/S2TLD/normal_1/images/%s.jpg\n' % (image_id))#不能使用r符号,否则\n不会被转义为换行符,导致后续找不到路径。
convert_annotation(image_id)
list_file.close()
到此生成YOLOV5格式的数据集
YOLOV5数据集格式如下:
yolov5_dataset
├── classes.txt
├── non_labels # 通常用来放负样本
│ └── bg1.jpeg
├── images
│ ├── images(13).jpg
│ └── images(3).jpg
├── labels
│ ├── images(13).txt
│ └── images(3).txt
├── train.txt
└── val.txt
通过label_convert工具,进行yolov5转yolov8
#网址 https://rapidai.github.io/LabelConvert/docs/supportconversions/yolov5_to_yolov8/
pip install label_convert
安装后,使用
yolov5_to_yolov8 --data_dir dataset/yolov5_dataset --mode_list train,val,test
即可得到yolov8数据格式数据集
--data_dir: 数据集所在目录。示例为dataset/yolov5_dataset
--save_dir: 保存转换后的数据集目录。默认为dataset/yolov5_dataset_yolov8
--mode_list: 指定划分的数据集种类。 (例如:train,val,test / train,val)
yolov8数据集格式如下
yolov8_dataset
├── images
│ ├── train
│ │ ├── 0dcddf72.jpg
│ │ └── images(3).jpg
│ └── val
│ ├── 8ae4af51.jpg
│ └── images(13).jpg
└── labels
├── train
│ ├── 0dcddf72.txt
│ └── images(3).txt
└── val
├── 8ae4af51.txt
└── images(13).txt
提示
如果使用label_convert工具时候,出现UTF-8编码错误说明,txt文件编码格式不对。需要指明编码方式。
对于txt文件编码格式可以用如下代码检测。
import chardet
with open(r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1\labels\000000.txt', 'rb') as f:
result = chardet.detect(f.read(100)) # 读取一定量的数据进行编码检测
print(result['encoding']) # 打印检测到的编码
with open(r'D:\DeepLearning\VOC2Yolo\S2TLD\normal_1\labels\000000.txt', 'r', encoding='utf-8') as file:
content = file.read()
print(content)
检测出来的结果是ASCII,则证明是UTF-8 ?