Spaces:
Sleeping
Sleeping
Commit ·
abb9574
1
Parent(s): 247f7f7
New Backend
Browse files- Related Documents and Diagrams/New Text Document.txt +10 -0
- Related Documents and Diagrams/The-architecture-of-the-Xception-model.png +3 -0
- Related Documents and Diagrams/Untitled Diagram.drawio +132 -0
- backend/Deepfake-Detection +0 -1
- backend/deepfake_integration.py +0 -275
- backend/download_models.py +0 -0
- backend/requirements.txt +0 -0
- backend/simple_server.py +0 -256
Related Documents and Diagrams/New Text Document.txt
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
The Xception model is a deep learning architecture designed for image classification tasks. It was proposed by François Chollet, the creator of the Keras library, and is an extension of the Inception architecture. The key innovation in Xception is the use of depthwise separable convolutions instead of the standard Inception modules.
|
| 2 |
+
|
| 3 |
+
Key Features of Xception
|
| 4 |
+
|
| 5 |
+
Depthwise Separable Convolutions: This technique involves performing a depthwise convolution (a single convolution on each input channel) followed by a pointwise convolution (a 1x1 convolution across all channels). This reduces the number of parameters and computational cost while maintaining performance.
|
| 6 |
+
|
| 7 |
+
Pre-trained on ImageNet: The Xception model can be pre-trained on the ImageNet dataset, which contains over 1.2 million images and 1,000 classes. This allows the model to leverage learned features and achieve high accuracy on various image classification tasks.
|
| 8 |
+
|
| 9 |
+
Input Size: The default input size for the Xception model is 299x299 pixels. This is larger than the typical 224x224 input size used by other models like VGG and ResNet.
|
| 10 |
+
|
Related Documents and Diagrams/The-architecture-of-the-Xception-model.png
ADDED
|
|
Git LFS Details
|
Related Documents and Diagrams/Untitled Diagram.drawio
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0" version="27.2.0">
|
| 2 |
+
<diagram name="Page-1" id="B7ypKxJ6UBQbOQEK7qXx">
|
| 3 |
+
<mxGraphModel dx="2298" dy="1373" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" background="#ffffff" math="0" shadow="0">
|
| 4 |
+
<root>
|
| 5 |
+
<mxCell id="0" />
|
| 6 |
+
<mxCell id="1" parent="0" />
|
| 7 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-2" value=" Python Backend - Flask" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;align=left;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;fontStyle=3;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
|
| 8 |
+
<mxGeometry x="230" y="170" width="990" height="560" as="geometry" />
|
| 9 |
+
</mxCell>
|
| 10 |
+
<mxCell id="CRdauCQWdr09auiODn36-16" value=" Machine Learning Models " style="whiteSpace=wrap;strokeWidth=2;fontSize=20;align=right;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;fontStyle=3;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
|
| 11 |
+
<mxGeometry x="720" y="534.95" width="360" height="165.05" as="geometry" />
|
| 12 |
+
</mxCell>
|
| 13 |
+
<mxCell id="CRdauCQWdr09auiODn36-15" value=" Input" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;align=left;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;fontStyle=3;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
| 14 |
+
<mxGeometry x="354" y="7" width="300" height="140" as="geometry" />
|
| 15 |
+
</mxCell>
|
| 16 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-1" value="Training Data" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;verticalAlign=top;fontStyle=3;fillColor=#ffcccc;strokeColor=#36393d;" parent="1" vertex="1">
|
| 17 |
+
<mxGeometry x="490" y="760.5" width="640" height="138" as="geometry" />
|
| 18 |
+
</mxCell>
|
| 19 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-4" value="User Uploads Image or Video" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;" parent="1" vertex="1">
|
| 20 |
+
<mxGeometry x="374" y="47" width="260" height="78" as="geometry" />
|
| 21 |
+
</mxCell>
|
| 22 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-6" value="API Endpoint: /predict" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;" parent="1" vertex="1">
|
| 23 |
+
<mxGeometry x="393" y="205.5" width="222" height="54" as="geometry" />
|
| 24 |
+
</mxCell>
|
| 25 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-7" value="Extract Frames with OpenCV" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;" parent="1" vertex="1">
|
| 26 |
+
<mxGeometry x="374" y="309.5" width="260" height="78" as="geometry" />
|
| 27 |
+
</mxCell>
|
| 28 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-8" value="Detect Face using Mediapipe" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;" parent="1" vertex="1">
|
| 29 |
+
<mxGeometry x="374" y="437.5" width="260" height="78" as="geometry" />
|
| 30 |
+
</mxCell>
|
| 31 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-9" value="Resize and Crop Frame" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;" parent="1" vertex="1">
|
| 32 |
+
<mxGeometry x="392" y="602.5" width="224" height="54" as="geometry" />
|
| 33 |
+
</mxCell>
|
| 34 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-12" value="Generate Grad-CAM Heatmap" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;" parent="1" vertex="1">
|
| 35 |
+
<mxGeometry x="1305" y="470.5" width="260" height="78" as="geometry" />
|
| 36 |
+
</mxCell>
|
| 37 |
+
<mxCell id="CRdauCQWdr09auiODn36-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;strokeWidth=4;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="I_QHsUmjhxNyvni-dwqb-13" target="CRdauCQWdr09auiODn36-9">
|
| 38 |
+
<mxGeometry relative="1" as="geometry" />
|
| 39 |
+
</mxCell>
|
| 40 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-13" value="Return Prediction and Heatmap" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;" parent="1" vertex="1">
|
| 41 |
+
<mxGeometry x="1305" y="586.5" width="260" height="78" as="geometry" />
|
| 42 |
+
</mxCell>
|
| 43 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-14" value="DFDC or FaceForensics++ Dataset" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;" parent="1" vertex="1">
|
| 44 |
+
<mxGeometry x="525" y="795.5" width="260" height="78" as="geometry" />
|
| 45 |
+
</mxCell>
|
| 46 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-15" value="Model Weights and Checkpoints" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;" parent="1" vertex="1">
|
| 47 |
+
<mxGeometry x="835" y="795.5" width="275" height="78" as="geometry" />
|
| 48 |
+
</mxCell>
|
| 49 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-16" value="" style="curved=1;startArrow=none;endArrow=block;exitX=0.5;exitY=1;entryX=0.5;entryY=0;rounded=0;entryDx=0;entryDy=0;strokeWidth=4;" parent="1" source="I_QHsUmjhxNyvni-dwqb-4" target="I_QHsUmjhxNyvni-dwqb-6" edge="1">
|
| 50 |
+
<mxGeometry relative="1" as="geometry">
|
| 51 |
+
<Array as="points" />
|
| 52 |
+
</mxGeometry>
|
| 53 |
+
</mxCell>
|
| 54 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-17" value="" style="curved=1;startArrow=none;endArrow=block;exitX=0.5;exitY=1;entryX=0.5;entryY=0;rounded=0;strokeWidth=4;" parent="1" source="I_QHsUmjhxNyvni-dwqb-6" target="I_QHsUmjhxNyvni-dwqb-7" edge="1">
|
| 55 |
+
<mxGeometry relative="1" as="geometry">
|
| 56 |
+
<Array as="points" />
|
| 57 |
+
</mxGeometry>
|
| 58 |
+
</mxCell>
|
| 59 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-18" value="" style="curved=1;startArrow=none;endArrow=block;exitX=0.5;exitY=1;entryX=0.5;entryY=0;rounded=0;strokeWidth=4;" parent="1" source="I_QHsUmjhxNyvni-dwqb-7" target="I_QHsUmjhxNyvni-dwqb-8" edge="1">
|
| 60 |
+
<mxGeometry relative="1" as="geometry">
|
| 61 |
+
<Array as="points" />
|
| 62 |
+
</mxGeometry>
|
| 63 |
+
</mxCell>
|
| 64 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-19" value="" style="curved=1;startArrow=none;endArrow=block;exitX=0.5;exitY=1;entryX=0.5;entryY=0;rounded=0;strokeWidth=4;" parent="1" source="I_QHsUmjhxNyvni-dwqb-8" target="I_QHsUmjhxNyvni-dwqb-9" edge="1">
|
| 65 |
+
<mxGeometry relative="1" as="geometry">
|
| 66 |
+
<Array as="points" />
|
| 67 |
+
</mxGeometry>
|
| 68 |
+
</mxCell>
|
| 69 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-20" value="" style="curved=1;startArrow=none;endArrow=block;exitX=1;exitY=0.5;entryX=0;entryY=0.5;rounded=0;entryDx=0;entryDy=0;exitDx=0;exitDy=0;strokeWidth=4;" parent="1" source="I_QHsUmjhxNyvni-dwqb-9" target="CRdauCQWdr09auiODn36-10" edge="1">
|
| 70 |
+
<mxGeometry relative="1" as="geometry">
|
| 71 |
+
<Array as="points" />
|
| 72 |
+
<mxPoint x="602" y="652.5" as="sourcePoint" />
|
| 73 |
+
<mxPoint x="900" y="629.5" as="targetPoint" />
|
| 74 |
+
</mxGeometry>
|
| 75 |
+
</mxCell>
|
| 76 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-21" value="" style="curved=1;startArrow=none;endArrow=block;entryX=0.001;entryY=0.527;rounded=0;entryDx=0;entryDy=0;entryPerimeter=0;exitX=1;exitY=0.664;exitDx=0;exitDy=0;exitPerimeter=0;strokeWidth=4;" parent="1" target="I_QHsUmjhxNyvni-dwqb-29" edge="1">
|
| 77 |
+
<mxGeometry relative="1" as="geometry">
|
| 78 |
+
<Array as="points">
|
| 79 |
+
<mxPoint x="1610" y="444" />
|
| 80 |
+
</Array>
|
| 81 |
+
<mxPoint x="1572.1599999999999" y="507.1400000000003" as="sourcePoint" />
|
| 82 |
+
</mxGeometry>
|
| 83 |
+
</mxCell>
|
| 84 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-24" value="" style="curved=1;startArrow=none;endArrow=block;exitX=0.5;exitY=1;entryX=0.5;entryY=0;rounded=0;entryDx=0;entryDy=0;strokeWidth=4;" parent="1" source="I_QHsUmjhxNyvni-dwqb-12" target="I_QHsUmjhxNyvni-dwqb-13" edge="1">
|
| 85 |
+
<mxGeometry relative="1" as="geometry">
|
| 86 |
+
<Array as="points" />
|
| 87 |
+
</mxGeometry>
|
| 88 |
+
</mxCell>
|
| 89 |
+
<mxCell id="I_QHsUmjhxNyvni-dwqb-26" value="" style="curved=1;startArrow=none;endArrow=block;rounded=0;strokeWidth=4;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="1" source="I_QHsUmjhxNyvni-dwqb-1" edge="1">
|
| 90 |
+
<mxGeometry relative="1" as="geometry">
|
| 91 |
+
<Array as="points" />
|
| 92 |
+
<mxPoint x="700" y="770.5" as="sourcePoint" />
|
| 93 |
+
<mxPoint x="810" y="670.5" as="targetPoint" />
|
| 94 |
+
</mxGeometry>
|
| 95 |
+
</mxCell>
|
| 96 |
+
<mxCell id="CRdauCQWdr09auiODn36-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeWidth=4;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="CRdauCQWdr09auiODn36-10">
|
| 97 |
+
<mxGeometry relative="1" as="geometry">
|
| 98 |
+
<mxPoint x="835.04" y="600.6800000000001" as="sourcePoint" />
|
| 99 |
+
<mxPoint x="1440" y="470" as="targetPoint" />
|
| 100 |
+
<Array as="points">
|
| 101 |
+
<mxPoint x="810" y="400" />
|
| 102 |
+
<mxPoint x="1440" y="400" />
|
| 103 |
+
</Array>
|
| 104 |
+
</mxGeometry>
|
| 105 |
+
</mxCell>
|
| 106 |
+
<mxCell id="CRdauCQWdr09auiODn36-9" value=" Output" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;align=left;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;fontStyle=3;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
|
| 107 |
+
<mxGeometry x="1275" y="738.5" width="320" height="160" as="geometry" />
|
| 108 |
+
</mxCell>
|
| 109 |
+
<mxCell id="CRdauCQWdr09auiODn36-4" value="Display Prediction and Heatmap" style="whiteSpace=wrap;strokeWidth=2;fontSize=20;" vertex="1" parent="1">
|
| 110 |
+
<mxGeometry x="1305" y="779.5" width="260" height="78" as="geometry" />
|
| 111 |
+
</mxCell>
|
| 112 |
+
<mxCell id="CRdauCQWdr09auiODn36-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;strokeWidth=4;" edge="1" parent="1" source="CRdauCQWdr09auiODn36-10" target="CRdauCQWdr09auiODn36-11">
|
| 113 |
+
<mxGeometry relative="1" as="geometry" />
|
| 114 |
+
</mxCell>
|
| 115 |
+
<mxCell id="CRdauCQWdr09auiODn36-10" value="Xception Model" style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" vertex="1" parent="1">
|
| 116 |
+
<mxGeometry x="750" y="599.5" width="120" height="60" as="geometry" />
|
| 117 |
+
</mxCell>
|
| 118 |
+
<mxCell id="CRdauCQWdr09auiODn36-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=4;" edge="1" parent="1" source="CRdauCQWdr09auiODn36-11" target="I_QHsUmjhxNyvni-dwqb-13">
|
| 119 |
+
<mxGeometry relative="1" as="geometry">
|
| 120 |
+
<mxPoint x="2400" y="430.5" as="targetPoint" />
|
| 121 |
+
<Array as="points">
|
| 122 |
+
<mxPoint x="1040" y="626" />
|
| 123 |
+
</Array>
|
| 124 |
+
</mxGeometry>
|
| 125 |
+
</mxCell>
|
| 126 |
+
<mxCell id="CRdauCQWdr09auiODn36-11" value="BI-LSTM" style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" vertex="1" parent="1">
|
| 127 |
+
<mxGeometry x="920" y="599.5" width="120" height="60" as="geometry" />
|
| 128 |
+
</mxCell>
|
| 129 |
+
</root>
|
| 130 |
+
</mxGraphModel>
|
| 131 |
+
</diagram>
|
| 132 |
+
</mxfile>
|
backend/Deepfake-Detection
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
Subproject commit cecd5ab4b50a482ccf5e64b1057b7cfbb6094fc9
|
|
|
|
|
|
backend/deepfake_integration.py
DELETED
|
@@ -1,275 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Enhanced Deepfake Detection Integration
|
| 3 |
-
Combines video and image analysis capabilities
|
| 4 |
-
"""
|
| 5 |
-
|
| 6 |
-
import os
|
| 7 |
-
import sys
|
| 8 |
-
import cv2
|
| 9 |
-
import dlib
|
| 10 |
-
import torch
|
| 11 |
-
import numpy as np
|
| 12 |
-
from PIL import Image
|
| 13 |
-
import argparse
|
| 14 |
-
import tempfile
|
| 15 |
-
import subprocess
|
| 16 |
-
from pathlib import Path
|
| 17 |
-
|
| 18 |
-
# Add the current directory to the path for imports
|
| 19 |
-
current_dir = Path(__file__).parent
|
| 20 |
-
deepfake_dir = current_dir / "Deepfake-Detection"
|
| 21 |
-
sys.path.insert(0, str(deepfake_dir))
|
| 22 |
-
|
| 23 |
-
try:
|
| 24 |
-
from network.models import model_selection
|
| 25 |
-
from dataset.transform import xception_default_data_transforms
|
| 26 |
-
from dataset.mydataset import MyDataset
|
| 27 |
-
except ImportError as e:
|
| 28 |
-
print(f"Warning: Could not import deepfake detection modules: {e}")
|
| 29 |
-
|
| 30 |
-
class DeepfakeAnalyzer:
|
| 31 |
-
def __init__(self):
|
| 32 |
-
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
| 33 |
-
print(f"Using device: {self.device}")
|
| 34 |
-
|
| 35 |
-
# Initialize dlib face detector
|
| 36 |
-
self.face_detector = dlib.get_frontal_face_detector()
|
| 37 |
-
|
| 38 |
-
# Load model
|
| 39 |
-
self.model = None
|
| 40 |
-
self.load_model()
|
| 41 |
-
|
| 42 |
-
def load_model(self, model_path=None):
|
| 43 |
-
"""Load the deepfake detection model"""
|
| 44 |
-
if model_path is None:
|
| 45 |
-
# Try different possible model paths
|
| 46 |
-
model_paths = [
|
| 47 |
-
deepfake_dir / "pretrained_model" / "FF++_c23.pth",
|
| 48 |
-
deepfake_dir / "pretrained_model" / "FF++_c40.pth",
|
| 49 |
-
deepfake_dir / "pretrained_model" / "df_c0_best.pkl"
|
| 50 |
-
]
|
| 51 |
-
|
| 52 |
-
for path in model_paths:
|
| 53 |
-
if path.exists():
|
| 54 |
-
model_path = str(path)
|
| 55 |
-
break
|
| 56 |
-
|
| 57 |
-
if model_path and os.path.exists(model_path):
|
| 58 |
-
try:
|
| 59 |
-
self.model = model_selection(modelname='xception', num_out_classes=2, dropout=0.5)
|
| 60 |
-
|
| 61 |
-
# Load model with proper device handling
|
| 62 |
-
if torch.cuda.is_available():
|
| 63 |
-
print("CUDA is available - using GPU")
|
| 64 |
-
self.model.load_state_dict(torch.load(model_path))
|
| 65 |
-
self.model = self.model.cuda()
|
| 66 |
-
else:
|
| 67 |
-
print("CUDA not available - using CPU")
|
| 68 |
-
self.model.load_state_dict(torch.load(model_path, map_location='cpu'))
|
| 69 |
-
|
| 70 |
-
self.model.to(self.device)
|
| 71 |
-
self.model.eval()
|
| 72 |
-
print(f"Model loaded from: {model_path}")
|
| 73 |
-
return True
|
| 74 |
-
except Exception as e:
|
| 75 |
-
print(f"Error loading model: {e}")
|
| 76 |
-
self.model = None
|
| 77 |
-
return False
|
| 78 |
-
else:
|
| 79 |
-
print("No pretrained model found. Please download FF++_c23.pth or FF++_c40.pth")
|
| 80 |
-
print("Place the model in: backend/Deepfake-Detection/pretrained_model/")
|
| 81 |
-
return False
|
| 82 |
-
|
| 83 |
-
def get_boundingbox(self, face, width, height, scale=1.3, minsize=None):
|
| 84 |
-
"""Generate bounding box for detected face"""
|
| 85 |
-
x1 = face.left()
|
| 86 |
-
y1 = face.top()
|
| 87 |
-
x2 = face.right()
|
| 88 |
-
y2 = face.bottom()
|
| 89 |
-
size_bb = int(max(x2 - x1, y2 - y1) * scale)
|
| 90 |
-
if minsize:
|
| 91 |
-
if size_bb < minsize:
|
| 92 |
-
size_bb = minsize
|
| 93 |
-
center_x, center_y = (x1 + x2) // 2, (y1 + y2) // 2
|
| 94 |
-
|
| 95 |
-
# Check for out of bounds, x-y top left corner
|
| 96 |
-
x1 = max(int(center_x - size_bb // 2), 0)
|
| 97 |
-
y1 = max(int(center_y - size_bb // 2), 0)
|
| 98 |
-
# Check for too big bb size for given x, y
|
| 99 |
-
size_bb = min(width - x1, size_bb)
|
| 100 |
-
size_bb = min(height - y1, size_bb)
|
| 101 |
-
|
| 102 |
-
return x1, y1, size_bb
|
| 103 |
-
|
| 104 |
-
def detect_faces(self, image):
|
| 105 |
-
"""Detect faces in image using dlib"""
|
| 106 |
-
if isinstance(image, str):
|
| 107 |
-
image = cv2.imread(image)
|
| 108 |
-
|
| 109 |
-
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
| 110 |
-
faces = self.face_detector(gray)
|
| 111 |
-
return faces
|
| 112 |
-
|
| 113 |
-
def analyze_image(self, image_path):
|
| 114 |
-
"""Analyze a single image for deepfakes"""
|
| 115 |
-
try:
|
| 116 |
-
# Load image
|
| 117 |
-
image = cv2.imread(str(image_path))
|
| 118 |
-
if image is None:
|
| 119 |
-
return {"error": "Could not load image"}
|
| 120 |
-
|
| 121 |
-
height, width = image.shape[:2]
|
| 122 |
-
|
| 123 |
-
# Detect faces
|
| 124 |
-
faces = self.detect_faces(image)
|
| 125 |
-
|
| 126 |
-
if not faces:
|
| 127 |
-
return {
|
| 128 |
-
"prediction": "no_faces",
|
| 129 |
-
"confidence": 0.0,
|
| 130 |
-
"message": "No faces detected in the image",
|
| 131 |
-
"faces_detected": 0
|
| 132 |
-
}
|
| 133 |
-
|
| 134 |
-
results = []
|
| 135 |
-
|
| 136 |
-
for i, face in enumerate(faces):
|
| 137 |
-
# Get bounding box
|
| 138 |
-
x, y, size = self.get_boundingbox(face, width, height)
|
| 139 |
-
|
| 140 |
-
# Extract face region
|
| 141 |
-
cropped_face = image[y:y+size, x:x+size]
|
| 142 |
-
|
| 143 |
-
if self.model is not None:
|
| 144 |
-
# Preprocess for model
|
| 145 |
-
face_pil = Image.fromarray(cv2.cvtColor(cropped_face, cv2.COLOR_BGR2RGB))
|
| 146 |
-
face_tensor = xception_default_data_transforms['test'](face_pil).unsqueeze(0)
|
| 147 |
-
|
| 148 |
-
# Move to device (CUDA or CPU)
|
| 149 |
-
face_tensor = face_tensor.to(self.device)
|
| 150 |
-
|
| 151 |
-
# Predict
|
| 152 |
-
with torch.no_grad():
|
| 153 |
-
outputs = self.model(face_tensor)
|
| 154 |
-
probabilities = torch.softmax(outputs, dim=1)
|
| 155 |
-
fake_prob = probabilities[0][1].item()
|
| 156 |
-
|
| 157 |
-
prediction = "fake" if fake_prob > 0.5 else "real"
|
| 158 |
-
confidence = fake_prob if prediction == "fake" else (1 - fake_prob)
|
| 159 |
-
else:
|
| 160 |
-
prediction = "unknown"
|
| 161 |
-
confidence = 0.0
|
| 162 |
-
|
| 163 |
-
results.append({
|
| 164 |
-
"face_id": i + 1,
|
| 165 |
-
"prediction": prediction,
|
| 166 |
-
"confidence": confidence,
|
| 167 |
-
"bbox": {"x": x, "y": y, "size": size}
|
| 168 |
-
})
|
| 169 |
-
|
| 170 |
-
# Overall prediction (worst case)
|
| 171 |
-
overall_prediction = "real"
|
| 172 |
-
max_fake_confidence = 0.0
|
| 173 |
-
|
| 174 |
-
for result in results:
|
| 175 |
-
if result["prediction"] == "fake" and result["confidence"] > max_fake_confidence:
|
| 176 |
-
max_fake_confidence = result["confidence"]
|
| 177 |
-
overall_prediction = "fake"
|
| 178 |
-
|
| 179 |
-
return {
|
| 180 |
-
"overall_prediction": overall_prediction,
|
| 181 |
-
"overall_confidence": max_fake_confidence if overall_prediction == "fake" else (1 - max_fake_confidence),
|
| 182 |
-
"faces_detected": len(faces),
|
| 183 |
-
"face_results": results
|
| 184 |
-
}
|
| 185 |
-
|
| 186 |
-
except Exception as e:
|
| 187 |
-
return {"error": str(e)}
|
| 188 |
-
|
| 189 |
-
def analyze_video(self, video_path, output_path=None):
|
| 190 |
-
"""Analyze video for deepfakes"""
|
| 191 |
-
if not os.path.exists(video_path):
|
| 192 |
-
return {"error": "Video file not found"}
|
| 193 |
-
|
| 194 |
-
# Use the detect_from_video.py script
|
| 195 |
-
cmd = [
|
| 196 |
-
sys.executable,
|
| 197 |
-
str(deepfake_dir / "detect_from_video.py"),
|
| 198 |
-
"-i", str(video_path),
|
| 199 |
-
"-m", str(deepfake_dir / "pretrained_model" / "FF++_c23.pth")
|
| 200 |
-
]
|
| 201 |
-
|
| 202 |
-
if output_path:
|
| 203 |
-
cmd.extend(["-o", str(output_path)])
|
| 204 |
-
|
| 205 |
-
try:
|
| 206 |
-
result = subprocess.run(cmd, capture_output=True, text=True, cwd=str(deepfake_dir))
|
| 207 |
-
|
| 208 |
-
if result.returncode == 0:
|
| 209 |
-
return {
|
| 210 |
-
"success": True,
|
| 211 |
-
"message": "Video analysis completed",
|
| 212 |
-
"output": result.stdout
|
| 213 |
-
}
|
| 214 |
-
else:
|
| 215 |
-
return {
|
| 216 |
-
"error": "Video analysis failed",
|
| 217 |
-
"details": result.stderr
|
| 218 |
-
}
|
| 219 |
-
except Exception as e:
|
| 220 |
-
return {"error": str(e)}
|
| 221 |
-
|
| 222 |
-
def test_setup():
|
| 223 |
-
"""Test the deepfake detection setup"""
|
| 224 |
-
print("Testing Deepfake Detection Setup")
|
| 225 |
-
print("=" * 40)
|
| 226 |
-
|
| 227 |
-
analyzer = DeepfakeAnalyzer()
|
| 228 |
-
|
| 229 |
-
# Test face detection
|
| 230 |
-
print(f"dlib face detector: {'✓' if analyzer.face_detector else '✗'}")
|
| 231 |
-
print(f"Model loaded: {'✓' if analyzer.model else '✗'}")
|
| 232 |
-
print(f"Device: {analyzer.device}")
|
| 233 |
-
|
| 234 |
-
# Test with sample image if available
|
| 235 |
-
sample_video = deepfake_dir / "videos" / "994.mp4"
|
| 236 |
-
if sample_video.exists():
|
| 237 |
-
print(f"Sample video found: {sample_video}")
|
| 238 |
-
|
| 239 |
-
# Extract a frame for testing
|
| 240 |
-
cap = cv2.VideoCapture(str(sample_video))
|
| 241 |
-
ret, frame = cap.read()
|
| 242 |
-
if ret:
|
| 243 |
-
test_image_path = "test_frame.jpg"
|
| 244 |
-
cv2.imwrite(test_image_path, frame)
|
| 245 |
-
|
| 246 |
-
result = analyzer.analyze_image(test_image_path)
|
| 247 |
-
print(f"Test analysis result: {result}")
|
| 248 |
-
|
| 249 |
-
# Cleanup
|
| 250 |
-
os.remove(test_image_path)
|
| 251 |
-
cap.release()
|
| 252 |
-
|
| 253 |
-
print("=" * 40)
|
| 254 |
-
|
| 255 |
-
if __name__ == "__main__":
|
| 256 |
-
parser = argparse.ArgumentParser(description='Enhanced Deepfake Detection')
|
| 257 |
-
parser.add_argument('--test', action='store_true', help='Test the setup')
|
| 258 |
-
parser.add_argument('--image', type=str, help='Path to image file to analyze')
|
| 259 |
-
parser.add_argument('--video', type=str, help='Path to video file to analyze')
|
| 260 |
-
parser.add_argument('--output', type=str, help='Output directory for results')
|
| 261 |
-
|
| 262 |
-
args = parser.parse_args()
|
| 263 |
-
|
| 264 |
-
if args.test:
|
| 265 |
-
test_setup()
|
| 266 |
-
elif args.image:
|
| 267 |
-
analyzer = DeepfakeAnalyzer()
|
| 268 |
-
result = analyzer.analyze_image(args.image)
|
| 269 |
-
print(f"Analysis result: {result}")
|
| 270 |
-
elif args.video:
|
| 271 |
-
analyzer = DeepfakeAnalyzer()
|
| 272 |
-
result = analyzer.analyze_video(args.video, args.output)
|
| 273 |
-
print(f"Video analysis result: {result}")
|
| 274 |
-
else:
|
| 275 |
-
print("Use --test to test setup, --image <path> to analyze image, or --video <path> to analyze video")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/download_models.py
DELETED
|
File without changes
|
backend/requirements.txt
DELETED
|
File without changes
|
backend/simple_server.py
DELETED
|
@@ -1,256 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python3
|
| 2 |
-
"""
|
| 3 |
-
Enhanced Deepfake Detection Server with dlib integration
|
| 4 |
-
"""
|
| 5 |
-
|
| 6 |
-
import os
|
| 7 |
-
import sys
|
| 8 |
-
import cv2
|
| 9 |
-
import dlib
|
| 10 |
-
import numpy as np
|
| 11 |
-
import torch
|
| 12 |
-
import torch.nn as nn
|
| 13 |
-
from PIL import Image
|
| 14 |
-
from flask import Flask, request, jsonify, send_file
|
| 15 |
-
from flask_cors import CORS
|
| 16 |
-
import tempfile
|
| 17 |
-
import logging
|
| 18 |
-
import traceback
|
| 19 |
-
from pathlib import Path
|
| 20 |
-
|
| 21 |
-
# Add Deepfake-Detection to path
|
| 22 |
-
current_dir = Path(__file__).parent
|
| 23 |
-
deepfake_dir = current_dir / "Deepfake-Detection"
|
| 24 |
-
sys.path.insert(0, str(deepfake_dir))
|
| 25 |
-
|
| 26 |
-
try:
|
| 27 |
-
from network.models import model_selection
|
| 28 |
-
from network.mesonet import Meso4, MesoInception4
|
| 29 |
-
from network.xception import TransferModel
|
| 30 |
-
except ImportError as e:
|
| 31 |
-
print(f"Warning: Could not import deepfake detection models: {e}")
|
| 32 |
-
print("Some functionality may be limited.")
|
| 33 |
-
|
| 34 |
-
# Configure logging
|
| 35 |
-
logging.basicConfig(level=logging.INFO)
|
| 36 |
-
logger = logging.getLogger(__name__)
|
| 37 |
-
|
| 38 |
-
app = Flask(__name__)
|
| 39 |
-
CORS(app)
|
| 40 |
-
|
| 41 |
-
class DeepfakeDetector:
|
| 42 |
-
def __init__(self):
|
| 43 |
-
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
| 44 |
-
logger.info(f"Using device: {self.device}")
|
| 45 |
-
|
| 46 |
-
# Initialize dlib face detector
|
| 47 |
-
self.face_detector = dlib.get_frontal_face_detector()
|
| 48 |
-
logger.info("dlib face detector initialized")
|
| 49 |
-
|
| 50 |
-
# Initialize face predictor (if available)
|
| 51 |
-
predictor_path = "shape_predictor_68_face_landmarks.dat"
|
| 52 |
-
if os.path.exists(predictor_path):
|
| 53 |
-
self.face_predictor = dlib.shape_predictor(predictor_path)
|
| 54 |
-
logger.info("dlib face predictor loaded")
|
| 55 |
-
else:
|
| 56 |
-
self.face_predictor = None
|
| 57 |
-
logger.warning("dlib face predictor not found. Download from: http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2")
|
| 58 |
-
|
| 59 |
-
# Load model
|
| 60 |
-
self.model = None
|
| 61 |
-
self.load_model()
|
| 62 |
-
|
| 63 |
-
def load_model(self):
|
| 64 |
-
"""Load the deepfake detection model"""
|
| 65 |
-
try:
|
| 66 |
-
model_path = deepfake_dir / "pretrained_model" / "FF++_c23.pth"
|
| 67 |
-
if not model_path.exists():
|
| 68 |
-
logger.warning(f"Model not found at {model_path}")
|
| 69 |
-
return
|
| 70 |
-
|
| 71 |
-
# Try to load Xception model
|
| 72 |
-
self.model = TransferModel(name='xception', num_out_classes=2)
|
| 73 |
-
self.model.load_state_dict(torch.load(str(model_path), map_location=self.device))
|
| 74 |
-
self.model.to(self.device)
|
| 75 |
-
self.model.eval()
|
| 76 |
-
logger.info("Xception model loaded successfully")
|
| 77 |
-
|
| 78 |
-
except Exception as e:
|
| 79 |
-
logger.error(f"Error loading model: {e}")
|
| 80 |
-
self.model = None
|
| 81 |
-
|
| 82 |
-
def detect_faces_dlib(self, image):
|
| 83 |
-
"""Detect faces using dlib"""
|
| 84 |
-
if isinstance(image, str):
|
| 85 |
-
image = cv2.imread(image)
|
| 86 |
-
|
| 87 |
-
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
| 88 |
-
faces = self.face_detector(gray)
|
| 89 |
-
|
| 90 |
-
face_regions = []
|
| 91 |
-
for face in faces:
|
| 92 |
-
x, y, w, h = face.left(), face.top(), face.width(), face.height()
|
| 93 |
-
face_regions.append((x, y, w, h))
|
| 94 |
-
|
| 95 |
-
return face_regions
|
| 96 |
-
|
| 97 |
-
def preprocess_face(self, face_image):
|
| 98 |
-
"""Preprocess face image for model input"""
|
| 99 |
-
# Resize to model input size (usually 299x299 for Xception)
|
| 100 |
-
face_resized = cv2.resize(face_image, (299, 299))
|
| 101 |
-
face_normalized = face_resized.astype(np.float32) / 255.0
|
| 102 |
-
|
| 103 |
-
# Convert to tensor and add batch dimension
|
| 104 |
-
face_tensor = torch.from_numpy(face_normalized).permute(2, 0, 1).unsqueeze(0)
|
| 105 |
-
return face_tensor.to(self.device)
|
| 106 |
-
|
| 107 |
-
def predict_deepfake(self, image_path):
|
| 108 |
-
"""Predict if image contains deepfake"""
|
| 109 |
-
try:
|
| 110 |
-
image = cv2.imread(str(image_path))
|
| 111 |
-
if image is None:
|
| 112 |
-
return {"error": "Could not load image"}
|
| 113 |
-
|
| 114 |
-
# Detect faces using dlib
|
| 115 |
-
faces = self.detect_faces_dlib(image)
|
| 116 |
-
|
| 117 |
-
if not faces:
|
| 118 |
-
return {
|
| 119 |
-
"prediction": "no_faces",
|
| 120 |
-
"confidence": 0.0,
|
| 121 |
-
"message": "No faces detected in the image"
|
| 122 |
-
}
|
| 123 |
-
|
| 124 |
-
results = []
|
| 125 |
-
|
| 126 |
-
for i, (x, y, w, h) in enumerate(faces):
|
| 127 |
-
# Extract face region
|
| 128 |
-
face_region = image[y:y+h, x:x+w]
|
| 129 |
-
|
| 130 |
-
if self.model is not None:
|
| 131 |
-
# Preprocess and predict
|
| 132 |
-
face_tensor = self.preprocess_face(face_region)
|
| 133 |
-
|
| 134 |
-
with torch.no_grad():
|
| 135 |
-
outputs = self.model(face_tensor)
|
| 136 |
-
probabilities = torch.softmax(outputs, dim=1)
|
| 137 |
-
fake_prob = probabilities[0][1].item() # Probability of being fake
|
| 138 |
-
|
| 139 |
-
prediction = "fake" if fake_prob > 0.5 else "real"
|
| 140 |
-
confidence = fake_prob if prediction == "fake" else (1 - fake_prob)
|
| 141 |
-
else:
|
| 142 |
-
# Fallback without model
|
| 143 |
-
prediction = "unknown"
|
| 144 |
-
confidence = 0.0
|
| 145 |
-
|
| 146 |
-
results.append({
|
| 147 |
-
"face_id": i + 1,
|
| 148 |
-
"prediction": prediction,
|
| 149 |
-
"confidence": confidence,
|
| 150 |
-
"bbox": {"x": x, "y": y, "width": w, "height": h}
|
| 151 |
-
})
|
| 152 |
-
|
| 153 |
-
# Overall result (worst case scenario)
|
| 154 |
-
overall_prediction = "real"
|
| 155 |
-
max_fake_confidence = 0.0
|
| 156 |
-
|
| 157 |
-
for result in results:
|
| 158 |
-
if result["prediction"] == "fake" and result["confidence"] > max_fake_confidence:
|
| 159 |
-
max_fake_confidence = result["confidence"]
|
| 160 |
-
overall_prediction = "fake"
|
| 161 |
-
|
| 162 |
-
return {
|
| 163 |
-
"overall_prediction": overall_prediction,
|
| 164 |
-
"overall_confidence": max_fake_confidence if overall_prediction == "fake" else (1 - max_fake_confidence),
|
| 165 |
-
"faces_detected": len(faces),
|
| 166 |
-
"face_results": results
|
| 167 |
-
}
|
| 168 |
-
|
| 169 |
-
except Exception as e:
|
| 170 |
-
logger.error(f"Error in prediction: {e}")
|
| 171 |
-
logger.error(traceback.format_exc())
|
| 172 |
-
return {"error": str(e)}
|
| 173 |
-
|
| 174 |
-
# Initialize detector
|
| 175 |
-
detector = DeepfakeDetector()
|
| 176 |
-
|
| 177 |
-
@app.route('/', methods=['GET'])
|
| 178 |
-
def health_check():
|
| 179 |
-
"""Health check endpoint"""
|
| 180 |
-
return jsonify({
|
| 181 |
-
"status": "healthy",
|
| 182 |
-
"message": "Enhanced Deepfake Detection Server with dlib",
|
| 183 |
-
"model_loaded": detector.model is not None,
|
| 184 |
-
"dlib_available": True,
|
| 185 |
-
"face_predictor_available": detector.face_predictor is not None,
|
| 186 |
-
"device": str(detector.device)
|
| 187 |
-
})
|
| 188 |
-
|
| 189 |
-
@app.route('/detect', methods=['POST'])
|
| 190 |
-
def detect_deepfake():
|
| 191 |
-
"""Main detection endpoint"""
|
| 192 |
-
try:
|
| 193 |
-
if 'file' not in request.files:
|
| 194 |
-
return jsonify({"error": "No file provided"}), 400
|
| 195 |
-
|
| 196 |
-
file = request.files['file']
|
| 197 |
-
if file.filename == '':
|
| 198 |
-
return jsonify({"error": "No file selected"}), 400
|
| 199 |
-
|
| 200 |
-
# Save uploaded file temporarily
|
| 201 |
-
with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as temp_file:
|
| 202 |
-
file.save(temp_file.name)
|
| 203 |
-
temp_path = temp_file.name
|
| 204 |
-
|
| 205 |
-
try:
|
| 206 |
-
# Perform detection
|
| 207 |
-
result = detector.predict_deepfake(temp_path)
|
| 208 |
-
return jsonify(result)
|
| 209 |
-
|
| 210 |
-
finally:
|
| 211 |
-
# Clean up temporary file
|
| 212 |
-
if os.path.exists(temp_path):
|
| 213 |
-
os.unlink(temp_path)
|
| 214 |
-
|
| 215 |
-
except Exception as e:
|
| 216 |
-
logger.error(f"Error in detection endpoint: {e}")
|
| 217 |
-
return jsonify({"error": str(e)}), 500
|
| 218 |
-
|
| 219 |
-
@app.route('/test', methods=['GET'])
|
| 220 |
-
def test_endpoint():
|
| 221 |
-
"""Test endpoint to verify dlib functionality"""
|
| 222 |
-
try:
|
| 223 |
-
# Test dlib face detection with a simple test
|
| 224 |
-
test_image = np.zeros((300, 300, 3), dtype=np.uint8)
|
| 225 |
-
faces = detector.detect_faces_dlib(test_image)
|
| 226 |
-
|
| 227 |
-
return jsonify({
|
| 228 |
-
"dlib_working": True,
|
| 229 |
-
"test_faces_detected": len(faces),
|
| 230 |
-
"model_available": detector.model is not None,
|
| 231 |
-
"message": "dlib integration is working properly"
|
| 232 |
-
})
|
| 233 |
-
|
| 234 |
-
except Exception as e:
|
| 235 |
-
return jsonify({
|
| 236 |
-
"dlib_working": False,
|
| 237 |
-
"error": str(e)
|
| 238 |
-
}), 500
|
| 239 |
-
|
| 240 |
-
if __name__ == '__main__':
|
| 241 |
-
print("="*50)
|
| 242 |
-
print("Enhanced Deepfake Detection Server with dlib")
|
| 243 |
-
print("="*50)
|
| 244 |
-
print(f"Using device: {detector.device}")
|
| 245 |
-
print(f"Model loaded: {detector.model is not None}")
|
| 246 |
-
print(f"dlib face detector: Available")
|
| 247 |
-
print(f"dlib face predictor: {'Available' if detector.face_predictor else 'Not available'}")
|
| 248 |
-
print("="*50)
|
| 249 |
-
print("Server starting on http://localhost:5000")
|
| 250 |
-
print("Endpoints:")
|
| 251 |
-
print(" GET / - Health check")
|
| 252 |
-
print(" POST /detect - Detect deepfakes in uploaded image")
|
| 253 |
-
print(" GET /test - Test dlib functionality")
|
| 254 |
-
print("="*50)
|
| 255 |
-
|
| 256 |
-
app.run(host='0.0.0.0', port=5000, debug=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|