【論文解説】Depth Prediction Without the Sensors: Leveraging Structure for Unsupervised Learning from Monocular Videos

# 概要
Google Brainによる単眼動画からの深度推定モデルの手法について、解説します。
本手法は、tensorflowのmodelsで、struct2depthという名前で公開されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4010/7268d782-c216-0e57-cedc-451b89f4fb81.png)

ベースとなる手法から、主に以下の3点が改善点として提案されています。

- Modeling Object Motion：画像中の物体の動きをモデル化
- Imposing Object Size Constrains：物体サイズによる正則化
- Online-Refinement：推論実行時に、オンラインにパラメータチューニングを行うことで高精度化

また、本手法は、物体ごとの動きも推定することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4010/8ae0b2f6-ba3e-7041-bdf5-50fcaff18b8f.png)


ベースとなる手法の詳細については、以下の記事をご覧ください。

- [SfMLearner](https://qiita.com/takoroy/items/96ad3e2ad14ba036df67)
- [Monodepth2](https://qiita.com/takoroy/items/191ec46211838daa47e1)

# 書誌情報
- Casser, Vincent, et al. "Depth prediction without the sensors: Leveraging structure for unsupervised learning from monocular videos." Proceedings of the AAAI Conference on Artificial Intelligence. Vol. 33. 2019.
- https://arxiv.org/pdf/1811.06152.pdf
- [プロジェクトページ](https://sites.google.com/view/struct2depth)
- [公式実装（tensorflow）](https://github.com/tensorflow/models/tree/master/research/struct2depth)

# ベースモデル
本論文では、既存手法のいいとこ取りをしたベースモデルを使用しています。

3枚一組の画像$I_1, I_2, I_3$を入力とし、$I_2$をターゲット画像、その他をソース画像とします。
ターゲット画像の深度を推定し、$1 \rightarrow 2, 3 \rightarrow 2$のカメラの姿勢変化を推定します。
これらの情報を利用し、合成画像$\hat{I}\_{1 \rightarrow 2}, \hat{I}\_{3 \rightarrow 2}$を推定します。

Monodepth2と同様に、複数のソース画像から作られた合成画像の内、ピクセルごとにターゲット画像に近いほうを使って再構成誤差を算出します。
例えば、$L1$損失は、以下のように推定されます。

$L_{r e c}=\min \left(\left\|\hat{I}\_{1 \rightarrow 2}-I_{2}\right\|,\left\|\hat{I}\_{3 \rightarrow 2}-I_{2}\right\|\right)$

損失関数は以下のように定義され、各解像度で算出されます。

$L=\alpha_{1} \sum_{i=0}^{3} L_{r e c}^{(i)}+\alpha_{2} L_{s s i m}^{(i)}+\alpha_{3} \frac{1}{2^{i}} L_{s m}^{(i)}$

$i$は3つ組の中のどの画像をターゲット画像とするかを表しています。$L_{rec}$は合成画像とターゲット画像のL1誤差、$L_{ssim}$はSSIM誤差、$L_{sm}$は深度マップの滑らかさに関する誤差で、SfMLearnerで使用されたものと同じものです。

また、深度の曖昧さによって生じる不具合を避けるため、Monodepth2でも使用されたDepth Normalizationが使われています。

# Modeling Object Motion
ベースとなる単眼深度推定手法では、カメラ以外の物体は基本的に動いていないことを前提にモデルが構築されていました。本手法では、前処理としてインスタンスセグメンテーションを施し、各物体ごとに何らかの運動をしているという仮定を置きます。


## 前処理
本手法では、入力される3つ組の画像に対してインスタンスセグメンテーションを適用しています。そして、その中に出現する物体領域を紐付け、同一の物体が各画像でどの領域に存在しているのかを明らかにします。[公式実装](https://github.com/tensorflow/models/blob/master/research/struct2depth/alignment.py)を確認すると、インスタンスセグメンテーションで得られた物体領域を、単純なしきい値処理で紐付けています。

こうして、各画像$I_1, I_2, I_3$に対して、セグメンテーションマスク$S_1, S_2, S_3$が得られます。シーケンス内の$i$番目の物体の領域は、各画像中の領域$O_i(S_1), O_i(S_2), O_i(S_3)$と表されます。

また、いかなる物体も含まない領域は$O_0(S_1), O_0(S_2),, O_0(S_3)$と表現されます。

## エゴモーション（カメラ姿勢の変化）の推定
ベースとなる手法と異なり、インスタンスセグメンテーションにより、動いている可能性がある物体の領域が明らかになっているのであれば、カメラの姿勢変化はその領域以外から求めたほうが精度は良くなりそうです。

そのため、3つ組の画像の中で物体領域を一切含まない領域$V$のみから、カメラの姿勢変化を推定します。$V$は以下のように表されます。

$V=O_{0}\left(S_{1}\right) \odot O_{0}\left(S_{2}\right) \odot O_{0}\left(S_{3}\right)$

$O_{0}\left(S_{i}\right)$は、いかなる物体も含まない領域なので、それらの要素積である$V$は、3つ組の画像全てにおいて物体ではない領域、となります。

エゴモーションの推定は、PoseCNN $\psi_E$を使って、以下のように推定されます。

$E_{1 \rightarrow 2}, E_{2 \rightarrow 3} = \psi_{E} \left(I_{1} \odot V, I_{2} \odot V, I_{3}  \odot V\right)$

ちなみに、エゴモーションの逆変換（$E_{2 \rightarrow 1}, E_{3 \rightarrow 2}$）は、回転$R$の逆行列と並進$T$を反転させることで簡単に得られます。

## 物体の動きの推定
エゴモーションの推定結果を元に、ソース画像や対応するセグメンテーションマスクを元に、合成画像$\hat{I}\_{s \rightarrow t}$や合成セグメンテーションマスク$\hat{S}\_{s \rightarrow t}$を作ります。これは、「ソース画像とターゲット画像の間で物体が動いていないとしたら別視点からはこう見えるはず」という結果になります。この2つを利用すると、合成画像中のある物体$i$の領域は、$\hat{I}\_{s \rightarrow t} \odot O_{i}\left(\hat{S}_{s \rightarrow t}\right)$と表されます。

この合成画像中の物体領域とターゲット画像中の物体領域$I_{2} \odot O_{i}\left(S_{2}\right)$の差異は、物体$i$が動いたことによって生じた差異と言えます。
この差異を用いて、物体$i$のモーション$M_{s \rightarrow t}^{(i)}$を求めることができます。

$M\_{1 \rightarrow 2}^{(i)}, M\_{2 \rightarrow 3}^{(i)}=\psi_{M}\left(\hat{I}\_{1 \rightarrow 2} \odot O_{i}\left(\hat{S}\_{1 \rightarrow 2}\right), I_{2} \odot O_{i}\left(S_{2}\right), \hat{I}\_{3 \rightarrow 2} \odot O_{i}\left(\hat{S}\_{3 \rightarrow 2}\right)\right)$

物体の運動の推定に使用するネットワーク$\psi_M$は、PoseCNNと同じ構造です。

## 最終的な合成画像

物体以外の領域の合成結果と、各物体領域の合成結果を組み合わせることで、最終的な合成結果が得られます。
ソース画像が1、ターゲット画像が2のとき、最終的な合成画像は以下のように作成されます。$i$は物体のインデックスです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4010/101f8509-bc9b-299b-6131-b22f9f481f00.png)

この結果を用いて、ベースラインと同様の再構成誤差やSSIM誤差を適用し、ネットワークを訓練します。

# Imposing Object Size Constrains
本手法では前処理でインスタンスセグメンテーションを行っていることもあり、各物体領域に関するクラスが得られています。物体はカメラからからの距離に応じて反比例してその大きさが小さく見えるため、クラスごとの大きさを事前知識として与えておけば、この事前知識は極端な深度推定結果を予防する正則化として使えます。

この知識は、ある物体領域の高さが$h$ピクセルのとき、物体領域内での深度推定結果が、およそ$D_{\text {approx }}(p ; h) \approx f_{y} \frac{p}{h}$になる、という制約として表現できます。$p$はクラスごとに事前に設定されたパラメータとなります。

物体$i$のクラスを$t(i)$、そのクラスのパラメータを$p_{t(i)}$とすると、損失関数は以下のようになります。

$L_{s c}=\sum_{i=1}^{N}\left\|\frac{D \odot O_{i}(S)}{\bar{D}}-\frac{D_{\text {approx }}\left(p_{t(i)} ; h\left(O_{i}(S)\right)\right)}{\bar{D}}\right\|$

$\bar{D}$は、3つ組の深度推定結果の平均値を使用しています。

# Online-Refinement

学習済みの深度推定モデルを実際に使うときに、隣接フレーム間で深度のスケールに不整合が生じます。これを避けるために、推論しながらファインチューニングする（オンラインチューニング）ことで、モデルを微調整できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4010/46f60aac-b175-73db-f91b-f84147698479.png)


3フレーム（つまり3つ組を1つ）使って、わずか20ステップ訓練するだけで、その後の推論精度が向上するとのことです。

# まとめ

struct2depthは、従来の手法が比較的雑に処理してきた動いている物体について、インスタンスセグメンテーションを行い、一つ一つの物体の動きを推定したり大きさと深度の関係を考慮することで、訓練中の混乱を避けることに成功しています。

また、Online-Refinementによって、Kittiデータセットで訓練したモデルを元に、Fetch robot Indoor Navigation datasetのような室内のデータに対しても深度推定をうまく行えています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4010/4c007fa2-26f8-50ab-e21d-be71106828c0.png)