EngAbod commited on
Commit
4a9658a
·
1 Parent(s): f1dbcba

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +334 -17
app.py CHANGED
@@ -1,24 +1,341 @@
1
- import streamlit as st
2
  import cv2
 
3
  import numpy as np
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
- def detect_face(image):
6
- face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
7
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
8
- faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
9
- for (x, y, w, h) in faces:
10
- cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
11
- return image
12
 
13
- st.title("Face Detection App")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
- uploaded_image = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"])
16
- if uploaded_image is not None:
17
- image = cv2.imdecode(np.fromstring(uploaded_image.read(), np.uint8), 1)
18
- st.image(image, caption="Uploaded Image", use_column_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
- if st.button("Detect Faces"):
21
- result_image = detect_face(image)
22
- st.image(result_image, caption="Image with Detected Faces", use_column_width=True)
 
 
23
 
24
- st.write("This is a simple face detection app using Streamlit and OpenCV.")
 
 
 
 
 
 
 
1
  import cv2
2
+ import mediapipe as mp
3
  import numpy as np
4
+ import time
5
+ from tensorflow.keras.models import Sequential
6
+ from tensorflow.keras.layers import Dense, Conv1D, MaxPooling1D, Flatten, Dropout
7
+ from tensorflow.keras.optimizers import Adam
8
+ # VECTORIZATION the u factor
9
+ from scipy.signal import convolve2d
10
+ import matplotlib.pyplot as plt
11
+ import math
12
+ from skimage import io, color
13
+ from tensorflow import keras
14
+ from tensorflow.keras.models import load_model
15
+ from sklearn.ensemble import RandomForestClassifier
16
+ from sklearn.metrics import accuracy_score
17
+ import os
18
+ import torch
19
+ import torchvision.transforms as transforms
20
+ import torchvision.models as models
21
+ import joblib
22
+ import h5py
23
+ from PIL import Image
24
+ import streamlit as st
25
+
26
+
27
+
28
+
29
+
30
+ # Load the model
31
+ model = load_model('best_model_HQ_v8.h5')
32
+
33
+ num_bins = 256
34
+
35
+ def u_sliding_factor(image_channel, P):
36
+
37
+ result = np.zeros(image_channel.shape, np.float32)
38
+
39
+ # Define the sliding window size
40
+
41
+ window_size = (3, 3)
42
+
43
+ # Create the convolution kernel
44
+ kernel = np.ones(window_size, np.float32)
45
+ kernel[1, 1] = 0
46
+ kernel = kernel / (2 * P)
47
+ kernal2 = np.zeros(window_size, np.float32)
48
+ kernal2[1, 1] = 1
49
+ kernal2 = kernal2 / 2
50
+ # Perform the convolution using scipy's convolve2d
51
+ convolution_matrix = cv2.filter2D(image_channel,-1,kernel) + cv2.filter2D(image_channel,-1,kernal2)
52
+ result = convolution_matrix[1:-1, 1:-1]
53
+
54
+ return result.astype(np.float32)
55
+
56
+ # Compute the C factor in this function which return a list of 8 values
57
+
58
+
59
+ # calculate C factor
60
+
61
+ def C_list_calculate(P):
62
+ C = []
63
+ for count in range(1, 9):
64
+ c_value = ((P - count) * (count - 1)) / math.floor(((P - 1) / 2)**2)
65
+ C.append(c_value)
66
+ return C
67
+
68
+
69
+ # The equilibriam Local Binary Pattern to compute the Texture values of an image
70
 
71
+ def ED_LBP_Sliding_Matrix(I, P):
72
+ # Define the amount of padding
73
+ padding_amount = 1
 
 
 
 
74
 
75
+ # Pad the array with zeros
76
+ I = np.pad(I, pad_width=padding_amount, mode='constant')
77
+ K = (2**P) - 1
78
+ C_list = C_list_calculate(8)
79
+ u_fac_matrix = u_sliding_factor(I.astype(np.float32),P)
80
+ slid_factor = np.zeros((u_fac_matrix.shape),np.float32)
81
+ m, n = u_fac_matrix.shape
82
+ ED_LBP = np.zeros(u_fac_matrix.shape,np.float32)
83
+ ED_LBP_matrix = np.zeros((u_fac_matrix.shape),np.float32)
84
+ K_matrix = np.ones(u_fac_matrix.shape).astype(np.float32) * K
85
+ offsets = [(0, 1), (0, 2), (1, 2), (2, 2), (2, 1), (2, 0), (1, 0),(0,0)]
86
+ count = 1
87
+ for offset in offsets:
88
+ row_offset, col_offset = offset
89
+ sliding_matrix = I[row_offset:row_offset+m, col_offset:col_offset+n].astype(np.float32) - u_fac_matrix.astype(np.float32)
90
+ slid_factor = np.maximum(sliding_matrix,0).astype(np.float32)
91
+ k_norm = K_matrix.astype(np.float32) - u_fac_matrix.astype(np.float32)
92
+ # Replace zero values with a small non-zero value to avoid division by zero
93
+ k_norm_nonzero = np.where(k_norm == 0, 1e-10, k_norm)
94
+ # Calculate A_factor with the corrected k_norm_nonzero
95
+ A_factor = np.where(k_norm != 0, slid_factor / k_norm_nonzero, 0)
96
+ #A_factor = np.where(k_norm != 0, slid_factor / k_norm, 0)
97
+ ED_LBP_matrix = (A_factor.astype(np.float32) * C_list[count-1]) + np.ones(A_factor.shape).astype(np.float32)
98
+ ED_LBP = ED_LBP + np.where(sliding_matrix >= 0, 2**((count-1)*ED_LBP_matrix.astype(np.float32)),0)
99
+ count = count + 1
100
+ ED_LBP = np.where(ED_LBP > 255, 255, np.round(ED_LBP))
101
 
102
+ return ED_LBP.astype(int)
103
+
104
+ # Compute Hostogram for the images to extract the Vector of Feachres
105
+
106
+
107
+ def compute_histogram(image, num_bins):
108
+ hist = cv2.calcHist([image], [0], None, [num_bins], [0, num_bins])
109
+ hist = hist / hist.sum() # Normalize the histogram
110
+ return hist
111
+
112
+ def spatial_pyramid(image, num_bins):
113
+ ED_LBP_image = np.zeros((image.shape),np.int16)
114
+ num_channels = image.shape[2]
115
+ histograms = []
116
+
117
+ for channel in range(num_channels):
118
+ #convert image to rgp
119
+
120
+ ED_LBP_image[:, :, channel] = ED_LBP_Sliding_Matrix(image[:, :, channel].astype(np.int16), 8)
121
+
122
+ # compute ED_LBP image
123
+
124
+ # Level 0: Compute histogram for the entire channel
125
+ H1_channel = compute_histogram(ED_LBP_image[:, :, channel].astype(np.uint8), num_bins).ravel() # Flatten H1_channel # Take care
126
+
127
+ # Level 2: Compute histograms for 4x4 grids
128
+ grid_size = 4
129
+ H2_channel = np.empty((grid_size, grid_size, num_bins))
130
+ grid_height, grid_width = ED_LBP_image[:, :, channel].shape[0] // grid_size, ED_LBP_image[:, :, channel].shape[1] // grid_size
131
+ for m in range(grid_size):
132
+ for n in range(grid_size):
133
+ grid_image = ED_LBP_image[m * grid_height : (m + 1) * grid_height,
134
+ n * grid_width : (n + 1) * grid_width, channel]
135
+ H2_channel[m, n] = compute_histogram(grid_image.astype(np.uint8), num_bins).ravel() # Flatten the histogram
136
+
137
+ H2_channel = H2_channel.reshape(-1) # Flatten H2_channel
138
+
139
+ # Concatenate histograms fr.om level 0 and level 2
140
+ Hs_channel = np.concatenate((H1_channel, H2_channel))
141
+ histograms.append(Hs_channel)
142
+
143
+ # Concatenate histograms from all channels
144
+ feature_vector = np.concatenate(histograms)
145
+ return feature_vector
146
+
147
+
148
+ # Land marks Detection
149
+ # Initialize variables to control frame capture interval
150
+ capture_interval = 10 # Capture one frame every 10 seconds
151
+ last_capture_time = 0
152
+
153
+ mp_face_mesh = mp.solutions.face_mesh
154
+ face_mesh = mp_face_mesh.FaceMesh(min_detection_confidence=0.5, min_tracking_confidence=0.5)
155
+ mp_drawing = mp.solutions.drawing_utils
156
+ drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1)
157
+ cap = cv2.VideoCapture(0)
158
+ # Streamlit
159
+ st.title("Liveness Detector")
160
+ frame_place_holder = st.empty()
161
+ text_element = st.empty()
162
+ stop_button_pressed = st.button("Stop")
163
+ # Initialize flags to track face detection and image saving
164
+ valid_face_detected = False
165
+ image_saved = False
166
+
167
+ while cap.isOpened() and not stop_button_pressed:
168
+ success, image = cap.read()
169
+ if not success:
170
+ st.write("End video")
171
+ break
172
+ start = time.time()
173
+ save_first_frame = True
174
+ #image = cv2.resize(image, (640, 480))
175
+ rotated_image = cv2.transpose(image)
176
+ #image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
177
+ image.flags.writeable = False
178
+ results = face_mesh.process(image)
179
+ image.flags.writeable = True
180
+ image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
181
+ img_h, img_w, img_c = image.shape
182
+ face_3d = []
183
+ face_2d = []
184
+ if results.multi_face_landmarks:
185
+ for face_landmarks in results.multi_face_landmarks:
186
+ for idx, lm in enumerate(face_landmarks.landmark):
187
+ if idx==33 or idx==263 or idx==1 or idx==61 or idx==291 or idx==199:
188
+ if idx == 1:
189
+ nose_2d = (lm.x * img_w, lm.y * img_h)
190
+ nose_3d = (lm.x * img_w, lm.y * img_h, lm.z * 3000)
191
+ x, y = int(lm.x * img_w), int(lm.y * img_h)
192
+
193
+ # Get the 2d cordinate
194
+ face_2d.append([x, y])
195
+
196
+ # Get 3d cordinate
197
+
198
+ face_3d.append([x, y, lm.z])
199
+ #convert to numpy array
200
+ face_2d = np.array(face_2d, dtype=np.float32)
201
+ face_3d = np.array(face_3d, dtype=np.float32)
202
+
203
+ #The camera matrix
204
+
205
+ focal_length = 1 * img_w
206
+ #The distance matrix
207
+ cam_matrix = np.array([[focal_length, 0, img_h / 2],
208
+ [0, focal_length, img_w / 2],
209
+ [0, 0, 1]])
210
+ # the distance matrix
211
+ dist_matrix = np.zeros((4, 1), dtype=np.float64)
212
+ #solve PnP
213
+ success, rot_vec, trans_vec = cv2.solvePnP(face_3d, face_2d, cam_matrix, dist_matrix)
214
+
215
+ #get rotational matrix
216
+ rmat ,jac = cv2.Rodrigues(rot_vec)
217
+
218
+ #Get angles1
219
+ angles, mtxR, mtxQ, Qx, Qy, Qz = cv2.RQDecomp3x3(rmat)
220
+
221
+ #get y rotation degree
222
+ x = angles[0] * 360
223
+ y = angles[1] * 360
224
+ z = angles[2] * 360
225
+ #text = "No Face"
226
+ # see where the user's head tilting
227
+ if y < -10:
228
+ text = "Look Right"
229
+ elif y > 10:
230
+ text = "Look Left"
231
+ elif x < -10:
232
+ text = "Look Up"
233
+ elif x > 10:
234
+ text = "Look Down"
235
+ else:
236
+ #text = "Forward"
237
+ current_time = time.time()
238
+ if current_time - last_capture_time >= capture_interval:
239
+ last_capture_time = current_time
240
+ image_data = []
241
+ features_list=[]
242
+ features_list2=[]
243
+ # Check if there are face landmarks detected
244
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
245
+
246
+
247
+ # Detect faces using cascade classifier
248
+ face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
249
+ faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
250
+ expansion_factor = 1.5
251
+ num_bins = 256
252
+ biggest_face = None
253
+ biggest_area = 0
254
+ target_size = (512,512)
255
+ for (x, y, w, h) in faces:
256
+ # Calculate the expanded dimensions
257
+ expanded_x = max(0, int(x - (w * (expansion_factor - 1) / 2)))
258
+ expanded_y = max(0, int(y - (h * (expansion_factor - 1) / 2)))
259
+ expanded_w = min(img_w, int(w * expansion_factor))
260
+ expanded_h = min(img_h, int(h * expansion_factor))
261
+
262
+ # Crop the expanded face region from the frame
263
+ current_area = expanded_w * expanded_h
264
+ if current_area > biggest_area:
265
+ biggest_area = current_area
266
+ # biggest_face = image[expanded_y:expanded_y + expanded_h, expanded_x:expanded_x + expanded_w]
267
+ biggest_face = image[y:y + h, x:x + w]
268
+ resized_face = cv2.resize(biggest_face, target_size)
269
+ resized_face = cv2.cvtColor(resized_face, cv2.COLOR_BGR2RGB)
270
+ if save_first_frame:
271
+ # Save the first frame as a JPG image
272
+ cv2.imwrite('first_frame.jpg', resized_face)
273
+ save_first_frame = False # Disable savin
274
+ if biggest_face is not None:
275
+
276
+ # Perform spatial pyramid feature extraction
277
+ rgb_features = spatial_pyramid(cv2.cvtColor(resized_face, cv2.COLOR_BGR2RGB), num_bins)
278
+ hsv_features = spatial_pyramid(cv2.cvtColor(resized_face, cv2.COLOR_BGR2HSV), num_bins)
279
+ ycbcr_features = spatial_pyramid(cv2.cvtColor(resized_face, cv2.COLOR_BGR2YCrCb), num_bins)
280
+ if rgb_features.size > 0 and hsv_features.size > 0 and ycbcr_features.size > 0:
281
+ combined_features = np.concatenate((rgb_features, hsv_features, ycbcr_features))
282
+ features_list.append(combined_features)
283
+
284
+ if len(features_list) > 0:
285
+ X_array = np.array(features_list)
286
+ X_test_array_reshaped = np.expand_dims(X_array, axis=-1)
287
+ prediction = model.predict(X_test_array_reshaped)
288
+
289
+
290
+ if prediction >= 0.74:
291
+ text2 = str(prediction[0])
292
+ valid_face_detected = True
293
+ if valid_face_detected and not image_saved:
294
+ # Save the current face image
295
+ cv2.imwrite('current_face.jpg', resized_face)
296
+ image_saved = True # Set this flag to indicate the image has been saved
297
+
298
+ #save current resized_face
299
+ elif prediction < 0.74:
300
+ text= "Not Live Image"
301
+ text2 = str(prediction[0])
302
+ else:
303
+ text = "Fake Image"
304
+
305
+ # Display the nose direction
306
+ nose_3d_projection, jacobian = cv2.projectPoints(nose_3d, rot_vec, trans_vec, cam_matrix, dist_matrix, dist_matrix)
307
+
308
+ p1 = (int(nose_2d[0]), int(nose_2d[1]))
309
+ p2 = (int(nose_2d[0] + y*10), int(nose_2d[1] - x * 10))
310
+
311
+ cv2.line(image, p1, p2, (255,0,0), 3)
312
+ cv2.putText(image, text, (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 0, 0))
313
+ cv2.putText(image, "x :" + str(np.round(x,2)), (500, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
314
+ cv2.putText(image, "y :" + str(np.round(x,2)), (500, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
315
+ cv2.putText(image, "z :" + str(np.round(x,2)), (500, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
316
+ mp_drawing.draw_landmarks(
317
+ image=image,
318
+ landmark_list=face_landmarks,
319
+ connections=mp_face_mesh.FACEMESH_TESSELATION,
320
+ landmark_drawing_spec=drawing_spec,
321
+ connection_drawing_spec=drawing_spec)
322
+ else:
323
+ text = "There is no Face"
324
+ #Add the text on the image
325
+ cv2.putText(image, text, (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 0, 0))
326
+
327
+ end = time.time()
328
+ totalTime = end - start
329
 
330
+ fps = 1 / totalTime
331
+
332
+ cv2.putText(image, f'FPS: {int(fps)}', (20,450), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255, 0, 0), 2)
333
+
334
+ frame_place_holder.image(cv2.cvtColor(image, cv2.COLOR_BGR2RGB), use_column_width=True, channels="BGR")
335
 
336
+ if (cv2.waitKey(5) & 0xff ==27) or stop_button_pressed:
337
+ break
338
+ valid_face_detected = False
339
+ image_saved = False
340
+
341
+ cap.release()