2016年1月19日火曜日

顔認識してみた

前回のブログでは一番簡単な画像認識のテンプレートマッチングについて書きました。
今回は少し難しくなってOpenCVで定番の顔認識をやってみたいと思います。

人間の顔認識、猫の顔認識、アニメのキャラクター認識、企業のロゴ認識なんてことをやるにはOpenCVでカスケード分類器というものを使います。

このカスケード分類器に人の顔のデータと人の顔でないデータを何千枚も見せて、機械学習させて、学習結果のデータを作ります。そして、その学習結果に識別させたい画像を入れて判別を行います。

カスケード分類器に機械学習をさせるためには顔と顔以外のデータを数千枚も用意しないといけないのです。とても大変な作業なのですが、OpenCVには顔を学習させた結果のデータファイルも入っているので、今回はこれを使うことにします。

OpenCVにはカスケード分類器に学習させるためのツールも入っているので、以下のページのようにすれば特定の人の顔を識別する学習データや、特定のロゴを識別する学習データも簡単につくることができます。

おじさんの時代はホームページ作れるだけでパソコンできるって言われてソニーとか松下電器に就職できたのに。
いまや小さな会社や学生が数時間で当たり前のように機械学習とかできるのね。
恐ろしい世の中です。Googleに入るためにはどんだけ勉強しないといけないんでしょ。

まぁそれは置いておいて、上記のページにはカスケード分類器を用いた顔認識の原理とかも書いてあるので、顔認識の原理を勉強するのにもとても参考になります。

コンピュータにいろいろなものを認識させたり学習させたりするときには、学習データと特徴ベクトルという画像の特徴を抽出するアルゴリズムが必要なのですが、顔認識ではだいたいHaar-Like特徴というアルゴリズムで特徴を抽出します。

いつものように、顔認識の原理を超省略して一行で簡単に説明すると、Haar-Like特徴によるカスケード分類器で機械学習させて、その学習結果で判別を行います。

まぁ機械学習には学習のさせ方の方法がたくさんある、判別させたいものの特徴を表す特徴ベクトルのアルゴリズムもたくさんある、学習結果のデータがいる程度のことを覚えておくといろいろな人に知ったかぶりできます。


ソースコードにするとこんな感じです。
-------------------------------
#include <stdio.h>
#include <opencv2/opencv.hpp>

#include "mygetopt.h"

#ifdef _WIN32
#pragma comment(lib,"opencv_core300")
#pragma comment(lib,"opencv_highgui300")
#pragma comment(lib,"opencv_hal300")
#pragma comment(lib,"opencv_world300")
//#pragma comment(lib,"opencv_ts300")
#pragma comment(lib,"ippicvmt")
#pragma comment(lib,"zlib")
#endif

int main(int argc,char* argv[])
{
int c;
cv::Mat image;
std::vector<cv::Rect> faces;
std::string img_file="lena.jpg";
std::string cascade_file="haarcascade_frontalface_default.xml";
cv::CascadeClassifier cascade;

while (1)
{
int this_option_optind = myoptind ? myoptind : 1;
c = mygetopt (argc, argv, "i:c:");
if (c == EOF)break;

switch (c){
case 'i':
img_file=myoptarg;
break;
case 'c':
cascade_file=myoptarg;
break;
}
}

image = cv::imread(img_file);
cascade.load(cascade_file);

cascade.detectMultiScale(image, faces, 1.1, 3, 0, cv::Size(20, 20));

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


cv::imshow("detect face", image);
cv::waitKey(0);

return 0;
}
-------------------------------


OpenCVにデフォルトで入っているhaarcascade_frontalface_default.xmlという顔認識の学習結果データを読み込んで、detectMultiScaleを呼び出すだけです。
顔認識はcascade.detectMultiScaleという一行で終わってしまうんですね。
とっても簡単です。これで以下のように顔の部分がわかります。


この写真の人はレナさんという人らしいです。
顔認識はかならずレナさんでやるみたいです。


とりあえず顔認識できた。機械学習による顔認識ってとってもかんたん。数時間でできちゃいます。
次は物体認識にしようかパターン認識にしようか音声認識にしようか文字認識にしようか迷っています。ではまた。









0 件のコメント:

コメントを投稿