深度学习中不同的模型训练所需要的数据集格式可能不同,这时可能就需要将数据集格式转为该模型要求的格式。
yolo2voc
import xml.dom.minidom
import glob
from PIL import Image
from math import ceil
import shutil
import os
yolo_file = r'folder' # yolo格式下的存放txt标注文件的文件夹
turn_xml_file = r'folder' # 转换后储存xml的文件夹地址
img_file = r'folder' # 存放图片的文件夹
#class id
labels = ['label']
src_img_dir = img_file
src_txt_dir = yolo_file
src_xml_dir = turn_xml_file # 转换后储存xml的文件夹地址
img_Lists = glob.glob(src_img_dir + '/*.jpg')
img_basenames = []
for item in img_Lists:
img_basenames.append(os.path.basename(item)) # os.path.basename返回path最后的文件名
img_names = []
for item in img_basenames:
temp1, temp2 = os.path.splitext(item) # os.path.splitext(“文件路径”) 分离文件名与扩展名
img_names.append(temp1)
total_num = len(img_names) # 统计当前总共要转换的图片标注数量
count = 0 # 技术变量
for img in img_names: # 这里的img是不加后缀的图片名称,如:'GF3_SAY_FSI_002732_E122.3_N29.9_20170215_L1A_HH_L10002188179__1__4320___10368'
count += 1
if count % 1000 == 0:
print("当前转换进度{}/{}".format(count, total_num))
im = Image.open((src_img_dir + '/' + img + '.jpg'))
width, height = im.size
# 打开yolo格式下的txt文件
gt = open(src_txt_dir + '/' + img + '.txt').read().splitlines()
if gt:
# 将主干部分写入xml文件中
xml_file = open((src_xml_dir + '/' + img + '.xml'), 'w')
xml_file.write('<annotation>\n')
xml_file.write(' <folder>VOC2007</folder>\n')
xml_file.write(' <filename>' + str(img) + '.jpg' + '</filename>\n')
xml_file.write(' <size>\n')
xml_file.write(' <width>' + str(width) + '</width>\n')
xml_file.write(' <height>' + str(height) + '</height>\n')
xml_file.write(' <depth>3</depth>\n')
xml_file.write(' </size>\n')
# write the region of image on xml file
for img_each_label in gt:
spt = img_each_label.split(' ') # 这里如果txt里面是以逗号‘,’隔开的,那么就改为spt = img_each_label.split(',')。
xml_file.write(' <object>\n')
xml_file.write(' <name>' + str(labels[int(spt[0])]) + '</name>\n')
xml_file.write(' <pose>Unspecified</pose>\n')
xml_file.write(' <truncated>0</truncated>\n')
xml_file.write(' <difficult>0</difficult>\n')
xml_file.write(' <bndbox>\n')
center_x = round(float(spt[1].strip()) * width)
center_y = round(float(spt[2].strip()) * height)
bbox_width = round(float(spt[3].strip()) * width)
bbox_height = round(float(spt[4].strip()) * height)
xmin = str(int(center_x - bbox_width / 2))
ymin = str(int(center_y - bbox_height / 2))
xmax = str(int(center_x + bbox_width / 2))
ymax = str(int(center_y + bbox_height / 2))
xml_file.write(' <xmin>' + xmin + '</xmin>\n')
xml_file.write(' <ymin>' + ymin + '</ymin>\n')
xml_file.write(' <xmax>' + xmax + '</xmax>\n')
xml_file.write(' <ymax>' + ymax + '</ymax>\n')
xml_file.write(' </bndbox>\n')
xml_file.write(' </object>\n')
xml_file.write('</annotation>')
else:
# 将主干部分写入xml文件中
xml_file = open((src_xml_dir + '/' + img + '.xml'), 'w')
xml_file.write('<annotation>\n')
xml_file.write(' <folder>VOC2007</folder>\n')
xml_file.write(' <filename>' + str(img) + '.jpg' + '</filename>\n')
xml_file.write(' <size>\n')
xml_file.write(' <width>' + str(width) + '</width>\n')
xml_file.write(' <height>' + str(height) + '</height>\n')
xml_file.write(' <depth>3</depth>\n')
xml_file.write(' </size>\n')
xml_file.write('</annotation>')
# 将转换后的xml文件按train 和test 归类到train.txt和test.txt中
path = r'folder'
xml_Lists = glob.glob(src_xml_dir + '/*.xml')
xml_basenames = []
for item in xml_Lists:
xml_basenames.append(os.path.basename(item))
xml_names = [] # 这里是将xml文件去掉.xml后缀储存到的列表中
for item in xml_basenames:
temp1, temp2 = os.path.splitext(item) # os.path.splitext(“文件路径”) 分离文件名与扩展名
xml_names.append(temp1)
txt_file = open((path + '/val.txt'), 'w')
for item in xml_names:
txt_file.write(str(item) + '\n')
yolo2coco
import os
import json
import cv2
import random
import time
from PIL import Image
coco_format_save_path = r'folder' # 要生成的标准coco格式标签所在文件夹
yolo_format_classes_path = r"classes.txt" # 类别文件,一行一个类
yolo_format_annotation_path = r'folder' # yolo格式标签所在文件夹
img_pathDir = r'folder' # 图片所在文件夹
with open(yolo_format_classes_path, 'r') as fr: # 打开并读取类别文件
lines1 = fr.readlines()
# print(lines1)
categories = [] # 存储类别的列表
for j, label in enumerate(lines1):
label = label.strip()
categories.append({'id': j + 1, 'name': label, 'supercategory': 'None'}) # 将类别信息添加到categories中
# print(categories)
write_json_context = dict() # 写入.json文件的大字典
write_json_context['info'] = {'description': '', 'url': '', 'version': '', 'year': 2023, 'contributor': 'JeJe',
'date_created': '2023-05-18'}
write_json_context['licenses'] = [{'id': 1, 'name': None, 'url': None}]
write_json_context['categories'] = categories
write_json_context['images'] = []
write_json_context['annotations'] = []
# 接下来的代码主要添加'images'和'annotations'的key值
imageFileList = os.listdir(img_pathDir) # 遍历该文件夹下的所有文件,并将所有文件名添加到列表中
for i, imageFile in enumerate(imageFileList):
imagePath = os.path.join(img_pathDir, imageFile) # 获取图片的绝对路径
image = Image.open(imagePath) # 读取图片,然后获取图片的宽和高
W, H = image.size
img_context = {} # 使用一个字典存储该图片信息
# img_name=os.path.basename(imagePath) #返回path最后的文件名。如果path以/或\结尾,那么就会返回空值
img_context['file_name'] = imageFile
img_context['height'] = H
img_context['width'] = W
img_context['date_captured'] = '2022-07-8'
img_context['id'] = i # 该图片的id
img_context['license'] = 1
img_context['color_url'] = ''
img_context['flickr_url'] = ''
write_json_context['images'].append(img_context) # 将该图片信息添加到'image'列表中
txtFile = imageFile.replace('.jpg', '.txt') # 获取该图片获取的txt文件
with open(os.path.join(yolo_format_annotation_path, txtFile), 'r') as fr:
lines = fr.readlines() # 读取txt文件的每一行数据,lines2是一个列表,包含了一个图片的所有标注信息
for j, line in enumerate(lines):
bbox_dict = {} # 将每一个bounding box信息存储在该字典中
# line = line.strip().split()
# print(line.strip().split(' '))
class_id, x, y, w, h = line.strip().split(' ') # 获取每一个标注框的详细信息
class_id, x, y, w, h = int(class_id), float(x), float(y), float(w), float(h) # 将字符串类型转为可计算的int和float类型
xmin = (x - w / 2) * W # 坐标转换
ymin = (y - h / 2) * H
xmax = (x + w / 2) * W
ymax = (y + h / 2) * H
w = w * W
h = h * H
bbox_dict['id'] = i * 10000 + j # bounding box的坐标信息
bbox_dict['image_id'] = i
bbox_dict['category_id'] = class_id + 1 # 注意目标类别要加一
bbox_dict['iscrowd'] = 0
height, width = abs(ymax - ymin), abs(xmax - xmin)
bbox_dict['area'] = height * width
bbox_dict['bbox'] = [xmin, ymin, w, h]
bbox_dict['segmentation'] = [[xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax]]
write_json_context['annotations'].append(bbox_dict) # 将每一个由字典存储的bounding box信息添加到'annotations'列表中
name = os.path.join(coco_format_save_path, "train" + '.json') # 生成json文件的名字
with open(name, 'w') as fw: # 将字典信息写入.json文件中
json.dump(write_json_context, fw, indent=2)
voc2yolo
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
# classes = ['hard_hat', 'other', 'regular', 'long_hair', 'braid', 'bald', 'beard']
def convert(size, box):
# size=(width, height) b=(xmin, xmax, ymin, ymax)
# x_center = (xmax+xmin)/2 y_center = (ymax+ymin)/2
# x = x_center / width y = y_center / height
# w = (xmax-xmin) / width h = (ymax-ymin) / height
x_center = (box[0] + box[1]) / 2.0
y_center = (box[2] + box[3]) / 2.0
x = x_center / size[0]
y = y_center / size[1]
w = (box[1] - box[0]) / size[0]
h = (box[3] - box[2]) / size[1]
# print(x, y, w, h)
return (x, y, w, h)
def convert_annotation(xml_files_path, save_txt_files_path, classes):
xml_files = os.listdir(xml_files_path)
print(xml_files)
for xml_name in xml_files:
print(xml_name)
xml_file = os.path.join(xml_files_path, xml_name)
out_txt_path = os.path.join(save_txt_files_path, xml_name.split('.')[0] + '.txt')
out_txt_f = open(out_txt_path, 'w')
tree = ET.parse(xml_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))
# b=(xmin, xmax, ymin, ymax)
print(w, h, b)
bb = convert((w, h), b)
out_txt_f.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
if __name__ == "__main__":
# 测试程序
# classes = ['hard_hat', 'other', 'regular', 'long_hair', 'braid', 'bald', 'beard']
# xml_files = r'D:\ZF\1_ZF_proj\3_脚本程序\2_voc格式转yolo格式\voc_labels'
# save_txt_files = r'D:\ZF\1_ZF_proj\3_脚本程序\2_voc格式转yolo格式\yolo_labels'
# convert_annotation(xml_files, save_txt_files, classes)
# ====================================================================================================
# 把帽子头发胡子的voc的xml标签文件转化为yolo的txt标签文件
# 1、帽子头发胡子的类别
classes1 = ['class']
# 2、voc格式的xml标签文件路径
xml_files1 = r'xml'
# 3、转化为yolo格式的txt标签文件存储路径
save_txt_files1 = r'label'
convert_annotation(xml_files1, save_txt_files1, classes1)
voc2coco
import sys
import os
import json
import xml.etree.ElementTree as ET
START_BOUNDING_BOX_ID = 0
PRE_DEFINE_CATEGORIES = {"LicensePlate": 1} # 修改的地方,修改为自己的类别
# If necessary, pre-define category and its id
# PRE_DEFINE_CATEGORIES = {"aeroplane": 1, "bicycle": 2, "bird": 3, "boat": 4,
# "bottle":5, "bus": 6, "car": 7, "cat": 8, "chair": 9,
# "cow": 10, "diningtable": 11, "dog": 12, "horse": 13,
# "motorbike": 14, "person": 15, "pottedplant": 16,
# "sheep": 17, "sofa": 18, "train": 19, "tvmonitor": 20}
def get(root, name):
vars = root.findall(name)
return vars
def get_and_check(root, name, length):
vars = root.findall(name)
if len(vars) == 0:
raise NotImplementedError('Can not find %s in %s.' % (name, root.tag))
if length > 0 and len(vars) != length:
raise NotImplementedError('The size of %s is supposed to be %d, but is %d.' % (name, length, len(vars)))
if length == 1:
vars = vars[0]
return vars
def get_filename_as_int(filename):
try:
filename = os.path.splitext(filename)[0]
return filename
except:
raise NotImplementedError('Filename %s is supposed to be an integer.' % (filename))
# xml_list为xml文件存放的txt文件名 xml_dir为真实xml的存放路径 json_file为存放的json路径
def convert(xml_list, xml_dir, json_file):
list_fp = open(xml_list, 'r')
json_dict = {"images": [], "type": "instances", "annotations": [],
"categories": []}
categories = PRE_DEFINE_CATEGORIES
bnd_id = START_BOUNDING_BOX_ID
for line in list_fp:
line = line.strip()
line = line + ".xml"
print("Processing %s" % (line))
xml_f = os.path.join(xml_dir, line)
tree = ET.parse(xml_f)
root = tree.getroot()
path = get(root, 'path')
if len(path) == 1:
filename = os.path.basename(path[0].text)
elif len(path) == 0:
filename = get_and_check(root, 'filename', 1).text
else:
raise NotImplementedError('%d paths found in %s' % (len(path), line))
## The filename must be a number
image_id = get_filename_as_int(filename)
size = get_and_check(root, 'size', 1)
width = int(get_and_check(size, 'width', 1).text)
height = int(get_and_check(size, 'height', 1).text)
image = {'file_name': filename, 'height': height, 'width': width,
'id': image_id}
json_dict['images'].append(image)
## Cruuently we do not support segmentation
# segmented = get_and_check(root, 'segmented', 1).text
# assert segmented == '0'
for obj in get(root, 'object'):
category = get_and_check(obj, 'name', 1).text
if category not in categories:
new_id = len(categories)
categories[category] = new_id
category_id = categories[category]
bndbox = get_and_check(obj, 'bndbox', 1)
xmin = int(get_and_check(bndbox, 'xmin', 1).text) - 1
ymin = int(get_and_check(bndbox, 'ymin', 1).text) - 1
xmax = int(get_and_check(bndbox, 'xmax', 1).text)
ymax = int(get_and_check(bndbox, 'ymax', 1).text)
assert (xmax > xmin)
assert (ymax > ymin)
o_width = abs(xmax - xmin)
o_height = abs(ymax - ymin)
ann = {'area': o_width * o_height, 'iscrowd': 0, 'image_id':
image_id, 'bbox': [xmin, ymin, o_width, o_height],
'category_id': category_id, 'id': bnd_id, 'ignore': 0,
'segmentation': []}
json_dict['annotations'].append(ann)
bnd_id = bnd_id + 1
for cate, cid in categories.items():
cat = {'supercategory': 'none', 'id': cid, 'name': cate}
json_dict['categories'].append(cat)
json_fp = open(json_file, 'w')
json_str = json.dumps(json_dict)
json_fp.write(json_str)
json_fp.close()
list_fp.close()
if __name__ == '__main__':
# xml_list为xml文件存放的txt文件名 xml_dir为真实xml的存放路径 json_file为存放的json路径
# xml_list = './data/VOCdevkit/ImageSets/Main/test.txt'
# xml_list = './data/VOCdevkit/ImageSets/Main/train.txt'
xml_list = './VOC_plate/VOC2007/ImageSets/Main/test.txt'
xml_dir = './VOC_plate/VOC2007/Annotations'
# json_dir = './data/COCO/annotations/test.json' # 注意!!!这里test.json先要自己创建,不然
# json_dir = './data/COCO/annotations/train.json' # 注意!!!这里test.json先要自己创建,不然
json_dir = 'RT-DETR/rtdetr_pytorch/COCO_plate/annotations/test.json' # 注意!!!这里test.json先要自己创建,不然 #程序回报权限不足
convert(xml_list, xml_dir, json_dir)
注意,实际使用时要根据自己的实际情况修改代码中的路径和参数。