Spaces:
Sleeping
Sleeping
import logging | |
import cv2 as cv | |
import numpy as np | |
import dlib | |
from typing import Optional | |
logging.basicConfig(level=logging.INFO) | |
class FaceGrabber: | |
def __init__(self): | |
self.cascades = [ | |
"haarcascade_frontalface_default.xml", | |
"haarcascade_frontalface_alt.xml", | |
"haarcascade_frontalface_alt2.xml", | |
"haarcascade_frontalface_alt_tree.xml" | |
] | |
self.detector = dlib.get_frontal_face_detector() # load face detector | |
self.predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks_GTX.dat") # load face predictor | |
self.mmod = dlib.cnn_face_detection_model_v1("mmod_human_face_detector.dat") # load face detector | |
self.paddingBy = 0.1 # padding by 10% | |
def grab_faces(self, img: np.ndarray, bGray: bool = False) -> Optional[np.ndarray]: | |
if bGray: | |
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # convert to grayscale | |
detected = None | |
if detected is None: | |
faces = self.detector(img) # detect faces | |
if len(faces) > 0: | |
detected = faces[0] | |
detected = (detected.left(), detected.top(), detected.width(), detected.height()) | |
logging.info("Face detected by dlib") | |
if detected is None: | |
faces = self.mmod(img) | |
if len(faces) > 0: | |
detected = faces[0] | |
detected = (detected.rect.left(), detected.rect.top(), detected.rect.width(), detected.rect.height()) | |
logging.info("Face detected by mmod") | |
if detected is None: | |
for cascade in self.cascades: | |
cascadeClassifier = cv.CascadeClassifier(cv.data.haarcascades + cascade) | |
faces = cascadeClassifier.detectMultiScale(img, scaleFactor=1.5, minNeighbors=5) # detect faces | |
if len(faces) > 0: | |
detected = faces[0] | |
logging.info(f"Face detected by {cascade}") | |
break | |
if detected is not None: # if face detected | |
x, y, w, h = detected # grab first face | |
padW = int(self.paddingBy * w) # get padding width | |
padH = int(self.paddingBy * h) # get padding height | |
imgH, imgW, _ = img.shape # get image dims | |
x = max(0, x - padW) | |
y = max(0, y - padH) | |
w = min(imgW - x, w + 2 * padW) | |
h = min(imgH - y, h + 2 * padH) | |
x = max(0, x - (w - detected[2]) // 2) # center the face horizontally | |
y = max(0, y - (h - detected[3]) // 2) # center the face vertically | |
face = img[y:y+h, x:x+w] # crop face | |
return face | |
return None |