MMDモーショントレース自動化への挑戦【第一章】

この度、MMDモーショントレース自動化への挑戦（以下、「MMD自動トレース」）がver1.00になりました。
これを機会に、これまでの改良や、これからの課題などを振り返ってみたいと思います。

以下は、すべてMMD自動トレースver1.00時点の情報となります。
改善点はver0.01から改善された点、課題はver1.00時点での課題です。

[【目次】MMDモーショントレース自動化への挑戦](https://qiita.com/miu200521358/items/d826e9d70853728abc51)

# プロモーション動画

[![MMDモーショントレース自動化への挑戦 ver1.00](http://img.youtube.com/vi/eYJnXCOGuxk/0.jpg)](https://www.youtube.com/watch?v=eYJnXCOGuxk)

# 序章からの変更

- グローバルX軸の前傾姿勢補正　…　ver0.02, ver0.03, ver0.10, ver1.00
- 関節角度適正化　…　ver0.03, ver0.05, ver1.00
- センター移動導入　…　ver0.04, ver1.00
- 足IK導入　…　ver0.05, ver1.00
- キーフレーム円滑化＆間引き　…　ver0.06, ver0.07, ver0.11, ver1.00
- 深度推定によるセンターZ推定導入　…　ver0.08, ver1.00
- 足IKの止め動作導入　…　ver0.08
- 3dpose_ganによる足のトレース精度向上　…　ver0.09, ver0.10
- Openposeの開始フレームNo指定機能追加　…　ver0.11
- 英語版バッチ追加　…　ver0.11
- 2人分トレース　…　ver1.00

詳しくは以下マイリストをご参照ください。
[MMDモーショントレース自動化への挑戦 -niconico](https://www.nicovideo.jp/mylist/61943776)

# 自動化手順

1. 素材となる動画を30fpsで用意する。サイズは任意ですが、小さいと精度が落ちますし、大きすぎると処理が遅いです。1280x720程度がオススメです。
1. `OpenPose` で二次元関節位置データを取得する
1. `FCRN-DepthPrediction-vmd` で、深度データおよび複数人数トレース用データ生成
1. `3d-pose-baseline-vmd` で、二次元関節位置データと深度データから、三次元の関節位置データを生成する
2. `3dpose-gan` で、別の学習モデルを使って、二次元関節位置データから三次元の関節位置データを生成する
1. `VMD-3d-pose-baseline-multi` で2つの三次元の関節位置データと深度データからMMDモーションデータを生成する
1. 生成したMMDモーションデータ(vmdファイル)をMMDでモデルに読み込む

5の時点で、センター移動のある三次元関節位置情報（テキストデータ）が出力されます。
MMD以外にも流用可能です。（ライセンスをご確認ください。）


# 使用技術概要

## 二次元関節推定

### [OpenPose](https://github.com/CMU-Perceptual-Computing-Lab/openpose)

画像から人体の骨格を検出するプログラム。複数人数の検知や動画からの検知も可能。
ただし、複数人数の場合、同一人物が同じインデックスに検出されている保証はない。
（追跡用パラメーターは予約されているので、今後に期待）

### [Openpose簡略起動バッチ](https://github.com/miu200521358/openpose-simple)

Openposeの実行を対話形式で行い、以降の処理を行いやすくするバッチ。

## 深度推定

### [iro-cp/FCRN-DepthPrediction](https://github.com/iro-cp/FCRN-DepthPrediction)

RGB単眼画像から深度推定（奥行きの推定）を行うプログラム。

### [miu200521358/FCRN-DepthPrediction-vmd](https://github.com/miu200521358/FCRN-DepthPrediction-vmd)

`iro-cp/FCRN-DepthPrediction` の私的改造版

#### 改造点

 - 動画を1Fずつ静止画として深度推定を行い、Openposeの二次元関節位置に該当する箇所の深度を人物の深度として取得する
 - 複数人数トレースの場合、Openposeの複数件の二次元関節位置と人物深度に基づき、人物インデックスの再振り分けを行う
 - Openposeが誤認識して、裏表反転している場合に、反転を補正した関節位置を取得する

#### 課題

 - 部屋に配置された家具の位置の推定が学習の元ネタなので、人物の移動距離程度だと、深度の推定精度が甘い

## 三次元関節位置推定

### [3d-pose-baseline](https://github.com/una-dinosauria/3d-pose-baseline)

2Dの人体モデルから3Dの人体モデルを生成するアルゴリズム

### [ArashHosseini/3d-pose-baseline](https://github.com/ArashHosseini/3d-pose-baseline)

上記をforkして、Openposeの二次元関節位置情報を元に三次元関節位置を推定できるようにしたプログラム。

### [miu200521358/3d-pose-baseline-vmd](https://github.com/miu200521358/3d-pose-baseline-vmd)

上記の私的改造版。

#### 改造点

 - confidenceが低い推定は誤認識が多いため使用しない
 - 部位が隠れているなどでOpenPoseで検出できなかった時間を線形補完
 - OpenPoseと3dBaselineの部位の対応関係を修正
 - 2D → 3D処理への入力データのスケールを調整
 - 3次元の位置の計算方法変更
 - 高さの基準変更

上記改造はすべて、[kenkra](https://qiita.com/kenkra)様のPullRequestによるものです。ありがとうございます。

#### 課題

足を上げたり、前屈したり、学習データ（Human3.6M）にない動作の推定に失敗する

### [学習に3Dデータセットを用いない3D姿勢推定](https://nico-opendata.jp/ja/casestudy/3dpose_gan/index.html)

> この研究では，写真を入力として，3Dのポーズを推定する手法を提案します． 中でも，2Dのポーズの推定は近年盛んに行われているので，推定された2Dポーズを3DにLiftする手法を提案しました． このような手法は従来から提案されていたのですが，それらは必ず学習時に3次元データセットを用いていました． 我々は，学習時にも推定時にも3Dのデータが全くいらない3Dポーズ推定の手法を初めて提案します．

3d-pose-baseline にはなかった学習データを使用しているため、足を高く上げる動作など、日常外の動作に強い。

### [miu200521358/3dpose_gan_vmd](https://github.com/miu200521358/3dpose_gan_vmd)

上記の私的改造版。

#### 改造点

 - 3d-pose-baseline-vmdと同じ入力（Openopse結果JSON）、出力形式に変更
 - 3d-pose-baseline-vmd の補完情報として使用

## MMDモーションデータ生成

### [VMD-Lifting](https://github.com/errno-mmd/VMD-Lifting)

> 写真から人のポーズを推定し、VMDフォーマットのモーション(ポーズ)データを出力するプログラムです。 ポーズ推定には Lifting from the Deep (https://github.com/DenisTome/Lifting-from-the-Deep-release) のプログラムを使用しています。

### [smoothvmd](https://github.com/errno-mmd/smoothvmd)

MMDモーションデータを円滑化、間引きするプログラム。

### [miu200521358/VMD-3d-pose-baseline-multi](https://github.com/miu200521358/VMD-3d-pose-baseline-multi)

上記2件の私的改造版。

#### 改造点

- 首や上半身２の角度推定追加
- センター移動導入
    - センターXYは `3d-pose-baseline-vmd` を基本とし、センターZは、`FCRN-DepthPrediction`から判定
- 足IK導入
    - 足の動きがほとんどない場合の足IK止め動作も導入
- キーフレーム円滑化＆間引き
    - 間引きは `smoothvmd`から移植させていただきました
- `3d-pose-baseline-vmd` を基本とし、関節角度が大きい場合に `3dpose_gan` を採用するようマージ

## バルクバッチ

### [motion_trace_bulk](https://github.com/miu200521358/motion_trace_bulk) 

これまで列挙した処理を一括で行うためのバッチ。
これにより、就寝中や外出中に処理を行わせておき、結果だけ後で確認するという事が可能になりました。
パラメーターファイルを読み込み、複数動画を順次処理するバッチもあります。

# 今後の予定

- 導入手順の簡略化
    - 「Docker for Windows」を使って、一連のプログラムの導入を簡略化したい
- 追加学習
    - 手首、足首、頭部、動きの大きな動作など、現在取れていない関節情報を取れるようにしたい
    - `3dpose_gan` で用いられたデータセットが参考になるかも
- 深度推定
    - 人物の移動量に合わせた学習データを用意して追加学習したい
    - 画面奥に移動した場合に、センターが沈んでしまう問題を解決したい
- 補間曲線による間引き
    - 現在補間曲線なしで線形の移動量で間引きしているが、これを補間曲線ありにしたい（修正の手間を考えると、なしの方が楽…？）
- トレース人数増加
    - 現在2人までしか確認できていないので、多人数トレースできるようにしたい

# 共同開発者募集中！

Twitter\([@miu200521358](https://twitter.com/miu200521358)\)よりお気軽にご連絡ください。
直接PullRequest投げてもらっても大丈夫です。