Spaces:
Sleeping
Sleeping
Rahulk2197
commited on
Commit
•
24b6b17
1
Parent(s):
240753e
Upload 8 files
Browse files- .gitattributes +1 -0
- app.py +281 -131
- functions.py +3 -9
- incept_v3_10fps_full_0.4.keras +3 -0
.gitattributes
CHANGED
@@ -36,3 +36,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
36 |
incept_v3_10fps_full_dp0.4.keras filter=lfs diff=lfs merge=lfs -text
|
37 |
res10_300x300_ssd_iter_140000.caffemodel filter=lfs diff=lfs merge=lfs -text
|
38 |
shape_predictor_68_face_landmarks.dat filter=lfs diff=lfs merge=lfs -text
|
|
|
|
36 |
incept_v3_10fps_full_dp0.4.keras filter=lfs diff=lfs merge=lfs -text
|
37 |
res10_300x300_ssd_iter_140000.caffemodel filter=lfs diff=lfs merge=lfs -text
|
38 |
shape_predictor_68_face_landmarks.dat filter=lfs diff=lfs merge=lfs -text
|
39 |
+
incept_v3_10fps_full_0.4.keras filter=lfs diff=lfs merge=lfs -text
|
app.py
CHANGED
@@ -1,131 +1,281 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
import
|
6 |
-
import
|
7 |
-
|
8 |
-
import
|
9 |
-
import
|
10 |
-
|
11 |
-
from
|
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 |
-
# Function to
|
82 |
-
def
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# import os
|
2 |
+
# os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
|
3 |
+
|
4 |
+
# import streamlit as st
|
5 |
+
# import cv2
|
6 |
+
# from tqdm import tqdm
|
7 |
+
# import numpy as np
|
8 |
+
# import tensorflow as tf
|
9 |
+
# import pandas as pd
|
10 |
+
# from tempfile import NamedTemporaryFile
|
11 |
+
# from functions import *
|
12 |
+
|
13 |
+
# threshold=[0.6827917,
|
14 |
+
# 0.7136434,
|
15 |
+
# 0.510756,
|
16 |
+
# 0.56771123,
|
17 |
+
# 0.49417764,
|
18 |
+
# 0.45892453,
|
19 |
+
# 0.32996163,
|
20 |
+
# 0.5038406,
|
21 |
+
# 0.44855,
|
22 |
+
# 0.32959282,
|
23 |
+
# 0.45619836,
|
24 |
+
# 0.4969851]
|
25 |
+
# au_to_movements= {
|
26 |
+
# 'au1': 'inner brow raiser',
|
27 |
+
# 'au2': 'outer brow raiser',
|
28 |
+
# 'au4': 'brow lowerer',
|
29 |
+
# 'au5': 'upper lid raiser',
|
30 |
+
# 'au6': 'cheek raiser',
|
31 |
+
# 'au9': 'nose wrinkler',
|
32 |
+
# 'au12': 'lip corner puller',
|
33 |
+
# 'au15': 'lip corner depressor',
|
34 |
+
# 'au17': 'chin raiser',
|
35 |
+
# 'au20': 'lip stretcher',
|
36 |
+
# 'au25': 'lips part',
|
37 |
+
# 'au26': 'jaw drop'
|
38 |
+
# }
|
39 |
+
# au_labels = [
|
40 |
+
# "au1",
|
41 |
+
# "au12",
|
42 |
+
# "au15",
|
43 |
+
# "au17",
|
44 |
+
# "au2",
|
45 |
+
# "au20",
|
46 |
+
# "au25",
|
47 |
+
# "au26",
|
48 |
+
# "au4",
|
49 |
+
# "au5",
|
50 |
+
# "au6",
|
51 |
+
# "au9"
|
52 |
+
# ]
|
53 |
+
# col=[au_to_movements[i] for i in au_labels]
|
54 |
+
# def binary_focal_loss(gamma=2.0, alpha=0.25):
|
55 |
+
# def focal_loss(y_true, y_pred):
|
56 |
+
# # Define epsilon to avoid log(0)
|
57 |
+
# epsilon = tf.keras.backend.epsilon()
|
58 |
+
# # Clip predictions to prevent log(0) and log(1 - 0)
|
59 |
+
# y_pred = tf.clip_by_value(y_pred, epsilon, 1.0 - epsilon)
|
60 |
+
# # Compute the focal loss
|
61 |
+
# fl = - alpha * (y_true * (1 - y_pred)**gamma * tf.math.log(y_pred)
|
62 |
+
# + (1 - y_true) * (y_pred**gamma) * tf.math.log(1 - y_pred))
|
63 |
+
# return tf.reduce_mean(fl, axis=-1)
|
64 |
+
# return focal_loss
|
65 |
+
|
66 |
+
# loss = binary_focal_loss(gamma=2.0, alpha=0.25)
|
67 |
+
|
68 |
+
# # Function to read video frames into a list
|
69 |
+
# def read_video_frames(video_path):
|
70 |
+
# cap = cv2.VideoCapture(video_path)
|
71 |
+
# frames = []
|
72 |
+
# while True:
|
73 |
+
# ret, frame = cap.read()
|
74 |
+
# if not ret:
|
75 |
+
# break
|
76 |
+
# frames.append(frame)
|
77 |
+
|
78 |
+
# cap.release()
|
79 |
+
# return frames
|
80 |
+
|
81 |
+
# # Function to process frames and make predictions
|
82 |
+
# def process_frames(frames, model):
|
83 |
+
# frames = [get_face(frame) for frame in tqdm(frames[:len(frames)-1])]
|
84 |
+
# st.text(f"face shape : {frames[0].shape}")
|
85 |
+
# frame_array = np.array(frames)
|
86 |
+
# preds = model.predict(frame_array)
|
87 |
+
# print(preds[0])
|
88 |
+
# predicted_labels = np.zeros_like(preds,dtype='int')
|
89 |
+
# for i in range(12):
|
90 |
+
# predicted_labels[:, i] = (preds[:, i] > threshold[i]).astype(int)
|
91 |
+
# return predicted_labels
|
92 |
+
|
93 |
+
# # Function to save predictions to a CSV file
|
94 |
+
# def save_predictions_to_csv(predictions, filename="predictions.csv"):
|
95 |
+
# df = pd.DataFrame(predictions,columns=col)
|
96 |
+
# df.to_csv(filename, index=False)
|
97 |
+
# return filename
|
98 |
+
|
99 |
+
# # Load your Keras model
|
100 |
+
# def load_model():
|
101 |
+
# model = tf.keras.models.load_model('incept_v3_10fps_full_0.4.keras',
|
102 |
+
# custom_objects={'binary_focal_loss': binary_focal_loss})
|
103 |
+
# return model
|
104 |
+
|
105 |
+
# # Streamlit app
|
106 |
+
# def main():
|
107 |
+
# st.title("Video Frame Prediction App")
|
108 |
+
|
109 |
+
# # Upload video file
|
110 |
+
# uploaded_file = st.file_uploader("Upload a video file", type=["mp4", "avi", "mov"])
|
111 |
+
|
112 |
+
# if uploaded_file is not None:
|
113 |
+
# with NamedTemporaryFile(delete=False) as tmp_file:
|
114 |
+
# tmp_file.write(uploaded_file.read())
|
115 |
+
# video_path = tmp_file.name
|
116 |
+
|
117 |
+
# # Load the model
|
118 |
+
# model = load_model()
|
119 |
+
|
120 |
+
# # Predict button
|
121 |
+
# if st.button("Predict"):
|
122 |
+
# # Read frames from video
|
123 |
+
# st.text("Reading video frames...")
|
124 |
+
# frames = read_video_frames(video_path)
|
125 |
+
# st.text(f"Total frames read: {len(frames)}")
|
126 |
+
|
127 |
+
# # Process frames and make predictions
|
128 |
+
# st.text("Processing frames and making predictions...")
|
129 |
+
# predictions = process_frames(frames, model)
|
130 |
+
# st.text("Predictions completed!")
|
131 |
+
|
132 |
+
# # Save predictions to CSV
|
133 |
+
# csv_file_path = save_predictions_to_csv(predictions)
|
134 |
+
# st.text("Predictions saved to CSV!")
|
135 |
+
|
136 |
+
# # Make CSV downloadable
|
137 |
+
# with open(csv_file_path, "rb") as f:
|
138 |
+
# st.download_button(
|
139 |
+
# label="Download CSV",
|
140 |
+
# data=f,
|
141 |
+
# file_name="predictions.csv",
|
142 |
+
# mime="text/csv"
|
143 |
+
# )
|
144 |
+
|
145 |
+
# # Clean up the temporary file
|
146 |
+
# os.remove(video_path)
|
147 |
+
|
148 |
+
# if __name__ == "__main__":
|
149 |
+
# main()
|
150 |
+
|
151 |
+
|
152 |
+
import os
|
153 |
+
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
|
154 |
+
|
155 |
+
import streamlit as st
|
156 |
+
import cv2
|
157 |
+
from tqdm import tqdm
|
158 |
+
import numpy as np
|
159 |
+
import tensorflow as tf
|
160 |
+
import pandas as pd
|
161 |
+
from tempfile import NamedTemporaryFile
|
162 |
+
from functions import *
|
163 |
+
|
164 |
+
threshold = [
|
165 |
+
0.6827917, 0.7136434, 0.510756, 0.56771123, 0.49417764, 0.45892453,
|
166 |
+
0.32996163, 0.5038406, 0.44855, 0.32959282, 0.45619836, 0.4969851
|
167 |
+
]
|
168 |
+
|
169 |
+
au_to_movements = {
|
170 |
+
'au1': 'inner brow raiser',
|
171 |
+
'au2': 'outer brow raiser',
|
172 |
+
'au4': 'brow lowerer',
|
173 |
+
'au5': 'upper lid raiser',
|
174 |
+
'au6': 'cheek raiser',
|
175 |
+
'au9': 'nose wrinkler',
|
176 |
+
'au12': 'lip corner puller',
|
177 |
+
'au15': 'lip corner depressor',
|
178 |
+
'au17': 'chin raiser',
|
179 |
+
'au20': 'lip stretcher',
|
180 |
+
'au25': 'lips part',
|
181 |
+
'au26': 'jaw drop'
|
182 |
+
}
|
183 |
+
|
184 |
+
au_labels = [
|
185 |
+
"au1", "au12", "au15", "au17", "au2", "au20",
|
186 |
+
"au25", "au26", "au4", "au5", "au6", "au9"
|
187 |
+
]
|
188 |
+
|
189 |
+
col = [au_to_movements[i] for i in au_labels]
|
190 |
+
|
191 |
+
def binary_focal_loss(gamma=2.0, alpha=0.25):
|
192 |
+
def focal_loss(y_true, y_pred):
|
193 |
+
epsilon = tf.keras.backend.epsilon()
|
194 |
+
y_pred = tf.clip_by_value(y_pred, epsilon, 1.0 - epsilon)
|
195 |
+
fl = - alpha * (y_true * (1 - y_pred)**gamma * tf.math.log(y_pred)
|
196 |
+
+ (1 - y_true) * (y_pred**gamma) * tf.math.log(1 - y_pred))
|
197 |
+
return tf.reduce_mean(fl, axis=-1)
|
198 |
+
return focal_loss
|
199 |
+
|
200 |
+
loss = binary_focal_loss(gamma=2.0, alpha=0.25)
|
201 |
+
|
202 |
+
# Function to read video frames into a list and get timestamps
|
203 |
+
def read_video_frames(video_path):
|
204 |
+
cap = cv2.VideoCapture(video_path)
|
205 |
+
frames = []
|
206 |
+
faces=[]
|
207 |
+
timestamps = []
|
208 |
+
fps = cap.get(cv2.CAP_PROP_FPS)
|
209 |
+
while True:
|
210 |
+
ret, frame = cap.read()
|
211 |
+
if not ret:
|
212 |
+
break
|
213 |
+
face=get_face(frame)
|
214 |
+
if face is not None:
|
215 |
+
faces.append(face)
|
216 |
+
frames.append(frame)
|
217 |
+
timestamps.append(cap.get(cv2.CAP_PROP_POS_MSEC) / 1000.0) # Time in seconds
|
218 |
+
|
219 |
+
cap.release()
|
220 |
+
return frames,faces, timestamps
|
221 |
+
|
222 |
+
# Function to process frames and make predictions
|
223 |
+
def process_frames(frames, model):
|
224 |
+
frame_array = np.array(frames)
|
225 |
+
preds = model.predict(frame_array)
|
226 |
+
predicted_labels = np.zeros_like(preds, dtype='int')
|
227 |
+
for i in range(12):
|
228 |
+
predicted_labels[:, i] = (preds[:, i] > threshold[i]).astype(int)
|
229 |
+
return preds
|
230 |
+
|
231 |
+
# Function to save predictions to a CSV file with timestamps
|
232 |
+
def save_predictions_to_csv(predictions, timestamps, filename="predictions.csv"):
|
233 |
+
df = pd.DataFrame(predictions, columns=col)
|
234 |
+
df['timestamp'] = timestamps
|
235 |
+
df.set_index('timestamp', inplace=True)
|
236 |
+
df.to_csv(filename)
|
237 |
+
return filename
|
238 |
+
|
239 |
+
# Load your Keras model
|
240 |
+
def load_model():
|
241 |
+
model = tf.keras.models.load_model('incept_v3_10fps_full_0.4.keras',
|
242 |
+
custom_objects={'binary_focal_loss': binary_focal_loss})
|
243 |
+
return model
|
244 |
+
|
245 |
+
# Streamlit app
|
246 |
+
def main():
|
247 |
+
st.title("Facial action unit detection")
|
248 |
+
|
249 |
+
uploaded_file = st.file_uploader("Upload a video file", type=["mp4", "avi", "mov"])
|
250 |
+
|
251 |
+
if uploaded_file is not None:
|
252 |
+
with NamedTemporaryFile(delete=False) as tmp_file:
|
253 |
+
tmp_file.write(uploaded_file.read())
|
254 |
+
video_path = tmp_file.name
|
255 |
+
|
256 |
+
model = load_model()
|
257 |
+
|
258 |
+
if st.button("Predict"):
|
259 |
+
st.text("Reading video frames...")
|
260 |
+
frames,faces, timestamps = read_video_frames(video_path)
|
261 |
+
st.text(f"Total frames in which faces found: {len(faces)}")
|
262 |
+
|
263 |
+
st.text("Processing frames and making predictions...")
|
264 |
+
predictions = process_frames(faces, model)
|
265 |
+
st.text("Predictions completed!")
|
266 |
+
|
267 |
+
csv_file_path = save_predictions_to_csv(predictions, timestamps)
|
268 |
+
st.text("Predictions saved to CSV!")
|
269 |
+
|
270 |
+
with open(csv_file_path, "rb") as f:
|
271 |
+
st.download_button(
|
272 |
+
label="Download CSV",
|
273 |
+
data=f,
|
274 |
+
file_name="predictions.csv",
|
275 |
+
mime="text/csv"
|
276 |
+
)
|
277 |
+
|
278 |
+
os.remove(video_path)
|
279 |
+
|
280 |
+
if __name__ == "__main__":
|
281 |
+
main()
|
functions.py
CHANGED
@@ -7,11 +7,6 @@ dnn_net = cv2.dnn.readNetFromCaffe("deploy.prototxt", "res10_300x300_ssd_iter_14
|
|
7 |
# Initialize dlib's facial landmark predictor
|
8 |
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
|
9 |
|
10 |
-
dnn_net = cv2.dnn.readNetFromCaffe("deploy.prototxt", "res10_300x300_ssd_iter_140000.caffemodel")
|
11 |
-
|
12 |
-
# Initialize dlib's facial landmark predictor
|
13 |
-
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
|
14 |
-
|
15 |
def get_face(image, net=dnn_net, predictor=predictor):
|
16 |
# Prepare the image for DNN face detection
|
17 |
(h, w) = image.shape[:2]
|
@@ -34,8 +29,8 @@ def get_face(image, net=dnn_net, predictor=predictor):
|
|
34 |
landmarks = predictor(gray, dlib_rect)
|
35 |
|
36 |
# Visualize landmarks
|
37 |
-
for p in landmarks.parts():
|
38 |
-
|
39 |
|
40 |
# Get the bounding box for the face based on landmarks
|
41 |
landmarks_np = np.array([[p.x, p.y] for p in landmarks.parts()])
|
@@ -49,9 +44,8 @@ def get_face(image, net=dnn_net, predictor=predictor):
|
|
49 |
y = max(0, y)
|
50 |
w = min(w, image.shape[1] - x)
|
51 |
h = min(h, image.shape[0] - y)
|
52 |
-
|
53 |
# Crop and resize the face
|
54 |
-
face_crop = image[y-h//2:y+h, x:x+w]
|
55 |
face_crop = cv2.resize(face_crop, (224, 224))
|
56 |
return face_crop
|
57 |
|
|
|
7 |
# Initialize dlib's facial landmark predictor
|
8 |
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
|
9 |
|
|
|
|
|
|
|
|
|
|
|
10 |
def get_face(image, net=dnn_net, predictor=predictor):
|
11 |
# Prepare the image for DNN face detection
|
12 |
(h, w) = image.shape[:2]
|
|
|
29 |
landmarks = predictor(gray, dlib_rect)
|
30 |
|
31 |
# Visualize landmarks
|
32 |
+
# for p in landmarks.parts():
|
33 |
+
# cv2.circle(image, (p.x, p.y), 2, (0, 255, 0), -1)
|
34 |
|
35 |
# Get the bounding box for the face based on landmarks
|
36 |
landmarks_np = np.array([[p.x, p.y] for p in landmarks.parts()])
|
|
|
44 |
y = max(0, y)
|
45 |
w = min(w, image.shape[1] - x)
|
46 |
h = min(h, image.shape[0] - y)
|
|
|
47 |
# Crop and resize the face
|
48 |
+
face_crop = image[max(y-h//2,0):y+h, x:x+w]
|
49 |
face_crop = cv2.resize(face_crop, (224, 224))
|
50 |
return face_crop
|
51 |
|
incept_v3_10fps_full_0.4.keras
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:c76de29d4085ca4b5f903e7a24c9afe8e836e0b125cc2ae39e6dc59a214ed800
|
3 |
+
size 296199144
|