当你准备训练一个YOLOv8-Pose模型时,最头疼的问题之一就是数据格式的兼容性。Labelme作为一款流行的标注工具,生成的JSON文件格式与YOLOv8-Pose所需的TXT格式完全不同。这种格式差异会导致很多开发者卡在数据准备阶段,浪费大量时间在格式转换上。
我最近就遇到了这个痛点。当时我需要训练一个自定义的人体姿态估计模型,用Labelme标注了几百张图片后才发现,YOLOv8-Pose根本无法直接使用这些标注。经过一番摸索,终于找到了一套完整的转换方案,现在分享给大家。
Labelme的JSON格式存储的是每个关键点的绝对坐标和形状信息,而YOLOv8-Pose需要的TXT文件则要求归一化的中心坐标、宽高比,以及关键点的相对位置。这种差异不仅仅是简单的数据结构变化,还涉及到坐标系的转换和归一化处理。
完整的转换过程可以分为三个主要步骤,形成一个清晰的转换流水线:
第一步是将Labelme的原始JSON格式转换为COCO格式。COCO作为一种广泛使用的中间格式,具有良好的通用性。这个步骤的关键在于正确处理关键点的分组和边界框的计算。
第二步是从COCO格式转换到YOLOv8-Pose专用的TXT格式。这里需要特别注意坐标归一化和关键点顺序的调整。YOLOv8-Pose对关键点的排列有特定要求,必须严格按照它的规范来组织数据。
第三步是验证转换结果的准确性。这一步经常被忽视,但至关重要。我们需要将转换后的TXT文件可视化到原图上,检查关键点和边界框的位置是否正确。
为了让大家更清楚地理解这个过程,我画了一个简单的流程图:
Labelme JSON → COCO格式 → YOLOv8-Pose TXT → 可视化验证
让我们先来看第一个关键步骤:Labelme JSON转COCO格式。这个转换的核心是一个Python脚本,我将其命名为labelme2coco.py。
这个脚本的核心是一个Lableme2CoCo类(注意这里有个拼写错误,应该是Labelme2CoCo,但为了保持与代码一致,我们暂时保留这个名称)。这个类负责处理所有的转换逻辑。
转换过程中有几个关键点需要特别注意:
首先是关键点的分组问题。在Labelme中,同一个人的不同关键点通过group_id进行关联。我们的脚本需要根据group_id将属于同一个人的关键点组合在一起。
其次是边界框的计算。Labelme可能提供矩形标注,也可能没有。如果没有,我们需要根据所有关键点的位置自动计算出一个合适的边界框。这里采用的方法是找出所有关键点的最小和最大x、y值,然后计算出包围盒。
最后是COCO格式的特殊要求。COCO要求每个关键点有三个值:x坐标、y坐标和可见性标志(2表示可见,1表示遮挡,0表示不可见)。我们的脚本需要确保这些信息被正确转换。
完成第一步转换后,我们得到了COCO格式的JSON文件。接下来是第二个关键步骤:将这些文件转换为YOLOv8-Pose可以直接使用的TXT格式。
这个转换由convert_coco_json函数完成。它接受COCO格式的JSON文件路径和输出目录作为参数。函数内部会处理以下几个关键操作:
坐标归一化是这一步骤的核心。YOLOv8-Pose要求所有坐标都是相对于图像宽高的比例值,范围在0到1之间。我们的脚本需要将COCO中的绝对坐标转换为这种相对坐标。
关键点顺序的调整也很重要。YOLOv8-Pose有自己定义的关键点顺序,可能与COCO的标准顺序不同。我们需要确保关键点按照YOLOv8-Pose期望的顺序排列。
输出格式方面,YOLOv8-Pose的TXT文件每行代表一个对象,包含以下信息:
转换完成后,我们必须验证结果的准确性。这一步经常被开发者忽略,但却至关重要。一个简单的可视化脚本可以帮助我们快速发现问题。
我编写了一个PoseVisualization.py脚本,它能够将TXT文件中的标注信息绘制到原始图像上。这个脚本会做以下几件事:
读取TXT文件中的标注信息,包括边界框和关键点坐标。由于这些坐标是归一化的,需要先将其转换回绝对坐标才能在图像上绘制。
绘制边界框。使用OpenCV的rectangle函数,根据转换后的坐标画出人物的包围盒。
绘制关键点和连接线。每个关键点用不同颜色的圆点表示,然后按照人体骨骼结构连接相关关键点。这样我们可以直观地看到整个人体姿态。
通过这种可视化,我们可以立即发现转换过程中可能出现的问题,比如关键点位置偏移、边界框大小不合适等。我在第一次转换时就发现有几个关键点的顺序错了,幸亏有这个验证步骤才及时发现。
完成标注文件的转换后,还有一个容易遗漏的步骤:整理配套的图片文件。YOLOv8-Pose训练时需要图片和标注文件保持一致的目录结构和文件名对应关系。
我写了一个简单的pickImg.py脚本来自动完成这项工作。它会:
扫描原始图片目录,找出所有JPG文件。然后检查转换后的TXT目录,找出对应的标注文件。只复制那些有对应标注文件的图片到目标目录。
这样确保了训练集中的每个图片都有对应的标注,避免了训练时出现图片与标注不匹配的问题。
在实际操作中,我遇到了几个典型问题,这里分享给大家:
第一个问题是关键点顺序错误。COCO和YOLOv8-Pose的关键点顺序略有不同,直接转换会导致姿态错乱。解决方案是仔细对照两者的关键点定义,在转换时重新排序。
第二个问题是边界框计算不准确。当Labelme标注中没有显式提供矩形框时,自动计算的包围盒可能过大或过小。我通过添加一定的padding解决了这个问题。
第三个问题是图片和标注文件不匹配。有时因为文件名不一致或路径问题,会导致训练时找不到对应的标注。建立严格的命名规范和目录结构可以避免这个问题。
性能方面,当处理大量数据时,纯Python的实现可能较慢。可以考虑使用多进程或优化关键计算步骤来提高转换速度。
为了提高效率,我将所有转换步骤整合成了一个自动化流程。这个流程包括:
一个主控制脚本,按顺序调用各个转换步骤。添加了日志记录功能,方便追踪转换过程中的问题。增加了错误处理机制,当某一步失败时能够 gracefully 退出。
对于大型数据集,我还添加了并行处理支持。可以将数据集分成多个部分,同时在多个进程中进行转换,大大提高了处理速度。
这个自动化流程我已经在多个实际项目中应用过,转换上千张图片的标注只需要几分钟时间,准确率也非常高。