Pythonでお手軽顔検出|Dlibのface_recognitionでCNNとHOG+SVM
人の顔を用いたディープラーニングのデータセットを用意するための準備です。
ディープラーニングの勉強をするためにデータセットを作る必要がありますが、用意が面倒!opencvのhaarlikecascadeは誤検出多いしな...
アイドル顔認識業界の大御所であるすぎゃーん神のサイトを舐め回すように参考にさせてもらっているのですが、氏でもデータセットを用意するための顔検出は苦労しているようです。
Heroku + OpenCVで簡易顔検出API - すぎゃーんメモ
TensorFlowで顔検出器を自作する - すぎゃーんメモ
もっと楽に顔画像のデータセットを楽に用意できないかなー。と、ネットサーフィンしていたところ、Dlibのface_recognitionのver1.0がリリースされていて良さげ。
ということで、face_recognitionを簡単に説明して性能を堪能します。最後はhaar-like cascadeも含めて検出率と速度を比較!
こまけーことはいいんだよ!って方は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でも見たことあるような図がありますね。お互い意識しているのかな。
今回紹介するface_recognitionを用いると、Dlibの顔関係モデルのサクッと感をさらに向上させることができます。8/29にver1.0がリリースされたようで作者に深く感謝の意を表明しつつ、早速活用。
環境構築で少しはまってしまいましたが、過去記事を参照してもらえれば解決するはず。
もしくは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が青となっています。
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、ライブも無料なので要チェックですよ!
それじゃ!