mirror of
https://github.com/serengil/deepface.git
synced 2025-06-07 12:05:22 +00:00
refactor detectors to have default detect_faces method that is based on process_single_image method
This commit is contained in:
parent
aae3af0d05
commit
8c7c2cb9b7
@ -1,37 +1,8 @@
|
|||||||
from typing import List, Tuple, Optional, Union
|
from typing import List, Tuple, Optional, Union
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
# Notice that all facial detector models must be inherited from this class
|
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=unnecessary-pass, too-few-public-methods, too-many-instance-attributes
|
|
||||||
class Detector(ABC):
|
|
||||||
@abstractmethod
|
|
||||||
def detect_faces(
|
|
||||||
self,
|
|
||||||
img: Union[np.ndarray, List[np.ndarray]]
|
|
||||||
) -> Union[List["FacialAreaRegion"], List[List["FacialAreaRegion"]]]:
|
|
||||||
"""
|
|
||||||
Interface for detect and align faces in a batch of images
|
|
||||||
|
|
||||||
Args:
|
|
||||||
img (Union[np.ndarray, List[np.ndarray]]):
|
|
||||||
Pre-loaded image as numpy array or a list of those
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
results (Union[List[List[FacialAreaRegion]], List[FacialAreaRegion]]):
|
|
||||||
A list or a list of lists of FacialAreaRegion objects
|
|
||||||
where each object contains:
|
|
||||||
|
|
||||||
- facial_area (FacialAreaRegion): The facial area region represented
|
|
||||||
as x, y, w, h, left_eye and right_eye. left eye and right eye are
|
|
||||||
eyes on the left and right respectively with respect to the person
|
|
||||||
instead of observer.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class FacialAreaRegion:
|
class FacialAreaRegion:
|
||||||
@ -77,3 +48,57 @@ class DetectedFace:
|
|||||||
img: np.ndarray
|
img: np.ndarray
|
||||||
facial_area: FacialAreaRegion
|
facial_area: FacialAreaRegion
|
||||||
confidence: float
|
confidence: float
|
||||||
|
|
||||||
|
|
||||||
|
# Notice that all facial detector models must be inherited from this class
|
||||||
|
|
||||||
|
# pylint: disable=unnecessary-pass, too-few-public-methods, too-many-instance-attributes
|
||||||
|
class Detector(ABC):
|
||||||
|
|
||||||
|
def detect_faces(
|
||||||
|
self,
|
||||||
|
img: Union[np.ndarray, List[np.ndarray]],
|
||||||
|
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
||||||
|
"""
|
||||||
|
Detect and align faces in an image or a list of images
|
||||||
|
|
||||||
|
Args:
|
||||||
|
img (Union[np.ndarray, List[np.ndarray]]):
|
||||||
|
pre-loaded image as numpy array or a list of those
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
||||||
|
A list or a list of lists of FacialAreaRegion objects
|
||||||
|
"""
|
||||||
|
is_batched_input = isinstance(img, list)
|
||||||
|
if not is_batched_input:
|
||||||
|
img = [img]
|
||||||
|
results = [self._process_single_image(single_img) for single_img in img]
|
||||||
|
if not is_batched_input:
|
||||||
|
return results[0]
|
||||||
|
return results
|
||||||
|
|
||||||
|
def _process_single_image(
|
||||||
|
self,
|
||||||
|
img: np.ndarray
|
||||||
|
) -> List[FacialAreaRegion]:
|
||||||
|
"""
|
||||||
|
Interface for detect and align faces in a single image
|
||||||
|
|
||||||
|
Args:
|
||||||
|
img (Union[np.ndarray, List[np.ndarray]]):
|
||||||
|
Pre-loaded image as numpy array or a list of those
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
results (Union[List[List[FacialAreaRegion]], List[FacialAreaRegion]]):
|
||||||
|
A list or a list of lists of FacialAreaRegion objects
|
||||||
|
where each object contains:
|
||||||
|
|
||||||
|
- facial_area (FacialAreaRegion): The facial area region represented
|
||||||
|
as x, y, w, h, left_eye and right_eye. left eye and right eye are
|
||||||
|
eyes on the left and right respectively with respect to the person
|
||||||
|
instead of observer.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError(
|
||||||
|
"Subclasses that do not implement batch detection must implement this method"
|
||||||
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# built-in dependencies
|
# built-in dependencies
|
||||||
import os
|
import os
|
||||||
from typing import List, Union
|
from typing import List
|
||||||
|
|
||||||
# 3rd party dependencies
|
# 3rd party dependencies
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -34,35 +34,12 @@ class CenterFaceClient(Detector):
|
|||||||
|
|
||||||
return CenterFace(weight_path=weights_path)
|
return CenterFace(weight_path=weights_path)
|
||||||
|
|
||||||
def detect_faces(
|
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
||||||
self,
|
|
||||||
img: Union[np.ndarray, List[np.ndarray]],
|
|
||||||
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
|
||||||
"""
|
|
||||||
Detect and align face with CenterFace
|
|
||||||
|
|
||||||
Args:
|
|
||||||
img (Union[np.ndarray, List[np.ndarray]]):
|
|
||||||
pre-loaded image as numpy array or a list of those
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
|
||||||
A list or a list of lists of FacialAreaRegion objects
|
|
||||||
"""
|
|
||||||
is_batched_input = isinstance(img, list)
|
|
||||||
if not is_batched_input:
|
|
||||||
img = [img]
|
|
||||||
results = [self._process_single_image(single_img) for single_img in img]
|
|
||||||
if not is_batched_input:
|
|
||||||
return results[0]
|
|
||||||
return results
|
|
||||||
|
|
||||||
def _process_single_image(self, single_img: np.ndarray) -> List[FacialAreaRegion]:
|
|
||||||
"""
|
"""
|
||||||
Helper function to detect faces in a single image.
|
Helper function to detect faces in a single image.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
single_img (np.ndarray): pre-loaded image as numpy array
|
img (np.ndarray): pre-loaded image as numpy array
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
results (List[FacialAreaRegion]): A list of FacialAreaRegion objects
|
results (List[FacialAreaRegion]): A list of FacialAreaRegion objects
|
||||||
@ -76,7 +53,7 @@ class CenterFaceClient(Detector):
|
|||||||
# img, img.shape[0], img.shape[1], threshold=threshold
|
# img, img.shape[0], img.shape[1], threshold=threshold
|
||||||
# )
|
# )
|
||||||
detections, landmarks = self.build_model().forward(
|
detections, landmarks = self.build_model().forward(
|
||||||
single_img, single_img.shape[0], single_img.shape[1], threshold=threshold
|
img, img.shape[0], img.shape[1], threshold=threshold
|
||||||
)
|
)
|
||||||
|
|
||||||
for i, detection in enumerate(detections):
|
for i, detection in enumerate(detections):
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# built-in dependencies
|
# built-in dependencies
|
||||||
from typing import List, Union
|
from typing import List
|
||||||
|
|
||||||
# 3rd party dependencies
|
# 3rd party dependencies
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -47,29 +47,6 @@ class DlibClient(Detector):
|
|||||||
detector["sp"] = sp
|
detector["sp"] = sp
|
||||||
return detector
|
return detector
|
||||||
|
|
||||||
def detect_faces(
|
|
||||||
self,
|
|
||||||
img: Union[np.ndarray, List[np.ndarray]],
|
|
||||||
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
|
||||||
"""
|
|
||||||
Detect and align face with dlib
|
|
||||||
|
|
||||||
Args:
|
|
||||||
img (Union[np.ndarray, List[np.ndarray]]):
|
|
||||||
pre-loaded image as numpy array or a list of those
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
|
||||||
A list or a list of lists of FacialAreaRegion objects
|
|
||||||
"""
|
|
||||||
is_batched_input = isinstance(img, list)
|
|
||||||
if not is_batched_input:
|
|
||||||
img = [img]
|
|
||||||
results = [self._process_single_image(single_img) for single_img in img]
|
|
||||||
if not is_batched_input:
|
|
||||||
return results[0]
|
|
||||||
return results
|
|
||||||
|
|
||||||
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
||||||
"""
|
"""
|
||||||
Helper function to detect faces in a single image.
|
Helper function to detect faces in a single image.
|
||||||
|
@ -17,29 +17,6 @@ class FastMtCnnClient(Detector):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.model = self.build_model()
|
self.model = self.build_model()
|
||||||
|
|
||||||
def detect_faces(
|
|
||||||
self,
|
|
||||||
img: Union[np.ndarray, List[np.ndarray]],
|
|
||||||
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
|
||||||
"""
|
|
||||||
Detect and align face with mtcnn
|
|
||||||
|
|
||||||
Args:
|
|
||||||
img (Union[np.ndarray, List[np.ndarray]]):
|
|
||||||
pre-loaded image as numpy array or a list of those
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
|
||||||
A list or a list of lists of FacialAreaRegion objects
|
|
||||||
"""
|
|
||||||
is_batched_input = isinstance(img, list)
|
|
||||||
if not is_batched_input:
|
|
||||||
img = [img]
|
|
||||||
results = [self._process_single_image(single_img) for single_img in img]
|
|
||||||
if not is_batched_input:
|
|
||||||
return results[0]
|
|
||||||
return results
|
|
||||||
|
|
||||||
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
||||||
"""
|
"""
|
||||||
Helper function to detect faces in a single image.
|
Helper function to detect faces in a single image.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# built-in dependencies
|
# built-in dependencies
|
||||||
import os
|
import os
|
||||||
from typing import Any, List, Union
|
from typing import Any, List
|
||||||
|
|
||||||
# 3rd party dependencies
|
# 3rd party dependencies
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -43,29 +43,6 @@ class MediaPipeClient(Detector):
|
|||||||
)
|
)
|
||||||
return face_detection
|
return face_detection
|
||||||
|
|
||||||
def detect_faces(
|
|
||||||
self,
|
|
||||||
img: Union[np.ndarray, List[np.ndarray]],
|
|
||||||
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
|
||||||
"""
|
|
||||||
Detect and align face with mediapipe
|
|
||||||
|
|
||||||
Args:
|
|
||||||
img (Union[np.ndarray, List[np.ndarray]]):
|
|
||||||
pre-loaded image as numpy array or a list of those
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
|
||||||
A list or a list of lists of FacialAreaRegion objects
|
|
||||||
"""
|
|
||||||
is_batched_input = isinstance(img, list)
|
|
||||||
if not is_batched_input:
|
|
||||||
img = [img]
|
|
||||||
results = [self._process_single_image(single_img) for single_img in img]
|
|
||||||
if not is_batched_input:
|
|
||||||
return results[0]
|
|
||||||
return results
|
|
||||||
|
|
||||||
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
||||||
"""
|
"""
|
||||||
Helper function to detect faces in a single image.
|
Helper function to detect faces in a single image.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# built-in dependencies
|
# built-in dependencies
|
||||||
import os
|
import os
|
||||||
from typing import Any, List, Union
|
from typing import Any, List
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
# 3rd party dependencies
|
# 3rd party dependencies
|
||||||
@ -45,65 +45,48 @@ class OpenCvClient(Detector):
|
|||||||
)
|
)
|
||||||
return supports_batch_detection
|
return supports_batch_detection
|
||||||
|
|
||||||
def detect_faces(
|
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
||||||
self,
|
|
||||||
img: Union[np.ndarray, List[np.ndarray]]
|
|
||||||
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
|
||||||
"""
|
"""
|
||||||
Detect and align face with opencv
|
Helper function to detect faces in a single image.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
img (Union[np.ndarray, List[np.ndarray]]):
|
img (np.ndarray): pre-loaded image as numpy array
|
||||||
Pre-loaded image as numpy array or a list of those
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
results (List[FacialAreaRegion]): A list of FacialAreaRegion objects
|
||||||
A list or a list of lists of FacialAreaRegion objects
|
|
||||||
"""
|
"""
|
||||||
if isinstance(img, np.ndarray):
|
resp = []
|
||||||
imgs = [img]
|
detected_face = None
|
||||||
elif self.supports_batch_detection:
|
faces = []
|
||||||
imgs = img
|
try:
|
||||||
else:
|
faces, _, scores = self.model["face_detector"].detectMultiScale3(
|
||||||
return [self.detect_faces(single_img) for single_img in img]
|
img, 1.1, 10, outputRejectLevels=True
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
batch_results = []
|
if len(faces) > 0:
|
||||||
|
for (x, y, w, h), confidence in zip(faces, scores):
|
||||||
|
detected_face = img[int(y):int(y + h), int(x):int(x + w)]
|
||||||
|
left_eye, right_eye = self.find_eyes(img=detected_face)
|
||||||
|
|
||||||
for single_img in imgs:
|
if left_eye is not None:
|
||||||
resp = []
|
left_eye = (int(x + left_eye[0]), int(y + left_eye[1]))
|
||||||
detected_face = None
|
if right_eye is not None:
|
||||||
faces = []
|
right_eye = (int(x + right_eye[0]), int(y + right_eye[1]))
|
||||||
try:
|
|
||||||
faces, _, scores = self.model["face_detector"].detectMultiScale3(
|
facial_area = FacialAreaRegion(
|
||||||
single_img, 1.1, 10, outputRejectLevels=True
|
x=x,
|
||||||
|
y=y,
|
||||||
|
w=w,
|
||||||
|
h=h,
|
||||||
|
left_eye=left_eye,
|
||||||
|
right_eye=right_eye,
|
||||||
|
confidence=(100 - confidence) / 100,
|
||||||
)
|
)
|
||||||
except:
|
resp.append(facial_area)
|
||||||
pass
|
|
||||||
|
|
||||||
if len(faces) > 0:
|
return resp
|
||||||
for (x, y, w, h), confidence in zip(faces, scores):
|
|
||||||
detected_face = single_img[int(y):int(y + h), int(x):int(x + w)]
|
|
||||||
left_eye, right_eye = self.find_eyes(img=detected_face)
|
|
||||||
|
|
||||||
if left_eye is not None:
|
|
||||||
left_eye = (int(x + left_eye[0]), int(y + left_eye[1]))
|
|
||||||
if right_eye is not None:
|
|
||||||
right_eye = (int(x + right_eye[0]), int(y + right_eye[1]))
|
|
||||||
|
|
||||||
facial_area = FacialAreaRegion(
|
|
||||||
x=x,
|
|
||||||
y=y,
|
|
||||||
w=w,
|
|
||||||
h=h,
|
|
||||||
left_eye=left_eye,
|
|
||||||
right_eye=right_eye,
|
|
||||||
confidence=(100 - confidence) / 100,
|
|
||||||
)
|
|
||||||
resp.append(facial_area)
|
|
||||||
|
|
||||||
batch_results.append(resp)
|
|
||||||
|
|
||||||
return batch_results if len(batch_results) > 1 else batch_results[0]
|
|
||||||
|
|
||||||
def find_eyes(self, img: np.ndarray) -> tuple:
|
def find_eyes(self, img: np.ndarray) -> tuple:
|
||||||
"""
|
"""
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# built-in dependencies
|
# built-in dependencies
|
||||||
from typing import List, Union
|
from typing import List
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
|
|
||||||
# 3rd party dependencies
|
# 3rd party dependencies
|
||||||
@ -54,48 +54,25 @@ class SsdClient(Detector):
|
|||||||
|
|
||||||
return {"face_detector": face_detector, "opencv_module": OpenCv.OpenCvClient()}
|
return {"face_detector": face_detector, "opencv_module": OpenCv.OpenCvClient()}
|
||||||
|
|
||||||
def detect_faces(
|
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
||||||
self,
|
|
||||||
img: Union[np.ndarray, List[np.ndarray]]
|
|
||||||
) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
|
||||||
"""
|
|
||||||
Detect and align faces with ssd in a batch of images
|
|
||||||
|
|
||||||
Args:
|
|
||||||
img (Union[np.ndarray, List[np.ndarray]]):
|
|
||||||
Pre-loaded image as numpy array or a list of those
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]):
|
|
||||||
A list or a list of lists of FacialAreaRegion objects
|
|
||||||
"""
|
|
||||||
is_batched_input = isinstance(img, list)
|
|
||||||
if not is_batched_input:
|
|
||||||
img = [img]
|
|
||||||
results = [self._process_single_image(single_img) for single_img in img]
|
|
||||||
if not is_batched_input:
|
|
||||||
return results[0]
|
|
||||||
return results
|
|
||||||
|
|
||||||
def _process_single_image(self, single_img: np.ndarray) -> List[FacialAreaRegion]:
|
|
||||||
"""
|
"""
|
||||||
Helper function to detect faces in a single image.
|
Helper function to detect faces in a single image.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
single_img (np.ndarray): Pre-loaded image as numpy array
|
img (np.ndarray): Pre-loaded image as numpy array
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
results (List[FacialAreaRegion]): A list of FacialAreaRegion objects
|
results (List[FacialAreaRegion]): A list of FacialAreaRegion objects
|
||||||
"""
|
"""
|
||||||
# Because cv2.dnn.blobFromImage expects CV_8U (8-bit unsigned integer) values
|
# Because cv2.dnn.blobFromImage expects CV_8U (8-bit unsigned integer) values
|
||||||
if single_img.dtype != np.uint8:
|
if img.dtype != np.uint8:
|
||||||
single_img = single_img.astype(np.uint8)
|
img = img.astype(np.uint8)
|
||||||
|
|
||||||
opencv_module: OpenCv.OpenCvClient = self.model["opencv_module"]
|
opencv_module: OpenCv.OpenCvClient = self.model["opencv_module"]
|
||||||
|
|
||||||
target_size = (300, 300)
|
target_size = (300, 300)
|
||||||
original_size = single_img.shape
|
original_size = img.shape
|
||||||
current_img = cv2.resize(single_img, target_size)
|
current_img = cv2.resize(img, target_size)
|
||||||
|
|
||||||
aspect_ratio_x = original_size[1] / target_size[1]
|
aspect_ratio_x = original_size[1] / target_size[1]
|
||||||
aspect_ratio_y = original_size[0] / target_size[0]
|
aspect_ratio_y = original_size[0] / target_size[0]
|
||||||
@ -132,7 +109,7 @@ class SsdClient(Detector):
|
|||||||
for face in faces:
|
for face in faces:
|
||||||
confidence = float(face[ssd_labels.confidence])
|
confidence = float(face[ssd_labels.confidence])
|
||||||
x, y, w, h = map(int, face[margins])
|
x, y, w, h = map(int, face[margins])
|
||||||
detected_face = single_img[y : y + h, x : x + w]
|
detected_face = img[y : y + h, x : x + w]
|
||||||
|
|
||||||
left_eye, right_eye = opencv_module.find_eyes(detected_face)
|
left_eye, right_eye = opencv_module.find_eyes(detected_face)
|
||||||
|
|
||||||
|
@ -78,7 +78,8 @@ class YoloDetectorClient(Detector):
|
|||||||
A list of lists of FacialAreaRegion objects
|
A list of lists of FacialAreaRegion objects
|
||||||
for each image or a list of FacialAreaRegion objects
|
for each image or a list of FacialAreaRegion objects
|
||||||
"""
|
"""
|
||||||
if not isinstance(img, list):
|
is_batched_input = isinstance(img, list)
|
||||||
|
if not is_batched_input:
|
||||||
img = [img]
|
img = [img]
|
||||||
|
|
||||||
all_results = []
|
all_results = []
|
||||||
@ -142,7 +143,7 @@ class YoloDetectorClient(Detector):
|
|||||||
|
|
||||||
all_results.append(resp)
|
all_results.append(resp)
|
||||||
|
|
||||||
if len(all_results) == 1:
|
if not is_batched_input:
|
||||||
return all_results[0]
|
return all_results[0]
|
||||||
return all_results
|
return all_results
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# built-in dependencies
|
# built-in dependencies
|
||||||
import os
|
import os
|
||||||
from typing import Any, List, Union
|
from typing import Any, List
|
||||||
|
|
||||||
# 3rd party dependencies
|
# 3rd party dependencies
|
||||||
import cv2
|
import cv2
|
||||||
@ -57,24 +57,6 @@ class YuNetClient(Detector):
|
|||||||
) from err
|
) from err
|
||||||
return face_detector
|
return face_detector
|
||||||
|
|
||||||
def detect_faces(self, img: Union[np.ndarray, List[np.ndarray]]) -> Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]:
|
|
||||||
"""
|
|
||||||
Detect and align face with yunet
|
|
||||||
|
|
||||||
Args:
|
|
||||||
img (Union[np.ndarray, List[np.ndarray]]): pre-loaded image as numpy array or a list of those
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
results (Union[List[FacialAreaRegion], List[List[FacialAreaRegion]]]): A list or a list of lists of FacialAreaRegion objects
|
|
||||||
"""
|
|
||||||
is_batched_input = isinstance(img, list)
|
|
||||||
if not is_batched_input:
|
|
||||||
img = [img]
|
|
||||||
results = [self._process_single_image(single_img) for single_img in img]
|
|
||||||
if not is_batched_input:
|
|
||||||
return results[0]
|
|
||||||
return results
|
|
||||||
|
|
||||||
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
def _process_single_image(self, img: np.ndarray) -> List[FacialAreaRegion]:
|
||||||
"""
|
"""
|
||||||
Helper function to detect faces in a single image.
|
Helper function to detect faces in a single image.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user