物体検出
■ 物体検出
OpenCVで用意されている物体検出は,(Haar-like特徴を利用した)ブーストされた弱分類器のカスケードを用いている. 細かいアルゴリズムに関しては,リファレンスおよびその他の参考文献に譲るが,分類器は大まかに以下のように構成されている.- Haar-like特徴を入力にとる決定木を,基本分類器とする.
- ブースティング技法を用いて,いくつかの基本分類器を複合させてステージ分類器が構成される.
- ステージ分類器が数珠つなぎに連結され,最終的なカスケードが構成される.
サンプル
顔の検出 cvHaarDetectObjects
あらかじめ学習された分類器を用いて入力画像中の顔を検出する
サンプルコード
#include <cv.h> #include <highgui.h> int main (int argc, char **argv) { int i; IplImage *src_img = 0, *src_gray = 0; const char *cascade_name = "haarcascade_frontalface_default.xml"; CvHaarClassifierCascade *cascade = 0; CvMemStorage *storage = 0; CvSeq *faces; static CvScalar colors[] = { {{0, 0, 255}}, {{0, 128, 255}}, {{0, 255, 255}}, {{0, 255, 0}}, {{255, 128, 0}}, {{255, 255, 0}}, {{255, 0, 0}}, {{255, 0, 255}} }; // (1)画像を読み込む if (argc < 2 || (src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR)) == 0) return -1; src_gray = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 1); // (2)ブーストされた分類器のカスケードを読み込む cascade = (CvHaarClassifierCascade *) cvLoad (cascade_name, 0, 0, 0); // (3)メモリを確保し,読み込んだ画像のグレースケール化,ヒストグラムの均一化を行う storage = cvCreateMemStorage (0); cvClearMemStorage (storage); cvCvtColor (src_img, src_gray, CV_BGR2GRAY); cvEqualizeHist (src_gray, src_gray); // (4)物体(顔)検出 faces = cvHaarDetectObjects (src_gray, cascade, storage, 1.11, 4, 0, cvSize (40, 40)); // (5)検出された全ての顔位置に,円を描画する for (i = 0; i < (faces ? faces->total : 0); i++) { CvRect *r = (CvRect *) cvGetSeqElem (faces, i); CvPoint center; int radius; center.x = cvRound (r->x + r->width * 0.5); center.y = cvRound (r->y + r->height * 0.5); radius = cvRound ((r->width + r->height) * 0.25); cvCircle (src_img, center, radius, colors[i % 8], 3, 8, 0); } // (6)画像を表示,キーが押されたときに終了 cvNamedWindow ("Face Detection", CV_WINDOW_AUTOSIZE); cvShowImage ("Face Detection", src_img); cvWaitKey (0); cvDestroyWindow ("Face Detection"); cvReleaseImage (&src_img); cvReleaseImage (&src_gray); cvReleaseMemStorage (&storage); return 0; }
// (1)画像を読み込む
関数 cvLoadImage()を用いて,顔を検出する対象となる(コマンド引数で指定された)画像を読み込む.
2番目の引数にCV_LOAD_IMAGE_COLORを指定することで,カラー画像として読み込む.
検出処理自体はグレースケール画像を対象に行われるが,検出結果を描画するために,カラー画像として読み込んでおく.
また,その処理のために,入力が像と同サイズのグレースケール画像(IplImage)を作成しておく.
// (2)ブーストされた分類器のカスケードを読み込む
学習によってあらかじめ獲得された,分類器のカスケードが記述されたxmlファイルを読み込む.
ここでは,OpenCVのサンプルに付属する正面顔画像学習結果の1つである,"haarcascade_frontalface_default.xml"を利用する.
// (3)メモリを確保し,読み込んだ画像のグレースケール化,ヒストグラムの均一化を行う
実際の顔検出の際に利用するメモリを確保,初期化する.
また,読み込まれたカラー画像をグレースケール画像に変更し,さらに,
関数 cvEqualizeHist()により,そのヒストグラムを均一化する.
// (4)物体(顔)検出
関数 cvHaarDetectObjects()により,画像から顔を検出する.
4番目の引数(1.11)は,探索ウィンドウのスケール変化を表しており,
今回の場合は,スケール毎の探索において,ウィンドウサイズが11[%]変化する事を示している.
また,5番目の引数は,オブジェクトを構成する近傍矩形の最小数を表しており,
これより少ない矩形から構成されるオブジェクトは,ノイズとして無視される.
つまり,実際のオブジェクトが存在する付近では,多少ずれた場所においてもオブジェクトを含む領域として認識されるはずなので,
1つのオブジェクトは,複数の矩形領域の集合として表される.
そうでない箇所(たとえば,その周辺に単一の矩形しか存在しないオブジェクト候補)は,
偶然カスケードをパスした領域として,無視される.
// (5)検出された全ての顔位置に,円を描画する
検出された全ての顔に対して,サイズと中心を求め,その場所に,円を描画する.
円の描画には,あらかじめ定めた8色を順次利用する.
// (6)画像を表示,キーが押されたときに終了
検出結果として円が描画された画像を表示し,何かキーが押されるまで待つ.