論文まとめ：HumanNeRF: Free-viewpoint Rendering of Moving People from Monocular Video

# はじめに
CVPR2022に採択されたらしきこちらの論文
[1] C. Y. Weng, et. al. HumanNeRF: Free-viewpoint Rendering of Moving People from Monocular Video.
のまとめ

- arXiv:
https://arxiv.org/pdf/2201.04127.pdf

- project page
https://grail.cs.washington.edu/projects/humannerf/

# 概要
- 単眼カメラから撮影されたビデオから、その映像内の人に対して新しい視点でレンダリングするしくみ
- T-pose上でNeRFを行い、それを各フレームごとの姿勢に変換する
- 事前に必要なものは3D骨格を推定するモデル

![スクリーンショット 2022-04-24 4.26.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/49d05979-1165-aad9-accc-ac0e83c14c29.png)

上図のように単眼ビデオを入力して、自由視点からのレンダリングを行う。

# 手法
## 全体像

まず ${\rm \bf x}\_0 \in \mathbb{R}^3 ?$: 各フレームにおける３次元（？）の座標とする。

また ${\rm \bf p} = (J, \Omega)$: そのフレームにおける人のposeで、

```math
\Omega = \{ \omega_i \}
```
は関節の相対回転ベクトルとし、

```math
J \in \mathbb{R}^{K \times 3}
```

は各関節の3D座標とする。撮影したフレームにおける３次元（？）の座標から canonical space（T-poseの空間）の座標へと変換（motion field)を T として 

```math
T: ({\rm \bf x}_0, {\rm \bf p}) \rightarrow {\rm \bf x}_c
```
とする。このcanonical spaceにおける点から色と密度を推定する関数を $F\_c : {\rm \bf x}\_c \rightarrow ({\rm \bf c}, \sigma)$ とする。

撮影したフレームにおける３次元位置と姿勢情報から以下の $F\_0 : $ でその色と密度を求める。 

```math 
F_0 ({\rm \bf x}, {\rm \bf p}) = F_c (T({\rm \bf x}, {\rm \bf p}) \tag{1}
```

さらにmotion field T は線形の逆運動学で決まる $T\_{skel}$ とそれを補完するoffset TNRに分ける。

```math
T({\rm \bf x}, {\rm \bf p}) = T_{skel}({\rm \bf x}, {\rm \bf p}) + T_{NR}(T_{skel}({\rm \bf x}, {\rm \bf p}), {\rm \bf p}) \tag{2}
```

ここまでまとめると、こんな感じか。

![スクリーンショット 2022-04-22 2.31.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/bae223c3-c51a-9719-7b0a-051e9de8bb91.png)

## canonical volume
canonical volume $F\_c$ は NeRF 的な部分だが、ここはMLPとする。

```math
F_c ({\rm \bf x}) = {\rm MLP}_{\theta_c} (\gamma ({\rm \bf x})) \tag{3}
```

$\gamma$ はNeRF同様以下でエンコードする。

```math
\gamma ({\rm \bf x}) = ({\rm \bf x}, \sin (2^0 \pi {\rm \bf x}), {\rm \bf x}, \cos (2^0 \pi {\rm \bf x}), \cdots, {\rm \bf x}, \sin (2^{L-1} \pi {\rm \bf x}), {\rm \bf x}, \cos (2^{L-1} \pi {\rm \bf x}))
```
図にするとこんな感じ。

![スクリーンショット 2022-04-22 2.44.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/b64bc90c-f421-c2ae-4aca-3d0675c3f7ca.png)

## skeletal motion
observation space における x は近傍の骨格に沿って変形させる。

body poseから計算した i 番目の関節の親関節に対する回転角と変位をR, tとして、

```math
T_{skel} ({\rm \bf x}, {\rm \bf p}) = \sum^{K}_{i=1} w^i_o ({\rm \bf x})(R_i {\rm \bf x} + {\rm \bf t}_i) \tag{4}
```

$w^i\_o ({\rm \bf x})$ は observation space における各点 x がどの関節と関連しているかを表す重みだが、これは以下の様に canonical space上の重みを使った表現に置き換える。

```math
w_o^i ({\rm \bf x}) = \frac{w_c^i (R_i {\rm \bf x} + {\rm \bf t}_i)}{\sum^K_{k=1} w^k_c (R_k {\rm \bf x} + {\rm \bf t}_k)} \tag{5}
```
ここで
```math 
\{ w^i_c({\rm \bf x}) \} = W_c({\rm \bf x})
```
とする。$W\_c({\rm \bf x})$ はニューラルネットの出力を想定して、Kチャンネルとする。

この $W\_c({\rm \bf x})$ は 乱数の定数である
 latent code z を使ってCNNから出力する。<font color="red">このあたりは意味不明</font>

```math
W_c({\rm \bf x}) = {\rm CNN}_{\theta_{\rm skel}}({\rm \bf x}; {\rm \bf z}) \tag{6}
```
このへんを図にするとこんな感じか。$w\_c$ 周りがよくわからん。

![スクリーンショット 2022-04-24 3.28.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/b74f2098-43f7-cb8f-315c-ce667583372d.png)

## Non-rigid motion
offset $\Delta{\rm \bf x}$ はposeとskeltal motionから

```math
T_{\rm NR} ({\rm \bf x}, {\rm \bf p}) = {\rm MLP}_{\theta_{\rm NR}} (\gamma ({\rm \bf x}; \Omega) \tag{7}
```

x は standard positional encoding $\gamma$ する。

あえて図にするとこんな感じ。

![スクリーンショット 2022-04-24 3.34.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/f8183f7d-d4b1-9f79-bfef-f69f0f650d51.png)


## Pose correction
3d 骨格モデルから推定される各関節の角度を学習によりrefineする。具体的には3d 骨格モデルから推定される各関節の角度に対して、正しい角度との差分を $\Delta\_{\Omega} = (\Delta\_{\omega\_{0}}, \cdots \Delta\_{\omega\_{K}})$ をMLPから求める。

```math
\Delta_{\Omega} = {\rm MLP}_{\theta_{pose}}(\Omega) \tag{9}
```

これに3D骨格モデルからの推定値を加えたposeを使用する。

```math
P_{\rm pose} ({\rm \bf p}) = (J, \Delta_{\Omega}({\rm \bf p}) \otimes \Omega) \tag{8}
```

ここの部分。

![スクリーンショット 2022-04-24 3.38.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/a8a20eca-6950-f61d-7df3-ac9926753e58.png)

# loss
## volume renderingによるloss
volume rendiringにより$\theta\_c, \theta\_{\rm skel}, \theta\_{\rm NR}, \theta\_{\rm pose}$ を求める。
${\rm \bf e}\_i$: i番目の画像に対応するカメラパラメータ
$\Gamma $: volume renderer
として、lossは以下のように１）observation space上の点をcanonical spaceに変換して、それを色を取得し、それを画像上にレンダリングしたものと、２）実際の画像、との間で計算する。

```math
\newcommand{\minimize}{\mathop{\rm minimize}\limits}
\minimize_{\Theta} \sum^N_{i=1} \mathcal{L} \{ \Gamma [F_c (T({\rm \bf x}, {\rm \bf p}_i)), {\rm \bf e}_i] I_i \} \tag{11}
```

lossの関数 $\mathcal{L}$ はMSEと perceptual loss の１種でVGGを使う LPIPS[2] との和とする。

```math
\mathcal{L} = \mathcal{L}_{\rm LPIPS} + 0.2 \times \mathcal{L}_{\rm MSE}
```

## 関節に対するweight
canonical spaceにおける体内の各点が各関節に対してどれくらいの重みかを表す  $\Delta W\_c$ は以下のように

```math
W_c = softmax(\Delta W_c + \log(W_g)) \tag{21}
```

各関節からのgaussianを仮定したデフォルト値 $W\_g$ との差分を加えることで表現する。この差分をニューラルネットで学習する。

## volume rendering
レンダリングに関してはNeRFごとく以下。

```math
\begin{eqnarray}
C({\rm \bf r}) &=& \sum^D_{i=1} (\prod^{i-1}_{j=1}(1 - \alpha_j)) \alpha_i {\rm \bf c}({\rm \bf r}_i) \tag{12} \\
\alpha_i &=& 1-\exp(-\sigma({\rm \bf x}_i) \Delta t_i)
\end{eqnarray}
```

サンプリングは3D pose estimationの過程で生じた（？）人の3D bounding box内のみで行う。

## delayed optimization of non-rigid motion field
<font color="red">ここはよくわかってないので雰囲気だけ。</font>

skeletal motion モデルと non-rigid motion モデルを同時に学習させると、後者が過学習するらしい。前者の主体は行列演算だが、パラメータで重み $w\_o$ を使っていて、これの元を正せばニューラルネット。よって前者が適切に学び、後者がその差分を学ぶ形が理想的だが、先に後者がフィッティングしてしまうらしい。

この対応策として、周波数領域にHann windowをかけて適切な周波数のみ選択する。学習と共にwindowの幅を広げていく。

## loss and ray sampling
perceptual loss である LPIPS を用いているので、NeRFのようなrandom samplingはできない。サンプリングはパッチとする。

# 実験と評価
## 用いたデータセット

- ZJU-MoCap dataset
- Youtubeのビデオ

## 学習の設定

- 最適化：Adam(β1=0.9, β2=0.99, lr=5x10-4 for $\theta\_c$, 5x10-5 for all)
- 1 rayあたり128点をサンプリング
- iteration:400K(4xRTX2080Tiで72時間）
- Youtubeのビデオを使用した場合の Ts, Teに対してdelayed optimization

## 比較対象
1. Neural Body
拙著 https://qiita.com/masataka46/items/dadfe474693961b19467 等参照
2. HyperNeRF[4]（結局、性能が悪すぎるので使われず）

## メトリクス
1. PSNR
2. SSIM
3. LPIPS*（上記LPIPSの値を100倍する）

## 他のモデルとの比較結果
ZJU-MoCap datasetを用いた場合の比較結果は以下

![スクリーンショット 2022-04-24 3.01.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/2b3bb642-48ab-aeec-32fd-6667c9b020c0.png)

いずれのメトリクスにおいてもneural bodyより精度が良い。

## 定性的評価
以下の図は上２行が著者らが撮影したビデオ映像、下３行がYoutubeの映像。

![スクリーンショット 2022-04-24 3.00.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/42147358-32c6-bb1a-74c6-508fc3223e3f.png)

neural bodyより本手法の方が細部まではっきりしている。

# reference

[2] Katja Schwarz, Yiyi Liao, Michael Niemeyer, and Andreas Geiger. GRAF: Generative radiance fields for 3d-aware im- age synthesis. NeurIPS, 2020.

[3] Nikos Kolotouros, Georgios Pavlakos, Michael J. Black, and Kostas Daniilidis. Learning to reconstruct 3D human pose and shape via model-fitting in the loop. ICCV, 2019.

[4] Keunhong Park, Utkarsh Sinha, Peter Hedman, Jonathan T. Barron, Sofien Bouaziz, Dan B Goldman, Ricardo Martin- Brualla, and Steven M. Seitz. HyperNeRF: A higher- dimensional representation for topologically varying neural radiance fields. SIGGRAPH Asia, 2021.