[目标检测]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把训练、验证的路径加进去即可。

相关推荐
Chef_Chen11 分钟前
从0开始学习机器学习--Day33--机器学习阶段总结
人工智能·学习·机器学习
搏博11 分钟前
神经网络问题之:梯度不稳定
人工智能·深度学习·神经网络
GL_Rain28 分钟前
【OpenCV】Could NOT find TIFF (missing: TIFF_LIBRARY TIFF_INCLUDE_DIR)
人工智能·opencv·计算机视觉
shansjqun33 分钟前
教学内容全覆盖:航拍杂草检测与分类
人工智能·分类·数据挖掘
狸克先生35 分钟前
如何用AI写小说(二):Gradio 超简单的网页前端交互
前端·人工智能·chatgpt·交互
baiduopenmap1 小时前
百度世界2024精选公开课:基于地图智能体的导航出行AI应用创新实践
前端·人工智能·百度地图
小任同学Alex1 小时前
浦语提示词工程实践(LangGPT版,服务器上部署internlm2-chat-1_8b,踩坑很多才完成的详细教程,)
人工智能·自然语言处理·大模型
新加坡内哥谈技术1 小时前
微软 Ignite 2024 大会
人工智能
江瀚视野1 小时前
Q3净利增长超预期,文心大模型调用量大增,百度未来如何分析?
人工智能
陪学2 小时前
百度遭初创企业指控抄袭,维权还是碰瓷?
人工智能·百度·面试·职场和发展·产品运营