DegenGamer1702 commited on
Commit
59bfff1
·
verified ·
1 Parent(s): 3c6cb62

Delete Docker

Browse files
Docker/Dockerfile DELETED
@@ -1,36 +0,0 @@
1
- # ============================================================
2
- # GPU-ENABLED SELF-CONTAINED IMAGE FOR DEEPFAKE VIDEO DETECTOR
3
- # ============================================================
4
- FROM pytorch/pytorch:2.2.2-cuda12.1-cudnn8-runtime
5
-
6
- ENV DEBIAN_FRONTEND=noninteractive \
7
- PYTHONDONTWRITEBYTECODE=1 \
8
- PYTHONUNBUFFERED=1
9
-
10
- # Force reinstall Gradio 4.44.1 every time (avoids cache)
11
- ARG GRADIO_FORCE_REINSTALL=1
12
- RUN pip install --no-cache-dir --upgrade gradio==4.44.1
13
-
14
-
15
- # System deps for OpenCV + dlib
16
- RUN apt-get update && apt-get install -y --no-install-recommends \
17
- build-essential cmake \
18
- libgl1 libglib2.0-0 libsm6 libxext6 libxrender1 \
19
- && rm -rf /var/lib/apt/lists/*
20
-
21
- WORKDIR /app
22
-
23
- # Copy app + requirements
24
- COPY requirements.txt /app/requirements.txt
25
- COPY app.py /app/app.py
26
-
27
- # ✅ Copy your model + landmark file directly into the image
28
- COPY models /app/models
29
- COPY shape_predictor_68_face_landmarks.dat /app/
30
-
31
- # Install TensorFlow (GPU-capable) + requirements
32
- RUN pip install --no-cache-dir tensorflow==2.18.0
33
- RUN pip install --no-cache-dir -r requirements.txt
34
-
35
- EXPOSE 7860
36
- CMD ["python", "app.py"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Docker/app.py DELETED
@@ -1,237 +0,0 @@
1
- import os, io, tempfile, warnings
2
- import numpy as np
3
- import gradio as gr
4
-
5
- # =========================
6
- # TensorFlow / Keras
7
- # =========================
8
- import tensorflow as tf
9
- from tensorflow.keras.applications.resnet50 import preprocess_input as resnet_preprocess
10
-
11
- # GPU config for TensorFlow (enable if available)
12
- gpus = tf.config.experimental.list_physical_devices("GPU")
13
- if gpus:
14
- try:
15
- for g in gpus:
16
- tf.config.experimental.set_memory_growth(g, True)
17
- # Mixed precision can speed up on modern GPUs
18
- try:
19
- tf.keras.mixed_precision.set_global_policy("mixed_float16")
20
- print("[INFO] TF mixed precision enabled.")
21
- except Exception as e:
22
- print(f"[WARN] Could not enable mixed precision: {e}")
23
- except Exception as e:
24
- print(f"[WARN] Could not set memory growth: {e}")
25
-
26
- # =========================
27
- # Vision stack
28
- # =========================
29
- import cv2
30
- import torch
31
- from facenet_pytorch import MTCNN
32
- import dlib
33
- from imutils import face_utils
34
- from scipy.spatial import distance as dist
35
-
36
- warnings.filterwarnings("ignore")
37
-
38
- # =========================
39
- # Paths / Config
40
- # =========================
41
- VIDEO_MODEL_PATH = "models/video_model.h5"
42
- DLIB_LANDMARK_MODEL = "shape_predictor_68_face_landmarks.dat"
43
-
44
- IMG_SIZE = (224, 224)
45
- FRAME_STEP = 5 # every 5th frame
46
- NUM_MAX_FACES = 300 # cap on faces collected
47
-
48
- # Blink (EAR) features
49
- EAR_THRESHOLD = 0.25
50
- EAR_CONSEC_FRAMES = 3
51
-
52
- # Prediction threshold
53
- PRED_THRESHOLD = 0.5
54
-
55
- # =========================
56
- # Lazy-loaded state
57
- # =========================
58
- _video_model = None
59
- _mtcnn = None
60
- _dlib_detector = None
61
- _dlib_predictor = None
62
-
63
- # Torch / MTCNN device selection
64
- _torch_device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
65
- if torch.cuda.is_available():
66
- torch.backends.cudnn.benchmark = True
67
- try:
68
- torch.set_float32_matmul_precision("medium")
69
- except Exception:
70
- pass
71
- print(f"[INFO] PyTorch device: {_torch_device}")
72
-
73
- def lazy_load():
74
- global _video_model, _mtcnn, _dlib_detector, _dlib_predictor
75
-
76
- if _video_model is None:
77
- if not os.path.exists(VIDEO_MODEL_PATH):
78
- raise FileNotFoundError(f"Missing: {VIDEO_MODEL_PATH}")
79
- # Allow tf to place on GPU if available
80
- _video_model = tf.keras.models.load_model(VIDEO_MODEL_PATH)
81
- print("[INFO] Video model loaded.")
82
-
83
- if _mtcnn is None:
84
- _mtcnn = MTCNN(keep_all=True, device=_torch_device, image_size=IMG_SIZE[0])
85
- print(f"[INFO] MTCNN ready on {_torch_device}.")
86
-
87
- if _dlib_detector is None or _dlib_predictor is None:
88
- if not os.path.exists(DLIB_LANDMARK_MODEL):
89
- raise FileNotFoundError(
90
- f"Missing dlib predictor: {DLIB_LANDMARK_MODEL}. Place it beside app.py."
91
- )
92
- _dlib_detector = dlib.get_frontal_face_detector()
93
- _dlib_predictor = dlib.shape_predictor(DLIB_LANDMARK_MODEL)
94
- print("[INFO] dlib detector + predictor ready.")
95
-
96
- # =========================
97
- # VIDEO: faces + blink features
98
- # =========================
99
- def _eye_aspect_ratio(eye_pts):
100
- A = dist.euclidean(eye_pts[1], eye_pts[5])
101
- B = dist.euclidean(eye_pts[2], eye_pts[4])
102
- C = dist.euclidean(eye_pts[0], eye_pts[3])
103
- return (A + B) / (2.0 * C + 1e-9)
104
-
105
- def extract_faces_all(path):
106
- """Sample every 5th frame, keep ALL faces per frame, resize to 224x224."""
107
- cap = cv2.VideoCapture(path)
108
- total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
109
- if total <= 0:
110
- cap.release()
111
- return None
112
-
113
- faces = []
114
- for idx in range(0, total, FRAME_STEP):
115
- if len(faces) >= NUM_MAX_FACES:
116
- break
117
- cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
118
- ok, frame = cap.read()
119
- if not ok:
120
- break
121
- rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
122
- boxes, _ = _mtcnn.detect(rgb)
123
- if boxes is None:
124
- continue
125
- for (x1, y1, x2, y2) in boxes.astype(int):
126
- x1, y1 = max(0, x1), max(0, y1)
127
- x2, y2 = min(frame.shape[1], x2), min(frame.shape[0], y2)
128
- crop = frame[y1:y2, x1:x2]
129
- if crop.size > 0:
130
- faces.append(cv2.resize(crop, IMG_SIZE))
131
- if len(faces) >= NUM_MAX_FACES:
132
- break
133
- cap.release()
134
- if not faces:
135
- return None
136
- return np.stack(faces, axis=0).astype(np.uint8)
137
-
138
- def blink_features_from_crops(faces):
139
- """Compute EAR on cropped faces; denominator = #frames with valid EAR."""
140
- (lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
141
- (rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
142
-
143
- ear_values = []
144
- blink_counter = 0
145
- total_blinks = 0
146
-
147
- for face in faces:
148
- gray = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY)
149
- rects = _dlib_detector(gray, 0)
150
- if len(rects) == 0:
151
- continue
152
- shape = _dlib_predictor(gray, rects[0])
153
- shape = face_utils.shape_to_np(shape)
154
-
155
- left_eye = shape[lStart:lEnd]
156
- right_eye = shape[rStart:rEnd]
157
- ear = 0.5 * (_eye_aspect_ratio(left_eye) + _eye_aspect_ratio(right_eye))
158
- ear_values.append(ear)
159
-
160
- if ear < EAR_THRESHOLD:
161
- blink_counter += 1
162
- else:
163
- if blink_counter >= EAR_CONSEC_FRAMES:
164
- total_blinks += 1
165
- blink_counter = 0
166
-
167
- n_ear = len(ear_values)
168
- if n_ear == 0:
169
- return np.array([0, 0.0, 0.0], dtype=np.float32)
170
-
171
- blink_freq = total_blinks / float(n_ear)
172
- ear_var = float(np.var(np.array(ear_values, dtype=np.float32)))
173
- return np.array([total_blinks, blink_freq, ear_var], dtype=np.float32)
174
-
175
- def predict_video_prob(video_path):
176
- faces = extract_faces_all(video_path)
177
- if faces is None or len(faces) == 0:
178
- return None, "No faces detected."
179
-
180
- blink_feats = blink_features_from_crops(faces)
181
- # Tile to per-face samples
182
- tiled = np.tile(blink_feats, (faces.shape[0], 1)).astype(np.float32)
183
- imgs = resnet_preprocess(faces.astype(np.float32))
184
-
185
- # Batch size heuristic (bigger if GPU is present)
186
- has_tf_gpu = len(tf.config.experimental.list_physical_devices("GPU")) > 0
187
- bs = 128 if has_tf_gpu else 32
188
-
189
- preds = []
190
- for i in range(0, imgs.shape[0], bs):
191
- p = _video_model.predict([imgs[i:i+bs], tiled[i:i+bs]], verbose=0)
192
- preds.append(p.reshape(-1))
193
- return float(np.mean(np.concatenate(preds, axis=0))), None
194
-
195
- def to_verdict(score):
196
- return "DEEPFAKE" if score >= PRED_THRESHOLD else "REAL"
197
-
198
- # =========================
199
- # Inference entry
200
- # =========================
201
- def run_inference(video_file):
202
- lazy_load()
203
- if video_file is None:
204
- return None, None, "Please upload a video file."
205
-
206
- video_prob, vmsg = predict_video_prob(video_file)
207
- if video_prob is None:
208
- return None, None, vmsg or "Unable to process the video."
209
-
210
- verdict = f"VIDEO ONLY: {to_verdict(video_prob)}"
211
- fmt = lambda x: None if x is None else round(float(x), 4)
212
- return fmt(video_prob), verdict, None
213
-
214
- # =========================
215
- # Gradio UI
216
- # =========================
217
- with gr.Blocks(title="Deepfake Detector — Video Only (GPU-ready)") as demo:
218
- gr.Markdown(
219
- "### 🎭 Deepfake Detector — **Video Only**\n"
220
- "- **Compute**: Uses GPU automatically if available (PyTorch MTCNN, TensorFlow model; mixed precision on TF).\n"
221
- "- **Video path**: samples every 5th frame, keeps **all** faces, resizes to 224×224.\n"
222
- "- **Features**: ResNet50 preprocessing + blink EAR features on cropped faces via dlib.\n"
223
- f"- **Threshold**: {PRED_THRESHOLD} (≥ means DEEPFAKE).\n"
224
- )
225
- with gr.Row():
226
- video_in = gr.Video(label="Video")
227
- go = gr.Button("Analyze")
228
- with gr.Row():
229
- v_out = gr.Number(label="Video probability (deepfake)", precision=4)
230
- verdict_out = gr.Textbox(label="Verdict", interactive=False)
231
- msg_out = gr.Textbox(label="Message / Warnings", interactive=False)
232
-
233
- go.click(run_inference, inputs=[video_in], outputs=[v_out, verdict_out, msg_out])
234
-
235
- if __name__ == "__main__":
236
- lazy_load()
237
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Docker/models/audio_model.keras DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e6be7d6e4320dce4e1e74edd0f8f3632aafd7b72be1f0973af72aef7cd52fd08
3
- size 25015854
 
 
 
 
Docker/models/audio_model/config.json DELETED
@@ -1 +0,0 @@
1
- {"module": "keras", "class_name": "Sequential", "config": {"name": "sequential", "trainable": true, "dtype": {"module": "keras", "class_name": "DTypePolicy", "config": {"name": "float32"}, "registered_name": null, "shared_object_id": 139413435787232}, "layers": [{"module": "keras.layers", "class_name": "InputLayer", "config": {"batch_shape": [null, 1000, 55], "dtype": "float32", "sparse": false, "ragged": false, "name": "input_layer"}, "registered_name": null}, {"module": "keras.layers", "class_name": "Conv1D", "config": {"name": "conv1d", "trainable": true, "dtype": {"module": "keras", "class_name": "DTypePolicy", "config": {"name": "float32"}, "registered_name": null}, "filters": 64, "kernel_size": [7], "strides": [1], "padding": "valid", "data_format": "channels_last", "dilation_rate": [1], "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 1000, 55]}}, {"module": "keras.layers", "class_name": "MaxPooling1D", "config": {"name": "max_pooling1d", "trainable": true, "dtype": {"module": "keras", "class_name": "DTypePolicy", "config": {"name": "float32"}, "registered_name": null, "shared_object_id": 139413435787232}, "pool_size": [2], "padding": "valid", "strides": [2], "data_format": "channels_last"}, "registered_name": null}, {"module": "keras.layers", "class_name": "Dropout", "config": {"name": "dropout", "trainable": true, "dtype": {"module": "keras", "class_name": "DTypePolicy", "config": {"name": "float32"}, "registered_name": null, "shared_object_id": 139413435787232}, "rate": 0.30000000000000004, "seed": null, "noise_shape": null}, "registered_name": null}, {"module": "keras.layers", "class_name": "Conv1D", "config": {"name": "conv1d_1", "trainable": true, "dtype": {"module": "keras", "class_name": "DTypePolicy", "config": {"name": "float32"}, "registered_name": null, "shared_object_id": 139413435787232}, "filters": 128, "kernel_size": [5], "strides": [1], "padding": "valid", "data_format": "channels_last", "dilation_rate": [1], "groups": 1, "activation": "relu", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 497, 64]}}, {"module": "keras.layers", "class_name": "MaxPooling1D", "config": {"name": "max_pooling1d_1", "trainable": true, "dtype": {"module": "keras", "class_name": "DTypePolicy", "config": {"name": "float32"}, "registered_name": null, "shared_object_id": 139413435787232}, "pool_size": [2], "padding": "valid", "strides": [2], "data_format": "channels_last"}, "registered_name": null}, {"module": "keras.layers", "class_name": "Dropout", "config": {"name": "dropout_1", "trainable": true, "dtype": {"module": "keras", "class_name": "DTypePolicy", "config": {"name": "float32"}, "registered_name": null, "shared_object_id": 139413435787232}, "rate": 0.30000000000000004, "seed": null, "noise_shape": null}, "registered_name": null}, {"module": "keras.layers", "class_name": "Flatten", "config": {"name": "flatten", "trainable": true, "dtype": {"module": "keras", "class_name": "DTypePolicy", "config": {"name": "float32"}, "registered_name": null, "shared_object_id": 139413435787232}, "data_format": "channels_last"}, "registered_name": null, "build_config": {"input_shape": [null, 246, 128]}}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": {"module": "keras", "class_name": "DTypePolicy", "config": {"name": "float32"}, "registered_name": null, "shared_object_id": 139413435787232}, "units": 64, "activation": "relu", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 31488]}}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": {"module": "keras", "class_name": "DTypePolicy", "config": {"name": "float32"}, "registered_name": null, "shared_object_id": 139413435787232}, "units": 1, "activation": "sigmoid", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 64]}}], "build_input_shape": [null, 1000, 55]}, "registered_name": null, "build_config": {"input_shape": [null, 1000, 55]}, "compile_config": {"optimizer": {"module": "keras.optimizers", "class_name": "Adam", "config": {"name": "adam", "learning_rate": 0.0010000000474974513, "weight_decay": null, "clipnorm": null, "global_clipnorm": null, "clipvalue": null, "use_ema": false, "ema_momentum": 0.99, "ema_overwrite_frequency": null, "loss_scale_factor": null, "gradient_accumulation_steps": null, "beta_1": 0.9, "beta_2": 0.999, "epsilon": 1e-07, "amsgrad": false}, "registered_name": null}, "loss": "binary_crossentropy", "loss_weights": null, "metrics": ["accuracy"], "weighted_metrics": null, "run_eagerly": false, "steps_per_execution": 1, "jit_compile": false}}
 
 
Docker/models/audio_model/metadata.json DELETED
@@ -1 +0,0 @@
1
- {"keras_version": "3.10.0", "date_saved": "2025-09-30@02:28:41"}
 
 
Docker/models/audio_model/model.weights.h5 DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e9a4c54ac044bcb96c43b9947c05af09fc1de6cceb3f2881a5761a2b2da8768c
3
- size 25009192
 
 
 
 
Docker/models/video_model.h5 DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:f623abf62c659bcfd8364bcc4b233680b6834d5371b925bfe62a9859efb7bd39
3
- size 285090744
 
 
 
 
Docker/requirements.txt DELETED
@@ -1,30 +0,0 @@
1
- # -----------------------------
2
- # Core scientific stack
3
- # -----------------------------
4
- numpy==1.26.4
5
- scipy==1.11.4
6
- pandas==2.2.2
7
-
8
- # -----------------------------
9
- # TensorFlow (GPU-enabled if CUDA present)
10
- # -----------------------------
11
- tensorflow==2.18.0
12
-
13
- # -----------------------------
14
- # PyTorch + facenet-pytorch
15
- # (CPU wheels by default; CUDA wheels provided in Dockerfile)
16
- # -----------------------------
17
- facenet-pytorch==2.6.0
18
- pillow==10.2.0
19
-
20
- # -----------------------------
21
- # Vision / utility
22
- # -----------------------------
23
- opencv-python-headless==4.9.0.80
24
- imutils==0.5.4
25
- dlib==19.24.4
26
-
27
- # -----------------------------
28
- # Web UI
29
- # -----------------------------
30
- gradio==4.4.1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Docker/shape_predictor_68_face_landmarks.dat DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:fbdc2cb80eb9aa7a758672cbfdda32ba6300efe9b6e6c7a299ff7e736b11b92f
3
- size 99693937