ひさふぃの日記

DjangoとPythonとLaravelが好き。大阪でフリーランスエンジニアやってます。

Pythonでお手軽顔検出|Dlibのface_recognitionでCNNとHOG+SVM

人の顔を用いたディープラーニングのデータセットを用意するための準備です。

ディープラーニングの勉強をするためにデータセットを作る必要がありますが、用意が面倒!opencvのhaarlikecascadeは誤検出多いしな...

アイドル顔認識業界の大御所であるすぎゃーん神のサイトを舐め回すように参考にさせてもらっているのですが、氏でもデータセットを用意するための顔検出は苦労しているようです。

Heroku + OpenCVで簡易顔検出API - すぎゃーんメモ

TensorFlowで顔検出器を自作する - すぎゃーんメモ

もっと楽に顔画像のデータセットを楽に用意できないかなー。と、ネットサーフィンしていたところ、Dlibのface_recognitionのver1.0がリリースされていて良さげ。

ということで、face_recognitionを簡単に説明して性能を堪能します。最後はhaar-like cascadeも含めて検出率と速度を比較!

shikouno.hatenablog.com

こまけーことはいいんだよ!って方はgithubに飛べば幸せになれるんやで。

GitHub - hisafi/compare_face_detector

Dlibのface_recognition

機械学習のライブラリといえばscikit-learnが有名ですが、Dlibも中々イケてるようですね。googleトレンドを見ても同じくらい検索されています。

https://trends.google.co.jp/trends/explore?q=dlib,scikit-learn

調べた限り、顔検出や顔認識をサクッと使う場合はDlibの方が良さそう。Dlibにもscikit-learnでも見たことあるような図がありますね。お互い意識しているのかな。

http://dlib.net/ml_guide.svg

機械学習のライブラリ dlib - Qiita

今回紹介するface_recognitionを用いると、Dlibの顔関係モデルのサクッと感をさらに向上させることができます。8/29にver1.0がリリースされたようで作者に深く感謝の意を表明しつつ、早速活用。

環境構築で少しはまってしまいましたが、過去記事を参照してもらえれば解決するはず。

shikouno.hatenablog.com

もしくはgithubページに飛んでくさいね(宣伝2回目)

GitHub - hisafi/compare_face_detector

このDlibのface_recognition、学習済みのCNNとHOG+SVMを用いることができます。

face_recognitionの使い方

たった3行!インポートして、画像読み込んで、モデルで顔検出!

face_locationsのデフォルトモデルはHOG+SVMですが、model引数にcnnを指定してあげるとCNNでの顔検出となります。

返り値は検出した座標のtop, left, bottom, rightのタプルです。複数検出される場合はタプルのタプル。

import face_recognition # Dlib library

dlib_img = face_recognition.load_image_file(img_name)
hogsvm_locations = face_recognition.face_locations(dlib_img) #hog+svm
cnn_locations = face_recognition.face_locations(dlib_img, model="cnn") #CNN

検出器の比較

検出率

opencvのhaar-like cascadeと併せて比較しています。

用いたコードは以下のとおり。

import face_recognition # Dlib library

def compare_face_recognition(img_name):
    #read image by opencv
    img = cv2.imread(img_name) 
    img_result = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #結果出力用

    #opencv haarcascade
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # グレースケール化
    cascade_path = "./haarcascades/haarcascade_frontalface_alt.xml"
    cascade = cv2.CascadeClassifier(cascade_path) # detectorを作成
    cascade_locations = cascade.detectMultiScale(img_gray, scaleFactor=1.1, minNeighbors=1) # 顔認識とパラメーター

    rect_color = (0, 255, 0)
    if len(cascade_locations) > 0:
        for x, y, width, height in cascade_locations:
            cv2.rectangle(img_result, (x, y), (x + width, y + height), rect_color, thickness=2)

    # Dlib
    dlib_img = face_recognition.load_image_file(img_name)
    # Dlib hog+svm
    hogsvm_locations = face_recognition.face_locations(dlib_img) #hog+svmモデルで顔認識
    
    rect_color = (0, 0, 255)
    if len(hogsvm_locations) > 0:
        for top, left, bottom, right in hogsvm_locations:
            cv2.rectangle(img_result, (left, top), (right, bottom), rect_color, thickness=2)

    # Dlib CNN        
    cnn_locations = face_recognition.face_locations(dlib_img, model="cnn") #CNNモデルで顔認識
    
    rect_color = (255, 0, 0)
    if len(cnn_locations) > 0:
        for top, left, bottom, right in cnn_locations:
            cv2.rectangle(img_result, (left, top), (right, bottom), rect_color, thickness=2)
    
    return img_result

結果は以下の通り。haar-like cascadeが緑、HOG+SVMが赤、CNNが青となっています。

f:id:shikouno:20171001212525j:plain

f:id:shikouno:20171001212520j:plain

f:id:shikouno:20171001212514j:plain

haar-like cascadeはメガネや顔の傾きがあると不検出。HOG+SVMは顔の輪郭が異なる場合は不検出。

結論、CNN(ディープラーニング)すごない?

しかし、顔を切り取ってデータセットを作る場合、口の辺りから上部分を検出しているCNNよりも顔の輪郭に沿って綺麗に検出しているHOG+SVMの方が向いている気がしないでもない。

要検証。

検出器の速度

jupyterのマジックコマンドを使って比較しました。

お使いのパソコンでの性能比較をする場合はgithubページに飛んでくさいね(宣伝3回目)

GitHub - hisafi/compare_face_detector

コードは以下の通り。

%%time
#open_cv haarcascade
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # グレースケール化
cascade_path = "./haarcascades/haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(cascade_path) # detectorを作成
cascade_locations = cascade.detectMultiScale(img_gray, scaleFactor=1.1, minNeighbors=1) 
%%time

# Dlib API
dlib_img = face_recognition.load_image_file(img_name)
# Dlib hog+svm
hogsvm_locations = face_recognition.face_locations(dlib_img) #hog+svm
%%time

# Dlib API
dlib_img = face_recognition.load_image_file(img_name)
# Dlib CNN        
cnn_locations = face_recognition.face_locations(dlib_img, model="cnn") #CNN
  • hear-like cascade
    • CPU times: user 2.5 s, sys: 96.2 ms, total: 2.59 s
    • Wall time: 818 ms
  • HOG+SVM
    • CPU times: user 1.39 s, sys: 72.2 ms, total: 1.46 s
    • Wall time: 1.47 s
  • CNN
    • CPU times: user 17.4 s, sys: 18.1 s, total: 35.4 s
    • Wall time: 30.9 s

GPUを使っていないためCNNは結構処理が遅くて、他と10倍以上の差がありますね。つらいな...

まとめ

データセットを作る場合、Dlibのface_recognitionの検出率がかなり高いので用いると楽できそう。

検出率重視ならCNN、速度重視ならHOG+SVM。ただし、顔の検出範囲が異なるためどちらが良いのかは要検証。

今回も画像は師匠が作成したサイトからお借りしました。ハンバーガールZ、ライブも無料なので要チェックですよ!

easelfamily.toyao.net

それじゃ!

今すぐ試したい! 機械学習・深層学習(ディープラーニング) 画像認識プログラミングレシピ