Dense Trajectoryにおけるtrajectory位置情報


[Dense trajectory](http://lear.inrialpes.fr/people/wang/dense_trajectories) はコンピュータビジョンの動作認識問題で最近よく使われる特徴記述で，密な点群を追跡し，その軌跡（dense trajectory）上の局所特徴量に基づいて高次特徴量を記述するというものです．コードは http://lear.inrialpes.fr/people/wang/dense_trajectories に公開されており，OpenCVとffmpegがあればコンパイルできます．


取り組む問題によっては，各フレームにおけるtrajecotryの位置を取得したくなるのですが，もとのコードのままだと，位置情報が特徴量ファイルに保存されないようです．


まず，先のリンク先のページを見ると，

> The following element are five descriptors concatenated one by one:

> Trajectory:    2x\[trajectory length\] (default 30 dimension) 
...

とあり，11次元目〜40次元目が位置情報にあたりそうです．

また，FAQを読むと，

> How can I recover the original trajectory coordinates?

> In the DenseTrack.cpp file:

> std::vector trajectory(trackInfo.length+1);
> for(int i = 0; i <= trackInfo.length; ++i)
>     trajectory[i] = iTrack->point[i]*fscales[iScale];

> The coordinates of a trajectory is saved in "std::vector<Point2f> trajectory". Here all the coordinates are mapped to the original resolution. You can output the trajectory coordinates right after that.

とあり，trajectory変数にその情報が格納されているようです．


ところが，実際に出力される特徴ベクトルの11次元目〜40次元目を見てみると（ここではx座標が格納されている```11:2:40```次元を見てみます）

```matlab
>> x(1,11:2:40)

ans =

  Columns 1 through 10

   -0.0114   -0.0110    0.0524    0.0558    0.0888    0.0497   -0.0926   -0.0850   -0.0523    0.0031

  Columns 11 through 15

    0.0259    0.0805    0.0810    0.1490    0.0575
```


となっており，負の値があったり，そもそも全て1未満の数値であったりと，なにかがおかしい…


### コードを読む

データの格納がされているのは，```DenseTrack.cpp```の168行目あたりです．

```cpp:DenseTrack.cpp(L168)
				// if the trajectory achieves the maximal length
				if(iTrack->index >= trackInfo.length) {
					std::vector<Point2f> trajectory(trackInfo.length+1);
					for(int i = 0; i <= trackInfo.length; ++i)
						trajectory[i] = iTrack->point[i]*fscales[iScale];
				
					float mean_x(0), mean_y(0), var_x(0), var_y(0), length(0);
					if(IsValid(trajectory, mean_x, mean_y, var_x, var_y, length)) {
						printf("%d\t%f\t%f\t%f\t%f\t%f\t%f\t", frame_num, mean_x, mean_y, var_x, var_y, length, fscales[iScale]);

						// for spatio-temporal pyramid
						printf("%f\t", std::min<float>(std::max<float>(mean_x/float(seqInfo.width), 0), 0.999));
						printf("%f\t", std::min<float>(std::max<float>(mean_y/float(seqInfo.height), 0), 0.999));
						printf("%f\t", std::min<float>(std::max<float>((frame_num - trackInfo.length/2.0 - start_frame)/float(seqInfo.length), 0), 0.999));
					
						// output the trajectory
						for (int i = 0; i < trackInfo.length; ++i)
							printf("%f\t%f\t", trajectory[i].x,trajectory[i].y);

```

結論から言うと，この```IsValid```関数が非常に曲者で，この中でtrajectory変数の値が書き換わってしまっていました．```IsValid```変数は```Descriptor.h```の中にあります．
まずは177行目を見ると，

```cpp:Descriptor.h(L177)
	float cur_max = 0;
	for(int i = 0; i < size-1; i++) {
		track[i] = track[i+1] - track[i];
		float temp = sqrt(track[i].x*track[i].x + track[i].y*track[i].y);

```

とあり，```track[i]```（=main関数の```trajectory```）にその差分が代入されてしまっています．まずはここを直します．

```cpp:Descriptor.h(L177)
		// track[i] = track[i+1] - track[i];
		// float temp = sqrt(track[i].x*track[i].x + track[i].y*track[i].y);
		float temp = sqrt((track[i+1]-track[i]).x*(track[i+1]-track[i]).x + (track[i+1]-track[i]).y*(track[i+1]-track[i]).y);
```

さらに下の方を見ていくと，位置がtrajectoryの長さ（正確には移動長の総和）で正規化されています．192行目

```cpp:Descriptor.h(L192)
	norm = 1./length;
	// normalize the trajectory
	for(int i = 0; i < size-1; i++)
		track[i] *= norm;
```

trajectory情報は```IsValid```関数が呼ばれた以降，どの入力にも使われないようですので，この部分をまるっとコメントアウトしても良いかと思います．あるいは，```length```変数は特徴ベクトルの6次元目に入っているので，以下のような掛け算によって，元の位置情報が出てきます．

```matlab
>> x(1,11:2:40) * x(1, 6)

ans =

  Columns 1 through 10

   57.0000   56.5570   56.1290   58.1660   60.3354   63.7844   65.7142   62.1172   58.8169   56.7860

  Columns 11 through 15

   56.9049   57.9097   61.0352   64.1834   69.9709
```

たぶん，Improved trajectoryの方も同じ問題があるはずなのですが，こっちはカメラ運動の推定があってもう少しややこしいので，今回は未検証です．