2016.10.17.
石立 喬

OpenCV3.1.0とVisual C++ 2015による画像処理と認識(16)

----- ブーストで、顔図形の分類と二次元座標の分類を試みる -----

 これは、「OpenCVとVisual C++による画像処理と認識(16)」をOpenCV3.1.0で書き直したもので、ブースティング全般の説明については、前資料を参照されたい。本資料で追加されているのは、二次元座標による二分類を、より詳細に試み、Boostタイプの全てで良好に分類できたもの、REALタイプを除いて良好だったもの、すべてのタイプで誤分類したものに分けたことである。

OpenCV3.1.0になって変わったところ
 すでに、ANN_MLPやSVMについて述べたのと同様に、Boostクラスでも、以下の変更が行われている。
1)Boostクラスは、create(生成)とパラメータ設定のsetBoostType、setWeakCount、setWeightTrimRateなどのみになった。
     パラメータには次のものがあるが、一般にはデフォルト条件で十分である。
     boostType = Boost::REAL ----- 他に、Boost::DISCRETE、Boost::LOGIT、Boost::GENTELEがある
     weakCount = 100 ----------- 弱識別器の数
     weightTrimRate = 0.95 ------- 訓練の繰返しごとに重みの小さい訓練用サンプルを減らす割合
2)Boost::Params構造体はなくなった。
3)train(訓練)、predict(分類)は、StatModel基底クラスのものを使う。
4)上記trainメソッドのlabels(分類のカテゴリ)は、CV_32F型からCV_32S型に変わった。

ブーストを使って、顔と非顔を判別する
 プログラムは、下記から成っている。
 ユーザー作成メソッド
 1)顔データ描画メソッドdrawFacesを用意する(図1)。
    引数は、描画先画像、描画位置、顔データ配列、顔データ番号である。
 2)ブーストにデータを与え、分類させ、結果を表示するメソッドtestBoostingを用意する(図2)。
    テスト用顔データ配列dataから顔データを一つずつ取り出して、一次元配列testとし、boost->predictを実行する。
    結果responseにより、"True"または"False"を描画先画像image上に表示する。
 プログラム本体
 3)訓練用顔データtraining_dataを準備する(図3)。
    それぞれ9部位の有無から成る真顔10個、偽顔10個の配列train_faceを作成し、Mat型化する。
    有無データは、1と0でも、1と-1でも同じ結果が得られたので、簡単のために前者を用いた。
 4)訓練用顔データを表示する(プログラムは図3、結果は図6)。
 5)訓練用ラベルtraining_labelsを準備する(図3)。
    真顔を1、偽顔を0として、配列train_faceに対応させる。
 6)Boostを生成し、訓練する(図3)。
    パラメータは特に指定しないで、デフォルト条件(BoostタイプはREAL)で使用する。
    Boostタイプを指定する場合には、boost->setBoostType(Boost::DISCRETE); などのコードを次行に記述する。
 7)テスト用データtest_data1を用意し、testBoostingメソッドを呼び出して、結果を表示する(図5)。
    test_data1は、訓練に使用した顔データからの抜粋10個から成る。
 8)テスト用データtest_data2を用意し、testBoostingメソッドを呼び出して、結果を表示する(図5)。
    test_data2は、訓練に使用していないデータ10個から成る。


図1 顔データを描画するメソッドを用意する



図2 ブーストを動作させるメソッド、顔データを表示し真偽の分類結果を表示する



図3 真顔10個、偽顔10個の訓練用顔データを準備する



図4 訓練用顔データを表示し、訓練用の真偽ラベルを準備して、ブーストの訓練を行う




図5 二種類のデータで、ブーストをテストし、判定結果を表示する


得られた結果
 まず最初に訓練用データのみを表示したのが図6で、上は真顔、下は偽顔である。
 訓練用顔データから、真顔5個、偽顔5個を選んで、BoostタイプをデフォルトのREALにして、testBoostingを実行させた結果が図7の上半分で、正しく分類されていることが分かる。
 訓練に使用していない顔データを使用して、同様にtestBoostingを行った結果を図7の下半分に示す。なんとなく納得できる結果が得られている。
 なお、REAL以外のすべてのBoostタイプでも試みたが、全く同じ結果が得られた。


図6 真顔と偽顔に分けて、訓練用データを表示する



図7 訓練に使った顔データの一部(上)と使っていない顔データ(下)での分類結果


ブーストで二次元座標を二分類する
 
SVMを用いて二次元座標データを分類する「OpenCV3.1.0とVisual C++ 2015による画像処理と認識(15)」と同様な内容を、ブーストで試した。図8はそのプログラム(説明は、前記資料にあるので省略)で、Boostパラメータは、タイプを色々な種類に変更できるようにした(例はDISCRETEを使用)。
 DISCRETE、REAL、LOGIT、GENTLEのすべてのタイプで良好な結果が得られたパターンの例を図9に示す。同じパターンを反時計方向に90°回転させたものでも、結果は良好であった。他にも、X方向またはY方向に線対称な数種のパターンが正常に分類できた。
 REALを除くタイプで良好だったものを図10に示す。図11は、図10と同じパターンで、REALによる誤った分類結果を示す。各パターンを反時計方向に90°回転させたものでも、結果は同様であった。
 いずれのBoostタイプでも正常に分類できなかったパターンの例を図12に示す。図は、DISCRETEタイプによる分類結果で、Boostタイプによっては、これと異なる誤分類もあった。



図8 二次元座標値を、ブーストで二分類するプログラム



図9 すべてのBoostタイプで正しく分類できたパターンの例



図10 REAL以外のBoostタイプでは良好に分類できたパターンの例



図11 REALだけが誤分類した例(他タイプでは正常だった図10に対応)



図12 すべてのBoostタイプで誤分類したパターンの例(DISCRETEの場合を示す)


結 論
   ブーストについてOpenCV3.1.0で変わった点は、他のMachine Learning関連クラスと同様に、BoostクラスのメンバーはcreateメソッドとsetBoostTypeなどの設定メソッドのみとなり、train、predictはStatMolelクラスのものを使用することである
 「OpenCVとVisual C++による画像処理と認識(16)」と同様に、顔に見立てた図形の9個の部位の有無を、ブーストに与えて訓練し、分類させた。訓練に使用した顔データは、すべてのBoostタイプで正確に分類でき、訓練に使用していない顔データでも、納得できる結果が得られた。
 「OpenCV3.1.0とVisual C++ 2015による画像処理と認識(15)」で、SVMで試みたのと同じ二次元座標の二分類では、Boostタイプの全てで正しく分類できたのは、ごく一部の単純なパターンのみで、REALタイプでの誤分類が目立ち、いずれのBoostタイプでも分類できないパターンもあった。
 BoostrタイプのREALは、優秀であるとしてデフォルトとして採用され、使用が推奨されているのもかかわらず、二次元座標の分類に限っては、残念な結果になった。




「Visual C++の勉強部屋」(目次)へ