OpenPose のDNN部分をChainer CPUで動かす。

OpenPose のDNN部分をChainer CPUで動かす。

今回はmacで、話題の人検出 OpenPoseをchainerを使って実行してみます。
(全体ではなく検出ヒートマップを生成する一部の機能になります)

1.Caffeの学習済みモデルをダウンロードする
2.ChainerからCaffeのモデルを読み込む
3.Chainerのネットワークに画像を適用する

CVPR2017で発表された単眼カメラによる骨格推定アルゴリズムのOpenPose、すでにUbuntu, Windowsでのリアルタイムな処理が実現することが報告されています。ですがGPUが必要だったりMacは対応してなかったりなので、どうにかMac やCPUでも動かせないかと思い、CaffeのモデルをChainerで読み込んで前半のDNNの部分だけ実行してみます。

環境 (Linuxでも動くはず)

Mac book Pro  (2.7 GHz Intel Core i5,16 GB 1867 MHz DDR3)
Python2.7 (Chainer, Numpy)

1.Caffeの学習済みモデルをダウンロードする

こちらにWindows向けのバイナリがあるのでダウンロードします。
(直リンクが気になる方は https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/installation.md の中程にあるDownload and unzip the portable OpenPose demo 1.0.1.から落としてください

2.ChainerからCaffeのモデルを読み込む

今回は、骨格18点を推定するCOCOモデルを使用します。(MPIモデルも同様の手順で可能)
Caffeのモデルが以下のディレクトリに保存されています。
OpenPose_demo_1.0.1/models/pose/coco/pose_iter_440000.caffemodel

これをchainerから読み込みます。

from chainer.functions import caffe
func = caffe.CaffeFunction('pose_iter_440000.caffemodel')

3.Chainerのネットワークに画像を適用する

OpenPose_demo_1.0.1/models/pose/coco/pose_deploy_linevec.prototxt
を読むとネットワークの構成が書かれており、最後の出力層をみてみると

layer {
   name: "concat_stage7"
   type: "Concat"
   bottom: "Mconv7_stage6_L2"
   bottom: "Mconv7_stage6_L1"
   # top: "concat_stage7"
   top: "net_output"
   concat_param {
     axis: 1
   }
 }


となっており、出力ノードの1つ目はMconv7_stage6_L2 という名前で定義されています。
(Mconv7_stage6_L1の方はボーンっぽい)

というわけで、これをfuncの出力層に指定することで(1,19,h,w)の出力マップを得ることができます。

x = chainer.Variable([画像のnumpy配列])
y, = func(inputs={'data': x}, outputs=['Mconv7_stage6_L2'])
print y.data.shape #(1,19,h,w)

画像のnumpy配列は、サイズが(1, 4, height, width) で値が0〜255ではなく0.0〜1.0
さらにdtypeがnp.float32になっていないといけないことに注意してください。
(RGBではなくRGBAが想定されているのか分かりませんが、4番目には0を埋めて入力しています)

↓試してみたのがこちらの画像

 

    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"},
    }

ヒートマップは上の構造体に書かれた体の部位のそれぞれの存在確率を示しています。
1枚あたり10秒ぐらいかかりますが、CPUでも動くので使い道が広がりそうです。