|
import cv2 |
|
import dlib |
|
import numpy as np |
|
|
|
|
|
def face_detection(img,upsample_times=1): |
|
|
|
|
|
|
|
detector = dlib.get_frontal_face_detector() |
|
faces = detector(img, upsample_times) |
|
|
|
return faces |
|
|
|
PREDICTOR_PATH = 'models/shape_predictor_68_face_landmarks.dat' |
|
predictor = dlib.shape_predictor(PREDICTOR_PATH) |
|
|
|
def face_points_detection(img, bbox:dlib.rectangle): |
|
|
|
shape = predictor(img, bbox) |
|
|
|
|
|
|
|
coords = np.asarray(list([p.x, p.y] for p in shape.parts()), dtype=int) |
|
|
|
|
|
return coords |
|
|
|
def select_face(im, r=10, choose=True): |
|
faces = face_detection(im) |
|
|
|
if len(faces) == 0: |
|
return None, None, None |
|
|
|
if len(faces) == 1 or not choose: |
|
idx = np.argmax([(face.right() - face.left()) * (face.bottom() - face.top()) for face in faces]) |
|
bbox = faces[idx] |
|
else: |
|
bbox = [] |
|
|
|
def click_on_face(event, x, y, flags, params): |
|
if event != cv2.EVENT_LBUTTONDOWN: |
|
return |
|
|
|
for face in faces: |
|
if face.left() < x < face.right() and face.top() < y < face.bottom(): |
|
bbox.append(face) |
|
break |
|
|
|
im_copy = im.copy() |
|
for face in faces: |
|
|
|
cv2.rectangle(im_copy, (face.left(), face.top()), (face.right(), face.bottom()), (0, 0, 255), 1) |
|
cv2.imshow('Click the Face:', im_copy) |
|
cv2.setMouseCallback('Click the Face:', click_on_face) |
|
while len(bbox) == 0: |
|
cv2.waitKey(1) |
|
cv2.destroyAllWindows() |
|
bbox = bbox[0] |
|
|
|
points = np.asarray(face_points_detection(im, bbox)) |
|
|
|
im_w, im_h = im.shape[:2] |
|
left, top = np.min(points, 0) |
|
right, bottom = np.max(points, 0) |
|
|
|
x, y = max(0, left - r), max(0, top - r) |
|
w, h = min(right + r, im_h) - x, min(bottom + r, im_w) - y |
|
|
|
return points - np.asarray([[x, y]]), (x, y, w, h), im[y:y + h, x:x + w] |
|
|
|
|
|
def select_all_faces(im, r=10): |
|
faces = face_detection(im) |
|
|
|
if len(faces) == 0: |
|
return None |
|
|
|
faceBoxes = {k : {"points" : None, |
|
"shape" : None, |
|
"face" : None} for k in range(len(faces))} |
|
for i, bbox in enumerate(faces): |
|
points = np.asarray(face_points_detection(im, bbox)) |
|
|
|
im_w, im_h = im.shape[:2] |
|
left, top = np.min(points, 0) |
|
right, bottom = np.max(points, 0) |
|
|
|
x, y = max(0, left - r), max(0, top - r) |
|
w, h = min(right + r, im_h) - x, min(bottom + r, im_w) - y |
|
faceBoxes[i]["points"] = points - np.asarray([[x, y]]) |
|
faceBoxes[i]["shape"] = (x, y, w, h) |
|
faceBoxes[i]["face"] = im[y:y + h, x:x + w] |
|
|
|
return faceBoxes |
|
|