Skip to content

Instantly share code, notes, and snippets.

@by-sabbir
Created February 23, 2020 17:45
Show Gist options
  • Save by-sabbir/42bcdb5b1172d8859e0e181b29a9138b to your computer and use it in GitHub Desktop.
Save by-sabbir/42bcdb5b1172d8859e0e181b29a9138b to your computer and use it in GitHub Desktop.
Medium Post The Math and Code Behind Facial Alignment
#optionally you can draw roi box by calling draw_rect() helper function
def draw_rect(image, rect):
x, y = rect.tl_corner().x, rect.tl_corner().y
w, h = rect.width(), rect.height()
cv.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
# summing up with detecting face and drawing rectangle
faces = face_detector(frame, 0)
for face in faces:
draw_rect(frame, face)
import os
import dlib
base_dir = os.path.dirname(__file__)
# download the predictor file from http://dlib.net/files/shape_predictor_5_face_landmarks.dat.bz2
shape_predictor_file = os.path.join(base_dir, "files", "shape_predictor_5_face_landmarks.dat")
face_detector = dlib.get_frontal_face_detector()
shape_predictor = dlib.shape_predictor(shape_predictor_file)
# helper function to compute angle and center of the line connecting eyes.
def get_angle(image, shape, type=5):
if type == 5:
shapes = np.array(shape.parts())
left_eye = ((shapes[0].x + shapes[1].x) // 2, (shapes[0].y + shapes[1].y) // 2)
right_eye = ((shapes[2].x + shapes[3].x) // 2, (shapes[2].y + shapes[3].y) // 2)
nose = (shapes[4].x, shapes[4].y)
eye_center = ((left_eye[0] + right_eye[0]) // 2, (left_eye[1] + right_eye[1]) // 2)
cv.circle(image, left_eye, 2, COLOR["white"], -1)
cv.circle(image, right_eye, 2, COLOR["white"], -1)
cv.circle(image, nose, 2, COLOR["white"], -1)
cv.circle(image, eye_center, 5, COLOR["white"], -1)
cv.line(image, left_eye, right_eye, COLOR["blue"], 2)
cv.line(image, left_eye, nose, COLOR["blue"], 2)
cv.line(image, right_eye, nose, COLOR["blue"], 2)
# computing angle
dx = left_eye[0] - right_eye[0]
dy = left_eye[1] - right_eye[1]
angle = np.degrees(np.arctan2(dy, dx))
cv.putText(image, str(int(abs(angle))) + " deg", (eye_center[0], eye_center[1] - 20), cv.FONT_HERSHEY_SIMPLEX, 0.6, COLOR["white"], 1)
return eye_center, angle
def align_img(image, center, angle):
height, width = image.shape[0], image.shape[1]
M = cv.getRotationMatrix2D(center, angle, 1)
return cv.warpAffine(image, M, (width, height))
# for clearity we will copy&paste the whole code from shape_predictor.py
for face in faces:
draw_rect(frame, face)
# 5 points shape predictor spits out four cordinates of eyes and one for nose
points = shape_predictor(frame, face)
center, angle = get_angle(frame, points, type=5)
# final image by rotating the image we get the warped image
warped_img = align_img(unaligned, center, angle)
import cv2 as cv
source = 0 # replace 0 with any file with absolute path to analyze from video source
cap = cv.VideoCapture(source)
while True:
ret, frame = cap.read()
# skipping an empty frame
if not ret:
continue
# press 'esc' to exit the program
if cv.waitKey(10) & 0xff == 27:
break
# cleaning up
cap.release()
cv.destroyAllWindows()
# will continue from the previous dlib_face_detector.py line 10
for face in faces:
draw_rect(frame, face)
# 5 points shape predictor spits out four cordinates of eyes and one for nose
points = shape_predictor(frame, face)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment