論文まとめ：PIFu: Pixel-Aligned Implicit Function for High-Resolution Clothed Human Digitization

# はじめに
ICCV2019から3D の人の形を推定する以下の論文
S. Saito, et. al. "PIFuHD: Multi-Level Pixel-Aligned Implicit Function for High-Resolution 3D Human Digitization"
のまとめ

ちなみに同じサイトーさんから既に
[2]PIFuHD: Multi-Level Pixel-Aligned Implicit Function for High-Resolution 3D Human Digitization
が発表されてて、CVPR2020にacceptされてるらしい。

arXiv:
https://arxiv.org/abs/1905.05172

著者のコード：
https://github.com/shunsukesaito/PIFu
Pytorchで実装されてる。

# まとめ
1. 服を着た人の画像を入力して、その３次元形状やテクスチャを推定するモデル
2. PIFu(Pixel-aligned implicit function)を使い end-to-end で学習する
3. これまでの3d 形状推定と比べて精度・及びメモリ使用量で優れる

以下が推論の例。

<img width="869" alt="PIFu_img00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/5dc7c723-e250-f58a-4372-4673c1abc4cc.png">

上側は１枚の画像を入力した場合で、下側がmultiな視点からの画像を入力した場合。いずれも３次元の形状、およびテクスチャを推定している。

# 手法
### もろもろ定義
$X$ ・・・３次元のカメラ座標におけるある点の位置。
$x = \pi(X)$ ・・・ $X$ を二次元にprojectしたもの
$I(x)$ ・・・ その Image
$z(x)$ ・・・カメラ座標における depth。

<img width="167" alt="PIFu_img01 _01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/1239cb20-1abc-e362-cf34-bb456dcbab8a.png">

$g$ ・・・入力画像（$I(x)$ ？）をエンコードする encoder。
$F(x) = g(I(x))$ ・・・入力画像をエンコードして得られる特徴量。
$F\_v(x)$ ・・・surfaceに関する特徴量。
$F\_c(x)$ ・・・textureに関する特徴量。

<img width="334" alt="PIFu_img01_02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/7eccc79b-6c7e-1bcd-dd53-cc8055a45093.png">

おそらく、$F$ はこのように入力画像と同じサイズにencode, decodeされ、その特徴マップ上の位置 $x(h, w)$ は画像上の $x(h, w)$ に対応していて、

<img width="557" alt="PIFu_img_30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/beafd46f-858b-924b-913a-182f5485c62a.png">

チャンネル方向の次元は特徴量の次元だろう。

### 陰関数の表現
特徴量 $F(x)$ と $X$ までのdepth $z(X)$ を用いて surface は以下のように表す。

```math
f(F(x), z(X)) = s:s \in \mathbb{R}
```

<img width="623" alt="PIFu_img01_03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/173734a4-b7a5-c392-5828-14c497a60070.png">

### surface の学習
まず陰関数のtargetは

```math
f^*_v (X) = \left\{ \begin{array}{ll}
    1 & if\ X\ is\ inside\ mesh\ surface \\
    0 & otherwise
  \end{array} \right.
```

として、推論値とのMSEをlossとする。

```math
\mathcal{L}_v = \frac{1}{n} \sum^n_{i=1} |f_v (F_V (x_i), z(X_i)) - f^*_v ( X_i)|^2
```

推論時は陰関数の値が $0.5$ となるところを表面とする。

### data のサンプリング方針

<img width="167" alt="PIFu_img01_01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/82fc9f2d-1547-0975-3d3a-196c7d5b4b5a.png">

データとなる点 $X$ は空間上から一様に取得すると、ほとんどが体表面から外れたものとなり、その結果、体表面の推定が困難なモデルができるだろう。

一方で体表面周囲のみから取得すると、過適合になるだろう。

そこで本手法では以下の１、２を $16:1$ の比率で混ぜて使う。著者によると、ここを変えると学習がうまくいかないらしい。

1. 体表面から正規分布 $\mathcal{N}(0, \sigma), \sigma=5.0 \ cm$ に従う値だけ外れた位置からサンプリングする
2. 空間上の一様分布からサンプリングする

### Texture Inference

テクスチャに関しても

```math
\mathcal{L}_C = \frac{1}{n} \sum^n_{i=1} |f_c (F_C (x_i), z(X_i)) - C ( X_i)|^2
```

としたいところ。ここで $C(X)$ は $X$ におけるRGB値。

しかし著者らに言わせると、この学習は進まない。問題点はこの図のように

<img width="650" alt="PIFu_img_31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/3146055c-a07b-a213-e6e0-9ee0a79d69b1.png">

$F_C$ が $(x, z)$ ・・・つまり空間上の位置 $X$ に対して体表面の RGB を推定するためにはそもそも体表面自体も推定しなければならない点。

そこで texture inferenceにsurface Reconstruction で推定した $F_V$ を入れることでこれを回避する。

```math
\mathcal{L}_C = \frac{1}{n} \sum^n_{i=1} |f_c (F_C (x'_i, F_V), X'_{i,z}) - C (X_i)|^2
```

ここで $X'\_i = X\_i + \epsilon \cdot N\_i, \  N\_i \sim \mathcal{N}(0,d)$ として体表面から一定の距離の位置に対しても色付けする。

<img width="652" alt="PIFu_img_32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/9d94445f-cd50-a736-8e90-c63d49d390b5.png">

改めてモデルの図を見ると、Surface Reconstruction で推定した $F\_V$ が Texture Inference に入力されている。

### multi-view stereo 画像の場合

multi-view のデータがある場合、この図のように

<img width="636" alt="PIFu_img02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/62bfa875-5b2f-1cc8-f347-3f5f49ca0950.png">

まず $f\_1$ でこれまでと同様 single-viewからの陰関数を推定し、

```math
\Phi_i =  f_1(F_i(x_i), z_i(X))
```

次に $f\_2$ でそれぞれの view からの陰関数を集計して包括的の陰関数を求める。

```math
f_2 (\Phi_1, \cdots , \Phi_n) = s
```

# 実験と結果
## 1. 定量的評価
メトリクスは以下

1. the average point-to-surface Euclidean distance(P2S) 
2. Chamfer distance
3. normal reprojection error

simgle-viewで RenderPeople dataset と BUFF dataset で学習させた結果は以下。

<img width="511" alt="PIFu_img05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/9877f7e9-222a-da76-ebdc-71375c398393.png">

いずれのメトリクスで見ても他の手法よりよい。

multi-viewで RenderPeople dataset と BUFF dataset で学習させた結果は以下。

<img width="507" alt="PIFu_img06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/ee6b39cf-d482-9b06-50e8-e2b0a56b4073.png">

こちらも他の手法より全般的に良い。

## 2. 定性的評価

DeepFashion dataset で学習させた場合の推論した surface と texture は以下。

<img width="1035" alt="PIFu_img03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/b563a815-11c8-67cd-caa8-2acb0082deb8.png">

いぃ感じに生成されてる。

また以下は他のモデルと出来具合を比較した画像。

<img width="1036" alt="PIFu_img04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/be8bdf83-5178-f794-50b4-c9c75147cc3f.png">

### 3. ablation study
multi-viewのあるデータに対してviewを増やしていった時に精度が上がるか、の検証は以下。

<img width="603" alt="PIFu_img09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/c12a9d5a-0de6-bd84-a89a-93043792b836.png">

multi-viewの増加に伴って、よりdetailが取れるようになってる。