pujanpaudel commited on
Commit
d60cc72
·
verified ·
1 Parent(s): 5e5b3b5

Upload 5 files

Browse files
Files changed (5) hide show
  1. Dockerfile +35 -0
  2. main.py +136 -0
  3. model.pth +3 -0
  4. preprocessor_config.json +17 -0
  5. requirements.txt +8 -0
Dockerfile ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile
2
+
3
+ # 1. Use an official Python runtime as a parent image
4
+ # Using python 3.10, but you can choose 3.9, 3.11 etc. based on your needs. Slim is smaller.
5
+ FROM python:3.10-slim
6
+
7
+ # 2. Set the working directory in the container
8
+ WORKDIR /code
9
+
10
+ # 3. Install system dependencies if any (e.g., for OpenCV if you were using it)
11
+ # RUN apt-get update && apt-get install -y --no-install-recommends some-package && rm -rf /var/lib/apt/lists/*
12
+
13
+ # 4. Copy the requirements file into the container
14
+ COPY requirements.txt .
15
+
16
+ # 5. Install Python dependencies
17
+ # Upgrade pip and install requirements, ensuring CPU PyTorch is used
18
+ # Using --no-cache-dir makes the image smaller
19
+ RUN pip install --no-cache-dir --upgrade pip && \
20
+ pip install --no-cache-dir -r requirements.txt
21
+
22
+ # 6. Copy your application code and model file into the container
23
+ COPY app.py .
24
+ COPY model.pth .
25
+ # Add any other necessary files/folders here (e.g., utility scripts, templates)
26
+ # COPY utils/ ./utils/
27
+
28
+ # 7. Expose the port the app runs on
29
+ # Hugging Face Spaces expects port 7860 by default
30
+ EXPOSE 7860
31
+
32
+ # 8. Define the command to run your application
33
+ # This command starts the uvicorn server, listening on all interfaces (0.0.0.0) on port 7860
34
+ # It will automatically reload the code upon changes if you mount volumes during local dev, but not relevant for HF Spaces deployment itself.
35
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
main.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, UploadFile, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from fastapi.responses import JSONResponse
4
+ from pydantic import BaseModel
5
+ import uvicorn
6
+ import numpy as np
7
+ import io
8
+ from PIL import Image
9
+ import base64
10
+ import torch
11
+ import torch.nn.functional as F
12
+ from transformers import ViTImageProcessor, SwinForImageClassification,AutoImageProcessor
13
+ import lightning as L
14
+ import uuid
15
+ # Set device
16
+ device = "cuda" if torch.cuda.is_available() else "cpu"
17
+
18
+ # Label mappings
19
+ label2id = {'fake': 0, 'real': 1}
20
+ id2label = {0: 'fake', 1: 'real'}
21
+
22
+ # Load model
23
+ hyper_params = {
24
+ "MODEL_CKPT": "microsoft/swin-small-patch4-window7-224",
25
+ "num_labels": 2,
26
+ "id2label": id2label,
27
+ "label2id": label2id,
28
+ }
29
+
30
+ preprocessor_config_path = "preprocessor_config.json"
31
+
32
+ # Load the processor manually
33
+ vit_img_processor = AutoImageProcessor.from_pretrained(preprocessor_config_path)
34
+
35
+ class DeepFakeModel(L.LightningModule):
36
+ def __init__(self, hyperparams: dict):
37
+ super().__init__()
38
+ self.model = SwinForImageClassification.from_pretrained(
39
+ hyperparams["MODEL_CKPT"],
40
+ num_labels=hyperparams["num_labels"],
41
+ id2label=hyperparams["id2label"],
42
+ label2id=hyperparams["label2id"],
43
+ ignore_mismatched_sizes=True
44
+ )
45
+ self.loss_fn = torch.nn.CrossEntropyLoss()
46
+
47
+ def forward(self, pixel_values):
48
+ output = self.model(pixel_values=pixel_values)
49
+ return output.logits
50
+
51
+ # Load trained model
52
+ model = DeepFakeModel(hyper_params)
53
+ state_dict = torch.load("model.pth", map_location=torch.device(device))
54
+ model.load_state_dict(state_dict)
55
+ model.to(device)
56
+ model.eval()
57
+ print("Model loaded successfully")
58
+
59
+ # Initialize FastAPI app
60
+ app = FastAPI(title="DeepFake Detector API", description="API for detecting deepfake images", version="1.0.0")
61
+
62
+ # Configure CORS
63
+ app.add_middleware(
64
+ CORSMiddleware,
65
+ allow_origins=["*"], # Update with frontend server address in production
66
+ allow_credentials=True,
67
+ allow_methods=["*"],
68
+ allow_headers=["*"],
69
+ )
70
+
71
+ class ImageData(BaseModel):
72
+ image: str # Base64 encoded image
73
+
74
+ class AnalysisResult(BaseModel):
75
+ id: str
76
+ isDeepfake: bool
77
+ confidence: float
78
+ details: str
79
+
80
+
81
+ def preprocess_image(img):
82
+ img = vit_img_processor(img, return_tensors='pt')['pixel_values'].to(device)
83
+ return img
84
+
85
+
86
+ def predict_deepfake(image):
87
+ try:
88
+ img_tensor = preprocess_image(image)
89
+ with torch.inference_mode():
90
+ logits = model(img_tensor)
91
+ probabilities = F.softmax(logits, dim=-1)
92
+ confidence, predicted_index = torch.max(probabilities, dim=-1)
93
+ predicted_label = id2label[predicted_index.item()]
94
+
95
+ details = "Deepfake detected." if predicted_label == "fake" else "Image appears to be real."
96
+ return {
97
+ "id": str(uuid.uuid4()),
98
+ "isDeepfake": predicted_label == "fake",
99
+ "confidence": round(confidence.item() * 100, 2),
100
+ "details": details
101
+ }
102
+ except Exception as e:
103
+ raise HTTPException(status_code=500, detail=f"Error during prediction: {str(e)}")
104
+
105
+
106
+ @app.post("/api/analyze", response_model=AnalysisResult)
107
+ async def analyze_image(file: UploadFile = File(...)):
108
+ if not file.content_type.startswith("image/"):
109
+ raise HTTPException(status_code=400, detail="File must be an image")
110
+ try:
111
+ contents = await file.read()
112
+ image = Image.open(io.BytesIO(contents)).convert("RGB")
113
+ result = predict_deepfake(image)
114
+ return JSONResponse(content=result)
115
+ except Exception as e:
116
+ raise HTTPException(status_code=500, detail=f"Error processing image: {str(e)}")
117
+
118
+
119
+ @app.post("/api/analyze-base64", response_model=AnalysisResult)
120
+ async def analyze_base64_image(data: ImageData):
121
+ try:
122
+ image_data = data.image.split("base64,")[-1]
123
+ image_bytes = base64.b64decode(image_data)
124
+ image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
125
+ result = predict_deepfake(image)
126
+ return JSONResponse(content=result)
127
+ except Exception as e:
128
+ raise HTTPException(status_code=500, detail=f"Error processing image: {str(e)}")
129
+
130
+
131
+ @app.get("/")
132
+ async def root():
133
+ return {"message": "DeepFake Detector API is running"}
134
+
135
+ if __name__ == "__main__":
136
+ uvicorn.run("app:app", host="0.0.0.0", port=7860)
model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4ebc3e51179a22a2b8682988dc165411517c98184cf4322b782feb5da465bc78
3
+ size 196012933
preprocessor_config.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "do_normalize": true,
3
+ "do_resize": true,
4
+ "feature_extractor_type": "ViTFeatureExtractor",
5
+ "image_mean": [
6
+ 0.485,
7
+ 0.456,
8
+ 0.406
9
+ ],
10
+ "image_std": [
11
+ 0.229,
12
+ 0.224,
13
+ 0.225
14
+ ],
15
+ "resample": 3,
16
+ "size": 224
17
+ }
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn[standard]
3
+ python-multipart
4
+ pillow
5
+ numpy
6
+ transformers
7
+ lightning
8
+ torch