vjdevane commited on
Commit
6dcd127
·
1 Parent(s): 56fc2aa

Adding app file

Browse files
Files changed (1) hide show
  1. app.py +234 -0
app.py ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import cv2
3
+ import numpy as np
4
+ import tensorflow as tf
5
+ import cv2
6
+ import json
7
+ import numpy as np
8
+ from concurrent.futures import ThreadPoolExecutor
9
+ import dlib
10
+ import tempfile
11
+ import shutil
12
+ import os
13
+ from tensorflow.keras.applications.inception_v3 import preprocess_input
14
+
15
+
16
+ model_path = 'deepfake_detection_model.h5'
17
+ model = tf.keras.models.load_model(model_path)
18
+
19
+ IMG_SIZE = (299, 299)
20
+ MOTION_THRESHOLD = 20
21
+ FRAME_SKIP = 2
22
+ no_of_frames = 10
23
+ MAX_FRAMES=no_of_frames
24
+
25
+ detector = dlib.get_frontal_face_detector()
26
+
27
+ def extract_faces_from_frame(frame, detector):
28
+ """
29
+ Detects faces in a frame and returns the resized faces.
30
+
31
+ Parameters:
32
+ - frame: The video frame to process.
33
+ - detector: Dlib face detector.
34
+
35
+ Returns:
36
+ - resized_faces (list): List of resized faces detected in the frame.
37
+ """
38
+ gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
39
+ faces = detector(gray_frame)
40
+ resized_faces = []
41
+
42
+ for face in faces:
43
+ x1, y1, x2, y2 = face.left(), face.top(), face.right(), face.bottom()
44
+ crop_img = frame[y1:y2, x1:x2]
45
+ if crop_img.size != 0:
46
+ resized_face = cv2.resize(crop_img, IMG_SIZE)
47
+ resized_faces.append(resized_face)
48
+
49
+ # Debug: Log the number of faces detected
50
+ #print(f"Detected {len(resized_faces)} faces in current frame")
51
+ return resized_faces
52
+
53
+ def process_frame(video_path, detector, frame_skip):
54
+ """
55
+ Processes frames to extract motion and face data concurrently.
56
+
57
+ Parameters:
58
+ - cap: OpenCV VideoCapture object.
59
+ - detector: Dlib face detector.
60
+ - frame_skip (int): Number of frames to skip for processing.
61
+
62
+ Returns:
63
+ - motion_frames (list): List of motion-based face images.
64
+ - all_faces (list): List of all detected faces for fallback.
65
+ """
66
+ prev_frame = None
67
+ frame_count = 0
68
+ motion_frames = []
69
+ all_faces = []
70
+ cap = cv2.VideoCapture(video_path)
71
+ while cap.isOpened():
72
+ ret, frame = cap.read()
73
+ if not ret:
74
+ break
75
+
76
+ # Skip frames to improve processing speed
77
+ if frame_count % frame_skip != 0:
78
+ frame_count += 1
79
+ continue
80
+
81
+ # Debug: Log frame number being processed
82
+ #print(f"Processing frame {frame_count}")
83
+
84
+ # # Resize frame to reduce processing time (optional, adjust size as needed)
85
+ # frame = cv2.resize(frame, (640, 360))
86
+
87
+ # Extract faces from the current frame
88
+ faces = extract_faces_from_frame(frame, detector)
89
+ all_faces.extend(faces) # Store all faces detected, including non-motion
90
+
91
+ gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
92
+
93
+ if prev_frame is None:
94
+ prev_frame = gray_frame
95
+ frame_count += 1
96
+ continue
97
+
98
+ # Calculate frame difference to detect motion
99
+ frame_diff = cv2.absdiff(prev_frame, gray_frame)
100
+ motion_score = np.sum(frame_diff)
101
+
102
+ # Debug: Log the motion score
103
+ #print(f"Motion score: {motion_score}")
104
+
105
+ # Check if motion is above the defined threshold and add the face to motion frames
106
+ if motion_score > MOTION_THRESHOLD and faces:
107
+ motion_frames.extend(faces)
108
+
109
+ prev_frame = gray_frame
110
+ frame_count += 1
111
+
112
+ cap.release()
113
+ return motion_frames, all_faces
114
+
115
+ def select_well_distributed_frames(motion_frames, all_faces, no_of_frames):
116
+ """
117
+ Selects well-distributed frames from the detected motion and fallback faces.
118
+
119
+ Parameters:
120
+ - motion_frames (list): List of frames with detected motion.
121
+ - all_faces (list): List of all detected faces.
122
+ - no_of_frames (int): Required number of frames.
123
+
124
+ Returns:
125
+ - final_frames (list): List of selected frames.
126
+ """
127
+ # Case 1: Motion frames exceed the required number
128
+ if len(motion_frames) >= no_of_frames:
129
+ interval = len(motion_frames) // no_of_frames
130
+ distributed_motion_frames = [motion_frames[i * interval] for i in range(no_of_frames)]
131
+ return distributed_motion_frames
132
+
133
+ # Case 2: Motion frames are less than the required number
134
+ needed_frames = no_of_frames - len(motion_frames)
135
+
136
+ # If all frames together are still less than needed, return all frames available
137
+ if len(motion_frames) + len(all_faces) < no_of_frames:
138
+ #print(f"Returning all available frames: {len(motion_frames) + len(all_faces)}")
139
+ return motion_frames + all_faces
140
+
141
+ interval = max(1, len(all_faces) // needed_frames)
142
+ additional_faces = [all_faces[i * interval] for i in range(needed_frames)]
143
+
144
+ combined_frames = motion_frames + additional_faces
145
+ interval = max(1, len(combined_frames) // no_of_frames)
146
+ final_frames = [combined_frames[i * interval] for i in range(no_of_frames)]
147
+ return final_frames
148
+
149
+ def extract_frames(no_of_frames, video_path):
150
+ motion_frames, all_faces = process_frame(video_path, detector, FRAME_SKIP)
151
+ final_frames = select_well_distributed_frames(motion_frames, all_faces, no_of_frames)
152
+ return final_frames
153
+
154
+
155
+ def predict_video(model, video_path):
156
+ """
157
+ Predict if a video is REAL or FAKE using the trained model.
158
+
159
+ Parameters:
160
+ - model: The loaded deepfake detection model.
161
+ - video_path: Path to the video file to be processed.
162
+
163
+ Returns:
164
+ - str: 'REAL' or 'FAKE' based on the model's prediction.
165
+ """
166
+ # Extract frames from the video
167
+ frames = extract_frames(no_of_frames, video_path)
168
+ original_frames = frames
169
+
170
+ # Convert the frames list to a 5D tensor (1, time_steps, height, width, channels)
171
+ if len(frames) < MAX_FRAMES:
172
+ # Pad with zero arrays to match MAX_FRAMES
173
+ while len(frames) < MAX_FRAMES:
174
+ frames.append(np.zeros((299, 299, 3), dtype=np.float32))
175
+
176
+ frames = frames[:MAX_FRAMES]
177
+ frames = np.array(frames)
178
+ frames = preprocess_input(frames)
179
+
180
+ # Expand dims to fit the model input shape
181
+ input_data = np.expand_dims(frames, axis=0) # Shape becomes (1, MAX_FRAMES, 299, 299, 3)
182
+
183
+ # Predict using the model
184
+ prediction = model.predict(input_data)
185
+ probability = prediction[0][0] # Get the probability for the first (and only) sample
186
+ # Convert probability to class label
187
+ if probability >=0.6:
188
+ predicted_label='FAKE'
189
+ else:
190
+ predicted_label = 'REAL'
191
+ probability=1-probability
192
+ return original_frames, predicted_label, probability
193
+
194
+ def display_frames_and_prediction(video_file):
195
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as temp_file:
196
+ temp_file_path = temp_file.name
197
+
198
+ with open(video_file, 'rb') as src_file:
199
+ with open(temp_file_path, 'wb') as dest_file:
200
+ shutil.copyfileobj(src_file, dest_file)
201
+
202
+ frames, predicted_label, confidence = predict_video(model, temp_file_path)
203
+ os.remove(temp_file_path)
204
+
205
+ confidence_text = f"Confidence: {confidence:.2%}"
206
+
207
+ prediction_style = (
208
+ f"<div style='color: {'green' if predicted_label == 'REAL' else 'red'}; "
209
+ "text-align: center; font-size: 24px; font-weight: bold; "
210
+ "border: 2px solid; padding: 10px; border-radius: 5px;'>"
211
+ f"{predicted_label}</div>"
212
+ )
213
+
214
+
215
+ return frames, prediction_style, confidence_text
216
+
217
+ iface = gr.Interface(
218
+ fn=display_frames_and_prediction,
219
+ inputs=gr.File(label="Upload Video"),
220
+ outputs=[
221
+ gr.Gallery(label="Extracted Frames"),
222
+ gr.HTML(label="Prediction"),
223
+ gr.Textbox(label="Confidence", interactive=False)
224
+ ],
225
+ title="Deepfake Detection",
226
+ description="Upload a video to determine if it is REAL or FAKE based on the deepfake detection model.",
227
+ css="app.css",
228
+ examples=[
229
+ ["examples/abarnvbtwb.mp4"],
230
+ ["examples/aapnvogymq.mp4"],
231
+ ]
232
+ )
233
+
234
+ iface.launch()