![]() |
OpenCV 4.13.0
Open Source Computer Vision
|
前のチュートリアル: オプティカルフロー
次のチュートリアル: カスケード分類器の学習
| 原著者 | Ana Huamán |
| 互換性 | OpenCV >= 3.0 |
このチュートリアルでは、
Haar特徴ベースのカスケード分類器を用いた物体検出は、Paul ViolaとMichael Jonesが2001年の論文 "Rapid Object Detection using a Boosted Cascade of Simple Features" で提案した効果的な物体検出手法である。これは機械学習ベースのアプローチであり、多数の正例画像と負例画像からカスケード関数を学習する。学習されたカスケード関数は、その後ほかの画像中の物体検出に用いられる。
ここでは顔検出を扱う。まずアルゴリズムは、分類器を学習するために多数の正例画像 (顔の画像) と負例画像 (顔のない画像) を必要とする。次に、そこから特徴を抽出する必要がある。このために、下の画像に示すHaar特徴が用いられる。これらはちょうど畳み込みカーネルのようなものである。各特徴は、黒い矩形の下のピクセルの総和から白い矩形の下のピクセルの総和を引くことで得られる単一の値である。
次に、各カーネルのあらゆるサイズと位置を用いて多数の特徴を計算する。(これにどれほどの計算量が必要か想像してみてほしい。24x24のウィンドウでさえ160000を超える特徴が生じる)。各特徴の計算では、白と黒の矩形の下のピクセルの総和を求める必要がある。これを解決するため、彼らは積分画像 (integral image) を導入した。画像がどれほど大きくても、ある1ピクセルの計算をわずか4ピクセルだけを使う演算に削減できる。素晴らしいと思わないか? これにより処理が非常に高速になる。
しかし、計算したこれらの特徴のうち、ほとんどは無関係である。たとえば、下の画像を見てほしい。上段は2つの良い特徴を示している。最初に選ばれた特徴は、目の領域が鼻や頬の領域よりもしばしば暗いという性質に着目しているようである。2番目に選ばれた特徴は、目が鼻筋よりも暗いという性質に依拠している。しかし、同じウィンドウを頬やそのほかの場所に適用しても無関係である。では、160000以上の特徴の中から最良の特徴をどのように選び出すのか? それは Adaboost によって実現される。
このために、すべての学習画像に対して一つ一つの特徴を適用する。各特徴について、顔を正例と負例に分類する最良のしきい値を求める。当然ながら、誤りや誤分類が生じる。誤り率が最小となる特徴を選択する。つまり、それらは顔画像と非顔画像を最も正確に分類する特徴である。(この処理はこれほど単純ではない。最初は各画像に等しい重みが与えられる。各分類の後、誤分類された画像の重みが増やされる。そして同じ処理が行われる。新しい誤り率が計算される。新しい重みも同様である。この処理は、必要な精度または誤り率が達成されるか、必要な数の特徴が見つかるまで続けられる)。
最終的な分類器は、これらの弱分類器の重み付き和である。弱いと呼ばれるのは、それ単独では画像を分類できないが、ほかと合わさると強い分類器を形成するからである。論文によれば、わずか200個の特徴でも95%の精度で検出が可能である。彼らの最終的な構成では約6000個の特徴を用いていた。(160000以上の特徴から6000個の特徴への削減を想像してみてほしい。これは大きな利得である)。
さて、これで画像を1枚用意する。各24x24のウィンドウを取り出す。それに6000個の特徴を適用する。顔かどうかを判定する。おや…これは少し非効率で時間がかかるのではないか? そのとおりである。著者らはそれに対する良い解決策を持っている。
画像において、その大部分は非顔領域である。したがって、あるウィンドウが顔領域でないかどうかを確認する単純な方法を用意するのが良い考えである。もし顔領域でなければ、一度で破棄し、二度と処理しない。代わりに顔があり得る領域に注力する。こうすることで、顔があり得る領域の確認により多くの時間を費やせる。
このために彼らは 分類器のカスケード (Cascade of Classifiers) という概念を導入した。6000個すべての特徴を1つのウィンドウに適用する代わりに、特徴を分類器の異なるステージにグループ化し、一つずつ適用する。(通常、最初の数ステージにはずっと少ない特徴しか含まれない)。あるウィンドウが最初のステージで不合格となれば、それを破棄する。残りの特徴は考慮しない。合格すれば、2番目のステージの特徴を適用し、処理を続ける。すべてのステージを通過したウィンドウが顔領域である。なんとうまい計画だろう!
著者らの検出器は6000以上の特徴を38ステージに分け、最初の5ステージにはそれぞれ1, 10, 25, 25, 50個の特徴を持っていた。(上の画像の2つの特徴は、実際にAdaboostによって最良の2つの特徴として得られたものである)。著者らによれば、平均してサブウィンドウあたり6000以上のうち10個の特徴が評価される。
以上が、Viola-Jonesの顔検出がどのように機能するかについての単純で直感的な説明である。詳細は論文を読むか、追加リソースのセクションにある参考文献を参照してほしい。
OpenCVは学習手法 (カスケード分類器の学習 を参照) または学習済みモデルを提供しており、これらは cv::CascadeClassifier::load メソッドで読み込める。学習済みモデルはOpenCVインストール先のdataフォルダにあるか、こちら で見つけられる。
以下のコード例では、学習済みのHaarカスケードモデルを用いて画像中の顔と目を検出する。まず cv::CascadeClassifier を作成し、必要なXMLファイルを cv::CascadeClassifier::load メソッドで読み込む。その後、cv::CascadeClassifier::detectMultiScale メソッドで検出を行い、これは検出された顔または目の境界矩形を返す。
プログラムがファイル haarcascade_frontalface_alt.xml と haarcascade_eye_tree_eyeglasses.xml のパスを見つけられることを確認すること。これらは opencv/data/haarcascades にある