[3D分野の深層学習] Feature-metric registration[勉強しようシリーズ]

点群の深層学習の世界をのぞいていくシリーズ

![dsffsd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581710/9f03d8fb-adc8-fc02-b0ae-3de20e6ac7ad.png)


https://arxiv.org/abs/2005.01014
https://github.com/XiaoshuiHuang/fmr

#はじめに
iphoneにもLiDARカメラが搭載される昨今ですが、
ノイズや外れ値から無縁の精度を得るには未だ時間がかかりそうです。

「深層学習ならノイズ・外れ値に対してもっと頑強になれるんじゃね？」という期待の元、
深層学習系の点群の位置合わせ等について勉強していきます。

勉強の過程をそのまま書いてるので、
本番に行く前に前提知識の説明が膨大に膨れたりしますがご容赦ください


#勉強の方針
https://qiita.com/akaiteto/items/d5f0d615916877091571
PointNetLKから地続きな形で、「Feature-metric registration」について勉強します。

#前提知識

##〇 PointNetLKによる変換行列の微小変化分の計算
https://qiita.com/akaiteto/items/d5f0d615916877091571
「読む」の「3.2」を参照

##〇 ヤコビ行列
例えば、(u,v)で表されたある空間・関数から、(x,y)で表された別の空間・関数に変換するとき、
$dxdy = ududv$というように、微小変化の変換をあらわしたものがヤコビ行列。

本稿で言えば、特徴誤差rの関数の微小変化#dr#を、剛体変換$theta$の微小変化$d\theta$に変換する。

式については、
https://qiita.com/akaiteto/items/d5f0d615916877091571
「読む」の「3.2」を参照

##〇 PointNetによる点群から特徴を抽出するネットワーク
https://qiita.com/akaiteto/items/d4d4e568fe16f73d0a1d
feature_transformでローカルな特徴を抽出します。

#読む(論文)
## 0 
従来の位置合わせでは、各ポイントの対応を検索してから変換行列を推定して
その時の投影誤差が最小になるまで繰り返す、というプロセスで行われました。

しかし、仮に２つの点群に全く同じものが映っていても、密度の違いや構造の違い、ノイズの影響により
かならずしもポイントとポイントがピッタリと一致することはあり得ません。
位置合わせの問題は、ポイントとポイントが1対1で一致しないという前提のもとで解決しなければいけません。
また、対応の検索が必要なので、多少なりとも処理に時間がかかります。

そこで、本稿では対応を検索することなく、
特徴メトリック投影エラーを最小化する方法を提案します。
重要なポイントとしては、以下の2つです。

(1)対応を検索することなく登録を解決する特徴メトリックベースの手法の提案
(2)特徴を抽出するエンコーダーを半教師あり学習により実行する方法の提案。

##3

###3.1

```math
argmin(\| {\bf F(P)-F(RQ+t)} \|_{2}^{2}) \\
⇔
argmin(\| {\bf r(F(P),F(RQ+t)}) \|_{2}^{2})
```

登録の目的は、
$P \in R^{M×3},Q \in R^{N×3}$の点群に対して、上式を満たすR,tを発見することです。
エンコーダーの特徴関数$F \in R^{K}$は、K次元の特徴を抽出し、rによって特徴量の誤差を計算します。

まずは特徴を抽出するエンコーダーの学習。
学習では、特徴量の誤差rを計算し、特徴の違いが最小になるような変換行列の微小増分を計算します。

変換行列の微小増分$\Delta \theta$は、PointNetLKのICアルゴリズムにより下記式で表されます。
(詳細は前提知識の項参照)

```math
\Delta \theta = (J^TJ)-1(J^Tr)
```

ヤコビ行列についても、PointNetLKと同様に下記のように計算します。
（PointNetLKではexposuremap形式ですが、ここではR,tの行列による表現です。）

```math
J_i = \frac{dF_p}{d\theta_{\xi}}
 = \frac
{F(R_iP+t_i) - F(P)}
{\xi}
```

$xi$は微小摂動です。
回転の3つの角度と移動の3つの移動量の微小な変化を与えたときの変化を計算します。

そしてネットワークを反復させて学習することで、
最終的な出力として推定剛体変換$G_{est}$、推定特徴誤差$r_{est}$、を得ます。

###3.2
特徴を抽出するエンコーダーについて。PointNetで特徴を抽出します。
詳細は前提知識の項参照。

###3.3

PointNetを活用したエンコーダーで特徴を抽出した後は、特徴の学習と変換行列の推定を行います。
デコーダーを作成し、特徴を再び点群に戻します。

エンコーダー・デコーダーの一連のネットワークで学習され、
エンコーダーは回転の違いを認識して特徴を抽出する方法を学習します。


・・・
・・
・

？エンコードしたものをデコードしたら元に戻るだけでは・・・？

ちょっとよくわかってないので、一旦次の節を読んで様子を見ます。
ここまで書いた時点では、抽出した特徴をあえて戻す意味がよくわかってません。
理解できたらまた追記します。

（追記）

" Encoder module should generate different features for P1 and P2 
and the decoder can recover the different features back to their correspondent rotated copies of the point cloud. "

この一文がこのネットワークの目的なのだろうと思います。

学習中のエンコーダは、それぞれに回転している点群$P1,P2$の特徴について
点群の回転を認識したうえで特徴を抽出する、と論文には記載があります。
言い換えるなら、回転の具合が特徴に反映されるので、
$P1,P2$がもしも同じ程度回転してるなら特徴は同じになるし、違うのなら特徴は異なる、ということです。

これを踏まえてエンコーダーの動きをみます。
エンコーダーはPointNetによるミニネットワークなので
点群$P1,P2$の特徴が同じような特徴になるようにパラメータの最適化が行われます。

特徴には回転の具合が反映されると上述しました。
そんな特徴が同じになるということは、点群$P1,P2$はエンコーダーの内部では
点群$P1,P2$の位置合わせのようなものが行われているといえます。

すなわち、エンコーダーの出力した特徴には
点群$P1,P2$がどれくらいパラメタ調整をすれば特徴が一致するか＝どれくらい回転させればポイントが一致するか
という位置合わせにおける回転の情報がつまっているわけです。

なので、ここでデコードを行うというのは、
回転に対する位置合わせが実行済みのポイントを取得することに等しいといえます。

具体的に何に対して最適化を行うかを考えたときには、
ここで取得された「回転に対する位置合わせが実行済みの"ソース点群"のポイント」と、
「位置合わせが行われる対象となる"ターゲット点群"ポイント」、
これらが等しくなるかどうかを評価すればよいわけです。(それが3.4.2の内容)


よって、このネットワークには、
この節で述べたエンコーダーデコーダによる位置合わせの推定(Task1)と、
PointNetLkによる剛体変換の推定による位置合わせの推定(Task2)、
これら２つが同時に実行される構図になります。

なので3.4.1以降に登場する損失関数では、
Chamfer lossでTask1の損失を計算し、
Geometric lossでTask2の損失が計算されているようです。



###3.3.2

位置合わせを実際に行うネットワークを定義します。

```math
r = \| {\bf F(P)-F(RQ+t)} \|_{2}^{2} \\
```

Fは特徴を抽出した関数です。位置合わせを行うために、$r$を最小化しなければいけません。
反復を繰り返し最適化していくことで、位置合わせは徐々に完全になっていきます。
$|r|$が0になるように損失関数を評価し最適化が行われます。


###3.4.2

Chamfer lossでTask1の損失を計算し、
Geometric lossでTask2の損失が計算されているようです。

Chamfer lossの式の意味としては、
まず基本的なコンセプトとしては、
エンコーダーデコーダによって取得された位置合わせ済みのソースのポイントと、
その位置合わせの対象となるポイントの二乗誤差を取ります。

そして、重要なのが$sum$でくくられている「Chamfer Distance」に基づく計算の部分ですがちょっとよくわかっていません。
式の意味がわかったら追記します。わからなかったらそのままです。


#読む(コード)
ちょっとイメージしきれていないところがあるので、
トレーニング部分のコードで全体の流れを追います。コードのベースがPointnetLKのようです。

## 1.ネットワーク定義
https://github.com/XiaoshuiHuang/fmr/blob/eb437bd6552b54e2c35bcb0311a706f3f5143278/train.py#L83

下記の3つのネットワークを定義します。
エンコーダー、デコーダー、特徴メトリックレジストレーション (fmr)

## 2.トレーニング
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L380
トレーニングを開始します。

## 3. 損失関数の取得
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L355

### 3.1 ICアルゴリズムによる変換行列推定
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L170
「特徴誤差$r$」、「剛体変換とエンコーダー・デコーダーネットワークの損失$loss_{en/decorder}$」を取得する。

####3.1.1 ICアルゴリズムによる変換行列の推定
変換行列の微小増分$\Delta g$を計算します。

#####3.1.1.1 エンコーダーのトレーニング
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L205

#####3.1.1.2 エンコーダーによる特徴抽出
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L215
ソース点群、ターゲット点群に対してエンコーダー（Pointnet)で特徴を計算します。

#####3.1.1.3 Task1の実行
######3.1.1.3.1 デコーダーによる特徴->点群の復元
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L221
ソース点群、ターゲット点群の特徴をデコーダーで元に戻します。

######3.1.1.3.2 エンコーダー・デコーダーの損失計算
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L228
損失の計算。Chamfer lossのみを計算します。

#####3.1.1.4 エンコーダーの学習完了
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L230

#####3.1.1.5 Task2の実行
######3.1.1.5.1 エンコーダーによる特徴抽出（2回目）
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L233

######3.1.1.5.2 PointnetLkによるヤコビ行列Jの計算
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L236

######3.1.1.5.3 PointnetLkによる変換行列と特徴誤差の推定
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L255

#####3.1.1.6 変換行列、特徴誤差、エンコーダー・デコーダーの損失の3つを返す

### 3.2 剛体変換の保持
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L190
PointNetLk同様、取得した剛体変換を保持していく。

### 3.3 特徴誤差から損失を返す
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L361

### 3.3 剛体変換から損失を返す
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L363

### 3.4 最終的な損失を返す
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L378
「特徴誤差」「剛体変換」「エンコーダー・デコーダー」の損失を加味した最終損失を返す。


## 4. 損失関数の最適化
https://github.com/XiaoshuiHuang/fmr/blob/d2a59925bb455c5e432a58cb8272780bac614248/model.py#L393