OpenCV 5.0.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 5.0.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
カスケード分類器

次のチュートリアル: カスケード分類器の学習

原著者Ana Huamán
互換性OpenCV >= 3.0

目的

このチュートリアルでは、

  • Haarカスケードによる物体検出の仕組みを学ぶ。
  • Haar特徴ベースのカスケード分類器を用いた顔検出と目検出の基礎を見ていく
  • We will use the cv::CascadeClassifier class to detect objects in a video stream. Particularly, we will use the functions:

理論

Haar特徴ベースのカスケード分類器を用いた物体検出は、Paul ViolaとMichael Jonesが2001年の論文 "Rapid Object Detection using a Boosted Cascade of Simple Features" で提案した効果的な物体検出手法である。これは機械学習ベースのアプローチであり、多数の正例画像と負例画像からカスケード関数を学習する。学習されたカスケード関数は、その後ほかの画像中の物体検出に用いられる。

ここでは顔検出を扱う。まずアルゴリズムは、分類器を学習するために多数の正例画像 (顔の画像) と負例画像 (顔のない画像) を必要とする。次に、そこから特徴を抽出する必要がある。このために、下の画像に示すHaar特徴が用いられる。これらはちょうど畳み込みカーネルのようなものである。各特徴は、黒い矩形の下のピクセルの総和から白い矩形の下のピクセルの総和を引くことで得られる単一の値である。

image

次に、各カーネルのあらゆるサイズと位置を用いて多数の特徴を計算する。(これにどれほどの計算量が必要か想像してみてほしい。24x24のウィンドウでさえ160000を超える特徴が生じる)。各特徴の計算では、白と黒の矩形の下のピクセルの総和を求める必要がある。これを解決するため、彼らは積分画像 (integral image) を導入した。画像がどれほど大きくても、ある1ピクセルの計算をわずか4ピクセルだけを使う演算に削減できる。素晴らしいと思わないか? これにより処理が非常に高速になる。

しかし、計算したこれらの特徴のうち、ほとんどは無関係である。たとえば、下の画像を見てほしい。上段は2つの良い特徴を示している。最初に選ばれた特徴は、目の領域が鼻や頬の領域よりもしばしば暗いという性質に着目しているようである。2番目に選ばれた特徴は、目が鼻筋よりも暗いという性質に依拠している。しかし、同じウィンドウを頬やそのほかの場所に適用しても無関係である。では、160000以上の特徴の中から最良の特徴をどのように選び出すのか? それは Adaboost によって実現される。

image

このために、すべての学習画像に対して一つ一つの特徴を適用する。各特徴について、顔を正例と負例に分類する最良のしきい値を求める。当然ながら、誤りや誤分類が生じる。誤り率が最小となる特徴を選択する。つまり、それらは顔画像と非顔画像を最も正確に分類する特徴である。(この処理はこれほど単純ではない。最初は各画像に等しい重みが与えられる。各分類の後、誤分類された画像の重みが増やされる。そして同じ処理が行われる。新しい誤り率が計算される。新しい重みも同様である。この処理は、必要な精度または誤り率が達成されるか、必要な数の特徴が見つかるまで続けられる)。

最終的な分類器は、これらの弱分類器の重み付き和である。弱いと呼ばれるのは、それ単独では画像を分類できないが、ほかと合わさると強い分類器を形成するからである。論文によれば、わずか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でのHaarカスケード検出

OpenCVは学習メソッド(カスケード分類器の学習 を参照)や、cv::CascadeClassifier::load メソッドで読み込める事前学習済みモデルを提供している。事前学習済みモデルはOpenCVインストール内のdataフォルダにあるか、こちらで見つけることができる。

以下のコード例では、学習済みのHaarカスケードモデルを用いて画像中の顔と目を検出する。まず cv::CascadeClassifier を作成し、必要なXMLファイルを cv::CascadeClassifier::load メソッドで読み込む。その後、cv::CascadeClassifier::detectMultiScale メソッドで検出を行い、これは検出された顔または目の境界矩形を返す。

結果

  1. 以下は、上記のコードを実行し、内蔵Webカメラの映像ストリームを入力として使用した結果である:

プログラムが haarcascade_frontalface_alt.xml および haarcascade_eye_tree_eyeglasses.xml ファイルのパスを見つけられることを確認すること。これらは opencv_contrib/modules/xobjdetect/data/haarcascades にある。

  1. これは、顔検出にファイル lbpcascade_frontalface.xml (LBP学習済み) を使用した結果である。目については、チュートリアルで使用したファイルを引き続き使用する。

追加リソース

  1. Paul Viola and Michael J. Jones. Robust real-time face detection. International Journal of Computer Vision, 57(2):137–154, 2004. [296]
  2. Rainer Lienhart and Jochen Maydt. An extended set of haar-like features for rapid object detection. In Image Processing. 2002. Proceedings. 2002 International Conference on, volume 1, pages I–900. IEEE, 2002. [172]
  3. 顔検出とトラッキングに関するビデオ講義
  4. Adam Harveyによる顔検出に関する興味深いインタビュー
  5. Adam HarveyによるVimeo上のOpenCV Face Detection: Visualized