yolo标签混乱转换工具

xml转txt格式

import glob
import os
import xml.etree.ElementTree as ET
classes={0: 'hat',1: 'masks',2: 'aprons',3: 'no_hat',4: 'no_mask',5: 'no_aprons',6: 'people',7:"mouse",8:'overflow',9:'garbage',10:'garbage_bin',11:'smoke',12:"phone",13:"chefclothes",14:"nochefclothes"}
classes = list(classes.values())

def xml_to_yolo(xml_path,out_path):
    global classes
    # 解析XML文件
    tree = ET.parse(xml_path)
    root = tree.getroot()

    # 获取图像尺寸
    size = root.find('size')
    width = int(size.find('width').text)
    height = int(size.find('height').text)

    # 初始化输出文件内容
    output_lines = []

    # 遍历所有对象
    for obj in root.findall('object'):
        # 获取类别名
        cls_name = obj.find('name').text
        if cls_name == 'without_mask':
            cls_name = 'no_mask'
        if cls_name == 'with_correct_mask':
            cls_name = 'masks'
        # 确保类别存在于类别列表中
        if cls_name not in classes:
            classes.append(cls_name)
        if cls_name in classes:
            cls_id = classes.index(cls_name)

            # 计算YOLO格式的坐标和尺寸
            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)
            x_center = (xmin + xmax) / 2 / width
            y_center = (ymin + ymax) / 2 / height
            width_bbox = (xmax - xmin) / width
            height_bbox = (ymax - ymin) / height

            # 添加到输出行
            output_line = f"{cls_id} {x_center:.6f} {y_center:.6f} {width_bbox:.6f} {height_bbox:.6f}"
            output_lines.append(output_line)

    # 写入到TXT文件
    with open(out_path+xml_path[:-4].split('\\')[-1]+".txt", 'w') as f:
        f.write('\n'.join(output_lines))


# 示例用法
  # 类别列表
directory_path = 'train/Annotations'
out_path = 'train/labels_origin\\'


# 使用glob模块匹配所有.xml文件
xml_files = glob.glob(os.path.join(directory_path, '*.xml'))

# 打印所有找到的.xml文件路径
for file in xml_files:
    print(file)
    print(out_path + file[:-4].split('\\')[-1] + ".txt")
    xml_to_yolo(file,out_path)
print(classes)
with open(out_path+'classes.txt', 'w') as f:
    f.write('\n'.join(classes))
# output_path = 'path_to_output_txt_file.txt'  # 输出TXT文件路径
#

yolo格式校验

import glob
import os


def validate_yolo_annotation(file_path):
    """
    验证一个TXT文件是否符合YOLO格式。

    :param file_path: TXT文件的路径。
    :return: 如果文件格式正确返回True,否则返回False以及错误信息。
    """
    with open(file_path, 'r') as file:
        lines = file.readlines()

    # 检查每行
    for line_number, line in enumerate(lines, start=1):
        parts = line.strip().split(" ")

        # 每行应该至少有5个部分(class_id, x_center, y_center, width, height)
        if len(parts) != 5:
            return False, f"Line {line}"

        try:
            class_id = int(parts[0])
            x_center = float(parts[1])
            y_center = float(parts[2])
            width = float(parts[3])
            height = float(parts[4])

            # 检查坐标和尺寸是否在合理范围内
            if not (0 <= x_center <= 1 and 0 <= y_center <= 1 and 0 < width <= 1 and 0 < height <= 1):
                return False, f"Line {line}"
        except ValueError:
            return False, f"Line {line}"

    # 如果所有行都通过了检查
    return True, ""


# 示例用法
directory_path = r'E:\zyx_project\new_shian\endtrain_img\labels'

# 使用glob模块匹配所有.xml文件
xml_files = glob.glob(os.path.join(directory_path, '*.txt'))

# 打印所有找到的.xml文件路径
for file in xml_files:
    #print(file)
    is_valid, message = validate_yolo_annotation(file)
    if is_valid:
        print(message,end='')
    else:
        print(file)
        print(f"Validation failed: {message}")

txt里面标签混乱,批量替换。

import os

def count_classes_in_yolo_labels(directory):
    class_counts = {}

    # 遍历指定目录下的所有 .txt 文件
    for filename in os.listdir(directory):
        if filename.endswith("classes.txt"):
            continue
        if filename.endswith(".txt"):
            filepath = os.path.join(directory, filename)

            # 打开文件并读取每一行
            with open(filepath, 'r') as file:
                for line in file:
                    parts = line.strip().split()
                    if len(parts) > 0:
                        class_id = parts[0]

                        # 如果类别ID不在字典中,则添加它并设置计数为1;否则增加计数
                        if class_id not in class_counts:
                            class_counts[class_id] = 1
                        else:
                            class_counts[class_id] += 1

    return class_counts
def replace_class_in_yolo_labels(directory, new_path,replace_class_dict):
    # 遍历指定目录下的所有 .txt 文件
    for filename in os.listdir(directory):
        if filename.endswith("classes.txt"):
            continue
        if filename.endswith(".txt"):
            filepath = os.path.join(directory, filename)

            # 读取文件内容
            with open(filepath, 'r') as file:
                lines = file.readlines()

            # 处理每一行,替换类别序号
            modified_lines = []
            for line in lines:
                parts = line.strip().split()
                if len(parts) > 0:
                    class_id = int(parts[0])
                    if class_id in replace_class_dict:
                        parts[0] = str(replace_class_dict[class_id])
                modified_lines.append(' '.join(parts) + '\n')

            # 写回修改后的内容
            with open(new_path+filepath.split("\\")[-1], 'w') as file:
                file.writelines(modified_lines)
if __name__ == '__main__':
    type_dict = {0: 'hat', 1: 'mask', 2: 'aprons', 3: 'no_hat', 4: 'no_mask', 5: 'no_aprons', 6: 'people', 7: "mouse",
                 8: 'overflow', 9: 'garbage', 10: 'garbage_bin', 11: 'smoke', 12: "phone", 13: "chefclothes",
                 14: "nochefclothes"}
    directory_path = 'new_image/labels_origin'  # 替换为你的文件路径
    new_path="new_image/labels/"
    with open(directory_path+'/classes.txt', 'r') as f:
        lines = f.readlines()
    classes = [line.strip() for line in lines]
    classes_dict = {i: classes[i] for i in range(len(classes))}
    print(classes)
    print("classes_dict:", classes_dict)
    for i in type_dict.values():
        print(i)
    for key in list(classes_dict.keys()):
        try:
            classes_dict[key]=int(classes_dict[key])
        except:
            if classes_dict[key] in type_dict.values():
                print(next((key for key, value in type_dict.items() if value == 1), None))
                classes_dict[key]=list(type_dict.values()).index(classes_dict[key])
            else:
                print("classes_dict_no_have:", classes_dict[key])
                del classes_dict[key]
    print("classes_dict:", classes_dict)

    # 使用函数

    counts = count_classes_in_yolo_labels(directory_path)

    # 输出结果
    for class_id, count in counts.items():
        print(f"Class {class_id}: {count} times")


    replace_class_in_yolo_labels(directory_path,new_path,classes_dict)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值