論文まとめ：Three-D Safari: Learning to Estimate Zebra Pose, Shape, and Texture from Images “In the Wild”

# はじめに
ICCV2019より以下の論文
[1] S. Zuffi, et. al. "Three-D Safari: Learning to Estimate Zebra Pose, Shape, and Texture from Images “In the Wild"ICCV2019
のまとめ

CVF open access:
https://openaccess.thecvf.com/content_ICCV_2019/html/Zuffi_Three-D_Safari_Learning_to_Estimate_Zebra_Pose_Shape_and_Texture_ICCV_2019_paper.html

著者らコード：
https://github.com/silviazuffi/smalst

関連論文のまとめ：
本論文の元となっているSMALRモデルの拙著まとめ
https://qiita.com/masataka46/items/23698308aedb9915b654

# 概要
- in the wildな環境の動物に対して3Dのpose、shape、テクスチャを出力する先駆け的な論文
- 3D modelは同著者らが提案しているSMALやSMALRを用いる
- 学習には合成したデータを用いる

以下は推論の例

![SMALST_img00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/b2830544-921a-8085-720a-13fedb0c7c00.png)

下から入力のin the wildなシマウマの画像、推定した3D modelを画像に重ねたもの、推定したモデルに推定したテクスチャを貼ったもの、推定したmodelを別角度から見たもの。

# SMAL と SMALR

## SMAL model

SMAL modelは著者らが[2]で提示したもので、人のshape model SMPLを動物に転用したもの。具体的には以下。

$\beta$ : PCAで次元削減された空間におけるshapeのベクトル。
$\theta = \{ {\bf r}\_i \}^N\_{i=1} \in \mathbb{R}^{3N}$ : 各関節の親関節に対する相対的なrotationでロドリゲスベクトルで表現したもの
$\gamma$ : ルートの関節のworld座標における translation
として、SMALモデル $M$ で表される 3dメッシュの頂点は

```math
{\bf v} = M(\beta, \theta, \gamma)
```
で表現される。

関節数はSMAL modelでは33だが、本手法では耳を加えて35とする。

## SMAL modelを個別の馬へ適応
${\bf v}\_{horse}$ : 馬のSMALテンプレート（馬の平均的な形状）
$B\_s$ : deformation matrix（低次元のshape特徴量を各馬への差分に変換する？）
として、個別の馬のT-pose（以下の図のような決まった姿勢）は

![SMALST_img10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/30ffc447-baaa-d88c-8252-c7b0a73c48bc.png)

```math
{\bf v}_{shape}(\beta) = {\bf v}_{house} + B_s \beta \tag{1}
```

として求める。

## SMALR
SMALR modelは著者らが[3]で提示したもので、画像からSMALを推定する。

$\hat{\beta} \ $ : 画像中の馬に対して推定したshapeのパラメータ
${\bf dv}^{SMALR}$ : SMALRのしくみで推定した displacement vector
として、
先と同様に、画像の馬に対する推定したT-poseは

```math
{\bf v}_{shape}({\bf dv}^{SMALR}) = {\bf v}_{house} + B_s \hat{\beta} + {\bf dv}^{SMALR} \tag{2}
```
で求める。

## 本論文で推定する dv
本論文では

```math
{\bf dv}^{SMALST}= B_s \hat{\beta} + {\bf dv}^{SMALR} \tag{3}
```

と考え、この ${\bf dv}^{SMALST}$ をモデルから推定する。そうすると

```math
\begin{eqnarray}
{\bf v}_{shape}({\bf dv}^{SMALST}) &=& {\bf v}_{house} + B_s \hat{\beta} + {\bf dv}^{SMALR} \\
&=& {\bf v}_{house} + {\bf dv}^{SMALST} \tag{4}
\end{eqnarray}
```

となる。


# 用いたデータセット
まず前提として、人と違って動物の3Dposeやshapeのデータセットはほとんどない。なので、シミュレーター等を利用して合成データを用いるのが常套手段。

- 12,850の馬の合成データを用いた
- SMALRモデルで生成し、OpenDRを使ってrenderingした

以下の図では上側が合成データ、下がリアルなデータ。

![SMALST_img02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/2bca029e-83f3-500d-1665-aba57f99f07b.png)


# 学習時のアーキテクチャ
アーキテクチャの全体像は以下。

![SMALST_img03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/c357e625-6428-ad46-8b24-45c53dc17db6.png)

各要素を見ていく。

## 画像からT-poseを推定する流れ

![SMALST_img11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/9ef5885a-3135-a45a-e318-4ca31c390c0b.png)

図の左端、馬付近を切り取った画像をencoderに入力する。encorderはResNet-50を用いている。これから得られた特徴量を出力ごとに分岐し、畳み込む。

shape predictorからは（２）式の ${\bf dv}$ 値を出力する。

これに対して（２）式でT-poseを出力する。

## 画像からテクスチャを推定する流れ

![SMALST_img12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/d7c88124-2e40-b2c9-572c-1d16f7aaa1d0.png)

shapeと同様に、馬画像を入力してuv-flowを出力する。ここでいうところの uv-flow とは、画像上の座標(x, y)からテクスチャ・マップの(u, v)へのflowのこと。

このuv-flowからその右、texture mapが生成される。

## 画像から各種パラメータを出力する流れ

![SMALST_img15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/7bb7a983-0d05-2e03-358d-3e24bb49c073.png)

同様に馬画像から translation：γ、focal length：f、各関節の相対 rotation：θを出力する。

## texture map、T-pose、パラメータから画像を生成する流れ

![SMALST_img16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/b78f31e2-1a4a-27e3-ca89-a2ddb823b869.png)

T-poseと translation, rotationで3Dモデルができあがる。これにtexture mapを貼る。（図中のprediction）

これをfocal lengthを用いて画像にprojectし、backgraoundを貼ると、元の画像を推定できる。

# Loss 
lossの全体像は以下。

```math
L_{train} = L_{mask} (S_{gt}, S) + L_{kp2D} ( K_{2D, gt}, K_{2D}) + L_{cam}(f_{gt}, f) + L_{img}(I_{input}, I, S_{gt}) + L_{pose}(\theta_{gt}, \theta) + L_{trans}(\gamma_{gt}, \gamma) + L_{shape}({\bf dv}_{gt}, {\bf dv}) + L_{uv}({\bf uv}_{gt}, {\bf uv}) + L_{tex}(T_{gt}, T) + L_{dt}({\bf uv}, S_{gt})
```

以下、各項。

## 1) Loss mask
$L\_{mask} (S\_{gt}, S)$ はmaskに関するloss。

$S\_{gt}$：ground truthのmask
$S$：推論したmask

おそらく馬のsegmentされた領域のことだろう。学習時の入力画像は合成データなのでground truthのmaskは常に存在する。これと推定した画像上の馬の領域とでL1を計算する。

## 2) Loss kp2D
$L\_{kp2D} ( K\_{2D, gt}, K\_{2D})$ は2D上のキーポイント（各関節）に関するloss。

$K\_{2D, gt}$：ground truthの2D上（画像座標上）のキーポイント。
$K\_{2D}$：推定した2D上のキーポイント

こちらも同様に合成画像の性質上、ground truthの2Dキーポイントは存在する。これと推定した3D-poseから各関節の位置を2Dに射影したキーポイントとでMSE lossを計算する。

## 3) Loss camera
$L\_{cam}(f\_{gt}, f)$ はカメラの焦点距離に関するloss。

$f\_{gt}$：ground truthの焦点距離
$f$：推定した焦点距離

やはり同様にシミュレーターから生成した合成画像なのでground truthの焦点距離は求まる。これと推定した焦点距離とでMSEを計算する。

## 4) Loss image
$L\_{img}(I\_{input}, I, S\_{gt})$ は画像同士のloss。

$I\_{input}, I$：入力画像の馬の部分
$I, S\_{gt}$：推定した諸々のデータから作成した馬と背景の画像から馬の部分だけを抜いたもの

この両者からperceptual distance[4]を求める。

## 5) Loss pose
$L\_{pose}(\theta\_{gt}, \theta)$ は各関節の相対的rotationに関するloss。

$\theta\_{gt}$：ground truthの各関節の相対的rotation
$\theta$：推定した各関節の相対的rotation

[5]の手法のようなMSEで求める。

## 6) Loss trans
$L\_{trans}(\gamma\_{gt}, \gamma)$ はroot関節のtranslationに関するloss。

$\gamma\_{gt}$：ground truthのroot関節 translation
$\gamma$：推定したroot関節 translation

MSEで求める。

## 7) Loss shape
$L\_{shape}({\bf dv}\_{gt}, {\bf dv})$ はshapeに関するloss。具体的には変位ベクトル <b>dv</b>値を使う。

${\bf dv}\_{gt}$：ground truthの変位ベクトル（<b>dv</b>）
${\bf dv}$：推定した変位ベクトル（<b>dv</b>）

MSEで求める。

## 8) Loss uv
$L\_{uv}({\bf uv}\_{gt}, {\bf uv})$ はuv-flowに関するloss。

${\bf uv}\_{gt}$：ground truthのuv-flow
${\bf uv}$：推定したuv-flow

両者でL1 lossを計算する。texture mapの見えてない部分に関してはlossを計算しない。

## 9) Loss texture
$L\_{tex}(T\_{gt}, T)$ textureに関するloss。

$T\_{gt}$：ground truthのtexture map
$T$：推定したtexture map

両者でL1 lossを計算する。

## 10) Loss dt
<font color='blue'>（ここ間違ってたら連絡ください）</font>

$L_{dt}({\bf uv}, S_{gt})$ は[6]に出てくる texture flow に関するloss。

上記の Loss uv はカメラから見えてない部分に関してはlossを計算しない。また Loss imageもカメラから見た3Dモデルを画像にprojectしているので、カメラから見えてない部分に関しては考慮されてない。

よって、以上のlossだとカメラから見えてない部分のtextureに関してはどのようなものを推定するか不明。

しかし、実際にはzebraの模様は左右がほぼ対象などの特徴がある。よって、例えば見えてない体の左側のtextureを「見えてる」体の右側の対応する点から取ってくると、それっぽいものができあがるだろう。よって、そのような学習を行いたい。

texture flowがinput imageの前景部分のみになるよう、texture flowが後景を示した場合にペナルティを与える。これにより、見えてない部分の texture flow は、頑張って前景部分の対応する点を見つけようとするだろう。

これにはまず、distance transformを用いる。これはまずmask画像のような{1, 0}のみの画像において、最も近い0の位置からの距離を示したマップ。例えば

```
[[0,1,1,1,1],
 [0,0,1,1,1],
 [0,1,1,1,1],
 [0,1,1,1,0],
 [0,1,1,0,0]]
```
であれば、

```
[[ 0.    ,  1.    ,  1.4142,  2.2361,  3.    ],
 [ 0.    ,  0.    ,  1.    ,  2.    ,  2.    ],
 [ 0.    ,  1.    ,  1.4142,  1.4142,  1.    ],
 [ 0.    ,  1.    ,  1.4142,  1.    ,  0.    ],
 [ 0.    ,  1.    ,  1.    ,  0.    ,  0.    ]]
```
となる。これを用いて、前景部分でほぼ 0.0, 後景部分でほぼ 1.0となるような演算を行う。

具体的には SMALSTコード utils/image.py内の compute_dt_barrier関数内で以下のような演算を行っている。

```python
from scipy.ndimage import distance_transform_edt
dist_out = distance_transform_edt(1-mask)
dist_in = distance_transform_edt(mask)
dist_diff = (dist_out - dist_in) / max(mask.shape)
dist = 1. / (1 + np.exp(50 * -dist_diff))
```
１行目：上で説明したdistance transformを行うライブラリをimport。
２行目：最も近傍の前景からの距離 dist_out を求める
３行目：最も近傍の後景からの距離 dist_in を求める
４行目：dist_out から dist_in を引くことで前景の中心部分であるほど正で絶対値が大きな値、後景で前景から離れるほど負で絶対値が大きな値となる。これを規格化する。
５行目：これに50という大きな値をかけて絶対値を大きくし、０から話した上でシグモイドを作用させる。これにより前景部分はほぼ1.0, 後景部分はほぼ0.0となる。

これらの処理を $D\_s(x) = 0$ とし、

```math
L_{dt} = \sum_i \sum_{u,v} G(\mathcal{D}_{S_i};\mathcal{F}_i)(u,v)
```
として loss とする。


# インスタンスごとの最適化
ネットワークで推論させた後に、各インスタンスごとに教師なしで最適化することで精度を上げる。

具体的には以下の図（再掲）の

![SMALST_img03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/8ea0f9b4-6e1f-b57a-64f8-31e4fbc44333.png)

ピンクの破線部分。以下の手順で行う。

（１）ネットワークのパラメータは固定する
（２）input画像をネットワークに入力し、特徴量（encoderからのfeatures）を得る
（３）特徴量から諸々の値を取得し、最終的には右端のシマウマをprojectして得た前景にbackground（データの平均画素値）を加えたもの（outputとする）を得る
（４）inputとoutputに関するlossを計算し、それを最小化するよう特徴量を更新する

Lossは以下のようにinputとoutputとのperceptual distanceを用いる。

```math
L_{photo} ( I_{input}, I) + L_{cam} ( \hat{f}, f) + L_{trans}(\hat{\gamma}, \gamma)
```

2項目と３項目はへんな方向に行かないための制約か？

# 学習のプロセス
## data生成
- 用いたシマウマの数は 10 subjects。合計57画像をSMALRを当てはめて3Dモデルを作成した。
- これに対し、OpenDRを使ってランダムに形状、pose、カメラパラメータ、background等を変え、12,850枚のdataを生成した

以下、データのvariationの詳細

### pose variation
- それぞれのSMALRモデルにおいて骨格の角度を正規分布に従う値で変えた。この分布はSMALRの57個のposeと歩いているシーンのposeから生成した
- その際の正規分布は57枚の画像におけるposeと合成的にwalkさせたものから得た
- 57個のposeにnoiseを加えて５倍にしたpose、計285個も追加した（これにより 1 subjectあたり計1,285個）
- depthも $\gamma\_0 = [0.5, -1.0, 20]$ と変化させた（1,285個に対してランダムにこのtranslationを当てはめたいう意味か？）

### Appearance variation
- 1 subjectあたり1,285枚 x 10 subjectの画像に対し、見た目を変化させるため white-balance algorithmを使ってテクスチャを変化させた。これによりtexture mapは倍となった
- input 画像に対して明度、彩度、色相をランダムに変化させた
- 3Dモデル上でランダムに照明も追加した
- input 画像の背景はCOCO datasetからランダムに取得した

### Shape and size variation
- β値のうち20個をランダムに変えることでshapeも変化させた
- focal lengthにもnoiseを加えた


# 実験の結果

精度は2D上の各関節が正解の一定範囲に収まっているかを表すPCK等で判定した。

## ablation study

以下のtable1では(B)が合成データに対する精度、(C)が本手法、等。

![SMALST_img05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/1e64baa8-2f87-23ac-b4a9-eef73f76ce23.png)


# reference
[2] Silvia Zuffi, Angjoo Kanazawa, David Jacobs, and Michael J. Black. 3D menagerie: Modeling the 3D shape and pose of animals. In Proceedings IEEE Conference on Com- puter Vision and Pattern Recognition (CVPR) 2017, pages 5524–5532, Piscataway, NJ, USA, July 2017. IEEE.

[3] SilviaZuffi,AngjooKanazawa,andMichaelJ.Black.Lions and tigers and bears: Capturing non-rigid, 3D, articulated shape from images. In IEEE Conference on Computer Vision and Pattern Recognition (CVPR). IEEE Computer Society, 2018.

[4] RichardZhang,PhillipIsola,AlexeiAEfros,EliShechtman, and Oliver Wang. The unreasonable effectiveness of deep features as a perceptual metric. In CVPR, 2018.

[5] Siddharth Mahendran, Haider Ali, and Rene ́ Vidal. 3d pose regression using convolutional neural networks. In 2017 IEEE Conference on Computer Vision and Pattern Recognition Workshops (CVPRW), pages 494–495, July 2017.

[6] Angjoo Kanazawa, Shubham Tulsiani, Alexei A. Efros, and Jitendra Malik. Learning category-specific mesh reconstruc- tion from image collections. In ECCV, 2018.