OpenCVでアニメ顔検出をやってみた

やったこと

顔などの特定の物体がどこにあるかを認識するときにはカスケード分類器というものをつかいます(物体検出 — opencv v2.1 documentation)。ここではOpenCVによるアニメ顔検出ならlbpcascade_animeface.xmlで公開されているアニメ顔検出器を使っています。

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void detectAndDisplay(Mat image);

CascadeClassifier face_cascade;

int main(void){
    //カスケードのロード
    face_cascade.load("lbpcascade_animeface.xml");

    Mat image;
    image = imread("face.jpg");
    detectAndDisplay(image);
    waitKey(0);
    return 0;
}

//認識と表示を行う関数
void detectAndDisplay(Mat image)
{
    vector<Rect> faces;
    Mat frame_gray;

    //画像のグレースケール化
    cvtColor(image, frame_gray, COLOR_BGR2GRAY );
    //ヒストグラムの平坦化
    equalizeHist(frame_gray, frame_gray);
    //顔の認識
    face_cascade.detectMultiScale(frame_gray, faces);
    //顔を丸で囲む
    for(int i = 0; i<faces.size(); i++){
        Point center(faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );
        ellipse(image, center, Size(faces[i].width/2, faces[i].height/2), 0, 0, 360, Scalar(255, 0, 255), 2, 8, 0);
    }
    //結果の表示
    imshow("Result", image);
}

コンパイル

g++ Anime.cpp -o anime `pkg-config opencv --cflags --libs`

結果

f:id:kivantium:20140916230440p:plain:w450
f:id:kivantium:20140916230538p:plain:w450
f:id:kivantium:20140916230527p:plain:w450
f:id:kivantium:20140916230507p:plain:w450
最後の画像以外は恐ろしく正確に検出できています。失敗したケースはおそらく目を閉じているのが原因だと思われます。目を閉じた顔も含めた学習用データを用意すれば精度が上がるかもしれませんが、今後の課題ということで。