顔検出用のプログラムを動かすまでのメモ

とりあえず、OpenCVを使って顔検出したい。

手順

- OpenCVのインストール
- object-markerでアノテーションを作成
- create-samplesでvecファイルを生成
- vecを元にカスケード生成
- カスケードを元に、サンプル作成

※アノテーション=画像に対する特徴箇所(座標, 大きさ)
※カスケード＝検出器

# OpenCVのインストール
brewでぶっこんだ

```
brew tap homebrew/science

cd /usr/local/Library/Taps/homebrew-science
brew install OpenCV 

# 必要であれば適宜ライブラリ切替
 brew switch opencv 2.4.8.2
 brew switch libpng 1.5.18
```

>参考: MacにHomebrewをインストールする - Qiita http://qiita.com/is0me/items/475fdbc4d770534f9ef1


# アノテーションの作成
 object-markerを使ってアノテーションを作成する。以下から、windows用のバイナリをダウンロードする。

>物体検出/追跡研究者のための画像アノテーションツール ObjectMarker - >takminの書きっぱなし備忘録 http://d.hatena.ne.jp/takmin/20100930/1285848450

## object-markerの簡単な使い方
- 上記サイトでダウンロードし、zip解凍
- rawdataディレクトリに対象の画像を保存（顔画像等）
 - 1000枚ぶっこめば使用に耐えうるらしい（ソースは理由があって出せない）
- ObjectMarker.exeを起動
- 「対象にした部位をマウスで囲みEnter」これをたくさんやる
- 成果物がannotation.txtとして出力されるのでこれを利用する（適宜リネーム）

## 注意点
 - 不正な画像ヘッダや、ふつうじゃないファイル名の画像を突っ込むと落ちるようなので注意

##生成ファイル例
フォーマット: ファイル名 部位の数 x1 y1 w1 h1 x2 y2 w2 h2...

```annotation.txt
rawdata/audrybt1.jpg 1 128 36 49 50 
rawdata/albert.jpg 2 63 23 34 33 55 14 47 47 
rawdata/albert.jpg 3 63 23 34 33 55 14 47 47 56 16 44 41
```


# 正解データのvecファイルを生成
object-markerで生成したアノテーションを利用し、正解データのvecファイルを生成する。out-face.vecとして保存。
なお、vecはvectorの略だと思われる

```
% OpenCV_createsamples -info annotation.txt -vec vec-files/out-face.vec -num 200 -w 24 -h 24
```

# カスケードを生成する前に
## 不正解画像を用意
適当に不正解画像（顔写ってない画像）を用意し、rawdata-ngに保存。1000枚ぐらい。
保存したら不正解画像一覧を「nagativelist.txt」として生成。

```
% ls -1 rawdata-ng/ | sed -e 's/*$//g' -e 's/^/rawdata-ng\//g' > nagativelist.txt

% head nagativelist.txt
rawdata-ng/001.jpg
rawdata-ng/002.jpg
rawdata-ng/003.jpg
...
```

# カスケードを生成
カスケードとは、所謂検出器のこと。


>カスケード型分類器 — opencv 2.2 (r4295) documentation http://>opencv.jp/opencv-2.2/py/objdetect_cascade_classification.html


nposは正解画像枚数、nnegは不正解画像を記載。// 1000枚ぐらい画像用意したいなぁ

枚数間違えたら途中で落ちるので注意
また、-bg用に作った「nagativelist.txt」を「data/」に格納して、コマンド実行したらおちたので、そこも注意
テストなので一旦枚数は絞っておく

```
% mkdir -p data/out-face
% opencv_traincascade -data ./data/out-face -vec ./vec-files/out-face.vec -bg nagativelist.txt \
-numPos 80 -numNeg 100 precalcValBufSize 1024 -precalcIdxBufSize 1024  -baseFormatSave
```

## 旧カスケード生成手順(やんなくていい）
はじめ、下記のopencv_haatrainingでトレーニングファイル作ってたけど、非推奨らしい。
やり方調べたので一応書いておく。

```
% OpenCV_haartraining -data out-face.xml -vec vec-files/out-face.vec -bg nagativelist.txt -npos 1000 -nneg 1000 -w 24 -h 24

# 妥協した枚数
% OpenCV_haartraining -data out-face.xml -vec vec-files/out-face.vec -bg nagativelist.txt -npos 100 -nneg 300 -w 24 -h 24
```

# カスケードの使い方
生成物が『data/out-face/casscade.xml』として、保存されてるので、それを利用する。

```
gem install ruby-opencv
```

# サンプル実行
rubyでcascade読み込んで、画像渡して検出させるサンプル
ライブラリ依存で、バグるかもしれないがんばれ

```obj_detect.rb
#!/usr/bin/env ruby

require 'opencv'
include OpenCV

if ARGV.size != 1
  puts 'Usage: ruby #{__FILE__} Image'
  img = './img/test.jpg'
else
  img = ARGV[0]
end

img = IplImage.load(img)

faces = OpenCV::CvHaarClassifierCascade.load './cascade.xml'

faces.detect_objects(img.to_CvMat) { |rect|
  img.rectangle!(rect.top_left, rect.bottom_right, :color => CvColor::Red)
}

window = GUI::Window.new('detect face')
window.show(img)
GUI::wait_key
```

以下コマンドで実行

```
ruby ./obj_detect.rb face.jpg
```
![画像検出サンプル](http://i.imgur.com/bbq7RVC.png)

# メモ
一つの顔に、四角がいっぱい出てしまう場合、統合するといいかもしれない
ヒント：Nearest Neighbor（最近傍決定則）

ユークリッド距離の計算式
![ユークリッド距離](http://i.imgur.com/Aofstzh.jpg)

# 参考資料
- アイエスエス株式会社　"Innovative System Solutions" - OpenCVを使った機械学習 http://www.japan-iss.co.jp/?p=1440
- OpenCV 2.4.2で分類器を作る - shkh's blog http://shkh.hatenablog.com/entry/2012/11/03/052251
- OpenCV 備忘録: OpenCVのカスケード分類器の学習の章を訳してみた http://iwaki2009.blogspot.jp/2013/12/opencv_11.html