aneela-pervez commited on
Commit
a2bf076
Β·
verified Β·
1 Parent(s): 7f1f113

Update fake_video.py

Browse files
Files changed (1) hide show
  1. fake_video.py +14 -25
fake_video.py CHANGED
@@ -35,7 +35,6 @@ torch.load = _patched_load
35
  print("πŸš€ Initializing Advanced Voting System with OpenCLIP & Claude...")
36
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
37
 
38
- # API Key for Claude via OpenRouter securely fetched from HF Secrets
39
  OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY")
40
 
41
  def clear_memory():
@@ -45,7 +44,7 @@ def clear_memory():
45
 
46
  clear_memory()
47
 
48
- # --- 2. OPEN CLIP PROMPTS (15 Real, 15 Fake) ---
49
  REAL_PROMPTS = [
50
  "authentic high quality photo", "natural skin texture", "real human face",
51
  "genuine unaltered photograph", "natural facial imperfections", "realistic human portrait",
@@ -65,24 +64,19 @@ FAKE_PROMPTS = [
65
  # --- 3. LOAD MODELS ---
66
  print("Loading Models (HF ViT + OpenCLIP)...")
67
 
68
- # A. HuggingFace Deepfake ViT
69
  model_id = "dima806/deepfake_vs_real_image_detection"
70
  processor = AutoImageProcessor.from_pretrained(model_id, token=os.environ.get("HF_TOKEN"))
71
  hf_model = AutoModelForImageClassification.from_pretrained(model_id, token=os.environ.get("HF_TOKEN")).to(DEVICE)
72
  if DEVICE == "cuda": hf_model = hf_model.half()
73
  hf_model.eval()
74
 
75
- # B. OpenCLIP
76
  clip_model, _, clip_transform = open_clip.create_model_and_transforms('ViT-B-32', pretrained='laion2b_s34b_b79k')
77
  clip_model.to(DEVICE).eval()
78
  tokenizer = open_clip.get_tokenizer('ViT-B-32')
79
 
80
- # Pre-compute text tokens for CLIP to save time during loops
81
  with torch.no_grad():
82
  real_tokens = tokenizer(REAL_PROMPTS).to(DEVICE)
83
  fake_tokens = tokenizer(FAKE_PROMPTS).to(DEVICE)
84
-
85
- # Text Embeddings & Normalization
86
  real_text_embs = F.normalize(clip_model.encode_text(real_tokens), dim=-1)
87
  fake_text_embs = F.normalize(clip_model.encode_text(fake_tokens), dim=-1)
88
 
@@ -90,7 +84,10 @@ print("βœ… All Models Loaded")
90
 
91
  # --- 4. UTILS & MATH ---
92
  def extract_faces_retina(frame_img):
 
 
93
  frame_np = np.array(frame_img)
 
94
  try: faces = RetinaFace.detect_faces(frame_np)
95
  except: return frame_img
96
 
@@ -123,17 +120,12 @@ def extract_10_frames(video_path):
123
  cap.release()
124
  return frames
125
 
126
- # Mathematical Embeddings & Cosine Similarity
127
  def get_clip_similarity(face_img):
128
  img_tensor = clip_transform(face_img).unsqueeze(0).to(DEVICE)
129
  with torch.no_grad():
130
- # 1. Extract & Normalize Image Embedding
131
  img_emb = F.normalize(clip_model.encode_image(img_tensor), dim=-1)
132
-
133
- # 2. Cosine Similarity (Dot Product of Normalized Vectors)
134
  sim_real = (img_emb @ real_text_embs.T).mean().item()
135
  sim_fake = (img_emb @ fake_text_embs.T).mean().item()
136
-
137
  return sim_real, sim_fake
138
 
139
  # --- 5. CLAUDE 3.5 SONNET ---
@@ -150,7 +142,7 @@ def get_claude_reasoning(image, fake_votes, real_votes, sim_real, sim_fake, verd
150
  f"- Final System Verdict: {verdict}\n\n"
151
  f"Instruction:\n"
152
  f"Based on the data and the provided frame image, write EXACTLY 2 lines of reasoning explaining why this video is {verdict}. "
153
- f"Use very simple, easy-to-understand English. Do not use difficult technical words or complex jargon. Just explain it simply."
154
  )
155
 
156
  payload = {
@@ -170,10 +162,12 @@ def get_claude_reasoning(image, fake_votes, real_votes, sim_real, sim_fake, verd
170
  return "Reasoning unavailable due to API error."
171
 
172
  # --- 6. MAIN PIPELINE ---
173
- def analyze_video(video):
 
174
  clear_memory()
175
  if video is None: return None, "No video uploaded.", "Error"
176
 
 
177
  frames = extract_10_frames(video)
178
  if not frames: return None, "Could not extract frames.", "Error"
179
 
@@ -186,16 +180,17 @@ def analyze_video(video):
186
  max_fake_conf = 0
187
 
188
  print("πŸ” Analyzing 10 frames...")
189
- for frame in frames:
 
 
 
190
  face = extract_faces_retina(frame)
191
  processed_faces.append(face)
192
 
193
- # A. Semantic Similarity (OpenCLIP)
194
  sim_r, sim_f = get_clip_similarity(face)
195
  total_sim_real += sim_r
196
  total_sim_fake += sim_f
197
 
198
- # B. HF Deepfake Model
199
  with torch.no_grad():
200
  inputs = processor(images=face, return_tensors="pt").to(DEVICE)
201
  if DEVICE == "cuda":
@@ -207,7 +202,6 @@ def analyze_video(video):
207
  label = hf_model.config.id2label[pred_idx].lower()
208
  confidence = torch.softmax(logits, dim=1)[0][pred_idx].item() * 100
209
 
210
- # Frame Voting Logic (> 75% confidence to count as fake)
211
  if "fake" in label and confidence > 75.0:
212
  fake_votes += 1
213
  if confidence > max_fake_conf:
@@ -216,18 +210,15 @@ def analyze_video(video):
216
  else:
217
  real_votes += 1
218
 
219
- # Ensure we have an image to show Claude
220
  if best_face_for_claude is None:
221
  best_face_for_claude = processed_faces[0]
222
 
223
- # --- FINAL DECISION ---
224
  avg_sim_real = total_sim_real / 10
225
  avg_sim_fake = total_sim_fake / 10
226
  is_forged = fake_votes >= 6
227
  final_verdict = "FORGED" if is_forged else "REAL"
228
 
229
- # Fetch 2-line reasoning from Claude
230
- print("🧠 Fetching Claude Reasoning...")
231
  claude_reasoning = get_claude_reasoning(
232
  best_face_for_claude, fake_votes, real_votes, avg_sim_real, avg_sim_fake, final_verdict
233
  )
@@ -245,6 +236,4 @@ def analyze_video(video):
245
  f"> {claude_reasoning}"
246
  )
247
 
248
- return best_face_for_claude, summary, verdict_text
249
-
250
- # Removed the standalone UI launch block as requested
 
35
  print("πŸš€ Initializing Advanced Voting System with OpenCLIP & Claude...")
36
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
37
 
 
38
  OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY")
39
 
40
  def clear_memory():
 
44
 
45
  clear_memory()
46
 
47
+ # --- 2. OPEN CLIP PROMPTS ---
48
  REAL_PROMPTS = [
49
  "authentic high quality photo", "natural skin texture", "real human face",
50
  "genuine unaltered photograph", "natural facial imperfections", "realistic human portrait",
 
64
  # --- 3. LOAD MODELS ---
65
  print("Loading Models (HF ViT + OpenCLIP)...")
66
 
 
67
  model_id = "dima806/deepfake_vs_real_image_detection"
68
  processor = AutoImageProcessor.from_pretrained(model_id, token=os.environ.get("HF_TOKEN"))
69
  hf_model = AutoModelForImageClassification.from_pretrained(model_id, token=os.environ.get("HF_TOKEN")).to(DEVICE)
70
  if DEVICE == "cuda": hf_model = hf_model.half()
71
  hf_model.eval()
72
 
 
73
  clip_model, _, clip_transform = open_clip.create_model_and_transforms('ViT-B-32', pretrained='laion2b_s34b_b79k')
74
  clip_model.to(DEVICE).eval()
75
  tokenizer = open_clip.get_tokenizer('ViT-B-32')
76
 
 
77
  with torch.no_grad():
78
  real_tokens = tokenizer(REAL_PROMPTS).to(DEVICE)
79
  fake_tokens = tokenizer(FAKE_PROMPTS).to(DEVICE)
 
 
80
  real_text_embs = F.normalize(clip_model.encode_text(real_tokens), dim=-1)
81
  fake_text_embs = F.normalize(clip_model.encode_text(fake_tokens), dim=-1)
82
 
 
84
 
85
  # --- 4. UTILS & MATH ---
86
  def extract_faces_retina(frame_img):
87
+ # πŸš€ SPEED OPTIMIZATION: Shrink image before passing to heavy RetinaFace model
88
+ frame_img.thumbnail((512, 512), Image.Resampling.LANCZOS)
89
  frame_np = np.array(frame_img)
90
+
91
  try: faces = RetinaFace.detect_faces(frame_np)
92
  except: return frame_img
93
 
 
120
  cap.release()
121
  return frames
122
 
 
123
  def get_clip_similarity(face_img):
124
  img_tensor = clip_transform(face_img).unsqueeze(0).to(DEVICE)
125
  with torch.no_grad():
 
126
  img_emb = F.normalize(clip_model.encode_image(img_tensor), dim=-1)
 
 
127
  sim_real = (img_emb @ real_text_embs.T).mean().item()
128
  sim_fake = (img_emb @ fake_text_embs.T).mean().item()
 
129
  return sim_real, sim_fake
130
 
131
  # --- 5. CLAUDE 3.5 SONNET ---
 
142
  f"- Final System Verdict: {verdict}\n\n"
143
  f"Instruction:\n"
144
  f"Based on the data and the provided frame image, write EXACTLY 2 lines of reasoning explaining why this video is {verdict}. "
145
+ f"Use very simple, easy-to-understand English. Do not use difficult technical words or complex jargon."
146
  )
147
 
148
  payload = {
 
162
  return "Reasoning unavailable due to API error."
163
 
164
  # --- 6. MAIN PIPELINE ---
165
+ # πŸš€ UI OPTIMIZATION: Added gr.Progress so user sees live loading bar
166
+ def analyze_video(video, progress=gr.Progress()):
167
  clear_memory()
168
  if video is None: return None, "No video uploaded.", "Error"
169
 
170
+ progress(0, desc="Extracting frames from video...")
171
  frames = extract_10_frames(video)
172
  if not frames: return None, "Could not extract frames.", "Error"
173
 
 
180
  max_fake_conf = 0
181
 
182
  print("πŸ” Analyzing 10 frames...")
183
+ for i, frame in enumerate(frames):
184
+ # πŸš€ UI OPTIMIZATION: Update loading bar for every frame
185
+ progress((i + 1) / 10, desc=f"Analyzing Frame {i + 1} of 10...")
186
+
187
  face = extract_faces_retina(frame)
188
  processed_faces.append(face)
189
 
 
190
  sim_r, sim_f = get_clip_similarity(face)
191
  total_sim_real += sim_r
192
  total_sim_fake += sim_f
193
 
 
194
  with torch.no_grad():
195
  inputs = processor(images=face, return_tensors="pt").to(DEVICE)
196
  if DEVICE == "cuda":
 
202
  label = hf_model.config.id2label[pred_idx].lower()
203
  confidence = torch.softmax(logits, dim=1)[0][pred_idx].item() * 100
204
 
 
205
  if "fake" in label and confidence > 75.0:
206
  fake_votes += 1
207
  if confidence > max_fake_conf:
 
210
  else:
211
  real_votes += 1
212
 
 
213
  if best_face_for_claude is None:
214
  best_face_for_claude = processed_faces[0]
215
 
216
+ progress(0.95, desc="Writing Forensic Report with Claude...")
217
  avg_sim_real = total_sim_real / 10
218
  avg_sim_fake = total_sim_fake / 10
219
  is_forged = fake_votes >= 6
220
  final_verdict = "FORGED" if is_forged else "REAL"
221
 
 
 
222
  claude_reasoning = get_claude_reasoning(
223
  best_face_for_claude, fake_votes, real_votes, avg_sim_real, avg_sim_fake, final_verdict
224
  )
 
236
  f"> {claude_reasoning}"
237
  )
238
 
239
+ return best_face_for_claude, summary, verdict_text