Labelme标注的JSON文件别浪费!手把手教你用Python脚本批量转成YOLO格式

发布时间:2026/6/10 3:26:51

Labelme标注的JSON文件别浪费!手把手教你用Python脚本批量转成YOLO格式 Labelme标注数据高效转换指南从JSON到YOLO格式的完整解决方案在计算机视觉项目的实际开发中数据标注往往占据了整个流程60%以上的时间成本。许多团队花费大量精力完成标注后却卡在了格式转换这一关键环节。Labelme作为一款优秀的图像标注工具生成的JSON文件包含了丰富的标注信息但这些数据并不能直接被YOLO等主流目标检测框架使用。本文将深入解析Labelme的JSON数据结构并提供一套完整的Python转换方案帮助您实现从原始标注到训练就绪数据的高效转化。1. 理解Labelme与YOLO的数据格式差异Labelme生成的JSON文件采用绝对坐标存储多边形(Polygon)顶点信息而YOLO需要的则是归一化后的中心点坐标和宽高比例。这种本质差异导致直接使用Labelme输出训练模型时会出现兼容性问题。Labelme JSON典型结构示例{ version: 4.5.6, flags: {}, shapes: [ { label: lodging, points: [[102, 205], [108, 234], [150, 227], [145, 193]], shape_type: polygon } ], imagePath: wheat_field_001.jpg, imageData: null }YOLO所需的TXT格式要求class_id x_center y_center width height其中所有坐标值都是相对于图像宽高的归一化数值(0-1之间)关键转换步骤解析JSON中的多边形顶点坐标计算多边形的最小外接矩形将绝对坐标转换为归一化值根据类别名称映射为YOLO的class_id2. 构建Python转换脚本的核心逻辑下面是一个功能完整的转换脚本包含错误处理和批量操作支持import json import os import numpy as np from pathlib import Path def labelme_to_yolo(json_path, output_dir, class_mapping): 将单个Labelme JSON文件转换为YOLO格式的TXT文件 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].lower() if label not in class_mapping: continue # 获取多边形顶点并计算外接矩形 points np.array(shape[points]) x_min, y_min np.min(points, axis0) x_max, y_max np.max(points, axis0) # 计算中心点和宽高(归一化) x_center ((x_min x_max) / 2) / img_width y_center ((y_min y_max) / 2) / img_height width (x_max - x_min) / img_width height (y_max - y_min) / img_height # 确保数值在有效范围内 x_center np.clip(x_center, 0, 1) y_center np.clip(y_center, 0, 1) width np.clip(width, 0, 1) height np.clip(height, 0, 1) txt_lines.append(f{class_mapping[label]} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) # 写入输出文件 output_path Path(output_dir) / (Path(json_path).stem .txt) with open(output_path, w) as f: f.write(\n.join(txt_lines)) def batch_convert(input_dir, output_dir, class_mapping): 批量处理目录中的所有JSON文件 if not os.path.exists(output_dir): os.makedirs(output_dir) json_files [f for f in os.listdir(input_dir) if f.endswith(.json)] for json_file in json_files: try: labelme_to_yolo( os.path.join(input_dir, json_file), output_dir, class_mapping ) except Exception as e: print(f处理文件 {json_file} 时出错: {str(e)}) print(f转换完成共处理 {len(json_files)} 个文件) # 示例使用 CLASS_MAPPING {lodging: 0} # 自定义标签到YOLO类别ID的映射 batch_convert(labelme_json, yolo_labels, CLASS_MAPPING)3. 高级应用场景与性能优化3.1 处理复杂标注情况实际项目中常遇到一些特殊情况需要特别处理多类别标注扩展CLASS_MAPPING字典即可支持CLASS_MAPPING { lodging: 0, healthy: 1, disease: 2 }无效标注过滤添加面积阈值过滤min_area 0.01 # 忽略面积小于图像1%的标注 area width * height if area min_area: continue标注验证可视化生成带标注框的图像用于人工校验import cv2 def visualize_yolo_labels(image_path, label_path, output_path): img cv2.imread(image_path) h, w img.shape[:2] with open(label_path, r) as f: lines f.readlines() for line in lines: class_id, xc, yc, bw, bh map(float, line.strip().split()) x1 int((xc - bw/2) * w) y1 int((yc - bh/2) * h) x2 int((xc bw/2) * w) y2 int((yc bh/2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite(output_path, img)3.2 性能优化技巧当处理大规模数据集时可以考虑以下优化策略多进程处理from multiprocessing import Pool def process_file(args): json_file, input_dir, output_dir, class_mapping args try: labelme_to_yolo( os.path.join(input_dir, json_file), output_dir, class_mapping ) except Exception as e: return fError in {json_file}: {str(e)} return None def parallel_convert(input_dir, output_dir, class_mapping, workers4): json_files [f for f in os.listdir(input_dir) if f.endswith(.json)] args [(f, input_dir, output_dir, class_mapping) for f in json_files] with Pool(workers) as p: results p.map(process_file, args) errors [r for r in results if r is not None] if errors: print(f遇到 {len(errors)} 个错误:) for e in errors[:3]: # 只打印前3个错误 print(e)内存优化对于超大JSON文件使用ijson库进行流式解析import ijson def parse_large_json(json_path): with open(json_path, rb) as f: shapes ijson.items(f, shapes.item) for shape in shapes: yield shape4. 转换后的数据验证与常见问题排查完成格式转换后必须进行严格的数据验证。以下是推荐的检查清单验证项目检查方法常见问题坐标范围确认所有值在[0,1]区间未归一化或计算错误类别映射检查class_id是否正确标签拼写不一致图像对应确保每个JSON都有匹配的图像文件命名不一致标注完整性抽样可视化检查多边形转换后丢失细节文件权限确认输出文件可读写权限不足导致写入失败可视化校验脚本import matplotlib.pyplot as plt import matplotlib.patches as patches def plot_yolo_annotation(image_path, label_path): img plt.imread(image_path) fig, ax plt.subplots(1) ax.imshow(img) with open(label_path, r) as f: lines f.readlines() for line in lines: class_id, xc, yc, bw, bh map(float, line.strip().split()) rect patches.Rectangle( ((xc - bw/2) * img.shape[1], (yc - bh/2) * img.shape[0]), bw * img.shape[1], bh * img.shape[0], linewidth1, edgecolorr, facecolornone ) ax.add_patch(rect) plt.show()遇到转换问题时可以按照以下流程排查检查原始JSON文件是否完整确认图像尺寸与JSON中的imageWidth/imageHeight一致验证类别标签是否完全匹配(注意大小写)检查多边形坐标是否形成闭合区域确认输出目录有写入权限

相关新闻