論文まとめ：JointFlow: Temporal Flow Fields for Multi Person Pose Tracking

# はじめに  
BMVC 2018 から以下の論文のまとめ
A. Doering, et. al, "JointFlow: Temporal Flow Fields for Multi Person Pose Tracking"

arXiv：
https://arxiv.org/abs/1805.04596

コードの場所は不明

# 概要
1. 単眼RGBビデオカメラからの映像から同時に複数人に対して姿勢推定・トラッキングを行うモデル
2. real timeで行うことが可能
3. 時間軸方向への関節の推移を表すベクトル場であるTFF(temporal flow fields) を用いる

以下がtrackingの例。

<img width="874" alt="jointflow_img_10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/d96062fb-5b63-ca70-90f1-3b84650b8ce0.png">

いずれもposetrack dataset に対する推論。上２つの行が車道のシーン、下２つの行がサッカーのシーン。

各列は左から右への時間推移だと思うが、同じ人に対して同じ色の骨格が塗られているので、同一の人物と推定されているだろう。


# アーキテクチャ 
アーキテクチャの全体像

以下の図が全体像。

<img width="884" alt="jointflow_img_00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/e5735417-7239-0c93-c27e-51b9d6fb7189.png">

１）左から t-1 時の画像 $I_{t-1}$ と t 時の画像 $I_t$ を入力する。

２）それぞれに対してCNNで特徴量を抽出する。

３）特徴量から各時間において関節の位置と四肢のベクトルを推定し、骨格を推定する。

４）一方で各時間における関節位置から関節の推移を推定する。


### 定義等  
$p_j = (x_j, y_j)$ ：関節 j の２次元座標  

$P= \left\\{ p_j \right\\}_{i:J} $ ：ある人の J 個ある関節群  

$I_t$ ： ビデオの t フレーム目の画像

$N_t$ ：ビデオの t フレーム目の画像内における人の数  
  
$\mathcal{P}_t = \\{ P^{1}_t, \cdots ,  P^{N}t \\}$ ：t フレーム目の姿勢群

### temporal flow fields 
TFF(temporal flow fields) はこの論文の中核である。

中身は、OpenPoseのPAF(part affinity fields)とほぼ同じ。

PAFはあるフレーム内における関節 j から関節 j' への単位ベクトルを表す場だったが、TFFは t-1 フレームにおける関節 j から t フレームにおける関節 j への単位ベクトルを表す場に変わっただけ。

まず t フレームにおける k 番目の人の関節 j を

```math
p^t_{j,k} \in P^k_t
```

で表す。単位ベクトル $\nu$ を k さんの j 関節におけるフレーム間の移動を正規化したものと考えると

```math
\begin{eqnarray*}
\nu &=& \frac{p^t_{j,k} - p^{t-1}_{j,k}}{\| p^t_{j,k} - p^{t-1}_{j,k} \|_2}\\
 &=& \frac{p^t_{j,k} - p^{t-1}_{j,k}}{\lambda_{j,k}}\\  
\end{eqnarray*}
```

次に以下の図のように $\nu$ と垂直な $\nu_{\perp}$ を定義する。

<img width="882" alt="jointflow_img_01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/f4eab2b5-5b80-0530-e64a-027f57c265ad.png">

以下のような領域 $\Omega_{j,k}$ を用いて、画像上の点 p がTFFに属する（$p \in \Omega_{j,k}$）か否かを判別する。

```math
\Omega_{j,k} = \left\{ p | 0 \leq \nu \cdot (p-p^{t-1}_{j,k}) \leq \lambda_{j,k} \land | \nu_{\perp} \cdot (p-p^{t-1}_{j,k}) | \leq \sigma \right\}
```

$\sigma$ はパラメータ。

つまり、$\Omega_{j,k}$ は

<img width="589" alt="jointflow_img_20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/a8cf4dd4-2f6d-42f2-1d76-2c656d2cc670.png">

こんな感じの領域。この領域内に p が入る時に値を $\nu$ とし、他を０とする。

```math
T^{*}_{j,k}(p) = \begin{cases}
    \nu & if \  p \in \Omega_{j,k} \\
    0 & otherwise.
  \end{cases}
```

１チャンネルの feature map に全ての人の関節 j に関するTFF をのせるので、関節 j のTFF は

```math
T^{*}_{j}(p) = \frac{1}{n_t (p)} \sum^K_{k=1} T^{*}_{j,k}(p)
```

となる。 $n_t (p)$ は non-zero となる $\nu$ の個数。

### アーキテクチャの詳細 

以下が詳細図。

<img width="888" alt="jointflow_img_02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/525cb532-2cd7-4fcb-719f-b341eefaadf2.png">

上側(a)部分に関してはほぼOpenPose。

本論文の中核(b)部分では、VGGからの特徴量（SVGG)とheatmapを入力とし、7x7 convで５回、1x1 convで２回畳み込んだ後にTFFを推定する。

### loss
(b)部分の loss は以下のようにL2で求める。

```math
\mathcal{L} = \sum^J_{j=1} \sum_{p\in \Omega} M(p) \cdot \| T^{*}_j (p) - T_j(p) \|^2_2
```

$T^{*}_j (p)$ は ground truthの TFF、$M(p)$ はバイナリーマスクで、アノテーションされてない領域に対して０とする。

#推論時の骨格トラッキング  
### 問題設定 

求まったTFFなどから骨格形成、およびトラッキングを行うロジックは、以下のように $P\_t \in \mathcal{P}\_t \ $ と $  \ P'\_{t-1} \in \mathcal{P}\_{t-1}$ からなる bipartite graph $\mathcal{G}$ に関するエネルギー最大化問題を解くことで達成する。

```math
\newcommand{\argmax}{\mathop{\rm arg~max}\limits}
\begin{eqnarray}
\hat{z} &=& \argmax_z \sum_{P_t \in \mathcal{P}_t} \sum_{P'_{t-1} \in \mathcal{P}_{t-1}} \Psi_{P_t, P'_{t-1}} \cdot z_{P_t, P'_{t-1}} \\
 &s.t.& \forall P_t \in \mathcal{P}_t, \sum_{P'_{t-1} \in \mathcal{P}_{t-1}} z_{P_t,P'_{t-1}} \leq 1 \ and \ \forall P'_{t-1} \in \mathcal{P}_{t-1}, \sum_{P_{t} \in \mathcal{P}_{t}} z_{P_t,P'_{t-1}} \leq 1\\  
\end{eqnarray}
```

ここで $z\_{P\_t, P'\_{t-1}} \in \\{ 0,1 \\}$ はindicator関数で、$P\_t \in \mathcal{P}\_t \ $ と $  \ P'\_{t-1} \in \mathcal{P}\_{t-1}$ とが対応している時に１、他は０となる。

また binary potential $\Psi\_{P\_t, P'\_{t-1}}$ は $P_t$ と $P'_{t-1}$ との類似度を表す。

よって、このエネルギー関数を最大化させることは $P\_t$ と $P'\_{t-1}$ とが対応している組に関して、その類似度を最大化させること。

ただし、条件から対応する $P\_t$ と $P'\_{t-1}$ とはそれぞれの点において１つ以下である。

### 最適化の手法 
上記のエネルギー最大化問題を解くため、

```math
Z^t_j = \left\{ z^{p_{t-1},p_t}_j \mid P_t \in \mathcal{P}_t, P_{t-1} \in \mathcal{P}_{t-1}  \right\}
```

なる edge から構成される subgraph $\mathcal{G}_j$ を考える。つまり以下の図のようにフレーム t および t-1 において関節 j と推定された全ての点に関するグラフである。

<img width="382" alt="jointflow_img_03 _2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/f6ea4bd6-33e2-5b77-88e6-3930d5d78f97.png">

この組み合わせに関して以下を求める。

```math
E_{aggr}(p^{t-1}_{j,m}, p^t_{j,n}) = \int_{o=0}^{o=1} T_j(i(o))^T \frac{p^t_{j,n} - p^{t-1}_{j,m}}{\| p^t_{j,n} - p^{t-1}_{j,m} \|_2} do,
```

ここで $i(o) = (1-o)\cdot p^{t-1}\_{j,m} + o\cdot p^t\_{j,n}$ とする。つまり $p^{t-1}\_{j,m} $ から $p^t\_{j,n}$ への直線経路。これに沿ってTFFとedgeの単位ベクトルとの内積を線積分するので、TFFが両nodeを対応すると考えているなら1に近い大きな値になるハズ。

ただこれだとTFFに基づいて対応するnodeを求めるため、対象の人の関節位置が動いてないと計算できない。そこで両node間のユークリッド距離 $\Delta p^t\_{j,m,n} = \left\| p^t\_{j,n} - p^{t-1}\_{j,m} \right\|\_2$ を用いて

```math
E_j ( p^{t-1}_{j,m}, p^t]{j,n}) = \begin{cases}
    E^T_{aggr} (p^{t-1}_{j,m}, p^t_{j,n}) & if \ \Delta p^t_{j,m,n} \geq \tau_{\Delta} \\
    1 & if \ \Delta p^t_{j,m,n} < \tau_{\Delta}
  \end{cases}
```

とする。 $\tau\_{\Delta}$ は閾値。

つまり、両nodeの距離が閾値を下回る時は１（対応）とし、上回る時は $E\_{aggr}$ を計算する。

こうして骨格 $j$ ごとに求まった $E_j$ の大小で t-1 フレームと t フレームの骨格を対応づけると、t-1 フレームの k さんの右肩と t フレームの m さんの右肩が対応づけられる一方で、t-1 フレームの k さんの左肩と t フレーム目の n さんの左肩が対応づけられるという状況も生じうる。

そこで、PAFにより定まった m さんの骨格、 n さんの骨格を基準として、人ベースでの対応づけとする。

$\Psi\_{P^m\_{t-1},P^t\_{t}}$ を $P^m\_{t-1}$ さんと $P^t\_{t}$ さんとの全ての骨格の対応づけと考えて、

```math
\Psi_{P^m_{t-1},P^t_{t}} = \sum^J_{j=1} \mathbb{1} (P^{t-1}_{j,m}, P^t_{j,n}) \cdot E_j(P^{t-1}_{j,m}, P^t_{j,n})
```

とする。ここで indicator関数 $\mathbb{1} (P^{t-1}\_{j,m}, P^t\_{j,n})$ は両方の関節が検出された場合に1、他を0とする。

そうすると以下の図のように人と人との対応関係ごとに $\Psi\_{P^m\_{t-1},P^t\_{t}}$ が求まるので、この値の大小で正しい対応関係を決めればいい。

<img width="452" alt="jointflow_img_03_3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/c867d01e-1398-478a-48a5-87578a0bed7d.png">

# 実装時のポイント
実装時のポイントは以下
1. ベースはOpenPoseのアーキテクチャだが、特徴量抽出部分でVGG19の10層を12層に変更する
2. 出力する関節の heat map は閾値 $\tau\_{NMS}$ により切り捨てる
3. まずOpenPose部分をMicrosoft COCO datasetと PoseTrack datasetの個々の画像で学習させる
4. 次にPoseTrack dataset をシーケンシャルに用いてTFF部分を学習させる
5. 推論時には４つのスケール（0.5, 1, 1.5, 2）の画像を入力し、その出力を平均して用いる

# 他の手法との比較  
PoseTrack dataset での他の手法との比較結果は以下。

<img width="850" alt="jointflow_img_06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/cbeafd87-4e95-661f-8ccc-e539b0c34ab9.png">

下段 test data で見ると、FlowTrackに次いで２番目のMOTAとなっている。ちなみに現在（19/6/9)ではtopdown方式のPOINetがMOTA=58.41で最もよい。