概要
tf-openposeを用いて骨格推定をして、その後3d-pose-estimatorを用いて3D姿勢推定をする一連の流れを解説します。また、それとともにハマった点とその解決方法を備忘録代わりに共有します。
tf-openposeについて
tf-openposeを用いれば手軽に骨格推定を行うことが可能です。

tf-openposeのインストール
git clone https://github.com/ildoonet/tf-pose-estimation
cd tf-pose-estimation
pip install -r requirements.txt
swigというC/C++で書かれたライブラリを多言語で利用できるようにするツールをインストールします。
brew install swig
次に学習済みのグラフをダウンロードします。
cd models/graph/cmu
bash download.sh
最後に
cd ~/tf-pose-estimation/tf_pose/pafprocess/
swig -python -c++ pafprocess.i && python3 setup.py build_ext --inplace
を実行してください。以上でtf-openposeのsettingは完了です。
tf-openposeの実行
cd ~/tf-pose-estimation
python run.py --model=mobilenet_thin --resize=432x368 --image=images/p2.jpg
3D Pose Estimation
 openposeを用いて画像から二次元の骨格情報を抽出することができました。これを3d-pose-estimationと組み合わせることで3次元空間での姿勢推定をすることが可能です。

この姿勢情報をunityなどと連携させることで3Dモデルを動画の人間の動きをトレースして動かすといったことが可能になります。
3D Pose Estimationのインストール
3D Pose Estimationは以前は先ほどクローンしてきた gitリポジトリ tf-pose-estimation に組み込まれていましたが現在は削除されています。これを利用するため(邪道であり、開発者様の意向に背いている気がしますが...)masterではなくbranchにあるコードを引用することにします。
まずはディレクトリを移動してブランチの一覧を取得します。
cd ~/tf-pose-estimation
git branch -r
一覧は以下です。
  origin/HEAD -> origin/master
  origin/dev/architecture-mobilenet-v2
  origin/devel
  origin/master
  origin/package
このうち、devel branchに切り替えてディレクトリを移動します。
git checkout devel
cd src
このsrcフォルダの中にあるliftingフォルダをクリップボードにコピーします。デスクトップなどにliftingフォルダを一度移すのでも構いません。
liftingフォルダをコピー(移動)することができたら、再びmasterに戻ります。
cd ~/tf-pose-estimation
git checkout master
次に、tf-pose-estimationフォルダの中にliftingフォルダをペーストしてください。
最後に仕上げです。run.pyの中身を以下のように書き換えてください(新しい.pyファイルを作っても良いです)。
import argparse
import logging
import sys
import time
import cv2
import numpy as np
import matplotlib.pyplot as plt
from tf_pose import common
from tf_pose.estimator import TfPoseEstimator
from tf_pose.networks import get_graph_path, model_wh
from lifting.prob_model import Prob3dPose
from lifting.draw import plot_pose
logger = logging.getLogger('TfPoseEstimator')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='tf-pose-estimation run')
    parser.add_argument('--image', type=str, default='./images/p1.jpg')
    parser.add_argument('--resolution', type=str, default='432x368', help='network input resolution. default=432x368')
    parser.add_argument('--model', type=str, default='mobilenet_thin', help='cmu / mobilenet_thin')
    parser.add_argument('--scales', type=str, default='[None]', help='for multiple scales, eg. [1.0, (1.1, 0.05)]')
    args = parser.parse_args()
    scales = ast.literal_eval(args.scales)
    w, h = model_wh(args.resolution)
    e = TfPoseEstimator(get_graph_path(args.model), target_size=(w, h))
    # estimate human poses from a single image !
    image = common.read_imgfile(args.image, None, None)
    # image = cv2.fastNlMeansDenoisingColored(image, None, 10, 10, 7, 21)
    t = time.time()
    humans = e.inference(image, scales=scales)
    elapsed = time.time() - t
    logger.info('inference image: %s in %.4f seconds.' % (args.image, elapsed))
    image = TfPoseEstimator.draw_humans(image, humans, imgcopy=False)
    logger.info('3d lifting initialization.')
    poseLifting = Prob3dPose('./lifting/models/prob_model_params.mat')
    image_h, image_w = image.shape[:2]
    standard_w = 640
    standard_h = 480
    pose_2d_mpiis = []
    visibilities = []
    for human in humans:
        pose_2d_mpii, visibility = common.MPIIPart.from_coco(human)
        pose_2d_mpiis.append([(int(x * standard_w + 0.5), int(y * standard_h + 0.5)) for x, y in pose_2d_mpii])
        visibilities.append(visibility)
    pose_2d_mpiis = np.array(pose_2d_mpiis)
    visibilities = np.array(visibilities)
    transformed_pose2d, weights = poseLifting.transform_joints(pose_2d_mpiis, visibilities)
    pose_3d = poseLifting.compute_3d(transformed_pose2d, weights)
    for i, single_3d in enumerate(pose_3d):
        plot_pose(single_3d)
    plt.show()
    pass
3D Pose Estimationの実行
python run.py --model=mobilenet_thin --resize=432x368 --image=images/p2.jpg
上記のコマンドを出力すれば以下の3d骨格プロットが得られます。人間が2人座っている画像の骨格を抽出したのでプロット画像も二つ出力されます。

骨格情報はpose_3dに入っています。サイズとともに出力すれば、
(2, 3, 17)
[[[  71.48704986  -58.26023795 -320.11229876 -183.15640429  216.8238699
    -11.48274567    4.4091282    82.49019393   39.70915699   -2.9661351
     27.84004239  205.97311297  362.78178305  171.281097   -122.7005334
   -202.29460299 -130.81136751]
  [ 113.24948881  194.50322367 -142.71512489 -148.85424371   31.99573068
   -302.24754322 -251.21557536  133.0771608    75.74529577  -14.18464889
     21.06375219    9.19473249  -60.88986293 -124.23290074  164.22177682
    206.25643283   58.97202917]
  [ -96.65909433  -58.91258719 -197.41306904 -613.05761654  -84.34510465
   -211.71201318 -647.53588523  126.09740822  363.46207416  413.2905669
    528.89131252  358.09240553  112.7854445   -58.77230858  318.24367281
     58.29690181  -41.64239587]]
 [[  91.95496863  -31.66337898 -316.19207754 -184.66998433  227.81491288
    -12.584797    -14.16200051   93.84625488   42.73471689   -2.67287331
     12.31833787  206.851387    344.64506511  164.43221306 -119.26256458
   -197.9342645  -122.32756546]
  [ 139.42261847  219.89602532 -162.84033638 -181.27356255   58.94920292
   -336.55624415 -283.76607766  149.11535314   83.52183789   -7.40499281
     30.51344165   14.21467296  -69.95918306 -120.88036364  172.58527775
    200.78417873   49.94852315]
  [-101.36476255  -62.85719618 -176.51123952 -564.96819735  -93.23573586
   -195.51713744 -604.7114395   113.59787852  344.77517494  387.22147932
    498.07333475  339.10907614  105.01815399  -57.24477445  296.2909129
     49.35912406  -34.22891739]]]
となっています。(人数, 三次元, 部位座標)という内訳です。部位座標はindexを0~16として
0 尻(尾てい骨)
1 右尻(右足付け根)
2 右ひざ
3 右足首
4 左尻(左足付け根)
5 左ひざ
6 左足首
7 脊椎
8 胸
9 首/鼻
10 頭
11 左肩
12 左ひじ
13 左手首
14 右肩
15 右ひじ
16 右手首
になっています。
本記事は以上です!お疲れ様でした!
参考URL
https://qiita.com/keel/items/0d64167850566586d22a
https://qiita.com/mdo4nt6n/items/d9523aff14dd9fb70c37
参考github
https://github.com/DenisTome/Lifting-from-the-Deep-release
https://github.com/ildoonet/tf-pose-estimation
