Human36M骨架

关于数据集的详细信息可以在这篇blog找到,本文主要讲Huamn36m数据集的骨架节点,以及怎么通过expmap旋转信息得到每个节点在三维空间的坐标

Human36M数据

在这里插入图片描述
在这里插入图片描述

0.0000000,0.0000000,0.0000000,-0.0000001,-0.0000000,-0.0000002,0.3978439,-0.4166636,0.1027215,-0.7767256,-0.0000000,-0.0000000,0.1704115,0.3078358,-0.1861640,0.3330379,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,0.0679339,0.2255526,0.2394881,-0.0989492,-0.0000000,-0.0000000,0.0677801,-0.3607298,0.0503249,0.1819232,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,0.3236777,-0.0476493,-0.0651256,-0.3150051,-0.0665669,0.3188994,-0.5980227,-0.1190833,-0.3017127,1.2270271,-0.1010960,0.2072986,-0.0000000,-0.0000000,-0.0000000,-0.2578378,-0.0125206,2.0266378,-0.3701521,0.0199115,0.5594162,-0.4625384,-0.0000000,-0.0000000,0.1653314,-0.3952765,-0.1731570,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,2.7825687,-1.4196042,-0.0936858,-1.0348599,-2.7419815,0.4518218,-0.3902033,-0.0000000,-0.0000000,0.0597317,0.0547002,0.0445105,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000
0.2240568,-0.0276901,-0.7433901,0.0004407,-0.0020624,0.0002131,0.3974636,-0.4157083,0.1030248,-0.7762963,-0.0000000,-0.0000000,0.1697988,0.3087364,-0.1863863,0.3327336,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,0.0689423,0.2282812,0.2395958,-0.0998311,-0.0000000,-0.0000000,0.0672752,-0.3615943,0.0505299,0.1816492,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,0.3223563,-0.0481131,-0.0659720,-0.3145134,-0.0656419,0.3206626,-0.5979006,-0.1181534,-0.3033383,1.2269648,-0.1011873,0.2057794,-0.0000000,-0.0000000,-0.0000000,-0.2590978,-0.0141497,2.0271597,-0.3699318,0.0128547,0.5556172,-0.4714990,-0.0000000,-0.0000000,0.1603251,-0.4157299,-0.1667608,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,2.7811005,-1.4192915,-0.0932141,-1.0294687,-2.7323222,0.4542309,-0.4048152,-0.0000000,-0.0000000,0.0568960,0.0525994,0.0493068,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000,-0.0000000

这个数据集中每个txt文件就是一个动作序列,文件中的行数表示总共帧数(上面显示的是S1中directions_1的前两行数据),列数为99,其中前三列表示每一帧根结点的偏移量(这个就是position三维坐标),后面的96列表示了32的骨架节点的旋转信息,用指数映射的方法表示,它具体的物理意义可以学习这个,按照我的理解就是每一个三维向量的单位向量表示这个结点的旋转轴方向,每个三维向量的范数就表示绕着旋转轴旋转的角度大小,当前节点旋转以后对自身并没有什么影响,但是会影响它的子节点的方向。
下面的信息中:
parent表示每一个节点的父节点,数组的索引表示当前节点序号,数组的值表示当前节点父节点的序号(根结点比较特殊,它的父节点序号为-1,无意义)。

 parent = np.array([0, 1, 2, 3, 4, 5, 1, 7, 8, 9, 10, 1, 12, 13, 14, 15, 13,
                       17, 18, 19, 20, 21, 20, 23, 13, 25, 26, 27, 28, 29, 28, 31]) - 1

offset表示每个骨架节点对应的骨头的向量,有的骨架节点对应骨头长度为0,比如根节点或者一些只用来改变子节点方向的节点。

					   [0., 0., 0.],
                       [-132.95, 0., 0.],
                       [0., -442.89, 0.],
                       [0., -454.21, 0.],
                       [0., 0., 162.77],
                       [0., 0., 75.],
                       [132.95, 0., 0.],
                       [0., -442.89, 0.],
                       [0., -454.21, 0.],
                       [0., 0., 162.77],
                       [0., 0., 75.],
                       [0., 0., 0.],
                       [0., 233.38, 0.],
                       [0., 257.08, 0.],
                       [0., 121.13, 0.],
                       [0., 115., 0.],
                       [0., 257.08, 0.],
                       [0., 151.03, 0.],
                       [0., 278.88, 0.],
                       [0., 251.73, 0.],
                       [0., 0., 0.],
                       [0., 0., 100.],
                       [0., 137.5, 0.],
                       [0., 0., 0.],
                       [0., 257.08, 0.],
                       [0., 151.03, 0.],
                       [0., 278.88, 0.],
                       [0., 251.73, 0.],
                       [0., 0., 0.],
                       [0., 0., 100.],
                       [0., 137.5, 0.],
                       [0., 0., 0.]

expmapInd表示每个节点对应的旋转信息的索引。

expmapInd = np.split(np.arange(4, 100) - 1, 32)

Human36M骨架图

h36m的32个骨架节点图
可以看到该图中实际的节点只有25个,其中有几个是重合的,0,11重合,这里11的父节点是0,但是它的offset为0,所以与0重合,它使用来改变12的方向的。这里的16,13,24也重合,但这里不同的是16和24的父节点并不是13,而是12,其实这里的操作是,16,13,24的offset都一样([0., 257.08, 0.])所以最后计算出的位置也一样,换句话说相当于从12这个节点长出来的三根长度相同的骨头重合在一起,不同的地方是三根骨头末端节点的方向朝向不一样,三个朝向代表了从这里即将长出的骨头的朝向,对应着上图分别是17,14,25。
23和31两个节点没啥用,因为它们没有子节点了,并且本身的offset为0。

算出一帧中每个骨架节点的三维坐标

先简单描述计算过程,整个过程需要用到前面的parent列表和offset列表。第一步我们需要把expmap表示转换成rotmat旋转矩阵。然后递归的算出每个节点关于世界坐标系的旋转矩阵(与该节点本身包含的旋转信息无关,只跟它的父节点,爷爷节点……有关),用这个旋转矩阵左乘该节点的offset再加上父节点的坐标向量得到自己的坐标向量。
代码如下所示:

xyzStruct = [dict() for x in range(njoints)]
    for i in np.arange(njoints):
        if i == 0:
            xangle = angles[0]
            yangle = angles[1]
            zangle = angles[2]
            thisPosition = np.array([xangle, yangle, zangle])  #全局的偏移
        else:
            thisPosition = np.array([0, 0, 0])

        r = angles[expmapInd[i]]  #第i个节点的expmap

        thisRotation = data_utils.expmap2rotmat(r)  #将expmap转化为旋转矩阵

        if parent[i] == -1:  # Root node
            xyzStruct[i]['rotation'] = thisRotation
            xyzStruct[i]['xyz'] = np.reshape(offset[i, :], (1, 3)) + thisPosition #如果是根结点,那它没有旋转信息,只需要加上最初的坐标偏移
        else:
            xyzStruct[i]['xyz'] = (offset[i, :] + thisPosition).dot(xyzStruct[parent[i]]['rotation']) + \
                                  xyzStruct[parent[i]]['xyz'] #如果不是根结点,则需要根据父节点保存的旋转信息将旋转后坐标系下的坐标offset变成跟父节点一样的坐标系下(世界坐标系)的坐标,然后把父节点的坐标当做偏移量,再相加得到世界坐标系下的坐标。
            xyzStruct[i]['rotation'] = thisRotation.dot(xyzStruct[parent[i]]['rotation'])  #改变当前节点的旋转信息,因为当前保存的是基于父节点的旋转,要想得到基于世界坐标系的旋转就需要右乘父节点的旋转信息(递归)

    xyz = [xyzStruct[i]['xyz'] for i in range(njoints)]
    xyz = np.array(xyz).squeeze()

其中expmap如何变成rotmat可以学习这个
代码如下所示:

#知乎讲解:https://www.zhihu.com/question/356466246/answer/2473399508
def expmap2rotmat(r):
    """
    Converts an exponential map angle to a rotation matrix
    Matlab port to python for evaluation purposes
    This is also called Rodrigues' formula
    https://github.com/asheshjain399/RNNexp/blob/srnn/structural_rnn/CRFProblems/H3.6m/mhmublv/Motion/expmap2rotmat.m

    Args
      r: 1x3 exponential map
    Returns
      R: 3x3 rotation matrix
    """
    theta = np.linalg.norm(r)   #计算旋转的角度
    r0 = np.divide(r, theta + np.finfo(np.float32).eps)   # 计算围绕哪个单位向量旋转
    r0x = np.array([0, -r0[2], r0[1], 0, 0, -r0[0], 0, 0, 0]).reshape(3, 3)    # 表示旋转单位向量的反对称矩阵的上三角部分
    r0x = r0x - r0x.T    # 表示整个旋转单位向量的反对称矩阵
    R = np.eye(3, 3) + np.sin(theta) * r0x + (1 - np.cos(theta)) * (r0x).dot(r0x)  #得到expmap对应的旋转矩阵
    return R
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值