OpenCV Haar-Cascadeによる顔検出

# まずはじめに
`LGTM` 乞食なのでよろしくお願いします¥

# この記事の目的
なんか顔認証のシステム作りたいなーと思い、OpenCVの基礎的な勉強から始めてます。

OpenCVでは、顔・目などを検出できるカスケード識別器の学習済みファイルを事前に用意されています。
学習済みファイルは下記リンク先からダウンロードできます。

今回は顔検出のために「haarcascade_frontalface_default.xml」を使ってみます。

> https://github.com/opencv/opencv/tree/master/data/haarcascades

以下も用意されてるのでまとめて```git clone```しましょう。

### カスケード型の識別器のファイル
|ファイル名|対象物体|
|---|---|
|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_2spits.xml|左目|
|haarcascade_licence_plate_rus_16stages.xml|ロシアのナンバープレート（全体）|
|haarcascade_lowerbody.xml|下半身|
|haarcascade_profileface.xml|顔（証明写真）|
|haarcascade_righteye_2splits.xml|右目|
|haarcascade_russian_plate_number.xml|笑顔|
|haarcascade_upperbody.xml|上半身|

# OpenCV概要
- OpenCVはIntel社で1999年に Gary Bradskyによって開発が開始され、2000年に最初リリースされた
- 画像処理・画像解析および機械学習等の機能を持つC/C++, Java, Python, MATLAB用ライブラリ
- プラットフォームとしてmacOSやFreeBSD等すべてのPOSIXに準拠したUnix系OS、Linux、Windows、Android、iOSをサポート
- 歴史
    - 1999年にプロジェクト開始。最初のアルファ版が公開されたのは、国際会議CVPR2000年である
    - 2001年から2005年の間に5つのベータ版がリリースされた
    - 1.0版がリリースされたのは2006年
    - 2008年にWillow Garageによるサポートを受け、開発情況が再び活発になった
    - 2009年10月に2回目のメジャーバージョンアップが実施され、2.0版がリリースされた
    - OpenCV 2.4.4以降ではJavaが公式にサポートされている
    - 2015年6月に3回目のメジャーバージョンアップデートとしてOpenCV 3.0が正式リリースされた
    - OpenCV 3.0では従来のC言語関数形式のインターフェースはレガシーAPI扱いとなり、メンテナンスが終了している
    - 代わりにC++ APIを使うことが推奨されている
    - 2018年11月にOpenCV 4.0がリリースされた

# 主な機能

|#|項目|機能|
|---|---|---|
|1|画像処理|勾配、エッジ、コーナー（Gradients, Egdes and Corners）|
|2|画像処理|サンプリング、補間、幾何変換（Sampling, Interpolation and Geometrical Transforms）|
|3|画像処理|モルフォロジー演算（morphological Operations）|
|4|画像処理|フィルタと色変換（Filters and Color Conversion）|
|5|画像処理|ピラミッドとその応用（Pyramids and the Applications）|
|6|画像処理|画像分割、領域結合、輪郭検出（Image Segmentation, Connected Componets and Contour Retrieval）|
|7|画像処理|画像と形状のモーメント（Image and Transforms）|
|8|画像処理|特殊な画像変換（Special Image Transforms）|
|9|画像処理|ヒストグラム（Histograms）|
|10|画像処理|マッチング（Matching）|
|11|画像処理|ラベリング（Labeling）※OpenCV 3.0以降|
|12|構造解析|輪郭処理（Contour Processing）|
|13|構造解析|計算幾何（Comutational Geometry）|
|14|構造解析|平面再分割（Planar Subdivisions）|
|15|モーション解析と物体追跡|背景統計量の累積（Accumulation of Backgorund Statistics）|
|16|モーション解析と物体追跡|モーションテンプレート（Motion Templates）|
|17|モーション解析と物体追跡|物体追跡（Object Tracking）|
|18|モーション解析と物体追跡|オプティカルフロー（Optical Flow）|
|19|モーション解析と物体追跡|推定器（Estimators）|
|20|パターン認識|物体検出（Object Detection）|
|21|カメラキャリブレーションと3次元再構成|カメラキャリブレーション（Camera Calibration）|
|22|メラキャリブレーションと3次元再構成|姿勢推定（Pose Estimation）|
|23|メラキャリブレーションと3次元再構成|エピポーラ幾何（Epipolar Geometry）|
|24|機械学習|単純ベイズ分類器（Native Bayes Classifier）|
|25|機械学習|k近傍法（K Nearest Neighbors）|
|26|機械学習|サポートベクターマシン（SVM）|
|27|機械学習|決定木（Decision Trees）|
|28|機械学習|ブースティング（Boosting）|
|29|機械学習|ランダムフォレスト（Random Forest）|
|30|機械学習|EMアルゴリズム（Expectation-Maximization）|
|31|機械学習|ニューラルネットワーク（Neural Networks）|
|32|ユーザインターフェース|シンプルGUI（Simple GUI）|
|33|ユーザインターフェース|画像の読み込みと保存（Loading and Saving Images）|
|34|ユーザインターフェース|ビデオ入出力（Video I/O）|
|35|ユーザインターフェース|OpenGL/Direct3Dの相互運用|


# やってみたこと
皆ほぼ同じにしか見えない就活生の顔をdetectしてやりたいと思います🙃

## もとの画像

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/756bbbe5-87ee-1846-cc55-5e15a63bb956.png)

## 結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/9fc309de-851e-a82c-8870-36e9604055d5.png)

おお、なんか惜しいな...🤔
後ろの方はもはや認識されていないように思える。

探索窓が小さすぎるとダメなねすかね。
前の方は顔半分見切れてるし...🤫

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/2de2e07e-7b3a-ecc4-8cb0-a07fad4a9a7c.png)



# コード

```python:python3
# -*- coding: utf-8 -*-
import cv2

def main():
    # 入力画像の読み込み
    img = cv2.imread("test.jpg")

    # カスケード型識別器の読み込み
    cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

    # グレースケール変換
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 顔領域の探索
    face = cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=3, minSize=(30, 30))
    
    # 顔領域を赤色の矩形で囲む
    for (x, y, w, h) in face:
        cv2.rectangle(img, (x, y), (x + w, y+h), (0,0,300), 4)

    # 結果を出力
    cv2.imwrite("result.jpg",img)

        
if __name__ == '__main__':
    main()

```


# 参考にさせていただいたサイト
幅広く詳解されています。
https://algorithm.joho.info/programming/python/opencv-haar-cascade-face-detection-py/