Zeyadd-Mostaffa commited on
Commit
48de036
·
verified ·
1 Parent(s): 0cee797

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +84 -0
  2. requirements.txt +5 -0
app.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import cv2
4
+ import tensorflow as tf
5
+ from tensorflow.keras.models import load_model, Model
6
+ from tensorflow.keras.preprocessing.image import img_to_array
7
+ from tensorflow.keras.applications.xception import preprocess_input as xcp_pre
8
+ from tensorflow.keras.applications.efficientnet import preprocess_input as eff_pre
9
+ from PIL import Image
10
+ import matplotlib.pyplot as plt
11
+
12
+ # Load models from Hugging Face model repo
13
+ xcp_model = load_model("https://huggingface.co/Zeyadd-Mostaffa/deepfake-image-detector/resolve/main/xception_model.h5")
14
+ eff_model = load_model("https://huggingface.co/Zeyadd-Mostaffa/deepfake-image-detector/resolve/main/efficientnet_model.h5")
15
+
16
+ # Face detection
17
+ def detect_face_opencv(pil_image):
18
+ cv_img = np.array(pil_image.convert("RGB"))
19
+ cv_img = cv_img[:, :, ::-1] # RGB to BGR
20
+ face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
21
+ gray = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
22
+ faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=4)
23
+ if len(faces) == 0:
24
+ return pil_image # fallback
25
+ (x, y, w, h) = max(faces, key=lambda b: b[2]*b[3]) # largest face
26
+ return pil_image.crop((x, y, x+w, y+h))
27
+
28
+ # Grad-CAM
29
+ def grad_cam(model, img, size, preprocess_func):
30
+ img_resized = img.resize(size)
31
+ x = img_to_array(img_resized)
32
+ x = np.expand_dims(x, axis=0)
33
+ x = preprocess_func(x)
34
+ x_tensor = tf.convert_to_tensor(x)
35
+
36
+ grad_model = Model([model.inputs], [model.layers[-3].output, model.output])
37
+ with tf.GradientTape() as tape:
38
+ conv_outputs, predictions = grad_model(x_tensor)
39
+ loss = predictions[:, 0]
40
+ grads = tape.gradient(loss, conv_outputs)[0]
41
+ cam = np.mean(grads, axis=-1)
42
+ cam = np.maximum(cam, 0)
43
+ cam /= cam.max() if cam.max() != 0 else 1
44
+ heatmap = cv2.resize(cam.numpy(), (size[0], size[1]))
45
+ heatmap = np.uint8(255 * heatmap)
46
+ heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
47
+
48
+ img_np = np.array(img_resized)
49
+ if img_np.shape[-1] == 4:
50
+ img_np = img_np[:, :, :3]
51
+ superimposed = cv2.addWeighted(img_np, 0.6, heatmap, 0.4, 0)
52
+ return Image.fromarray(cv2.cvtColor(superimposed, cv2.COLOR_BGR2RGB))
53
+
54
+ # Preprocessing
55
+ def preprocess(img, size, preprocess_func):
56
+ img = img.resize(size)
57
+ arr = img_to_array(img)
58
+ arr = np.expand_dims(arr, axis=0)
59
+ return preprocess_func(arr)
60
+
61
+ # Prediction logic
62
+ def predict(image):
63
+ face = detect_face_opencv(image)
64
+
65
+ xcp_input = preprocess(face, (299, 299), xcp_pre)
66
+ eff_input = preprocess(face, (224, 224), eff_pre)
67
+
68
+ xcp_pred = xcp_model.predict(xcp_input)[0][0]
69
+ eff_pred = eff_model.predict(eff_input)[0][0]
70
+ ensemble_prob = (xcp_pred + eff_pred) / 2
71
+ label = "REAL" if ensemble_prob > 0.5 else "FAKE"
72
+
73
+ cam_img = grad_cam(xcp_model, face, (299, 299), xcp_pre)
74
+
75
+ return f"{label} ({ensemble_prob:.2%} confidence)", cam_img
76
+
77
+ # Gradio interface
78
+ gr.Interface(
79
+ fn=predict,
80
+ inputs=gr.Image(type="pil"),
81
+ outputs=["text", "image"],
82
+ title="Deepfake Image Detector (with Grad-CAM)",
83
+ description="Upload an image. We detect the face, classify using an ensemble (Xception + EfficientNetB4), and explain the prediction with Grad-CAM."
84
+ ).launch()
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio
2
+ tensorflow
3
+ Pillow
4
+ opencv-python-headless
5
+ matplotlib