はじめに
google-image-downloadで取得した画像ファイルから、学習用の顔画像をファイルに保存するために、OpenCVのHaarCascadeとdlibのface Detetor(HOG)を試して、性能を比較してみました。
開発環境
Ubuntu 18.04.4 LTS
Python 3.6.9
opencv 4.5.1
dlib 19.21.1
比較結果
入力画像ファイル数 | 正しく検出した顔の数 | 誤検出した数 | 処理時間 | |
---|---|---|---|---|
OpenCV HaarCascade | 468 | 278 | 8 | real 0m28.000s |
dlib Face Detector(HOG) | 468 | 841 | 9 | real 9m43.149s |
入力画像に含まれている顔の数は様々です。 | ||||
誤検出したどうかは、切り出し後の画像を目視して確認しました。 |
ソースコード
#!/usr/bin/env python3
import cv2
import dlib
import sys
import os
import argparse
import logging
logger = logging.getLogger()
SAVED_IMAGE_SIZE = (200, 200)
class faceDetector:
pass
class HaarDetector(faceDetector):
def __init__(self):
self.__detector = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
def run(self, img):
return self.__detector.detectMultiScale(img, 1.08, 5, minSize=SAVED_IMAGE_SIZE)
def getVertexes(self, face):
(x, y, w, h) = face
return (x, y, w, h)
class HogDetector(faceDetector):
def __init__(self):
self.__detector = dlib.get_frontal_face_detector()
def run(self, img):
return self.__detector(img, 1)
def getVertexes(self, face):
x0 = max(0, face.left())
y0 = max(0, face.top())
x1 = max(0, face.right())
y1 = max(0, face.bottom())
return (x0, y0, x1-x0+1, y1-y0+1)
OpenCV HaarCascadeとglib face detectorのインタフェース差異を吸収するためにfaceDetectorクラスを作成しました。
以下の関数で、入力画像ファイルから顔認識を行い、認識した領域をファイルに保存します。
def detectAndSaveFace(input_dir, output_dir, useHaar):
logging.basicConfig(level=logging.INFO, format='%(message)s')
if useHaar:
detector = HaarDetector()
else:
detector = HogDetector()
files_processed = 0
faces_detected = 0
for filename in os.listdir(input_dir):
orig_img = cv2.imread(os.path.join(input_dir, filename), cv2.IMREAD_GRAYSCALE)
if orig_img is None:
logger.warning('ignoring {0}'.format(filename))
continue
faces = detector.run(orig_img)
logger.debug('Detected({0}) in {1}'.format(len(faces), filename))
files_processed += 1
# Save the detected bounding boxes
for face in faces:
(x, y, w, h) = detector.getVertexes(face)
face_img = cv2.resize(orig_img[y:y+h, x:x+w], SAVED_IMAGE_SIZE)
face_filename = '{0}/{1}.pgm'.format(output_dir, faces_detected)
cv2.imwrite(face_filename, face_img)
faces_detected += 1
logger.info('files processed = {0}, faces detected = {1}'.format(files_processed, faces_detected))
余談
正面を向いた顔画像を保存したかったので、dlibのCNNは試しませんでした。
dlibで検出した画像範囲の座標がマイナスになる場合がありました。
最後に
dlibのHOGによる検出精度が良いのは想定通りでしたが、私のPCでは予想以上に処理時間がかかりました。