DanielFD commited on
Commit
25169f2
·
1 Parent(s): 687ca58

first_upload app

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