Python——计算人体关节角

 在对人体模型进行分析时有时需要对人体模型的一些关节角度进行分析,这里主要介绍我自己使用的计算人体关节角度的程序。

人体模型

在计算人体关节角度的时候需要首先明确自己使用的是哪种人体模型,弄清楚需要计算的关键点的索引。
这里我使用的是SMPLX人体模型,该人体模型对人手的动作和面部表情有了更加细致的表达。
需要了解SMPLX人体模型的可以参考:Expressive Body Capture: 3D Hands, Face, and Body from a Single Image
里面包含了文献的翻译和项目的地址。

创建人体模型

这里的人体模型参数从我之前存储的pkl文件中读取的,你们也可以自己将人体模型的参数传入

model = smplx.create(args.model_folder, model_type='smplx',
                         gender=gender, ext='npz',
                         num_pca_comps=args.num_pca_comps,
                         create_global_orient=True,
                         create_body_pose=True,
                         create_betas=True,
                         create_left_hand_pose=True,
                         create_right_hand_pose=True,
                         create_expression=True,
                         create_jaw_pose=True,
                         create_leye_pose=True,
                         create_reye_pose=True,
                         create_transl=True
                         )
with open(osp.join(fitting_dir, img_name, '000.pkl'), 'rb') as f:
    param = pickle.load(f)
torch_param = {}
for key in param.keys():
    if key in ['pose_embedding', 'camera_rotation', 'camera_translation']:
        continue
    else:
        torch_param[key] = torch.tensor(param[key])

output = model(return_verts=True, return_full_pose=True, **torch_param)
vertices = output.vertices.detach().cpu().numpy().squeeze()
joints = output.joints.detach().cpu().numpy().squeeze()                         

向量的表示

计算人体模型的关节角其实就是计算两个向量之前的夹角
参考python——向量的表示及相关计算

计算关节角并绘制

这里只要你输入需要绘制的关节和顶点调用下面的函数即可绘制,计算关节的角度需要你自己知道部位的索引,这里我计算的是肘部、脚踝和膝盖处的关节角

def plot_humanmodel(joints_input, vertices_input):
    verts = vertices_input.detach().cpu().numpy()
    joint = joints_input.detach().cpu().numpy()
    verts = (verts + 1) / 2 * 255
    joint = (joint + 1) / 2 * 255

    verts_x = verts[:, :, 0]
    verts_y = verts[:, :, 2]
    verts_z = verts[:, :, 1]
    joints_x = joint[:, :, 0]
    joints_y = joint[:, :, 2]
    joints_z = joint[:, :, 1]

    x_max = np.max([np.max(verts_x), np.max(joints_x)])
    x_min = np.min([np.min(verts_x), np.min(joints_x)])

    y_max = np.max([np.max(verts_y), np.max(joints_y)])
    y_min = np.min([np.min(verts_y), np.min(joints_y)])

    z_max = np.max([np.max(verts_z), np.max(joints_z)])
    z_min = np.min([np.min(verts_z), np.min(joints_z)])

    def calculate_Vector(coord1, coord2, coord3):
        vec1_x = joints_x[0, coord1] - joints_x[0, coord2]
        vec1_y = joints_y[0, coord1] - joints_y[0, coord2]
        vec1_z = joints_z[0, coord1] - joints_z[0, coord2]

        vec2_x = joints_x[0, coord3] - joints_x[0, coord2]
        vec2_y = joints_y[0, coord3] - joints_y[0, coord2]
        vec2_z = joints_z[0, coord3] - joints_z[0, coord2]

        v = [str(vec1_x), str(vec1_y), str(vec1_z)]
        w = [str(vec2_x), str(vec2_y), str(vec2_z)]

        vec1 = Vector(v)
        vec2 = Vector(w)

        return vec1.angle_with(vec2)

    for i in range(verts.shape[0]):
        fig = plt.figure()
        ax = Axes3D(fig)
        ax.view_init(elev=20, azim=-120)  # 调整观察角度

        ax.scatter(verts_x[i, :], verts_y[i, :], verts_z[i, :], s=0.1, c='y')  # 画顶点
        ax.scatter(joints_x[i, :], joints_y[i, :], joints_z[i, :], s=3, c='r')
        for n in range(len(joints_x[i, :])):
            ax.text(joints_x[i, n] + 2, joints_y[i, n] + 2, joints_z[i, n] + 2, '{}'.format(n), fontsize=7)  # 画关键点
        line_map = [[9, 10], [10, 11], [12, 13], [13, 14], [14, 19], [11, 22],
                    [2, 3], [3, 4], [5, 6], [6, 7]]
        for i in range(len(line_map)):
            first_point = line_map[i][0]
            second_point = line_map[i][1]
            line_x = [joints_x[0, first_point], joints_x[0, second_point]]
            line_y = [joints_y[0, first_point], joints_y[0, second_point]]
            line_z = [joints_z[0, first_point], joints_z[0, second_point]]
            ax.plot(line_x, line_y, line_z, c='r')
        ax.set_xlim3d(x_min - 50, x_max + 50)
        ax.set_ylim3d(y_min - 50, y_max + 50)
        ax.set_zlim3d(z_max + 50, z_min - 50)
        print('Left knee joint angle is:', calculate_Vector(9, 10, 11))
        print('Light ankle joint angle is', calculate_Vector(10, 11, 22))
        print('Left elbow joint angle is', calculate_Vector(2, 3, 4))
        print('Right knee joint angle is:', calculate_Vector(12, 13, 14))
        print('Right ankle joint angle is', calculate_Vector(13, 14, 19))
        print('Right elbow joint angle is', calculate_Vector(5, 6, 7))

        plt.show()         

实现效果

在这里插入图片描述
计算出的关节角:

  • Right knee joint angle is: 74.08961970394783
  • Right ankle joint angle is 137.60285555069925
  • Right elbow joint angle is 102.81769110442562
  • Left knee joint angle is: 90.00728594464235
  • Left ankle joint angle is 120.49029637105222
  • Left elbow joint angle is 114.40360362550719
  • 8
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值