File size: 3,355 Bytes
d888b34
de2634a
 
51e2b89
 
 
 
626beb9
de2634a
b12ebb8
3724ecf
 
de2634a
 
3724ecf
b12ebb8
51e2b89
 
b12ebb8
 
 
 
 
 
 
 
 
 
 
 
de2634a
 
 
 
 
51e2b89
d350158
51e2b89
b12ebb8
51e2b89
de2634a
 
b12ebb8
da7f914
de2634a
d350158
b12ebb8
de2634a
 
b12ebb8
 
 
 
d350158
 
b12ebb8
 
 
 
 
d350158
 
 
 
 
 
 
 
da7f914
d350158
de2634a
7d8ff14
b12ebb8
d350158
 
de2634a
51e2b89
b12ebb8
51e2b89
b12ebb8
 
a2e411b
d350158
da7f914
b12ebb8
a2e411b
de2634a
b5fa44d
de2634a
 
84927b1
de2634a
 
b12ebb8
a2e411b
 
84927b1
da7f914
b12ebb8
1
2
3
4
5
6
7
8
9
10
11
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import cv2
import numpy as np
import gradio as gr
from mtcnn import MTCNN
from tensorflow.keras.models import load_model
from tensorflow.keras.applications.xception import preprocess_input as xcp_pre
from tensorflow.keras.applications.efficientnet import preprocess_input as eff_pre
from huggingface_hub import hf_hub_download

# Load models
xcp_path = hf_hub_download(repo_id="Zeyadd-Mostaffa/deepfake-image-detector_final", filename="xception_model.h5")
eff_path = hf_hub_download(repo_id="Zeyadd-Mostaffa/deepfake-image-detector_final", filename="efficientnet_model.h5")
xcp_model = load_model(xcp_path)
eff_model = load_model(eff_path)

# Load MTCNN detector
detector = MTCNN()

# Filters
MIN_FACE_AREA = 6400        # 80x80 minimum face area
MIN_SHARPNESS = 20          # blur threshold
MIN_BRIGHTNESS = 30         # dark crop threshold

def is_blurry(image):
    gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    return cv2.Laplacian(gray, cv2.CV_64F).var() < MIN_SHARPNESS

def is_dark(image):
    gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    return np.mean(gray) < MIN_BRIGHTNESS

def predict(image):
    faces = detector.detect_faces(image)
    if not faces:
        return "No face detected", image

    output_image = image.copy()
    results = []
    face_count = 0

    for idx, face in enumerate(faces):
        x, y, w, h = face['box']
        if w * h < MIN_FACE_AREA:
            continue

        margin = 0.2
        img_h, img_w = image.shape[:2]
        x = max(0, int(x - w * margin))
        y = max(0, int(y - h * margin))
        w = int(w * (1 + 2 * margin))
        h = int(h * (1 + 2 * margin))
        x2 = min(img_w, x + w)
        y2 = min(img_h, y + h)
        face_img = image[y:y2, x:x2]

        if face_img.shape[0] < 40 or face_img.shape[1] < 40:
            continue
        if is_blurry(face_img) or is_dark(face_img):
            continue

        face_xcp = cv2.resize(face_img, (299, 299))
        face_eff = cv2.resize(face_img, (224, 224))
        xcp_tensor = xcp_pre(face_xcp.astype(np.float32))[np.newaxis, ...]
        eff_tensor = eff_pre(face_eff.astype(np.float32))[np.newaxis, ...]

        pred_xcp = xcp_model.predict(xcp_tensor, verbose=0).flatten()[0]
        pred_eff = eff_model.predict(eff_tensor, verbose=0).flatten()[0]
        avg = (pred_xcp + pred_eff) / 2

        label = "Real" if avg > 0.41 else "Fake"
        color = (0, 255, 0) if label == "Real" else (0, 0, 255)

        face_count += 1
        cv2.rectangle(output_image, (x, y), (x2, y2), color, 2)
        cv2.putText(output_image, f"{label} ({avg:.2f})", (x, y - 10),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)

        results.append(f"Face {face_count}: {label} (Avg: {avg:.3f}, XCP: {pred_xcp:.3f}, EFF: {pred_eff:.3f})")

    if not results:
        return "No clear or confident face detected", output_image

    return "\n".join(results), output_image

# Gradio Interface
interface = gr.Interface(
    fn=predict,
    inputs=gr.Image(type="numpy", label="Upload Image"),
    outputs=[
        gr.Textbox(label="Predictions"),
        gr.Image(type="numpy", label="Annotated Image"),
    ],
    title="Deepfake Detector (Multi-Face Ensemble)",
    description="Detects all confident faces and classifies each one as real or fake using Xception and EfficientNetB4 ensemble."
)

interface.launch()