【Python】dlibで顔検出(CNN版)
前回紹介した「dlib」の顔検出のうち、CNN版で顔検出を行いました。
前回、dlibで顔検出を行いOpenCVよりも精度は向上しました。しかしながら、横顔の検出などには課題が残りました。
https://predora005.hatenablog.com/entry/2021/08/30/190000predora005.hatenablog.com
CNN版を使用した結果を先に言うと、処理時間が長くなるものの精度は向上しました。
[1] 事前準備
[1-1] dlibのインストール
前回紹介した内容と同様です。
https://predora005.hatenablog.com/entry/2021/08/30/190000https://predora005.hatenablog.com/entry/2021/08/30/190000
[1-2] 顔検出器のダウンロード
学習済みのモデルをダウンロードし、解凍します。
curl -O http://dlib.net/files/mmod_human_face_detector.dat.bz2 bzip2 -d mmod_human_face_detector.dat.bz2
[2] ソースコード
公式のExampleを元に作成しています。
dlib/cnn_face_detector.py at master · davisking/dlib · GitHub
顔検出だけであれば「dlib」のみインポートで十分ですが、検出領域の表示等で「OpenCV」を使用しています。
mport os import cv2 import dlib # 顔検出器を取得 detector_file = 'mmod_human_face_detector.dat' detector_path = os.path.join(os.path.expanduser('~'), detector_file) cnn_face_detector = dlib.cnn_face_detection_model_v1(detector_path) # 読み込むファイルのリスト filelist = [ 'sample1.jpg', 'sample2.jpg', 'sample3.jpg'] for file in filelist: print("------------------------------") print("Processing file: {}".format(file)) # 画像を読み込み imgdir = os.path.join(os.path.expanduser('~'), 'img') imgpath = os.path.join(imgdir, file) img = dlib.load_rgb_image(imgpath) # 顔検出を実行 dets = cnn_face_detector(img, 1) # 検出した領域を出力 print("Number of faces detected: {}".format(len(dets))) for i, d in enumerate(dets): print("Detection {}: Left: {} Top: {} Right: {} Bottom: {} Confidence: {}".format( i, d.rect.left(), d.rect.top(), d.rect.right(), d.rect.bottom(), d.confidence)) # 保存用の画像データを準備 save_img = cv2.imread(imgpath) # 検出した範囲を保存用画像に短形表示 for d in dets: x1, y1, x2, y2 = d.rect.left(), d.rect.top(), d.rect.right(), d.rect.bottom() cv2.rectangle(save_img, (x1, y1), (x2, y2), color=(0,0,255), thickness=4) # 検出領域を示した画像を保存 save_file = 'dlib_cnn_' + file save_imgpath = os.path.join(imgdir, save_file) cv2.imwrite(save_imgpath, save_img)
[3] 顔検出の結果
以前に紹介したOpenCVと同じ画像で、顔検出を行いました。
https://predora005.hatenablog.com/entry/2021/08/23/190000predora005.hatenablog.com
[3-1] OpenCVでも上手くいった例
OpenCVと同様に、上手く検出できています。
[3-2] OpenCVでは微妙だった例
<Werner HeiberによるPixabayからの画像>
CNN版では6人中5人まで検出できています。OpenCVでは6人中3人の検出、dlibでは6人中4人の検出でした。
[3-3] OpenCV, dlibでは上手くいかなかった例
OpenCV, dlibともに1人しか検出できていませんでしたが、CNN版では4人まで検出できています。
[4] 補足とトラブルシューティング
[4-1] Memory Error
t3.medium(メモリ 4GiB)では足りませんでした。r5.large(メモリ 16GiB)では足りました。
MemoryError: std::bad_alloc
終わりに
CNN版を用いることで、精度が大きく向上しました。
一方、精度が向上したトレードオフとして、処理時間が長くなり、メモリ使用量が増大しました。
マシンスペックがそれなりに無いと動きません。小スペックの場合にはCNNではない、顔検出器を用いるのが良さそうです。
参考文献
画像の出典
- ゆうせい モデルの紹介 - ぱくたそ
- Werner HeiberによるPixabayからの画像
- Sanu A SによるPixabayからの画像