格式转化工具.exe

本文介绍了一个用于将VOC格式的水平和旋转矩形框转换为YOLO格式的应用程序,包括从VOC到YOLO的转换,以及新增的roLabelimg到YOLO旋转和DOTA转换功能。用户可以选择源文件夹和目标文件夹,并自定义类名称和索引。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 目前更新到V0.2版本,只支持win平台。

LabelConverter

水平矩形框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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值