OpenCVを利用したアプリ開発 顔認識
カメラ画像から人の顔を検出した場合に赤枠で囲むアプリ開発のメモ
分類器読み込み
OpenCVにはHaar-likeとよばれる明暗で構成される矩形のパターンを検出に使う手法の特徴分類機が予め用意されている。
格納場所:[OpenCV Install Dir]/Library/etc/haarcascades/
haarcascade_frontalcatface.xml は猫の顔、haarcascade_smile.xml は笑顔を分類できる。
今回は、haarcascade_frontalface_alt.xml で正面の人の顔を認識するアプリを作る。
これをオブジェクト検出のためのカスケード分類器クラスに読み込む
//顔を学習した分類器読み込み CascadeClassifier cascade; cascade.load("C:/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml");
※CascadeClassifierの利用には、[opencv_objdetectXXX.lib]を依存ファイルに追加する必要あり
以下参考
初めてのOpenCV開発 ― Visual Studio/CMake/NuGetでプロジェクト作成【OpenCV 3.0/3.1】 - Build Insider
カメラ画像取得
VideoCapture cap(0) でカメラをオープン。引数の"0"はデフォルトのカメラを意味する。
2台目のカメラを接続しオープンする場合は、"1"を指定する。
VideoCapture::isOpened() でカメラがオープンされたかチェック
cap >> frame で現在のフレームをcv::Matに取得。
//カメラ画像取得 Mat frame; VideoCapture cap(0); // デフォルトカメラをオープン if (!cap.isOpened()) // カメラオープンの成否判定 { return -1; } do { cap >> frame; // カメラから新しいフレームを取得 } while (frame.empty());
グレースケール化
2値化処理を行うためにRGB画像からグレースケールへの変換
Mat gray; cvtColor(frame, gray, CV_BGR2GRAY);
物体検出
読み込んだ分類器を元に、入力画像中から該当するオブジェクトを検出
オブジェクトを検出するメソッドは"cascade.detectMultiScale"
//物体検出 vector<Rect> faces; cascade.detectMultiScale(dst, faces, 1.1, 2, CV_HAAR_SCALE_IMAGE, Size(30, 30));
あとは検出した場合、顔を囲む短形を"cv::rectangle"で描画する
プログラミング
※重い処理になるので物体検出用に入力画像を縮小している
#include "opencv2/opencv.hpp" #include "opencv2/objdetect/objdetect.hpp" using namespace cv; int main() { printf("Lesson2\n"); //顔を学習した分類器読み込み CascadeClassifier cascade; cascade.load("C:/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml"); //カメラ画像取得 Mat frame; VideoCapture cap(0); // デフォルトカメラをオープン if (!cap.isOpened()) // カメラオープンの成否判定 { return -1; } while (1) { do { cap >> frame; // カメラから新しいフレームを取得 } while (frame.empty()); double scale = 4.0; // 1/4 Mat gray, smallImg(saturate_cast<int>(frame.rows / scale), saturate_cast<int>(frame.cols / scale), CV_8UC1); //グレースケール化 cvtColor(frame, gray, CV_BGR2GRAY); // 縮小 resize(gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR); //ヒストグラム均一化 equalizeHist(smallImg, smallImg); //imshow("frame", smallImg); //物体検出 vector<Rect> faces; cascade.detectMultiScale(smallImg, faces, 1.1, 2, CV_HAAR_SCALE_IMAGE, Size(30, 30)); std::vector<Rect>::const_iterator r = faces.begin(); for (; r != faces.end(); ++r) { rectangle(frame, Size(saturate_cast<int>(r->tl().x * scale), saturate_cast<int>(r->tl().y * scale)), Size(saturate_cast<int>(r->br().x * scale), saturate_cast<int>(r->br().y * scale)), Scalar(0, 0, 255), 3, 4); } imshow("frame", frame); if (waitKey(30) >= 0) { break; } } return 0; }