カスケード型分類器 =========================== .. highlight:: python Haar Feature-based Cascade Classifier for Object Detection ---------------------------------------------------------- ここで述べられるオブジェクト検出器は, Paul Viola :ref:`Viola01` によって提案され,Rainer Lienhart :ref:`Lienhart02` によって改良されたものです.まず,分類器(つまり, *haar-like特徴を用いるブースティングされた分類器のカスケード* )は,数百の正例と負例によって学習されます. 正例とは,同一のサイズ(例えば, 20x20)にスケーリングされた特定のオブジェクト(つまり,顔や車)を含むサンプル画像であり,負例とは,正例と同一サイズの任意の画像です. 学習が終わると,分類器は入力画像の(学習に用いられた物と同じサイズの)ROI に対して適用されます.その領域にオブジェクト(顔や車)が写っていると思われる場合は,分類器は「1」を出力し,それ以外では,「0」を出力します.画像全体からオブジェクトを探索するためには,画像中の探索窓を移動させながら,その個々の領域を分類器を用いて判別します.学習時とは異なるサイズのオブジェクトも検出できるように,分類器は簡単に「サイズ変更」できるように設計されており,これは画像自体のサイズを変更するよりも効率的です.そして,画像中からサイズ不明のオブジェクトを検出するためには,異なるスケールで複数回の探索処理が必要です. 分類器の名前にある「カスケード」という単語は,最終的に得られる分類器がいくつかの単純な分類器( *stages* )から構成される,という事を意味しています.この単純な分類器たちが ROI に対して次々に適用され,オブジェクト候補は,いずれかのステージで却下されるか,あるいは全てのステージを通過します.また,「ブーストされた」という単語は,カスケードの各ステージにおける単純な分類器自身が複合体である事を意味します.これらの単純な分類器は基本分類器から構成され,それには4種類の ``ブースティング`` 技法(重み付き投票)の内の1つが利用されます.現在のところ,Discrete Adaboost,Real Adaboost,Gentle Adaboost そして Logitboost がサポートされています.ここで利用される基本分類器は,少なくとも2つの葉を持つ決定木です. Haar-like 特徴はこの基本分類器の入力であり,その算出方法については後述します.現在のアルゴリズムでは次のような Haar-like 特徴を用いています: .. image:: ../../pics/haarfeatures.png 個々の分類器で用いられる特徴は,形状(1a, 2b など),ROI 内での位置,スケール(このスケールは検出ステージで用いられるスケールとは別物ですが,これら2つのスケールは乗じられます)によって規定されます.例えば,ライン特徴の3番目(2c)の場合,(2つの白ストライプと中央の黒ストライプを含む)特徴全体の矩形部分の画像ピクセルの和と,黒ストライプ部分の画像ピクセルの和を(領域サイズの違いを相殺するために)3倍したもの,との差分が出力となります.矩形領域全体のピクセル値の合計は,積分画像(以下の説明,および :ref:`Integral` を参照してください)を用いて高速に計算されます. 顔検出の簡単なデモンストレーション.検出された顔の周りに矩形を描きます: .. code-block:: python hc = cv.Load("haarcascade_frontalface_default.xml") img = cv.LoadImage("faces.jpg", 0) faces = cv.HaarDetectObjects(img, hc, cv.CreateMemStorage()) for (x,y,w,h),n in faces: cv.Rectangle(img, (x,y), (x+w,y+h), 255) cv.SaveImage("faces_detected.jpg", img) .. .. index:: HaarDetectObjects .. _HaarDetectObjects: HaarDetectObjects ----------------- `id=0.159743150894 Comments from the Wiki `__ .. function:: HaarDetectObjects(image,cascade,storage,scaleFactor=1.1,minNeighbors=3,flags=0,minSize=(0,0))-> detected_objects 画像からオブジェクト検出を行います. :param image: この画像の中からオブジェクトを検出します. :type image: :class:`CvArr` :param cascade: Haar分類器カスケードの内部表現. :type cascade: :class:`CvHaarClassifierCascade` :param storage: オブジェクト候補の矩形列を保存するメモリストレージ :type storage: :class:`CvMemStorage` :param scale_factor: スキャン毎にスケーリングされる探索窓のスケーリングファクタ.たとえば,これが1.1ならば,探索窓が10 % 大きくなります :type scale_factor: float :param min_neighbors: (これから1を引いた値が),オブジェクトを表す矩形を構成する近傍矩形の最小数となります.つまり, ``min_neighbors`` -1 より少ない数の矩形しか含まないグループは,全て棄却されます. ``min_neighbors`` が0 の場合は,グループ化が行われずに,オブジェクトの候補となる個々の矩形が全て返されます.これは,ユーザが独自のグループ化処理を行いたい場合に有用です :type min_neighbors: int :param flags: 処理モード.現在は, ``CV_HAAR_DO_CANNY_PRUNING`` のみ有効です.このフラグが指定されている場合,関数はCannyエッジ検出器を利用し,非常に多くのエッジを含む(あるいは非常に少ないエッジしか含まない)画像領域を,探索オブジェクトを含まない領域であると見なして棄却します.特定の閾値は顔検出用に調整されており,この場合,枝刈りにより処理が高速化されます :type flags: int :param min_size: 探索窓の最小サイズ.デフォルトでは,分類器の学習に用いられたサンプルのサイズが設定されます(顔検出の場合は :math:`\sim 20\times 20` ) :type min_size: :class:`CvSize` :param maxSize: 探索窓の最大サイズ.デフォルトでは,画像サイズに設定されます. この関数は,与えられた画像から,カスケードの学習対象となったオブジェクトを含むであろう矩形領域を検出し,それらの領域を矩形のシーケンスとして返します.これは,画像のスキャンを異なるスケールで複数回行います( :ref:`SetImagesForHaarClassifierCascade` を参照してください).毎回,各スケールにあった画像領域を処理対象とし, :ref:`RunHaarClassifierCascade` を用いて,分類器をこの領域に適用します.また,判別する領域数を減らすために,Cannyエッジ検出器を用いた枝刈り処理のようなヒューリスティックな手法を適用することもあります.処理されたオブジェクト候補矩形(分類器カスケードに渡された領域)が集められると,それらはグループ化され,さらに十分に大きいグループの平均矩形のみがシーケンスとして返されます.デフォルトパラメータ( ``scale_factor`` =1.1, ``min_neighbors`` =3, ``flags`` =0)は,正確ではあるが低速なオブジェクト検出用に調整されたものです.実際の動画像に対する,より高速な処理のためには,以下のような値が考えられます: ``scale_factor`` =1.2, ``min_neighbors`` =2, ``flags`` = ``CV_HAAR_DO_CANNY_PRUNING`` , ``min_size`` = *あり得る最小の顔サイズ* (例えばビデオ会議の場合は,画面全体の :math:`\sim` 1/4 から 1/16 ) この関数は,タプル ``(rect, neighbors)`` のリストを返します.ここで, rect はオブジェクトの範囲を示す :ref:`CvRect` であり,また neighbors は隣接矩形の個数を示します. .. doctest:: >>> import cv >>> image = cv.LoadImageM("lena.jpg", cv.CV_LOAD_IMAGE_GRAYSCALE) >>> cascade = cv.Load("../../data/haarcascades/haarcascade_frontalface_alt.xml") >>> print cv.HaarDetectObjects(image, cascade, cv.CreateMemStorage(0), 1.2, 2, 0, (20, 20)) [((217, 203, 169, 169), 24)] ..