summaryrefslogtreecommitdiff
path: root/megapixels/app/processors/face_pose.py
diff options
context:
space:
mode:
Diffstat (limited to 'megapixels/app/processors/face_pose.py')
-rw-r--r--megapixels/app/processors/face_pose.py148
1 files changed, 71 insertions, 77 deletions
diff --git a/megapixels/app/processors/face_pose.py b/megapixels/app/processors/face_pose.py
index 67ac685d..f2548b32 100644
--- a/megapixels/app/processors/face_pose.py
+++ b/megapixels/app/processors/face_pose.py
@@ -22,89 +22,83 @@ class FacePoseDLIB:
def __init__(self):
pass
- def pose(self, landmarks, dim):
- '''Calculates pose
- '''
- degrees = compute_pose_degrees(landmarks, dim)
- return degrees
+ def pose(self, landmarks, dim, project_points=False):
+ # computes pose using 6 / 68 points from dlib face landmarks
+ # based on learnopencv.com and
+ # https://github.com/jerryhouuu/Face-Yaw-Roll-Pitch-from-Pose-Estimation-using-OpenCV/
+ # NB: not as accurate as MTCNN, see @jerryhouuu for ideas
+
+ pose_points_idx = (30, 8, 36, 45, 48, 54)
+ axis = np.float32([[500,0,0], [0,500,0], [0,0,500]])
+
+ # 3D model points.
+ model_points = np.array([
+ (0.0, 0.0, 0.0), # Nose tip
+ (0.0, -330.0, -65.0), # Chin
+ (-225.0, 170.0, -135.0), # Left eye left corner
+ (225.0, 170.0, -135.0), # Right eye right corne
+ (-150.0, -150.0, -125.0), # Left Mouth corner
+ (150.0, -150.0, -125.0) # Right mouth corner
+ ])
+
+ # Assuming no lens distortion
+ dist_coeffs = np.zeros((4,1))
-# -----------------------------------------------------------
-# utilities
-# -----------------------------------------------------------
+ # find 6 pose points
+ pose_points = []
+ for j, idx in enumerate(pose_points_idx):
+ pt = landmarks[idx]
+ pose_points.append((pt[0], pt[1]))
+ pose_points = np.array(pose_points, dtype='double') # convert to double
+
+ # create camera matrix
+ focal_length = dim[0]
+ center = (dim[0]/2, dim[1]/2)
+ cam_mat = np.array(
+ [[focal_length, 0, center[0]],
+ [0, focal_length, center[1]],
+ [0, 1, 1]], dtype = "double")
+
+ # solve PnP for rotation and translation
+ (success, rot_vec, tran_vec) = cv.solvePnP(model_points, pose_points,
+ cam_mat, dist_coeffs,
+ flags=cv.SOLVEPNP_ITERATIVE)
-def compute_pose_degrees(landmarks, dim):
- # computes pose using 6 / 68 points from dlib face landmarks
- # based on learnopencv.com and
- # https://github.com/jerryhouuu/Face-Yaw-Roll-Pitch-from-Pose-Estimation-using-OpenCV/
- # NB: not as accurate as MTCNN, see @jerryhouuu for ideas
-
- pose_points_idx = (30, 8, 36, 45, 48, 54)
- axis = np.float32([[500,0,0], [0,500,0], [0,0,500]])
-
- # 3D model points.
- model_points = np.array([
- (0.0, 0.0, 0.0), # Nose tip
- (0.0, -330.0, -65.0), # Chin
- (-225.0, 170.0, -135.0), # Left eye left corner
- (225.0, 170.0, -135.0), # Right eye right corne
- (-150.0, -150.0, -125.0), # Left Mouth corner
- (150.0, -150.0, -125.0) # Right mouth corner
- ])
-
- # Assuming no lens distortion
- dist_coeffs = np.zeros((4,1))
+ result = {}
- # find 6 pose points
- pose_points = []
- for j, idx in enumerate(pose_points_idx):
- pt = landmarks[idx]
- pose_points.append((pt[0], pt[1]))
- pose_points = np.array(pose_points, dtype='double') # convert to double
-
- # create camera matrix
- focal_length = dim[0]
- center = (dim[0]/2, dim[1]/2)
- cam_mat = np.array(
- [[focal_length, 0, center[0]],
- [0, focal_length, center[1]],
- [0, 1, 1]], dtype = "double")
-
- # solve PnP for rotation and translation
- (success, rot_vec, tran_vec) = cv.solvePnP(model_points, pose_points,
- cam_mat, dist_coeffs,
- flags=cv.SOLVEPNP_ITERATIVE)
+ # project points
+ if project_points:
+ pts_im, jac = cv.projectPoints(axis, rot_vec, tran_vec, cam_mat, dist_coeffs)
+ pts_model, jac2 = cv.projectPoints(model_points, rot_vec, tran_vec, cam_mat, dist_coeffs)
+ result['points_model'] = pts_model
+ result['points_image'] = pts_im
+ result['point_nose'] = tuple(landmarks[pose_points_idx[0]])
- # project points
- #pts_im, jac = cv.projectPoints(axis, rot_vec, tran_vec, cam_mat, dist_coeffs)
- #pts_model, jac2 = cv.projectPoints(model_points, rot_vec, tran_vec, cam_mat, dist_coeffs)
- rvec_matrix = cv.Rodrigues(rot_vec)[0]
-
- # convert to degrees
- proj_matrix = np.hstack((rvec_matrix, tran_vec))
- eulerAngles = cv.decomposeProjectionMatrix(proj_matrix)[6]
- pitch, yaw, roll = [math.radians(x) for x in eulerAngles]
- pitch = math.degrees(math.asin(math.sin(pitch)))
- roll = -math.degrees(math.asin(math.sin(roll)))
- yaw = math.degrees(math.asin(math.sin(yaw)))
- degrees = {'pitch': pitch, 'roll': roll, 'yaw': yaw}
-
- # add nose point
- #pt_nose = tuple(landmarks[pose_points_idx[0]])
- return degrees
- #return pts_im, pts_model, degrees, pt_nose
+ rvec_matrix = cv.Rodrigues(rot_vec)[0]
+
+ # convert to degrees
+ proj_matrix = np.hstack((rvec_matrix, tran_vec))
+ eulerAngles = cv.decomposeProjectionMatrix(proj_matrix)[6]
+ pitch, yaw, roll = [math.radians(x) for x in eulerAngles]
+ pitch = math.degrees(math.asin(math.sin(pitch)))
+ roll = -math.degrees(math.asin(math.sin(roll)))
+ yaw = math.degrees(math.asin(math.sin(yaw)))
+ degrees = {'pitch': pitch, 'roll': roll, 'yaw': yaw}
+ result['degrees'] = degrees
+ return result
-def draw_pose(im, pts_im, pts_model, pt_nose):
- cv.line(im, pt_nose, tuple(pts_im[1].ravel()), (0,255,0), 3) #GREEN
- cv.line(im, pt_nose, tuple(pts_im[0].ravel()), (255,0,), 3) #BLUE
- cv.line(im, pt_nose, tuple(pts_im[2].ravel()), (0,0,255), 3) #RED
- return im
+ def draw_pose(self, im, pts_im, pts_model, pt_nose):
+ cv.line(im, pt_nose, tuple(pts_im[1].ravel()), (0,255,0), 3) #GREEN
+ cv.line(im, pt_nose, tuple(pts_im[0].ravel()), (255,0,), 3) #BLUE
+ cv.line(im, pt_nose, tuple(pts_im[2].ravel()), (0,0,255), 3) #RED
-def draw_degrees(im, degrees, color=(0,255,0)):
- for i, item in enumerate(degrees.items()):
- k, v = item
- t = '{}: {:.2f}'.format(k, v)
- origin = (10, 30 + (25 * i))
- cv.putText(im, t, origin, cv.FONT_HERSHEY_SIMPLEX, 0.5, color, thickness=2, lineType=2) \ No newline at end of file
+
+ def draw_degrees(self, im, degrees, color=(0,255,0)):
+ for i, item in enumerate(degrees.items()):
+ k, v = item
+ t = '{}: {:.2f}'.format(k, v)
+ origin = (10, 30 + (25 * i))
+ cv.putText(im, t, origin, cv.FONT_HERSHEY_SIMPLEX, 0.5, color, thickness=2, lineType=2) \ No newline at end of file