分享一个json格式转yolo格式的脚本

大家在使用labelme,或者labelimg标注完数据之后呢,想要训练yolo系列目标检测模型时会需要将标注文件的json格式转换为yolo所需要的txt格式。

下面废话不多说,直接安排对应的脚本。

需要修改的只有三个地方json_path,image_path,output_folder,分别代表json文件的存储路径,图片文件夹的路径,txt格式的结果路径。

转换完成之后根据自己的比例划分train和val,在自己建一个yaml即可训练自己的yolo模型

import cv2
import os
import json
import glob
import numpy as np

def convert_json_label_to_yolov_seg_label():
    json_path = r"D:\Desktop\label"  # JSON文件路径
    image_path = r"D:\Desktop\rock"  # 图片文件路径
    json_files = glob.glob(json_path + "/*.json")
    print("找到的JSON文件:", json_files)

    # 指定输出文件夹
    output_folder = r"D:\Desktop\txt"  # txt存放路径
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    for json_file in json_files:
        print(f"\n处理文件: {json_file}")
        with open(json_file, 'r') as f:
            json_info = json.load(f)

        # 获取图片文件名(去除相对路径)
        img_name = os.path.basename(json_info["imagePath"])
        img_path = os.path.join(image_path, img_name)
        print(f"图片路径: {img_path}")

        # 检查图片是否存在
        if not os.path.exists(img_path):
            print(f"警告: 图片不存在 {img_path}")
            continue

        # 读取图片
        img = cv2.imread(img_path)
        if img is None:
            print(f"警告: 无法读取图片 {img_path}")
            continue

        height, width, _ = img.shape
        np_w_h = np.array([[width, height]], np.int32)

        # 生成输出文件名
        txt_file = os.path.join(output_folder, os.path.splitext(img_name)[0] + ".txt")
        print(f"保存标注到: {txt_file}")

        # 写入标注信息
        with open(txt_file, "w") as f:
            for shape in json_info["shapes"]:
                # 获取每个形状的点
                points = shape["points"]
                # 转换为numpy数组
                np_points = np.array(points, np.float32)
                # 归一化坐标
                norm_points = np_points / np_w_h
                # 转换为列表
                norm_points_list = norm_points.tolist()
                # 生成标注内容
                txt_content = "0 " + " ".join(
                    [" ".join([str(cell[0]), str(cell[1])]) for cell in norm_points_list]
                ) + "\n"
                f.write(txt_content)

if __name__ == "__main__":
    convert_json_label_to_yolov_seg_label()

<think>好的,我现在需要帮助用户解决如何将JSON格式的数据换为YOLO格式的问题。用户提到了参考的两个引用,一个是关于JSONYOLO的步骤和代码示例,另一个是GTSDB数据集换的例子。首先,我需要理解用户的需求,他们可能是在处理目标检测任务,需要将标注数据从JSON格式换为YOLO所需的txt格式。 首先,我应该回顾YOLO格式的要求。YOLO需要的每个图像对应一个txt文件,每行包含类别ID、中心点坐标(x_center, y_center)以及宽度和高度,这些都需要归一化到0-1之间。而JSON格式的结构可能因数据集而异,但通常包含图像尺寸和每个目标的边界框坐标,可能是左上角和右下角的坐标,或者其他形式,比如绝对坐标或相对坐标。 接下来,用户提供的参考引用1和2中,引用1提到了步骤指南和代码实现,包括类别映射、边界框换函数、JSON解码和主程序。引用2则具体处理GTSDB数据集,其中标签是左上角和右下角坐标,需要换为YOLO的中心点和宽高,并进行归一化。因此,我需要结合这两个引用来构建通用的换方法。 用户需要的是编写代码的示例或实现方式。我需要先整理换的步骤,然后提供代码示例,并确保代码正确处理不同的JSON结构。可能需要注意的问题包括:如何从JSON中提取图像尺寸,如何解析边界框坐标,处理不同坐标格式(比如绝对值或相对值),以及归一化的正确计算。 首先,步骤指南应该包括: 1. 读取JSON文件,解析出图像的基本信息,如宽度和高度。 2. 遍历每个目标对象,获取其类别名称,并将其映射到对应的类别ID。 3. 提取边界框的坐标,可能是不同的格式(例如左上右下或xmin, ymin, width, height)。 4. 将边界框换为YOLO格式的中心点坐标和宽高,并进行归一化。 5. 将换后的数据写入对应的txt文件,每个图像一个文件。 在代码实现部分,需要包括以下几个函数: - 类别名称到ID的映射函数,可能需要一个字典来存储类别和对应的ID。 - 边界框换函数,将原始坐标换为YOLO格式,例如从左上右下为中心点并归一化。 - JSON解码函数,用于读取和解析JSON文件,提取必要的信息。 - 主程序,处理整个流程,包括读取输入、处理每个图像的数据、保存结果。 需要注意的潜在问题包括:不同的JSON结构可能需要不同的解析方式,例如有些数据集可能将边界框存储为数组,有些可能使用不同的键名。因此,代码需要根据具体的JSON结构进行调整,用户可能需要根据实际情况修改键名或结构路径。 另外,归一化的计算必须正确,即中心点的x坐标是(x_min + x_max)/ 2 / 图像宽度,宽度是(x_max - x_min)/ 图像宽度,同理高度也是如此。如果原始坐标已经是归一化的,则不需要再次归一化,但这种情况较少见,通常需要换绝对坐标到归一化。 在示例代码中,可以假设JSON结构中的每个对象包含类别名称、边界框坐标(比如x1, y1, x2, y2),以及图像的尺寸。然后,代码会遍历每个对象,进行换,并写入对应的txt文件。 同时,需要提醒用户注意图像路径和保存路径的正确设置,确保生成的txt文件与图像文件对应,并放在正确的目录下,以便YOLO训练时能够正确读取。 最后,生成的相关问题应该围绕数据换的其他方面,例如处理不同数据集的结构差异、处理归一化错误、批量换的方法,以及与其他格式换(如COCO到YOLO),这些都能帮助用户进一步解决可能遇到的问题。</think>### JSONYOLO格式代码实现 #### 一、核心步骤 1. **提取图像尺寸**:从JSON中读取图像的宽度$w$和高度$h$ 2. **类别映射**:将类别名称映射为YOLO格式要求的数字ID(如"car"→0) 3. **坐标换**:将原始边框坐标(如左上角xy+右下角xy)换为归一化后的中心点坐标和宽高 $$x_{\text{center}} = \frac{x_{\text{min}} + x_{\text{max}}}{2w}, \quad y_{\text{center}} = \frac{y_{\text{min}} + y_{\text{max}}}{2h}$$ $$width = \frac{x_{\text{max}} - x_{\text{min}}}{w}, \quad height = \frac{y_{\text{max}} - y_{\text{min}}}{h}$$ 4. **生成TXT文件**:为每个图像创建单独标注文件,命名与图像文件保持一致(如image.jpg→image.txt) #### 二、Python代码示例 ```python import json import os def json_to_yolo(json_path, output_dir): # 创建类别映射字典(根据实际类别修改) class_map = {"cat":0, "dog":1, "person":2} # 读取JSON文件 with open(json_path) as f: data = json.load(f) # 遍历所有图像数据 for image in data["images"]: img_id = image["id"] img_name = image["file_name"].split('.')[0] img_w = image["width"] img_h = image["height"] # 筛选该图像对应的标注 annotations = [ann for ann in data["annotations"] if ann["image_id"] == img_id] # 生成YOLO格式内容 yolo_lines = [] for ann in annotations: # 获取类别ID class_name = ann["category_name"] # JSON中类别字段名可能不同 class_id = class_map[class_name] # 换坐标(假设原始格式为xmin,ymin,xmax,ymax) x_min, y_min, x_max, y_max = ann["bbox"] x_center = (x_min + x_max) / (2 * img_w) y_center = (y_min + y_max) / (2 * img_h) width = (x_max - x_min) / img_w height = (y_max - y_min) / img_h # 保留6位小数 yolo_line = f"{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}" yolo_lines.append(yolo_line) # 写入TXT文件 output_path = os.path.join(output_dir, f"{img_name}.txt") with open(output_path, 'w') as f: f.write('\n'.join(yolo_lines)) # 使用示例 json_to_yolo("annotations.json", "yolo_labels/") ``` #### 三、关键说明 1. **坐标归一化**:必须除以图像宽高实现坐标归一化,否则会导致训练错误[^2] 2. **格式验证**:换后应检查数值范围是否在[0,1]之间 3. **特殊处理**:若JSON使用其他坐标格式(如中心点坐标),需调整换公式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值