MotoJapan's Tech-Memo

技術めも

【行動認識 #8】OpenPoseのBodyParts推定をTensorFlowでCPU実行する方法 (Linux : Ubuntu 16.04 LTS)

OpenPoseのBodyParts推定をTensorFlowでCPU実行する方法について。(想定環境はUbuntu 16.04 LTS)

どうしてもTensorFlowで動かしたい人はやってみてもいいかも。(そんな人いる?)
個人的にはTensorFlowのアーキテクチャの方が好きですが。

OpenPoseの大枠を知りたいなら前回を参考。
motojapan.hateblo.jp

アプローチ

OpenPoseのBodyParts推定モデルはCaffeで提供されるので、これをTensorflowモデルに変換すればできるはず。

想定環境

手順

1. OpenPoseのCaffeモデルをダウンロード

本家からportable OpenPose demo 1.0.1.をダウンロード
この中に pose_deploy_linevec.prototxt(モデル情報)、pose_iter_440000.caffemodel(重み情報)が格納されている。

2. Caffeモデル/重みをTensorFlow用に変換

ここ(caffe-tensorflow)のconvert.pyで変換できるらしい。
このスクリプトで、.prototxt→.py、.caffemodel→.npyに変換される。
例えば、model.py/model.npyに変換したとする。

変換方法、変換済みファイルを扱う基本実装の参考
テンソルフローでfinetuning | OpenBook

3. Tensorflowモデルを読み込んでヒートマップを推論

下記で読み込み。
重要なのは、placeholderのテンソル順序で次の通り。
[batch_size, image_height, iamge_width, color_channel]

import tensorflow as tf
# networkはmodel.pyを編集して各自定義(例えばBodyPartsNet)
from model import BodyPartsNet 
# 入力(画像)用テンソルを準備
# [batch_size, image_height, iamge_width, color_channel]
x = tf.placeholder(tf.float32, [None, H, W, 3])
# 出力(ヒートマップ)用テンソルを準備
pred = net.layers['Mconv7_stage6_L2']
#モデルの読み込み
net = BodyPartsNet({'iamge': x})
sess = tf.Session()
sess.run(tf.initialize_all_variables()) 
#重みの読み込み
net.load('model.npy', sess)

後は、forwardのsession.runをすれば動くはず。

BodyParts出力順は本家の通り以下の順。

    POSE_COCO_BODY_PARTS {
        {0,  "Nose"},
        {1,  "Neck"},
        {2,  "RShoulder"},
        {3,  "RElbow"},
        {4,  "RWrist"},
        {5,  "LShoulder"},
        {6,  "LElbow"},
        {7,  "LWrist"},
        {8,  "RHip"},
        {9,  "RKnee"},
        {10, "RAnkle"},
        {11, "LHip"},
        {12, "LKnee"},
        {13, "LAnkle"},
        {14, "REye"},
        {15, "LEye"},
        {16, "REar"},
        {17, "LEar"},
        {18, "Bkg"},
    }

caffe-tensorflowエラー対策

caffe-tensorflowは環境によって時折エラーがでるのでいくつか対策が必要。

エラーケース1:TypeError: Descriptors should not be created directly, but only retrieved from their parent.

convert.pyでの変換時のエラー

TypeError: Descriptors should not be created directly, but only retrieved from their parent.

対策:
protobufのバージョン変更。

pip install protobuf==3.0.0b2

エラーケース2:TypeError: concat() got an unexpected keyword argument 'concat_dim'

networkにconcatが含まれる場合の実行時エラー

TypeError: concat() got an unexpected keyword argument 'concat_dim'

対策:
concatの呼び出し記述が古いのが原因。
tensorflow 1.0.0に対応した記述にNetwork.pyを変更(下記のような感じ)

    @layer
    def concat(self, inputs, axis, name):
-        return tf.concat(concat_dim=axis, values=inputs, name=name)
+        return tf.concat(axis=axis, values=inputs, name=name)

おまけ

1.Caffeの環境を構築するのが億劫な人にはいいかも
Caffe環境構築も大変だし。

2.windowsでは簡単には動かないと思う
理由は、tensorflowがwindows x python 2.7系に対応していない。
そして、convert.pyはpython 2.7系。

最近はiOS stand-aloneでも動かしたりしていて、320x320の画像は5秒くらいで認識できた。
需要があれば方法だけでも纏めようかなー。

以上。