当前位置: 首页 > article >正文

Labelme标注数据转YOLOv5格式:手把手教你JSON转TXT(附完整代码)

Labelme标注数据转YOLOv5格式从原理到实践的完整指南在计算机视觉项目中数据标注是模型训练前的关键步骤。Labelme作为一款开源的图像标注工具因其简单易用而广受欢迎。然而当我们需要将Labelme生成的JSON标注文件转换为YOLOv5训练所需的TXT格式时往往会遇到一些技术障碍。本文将深入解析这一转换过程不仅提供完整的代码实现还会详细讲解背后的数学原理和实际应用中的注意事项。1. 理解数据格式差异在开始转换之前我们需要清楚地了解Labelme和YOLOv5使用不同数据格式的原因及其本质区别。Labelme生成的JSON文件采用绝对坐标系统记录了多边形或矩形框的顶点坐标。这种格式的优势在于保留了完整的几何信息便于人工检查和修改。一个典型的Labelme JSON文件包含以下关键信息{ version: 4.5.6, flags: {}, shapes: [ { label: person, points: [[100, 150], [300, 150], [300, 400], [100, 400]], shape_type: polygon } ], imagePath: example.jpg, imageHeight: 640, imageWidth: 480 }相比之下YOLOv5需要的TXT格式则采用相对坐标系统每个标注行包含class_id x_center y_center width height其中所有坐标值都是相对于图像宽度和高度的比例值范围在0到1之间。这种设计使YOLOv5模型能够处理不同尺寸的输入图像而无需调整标注数据。注意YOLO格式使用中心点坐标而非顶点坐标这是与许多其他目标检测框架的重要区别。2. 转换过程的核心算法从Labelme的JSON到YOLOv5的TXT格式转换核心在于坐标系的转换和归一化处理。让我们分解这一过程的数学原理。2.1 边界框提取对于矩形标注shape_type为rectangleLabelme通常存储两个对角点的坐标。我们需要先确定边界框的四个极值x_min min(points[0][0], points[1][0]) y_min min(points[0][1], points[1][1]) x_max max(points[0][0], points[1][0]) y_max max(points[0][1], points[1][1])对于多边形标注shape_type为polygon则需要遍历所有顶点找出最小和最大的x、y值x_coords [p[0] for p in points] y_coords [p[1] for p in points] x_min, x_max min(x_coords), max(x_coords) y_min, y_max min(y_coords), max(y_coords)2.2 坐标归一化获取绝对坐标的边界框后我们需要将其转换为YOLO格式的相对坐标。转换公式如下x_center (x_min x_max) / (2 * image_width) y_center (y_min y_max) / (2 * image_height) width (x_max - x_min) / image_width height (y_max - y_min) / image_height这一转换确保了无论原始图像尺寸如何变化标注数据都能保持一致性。以下是Python实现def xyxy2xywh(size, box): image_width, image_height size x_min, y_min, x_max, y_max box x_center (x_min x_max) / 2 / image_width y_center (y_min y_max) / 2 / image_height width (x_max - x_min) / image_width height (y_max - y_min) / image_height return (x_center, y_center, width, height)3. 完整转换代码实现基于上述原理我们开发了一个健壮的转换脚本支持批量处理和多类别转换。以下是完整的代码实现import json import os from pathlib import Path import cv2 class Labelme2YOLOv5Converter: def __init__(self, class_mappingNone): 初始化转换器 :param class_mapping: 类别名称到ID的映射字典如 {person: 0, car: 1} self.class_mapping class_mapping or {} def convert_file(self, json_path, image_dir, output_dir): 转换单个JSON文件 :param json_path: JSON文件路径 :param image_dir: 图像文件目录 :param output_dir: 输出TXT目录 with open(json_path, r) as f: data json.load(f) image_path os.path.join(image_dir, data[imagePath]) image cv2.imread(image_path) if image is None: raise FileNotFoundError(f无法加载图像: {image_path}) height, width image.shape[:2] txt_lines [] for shape in data[shapes]: label shape[label] class_id self.class_mapping.get(label, -1) if class_id -1: continue points shape[points] if shape[shape_type] rectangle: x_coords [p[0] for p in points] y_coords [p[1] for p in points] x_min, x_max min(x_coords), max(x_coords) y_min, y_max min(y_coords), max(y_coords) else: x_coords [p[0] for p in points] y_coords [p[1] for p in points] x_min, x_max min(x_coords), max(x_coords) y_min, y_max min(y_coords), max(y_coords) x_center, y_center, w, h self.xyxy2xywh((width, height), (x_min, y_min, x_max, y_max)) txt_lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) # 保存TXT文件 txt_filename os.path.splitext(data[imagePath])[0] .txt txt_path os.path.join(output_dir, txt_filename) os.makedirs(output_dir, exist_okTrue) with open(txt_path, w) as f: f.write(\n.join(txt_lines)) staticmethod def xyxy2xywh(size, box): 将绝对坐标转换为YOLO格式的相对坐标 width, height size x_min, y_min, x_max, y_max box x_center (x_min x_max) / 2 / width y_center (y_min y_max) / 2 / height w (x_max - x_min) / width h (y_max - y_min) / height return x_center, y_center, w, h def convert_folder(self, json_dir, image_dir, output_dir): 批量转换目录下的所有JSON文件 :param json_dir: JSON文件目录 :param image_dir: 图像文件目录 :param output_dir: 输出TXT目录 json_files [f for f in os.listdir(json_dir) if f.endswith(.json)] for json_file in json_files: try: self.convert_file( os.path.join(json_dir, json_file), image_dir, output_dir ) print(f成功转换: {json_file}) except Exception as e: print(f转换失败 {json_file}: {str(e)}) # 使用示例 if __name__ __main__: # 定义类别映射 CLASS_MAPPING { person: 0, car: 1, dog: 2 } # 初始化转换器 converter Labelme2YOLOv5Converter(CLASS_MAPPING) # 设置路径 JSON_DIR path/to/json_files IMAGE_DIR path/to/images OUTPUT_DIR path/to/output_txt # 执行转换 converter.convert_folder(JSON_DIR, IMAGE_DIR, OUTPUT_DIR)4. 实际应用中的优化技巧在实际项目中我们积累了一些优化转换过程的经验技巧4.1 多类别处理策略自动类别发现当类别较多时可以修改代码自动发现所有类别并生成映射def discover_classes(json_dir): classes set() for json_file in os.listdir(json_dir): if json_file.endswith(.json): with open(os.path.join(json_dir, json_file), r) as f: data json.load(f) for shape in data[shapes]: classes.add(shape[label]) return {name: idx for idx, name in enumerate(sorted(classes))}类别验证在转换前检查所有类别是否都有映射避免数据丢失missing_classes [shape[label] for shape in data[shapes] if shape[label] not in self.class_mapping] if missing_classes: print(f警告: 发现未映射的类别: {set(missing_classes)})4.2 性能优化对于大规模数据集可以采用以下优化措施并行处理使用Python的multiprocessing模块加速批量转换from multiprocessing import Pool def process_file(args): json_file, image_dir, output_dir, converter args try: converter.convert_file( os.path.join(json_dir, json_file), image_dir, output_dir ) return (json_file, True) except Exception as e: return (json_file, False, str(e)) # 在convert_folder方法中使用 with Pool(processes4) as pool: # 使用4个进程 args_list [(f, image_dir, output_dir, self) for f in json_files] results pool.map(process_file, args_list)增量处理记录已处理的文件避免重复工作processed_file os.path.join(output_dir, .processed_files.txt) def get_processed_files(): if os.path.exists(processed_file): with open(processed_file, r) as f: return set(f.read().splitlines()) return set() def update_processed_files(file_list): existing get_processed_files() with open(processed_file, a) as f: for file in file_list: if file not in existing: f.write(file \n) # 在convert_folder中调用 processed get_processed_files() json_files [f for f in os.listdir(json_dir) if f.endswith(.json) and f not in processed] update_processed_files([f for f in json_files])4.3 数据验证转换完成后建议进行数据验证以确保质量可视化检查编写脚本将YOLO格式标注绘制到图像上验证import matplotlib.pyplot as plt import matplotlib.patches as patches def visualize_yolo_annotation(image_path, txt_path, class_names): image cv2.imread(image_path) image cv2.cvtColor(image, cv2.COLOR_BGR2RGB) height, width image.shape[:2] fig, ax plt.subplots(1) ax.imshow(image) with open(txt_path, r) as f: for line in f: class_id, x, y, w, h map(float, line.strip().split()) # 转换回绝对坐标 x_abs x * width y_abs y * height w_abs w * width h_abs h * height # 计算矩形框左上角坐标 x_min x_abs - w_abs/2 y_min y_abs - h_abs/2 rect patches.Rectangle( (x_min, y_min), w_abs, h_abs, linewidth2, edgecolorr, facecolornone ) ax.add_patch(rect) label class_names[int(class_id)] if class_names else str(int(class_id)) ax.text(x_min, y_min-5, label, colorr, fontsize12) plt.show()统计检查生成标注统计报告def generate_stats_report(txt_dir, class_namesNone): class_counts {} total_boxes 0 for txt_file in os.listdir(txt_dir): if txt_file.endswith(.txt): with open(os.path.join(txt_dir, txt_file), r) as f: for line in f: class_id int(line.strip().split()[0]) class_counts[class_id] class_counts.get(class_id, 0) 1 total_boxes 1 print(f总标注框数: {total_boxes}) print(各类别分布:) for class_id, count in sorted(class_counts.items()): class_name class_names[class_id] if class_names else str(class_id) print(f {class_name}: {count} ({count/total_boxes:.1%}))5. 常见问题与解决方案在实际应用中我们总结了几个常见问题及其解决方法坐标越界问题现象转换后的x_center、y_center、w或h值超出[0,1]范围原因原始标注超出了图像边界解决方案在转换前对坐标进行裁剪def clip_coordinates(box, width, height): x_min, y_min, x_max, y_max box x_min max(0, min(x_min, width-1)) y_min max(0, min(y_min, height-1)) x_max max(0, min(x_max, width-1)) y_max max(0, min(y_max, height-1)) return (x_min, y_min, x_max, y_max)图像与JSON不匹配问题现象JSON中记录的imageHeight/imageWidth与实际图像尺寸不符解决方案优先使用实际图像尺寸# 在convert_file方法中替换 height, width image.shape[:2] # 替代 # height data[imageHeight] # width data[imageWidth]多对象标注处理现象一个JSON文件中包含多个对象的标注解决方案我们的完整代码已经支持每个shape会生成一行记录特殊形状处理现象Labelme支持circle、linestrip等特殊形状解决方案转换为边界框或扩展转换逻辑if shape[shape_type] circle: center_x, center_y shape[points][0] radius_x abs(shape[points][1][0] - center_x) radius_y abs(shape[points][1][1] - center_y) x_min, x_max center_x - radius_x, center_x radius_x y_min, y_max center_y - radius_y, center_y radius_y中文路径问题现象在Windows系统上可能遇到中文路径问题解决方案使用Pathlib处理路径from pathlib import Path image_path Path(image_dir) / data[imagePath] with open(image_path, rb) as f: bytes bytearray(f.read()) numpyarray np.asarray(bytes, dtypenp.uint8) image cv2.imdecode(numpyarray, cv2.IMREAD_UNCHANGED)

相关文章:

Labelme标注数据转YOLOv5格式:手把手教你JSON转TXT(附完整代码)

Labelme标注数据转YOLOv5格式:从原理到实践的完整指南 在计算机视觉项目中,数据标注是模型训练前的关键步骤。Labelme作为一款开源的图像标注工具,因其简单易用而广受欢迎。然而,当我们需要将Labelme生成的JSON标注文件转换为YOLO…...

LeetCode --- 2293. Min Max Game 解题报告

原问题 Question: You are given a 0-indexed integer array nums whose length is a power of 2. Apply the following algorithm on nums: Let n be the length of nums. If n == 1, end the process. Otherwise, create a new 0-indexed integer array newNums of length …...

抖音批量下载技术深度解析:从单视频到用户主页的全场景解决方案

抖音批量下载技术深度解析:从单视频到用户主页的全场景解决方案 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallb…...

Qwen3-ForcedAligner常见问题全解析:从错误码到成功对齐

Qwen3-ForcedAligner常见问题全解析:从错误码到成功对齐 1. 为什么你的音文对齐总是失败?先理解这个核心逻辑 想象一下这个场景:你有一段清晰的会议录音,也有完整的会议纪要文字稿,现在需要把每个字在录音里的起止时…...

Qwen3-VL-8B多模态工具亲测:上传图片就能问,本地部署真简单

Qwen3-VL-8B多模态工具亲测:上传图片就能问,本地部署真简单 1. 工具概览:你的私人视觉助手 想象一下,当你看到一张复杂的图表或一张陌生的植物照片时,只需要上传图片并提问,就能立即获得专业级的解释和分…...

Diablo Edit2:终极暗黑破坏神II存档编辑器完整指南

Diablo Edit2:终极暗黑破坏神II存档编辑器完整指南 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit 还在为刷不到心仪的装备而烦恼吗?想要体验不同技能组合却不想重新练级&a…...

Windows系统下MacBook Pro Touch Bar高效解锁指南:一键开启智能触控显示功能

Windows系统下MacBook Pro Touch Bar高效解锁指南:一键开启智能触控显示功能 【免费下载链接】DFRDisplayKm Windows infrastructure support for Apple DFR (Touch Bar) 项目地址: https://gitcode.com/gh_mirrors/df/DFRDisplayKm 还在为Windows系统下MacB…...

如何在6GB显存下运行专业级AI图像生成模型

如何在6GB显存下运行专业级AI图像生成模型 【免费下载链接】flux1-dev 项目地址: https://ai.gitcode.com/hf_mirrors/Comfy-Org/flux1-dev 当大多数AI创作者还在为动辄需要24GB显存的高端显卡而烦恼时,FLUX.1-dev FP8量化模型的出现彻底改变了游戏规则。这…...

PROJECT MOGFACE创意编程项目展示:自动生成交互式网页小游戏

PROJECT MOGFACE创意编程项目展示:自动生成交互式网页小游戏 你有没有过这样的瞬间?脑子里突然蹦出一个绝妙的游戏点子,比如“一个控制小方块躲避从天而降的障碍物”,但一想到要写HTML、CSS、JavaScript,还要调试物理…...

Excel VBA 入门到精通(九):错误处理与调试

🎯 本章目标:掌握 VBA 错误处理机制,学会使用调试工具定位问题,编写健壮、可靠的代码。 一、错误类型 1.1 VBA 中的三种错误 ┌─────────────────────────────────────────────┐ │ VBA 错误类型 …...

宝塔面板如何实现网站重定向_配置301永久跳转与域名更换

宝塔面板中301重定向在网站设置页的「重定向」选项卡配置,需勾选“301永久重定向”,源目录填/实现整站跳转;路径映射复杂时须手动编辑Nginx配置文件添加rewrite规则并加permanent标志。宝塔面板里 301 重定向在哪配就在网站设置页的「重定向」…...

SQL如何检测分组内是否存在满足条件的数据_EXISTS结合分组

用 MAX(CASE WHEN condition THEN 1 ELSE 0 END) 1 判断分组内是否存在符合条件的行最稳妥,避免 EXISTS 在 GROUP BY 中语法错误或逻辑失效,兼容性好且语义清晰。GROUP BY 后怎么判断某组里有没有符合条件的行直接用 HAVING 配合聚合函数最稳妥&#xf…...

BEAST 2 贝叶斯进化分析:从新手到专家的完整指南

BEAST 2 贝叶斯进化分析:从新手到专家的完整指南 【免费下载链接】beast2 Bayesian Evolutionary Analysis by Sampling Trees 项目地址: https://gitcode.com/gh_mirrors/be/beast2 BEAST 2(Bayesian Evolutionary Analysis by Sampling Trees&a…...

AlienFX-Tools终极指南:释放Alienware设备的全部潜能

AlienFX-Tools终极指南:释放Alienware设备的全部潜能 【免费下载链接】alienfx-tools Alienware systems lights, fans, and power control tools and apps 项目地址: https://gitcode.com/gh_mirrors/al/alienfx-tools AlienFX-Tools是一款功能强大的开源硬…...

PvZ Toolkit:如何为植物大战僵尸PC版打造个性化游戏体验

PvZ Toolkit:如何为植物大战僵尸PC版打造个性化游戏体验 【免费下载链接】pvztoolkit 植物大战僵尸 PC 版综合修改器 项目地址: https://gitcode.com/gh_mirrors/pv/pvztoolkit 你是否曾经在植物大战僵尸的无尽模式中,精心布置的阵型因为一次失误…...

太极重命名软件的功能架构与技术实现分析

软件工具的价值不仅在于其外在功能,更在于其内在的技术架构设计。 太极重命名作为一款优秀的文件批量处理工具,其技术实现层面同样有诸多值得深入分析的地方。 本文将从技术视角对该软件的功能架构与实现原理进行剖析。 首先值得关注的是该软件的单文件…...

轻量化文件批量重命名工具——太极重命名的设计理念与实践

在数字化办公日益普及的今天,文件管理成为每个人都要面对的日常任务。 批量重命名作为文件管理中的高频操作,却往往缺乏简单高效的解决方案。 太极重命名软件正是在这样的背景下应运而生,以其独特的设计理念满足用户需求。 该软件最为显著的…...

实战教程:用YOLOv12打造高精度交通标志识别桌面应用(附PySide6界面源码)

实战教程:用YOLOv12打造高精度交通标志识别桌面应用(附PySide6界面源码) 交通标志识别技术正逐渐成为智能交通系统和自动驾驶领域的关键组件。随着深度学习算法的快速发展,YOLO系列模型因其出色的实时性和准确性,成为目…...

告别GUI:在Matlab命令行里优雅地处理GRACE RL06数据(附代码详解)

命令行驱动的GRACE RL06数据处理:Matlab高效工作流构建指南 在卫星重力测量领域,GRACE(Gravity Recovery and Climate Experiment)数据已成为研究地球质量变化不可或缺的资源。随着RL06数据版本的发布,其精度和可靠性进…...

【深度学习:实践篇】从零构建--联邦学习系统

1. 联邦学习系统架构设计 第一次接触联邦学习系统时,我被它精妙的设计理念所吸引。这就像几个邻居想一起烤蛋糕,但谁也不愿意公开自己的独家配方。最后大家决定:各自在家烤好蛋糕胚,只把半成品送到中央厨房做最后装饰。这种"…...

若依Vue3前后端分离项目宝塔部署实战:从环境配置到Nginx调优

1. 环境准备与宝塔面板初始化 部署若依Vue3前后端分离项目前,服务器环境准备是重中之重。我建议选择CentOS 7.6或Ubuntu 20.04这类长期支持版本的操作系统,它们与宝塔面板的兼容性最好。记得在购买云服务器时勾选"安全组放行80/443端口"选项&a…...

千问3.5-27B轻量级部署方案:单卡A100适配路径与性能衰减评估

千问3.5-27B轻量级部署方案:单卡A100适配路径与性能衰减评估 1. 引言:当大模型遇上单卡部署 如果你手头只有一张A100,却想跑起来一个270亿参数的大模型,是不是觉得有点异想天开?别急着放弃,这篇文章就是为…...

RexUniNLU真实生成效果:医疗问诊记录中症状实体+情感倾向联合输出

RexUniNLU真实生成效果:医疗问诊记录中症状实体情感倾向联合输出 1. 引言:当AI能看懂病历和感受情绪 想象一下,一位医生每天要面对几十份电子病历和问诊记录。他需要快速找出病人的关键症状,同时还要判断病人描述病情时的情绪状…...

在Termux中构建高效C++开发环境:Vim插件与LSP的完美结合

1. 为什么选择Termux进行C开发? 在移动设备上写代码听起来像行为艺术,但Termux让这件事变得异常实用。我最初在平板上配置这个环境只是为了应急调试,结果现在80%的C小项目都在这里完成。相比传统IDE,这个组合有几个致命优势&#…...

3分钟解锁网易云音乐NCM格式限制:ncmdumpGUI终极使用指南

3分钟解锁网易云音乐NCM格式限制:ncmdumpGUI终极使用指南 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾经遇到过这样的困扰?…...

GLM-4.1V-9B-Base真实作品:政务办事指南截图→办事条件+材料清单+流程图解

GLM-4.1V-9B-Base真实作品:政务办事指南截图→办事条件材料清单流程图解 1. 模型能力展示:政务场景的视觉理解 今天我要带大家看一个特别实用的案例 - 如何用GLM-4.1V-9B-Base模型快速解析政务办事指南截图。这类图片通常包含办事条件、材料清单和流程…...

Playwright Python:企业级跨浏览器自动化测试的战略解决方案

Playwright Python:企业级跨浏览器自动化测试的战略解决方案 【免费下载链接】playwright-python Python version of the Playwright testing and automation library. 项目地址: https://gitcode.com/GitHub_Trending/pl/playwright-python 在当今快速发展的…...

Golang如何处理JSON空值null_Golang JSON空值处理教程【精通】

Go解析JSON时null被忽略或panic的解决方法:用*string等指针类型接收可空字段;对三态需求(null/空值/缺失)用NullString;避免interface{}和滥用json.RawMessage;优先用标准库,第三方库仅在性能或…...

5分钟快速上手:Windows游戏文本提取神器Textractor终极指南 [特殊字符]

5分钟快速上手:Windows游戏文本提取神器Textractor终极指南 🎮 【免费下载链接】Textractor Extracts text from video games and visual novels. Highly extensible. 项目地址: https://gitcode.com/gh_mirrors/te/Textractor Textractor是一款功…...

GitHub进阶玩法全解析,零基础可快速上手进阶高手,轻松解决各类常见难题。

GitHub高级使用方法大全:从分支管理到自动化工作流 目录 开篇:超越基础,进入工程化协作高级分支策略:不只是存放代码提交的艺术:让每次提交都有价值Pull Request进阶:打造高效Code Review流程GitHub Acti…...