目前更新到V0.2版本,只支持win平台。
水平矩形框VOC -- > YOLO (选源文件夹+目标文件夹)
旋转矩形框roLabelimg --> YOLO-rotation[0,180) (选源文件夹+目标文件夹)
水平矩形框YOLO -- > VOC (选源文件夹+目标文件夹+图片jpg文件夹+标签字典txt)
如果觉得好用,请打个小星星♥♥
import os
import tkinter as tk
from tkinter import filedialog
import xml.etree.ElementTree as ET
class App(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.source_path = ""
self.target_path = ""
self.file_list = []
self.classes = {} # 字典classes,key=,value=
self.sorted_classes = {}
self.sorted_classes_dict = {}
self.master.title("VOC to YOLO Converter")
self.master.geometry("800x400")
self.master.resizable(False, False)
self.pack()
self.create_widgets()
def create_widgets(self):
# Source folder path
self.btn_select_source = tk.Button(self, text="Select Source Folder", command=self.select_source)
self.btn_select_source.pack()
self.lbl_source_path = tk.Label(self)
self.lbl_source_path.pack()
# Target folder path
self.btn_select_target = tk.Button(self, text="Select Target Folder", command=self.select_target)
self.btn_select_target.pack()
self.lbl_target_path = tk.Label(self)
self.lbl_target_path.pack()
# Class names and indices
self.lbl_classes = tk.Label(self,justify="left")
self.lbl_classes.pack()
# Convert progress
self.progress = tk.StringVar()
self.progress_label = tk.Label(self, textvariable=self.progress)
self.progress_label.pack()
# Convert button
self.btn_convert = tk.Button(self, text="GO", command=self.convert)
self.btn_convert.pack()
def select_source(self):
self.source_path = filedialog.askdirectory()
self.lbl_source_path.configure(text="Source folder: " + self.source_path)
def select_target(self):
self.target_path = filedialog.askdirectory()
self.lbl_target_path.configure(text="Target folder: " + self.target_path)
def convert(self):
if self.source_path == "":
print("Please select source folder first!")
return
if self.target_path == "":
print("Please select target folder first!")
return
self.file_list = []
for filename in os.listdir(self.source_path):
if filename.endswith(".xml"):
self.file_list.append(filename)
total_files = len(self.file_list)
count = 0
for filename in self.file_list:
xml_file = os.path.join(self.source_path, filename)
# Parse XML file
tree = ET.parse(xml_file)
root = tree.getroot()
# 获取图像的宽度和高度
width = int(root.find(".//width").text)
height = int(root.find(".//height").text)
for obj in root.findall("object"):
class_name = obj.find("name").text # 解析类名class_name
if class_name not in self.classes:
self.classes[class_name] = len(self.classes)
self.sorted_keys = sorted(self.classes.keys())
for index, key in enumerate(self.sorted_keys):
self.classes[key] = index
for filename in self.file_list:
# Create YOLO format txt file
txt_filename = os.path.splitext(filename)[0] + ".txt"
txt_file = os.path.join(self.target_path, txt_filename)
with open(txt_file, "w") as f:
for obj in root.findall("object"):
class_name = obj.find("name").text
class_index = self.classes[class_name]
bbox = obj.find("bndbox")
xmin = float(bbox.find("xmin").text)
ymin = float(bbox.find("ymin").text)
xmax = float(bbox.find("xmax").text)
ymax = float(bbox.find("ymax").text)
# 计算YOLO格式的坐标和中心点
x = (xmin + xmax) / 2.0/width
y = (ymin + ymax) / 2.0/height
w = xmax - xmin/width
h = ymax - ymin/height
# 写入YOLO格式的行
f.write(f"{class_index} {x:.6f} {y:.6f} {w:.6f} {h:.6f}\n")
count += 1
self.progress.set(f"Progress: {count}/{total_files}")
self.lbl_classes.configure(text=self.get_classes_text())
def get_classes_text(self):
text = "Class names and indices:\n\n"
for class_name, index in self.classes.items():
text += f"{index}:{class_name}\n"
return text
root = tk.Tk()
app = App(master=root)
app.mainloop()
bug:显示没有按0开始的排序。
增加roLabelimg2YOLOrotation
增加roLabelimg2DOTA
YOLOrotation2DOAT
DOAT2YOLOrotation