Spaces:
Runtime error
Runtime error
File size: 6,644 Bytes
25169f2 d976df5 25169f2 d976df5 25169f2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
import gradio as gr
from flask import Flask, Response
import cv2
import numpy as np
import mediapipe as mp
import matplotlib.pyplot as plt
import math
from IPython import display
# --------------------
MAX_ANGLE = 10
# --------------------
# --------------------
# --------------------
# --------------------
def distanceCalculate(p):
p1 = p[0]
p2 = p[1]
dis = ((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2) ** 0.5
return dis
# --------------------
def angleLinePoints(p):
p1 = p[0]
p2 = p[1]
#
p1_x = p1[0]
p1_y = p1[1]
p2_x = p2[0]
p2_y = p2[1]
#
d_x = p2_x - p1_x
d_y = p2_y - p1_y
#
angle_radians = np.arctan(d_y/d_x)
angle_degrees = math.degrees(angle_radians)
return angle_degrees
# --------------------
def process_image(image):
if isinstance(image, str):
image = cv2.imread(image)
#
(B, G, R) = cv2.split(image)
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(
static_image_mode=True,
max_num_faces=1,
refine_landmarks=True,
min_detection_confidence=0.5)
result = face_mesh.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
height, width, _ = image.shape
mesh_points= np.array([np.multiply([p.x, p.y], [width, height]).astype(int) for p in result.multi_face_landmarks[0].landmark])
# Landmark mapping
landmarks = {
'topToBottom': [10, 152],
'leftToRight': [234, 454],
'rightEyeIris': [473, 474, 475, 476, 477],
'leftEyeIris': [468, 469, 470, 471, 472],
'outerRightEyebrowUpper': 70,
'outerLeftEyebrowUpper': 300,
'silhouette': [10, 338, 297, 332, 284, 251, 389, 356, 454, 323, 361, 288,
397, 365, 379, 378, 400, 377, 152, 148, 176, 149, 150, 136,
172, 58, 132, 93, 234, 127, 162, 21, 54, 103, 67, 109]}
# Iris location
(l_cx, l_cy), l_radius = cv2.minEnclosingCircle(mesh_points[landmarks['rightEyeIris']])
(r_cx, r_cy), r_radius = cv2.minEnclosingCircle(mesh_points[landmarks['leftEyeIris']])
center_left_iris = np.array([l_cx, l_cy], dtype=np.int32)
center_right_iris = np.array([r_cx, r_cy], dtype=np.int32)
# Face dimension
width_face_px = distanceCalculate(mesh_points[landmarks['leftToRight']])
height_face_px = distanceCalculate(mesh_points[landmarks['topToBottom']])
# IPD calculation
ipd = distanceCalculate([center_left_iris, center_right_iris])
# Photo Quality Check
vertical_angle = angleLinePoints(mesh_points[landmarks['topToBottom']])
horizonal_angle = angleLinePoints(mesh_points[landmarks['leftToRight']])
# Rectangle for Card Area
x_start = mesh_points[landmarks['outerRightEyebrowUpper']][0]
y_start = mesh_points[landmarks['outerRightEyebrowUpper']][1] - 0.6*height_face_px
x_end, y_end = mesh_points[landmarks['outerLeftEyebrowUpper']]
start_point = (int(x_start), int(y_start))
end_point = (int(x_end), int(y_end))
#
overlay = image.copy()
alpha = 0.1
beta = (1.0 - alpha)
# Plot all the information
# plt.imshow(image)
# plt.imshow(image_landmarks)
for facial_landmarks in result.multi_face_landmarks:
for i in range(0, 468):
pt1 = facial_landmarks.landmark[i]
x = int(pt1.x * width)
y = int(pt1.y * height)
cv2.circle(image, (x, y), 1, (0,255,0), -1)
plt.imshow(cv2.polylines(image, [mesh_points[landmarks['topToBottom']]], 1, (0,255,0), 1))
plt.imshow(cv2.polylines(image, [mesh_points[landmarks['leftToRight']]], 1, (0,255,0), 1))
plt.imshow(cv2.polylines(image, [mesh_points[landmarks['silhouette']]], 1, (0,255,0), 1))
plt.imshow(cv2.line(image, center_left_iris, center_right_iris, (0, 255, 0), 2))
plt.imshow(cv2.line(image, mesh_points[landmarks['outerLeftEyebrowUpper']], mesh_points[landmarks['outerRightEyebrowUpper']], (0, 255, 0), 1))
plt.imshow(cv2.rectangle(image, start_point, end_point, (255,0,0), 1))
plt.imshow(cv2.ellipse(image, center=(int(width/2), int(height/2)), axes=(int(min(width,height)/4),int(min(width,height)/3)), angle=0, startAngle=0, endAngle=360, color=(255,255,255), thickness=4))
plt.imshow(cv2.putText(image, f'IPD: {str(ipd)} [px]', (50,50), cv2.FONT_HERSHEY_PLAIN,1, (0,0,0), 1))
plt.imshow(cv2.putText(image, f'Face Height: {str(height_face_px)} [px]', (50,100), cv2.FONT_HERSHEY_PLAIN,1, (0,0,0),1))
plt.imshow(cv2.putText(image, f'Face Width: {str(width_face_px)} [px]', (50,150), cv2.FONT_HERSHEY_PLAIN,1, (0,0,0), 1))
if abs(horizonal_angle) < MAX_ANGLE:
plt.imshow(cv2.putText(image, f'Horizonal Angle: {str(horizonal_angle)} [degrees]', (50,200), cv2.FONT_HERSHEY_PLAIN,1, (0,255,0), 1))
cv2.rectangle(overlay, (0,0), (width, height), (0, 255, 0), -1)
image = cv2.addWeighted(overlay, alpha, image, 1 - alpha, 0)
elif horizonal_angle < -MAX_ANGLE:
plt.imshow(cv2.arrowedLine(image,[int(x_start) - (int(min(width,height)/4)),int(y_start+ height_face_px/2)], [int(x_start), int(y_start+ height_face_px/2)], (0, 255, 0), 4))
plt.imshow(cv2.putText(image, f'Horizonal Angle: {str(horizonal_angle)} [degrees]', (50,200), cv2.FONT_HERSHEY_PLAIN,1, (0,0,255), 1))
cv2.rectangle(overlay, (0,0), (width, height), (0, 0, 255), -1)
image = cv2.addWeighted(overlay, alpha, image, 1 - alpha, 0)
plt.imshow(image)
elif horizonal_angle > MAX_ANGLE:
plt.imshow(cv2.arrowedLine(image, [int(x_start), int(y_start+ height_face_px/2)],[int(x_start) - (int(min(width,height)/4)),int(y_start+ height_face_px/2)], (0, 255, 0), 4))
plt.imshow(cv2.putText(image, f'Horizonal Angle: {str(horizonal_angle)} [degrees]', (50,200), cv2.FONT_HERSHEY_PLAIN,1, (0,0,255), 1))
cv2.rectangle(overlay, (0,0), (width, height), (0, 0, 255), -1)
image = cv2.addWeighted(overlay, alpha, image, 1 - alpha, 0)
plt.imshow(image)
if abs(vertical_angle) > (90 - MAX_ANGLE): #[-80, 80] -> okay
plt.imshow(cv2.putText(image, f'Vertical Angle: {str(vertical_angle)} [degrees]', (50,250), cv2.FONT_HERSHEY_PLAIN,1, (0,255,0), 1))
else:
plt.imshow(cv2.putText(image, f'Vertical Angle: {str(vertical_angle)} [degrees]', (50,250), cv2.FONT_HERSHEY_PLAIN,1, (0,0,255), 1))
#
return image
# --------------------
# --------------------
# --------------------
# --------------------
def processing_frame(im):
image = process_image(im)
return image
#
demo = gr.Interface(
processing_frame,
gr.Image(source="webcam", streaming=True),
"image",
live=True
)
demo.launch() |