json类型文件转为yolo可识别的txt文件

本文介绍了如何使用Python将JSON文件转换为YOLO(You Only Look Once)算法可识别的TXT标注文件。适用于深度学习和计算机视觉任务,特别是基于PyTorch的项目。
# --把4点标注的json文件转化为(x_c,y_c,h,w,theta)的yolo txt 格式
import json
import os
import math
import random

my_class = ["bottle"]


def convert(image_id):

    in_file = 'annotations/%s.json' % image_id
    out_file = open('labels/%s.txt' % image_id, 'w')
    with open(in_file) as f_obj:
        label = json.load(f_obj)

    for bbox in label["shapes"]:
        vertices = bbox["points"]  # 顶点列表
        a, b, c, d = vertices

        x_c = (a[0]+b[0]+c[0]+d[0])/4
        y_c = (a[1] + b[1] + c[1] + d[1]) / 4
   
<think>我们已知用户提供的JSON文件格式(来自labelme标注工具)包含多边形(polygon)或折线(linestrip)标注,需要转换为YOLOv8所需的txt格式。YOLOv8的标注格式为每行一个对象,格式为:`class_id center_x center_y width height`(对于目标检测)或`class_id x1 y1 x2 y2 ...`(对于姿态估计,但这里用户给的是多边形标注,所以可能是分割任务?)。但是,根据引用[1][2][3]和用户提供的JSON结构,这里的目标检测任务使用边界框(bbox),而分割任务需要转换为多边形点集(但YOLOv8分割任务通常要求多边形点集归一化坐标)。 然而,观察用户提供的JSON示例,它使用的是`"shape_type": "linestrip"`(折线)并且有多个点。但YOLOv8的目标检测通常使用矩形框(bbox),而分割任务使用多边形点。 根据用户问题,他需要的是YOLOv8可用的文件。这里需要明确YOLOv8的任务类型: 1. 如果是目标检测(detect),则需要将多边形(或折线)转换为外接矩形框(bbox)。 2. 如果是分割(segment),则需要将多边形点(注意折线在标注中通常不是闭合的,但多边形是闭合的)归一化并写入txt,格式为:`class_id x1 y1 x2 y2 ...`(归一化后的多边形点坐标,用空格分隔)。 但用户没有明确任务类型。根据引用[1][3]的做法,它们都是转换为目标检测的bbox。而引用[2]是姿态估计(关键点),但用户提供的JSON不是关键点。 考虑到用户提供的JSON中`"shape_type"`是`"linestrip"`(折线),这通常用于线段标注,但也可以近似作为多边形(如果首尾相连的话)。然而,在用户示例中,点集没有首尾相连,所以可能标注的是曲线?但YOLOv8目标检测不支持折线,所以可能需要转换为外接矩形框。 因此,我们假设用户需要的是目标检测任务,那么就需要根据折线(或多边形)点集计算最小外接矩形(旋转矩形或正矩形?)。但通常,我们取坐标的最大最小值形成正矩形。 总结步骤: 1. 读取JSON文件,解析每个`shape`(即每个对象)。 2. 对于每个对象,提取`label`(类别)和`points`(点集)。 3. 将点集转换为外接矩形(通过计算所有点的最小x,最小y,最大x,最大y)。 4. 将矩形转换为YOLOv8格式:归一化的中心坐标和宽高。 5. 写入txt文件,每个对象一行:`class_id center_x center_y width height` 注意:归一化方法: center_x = (x_min + x_max) / 2 / image_width center_y = (y_min + y_max) / 2 / image_height width = (x_max - x_min) / image_width height = (y_max - y_min) / image_height 另外,需要类别到id的映射,用户需要提供一个class列表。 但是,用户提供的JSON中,`imageHeight`和`imageWidth`字段在JSON中已经给出,所以可以直接使用。 如果用户需要的是分割任务,那么就不需要转换为矩形,而是直接将多边形点归一化(注意归一化到0-1之间,每个点坐标除以对应的图像宽度或高度),然后写入txt文件,格式为:`class_id p1_x p1_y p2_x p2_y ...` 由于用户没有明确,而且提供的示例是折线(通常折线在分割任务中不会被使用),所以这里我们按目标检测任务转换。 根据引用[3]中的JSON格式(labelme)和转换目标(YOLOv5的txtYOLOv8目标检测的txt格式相同),我们采用目标检测的转换。 因此,我们将编写一个Python脚本来完成转换。 步骤: 1. 遍历指定文件夹中的所有JSON文件。 2. 对于每个JSON文件,读取内容。 3. 获取图像宽度和高度(从JSON的`imageWidth`和`imageHeight`字段)。 4. 遍历每个`shapes`,对于每个形状(无论它是多边形还是折线),计算所有点的最小外接矩形(正矩形)。 5. 将矩形归一化,并转换为YOLO格式。 6. 写入与JSON同名的txt文件(保存在指定目录,如`labels`文件夹),每个对象一行。 注意:同一个JSON文件(即同一张图片)的所有对象都写入同一个txt文件。 另外,需要类别映射(label字符串到整数id)。这里我们可以通过用户提供的类别列表来映射,或者从所有JSON文件中收集所有类别然后排序映射。但为了简单,我们假设用户已经有一个固定的类别列表,并可以在脚本中配置。 我们假设类别列表为:['huaizao', ...] (根据用户示例中的label为"huaizao") 脚本如下: </think>根据您提供的JSON格式(由标注工具如LabelMe生成)和YOLOv8的要求,以下是完整的Python代码实现,用于将JSON标注转换为YOLOv8兼容的TXT格式: ```python import json import os from pathlib import Path def json_to_yolov8(json_path, output_dir, class_map): """ 将LabelMe生成的JSON标注转换为YOLOv8格式 参数: json_path: JSON文件路径 output_dir: 输出TXT文件目录 class_map: 类别名称到ID的映射字典 """ with open(json_path, 'r') as f: data = json.load(f) img_width = data['imageWidth'] img_height = data['imageHeight'] txt_lines = [] for shape in data['shapes']: label = shape['label'] points = shape['points'] # 提取所有点的x和y坐标 x_coords = [p[0] for p in points] y_coords = [p[1] for p in points] # 计算边界框 x_min = min(x_coords) y_min = min(y_coords) x_max = max(x_coords) y_max = max(y_coords) # 转换为YOLO格式:归一化中心坐标 + 宽高 center_x = (x_min + x_max) / 2 / img_width center_y = (y_min + y_max) / 2 / img_height width = (x_max - x_min) / img_width height = (y_max - y_min) / img_height # 确保坐标在[0,1]范围内 center_x = max(0, min(1, center_x)) center_y = max(0, min(1, center_y)) width = max(0, min(1, width)) height = max(0, min(1, height)) # 获取类别ID class_id = class_map.get(label, -1) if class_id == -1: print(f"警告: 未识别的标签 '{label}',跳过此标注") continue txt_lines.append(f"{class_id} {center_x:.6f} {center_y:.6f} {width:.6f} {height:.6f}") # 写入TXT文件 if txt_lines: txt_filename = Path(json_path).stem + '.txt' txt_path = os.path.join(output_dir, txt_filename) with open(txt_path, 'w') as f: f.write('\n'.join(txt_lines)) return True return False # 示例使用 if __name__ == "__main__": # 配置参数 JSON_DIR = "/path/to/json/files" # JSON文件目录 OUTPUT_DIR = "/path/to/output/labels" # 输出目录 CLASS_MAP = {"huaizao": 0, "other_class": 1} # 类别映射 # 确保输出目录存在 os.makedirs(OUTPUT_DIR, exist_ok=True) # 处理所有JSON文件 converted_count = 0 for filename in os.listdir(JSON_DIR): if filename.endswith('.json'): json_path = os.path.join(JSON_DIR, filename) if json_to_yolov8(json_path, OUTPUT_DIR, CLASS_MAP): converted_count += 1 print(f"转换完成! 成功处理 {converted_count} 个文件") ``` ### 关键说明: 1. **类别映射**: - `CLASS_MAP` 字典定义类别名称到ID的映射 - 示例:`{"huaizao": 0, "person": 1, "car": 2}` 2. **转换逻辑**: -JSON中提取多边形所有顶点坐标 - 计算最小外接矩形作为边界框 - 将边界框转换为YOLO格式:归一化中心坐标 + 宽高 - 坐标归一化公式:$ \text{norm} = \frac{\text{pixel}}{\text{image\_dim}} $ 3. **输出格式**: ``` <class_id> <center_x> <center_y> <width> <height> ``` 示例:`0 0.512345 0.423456 0.123456 0.234567` 4. **文件结构**: ```bash dataset/ ├── images/ # 存放原始图像 └── labels/ # 存放转换后的TXT文件 ``` ### 使用注意事项: 1. **空标注处理**:无标注对象的图像会生成空TXT文件 2. **坐标归一化**:所有坐标值在[0,1]范围内 3. **图像尺寸**:直接从JSON的`imageWidth`和`imageHeight`获取 4. **目录创建**:脚本会自动创建输出目录 此脚本兼容LabelMe生成的JSON格式,可直接用于YOLOv8训练[^1][^3]。转换后的数据集结构符合YOLOv8要求: ``` class_id center_x center_y width height ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值