最新deep learningを用いて、一枚全身画像から人を復元してみた👬

# Advent Calendar 2019
こちらはestie Advent Calendar 2019 19日目の記事になります。
是非、他の記事もご覧ください。 https://qiita.com/advent-calendar/2019/estie

## はじめに
こんにちは、私はestieでAIアルゴリズム開発をしているなつめです。
普段は学生としてコンピュータビジョン系の研究を行なっています。
本記事では、estieの業務と直接は関係ありませんが、折角の機会なので私の研究していたdeep learning技術である「一枚の画像から人の三次元形状復元」について紹介していきます。

## 三次元復元の研究目的・背景
近年、ARやVRなどの没入型の映像体験が流行しています。
それらの映像に必要なCDCGコンテンツを製作するためには、現実世界の三次元物体をデジタル化する必要があります。
特に、着衣人物の3DCG化の場合は、何十台ものカメラを用いた緻密なスキャン装置や、複雑かつ長時間の撮影作業が必要となります。
そこで、一枚の画像から深層学習を用いて着衣人物の全身を3DCG化をしようというのが、大きな目的です。

## 今回やったこと
実際に、iPhoneで撮影した着衣人物の画像一枚から、PIFuと呼ばれる手法を使って人の三次元形状復元を行いました。
さらに、復元した形状を使って、何ができるかといことを紹介して行こうと思います。
実際に今回行ったことは以下の二つです。
1. 復元した三次元モデルを動かす
2. 三次元プリンティングする

## PIFuと呼ばれる三次元復元手法
この研究は私がICCV2019という国際会議で発表した内容で、Deep Learningを用いて学習することで二次元画像から三次元形状を復元するといった研究です。
論文中の結果がこちらです。inputの列が入力画像、reconstructed geometoryの三列が復元された形状、textured reconsturctionの三列が復元された形状と色情報を示した図です。
<img width="100%" alt="スクリーンショット-2019-07-09-10.03.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/d7526cc8-a0a3-9ea4-5b34-aef6b4590ca7.png">
このように、**一枚の画像からは見えていない背面を含んだ全身の形状や色情報**を復元することが可能です。


## 何でできるの？？
ネットワークの構造とは説明しませんが、簡単に言うと、
正解データの三次元データと画像のペアを用意して、画像から三次元データを出力するように学習します。
実際には、三次元スキャンを用いて人の三次元形状データを取得します。
次に、得られた三次元形状データから、レンダリングという三次元データから映像を作成する技術を用いて、大量の二次元の画像を作成することで、正解のペアを用意することができます。


## 実際に復元してみた
PIFuで復元するためには、入力画像から人領域を抽出する必要があります。
今回は、[remove.bg](https://www.remove.bg/)というサイトを使いました。
様々な画像に対して、前景領域を綺麗に切り抜くことができるのでおすすめです。
入力画像がこちら。
<img width="148" alt="Screen Shot 2019-12-17 at 16.25.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/118d06a1-c05d-07ab-84f6-0d77ed48917d.png">
切り抜かれた画像がこちら。
<img width="148" alt="ryota.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/a28be163-4a6c-9828-e1bb-e5cd2667a485.png">
すごい。。。。
そして、切り抜かれた画像からMaskを抽出します。

```python:get_mask.rb
import cv2
img = cv2.imread(img_path, -1)
mask = np.where(img[:,:, -1]==255, 255 ,0)
cv2.imwrite(mask_path, mask)
```

そして、PIFuを使って復元!!!
![Picture1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/9d4583d9-e669-1f51-91a6-f96aeb7c4bc2.png)
ちゃんと顔の反対側が髪であることを、ネットワークが理解している様です。
姿勢に関しては、本来右足と左足は横並びになっているのですが、復元結果だと若干左足が後ろになっています。
二次元画像から三次元の難しいところは、まさにここの部分で、奥行きの情報が失われてしまっているので、ポーズが必ずしも元画像と一致しない問題点があります。
実際に、私たちが入力画像を見てみても、左足が後ろ側にあるように見える気がします（錯覚？）。


## 動かしてみた
次は、復元した三次元モデルを動かしてみたいと思います。
復元した三次元モデルを動かすためには、リグと呼ばれる関節のようなものを割り当てる必要があります。
その関節を動かすことで、三次元モデルにアニメーションをつけるという感じです。
今回は、[Pinocchio](https://github.com/elrond79/Pinocchio)という、Siggraph2007で発表された技術を用いました。
コードは、openFrameWorksのaddonで公開されているものを用いました。
https://github.com/kashimAstro/ofxAutoRiggingModel
こちらの復元結果を入力にしました。
![Picture3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/282ed1c2-c1c2-f120-8c26-c09a3d3932bf.png)
動かしてみた結果がこちら！
![animate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/29987429-b2ec-33c4-48d1-380943597319.gif)
ちゃんと動いていますね。
パーカの布のたるみの部分をもう少しリアルに表現できるとさらに良さそうですね。
この技術があれば、画像中の人を好きなポーズにさせることができます！！👫👫👫
ゲームをするときに、自分をアバターにして遊ぶことも夢ではないですね！！


## 3Dプリントしてみた
三次元復元されたモデルは、3Dプリントして実世界に持ってるくることもできます。
今回は、DMM makeさんで三次元プリンティングをしていただきました。
短納期エクスプレスサービスを利用したので、一体当たり5,500円ほどで印刷できました。
実際に印刷するためには、DMM makeさんの対応しているフォーマットに直す必要があります。
具体的には復元されたobjは頂点ごとにtextureが割り振られているのですが、textureはuv画像として保存する必要があるので変換していきます。Meshlabを用いて変換を行いました。
1. メニューのFile→Import Meshでobjを読み込みます
<img width="1280" alt="Screen Shot 2019-12-15 at 16.05.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/24d2c9c2-cda2-f254-0068-378fa17cb257.png">
2. メニューのFilters→Texture→Parametrization: Trivial Per-Triangle
<img width="1280" alt="Screen Shot 2019-12-15 at 16.09.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/24d2afc6-4258-1cba-0bb6-1ece066dab6e.png">
3. メニューのFilters→Texture→Transfer Vertex Attributes to Texture
<img width="1280" alt="Screen Shot 2019-12-15 at 16.10.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/0204b9c4-a9c0-9c9d-7731-9d075d835c08.png">
4. メニューのFile→Export Mesh As
<img width="1280" alt="Screen Shot 2019-12-15 at 16.11.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/a056b3b1-e4d4-df9d-8c2f-22151ec4877c.png">
変換したobj, mtl, uvmapをzipにして、フォームから送信するだけで、３Dプリントして発送されます。
プリント結果がこちらです！黒いノイズがのってしまったのですが、形状的には人らしいなと感じました。
もしかしたら、メッシュをもっとクリーンなものにしてからプリントする必要があったのかもしれません。
<img width="1167" alt="Screen Shot 2019-12-17 at 18.45.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/6cb169d7-784a-719e-8c86-553e122b3ddb.png">
余談ですが、数日後顔が取れてしまいました。
フィギュアですが予想以上に不気味でした笑
<img width="574" alt="Screen Shot 2019-12-17 at 18.44.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115198/16845942-d146-9a4d-7ec0-277e1974be1f.png">

## まとめ
ということで、今回は最新技術の紹介として、一枚画像から人の全身を三次元復元して遊んでみるという内容でした！
今後もっと復元精度が良くなっていけば、映像作成やゲーム等に使えそうですね！！

estieは[本郷AI](https://hongo.ai/)に選出されたりと、AIアルゴリズムに力を入れているベンチャー企業です。
新しい技術にアンテナを張っているエンジニア、フルスタックのエンジニアを常に募集しています！
私のようにAI研究をするメンバーもいますので、興味ある方はぜひお待ちしております😁
https://www.wantedly.com/companies/company_6314859/projects

estie -> https://www.estie.jp
estiepro -> https://pro.estie.jp
会社サイト -> https://www.estie.co.jp


## 参考文献
- Saito, S., Huang, Z., Natsume, R., Morishima, S., Kanazawa, A., & Li, H. (2019). PIFu: Pixel-Aligned Implicit Function for High-Resolution Clothed Human Digitization. arXiv preprint arXiv:1905.05172.