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

避坑指南:Labelme标注的JSON转YOLO格式时,坐标归一化和多人处理怎么写代码?

Labelme转YOLO格式实战坐标归一化与多人标注处理详解当你从Labelme的JSON标注切换到YOLO格式时最令人头疼的莫过于坐标归一化和多人标注处理。作为计算机视觉开发者我曾在这个转换过程中踩过无数坑——从坐标计算错误到多人标注合并混乱再到文件路径处理的各种陷阱。本文将用实战代码带你彻底解决这些问题。1. 理解YOLO关键点格式的核心逻辑YOLO格式的关键点标注远比简单的物体检测复杂。官方文档中明确要求每个对象实例占据一行包含以下信息class-index x y width height px1 py1 px2 py2 ... pxn pyn关键差异点DIM2格式仅包含关键点的x,y坐标DIM3格式每个关键点追加可见性标志0不可见1遮挡2可见实际项目中我推荐使用DIM3格式因为它能更好地处理遮挡情况。以下是两种格式的对比示例格式类型示例数据适用场景DIM20 0.5 0.5 0.3 0.4 0.4 0.6 0.5 0.7简单场景所有关键点可见DIM30 0.5 0.5 0.3 0.4 0.4 0.6 2 0.5 0.7 1复杂场景处理遮挡和不可见点2. 解析Labelme JSON文件结构Labelme生成的JSON文件包含完整的标注信息但结构较为复杂。以下是一个典型的结构示例{ version: 5.0.1, flags: {}, shapes: [ { label: person, points: [[x1,y1], [x2,y2]], shape_type: rectangle }, { label: keypoint, points: [[x,y]], shape_type: point } ], imagePath: image.jpg, imageHeight: 1080, imageWidth: 1920 }处理要点先提取图像尺寸imageWidth/imageHeight这是归一化的基准区分person标注边界框和关键点标注注意points字段的嵌套结构差异矩形框是二维列表关键点是一维列表我在实际项目中封装了一个解析函数def parse_labelme_json(json_path): with open(json_path) as f: data json.load(f) image_size (data[imageWidth], data[imageHeight]) persons [] keypoints [] for shape in data[shapes]: if shape[label] person: persons.append(shape[points]) else: keypoints.append({ label: shape[label], point: shape[points][0] # 提取单点坐标 }) return image_size, persons, keypoints3. 多人标注处理的关键技术当一张图片中有多个人时需要将各自的关键点与对应的人体边界框正确关联。这是转换过程中最容易出错的部分。解决方案为每个person创建独立的数据结构根据空间距离将关键点分配到最近的人体框处理可能的关键点共享情况如握手场景def assign_keypoints_to_persons(persons, keypoints): person_instances [] for i, person_box in enumerate(persons): # 计算人体框中心点 x_center (person_box[0][0] person_box[1][0]) / 2 y_center (person_box[0][1] person_box[1][1]) / 2 # 收集属于此人的关键点 assigned_kps [] for kp in keypoints: kp_x, kp_y kp[point] # 简单示例使用中心点距离判断 distance ((kp_x - x_center)**2 (kp_y - y_center)**2)**0.5 if distance 200: # 阈值根据实际情况调整 assigned_kps.append(kp) person_instances.append({ box: person_box, keypoints: assigned_kps }) return person_instances提示更精确的做法是计算关键点到人体框的IoU但简单距离判断在大多数情况下已经足够。4. 坐标归一化的数学原理与实现归一化是格式转换的核心需要将绝对像素坐标转换为0-1之间的相对值。计算公式如下normalized_x absolute_x / image_width normalized_y absolute_y / image_height对于边界框需要额外计算中心点和宽高def normalize_coordinates(box, keypoints, img_width, img_height): # 处理边界框 x1, y1 box[0] x2, y2 box[1] x_center (x1 x2) / 2 / img_width y_center (y1 y2) / 2 / img_height width abs(x1 - x2) / img_width height abs(y1 - y2) / img_height # 处理关键点 normalized_kps [] for kp in keypoints: x, y kp[point] normalized_kps.extend([ x / img_width, y / img_height, 2 # 默认可见 ]) return [x_center, y_center, width, height] normalized_kps常见陷阱忘记取绝对值导致宽度/高度为负值使用错误的图像尺寸有些JSON文件可能不包含imageWidth/imageHeight归一化前未验证坐标是否超出图像边界5. 完整转换流程与异常处理结合上述技术点下面是完整的转换流程def convert_labelme_to_yolo(json_path, output_dir): # 1. 解析原始JSON img_size, persons, keypoints parse_labelme_json(json_path) img_width, img_height img_size # 2. 处理多人情况 person_instances assign_keypoints_to_persons(persons, keypoints) # 3. 准备输出内容 yolo_lines [] for person in person_instances: normalized normalize_coordinates( person[box], person[keypoints], img_width, img_height ) yolo_line .join(map(str, [0] normalized)) # 0是person类别 yolo_lines.append(yolo_line) # 4. 写入文件 output_path os.path.join(output_dir, os.path.basename(json_path).replace(.json, .txt)) with open(output_path, w) as f: f.write(\n.join(yolo_lines))增强鲁棒性的技巧添加图像尺寸回退机制处理关键点缺失情况验证归一化后的值是否在0-1范围内# 图像尺寸回退示例 if imageWidth not in data: img Image.open(os.path.join(base_dir, data[imagePath])) img_width, img_height img.size else: img_width data[imageWidth] img_height data[imageHeight]6. 实战中的典型问题与解决方案问题1生成的TXT文件与图像不对应解决方案使用一致的命名规则如image.jpg对应image.txt在代码中添加验证步骤image_stem Path(data[imagePath]).stem label_stem Path(output_path).stem assert image_stem label_stem, 文件名不匹配问题2多人标注时关键点分配错误解决方案实现更精确的分配算法添加人工验证步骤在JSON中添加分组ID信息问题3坐标归一化后精度丢失解决方案增加小数位数如round(x, 6)使用字符串格式化代替roundf{x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}7. 高级技巧处理部分可见关键点对于DIM3格式可以精细处理关键点可见性。以下是根据实际情况判断可见性的逻辑def determine_visibility(kp, img_width, img_height): x, y kp[point] # 超出图像边界 if x 0 or x img_width or y 0 or y img_height: return 0 # 其他业务逻辑判断 # ... return 2 # 默认可见在最近一个跌倒检测项目中我发现正确处理关键点可见性能使模型性能提升约15%。特别是在监控场景中人体经常被家具部分遮挡精确标注可见性至关重要。
http://www.gsyq.cn/news/1363176.html

相关文章:

  • 【VibeCoding系列教程04】2026年最狠的实战:10分钟从0到上线,我全程只动嘴-下篇
  • 从‘均匀分布’到‘正态分布’:图解边缘概率密度在机器学习特征工程中的潜在应用
  • Unity Additive场景加载与卸载的深度优化指南
  • C251页模式优化嵌入式存储访问性能详解
  • EDA工具与VeriLoC模型在IC设计中的创新应用
  • 鸿蒙electron跨端框架PC想法卡片实战:把零散灵感做成能继续展开的卡片流
  • 别再只会用LSB了:聊聊DWT小波变换水印在Python里的实战(附代码避坑)
  • nuScenes数据实战:用Python脚本一键提取Lidar点云和未标注的Sweeps帧(附完整代码)
  • 嵌入式GPU如何实现边缘视觉应用820%性能跃迁:从架构解析到实战优化
  • XRDP远程桌面太卡?手把手教你优化Ubuntu 22.04的传输性能与画质
  • 告别踩坑:手把手教你为openEuler 22.03 LST配置RealVNC 6.11远程桌面(含序列号激活)
  • Bittensor:去中心化AI网络的架构、挑战与激励模型优化
  • 双系统Ubuntu 20.04装完没WiFi?别急着重装,试试这个Realtek网卡驱动手动编译大法
  • C51开发中汇编注释问题的解决方案
  • 汽车电子系统中GIC-600AE与CMN-600AE互连的安全机制解析
  • 从《炉石传说》猜卡组到垃圾邮件过滤:用Python手把手实现贝叶斯更新(附代码)
  • Mali Midgard GPU架构与OpenCL开发优化指南
  • 从‘封建网络’到‘选项框架’:手把手拆解5种主流HRL算法核心思想与PyTorch实现要点
  • openKylin双系统安装保姆级复盘:我踩过的三个坑(分区、引导、驱动)及完美解决方案
  • 别再硬改Seurat对象行名了!从ENSEMBL ID到Gene Symbol的正确转换姿势(附避坑代码)
  • 视觉着陆系统预测不确定性:从亚像素回归到RAIM完整性监测
  • 计算机视觉如何让外骨骼机器人实现预见式步态辅助控制
  • Linux下离线安装Mamba_SSM和Causal-Conv1d避坑指南(附CUDA 11.8 + PyTorch 2.0环境包)
  • 别再手动复制地址了!手把手教你配置Jupyter Notebook自动在Chrome/Edge浏览器打开(附路径查找技巧)
  • 紧急预警:92%的法律团队仍在用基础版Claude处理涉外合同(附GDPR/CCPA双合规审查Checklist)
  • 保姆级教程:用Python复现CDSM融合算法,在NuScenes上跑通3D目标检测
  • 【AI Agent健身行业落地实战指南】:2024年已验证的7大高转化场景与避坑清单
  • Silvaco TCAD 半导体器件仿真全攻略:从入门到精通
  • 基于滑模理论的异步电机控制系统设计与仿真
  • 基于随机森林与混淆矩阵的拉曼光谱香精识别模型