做3D pose的同学经常需要可视化单帧的3D关键点结果来进行调试。

本文实验目的,用matplotlib把一组点画成3D火柴人。注意:我画的都是17关节点的,其他数量的关节点请对照着改。

输入

[[9.07790224, -72.22343977, -76.2384473, -14.76985357, 93.36553108,
  37.00967529, 50.77555181, 23.629042, -8.17606904, -55.17824984,
  -20.64523825, 128.93648202, 161.99088735, 137.73662061, -105.13621915,
  -173.42035763, -139.20512344], # axis-x
 [17.67119202, 117.5121073, 80.80944741, 151.41362938, -82.1697299,
  -108.63658419, -62.51112022, 25.61594197, -0.93282285, -57.61404975,
  -33.30759321, -92.44999831, -192.53606268, -213.71209574, 110.08766607,
  213.40229899, 135.20572051], # axis-y
 [-30.39547729, 26.18883494, -502.97420581, -927.51450811, 24.75648722,
  -501.73217965, -929.53198007, 196.18478224, 435.39843872, 489.66153962,
  610.95493383, 412.93642629, 224.81752081, 97.52059155, 415.66381442,
  258.698571, 97.77770797 # axis-z
]]

 输出

代码:

# author: muzhan
import matplotlib
import numpy as np
 
matplotlib.use('Agg')
import matplotlib.pyplot as plt
 
ap1 = [[9.07790224, -72.22343977, -76.2384473, -14.76985357, 93.36553108,
        37.00967529, 50.77555181, 23.629042, -8.17606904, -55.17824984,
        -20.64523825, 128.93648202, 161.99088735, 137.73662061, -105.13621915,
        -173.42035763, -139.20512344],
       [17.67119202, 117.5121073, 80.80944741, 151.41362938, -82.1697299,
        -108.63658419, -62.51112022, 25.61594197, -0.93282285, -57.61404975,
        -33.30759321, -92.44999831, -192.53606268, -213.71209574, 110.08766607,
        213.40229899, 135.20572051],
       [-30.39547729, 26.18883494, -502.97420581, -927.51450811, 24.75648722,
        -501.73217965, -929.53198007, 196.18478224, 435.39843872, 489.66153962,
        610.95493383, 412.93642629, 224.81752081, 97.52059155, 415.66381442,
        258.698571, 97.77770797]]
 
ap = np.array(ap1, dtype='float32').T / 1000.0
np_data = ap
xp = np_data.T[0].T
yp = np_data.T[1].T
zp = np_data.T[2].T  + 0.5
 
ax = plt.axes(projection='3d')
 
radius = 1.7
ax.set_xlim3d([-radius / 2, radius / 2])
ax.set_zlim3d([0, radius])
ax.set_ylim3d([-radius / 2, radius / 2])
ax.view_init(elev=15., azim=70)
ax.dist = 7.5
 
# 3D scatter
ax.scatter3D(xp, yp, zp, cmap='Greens')
 
# left leg, node [0, 1, 2, 3]
ax.plot(xp[0:4], yp[0:4], zp[0:4], ls='-', color='red')
 
# right leg
ax.plot(np.hstack((xp[0], xp[4:7])),
        np.hstack((yp[0], yp[4:7])),
        np.hstack((zp[0], zp[4:7])),
        ls='-', color='blue')
 
# spine, node [0, 7, 8, 9, 10]
ax.plot(np.hstack((xp[0], xp[7:11])),
        np.hstack((yp[0], yp[7:11])),
        np.hstack((zp[0], zp[7:11])),
        ls='-', color='gray')
 
# right arm, node [8, 11, 12, 13]
ax.plot(np.hstack((xp[8], xp[11:14])),
        np.hstack((yp[8], yp[11:14])),
        np.hstack((zp[8], zp[11:14])),
        ls='-', color='blue')
 
# left arm, node [8, 14, 15, 16]
ax.plot(np.hstack((xp[8], xp[14:])),
        np.hstack((yp[8], yp[14:])),
        np.hstack((zp[8], zp[14:])),
        ls='-', color='red')
plt.savefig('skeleton.jpg')

上面那段代码就够画出骨架了~

下面介绍另一种形式的输出关节点:

3D关节点通常有过一定的线性变换,所以有时候画出来图案比较奇怪,可能是需要调节scale以及平移。比如下面这个栗子,稍微需要做个转置以及往下平移:

import matplotlib
import numpy as np
 
matplotlib.use('Agg')
import matplotlib.pyplot as plt
 
ap0 = [[-0.00001, -0.00002, 1.00830],
       [0.14475, -0.07537, 0.99674],
       [0.13747, -0.10477, 0.51222],
       [0.05090, -0.27371, 0.07246],
       [-0.14476, 0.07535, 1.01964],
       [-0.19476, -0.03135, 0.54859],
       [-0.33582, -0.27418, 0.14530],
       [0.03465, 0.07187, 1.27154],
       [0.08203, 0.09819, 1.55611],
       [0.13682, 0.16097, 1.71822],
       [0.09326, 0.02394, 1.77841],
       [-0.10811, 0.13847, 1.54135],
       [-0.40501, 0.27080, 1.54436],
       [-0.48869, 0.47729, 1.79511],
       [0.21069, -0.01737, 1.48483],
       [0.39367, -0.21920, 1.31686],
       [0.63089, -0.16669, 1.51139]]
 
ap = np.array(ap0, dtype='float32')
np_data = ap
xp = np_data.T[0].T
yp = np_data.T[1].T
zp = np_data.T[2].T
 
ax = plt.axes(projection='3d')
 
radius = 1.7
ax.set_xlim3d([-radius / 2, radius / 2])
ax.set_zlim3d([0, radius])
ax.set_ylim3d([-radius / 2, radius / 2])
ax.view_init(elev=15., azim=70)
ax.dist = 7.5
 
# 3D scatter
ax.scatter3D(xp, yp, zp, cmap='Greens')
 
# left leg, node [0, 1, 2, 3]
ax.plot(xp[0:4], yp[0:4], zp[0:4], ls='-', color='red')
 
# right leg
ax.plot(np.hstack((xp[0], xp[4:7])),
        np.hstack((yp[0], yp[4:7])),
        np.hstack((zp[0], zp[4:7])),
        ls='-', color='blue')
 
# spine, node [0, 7, 8, 9, 10]
ax.plot(np.hstack((xp[0], xp[7:11])),
        np.hstack((yp[0], yp[7:11])),
        np.hstack((zp[0], zp[7:11])),
        ls='-', color='gray')
 
# right arm, node [8, 11, 12, 13]
ax.plot(np.hstack((xp[8], xp[11:14])),
        np.hstack((yp[8], yp[11:14])),
        np.hstack((zp[8], zp[11:14])),
        ls='-', color='blue')
 
# left arm, node [8, 14, 15, 16]
ax.plot(np.hstack((xp[8], xp[14:])),
        np.hstack((yp[8], yp[14:])),
        np.hstack((zp[8], zp[14:])),
        ls='-', color='red')
plt.savefig('skeleton.jpg')

输出为:

文章知识点与官方知识档案匹配,可进一步学习相关知识