Spaces:
Sleeping
Sleeping
| import cv2 | |
| import mediapipe as mp | |
| from mediapipe import solutions | |
| from mediapipe.framework.formats import landmark_pb2 | |
| import numpy as np | |
| import math | |
| # visualization libraries | |
| import matplotlib.pyplot as plt | |
| import matplotlib.animation as animation | |
| from matplotlib import style | |
| def draw_eyes_on_image(rgb_image, detection_result): | |
| # return rgb_image, 0, 0 | |
| # canonical_face_model_uv_visualization in the below link | |
| # https://github.com/google/mediapipe/blob/a908d668c730da128dfa8d9f6bd25d519d006692/mediapipe/modules/face_geometry/data/canonical_face_model_uv_visualization.png | |
| left_eyes_bottom_list = [33, 7, 163, 144, 145, 153, 154, 155, 133] | |
| left_eyes_top_list = [246, 161, 160, 159, 158, 157, 173] | |
| right_eyes_bottom_list = [362, 382, 381, 380, 374, 373, 390, 249, 263] | |
| right_eyes_top_list = [398, 384, 385, 386, 387, 388, 466] | |
| face_landmarks_list = detection_result.face_landmarks | |
| annotated_image = np.copy(rgb_image) | |
| # We resize image to 640 * 360 | |
| height, width, channels = rgb_image.shape | |
| # Loop through the detected faces to visualize. Actually, if we detect more than two faces, we will require user closer to the camera | |
| for idx in range(len(face_landmarks_list)): | |
| face_landmarks = face_landmarks_list[idx] | |
| mlist = [] | |
| for landmark in face_landmarks: | |
| mlist.append([int(landmark.x * width), int(landmark.y * height), landmark.z]) | |
| narray = np.copy(mlist) | |
| # Vertical line | |
| # | |
| # | |
| # Pick the largest difference (middle of the eyes) | |
| leftUp = narray[159] | |
| leftDown = narray[145] | |
| rightUp = narray[386] | |
| rightDown = narray[374] | |
| # compute left eye distance (vertical) | |
| leftUp_x = int(leftUp[0]) | |
| leftUp_y = int(leftUp[1]) | |
| leftDown_x = int(leftDown[0]) | |
| leftDown_y = int(leftDown[1]) | |
| leftVerDis = math.dist([leftUp_x, leftUp_y],[leftDown_x, leftDown_y]) | |
| # compute right eye distance (vertical) | |
| rightUp_x = int(rightUp[0]) | |
| rightUp_y = int(rightUp[1]) | |
| rightDown_x = int(rightDown[0]) | |
| rightDown_y = int(rightDown[1]) | |
| rightVerDis = math.dist([rightUp_x, rightUp_y],[rightDown_x, rightDown_y]) | |
| # print(f'leftVerDis: {leftVerDis} and rightVerDis: {rightVerDis}') | |
| # draw a line from left eye top to bottom | |
| annotated_image = cv2.line(rgb_image, (int(leftUp_x), int(leftUp_y)), (int(leftDown_x), int(leftDown_y)), (0, 200, 0), 1) | |
| # draw a line from right eye top to bottom | |
| annotated_image = cv2.line(rgb_image, (int(rightUp_x), int(rightUp_y)), (int(rightDown_x), int(rightDown_y)), (0, 200, 0), 1) | |
| # | |
| # | |
| # Horizontonal line | |
| # | |
| # | |
| # Pick the largest difference (middle of the eyes) | |
| leftLeft = narray[33] | |
| leftRight = narray[133] | |
| rightLeft = narray[362] | |
| rightRight = narray[263] | |
| # compute left eye distance (horizontal) | |
| leftLeft_x = int(leftLeft[0]) | |
| leftLeft_y = int(leftLeft[1]) | |
| leftRight_x = int(leftRight[0]) | |
| leftRight_y = int(leftRight[1]) | |
| leftHorDis = math.dist([leftLeft_x, leftLeft_y],[leftRight_x, leftRight_y]) | |
| # compute right eye distance (horizontal) | |
| rightLeft_x = int(rightLeft[0]) | |
| rightLeft_y = int(rightLeft[1]) | |
| rightRight_x = int(rightRight[0]) | |
| rightRight_y = int(rightRight[1]) | |
| rightHorDis = math.dist([rightLeft_x, rightLeft_y],[rightRight_x, rightRight_y]) | |
| # print(f'leftHorDis: {leftHorDis} and rightHorDis: {rightHorDis}') | |
| # draw a line from left eye top to bottom | |
| annotated_image = cv2.line(rgb_image, (int(leftLeft_x), int(leftLeft_y)), (int(leftRight_x), int(leftRight_y)), (0, 200, 0), 1) | |
| # draw a line from right eye top to bottom | |
| annotated_image = cv2.line(rgb_image, (int(rightLeft_x), int(rightLeft_y)), (int(rightRight_x), int(rightRight_y)), (0, 200, 0), 1) | |
| # | |
| # | |
| # | |
| # | |
| # print(f'leftRatio: {leftVerDis/leftHorDis} and rightRatio: {rightVerDis/rightHorDis}') | |
| leftRatio = leftVerDis/leftHorDis*100 | |
| rightRatio = rightVerDis/rightHorDis*100 | |
| # left_eyes_bottom = [narray[x] for x in left_eyes_bottom_list] | |
| # left_eyes_top = [narray[x] for x in left_eyes_top_list] | |
| # right_eyes_bottom = [narray[x] for x in right_eyes_bottom_list] | |
| # right_eyes_top = [narray[x] for x in right_eyes_top_list] | |
| # for p in left_eyes_bottom: | |
| # annotated_image = cv2.circle(rgb_image, (int(p[0]), int(p[1])), radius=1, color=(0,0,255), thickness=1) | |
| # for p in left_eyes_top: | |
| # annotated_image = cv2.circle(rgb_image, (int(p[0]), int(p[1])), radius=1, color=(0,0,255), thickness=1) | |
| # for p in right_eyes_bottom: | |
| # annotated_image = cv2.circle(rgb_image, (int(p[0]), int(p[1])), radius=1, color=(0,0,255), thickness=1) | |
| # for p in right_eyes_top: | |
| # annotated_image = cv2.circle(rgb_image, (int(p[0]), int(p[1])), radius=1, color=(0,0,255), thickness=1) | |
| return annotated_image, leftRatio, rightRatio | |
| def draw_landmarks_on_image(rgb_image, detection_result): | |
| face_landmarks_list = detection_result.face_landmarks | |
| annotated_image = np.copy(rgb_image) | |
| # Loop through the detected faces to visualize. Actually, if we detect more than two faces, we will require user closer to the camera | |
| for idx in range(len(face_landmarks_list)): | |
| face_landmarks = face_landmarks_list[idx] | |
| # Draw the face landmarks. | |
| face_landmarks_proto = landmark_pb2.NormalizedLandmarkList() | |
| face_landmarks_proto.landmark.extend([ | |
| landmark_pb2.NormalizedLandmark(x=landmark.x, y=landmark.y, z=landmark.z) for landmark in face_landmarks | |
| ]) | |
| solutions.drawing_utils.draw_landmarks( | |
| image=annotated_image, | |
| landmark_list=face_landmarks_proto, | |
| connections=mp.solutions.face_mesh.FACEMESH_TESSELATION, | |
| landmark_drawing_spec=None, | |
| connection_drawing_spec=mp.solutions.drawing_styles | |
| .get_default_face_mesh_tesselation_style()) | |
| solutions.drawing_utils.draw_landmarks( | |
| image=annotated_image, | |
| landmark_list=face_landmarks_proto, | |
| connections=mp.solutions.face_mesh.FACEMESH_CONTOURS, | |
| landmark_drawing_spec=None, | |
| connection_drawing_spec=mp.solutions.drawing_styles | |
| .get_default_face_mesh_contours_style()) | |
| solutions.drawing_utils.draw_landmarks( | |
| image=annotated_image, | |
| landmark_list=face_landmarks_proto, | |
| connections=mp.solutions.face_mesh.FACEMESH_IRISES, | |
| landmark_drawing_spec=None, | |
| connection_drawing_spec=mp.solutions.drawing_styles | |
| .get_default_face_mesh_iris_connections_style()) | |
| return annotated_image | |
| def plot_face_blendshapes_bar_graph(face_blendshapes): | |
| # Extract the face blendshapes category names and scores. | |
| face_blendshapes_names = [face_blendshapes_category.category_name for face_blendshapes_category in face_blendshapes] | |
| face_blendshapes_scores = [face_blendshapes_category.score for face_blendshapes_category in face_blendshapes] | |
| # The blendshapes are ordered in decreasing score value. | |
| face_blendshapes_ranks = range(len(face_blendshapes_names)) | |
| fig, ax = plt.subplots(figsize=(12, 12)) | |
| bar = ax.barh(face_blendshapes_ranks, face_blendshapes_scores, label=[str(x) for x in face_blendshapes_ranks]) | |
| ax.set_yticks(face_blendshapes_ranks, face_blendshapes_names) | |
| ax.invert_yaxis() | |
| # Label each bar with values | |
| for score, patch in zip(face_blendshapes_scores, bar.patches): | |
| plt.text(patch.get_x() + patch.get_width(), patch.get_y(), f"{score:.4f}", va="top") | |
| ax.set_xlabel('Score') | |
| ax.set_title("Face Blendshapes") | |
| plt.tight_layout() | |
| plt.show() |