Spaces:
Runtime error
Runtime error
import cv2 | |
import numpy as np | |
from skimage import transform as trans | |
# from mtcnn.mtcnn import MTCNN | |
def get_keypts(face): | |
# get key points from the results of mtcnn | |
if len(face['keypoints']) == 0: | |
return [] | |
leye = np.array(face['keypoints']['left_eye'], dtype=np.int).reshape(-1, 2) | |
reye = np.array(face['keypoints']['right_eye'], | |
dtype=np.int).reshape(-1, 2) | |
nose = np.array(face['keypoints']['nose'], dtype=np.int).reshape(-1, 2) | |
lmouth = np.array(face['keypoints']['mouth_left'], | |
dtype=np.int).reshape(-1, 2) | |
rmouth = np.array(face['keypoints']['mouth_right'], | |
dtype=np.int).reshape(-1, 2) | |
pts = np.concatenate([leye, reye, nose, lmouth, rmouth], axis=0) | |
return pts | |
def img_align_crop(img, landmark=None, outsize=None, scale=1.3, mask=None): | |
""" align and crop the face according to the given bbox and landmarks | |
landmark: 5 key points | |
""" | |
M = None | |
target_size = [112, 112] | |
dst = np.array([ | |
[30.2946, 51.6963], | |
[65.5318, 51.5014], | |
[48.0252, 71.7366], | |
[33.5493, 92.3655], | |
[62.7299, 92.2041]], dtype=np.float32) | |
if target_size[1] == 112: | |
dst[:, 0] += 8.0 | |
dst[:, 0] = dst[:, 0] * outsize[0] / target_size[0] | |
dst[:, 1] = dst[:, 1] * outsize[1] / target_size[1] | |
target_size = outsize | |
margin_rate = scale - 1 | |
x_margin = target_size[0] * margin_rate / 2. | |
y_margin = target_size[1] * margin_rate / 2. | |
# move | |
dst[:, 0] += x_margin | |
dst[:, 1] += y_margin | |
# resize | |
dst[:, 0] *= target_size[0] / (target_size[0] + 2 * x_margin) | |
dst[:, 1] *= target_size[1] / (target_size[1] + 2 * y_margin) | |
src = landmark.astype(np.float32) | |
# use skimage tranformation | |
tform = trans.SimilarityTransform() | |
tform.estimate(src, dst) | |
M = tform.params[0:2, :] | |
# M: use opencv | |
# M = cv2.getAffineTransform(src[[0,1,2],:],dst[[0,1,2],:]) | |
img = cv2.warpAffine(img, M, (target_size[1], target_size[0])) | |
if outsize is not None: | |
img = cv2.resize(img, (outsize[1], outsize[0])) | |
if mask is not None: | |
mask = cv2.warpAffine(mask, M, (target_size[1], target_size[0])) | |
mask = cv2.resize(mask, (outsize[1], outsize[0])) | |
return img, mask | |
else: | |
return img | |
def expand_bbox(bbox, width, height, scale=1.3, minsize=None): | |
""" | |
Expand original boundingbox by scale. | |
:param bbx: original boundingbox | |
:param width: frame width | |
:param height: frame height | |
:param scale: bounding box size multiplier to get a bigger face region | |
:param minsize: set minimum bounding box size | |
:return: expanded bbox | |
""" | |
x, y, w, h = bbox | |
# box center | |
cx = int(x + w / 2) | |
cy = int(y + h / 2) | |
# expand by scale factor | |
new_size = max(int(w * scale), int(h * scale)) | |
new_x = max(0, int(cx - new_size / 2)) | |
new_y = max(0, int(cy - new_size / 2)) | |
# Check for too big bbox for given x, y | |
new_size = min(width - new_x, new_size) | |
new_size = min(height - new_size, new_size) | |
return new_x, new_y, new_size, new_size | |
def extract_face_MTCNN(face_detector, image, expand_scale=1.3, res=256): | |
# Image size | |
height, width = image.shape[:2] | |
# Convert to rgb | |
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
# Detect with dlib | |
faces = face_detector.detect_faces(rgb) | |
if len(faces): | |
# For now only take biggest face | |
face = None | |
bbox = None | |
max_region = 0 | |
for ff in faces: | |
if max_region == 0: | |
face = ff | |
bbox = face['box'] | |
max_region = bbox[2]*bbox[3] | |
else: | |
bb = ff['box'] | |
region = bb[2]*bb[3] | |
if region > max_rigion: | |
max_rigion = region | |
face = ff | |
bbox = face['box'] | |
print(max_region) | |
#face = faces[0] | |
#bbox = face['box'] | |
# --- Prediction --------------------------------------------------- | |
# Face crop with MTCNN and bounding box scale enlargement | |
x, y, w, h = expand_bbox(bbox, width, height, scale=expand_scale) | |
cropped_face = rgb[y:y+h, x:x+w] | |
cropped_face = cv2.resize( | |
cropped_face, (res, res), interpolation=cv2.INTER_CUBIC) | |
cropped_face = cv2.cvtColor(cropped_face, cv2.COLOR_RGB2BGR) | |
return cropped_face | |
return None | |
def extract_aligned_face_MTCNN(face_detector, image, expand_scale=1.3, res=256, mask=None): | |
# Image size | |
height, width = image.shape[:2] | |
# Convert to rgb | |
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
# Detect with dlib | |
faces = face_detector.detect_faces(rgb) | |
if len(faces): | |
# For now only take biggest face | |
face = None | |
bbox = None | |
max_region = 0 | |
for i, ff in enumerate(faces): | |
if max_region == 0: | |
face = ff | |
bbox = face['box'] | |
max_region = bbox[2]*bbox[3] | |
else: | |
bb = ff['box'] | |
region = bb[2]*bb[3] | |
if region > max_region: | |
max_region = region | |
face = ff | |
bbox = face['box'] | |
#print('face {}: {}'.format(i, max_region)) | |
#face = faces[0] | |
landmarks = get_keypts(face) | |
# --- Prediction --------------------------------------------------- | |
# Face aligned crop with MTCNN and bounding box scale enlargement | |
if mask is not None: | |
cropped_face, cropped_mask = img_align_crop(rgb, landmarks, outsize=[ | |
res, res], scale=expand_scale, mask=mask) | |
cropped_face = cv2.cvtColor(cropped_face, cv2.COLOR_RGB2BGR) | |
cropped_mask = cv2.cvtColor(cropped_mask, cv2.COLOR_RGB2GRAY) | |
return cropped_face, cropped_mask | |
else: | |
cropped_face = img_align_crop(rgb, landmarks, outsize=[ | |
res, res], scale=expand_scale) | |
cropped_face = cv2.cvtColor(cropped_face, cv2.COLOR_RGB2BGR) | |
return cropped_face | |
return None | |
def extract_face_DLIB(face_detector, image, expand_scale=1.3, res=256): | |
# Image size | |
height, width = image.shape[:2] | |
# Convert to gray | |
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) | |
# Detect with dlib | |
faces = face_detector(gray, 1) | |
if len(faces): | |
# For now only take biggest face | |
face = faces[0] | |
x1 = face.left() | |
y1 = face.top() | |
x2 = face.right() | |
y2 = face.bottom() | |
bbox = (x1, y1, x2-x1, y2-y1) | |
# --- Prediction --------------------------------------------------- | |
# Face crop with dlib and bounding box scale enlargement | |
x, y, w, h = expand_bbox(bbox, width, height, scale=expand_scale) | |
cropped_face = image[y:y+h, x:x+w] | |
cropped_face = cv2.resize( | |
cropped_face, (res, res), interpolation=cv2.INTER_CUBIC) | |
return cropped_face | |
return None | |