[目标检测]labelme标注数据转yoloV8需要的.txt格式

1、首先需要知道yoloV8目标检测的标签格式:

yolov8标签数据格式说明

After using a tool like Roboflow Annotate to label your images, export your labels to YOLO format, with one *.txt file per image (if no objects in image, no *.txt file is required). The *.txt file specifications are:

One row per object

Each row is class x_center y_center width height format.

Box coordinates must be in normalized xywh format (from 0 - 1). If your boxes are in pixels, divide x_center and width by image width, and y_center and height by image height.

Class numbers are zero-indexed (start from 0).

主要包括五个数字 id 、x 、y 、w,、h,分别代表标签类别、目标对象在图像中的中心位置(x,y)、目标对象的宽和高。

注意的是中心位置坐标、以及目标对象的宽和高都需要进行归一化到0-1之间。如下:

0 0.060000 0.460000 0.12 0.65

1 0.450000 0.480000 0.38 0.68

0 0.880000 0.470000 0.24 0.63

2、示例有两种标签类型,转化为.txt的代码如下:

import json
import os
import shutil
import random

# Convert label to idx
with open("labels.txt", "r") as f:
    classes = [c.strip() for c in f.readlines()]
    idx_dict = {c: str(i) for i, c in enumerate(classes)}

def convert_labelmes_to_yolo(labelme_folder, output_folder):
    label_folder = os.path.join(output_folder, "labels")         # label_folder = image_folder/labels
    os.makedirs(label_folder, exist_ok=True)
    image_folder = os.path.join(output_folder, "images")         # image_folder = image_folder/images
    os.makedirs(image_folder, exist_ok=True)

    for root, dirs, files in os.walk(labelme_folder):          # root-文件夹所在路径  dir-路经下的文件夹   file-里面的文件
        for file in files:
            file_path = os.path.join(root, file)
            if os.path.splitext(file)[-1] != ".json":      # 分割文件名和扩展名
                shutil.copy(file_path, image_folder)
                print(f"Copied {file_path} to {image_folder}")
            else:
                # 读取json文件
                with open(file_path, 'r') as f:
                    labelme_data = json.load(f)

                image_filename = labelme_data["imagePath"]
                image_width = labelme_data["imageWidth"]
                image_height = labelme_data["imageHeight"]

                txt_filename = os.path.splitext(image_filename)[0] + ".txt"
                txt_path = os.path.join(label_folder, txt_filename)

                with open(txt_path, 'w') as f:
                    for shape in labelme_data["shapes"]:
                        label = shape["label"]
                        points = shape["points"]
                        x_min, y_min = points[0]
                        x_max, y_max = points[1]

                        center_x = round(((x_min + x_max) / 2) / image_width , 2)
                        center_y = round(((y_min + y_max) / 2) / image_height ,2)
                        width = round(abs(x_min - x_max) / image_width, 2)
                        height = round(abs(y_min - y_max) / image_height, 2)

                        class_id = label_dict[label]
                        f.write(f"{class_id}  {center_x:.6f} {center_y:.6f} {width} {height}\n")

                print(f"Converted {file} to {txt_path}")

    print("转换成功")

def split_data(output_folder, dataset_folder):
    random.seed(0)
    split_rate = 0.2 #验证集占比
    origin_label_path = os.path.join(output_folder, "labels")
    origin_image_path = os.path.join(output_folder, "images")
    train_label_path = os.path.join(dataset_folder, "train", "labels")
    os.makedirs(train_label_path, exist_ok=True)
    train_image_path = os.path.join(dataset_folder, "train", "images")
    os.makedirs(train_image_path, exist_ok=True)
    val_label_path = os.path.join(dataset_folder, "val", "labels")
    os.makedirs(val_label_path, exist_ok=True)
    val_image_path = os.path.join(dataset_folder, "val", "images")
    os.makedirs(val_image_path, exist_ok=True)

    images = os.listdir(origin_image_path)
    num = len(images)
    eval_index = random.sample(images,k=int(num*split_rate))
    for single_image in images:
        origin_single_image_path = os.path.join(origin_image_path, single_image)
        single_txt = os.path.splitext(single_image)[0] + ".txt"
        origin_single_txt_path = os.path.join(origin_label_path, single_txt)
        if single_image in eval_index:
            #single_json_path = os.path.join(val_label_path,single_json)
            shutil.copy(origin_single_image_path, val_image_path)
            shutil.copy(origin_single_txt_path, val_label_path)
        else:
            #single_json_path = os.path.join(train_label_path,single_json)
            shutil.copy(origin_single_image_path, train_image_path)
            shutil.copy(origin_single_txt_path, train_label_path)

    print("数据集划分完成")

    with open(os.path.join(dataset_folder,"data.yaml"),"w") as f:
        f.write(f"train: {dataset_folder}\n")
        f.write(f"val: {val_image_path}\n")
        f.write(f"test: {val_image_path}\n\n")
        f.write(f"nc: {len(classes)}\n")
        f.write(f"names: {classes}\n")

if __name__ == '__main__':
    label_dict = {"incp_tank": 0, "cp_tank": 1}
    labelme_folder = "./labelme_folder" #labelme生成的标注文件所在的文件夹
    output_folder = "./test" #存储yolo标注文件的文件夹
    dataset_folder = "./mydata" #存储划分好的数据集的文件夹
    convert_labelmes_to_yolo(labelme_folder, output_folder)#将labelme标注文件转换为yolo格式
    split_data(output_folder, dataset_folder)#划分训练集和验证级

注意:你需要新建一个label.txt文件,把涉及到的标签名字输入进去,会自动得到.yaml文件。当然也可以把这一步省略,后面我们直接copy已有的.yaml把训练、验证的路径加进去即可。

相关推荐
ZHOU_WUYI24 分钟前
4.metagpt中的软件公司智能体 (ProjectManager 角色)
人工智能·metagpt
靴子学长1 小时前
基于字节大模型的论文翻译(含免费源码)
人工智能·深度学习·nlp
AI_NEW_COME2 小时前
知识库管理系统可扩展性深度测评
人工智能
海棠AI实验室2 小时前
AI的进阶之路:从机器学习到深度学习的演变(一)
人工智能·深度学习·机器学习
hunteritself2 小时前
AI Weekly『12月16-22日』:OpenAI公布o3,谷歌发布首个推理模型,GitHub Copilot免费版上线!
人工智能·gpt·chatgpt·github·openai·copilot
IT古董3 小时前
【机器学习】机器学习的基本分类-强化学习-策略梯度(Policy Gradient,PG)
人工智能·机器学习·分类
centurysee3 小时前
【最佳实践】Anthropic:Agentic系统实践案例
人工智能
mahuifa3 小时前
混合开发环境---使用编程AI辅助开发Qt
人工智能·vscode·qt·qtcreator·编程ai
四口鲸鱼爱吃盐3 小时前
Pytorch | 从零构建GoogleNet对CIFAR10进行分类
人工智能·pytorch·分类
蓝天星空3 小时前
Python调用open ai接口
人工智能·python