该工作适用于目标检测工作。

由于labelme标注出的文件是如下图的单个json文件格式,不符合yolo的训练格式,需要转格式。

观察发现labelme标注的json文件中有imageData,还挺大的,查阅后得知是base64后的图片数据,也就是说json文件中,只要带有imageData就其实是包含了图片文件的数据,可以用json文件直接输出图片文件。

所以利用labelme的json可以直接完成yolo格式标注的输出。使用该代码可以直接按比例分割train,val,test,并输出文件到如下标准格式文件目录

yoloformat
    |--images
    |    |--train
    |    |--val
    |    |--test
    |--labels
         |--train
         |--val
         |--test

代码如下:

import base64
import os
import io
import json
import glob
from PIL import Image
import random

def labelme_to_yolo(json_file, output_img_dir, output_label_dir, class_dict):
    # 读取JSON文件
    with open(json_file, 'r') as f:
        data = json.load(f)
    
    # 解析imageData并获取图像的宽度和高度
    image = Image.open(io.BytesIO(base64.b64decode(data['imageData'])))
    width, height = image.size
    
    # 提取JSON文件的基础文件名
    base_name = os.path.basename(json_file).replace('.json', '')
    
    # 保存图像
    image_path = os.path.join(output_img_dir, base_name + '.png')
    image.save(image_path)
    
    # 创建YOLO标注文件
    txt_path = os.path.join(output_label_dir, base_name + '.txt')
    with open(txt_path, 'w') as f:
        for shape in data['shapes']:
            # 获取对象的类别和边界框
            label = shape['label']
            points = shape['points']
            
            # 计算YOLO格式的中心点和宽度/高度
            x_center = (points[0][0] + points[1][0]) / 2 / width
            y_center = (points[0][1] + points[1][1]) / 2 / height
            box_width = abs(points[1][0] - points[0][0]) / width
            box_height = abs(points[1][1] - points[0][1]) / height
            
            # 将此行写入YOLO标注文件
            f.write(f"{class_dict[label]} {x_center} {y_center} {box_width} {box_height}\n")

# 类别字典,将类别名称映射为整数
class_dict = {"oil": 0, "scr": 1, "sta": 2}  # 根据你的数据集来替换这些类别

# 设置输出目录
output_dir = 'newlabel'
os.makedirs(os.path.join(output_dir, 'images', 'train'), exist_ok=True)
os.makedirs(os.path.join(output_dir, 'images', 'val'), exist_ok=True)
os.makedirs(os.path.join(output_dir, 'images', 'test'), exist_ok=True)
os.makedirs(os.path.join(output_dir, 'labels', 'train'), exist_ok=True)
os.makedirs(os.path.join(output_dir, 'labels', 'val'), exist_ok=True)
os.makedirs(os.path.join(output_dir, 'labels', 'test'), exist_ok=True)

# 获取所有的JSON文件
json_files = glob.glob('*.json')

# 打乱文件列表
random.shuffle(json_files)

# 计算训练集、验证集和测试集的大小
n_total = len(json_files)
n_val = int(n_total * 0.12)
n_test = int(n_total * 0.12)
n_train = n_total - n_val - n_test

# 分割文件列表
train_files = json_files[:n_train]
val_files = json_files[n_train:n_train+n_val]
test_files = json_files[n_train+n_val:]

# 处理所有的JSON文件
for json_file in train_files:
    labelme_to_yolo(json_file, os.path.join(output_dir, 'images', 'train'), os.path.join(output_dir, 'labels', 'train'), class_dict)
for json_file in val_files:
    labelme_to_yolo(json_file, os.path.join(output_dir, 'images', 'val'), os.path.join(output_dir, 'labels', 'val'), class_dict)
for json_file in test_files:
    labelme_to_yolo(json_file, os.path.join(output_dir, 'images', 'test'), os.path.join(output_dir, 'labels', 'test'), class_dict)

GitHub 加速计划 / js / json
43
5
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:6 个月前 )
4424a0fc Signed-off-by: Niels Lohmann <mail@nlohmann.me> 4 天前
11aa5f94 * Make std::filesystem::path conversion to/from UTF-8 encoded JSON string explicit. Signed-off-by: Richard Musil <risa2000x@gmail.com> * Experimental: Changing C++ standard detection logic to accommodate potential corner cases. Signed-off-by: Richard Musil <risa2000x@gmail.com> * Drop C++ standard tests for compilers which do not implement required features. Signed-off-by: Richard Musil <risa2000x@gmail.com> * Drop C++ standard tests for MSVC versions which do not implement required features. Signed-off-by: Richard Musil <risa2000x@gmail.com> --------- Signed-off-by: Richard Musil <risa2000x@gmail.com> Co-authored-by: Richard Musil <risa2000x@gmail.com> 5 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐