OpenCVを使った顔認識（Haar-like特徴分類器）


# Haar-like特徴分類器
　「Haar-like特徴を用いたブースティングされた分類器のカスケード」とは、Haar-likeとよばれる明暗で構成される矩形のパターンを検出に使う手法です。Haar-like特徴と対象画像を重ね合わせ、パターンがあるかないかを判定します。
　![haar.png](https://qiita-image-store.s3.amazonaws.com/0/107056/541197b2-2c06-102f-a275-704a8c12136c.png)

OpenCVには以下のHaar-like特徴分類器があらかじめ用意されています。
[OpenCV Install Dir]/Library/etc/haarcascades/

|ファイル名          |内容|
|:-----------------------------------------|:---------------------------|
|haarcascade_eye.xml                       |目                          |
|haarcascade_eye_tree_eyeglasses.xml       |眼鏡                        |
|haarcascade_frontalcatface.xml            |猫の顔（正面）               |
|haarcascade_frontalcatface_extended.xml   |猫の顔（正面）               |
|haarcascade_frontalface_alt.xml           |顔（正面）                   |
|haarcascade_frontalface_alt2.xml          |顔（正面）                   |
|haarcascade_frontalface_alt_tree.xml      |顔（正面）                   |
|haarcascade_frontalface_default.xml       |顔（正面）                   |
|haarcascade_fullbody.xml                  |全身                         |
|haarcascade_lefteye_2splits.xml           |左目                         |
|haarcascade_licence_plate_rus_16stages.xml|ロシアのナンバープレート（全体）|
|haarcascade_lowerbody.xml                 |下半身                       |
|haarcascade_profileface.xml               |顔（証明写真）                |
|haarcascade_righteye_2splits.xml          |右目                         |
|haarcascade_russian_plate_number.xml      |ロシアのナンバープレート（数字）|
|haarcascade_smile.xml                     |笑顔                         |
|haarcascade_upperbody.xml                 |上半身                       |

今回は、OpenCVのHaar-like特徴分類器を使って、顔認識をしてみます。

# OpenCV
OpenCV(Open Source Computer Vision Library)はBSDライセンスの映像/画像処理ライブラリ集です。画像のフィルタ処理、テンプレートマッチング、物体認識、映像解析、機械学習などのアルゴリズムが多数用意されています。

■ OpenCVを使った動体追跡の例 (OpenCV Google Summer of Code 2015)
[https://www.youtube.com/watch?v=OUbUFn71S4s](https://www.youtube.com/watch?v=OUbUFn71S4s)

■ インストールと簡単な使い方はこちら
[OpenCV 3（core + contrib）をPython 3の環境にインストール＆OpenCV 2とOpenCV 3の違い＆簡単な動作チェック](http://qiita.com/olympic2020/items/d5d475a446ec9c73261e)
　　★ モーションテンプレートを実行するために、core + opencv_contrib をインストールしてください。

■ 静止画像のフィルター処理についてはこちら
[OpenCVでエッジ検出してみる](http://qiita.com/olympic2020/items/2c3a2bfefe73ab5c86a4)
[OpenCVで各種フィルター処理をする（グラディエント、ハイパス、ラプラシアン、ガウシアン）](http://qiita.com/olympic2020/items/93e01ef22e46b14a60a9)
[OpenCVで特徴点を抽出する（AgastFeature, FAST, GFTT, MSER, AKAZE, BRISK, KAZE, ORB, SimpleBlob）](http://qiita.com/olympic2020/items/62989573a30ec1d8180b)

■ 動画ファイルの処理についてはこちら
[OpenCVで動画をリアルタイムに変換してみる](http://qiita.com/olympic2020/items/ce00fab38d829965db3b)
[OpenCVでWebカメラ/ビデオカメラの動画をリアルタイムに変換してみる](http://qiita.com/olympic2020/items/12a2eceaf65f142ec3df)
[OpenCVでオプティカルフローをリアルタイムに描画する（Shi-Tomasi法、Lucas-Kanade法）](http://qiita.com/olympic2020/items/772549d0fc3c89fb3cc4)
[OpenCVを使った物体追跡（マウスで指定した特徴点をLucas-Kanade法で追跡する](http://qiita.com/olympic2020/items/3d8973f855e963c9d999)
[OpenCVを使ったモーション テンプレート解析（リアルタイムに物体とその動く方向を認識する）](http://qiita.com/olympic2020/items/a4ecf7babdbe710208ae)

# プログラム
流れは、下記のようになっています。
1. cv2.CascadeClassifier([Haar-like特徴ファイル.xml])でHaar-like特徴分類器を作成
2. Haar-like特徴分類器に対して画像を指定
3. 画像に対して検出した領域を矩形で囲む

```face.py
import cv2

# Haar-like特徴分類器の読み込み
face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_eye.xml')

# イメージファイルの読み込み
img = cv2.imread('face.png')

# グレースケール変換
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 顔を検知
faces = face_cascade.detectMultiScale(gray)
for (x,y,w,h) in faces:
    # 検知した顔を矩形で囲む
    cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
    # 顔画像（グレースケール）
    roi_gray = gray[y:y+h, x:x+w]
    # 顔ｇ増（カラースケール）
    roi_color = img[y:y+h, x:x+w]
    # 顔の中から目を検知
    eyes = eye_cascade.detectMultiScale(roi_gray)
    for (ex,ey,ew,eh) in eyes:
        # 検知した目を矩形で囲む
        cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)

# 画像表示
cv2.imshow('img',img)

# 何かキーを押したら終了
cv2.waitKey(0)
cv2.destroyAllWindows()
```

# 実行結果
こんな画像だと、こんな感じで認識します。
顔は全て認識しているものの、目はぼんやりとした画像のためかあまり認識してくれていません。
![result.png](https://qiita-image-store.s3.amazonaws.com/0/107056/7e025ab6-ba42-ff57-dfd2-0453a8fc7f3a.png)

こんな画像だと、こんな感じで認識します。
顔全体は、かなり認識してくれます。一方、目は視線が正面を向いていれば認識してくれています。
![result12.png](https://qiita-image-store.s3.amazonaws.com/0/107056/1e90ca8a-0224-e932-9a6c-7d3a1228e6ee.png)

目や横顔などの検出パターンをある程度把握していけば、目線や目線の先にある物を推測することもできそうです。