(深度学习)YOLOPose:如何处理被遮挡的关键点并将json格式文件转为txt文本文件?

本文讲述了作者在竞赛项目中使用yolopose遇到的关键点标注问题,包括如何处理被遮挡的关键点和json文件转换为txt文件的过程,推荐labelme工具,并分享了数据标注的注意事项和关键点分类方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

半年前做比赛项目,其中涉及到了目标检测与姿态估计技术,于是采用了YOLOPose模型框架,当时训练模型时一度遇到难题(一不小心就熬到1,2点,真的累)。发表这篇文章是因为当时自己做项目也很迷,大概弄懂之后有人在b战和csdn里面私信问我如何解决,可做项目属实是比较忙,如今时间相对比较宽裕了,就给大家分享一下在标记过程中如何处理被遮挡的关键点以及如何将json文件转为txt文件(以下说明均以人体的17个关键点为例)。

1、标注工具的选择

标注工具推荐大家使用labelme,因为labelimg无法进行关键点的标记。labelme的下载与使用这里我不再赘述,有很多博客文章都详细介绍过,不了解的小伙伴可自行查阅一下。

顺便给大家提一嘴,大家在使用labelme标注的过程中最好打开save automatically(自动保存),因为这款软件不是很稳定,可能会闪退

2、数据标注注意点

(1)标注的图片保存路径不要存在中文

(2)所有图片的标注采用一个特定顺序,如先标记类别框,再标记关键点,且关键点的标记顺序也不能错乱,这样做是方便后续格式文件的转换;

(3)标注过程中如果一张图片有多个类别物体,则分别单独标记,如一张图片中有2个人,那就标完第一个人后再标记第二个人,不要混合标注(如先把框都标完再去标记关键点,这种做法会在后面转换格式文件时造成不必要的麻烦);

(4)类别可通过添加group_id值进行区分,如人类别的group_id = 1,猫类别的group_id = 2 等,如下图所示,当然如果你不想麻烦的话,可以在后续将json转换为txt格式文件时写几句代码自动添加上去。

3、关键点的处理

对于yolopose模型而言,关键点分为三种:(1)标记且正常显示的关键点;(2)标记但被遮挡的关键点;(3)未被标记的关键点。

三类关键点在yolo模型训练所需读取的txt格式文件中分别被标记为2,1,0。第一类和第三类都很好处理,那么如何处理被遮挡的关键点呢?

首先,第二类和第三类关键点对于我们标记的人而言其实是属于一类的,即都无法用人眼直接观察到,但区别在于被遮挡的关键点的位置我们是大概知道的,而不被标记的关键点我们是几乎不知道的,所以被遮挡的关键点要不要选择标记取决于2点:(1)它的位置是不是大概知道;(2)项目功能的精度与关键点的联系有多大,如果精度很大程度上取决于关键点,那么位置比较模糊的被遮挡关键点就可以不进行标记,反之则可以进行标记。对于两类关键点的区分大家可以参考下图(此处只是作为参考,具体要不要标注视自己的项目而定)

其次,在我们知道了被遮挡的关键点要不要标注之后,我们需要通过添加group_id值来区分三类关键点,不过我已经在后面的格式转换代码中对三类关键点做了区分处理,所以大家在标注时只需要对被遮挡的关键点添加group_id值即可。对于group_id值我填写的是1,但大家可任意选取,只需在后面的代码中进行更改就可以。

4、json格式文件信息简析

json格式文件如上图所示(很长,只截取了部分),这其中包含了很多信息,但不是所有信息都是我们需要的,我们所需要的是'shapes'这个信息数组以及'imageHeight'和'imageWidth'。'shapes'数组里面包含了标注的类别框和关键点信息,'imageHeight'与'imageWidth'则表示图片宽高。

5、json文件信息写入到txt文本文件

为什么要进行文件格式的转换是因为yolo模型在训练时只能识别读取到txt文本中的内容,转换代码我直接放在下面了,为了助于大家理解,我做了一定的注释,不懂的地方大家可留言讨论。

import json
import os

json_path = r'你的json文件存放路径'    # json文件路径
txt_path = r'你的txt文本文件存放路径'   # txt文本文件路径

# 关键点数组(这里我写的是人体的17个骨骼关键点,大家可以改成自己标注顺序的关键点数组)
pointsArr = ['nose', 'left_eye', 'right_eye', 'left_ear', 'right_ear', 'left_shoulder', 'right_shoulder',
             'left_elbow', 'right_elbow', 'left_wrist', 'right_wrist', 'left_hip', 'right_hip', 'left_knee',
             'right_knee', 'left_ankle', 'right_ankle']


# 坐标归一化,返回中心点坐标和宽高
def coordinates2yolo(xmin, ymin, xmax, ymax, img_w, img_h):
    x = abs(xmin + xmax) / (2.0 * img_w)
    y = abs(ymin + ymax) / (2.0 * img_h)
    w = abs(xmax - xmin) / (1.0 * img_w)
    h = abs(ymax - ymin) / (1.0 * img_h)
    return x, y, w, h


def writeJson(rootpath, rootpath1, filename):
    path = os.path.join(rootpath, filename + '.json')
    count = 0      # 记录一张图片中人数的多少
    index = 0      # data索引,用于区分json文件中的label值

    with open(path) as f:
        # 读取json格式文件并获取相应信息
        data = json.load(f)
        imageHeight = data['imageHeight']
        imageWidth = data['imageWidth']
        data = data['shapes']
        length = len(data)
        # print('length', length)

    # 遍历json文件,用变量count记录 data[i]['label']=’类别名‘ 的次数,以此说明图片中有几个人
    for i in range(0, length):
        # 类别名换成自己的类别,当有多个类别时,用关键字or进行连接
        # if data[i]['label'] == '类别名1' or data[i]['label'] == '类别名2'。。。
        if data[i]['label'] == '类别名':
            count += 1

    # 将json文件信息写入txt文本文件中
    file = open(os.path.join(rootpath1, filename + '.txt'), mode='w')
    for j in range(0, count):
        # 在txt文本文件中写入类别id、目标框中心坐标以及图片宽高
        file.write(str(data[index]['group_id']))
        file.write(" ")
        points = data[index]['points']
        xmin = points[0][0]
        ymin = points[0][1]
        xmax = points[1][0]
        ymax = points[1][1]
        x, y, w, h = coordinates2yolo(xmin, ymin, xmax, ymax, imageWidth, imageHeight)
        file.write(str(round(x, 6)))
        file.write(" ")
        file.write(str(round(y, 6)))
        file.write(" ")
        file.write(str(round(w, 6)))
        file.write(" ")
        file.write(str(round(h, 6)))
        file.write(" ")
        index += 1
        # 在txt文本文件中写入关键点坐标与对应id值
        for point in pointsArr:
            # print(index)
            if index < length:
                if data[index]['label'] == point:
                    point = data[index]['points']    # 获取关键点的坐标值
                    file.write(str(round(point[0][0] / imageWidth, 6)))
                    file.write(" ")
                    file.write(str(round(point[0][1] / imageHeight, 6)))
                    file.write(" ")
                    # data[index]['group_id'] == 1,表名为被遮挡的关键点,在txt文档中写入1
                    if data[index]['group_id'] == 1:
                        file.write('1.000000')
                        file.write(" ")
                    # data[index]['group_id'] != 1,表名为正常标记的关键点,在txt文档中写入2
                    else:
                        file.write('2.000000')
                        file.write(" ")
                    index += 1
                # 若data[index]['label'] != point,则写入(0, 0, 0),前两个代表坐标,最后一个‘0’代表此关键点未被标记
                else:
                    file.write('0.000000')
                    file.write(" ")
                    file.write('0.000000')
                    file.write(" ")
                    file.write('0.000000')
                    file.write(" ")
            else:
                file.write('0.000000')
                file.write(" ")
                file.write('0.000000')
                file.write(" ")
                file.write('0.000000')
                file.write(" ")
        file.write('\n')


# 读取path路径中的文件
filenames = os.listdir(json_path)
for item in filenames:
    # 以'.'为标志分割获取文件名
    filename = item.split('.')[0]
    print(filename)
    writeJson(json_path, txt_path, filename)

转换后的txt文本文件的内容如下所示

其中每一串数据的第一个值代表类别id,用于区分类别,后面紧跟的4个值代表类别目标框的四个角点坐标,之后的一连串数据则代表关键点信息,其中每三个为一组,前两个代表关键点坐标,后一个代表关键点类别。

OK,上述就是我对于如何处理被遮挡的关键点并将json格式文件转为txt文本文件操作的全过程,也是本次文章的全部内容,感谢大家阅读!

<think>好的,我现在需要回答用户关于如何使用Labelme标注遮挡关键点的问题。首先,我需要回忆Labelme的基本使用方法,尤其是关键点标注的部分。根据用户提供的引用内容,Labelme标注时需要先画一个矩形框,再标注关键点。那被遮挡关键点应该如何处理呢? 首先,用户可能想知道的是,当关键点被其他物体或自身遮挡时,是否仍然需要标注,以及如何标注。根据引用[1]和[2],Labelme关键点坐标是包含在标记框内的向量。那么,被遮挡关键点的位置可能需要估计,比如在人体的关节处,即使被衣服遮挡,也应该标注在正确的位置上。 然后,用户可能需要具体的步骤。例如,在标注时,是否需要在某个地方标记该关键点遮挡Labelme是否有这样的属性设置?根据引用[2],可能需要手动添加属性,比如“occluded”标签。或者,在标注时,使用不同的标签名称来区分遮挡情况,例如“left_eye_occluded”。 另外,用户可能关心数据转换的问题,比如转为YOLO格式时,被遮挡关键点信息是否会保留。引用[2]提到json转YOLO的步骤,可能需要确认转换脚本是否处理遮挡属性,或者在转换后的数据中如何表示被遮挡关键点。 还需要考虑实际操作的例子,比如如何在Labelme界面中添加被遮挡的标记。可能需要指导用户右键点击关键点,添加属性,或者修改标签名称。如果Labelme本身不支持,可能需要建议用户使用额外的字段或注释来记录遮挡信息。 最后,应该提醒用户保持标注的一致性,比如团队协作时统一使用相同的标注方法,在转换数据时确保遮挡信息不被丢失。可能还需要建议用户查看官方文档或社区讨论,寻找最佳实践。 总结回答的结构:首先说明处理遮挡关键点的基本方法,然后分步骤讲解具体操作,包括标注步骤、属性设置、数据转换注意事项,最后强调一致性和验证的重要性。同时,引用提供的资料,特别是关于标记框和关键点坐标的部分,以及json转YOLO的相关内容。</think>### 如何使用Labelme标注遮挡关键点? #### 1. **标注遮挡关键点的基本原则** - **估计位置**:即使关键点遮挡,仍需根据目标结构(如人体骨骼、物体边缘)推测其理论位置标注[^1]。 - **添加属性标识**:在Labelme中可为关键点添加自定义属性(如`occluded:true`),标注时右键关键点选择`Add Attribute`,输入遮挡状态[^2]。 #### 2. **具体操作步骤** 1. **绘制边界框**: 先用矩形框包裹目标(如人体),确保遮挡区域在框内。 2. **标注关键点**: - 点击`Create Point`标注可见关键点。 - 对遮挡点,同样点击目标应处位置,标注后右键该点添加属性(例如`occluded`)。 3. **属性设置示例**: ```json { "label": "left_shoulder", "points": [[x, y]], "occluded": true // 手动添加遮挡标识 } ``` #### 3. **数据转换注意事项** - **YOLO格式兼容性**: 转换工具(如`json2yolo`脚本)需自定义解析逻辑,将`occluded`属性映射到特定字段(如YOLO关键点格式的可见性标记`0/1`)[^2]。 - 示例YOLO行数据: ```text class_id x_center y_center width height px1 py1 visible1 px2 py2 visible2 ... ``` #### 4. **标注一致性建议** - **团队协作规范**:统一遮挡属性的命名(如`occluded`或`visibility`),避免后续训练数据歧义。 - **可视化验证**:转换后通过脚本或工具检查遮挡关键点是否保留属性(如图像中标记为半透明点)。
评论 58
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值