DesignAssembler

備忘録に近い

OpenCVで顔検出

カスケード分類器というものを使って入力した画像から顔を検出します。

カスケード分類器

カスケードとは、連続したもの、数珠繋ぎになったものを意味します。

カスケード分類器は、いくつかの特徴量をまとめた学習データです。

ここでの顔検出の流れは、

  1. 入力画像の特徴を抽出
  2. カスケード分類器よりその特徴にマッチする部分を探す

となります。

また、カスケード分類器は以下の特徴のどれかを使って作成することができます。

  • Haar-Like特徴
  • LBP特徴
  • HOG特徴

(これらの特徴の詳しい説明は省きます・・・)
OpenCVではHaar-Like特徴とLBP特徴のカスケード分類器を標準で提供しています。

OpenCVで顔検出

ここではHaar-Like特徴を用いた分類器を使用します。

#include "opencv2/opencv.hpp"
#include <iostream>

using namespace std;
using namespace cv;

Mat detectFaceInImage(Mat &image, string &cascade_file){
  CascadeClassifier cascade;
  cascade.load(cascade_file);

  vector<Rect> faces;
  cascade.detectMultiScale(image, faces, 1.1,3,0,Size(20,20));

  for(int i = 0;i < faces.size(); i++){
    rectangle(image, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width,faces[i].y + faces[i].height),Scalar(0,200,0),3,CV_AA);
  }
  return image;
}

int main(int argc, char const *argv[]){
  Mat image = imread(argv[1]);
  string filename = argv[2];
  Mat detectFaceImage = detectFaceInImage(image, filename);
  imwrite(argv[3], detectFaceImage);

  return 0;
}

detectMultiScaleメソッドでカスケード分類器に基づいて物体検出しています。

void detectMultiScale( const Mat& image, vector<Rect>& objects,
                           double scaleFactor=1.1, int minNeighbors=3,
                                                   int flags=0, Size minSize=Size());
  • imageは入力画像(の行列)
  • objectsは矩形を要素とするベクトル
  • scaleFactorは各画像スケールにおける縮小量
  • minNeighborsは検出される領域の候補となる矩形は最低でもこの数の近傍矩形を含む
  • minSizeは検出される領域が取りうる最小サイズ

コンパイル

$ g++ `pkg-config opencv --cflags` `pkg-config opencv --libs` -o pic_detect pic_detect.cpp

実行

$ ./pic_detect lenna.png /usr/local/opt/opencv/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml lenna_out.png

第二引数ではカスケード特徴器を指定しています。これを変えると顔検出ではなく目の検出などもできるようになります。

画像検出

まずはlenna f:id:hyottokoaloha:20160313154746p:plain

できました。

次は複数人の画像 f:id:hyottokoaloha:20160313154800p:plain

凄い。

参考