画像認識で使われるBINGのソースコードの使い方

#概要
ObjectnessのSOTAの１つであるBINGは論文・ソースコードともに[公開](http://mmcheng.net/bing/)されている。
本稿では，公開されているソースコードの使い方を中心に説明する。
手法自体の解説は参考文献を参照してください。

#ダウンロードとインストール
BINGの本家サイトからダウンロードできる。
ダウンロードしたソースコードの解凍には鍵が必要だが，これは本家サイトで利用目的のアンケートに答えればもらえる。
このソースコードはOpenCVを利用しているので，事前にインストールが必要である。
このソースコードはLibLinear（大規模なデータに使えるオープンソースの線形クラスタリングライブラリ）を利用しているが，こちらはダウンロードしたソースコードに一緒に含まれているので，事前にインストールする必要はない。


#ファイル構成
objectness/
　├ resource/
　|　└ 省略
　├ header/
　|　└ 省略
　└ source/
　 　├ Cmfile.cpp
　 　├ CmShow.cpp
　 　├ DataSetVOC.cpp
　 　├ FilterBING.cpp
　 　├ Main.cpp
　 　├ Objectness.cpp
　 　└ stdafx.cpp

##Main.cpp
ここから始まる。基本的に書き換えるのはここだけ。
あとは用意されているクラスから呼び込めばよい。
DataSetVOCクラスからデータセットを読み込み，ObjectnessクラスでBINGの学習・結果の出力を行う。

##DataSetVOC.cpp
データセットの読み込みを担当しているクラス。
VOC2007のフォルダ構造をもとに読み込みを行う。
異なるデータセットや自作のデータセットはVOC2007のフォルダ構造に習って修正しよう。


VOC2007/
　├ Annotations/
　|　├ 000001.yml
　|　├ 000002.yml
　|　├ ・・・
　|　└ ・・・
　├ ImageSets/
　|　└ Main/
　|　　　├ class.txt
　|　　　└ test.txt
　|　　　└ train.txt
　└ JPEGImages/
　 　├ 000001.jpg
　 　├ 000002.jpg
　 　├ ・・・
　 　└ ・・・

```cpp:main.cpp
DataSetVOC voc2007("C:/dataset/root/path/");
voc2007.loadAnnotations();
```
データセットの読み込みは2行で完了！
用途の分からない関数も多数あるので注意！

##Objectness.cpp
BINGの学習・結果の出力を行うクラス。

```cpp:main.cpp
double base  = 2   // ウィンドウの大きさの量子化の底値
int W        = 8   // ウィンドウの大きさ
int NSS      = 2   // Non-maximum size suppressの大きさ
int numPerSz = 130 // 出力候補の数
vector<vector<Vec4i>> boxesTests;
Objectness objNess(voc2007, base, W, NSS);  // オブジェクト生成
objNess.getObjBndBoxesForTestsFast(boxesTests, numPerSz); // 学習
```

基本，上の数行で学習・結果の出力が完了する。
このクラスには他にもいくつか便利なクラスが用意されている。
（グラフ出力してくれる関数もあるが，matlabで見る必要あり）
以下でobjectnessの関数を見ていきます。

###Objectness::getObjBndBoxesForTestsFast
学習関数。準備したAnnotationとImageをもとに学習を行い，学習結果を出力する。こちらの関数は，MAXBGR色空間でBING処理する。
###Objectness::getObjBndBoxesForTests
学習関数。getObjBndBoxesForTestsFastと同様で，準備したAnnotationとImageをもとに学習を行い，学習結果を出力する関数。こちらの関数は，全ての色空間でBING処理する。
###Objectness::illuTestReults
描画関数。事前に学習関数を呼び出す必要がある。用意したAnnotationの矩形領域ごとに，学習で得られた結果の中から最もカバー率の高い矩形領域を選択し描画する。したがって，前処理としてBINGを行い，後処理で適切に矩形を選択することが出来る最良の結果がこの関数によって得られる。
###Objectness::evaluatePerClassRecall
描画関数。
###Objectness::setColorSpace
色空間を設定。BGR，HSV，GRAY SCALEから選べる。
###Objectness::trainObjectness
BINGの学習データ取得までの一連の処理。
###Objectness::loadTrainedModel
wS1ファイルからFilter.pngを作成。もしwS2ファイルがあれば，それを読み込む。
###Objectness::getObjBndBoxes
Test時に呼ばれる関数。画像を入力し，predictBBoxSIとpredictBBoxSIIを行う。
###Objectness::trainSVM
###Objectness::generateTrainData
データセットから，訓練データ（idxファイル，xPファイル，xNファイル）を作成。
###Objectness::getFeature
画像から矩形を切り出し，一辺Wの正方形にリサイズし，勾配画像に変換し，正規化したものを出力。
###Objectness::gtBndBoxSampling
与えられた矩形をもとに複数の矩形を生成し，その中でかぶり具合が閾値以上（ソースでは0.5）の矩形座標と矩形サイズを抽出。
###Objectness::trainStageI
xPファイル，xNファイルをもとにtrainSVMで学習し，その結果をwS1ファイルに出力。
これは論文のstage1に該当し，positive training data と negative traineing dataを用いてlinearSVMによってモデルWを求めている。
###Objectness::trainStageII
これは論文のstage2に該当し，NMSを用いて矩形サイズの評価を行っている。
###Objectness::predictBBoxSI
画像をリサイズし，勾配に変換し，テンプレートマッチングし，評価・矩形座標を算出。
###Objectness::predictBBoxSII
###Objectness::nonMaxSup
###Objectness::gradientMag, Objectness::gradientRGB, Objectness::gradientGray, Objectness::gradientHSV, Objectness::gradientXY
画像から勾配画像を作成。


##FilterBING.cpp, CmFile.cpp, CmShow.cpp, stdafx.cpp

#設定変数
_base, _W, _NSS, _maxT, _minT, _numT, _Clr


#生成ファイル
BINGの出力ファイルは{dataset path}/resultsと{dataset path}/localに格納される。
##/results/BBoxesB{B}W{W}{ColorSpace}/
テストデータごとのproposal結果が格納されている。先頭行はproposal数。
##/results/Filter.png
BINGで学習したフィルタを可視化したもの。
##/results/ObjNessB{B}W{W}{ColorSpace}.xP
全ての画像のpositive training data を集めたファイル。positive training data とは，1枚の画像から，訓練データで与えられたそれぞれのアノテーションに対しgtBndBoxSamplingしそれぞれをgetFeatureしたもの。すなわち，訓練データとそれに類似したデータの集合のNG特徴である。このデータのcolは画像の大きさ，rowはデータ数を表す。
##/results/ObjNessB{B}W{W}{ColorSpace}.xN
全ての画像のnegative training data を集めたファイル。negative training data とは，一枚の画像からランダムに矩形を切り出し，訓練データで与えたどの矩形とのかぶり具合も閾値以下（ソースでは0.5）であるものを対象に，getFeatureしたもの。すなわち，訓練データには当てはまらないデータの集合のNG特徴である。このデータのcolは画像の大きさ，rowはデータ数を表す。
##/results/ObjNessB{B}W{W}{ColorSpace}.idx
xPファイル作成時に集めた矩形の中で，閾値以上（ソースでは50）出現した矩形のサイズを出力。colは1で，rowは矩形のサイズの種類の数だけある。
##/results/ObjNessB{B}W{W}{ColorSpace}.wS1
学習したフィルタ。フィルタの大きさと同一。
##/results/ObjNessB{B}W{W}{ColorSpace}.wS2
Windowごとの補正係数。colは2で，rowは矩形のサイズの種類の数だけある。

#用語
##PAMI
Pattern Analysis and Machine Intelligence
##IJCV
International Journal of Computer Vision
##NMS
Non-maximal suppression(局所的に最大値以外を0に抑える)
DoG処理によりエッジ画像を取得したら、次はNon-Maximum suppressionという処理を行います。これは日本語で言うと「最大でない値は(すべて)値を抑える(=値をゼロにする)」という意味の処理です。つまりは、DoG画像で既に大体のところ浮かび上がっているエッジ候補の白色領域について、エッジとみなせる所以外をすべて黒(0)に抑えてしまう処理です。この処理の目的は「細線化を行い、DoG画像の時点よりもエッジ部分だけを残す画像をつくる」という点にあります。
処理の手順ですが、まずはDoG画像の各ピクセルにおいて、エッジの回転方向θの値を求めます。次に、各注目画素において、その法線方向に沿った直線上で隣り合う2つの画素での値と比較し、その注目画素が3つの中で最大値を取っている注目画素のみを画素値255(白)とし、それ以外の画素値を0(黒)に変更します。白になった画素は法線方向に隣の2つの画素の勾配値より自身の勾配値が高い場所ですので、山の頂点か谷の底である境界を示しており、細線化後に残すべき画素だと言えるでしょう。
こうしてDoG画像上の各画素において、その法線方向で最大の値を持つ画素のみが境界の端点として残るので、エッジが細線化されて細い輪郭に変わるわけです。

#参考文献
- [本家サイト](http://mmcheng.net/bing/)
- [よくわかるBING](http://www.slideshare.net/takmin/cvprbing)
- [本家コード Github](https://github.com/bittnt/Objectness)
- [pythonWrapper Github](https://github.com/alessandroferrari/BING-Objectness)