AI初心者がOpenPoseのモバイル実装に取り組んだ話

[OpenPose](https://github.com/CMU-Perceptual-Computing-Lab/openpose)は画像から人物の姿勢を推定する論文と、その実装、モデルの学習環境、学習済みモデルを含むプロジェクトです。  
OpenPoseの実行環境はGPUを積んだハイスペックマシンが主となっていますが、モバイルで動かすことが出来れば、様々な活用が出来るのではないかと考え、モバイルで実装するプロジェクトを始めました。  

勿論私以外にも、OpenPoseでモバイル実装が出来ないかと考える人たちがおり、「[モバイルへ移植するのは難しいか？](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/69) 」といったIssueがあります。  
私もこちらのIssueに活動状況を投稿しています。  

## 第一段階: OpenPose Caffe Model -> iOS CoreML Modelにコンバートし、ヒートマップの作成

最初の調査としては、OpenPoseが提供する学習済みモデル(Caffe-Model)からCoreMLモデルに変換して動くか？でした。  
これは割とさくっと出来ました。  

![pcm_model.png](https://qiita-image-store.s3.amazonaws.com/0/35973/6521effe-3b5e-8166-3d66-45f912cdea52.png)


画像を「学習モデル」に渡すと、推論結果として、「部位の位置(PCM)と、部位間の関連度(PAF)の行列を出力」します。

- PCM (Part Confidence Maps)
- PAF (Part Affinity Fields)

画像赤丸部分のPCM(Part Confidence Maps)をヒートマップにしたところ画像の結果が返ってきました。

![cap512.png](https://qiita-image-store.s3.amazonaws.com/0/35973/606108b1-f9b4-1849-a684-2111c7f8d879.png)

元の画像は[エネルギー波を繰り出す女子高生](https://www.pakutaso.com/20151016274post-6129.html)

なかなかいい感じに部位の位置が検出出来ており、OpenPose Caffe-ModelからCoreMLへのコンバートは成功してそうです。
ただし、CoreMLの推論完了には2～4秒程度要すことから実用には難しい印象です。

コンバート処理と、ヒートマップを表示するコードは[Gist](https://gist.github.com/otmb/7b2e1caf3330b97c82dc217af5844ad5)で公開しています。  

## 第二段階: モデルの結果をコーディングして姿勢を推定

次に姿勢を推定します。
先ほどの、PCMとPAFをBipartite Matchingで繋ぎ合わせると結果として姿勢(ボーン)が推定できます。

![cording.png](https://qiita-image-store.s3.amazonaws.com/0/35973/3d6088d1-d7d2-aaa2-69d7-6e78cc51331c.png)

Bipartite Matchingのロジックは[tf-openpose](https://github.com/ildoonet/tf-openpose)のコードをベースに実装しました。
行列の演算には、[Accelerate Framework](https://developer.apple.com/documentation/accelerate)の[vDSL](https://developer.apple.com/documentation/accelerate/vdsp)で実装しています。  

結果として、Bipartite Matchingの処理速度は0.3秒程度と、それなりの速度で動くことが確認出来ました。

ここまでのコードは、[infocom-tpo/SwiftOpenPose](https://github.com/infocom-tpo/SwiftOpenPose)でMITライセンスとして公開しています。
ライセンスについては後述にある「GitHubで公開するにあたりOpenPoseのライセンス確認」の内容で確認を行っています。

基本的には動くことが確認出来ましたが、OpenPoseはリアルタイムなボーン検出を目的としています。
現在のCoreMLの推論完了には2～4秒程度要しますので高速化が必要です。

次の対応として、学習モデルの高速化手法として、[tf-openpose](https://github.com/ildoonet/tf-openpose)にある高速な学習モデルの移植作業を始めました。

### tf-openposeとは？

OpenPoseをPython+TensorFlowで実装したプロジェクトです。
特徴として、Mobilenetで実装した高速な学習モデルを公開しています。  
LicenseはApache2です。

## 第三段階: Mobilenetで高速化

![conv2d.png](https://qiita-image-store.s3.amazonaws.com/0/35973/f45537b4-7f20-f78b-596d-df26f6a365e7.png)

[tf-openpose](https://github.com/ildoonet/tf-openpose)の学習モデルはTensorflowで書かれており、画像の青色部分にMobilenetのDepthwise Convolutionレイヤーが使われています。  
Mobilenetのレイヤーを用いることで、計算量やパラメータ数の削減が行われ高速化が期待できます。  

tf-openposeのレイヤー構造の詳細(Keras移植後)はこちらの[画像](https://qiita-image-store.s3.amazonaws.com/0/35973/d97325a0-9d5c-d97d-c8cd-32c5c2b14b53.png)をご覧ください

### Mobilenetについて簡単に説明

[Mobilenet](https://arxiv.org/abs/1704.04861)は2017/04に発表された論文の実装です。   
Mobilenetのアプローチとしては、これまでの機械学習は高精度を達成するのに、より深く複雑なネットワークを用いてましたが、あらたに高速で精度を維持する試みとして、より効率的にサイズ及び速度に重点を置き、小型で低レイテンシ、主に待ち時間の最適化に重点を置いた手法になります。

### TensorFlowモデルをCoreMLに変換する

![modelng.png](https://qiita-image-store.s3.amazonaws.com/0/35973/7ed6ee14-1de2-9cd5-8bb6-1cc2618e9aa1.png)

TensorFlowから、CoreMLへ直接変換することは出来ません。
[Keras](https://keras.io/ja/)、または[Caffe](http://caffe.berkeleyvision.org/)を一度経由する必要があります。

※ 備考: 2017/12/05に[TensorFlowLite](https://github.com/tf-coreml/tf-coreml)でCoreMLへの変換処理が登場しました。しかしながらCoreMLで利用するには、後述するinstance_normalizationの問題の解消が必要です。


### 学習モデルの移植を試みた結果

TensorFlowからKerasモデルへの移植は出来ました。  
CaffeについてはKerasで動作が確認できたタイミングでまだ作業が完了していないこともあり、作業を凍結としました。  
次に、KerasからCoreMLへの変換でBatchNormalizationに問題があることが解りました。 
tf-openposeではinstance_normalizationが有効となっており、CoreMLではinstance_normalizationがサポートがされていませんでした。  

[Instance normalization removed in 0.4.0](https://forums.developer.apple.com/thread/81520)
 
URL先のdeveloper.appleのフォーラムでは端末毎に計算結果が合わないので一時的に削除することにしたそうです。  
将来的には対応を考えているそうなので暫く待つか、instance_normalizationを無効にして再学習するしかなさそうです。  

### 作成したTensorFlow to Keras変換

Kerasへの変換モデルはtf-openposeをForkする形で公開しました。
[OpenPose Keras Mobilenet-Model](https://github.com/infocom-tpo/tf-openpose/tree/master/convert)

### tf-openposeのMobilenetを再学習してみる

先に書いたInstance normalizationを無効にした状態で再学習を実施しています。 

- [tf-openpose 変更点](https://github.com/infocom-tpo/tf-openpose/commit/2c6484888f6035054b897ddc35cbcc257f1c1cdf)

今日現在、13万回トレーニング実施したことろで画像の精度までとなっております。
また、今後トレーニングを続けても精度が出るか解りませんので、このブログではここまでを一旦成果としてまとめております。

<img src="https://qiita-image-store.s3.amazonaws.com/0/35973/77337d9b-edc0-40ab-10d8-3087d254177f.png" width=500>

#### CoreMLベンチマーク(Mobilenet)

CaffeからMobilenetのCoreMLに切り替えたところ、iPad2017でCoreMLの処理は0.9秒、全体で1秒程度で実行できることが確認出来ました。
※ 精度が足りない分結果データが少ないこともあり正確な値とはいえませんが。。

```
coreml elapsed for 0.933373987674713 seconds
init elapsed for 0.05858200788 seconds
others elapsed for: 0.0199159979820251 seconds
human_roop Time elapsed for roop: 0.011730968952179 seconds
estimate_pose Elapsed time is 0.0904630422592163 seconds.
Elapsed time is 1.06164801120758 seconds.
```

## GitHubで公開するにあたりOpenPoseのライセンス確認

OpenPoseはコードと学習したモデルのライセンスと二種類あります。  

- コード
 - アカデミックでの利用は問題ないのですが、商用での利用は有償です。    
- 学習したモデル
 - モデルの形式は[Caffe](http://caffe.berkeleyvision.org/)です。ライセンスは[BAIR](http://bair.berkeley.edu/)になります。

コードを公開するにあたり、特許情報プラットフォーム[J-PlatPat](https://www.j-platpat.inpit.go.jp/web/all/top/BTmTopSearchPage.action)で特許や商標に抵触しないか論文の作者の英名や、OpenPoseが商標登録しているかを確認しましたが特に何も見つかりませんでした。  

今回の場合ですと、コードの利用はなく、またはかなりの変更が行われている。
学習モデルの利用のみで、学習に利用するデータを含まないことから、特に問題ないと判断しました。  

## 私のバックグラウンド

一応、簡単に紹介

### AI初心者度

[ゼロから作るDeepLearning](https://www.oreilly.co.jp/books/9784873117584/)を読んだことがあるくらいで、業務でのコーディング経験はありません。
本の理解度も怪しいですね。  

### 最近の開発

最近ではIoTやVRやARといった活動が主でした。  

* [THETAと全方位マイクを組み合わせたアプリを作りました](https://lab.infocom.co.jp/2016/08/theta.html)
* [バーチャルテレポート: メッシュ処理](https://lab.infocom.co.jp/2017/06/appsjapan.html)
* [ARKitによる空間認識技術のコモディティ化](https://lab.infocom.co.jp/2017/10/arkit.html)


## まとめ

- Bipartite Matchingは行列計算でそれなりの速度は出る
- CoreMLではOpenPoseのモデルをそのまま使うと速度に問題がある
- 高速化はtf-openposのMobilenetの手法が使えそう
 - ただし、学習モデルをinstance_normalizationを無効にして再学習するか、CoreMLのinstance_normalizationへの対応を待つ必要がある
 - 現在、instance_normalizationを無効にして再学習中。後日に期待。

これから取り組む方に向けて、有益な情報を紹介出来たように思います。
今後、モバイルでの推論は端末で行い、匿名性の高い情報だけをサーバーに集めるといった機会が増えると予想しています。
そういった流れの中で、今回の題材は割と面白いところを引っ張ってこれたのではないかなと考えています。  

まだまだAIは始めたばかりの初心者です。ぬるい目で見守っていただければと思います。  
それではよいお年を！  

# コードの公開先

* Swift実装: [infocom-tpo/SwiftOpenPose](https://github.com/infocom-tpo/SwiftOpenPose)
* Gist: [Caffe to CoreMLのコンバートと、ヒートマップ表示](https://gist.github.com/otmb/7b2e1caf3330b97c82dc217af5844ad5)
* Fork: [OpenPose Keras Mobilenet-Model](https://github.com/infocom-tpo/tf-openpose/tree/master/convert)

# 引用

[Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields](https://arxiv.org/abs/1611.08050)