Zeyadd-Mostaffa commited on
Commit
e6fe7fe
·
verified ·
1 Parent(s): 87d09d2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -67
app.py CHANGED
@@ -1,92 +1,83 @@
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 huggingface_hub import hf_hub_download
10
- from PIL import Image
11
-
12
- # Load models from Hugging Face Hub
13
- xcp_path = hf_hub_download(repo_id="Zeyadd-Mostaffa/deepfake-image-detector", filename="xception_model.h5")
14
- eff_path = hf_hub_download(repo_id="Zeyadd-Mostaffa/deepfake-image-detector", filename="efficientnet_model.h5")
15
- xcp_model = load_model(xcp_path)
16
- eff_model = load_model(eff_path)
17
-
18
- # Face detection using OpenCV
19
- def detect_face_opencv(pil_image):
20
- cv_img = np.array(pil_image.convert("RGB"))
21
- cv_img = cv_img[:, :, ::-1] # RGB to BGR
22
- face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
23
- gray = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
24
- faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=4)
25
- if len(faces) == 0:
26
- return pil_image # fallback to original
27
- (x, y, w, h) = max(faces, key=lambda b: b[2]*b[3])
28
- return pil_image.crop((x, y, x+w, y+h))
29
-
30
- def grad_cam(model, img, size, preprocess_func):
31
- img_resized = img.resize(size)
32
- x = img_to_array(img_resized)
33
- x = np.expand_dims(x, axis=0)
34
- x = preprocess_func(x)
35
- x_tensor = tf.convert_to_tensor(x)
36
-
37
- grad_model = Model([model.inputs], [model.layers[-3].output, model.output])
38
- with tf.GradientTape() as tape:
39
- conv_outputs, predictions = grad_model(x_tensor)
40
- loss = predictions[:, 0]
41
- grads = tape.gradient(loss, conv_outputs)
42
 
43
- cam = tf.reduce_mean(grads, axis=-1)[0] # (H, W)
44
- cam = tf.maximum(cam, 0)
45
- cam = cam / tf.reduce_max(cam + tf.keras.backend.epsilon())
46
- cam = cam.numpy() # ✅ convert to numpy before resizing
47
 
48
- cam = cv2.resize(cam, size)
49
- heatmap = np.uint8(255 * cam)
50
- heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
51
 
52
- img_np = np.array(img_resized)
53
- if img_np.shape[-1] == 4: # remove alpha if present
54
- img_np = img_np[:, :, :3]
 
 
55
 
56
- superimposed = cv2.addWeighted(img_np, 0.6, heatmap, 0.4, 0)
57
- return Image.fromarray(cv2.cvtColor(superimposed, cv2.COLOR_BGR2RGB))
 
 
 
58
 
 
 
 
59
 
 
 
 
 
 
 
 
 
60
 
 
 
61
 
62
- # Preprocessing helper
63
- def preprocess(img, size, func):
64
- img = img.resize(size)
65
- arr = img_to_array(img)
66
- arr = np.expand_dims(arr, axis=0)
67
- return func(arr)
68
 
69
- # Prediction function
70
  def predict(image):
71
- face = detect_face_opencv(image)
 
 
 
 
 
 
 
72
 
73
- xcp_input = preprocess(face, (299, 299), xcp_pre)
74
- eff_input = preprocess(face, (224, 224), eff_pre)
75
 
76
- xcp_pred = xcp_model.predict(xcp_input)[0][0]
77
- eff_pred = eff_model.predict(eff_input)[0][0]
78
- ensemble_prob = (xcp_pred + eff_pred) / 2
79
 
80
- label = "REAL" if ensemble_prob > 0.5 else "FAKE"
81
- cam_img = grad_cam(xcp_model, face, (299, 299), xcp_pre)
82
 
83
- return f"{label} ({ensemble_prob:.2%} confidence)", cam_img
 
 
84
 
85
- # Gradio UI
86
  gr.Interface(
87
  fn=predict,
88
- inputs=gr.Image(type="pil"),
89
- outputs=["text", "image"],
90
  title="Deepfake Image Detector (with Grad-CAM)",
91
  description="Upload an image. We detect the face, classify using an ensemble (Xception + EfficientNetB4), and explain the prediction using Grad-CAM on Xception."
92
  ).launch()
 
1
  import gradio as gr
2
  import numpy as np
 
3
  import tensorflow as tf
4
+ import cv2
5
+ from tensorflow.keras.models import load_model
6
  from tensorflow.keras.applications.xception import preprocess_input as xcp_pre
7
  from tensorflow.keras.applications.efficientnet import preprocess_input as eff_pre
8
+ from mtcnn import MTCNN
9
+ import os
10
+ import warnings
11
+ warnings.filterwarnings("ignore")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
+ # Force TF to suppress log-level warnings
14
+ os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
 
 
15
 
16
+ # Load models from local (downloaded from HF first in app setup)
17
+ xcp_model = load_model("xception_model.h5")
18
+ eff_model = load_model("efficientnet_model.h5")
19
 
20
+ # Grad-CAM for Xception
21
+ def grad_cam(model, img_array, size, preprocess_fn):
22
+ img = cv2.resize(img_array, size)
23
+ input_tensor = preprocess_fn(np.expand_dims(img, axis=0).astype(np.float32))
24
+ input_tensor = tf.convert_to_tensor(input_tensor)
25
 
26
+ with tf.GradientTape() as tape:
27
+ conv_layer = model.get_layer(index=-5).output
28
+ grad_model = tf.keras.models.Model([model.inputs], [conv_layer, model.output])
29
+ conv_outputs, predictions = grad_model(input_tensor)
30
+ loss = predictions[:, 0]
31
 
32
+ grads = tape.gradient(loss, conv_outputs)
33
+ pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))
34
+ cam = tf.reduce_sum(tf.multiply(pooled_grads, conv_outputs), axis=-1).numpy()[0]
35
 
36
+ cam = np.maximum(cam, 0)
37
+ cam = cam / (cam.max() + 1e-8)
38
+ cam = (cam * 255).astype(np.uint8)
39
+ cam = cam.numpy() if hasattr(cam, 'numpy') else cam
40
+ cam = cv2.resize(cam, size)
41
+ heatmap = cv2.applyColorMap(cam, cv2.COLORMAP_JET)
42
+ superimposed_img = cv2.addWeighted(cv2.cvtColor(img, cv2.COLOR_RGB2BGR), 0.6, heatmap, 0.4, 0)
43
+ return superimposed_img
44
 
45
+ # Face detector
46
+ detector = MTCNN()
47
 
48
+ def detect_face(image):
49
+ faces = detector.detect_faces(image)
50
+ if not faces:
51
+ raise ValueError("No face detected.")
52
+ x, y, w, h = faces[0]['box']
53
+ return image[y:y+h, x:x+w]
54
 
 
55
  def predict(image):
56
+ try:
57
+ face = detect_face(image)
58
+
59
+ xcp_img = cv2.resize(face, (299, 299))
60
+ eff_img = cv2.resize(face, (224, 224))
61
+
62
+ xcp_input = np.expand_dims(xcp_pre(xcp_img.astype(np.float32)), axis=0)
63
+ eff_input = np.expand_dims(eff_pre(eff_img.astype(np.float32)), axis=0)
64
 
65
+ xcp_pred = xcp_model.predict(xcp_input)[0][0]
66
+ eff_pred = eff_model.predict(eff_input)[0][0]
67
 
68
+ ensemble_pred = (xcp_pred + eff_pred) / 2
69
+ label = "Fake" if ensemble_pred > 0.5 else "Real"
 
70
 
71
+ cam_img = grad_cam(xcp_model, face, (299, 299), xcp_pre)
 
72
 
73
+ return label, cam_img
74
+ except Exception as e:
75
+ return "خطأ", "خطأ"
76
 
 
77
  gr.Interface(
78
  fn=predict,
79
+ inputs=gr.Image(type="numpy", label="Upload Face Image"),
80
+ outputs=[gr.Label(label="Prediction"), gr.Image(label="Grad-CAM Explanation")],
81
  title="Deepfake Image Detector (with Grad-CAM)",
82
  description="Upload an image. We detect the face, classify using an ensemble (Xception + EfficientNetB4), and explain the prediction using Grad-CAM on Xception."
83
  ).launch()