|
from typing import Any, Union, List |
|
import cv2 |
|
import numpy as np |
|
from deepface.models.Detector import Detector, FacialAreaRegion |
|
|
|
|
|
|
|
|
|
|
|
class FastMtCnnClient(Detector): |
|
def __init__(self): |
|
self.model = self.build_model() |
|
|
|
def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]: |
|
""" |
|
Detect and align face with mtcnn |
|
|
|
Args: |
|
img (np.ndarray): pre-loaded image as numpy array |
|
|
|
Returns: |
|
results (List[FacialAreaRegion]): A list of FacialAreaRegion objects |
|
""" |
|
resp = [] |
|
|
|
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) |
|
detections = self.model.detect( |
|
img_rgb, landmarks=True |
|
) |
|
if ( |
|
detections is not None |
|
and len(detections) > 0 |
|
and not any(detection is None for detection in detections) |
|
): |
|
for regions, confidence, eyes in zip(*detections): |
|
x, y, w, h = xyxy_to_xywh(regions) |
|
right_eye = eyes[0] |
|
left_eye = eyes[1] |
|
|
|
left_eye = tuple(int(i) for i in left_eye) |
|
right_eye = tuple(int(i) for i in right_eye) |
|
|
|
facial_area = FacialAreaRegion( |
|
x=x, |
|
y=y, |
|
w=w, |
|
h=h, |
|
left_eye=left_eye, |
|
right_eye=right_eye, |
|
confidence=confidence, |
|
) |
|
resp.append(facial_area) |
|
|
|
return resp |
|
|
|
def build_model(self) -> Any: |
|
""" |
|
Build a fast mtcnn face detector model |
|
Returns: |
|
model (Any) |
|
""" |
|
|
|
try: |
|
from facenet_pytorch import MTCNN as fast_mtcnn |
|
import torch |
|
except ModuleNotFoundError as e: |
|
raise ImportError( |
|
"FastMtcnn is an optional detector, ensure the library is installed." |
|
"Please install using 'pip install facenet-pytorch' " |
|
) from e |
|
|
|
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') |
|
face_detector = fast_mtcnn(device=device) |
|
|
|
return face_detector |
|
|
|
|
|
def xyxy_to_xywh(regions: Union[list, tuple]) -> tuple: |
|
""" |
|
Convert (x1, y1, x2, y2) format to (x, y, w, h) format. |
|
Args: |
|
regions (list or tuple): facial area coordinates as x, y, x+w, y+h |
|
Returns: |
|
regions (tuple): facial area coordinates as x, y, w, h |
|
""" |
|
x, y, x_plus_w, y_plus_h = regions[0], regions[1], regions[2], regions[3] |
|
w = x_plus_w - x |
|
h = y_plus_h - y |
|
return (x, y, w, h) |
|
|