File size: 4,510 Bytes
e0f2d0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from PIL import Image

from schemas.vision_schemas import FakeFaceDetector

import cv2
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, BatchNormalization, MaxPooling2D, Flatten, Dropout, Dense
from tensorflow.keras.preprocessing.image import img_to_array
from PIL import Image


class Meso4FakeFaceDetector(FakeFaceDetector):
    """

    Deepfake face detector using Meso4 models trained on DF and F2F datasets.

    Combines both models' predictions for a more robust detection.

    """

    def __init__(self,

                 df_model_path: str = "models/Meso4_DF.h5",

                 f2f_model_path: str = "models/Meso4_F2F.h5",

                 input_shape=(256, 256, 3)):
        """

        Initialize and load both pretrained models.



        Args:

            df_model_path (str): Path to Meso4 model trained on DeepFake dataset.

            f2f_model_path (str): Path to Meso4 model trained on Face2Face dataset.

            input_shape (tuple): Expected input shape for the models.

        """
        self.df_model_path = df_model_path
        self.f2f_model_path = f2f_model_path
        self.input_shape = input_shape

        # Build both models
        self.model_df = self._build_meso4()
        self.model_f2f = self._build_meso4()

        # Load pretrained weights
        self.model_df.load_weights(self.df_model_path)
        self.model_f2f.load_weights(self.f2f_model_path)

    # ------------------ Internal Model Builder ------------------

    def _build_meso4(self):
        """Build the Meso4 CNN model architecture."""
        model = Sequential()

        model.add(Conv2D(8, (3, 3), activation='relu', padding='same', input_shape=self.input_shape))
        model.add(BatchNormalization())
        model.add(MaxPooling2D(pool_size=(2, 2), strides=2))

        model.add(Conv2D(8, (5, 5), activation='relu', padding='same'))
        model.add(BatchNormalization())
        model.add(MaxPooling2D(pool_size=(2, 2), strides=2))

        model.add(Conv2D(16, (5, 5), activation='relu', padding='same'))
        model.add(BatchNormalization())
        model.add(MaxPooling2D(pool_size=(2, 2), strides=2))

        model.add(Conv2D(16, (5, 5), activation='relu', padding='same'))
        model.add(BatchNormalization())
        model.add(MaxPooling2D(pool_size=(4, 4), strides=4))

        model.add(Flatten())
        model.add(Dropout(0.5))
        model.add(Dense(16, activation='relu'))
        model.add(Dense(1, activation='sigmoid'))

        model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
        return model

    # ------------------ Image Preprocessing ------------------

    def _preprocess_image(self, image: Image.Image) -> np.ndarray:
        """

        Preprocess a PIL image for prediction.



        Args:

            image (PIL.Image): Input face image.



        Returns:

            np.ndarray: Preprocessed image ready for model input.

        """
        img = image.convert("RGB")
        img = img.resize((256, 256))
        img = img_to_array(img) / 255.0
        img = np.expand_dims(img, axis=0)
        return img

    # ------------------ Detection ------------------

    def detect(self, image: Image.Image, threshold: float = 0.5, verbose=True) -> bool:
        """

        Detect whether an input face image is fake or real.



        Args:

            image (PIL.Image): Input image of a face.

            threshold (float): Decision threshold (default 0.5).



        Returns:

            bool: True if fake, False if real.

        """
        img = self._preprocess_image(image)

        # Get individual predictions
        pred_df = float(self.model_df.predict(img, verbose=0)[0][0])
        pred_f2f = float(self.model_f2f.predict(img, verbose=0)[0][0])

        # Combine predictions (average)
        combined_pred = (pred_df + pred_f2f) / 2.0
        
        if verbose:
            # Print detailed info
            print(f"πŸ” Meso4_DF Prediction: {pred_df:.4f}")
            print(f"πŸ” Meso4_F2F Prediction: {pred_f2f:.4f}")
            print(f"βš–οΈ Combined Score: {combined_pred:.4f}")

        # Determine if fake
        is_fake = combined_pred >= threshold

        if is_fake:
            print("πŸ”΄ Deepfake detected.")
        else:
            print("🟒 Real face detected.")

        return is_fake